9 #include "messageitem.h" 10 #include "messageitem_p.h" 12 #include <PimCommonAkonadi/AnnotationDialog> 15 #include <entityannotationsattribute.h> 16 #include <tagattribute.h> 17 #include <tagfetchjob.h> 18 #include <tagfetchscope.h> 19 #include <KIconLoader> 20 #include <KLocalizedString> 23 #include "messagelist_debug.h" 26 Q_GLOBAL_STATIC(TagCache, s_tagCache)
53 MessageItem::Tag::~Tag()
58 const QPixmap &MessageItem::Tag::pixmap()
const 63 const QString &MessageItem::Tag::name()
const 68 const QString &MessageItem::Tag::id()
const 73 const QColor &MessageItem::Tag::textColor()
const 78 const QColor &MessageItem::Tag::backgroundColor()
const 80 return d->mBackgroundColor;
83 const QFont &MessageItem::Tag::font()
const 88 int MessageItem::Tag::priority()
const 93 void MessageItem::Tag::setTextColor(
const QColor &textColor)
95 d->mTextColor = textColor;
98 void MessageItem::Tag::setBackgroundColor(
const QColor &backgroundColor)
100 d->mBackgroundColor = backgroundColor;
103 void MessageItem::Tag::setFont(
const QFont &font)
108 void MessageItem::Tag::setPriority(
int priority)
110 d->mPriority = priority;
113 class MessageItemPrivateSettings
116 QColor mColorUnreadMessage;
117 QColor mColorImportantMessage;
120 QFont mFontUnreadMessage;
121 QFont mFontImportantMessage;
122 QFont mFontToDoMessage;
130 Q_GLOBAL_STATIC(MessageItemPrivateSettings, s_settings)
132 MessageItemPrivate::MessageItemPrivate(
MessageItem *qq)
137 , mAboutToBeRemoved(false)
138 , mSubjectIsPrefixed(false)
143 MessageItemPrivate::~MessageItemPrivate()
145 s_tagCache->cancelRequest(
this);
146 invalidateTagCache();
149 void MessageItemPrivate::invalidateTagCache()
152 qDeleteAll(*mTagList);
158 void MessageItemPrivate::invalidateAnnotationCache()
162 const MessageItem::Tag *MessageItemPrivate::bestTag()
const 164 const MessageItem::Tag *best =
nullptr;
165 foreach (
const MessageItem::Tag *tag, getTagList()) {
166 if (!best || tag->priority() < best->priority()) {
173 void MessageItemPrivate::fillTagList(
const Akonadi::Tag::List &taglist)
184 QString symbol = QStringLiteral(
"mail-tagged");
187 if (!attr->iconName().isEmpty()) {
188 symbol = attr->iconName();
194 messageListTag->setTextColor(attr->textColor());
195 messageListTag->setBackgroundColor(attr->backgroundColor());
196 if (!attr->font().isEmpty()) {
199 messageListTag->setFont(font);
202 if (attr->priority() != -1) {
203 messageListTag->setPriority(attr->priority());
205 messageListTag->setPriority(0xFFFF);
209 mTagList->append(messageListTag);
216 s_tagCache->retrieveTags(mAkonadiItem.tags(),
const_cast<MessageItemPrivate *
>(
this));
223 bool MessageItemPrivate::tagListInitialized()
const 225 return mTagList !=
nullptr;
228 MessageItem::MessageItem()
234 MessageItem::MessageItem(MessageItemPrivate *dd)
240 MessageItem::~MessageItem()
247 return d->getTagList();
250 bool MessageItem::hasAnnotation()
const 262 const auto annotations = attr->annotations();
263 QByteArray annot = annotations.value(
"/private/comment");
267 annot = annotations.value(
"/shared/comment");
275 void MessageItem::editAnnotation(
QWidget *parent)
280 if (mAnnotationDialog->exec()) {
283 delete mAnnotationDialog;
286 const MessageItem::Tag *MessageItemPrivate::findTagInternal(
const QString &szTagId)
const 288 foreach (
const MessageItem::Tag *tag, getTagList()) {
289 if (tag->id() == szTagId) {
296 const MessageItem::Tag *MessageItem::findTag(
const QString &szTagId)
const 299 return d->findTagInternal(szTagId);
302 QString MessageItem::tagListDescription()
const 306 foreach (
const Tag *tag, tagList()) {
316 void MessageItem::invalidateTagCache()
319 d->invalidateTagCache();
322 void MessageItem::invalidateAnnotationCache()
325 d->invalidateAnnotationCache();
328 const QColor &MessageItem::textColor()
const 331 const Tag *bestTag = d->bestTag();
332 if (bestTag !=
nullptr && bestTag->textColor().isValid()) {
333 return bestTag->textColor();
337 if (!messageStatus.
isRead()) {
338 return s_settings->mColorUnreadMessage;
340 return s_settings->mColorImportantMessage;
341 }
else if (messageStatus.
isToAct()) {
342 return s_settings->mColorToDoMessage;
344 return s_settings->mColor;
348 const QColor &MessageItem::backgroundColor()
const 351 const Tag *bestTag = d->bestTag();
353 return bestTag->backgroundColor();
355 return s_settings->mBackgroundColor;
359 const QFont &MessageItem::font()
const 365 if (d->tagListInitialized()) {
366 const Tag *bestTag = d->bestTag();
367 if (bestTag && bestTag->font() !=
QFont()) {
368 return bestTag->font();
375 return s_settings->mFontImportantMessage;
376 }
else if (!messageStatus.
isRead()) {
377 return s_settings->mFontUnreadMessage;
378 }
else if (messageStatus.
isToAct()) {
379 return s_settings->mFontToDoMessage;
381 return s_settings->mFont;
385 MessageItem::SignatureState MessageItem::signatureState()
const 388 return d->mSignatureState;
391 void MessageItem::setSignatureState(SignatureState state)
394 d->mSignatureState = state;
397 MessageItem::EncryptionState MessageItem::encryptionState()
const 400 return d->mEncryptionState;
403 void MessageItem::setEncryptionState(EncryptionState state)
406 d->mEncryptionState = state;
412 return d->mMessageIdMD5;
415 void MessageItem::setMessageIdMD5(
const QByteArray &md5)
418 d->mMessageIdMD5 = md5;
421 QByteArray MessageItem::inReplyToIdMD5()
const 424 return d->mInReplyToIdMD5;
427 void MessageItem::setInReplyToIdMD5(
const QByteArray &md5)
430 d->mInReplyToIdMD5 = md5;
433 QByteArray MessageItem::referencesIdMD5()
const 436 return d->mReferencesIdMD5;
439 void MessageItem::setReferencesIdMD5(
const QByteArray &md5)
442 d->mReferencesIdMD5 = md5;
445 void MessageItem::setSubjectIsPrefixed(
bool subjectIsPrefixed)
448 d->mSubjectIsPrefixed = subjectIsPrefixed;
451 bool MessageItem::subjectIsPrefixed()
const 454 return d->mSubjectIsPrefixed;
457 QByteArray MessageItem::strippedSubjectMD5()
const 460 return d->mStrippedSubjectMD5;
463 void MessageItem::setStrippedSubjectMD5(
const QByteArray &md5)
466 d->mStrippedSubjectMD5 = md5;
469 bool MessageItem::aboutToBeRemoved()
const 472 return d->mAboutToBeRemoved;
475 void MessageItem::setAboutToBeRemoved(
bool aboutToBeRemoved)
478 d->mAboutToBeRemoved = aboutToBeRemoved;
484 return d->mThreadingStatus;
490 d->mThreadingStatus = threadingStatus;
493 unsigned long MessageItem::uniqueId()
const 496 return d->mAkonadiItem.id();
499 Akonadi::Item MessageList::Core::MessageItem::akonadiItem()
const 502 return d->mAkonadiItem;
505 void MessageList::Core::MessageItem::setAkonadiItem(
const Akonadi::Item &item)
508 d->mAkonadiItem = item;
516 if (parent()->type() == Item::Message) {
517 return static_cast< MessageItem *
>(parent())->topmostMessage();
525 case Theme::ContentItem::Subject:
526 return d_ptr->mSubject;
527 case Theme::ContentItem::Sender:
528 return d_ptr->mSender;
529 case Theme::ContentItem::Receiver:
530 return d_ptr->mReceiver;
531 case Theme::ContentItem::SenderOrReceiver:
532 return senderOrReceiver();
533 case Theme::ContentItem::Date:
534 return formattedDate();
535 case Theme::ContentItem::Size:
536 return formattedSize();
537 case Theme::ContentItem::RepliedStateIcon:
538 return status().isReplied() ?
i18nc(
"Status of an item",
"Replied") :
QString();
539 case Theme::ContentItem::ReadStateIcon:
540 return status().isRead() ?
i18nc(
"Status of an item",
"Read") :
i18nc(
"Status of an item",
"Unread");
541 case Theme::ContentItem::CombinedReadRepliedStateIcon:
542 return accessibleTextForField(Theme::ContentItem::ReadStateIcon) + accessibleTextForField(Theme::ContentItem::RepliedStateIcon);
548 QString MessageItem::accessibleText(
const Theme *theme,
int columnIndex)
557 const auto leftItems = row->leftItems();
558 leftStrings.
reserve(leftItems.count());
560 leftStrings.
append(accessibleTextForField(contentItem->type()));
563 const auto rightItems = row->rightItems();
564 rightStrings.
reserve(rightItems.count());
566 rightStrings.
insert(rightStrings.
begin(), accessibleTextForField(contentItem->type()));
578 const auto childList = childItems();
582 for (
const auto child : qAsConst(*childList)) {
583 Q_ASSERT(child->type() == Item::Message);
584 static_cast<MessageItem *
>(child)->subTreeToList(list);
588 void MessageItem::setUnreadMessageColor(
const QColor &color)
590 s_settings->mColorUnreadMessage = color;
593 void MessageItem::setImportantMessageColor(
const QColor &color)
595 s_settings->mColorImportantMessage = color;
598 void MessageItem::setToDoMessageColor(
const QColor &color)
600 s_settings->mColorToDoMessage = color;
603 void MessageItem::setGeneralFont(
const QFont &font)
605 s_settings->mFont = font;
608 void MessageItem::setUnreadMessageFont(
const QFont &font)
610 s_settings->mFontUnreadMessage = font;
613 void MessageItem::setImportantMessageFont(
const QFont &font)
615 s_settings->mFontImportantMessage = font;
618 void MessageItem::setToDoMessageFont(
const QFont &font)
620 s_settings->mFontToDoMessage = font;
623 FakeItemPrivate::FakeItemPrivate(
FakeItem *qq) : MessageItemPrivate(qq)
632 FakeItem::~FakeItem()
635 qDeleteAll(d->mFakeTags);
647 d->mFakeTags = tagList;
650 bool FakeItem::hasAnnotation()
const 659 mCache.setMaxCost(100);
660 mMonitor->
setObjectName(QStringLiteral(
"MessageListTagCacheMonitor"));
661 mMonitor->setTypeMonitored(Akonadi::Monitor::Tags);
675 mCache.remove(tag.
id());
680 mCache.remove(tag.
id());
683 void TagCache::retrieveTags(
const Akonadi::Tag::List &tags, MessageItemPrivate *m)
686 if (mRequests.key(m)) {
689 Akonadi::Tag::List toFetch;
690 Akonadi::Tag::List available;
692 if (mCache.contains(tag.
id())) {
693 available << *mCache.object(tag.
id());
699 if (!toFetch.isEmpty()) {
703 mRequests.insert(tagFetchJob, m);
705 m->fillTagList(available);
709 void TagCache::cancelRequest(MessageItemPrivate *m)
712 Q_FOREACH (
KJob *job, keys) {
713 mRequests.remove(job);
717 void TagCache::onTagsFetched(
KJob *job)
720 qCWarning(MESSAGELIST_LOG) <<
"Failed to fetch tags: " << job->
errorString();
727 if (
auto m = mRequests.take(fetchJob)) {
728 m->fillTagList(fetchJob->tags());
The ContentItem class defines a content item inside a Row.
void append(const T &value)
virtual QString errorString() const
The Row class defines a row of items inside a Column.
bool isEmpty() const const
The implementation independent part of the MessageList library.
QString join(const QString &separator) const const
void tagAdded(const Akonadi::Tag &tag)
int count(const T &value) const const
void append(const T &value)
const QList< Row * > & messageRows() const
Returns the list of rows visible in this column for a MessageItem.
bool fromString(const QString &descrip)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void setObjectName(const QString &name)
bool isEmpty() const const
Type
The available ContentItem types.
void tagRemoved(const Akonadi::Tag &tag)
A single item of the MessageList tree managed by MessageList::Model.
A message item that can have a fake tag list and a fake annotation.
Column * column(int idx) const
Returns a pointer to the column at the specified index or 0 if there is no such column.
QString name() const const
void tagChanged(const Akonadi::Tag &tag)
void insert(int i, const T &value)
QString fromLatin1(const char *str, int size)
QIcon fromTheme(const QString &name)
The Theme class defines the visual appearance of the MessageList.
An invariant index that can be ALWAYS used to reference an item inside a QAbstractItemModel.