Messagelib
model.cpp
142 * That's why we in fact have Pass1Fill, Pass1Cleanup, Pass1Update, Pass2, Pass3, Pass4 and Pass5 below.
143 * Pass1Fill, Pass1Cleanup and Pass1Update are exclusive and all of them proceed with Pass2 when finished.
149 Pass1Fill = 0, ///< Build threading caches, *TRY* to do some threading, try to attach something to the view
200 ViewItemJob(int startIndex, int endIndex, int chunkTimeout, int idleInterval, int messageCheckCount, bool disconnectUI = false)
216 ViewItemJob(Pass pass, QList<ModelInvariantIndex *> *invariantIndexList, int chunkTimeout, int idleInterval, int messageCheckCount)
341 d->mCachedWatchedOrIgnoredStatusBits = Akonadi::MessageStatus::statusIgnored().toQInt32() | Akonadi::MessageStatus::statusWatched().toQInt32();
373 d->mView->setRootIsDecorated((d->mAggregation->grouping() == Aggregation::NoGrouping) && (d->mAggregation->threading() != Aggregation::NoThreading));
578 // FIXME: This function is a bottleneck (the caching in indexOfChildItem only works 30% of the time)
602 return QModelIndex(); // senseless column (we could optimize by skipping this check but ModelTest from trolltech is pedantic)
755 std::for_each(d->mStorageModelConnections.cbegin(), d->mStorageModelConnections.cend(), [](const QMetaObject::Connection &c) -> bool {
778 qCDebug(MESSAGELIST_LOG) << "Threading disabled in previous folder, not saving threading cache";
790 qCDebug(MESSAGELIST_LOG) << "Threading disabled in folder" << d->mStorageModel->id() << ", not using threading cache";
826 connect(d->mStorageModel, &StorageModel::headerDataChanged, this, [this](Qt::Orientation orientation, int first, int last) {
850 // adjusted by the second job. For instance, in my kernel mailing list folder this "smart" approach
906 (d->mAggregation->threadExpandPolicy() == Aggregation::NeverExpandThreads) || // or we expand threads but we'll be going to expand really only a few
909 (d->mAggregation->threadExpandPolicy() != Aggregation::AlwaysExpandThreads) && // and we'd expand only a few in fact
916 // First a small job with the most recent messages. Large chunk, small (but non zero) idle interval
919 new ViewItemJob(d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 200, 20, 100, canDoFirstSmallChunkWithDisconnectedUI);
921 // Then a larger job with older messages. Small chunk, bigger idle interval, small number of messages to
932 auto job = new ViewItemJob(0, d->mStorageModel->rowCount() - 1, 150, 30, 30, canDoJobWithDisconnectedUI);
941 new ViewItemJob(d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoFirstSmallChunkWithDisconnectedUI);
948 auto job = new ViewItemJob(0, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoJobWithDisconnectedUI);
954 auto job = new ViewItemJob(0, d->mStorageModel->rowCount() - 1, 60000, 0, 100000, canDoJobWithDisconnectedUI);
971 // This function is called by MessageList::Core::Manager once in a while (every 1 minute or sth).
975 // on the fly would be too expensive). We also cache the labels of the groups which often display dates.
1010 // The "view fill" algorithm implemented in the functions below is quite smart but also quite complex.
1013 // - Be flexible: allow different configurations from "unsorted flat list" to a "grouped and threaded
1017 // - Be interruptible: user must be able to abort the execution and just switch to another folder in the middle
1041 // Something may *also* be in mUnassignedMessageListForPass3 and mUnassignedMessageListForPass4
1099 // mUnassignedMessageListForPass4 is empty so we must be at the end of a very special kind of Pass2
1166 mModelForItemFunctions = q; // make sure it's true, as there remains no job with disconnected UI
1227 if (ghi->initialExpandStatus() == Item::ExpandNeeded) { // this actually is a "non viewable expanded state"
1270 // - it has at least one children (well.. this is not a strict requirement, but it's a waste of resources to expand items that don't have children)
1274 // if ( !mView->isExpanded( idx ) ) // this is O(logN!) in Qt.... very ugly... but it should never happen here
1324 auto dayName = mCachedDayNameLabel.find(dDate.dayOfWeek()); // non-const call, but non-shared container
1326 dayName = mCachedDayNameLabel.insert(dDate.dayOfWeek(), QLocale::system().standaloneDayName(dDate.dayOfWeek()));
1329 } else if (mAggregation->grouping() == Aggregation::GroupByDate) { // GroupByDate seven days or more ago
1333 int startOfWeekDaysAgo = (daysInWeek + mTodayDate.dayOfWeek() - QLocale().firstDayOfWeek()) % daysInWeek;
1358 auto monthName = mCachedMonthNameLabel.find(dDate.month()); // non-const call, but non-shared container
1360 monthName = mCachedMonthNameLabel.insert(dDate.month(), QLocale::system().standaloneMonthName(dDate.month()));
1364 auto monthName = mCachedMonthNameLabel.find(dDate.month()); // non-const call, but non-shared container
1366 monthName = mCachedMonthNameLabel.insert(dDate.month(), QLocale::system().standaloneMonthName(dDate.month()));
1462 Q_ASSERT(mAggregation->threading() != Aggregation::NoThreading); // caller must take care of this
1495 qCWarning(MESSAGELIST_LOG) << "Circular In-Reply-To reference loop detected in the message tree";
1508 mi->setThreadingStatus(bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable);
1541 auto messagesWithTheSameReferences = mThreadingCacheMessageReferencesIdMD5ToMessageItem.value(md5, nullptr);
1557 mi->setThreadingStatus(bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable);
1569 mi->setThreadingStatus((bMessageWasThreadable || mi->subjectIsPrefixed()) ? MessageItem::ParentMissing : MessageItem::NonThreadable);
1577 void dump_iterator_and_list(QList< MessageItem * >::Iterator &iter, QList< MessageItem * > *list)
1583 qCDebug(MESSAGELIST_LOG) << "Iterator pointing to " << *iter << " subject [" << (*iter)->subject() << "] date [" << (*iter)->date() << "]";
1587 qCDebug(MESSAGELIST_LOG) << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]";
1598 qCDebug(MESSAGELIST_LOG) << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]";
1625 // Messages in this cache are sorted by date, and if dates are equal then they are sorted by pointer value.
1632 auto messagesWithTheSameReference = mThreadingCacheMessageReferencesIdMD5ToMessageItem.value(mi->referencesIdMD5(), nullptr);
1636 mThreadingCacheMessageReferencesIdMD5ToMessageItem.insert(mi->referencesIdMD5(), messagesWithTheSameReference);
1645 auto it = std::lower_bound(messagesWithTheSameReference->begin(), messagesWithTheSameReference->end(), mi, MessageLessThanByDate());
1654 auto messagesWithTheSameReference = mThreadingCacheMessageReferencesIdMD5ToMessageItem.value(mi->referencesIdMD5(), nullptr);
1660 auto it = std::lower_bound(messagesWithTheSameReference->begin(), messagesWithTheSameReference->end(), mi, MessageLessThanByDate());
1680 // Messages in this cache are sorted by date, and if dates are equal then they are sorted by pointer value.
1688 auto messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value(mi->strippedSubjectMD5(), nullptr);
1693 mThreadingCacheMessageSubjectMD5ToMessageItem.insert(mi->strippedSubjectMD5(), messagesWithTheSameStrippedSubject);
1702 auto it = std::lower_bound(messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate());
1714 auto messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value(mi->strippedSubjectMD5(), nullptr);
1720 auto it = std::lower_bound(messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate());
1747 Q_ASSERT(mAggregation->threading() == Aggregation::PerfectReferencesAndSubject); // caller must take care of this
1754 auto messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value(md5, nullptr);
1830 static bool messageItemNeedsReSorting(SortOrder::SortDirection messageSortDirection, ItemPrivate *parent, MessageItem *messageItem)
1843 // - If we're sorting messages by min/max date then at each level the messages might need resorting.
1871 mGroupHeadersThatNeedUpdate.insert(static_cast<GroupHeaderItem *>(item), static_cast<GroupHeaderItem *>(item));
1883 if (messageItemNeedsReSorting<ItemDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1890 if (messageItemNeedsReSorting<ItemMaxDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1897 if (messageItemNeedsReSorting<ItemActionItemStatusComparator>(mSortOrder->messageSortDirection(),
1915 if (messageItemNeedsReSorting<ItemImportantStatusComparator>(mSortOrder->messageSortDirection(),
1924 if (messageItemNeedsReSorting<ItemAttachmentStatusComparator>(mSortOrder->messageSortDirection(),
1971 if (messageItemNeedsReSorting<ItemDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1978 if (messageItemNeedsReSorting<ItemMaxDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1985 if (messageItemNeedsReSorting<ItemActionItemStatusComparator>(mSortOrder->messageSortDirection(),
1994 if (messageItemNeedsReSorting<ItemUnreadStatusComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
2001 if (messageItemNeedsReSorting<ItemImportantStatusComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
2008 if (messageItemNeedsReSorting<ItemAttachmentStatusComparator>(mSortOrder->messageSortDirection(),
2069 mGroupHeadersThatNeedUpdate.insert(static_cast<GroupHeaderItem *>(oldParent), static_cast<GroupHeaderItem *>(oldParent));
2117 void ModelPrivate::attachMessageToParent(Item *pParent, MessageItem *mi, AttachOptions attachOptions)
2209 Q_ASSERT(!mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains(mi->inReplyToIdMD5(), mi));
2244 if ((mSortOrder->messageSortDirection() == SortOrder::Ascending) || (pParent->type() == Item::Message)) { \
2305 case Aggregation::ExpandThreadsWithNewMessages: // No more new status. fall through to unread if it exists in config
2315 if (childNeedsExpanding || !mi->status().isRead() || mi->status().isImportant() || mi->status().isToAct()) {
2418 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass5(ViewItemJob *job, QElapsedTimer elapsedTimer)
2456 needsReSorting = (*it)->parent()->d_ptr->childItemNeedsReSorting<_ItemDateComparator, true>(*it); \
2459 needsReSorting = (*it)->parent()->d_ptr->childItemNeedsReSorting<_ItemDateComparator, false>(*it); \
2516 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass4(ViewItemJob *job, QElapsedTimer elapsedTimer)
2557 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass3(ViewItemJob *job, QElapsedTimer elapsedTimer)
2601 // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable)
2602 Q_ASSERT((mi->threadingStatus() == MessageItem::ParentMissing) || (mi->threadingStatus() == MessageItem::NonThreadable));
2608 Q_ASSERT((mi->threadingStatus() == MessageItem::ParentMissing) || (mi->threadingStatus() == MessageItem::NonThreadable));
2614 // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent.
2638 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass2(ViewItemJob *job, QElapsedTimer elapsedTimer)
2643 // to attach in Pass1Fill and their children (which we find here) will make it to the small Pass3
2660 // If it has no parent or it has a temporary one (mi->parent() && mi->threadingStatus() == MessageItem::ParentMissing)
2661 // then we attempt to (re-)thread it. Otherwise we just do nothing (the job has already been done by the previous steps).
2701 // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable)
2718 qCWarning(MESSAGELIST_LOG) << "ERROR: Invalid message threading status returned by findMessageParent()!";
2726 // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent.
2729 qCWarning(MESSAGELIST_LOG) << "Non viewable message " << mi << " subject " << mi->subject().toUtf8().data();
2753 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Fill(ViewItemJob *job, QElapsedTimer elapsedTimer)
2772 unsigned long msgToSelect = mPreSelectionMode == PreSelectLastSelected ? mStorageModel->preSelectedMessage() : 0;
2787 qCWarning(MESSAGELIST_LOG) << "Fill of the MessageItem at storage row index " << curIndex << " failed";
2825 mStorageModel->fillMessageItemThreadingData(mi, curIndex, StorageModel::PerfectThreadingReferencesAndSubject);
2832 mStorageModel->fillMessageItemThreadingData(mi, curIndex, StorageModel::PerfectThreadingPlusReferences);
2872 const auto lImperfectlyThreaded = mThreadingCacheMessageInReplyToIdMD5ToMessageItem.values(mi->messageIdMD5());
2877 if (!((it->threadingStatus() == MessageItem::ImperfectParentFound) || (it->threadingStatus() == MessageItem::ParentMissing))) {
2879 Q_ASSERT_X(false, "ModelPrivate::viewItemJobStepInternalForJobPass1Fill", "Wrong threading status");
2924 qCWarning(MESSAGELIST_LOG) << "Circular In-Reply-To reference loop detected in the message tree";
2967 if ((mAggregation->grouping() == Aggregation::NoGrouping) || (mAggregation->threadLeader() == Aggregation::TopmostMessage)) {
2970 // qCDebug(MESSAGELIST_LOG) << "Setting message status from " << mi->threadingStatus() << " to non threadable (1) " << mi;
2995 // qCDebug(MESSAGELIST_LOG) << "Setting message status from " << mi->threadingStatus() << " to non threadable (2) " << mi;
3025 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Cleanup(ViewItemJob *job, QElapsedTimer elapsedTimer)
3084 mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemAfter(dyingMessage, MessageTypeAny, false);
3090 mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemBefore(dyingMessage, MessageTypeAny, false);
3093 Q_ASSERT((!mCurrentItemToRestoreAfterViewItemJobStep) || mCurrentItemToRestoreAfterViewItemJobStep->isViewable());
3116 mOrphanChildrenHash.remove(dyingMessage); // this can turn to a no-op (dyingMessage not present in fact)
3134 // If we also have a cache for subject/reference-based threading then remove the message from there too
3151 Q_ASSERT(!mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains(dyingMessage->inReplyToIdMD5(), dyingMessage));
3168 Q_ASSERT(!mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains(childMessage->inReplyToIdMD5(), childMessage));
3169 mThreadingCacheMessageInReplyToIdMD5ToMessageItem.insert(childMessage->inReplyToIdMD5(), childMessage);
3259 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Update(ViewItemJob *job, QElapsedTimer elapsedTimer)
3358 } // else there is no parent so the item isn't attached to the view: re-grouping/re-sorting not needed.
3363 // In all the other cases we (re-)apply the filter to the topmost subtree that this message is in.
3377 // above and climb up eventually hiding parents (without descending the sibling subtrees again).
3405 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJob(ViewItemJob *job, QElapsedTimer elapsedTimer)
3613 static const char *jobDescription[numberOfPasses] = {"Creating items from messages and simple threading",
3662 messagesWithSameSubjectAvg = messagesWithSameSubjectAvg / (float)mThreadingCacheMessageSubjectMD5ToMessageItem.size();
3674 qCDebug(MESSAGELIST_LOG) << "That took" << totalTotalTime << "msecs inside the model and" << completeTime << "in total.";
3675 qCDebug(MESSAGELIST_LOG) << (totalTotalTime / (float)completeTime) * 100.0f << "percent of the time was spent in the model.";
3676 qCDebug(MESSAGELIST_LOG) << "Time for layoutChanged(), in msecs:" << layoutChangeTime << "(" << (layoutChangeTime / (float)totalTotalTime) * 100.0f
3678 qCDebug(MESSAGELIST_LOG) << "Time to expand tree, in msecs:" << expandingTreeTime << "(" << (expandingTreeTime / (float)totalTotalTime) * 100.0f
3685 qCDebug(MESSAGELIST_LOG) << "Threads per group:" << totalThreads / (float)mGroupHeaderItemHash.size();
3701 qCDebug(MESSAGELIST_LOG) << "Number of elements:" << numElements[i]; // TODO: map of element string
3763 // With a connected UI we need to avoid the view to update the scrollbars at EVERY insertion or expansion.
3764 // QTreeViewPrivate::updateScrollBars() is very expensive as it loops through ALL the items in the view every time.
3765 // We can't disable the function directly as it's hidden in the private data object of QTreeView
3934 Item *currentItemBeforeStep = currentIndexBeforeStep.isValid() ? static_cast<Item *>(currentIndexBeforeStep.internalPointer()) : nullptr;
3945 // This is generally SLOW AS HELL... (so we avoid it if we lock the view and thus don't need it)
3963 mFillStepTimer.start(mViewItemJobStepIdleInterval); // this is a single shot timer connected to viewItemJobStep()
4007 qCWarning(MESSAGELIST_LOG) << "ERROR: Unrecognized pre-selection mode " << static_cast<int>(mPreSelectionMode);
4054 Item *currentAfterStep = currentIndexAfterStep.isValid() ? static_cast<Item *>(currentIndexAfterStep.internalPointer()) : nullptr;
4072 qCDebug(MESSAGELIST_LOG) << "Gonna restore current here" << mCurrentItemToRestoreAfterViewItemJobStep->subject();
4086 qCDebug(MESSAGELIST_LOG) << "Gonna restore selection here" << mCurrentItemToRestoreAfterViewItemJobStep->subject();
4090 mView->selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
4095 // FIXME: If it was selected before the change, then re-select it (it may happen that it's not)
4098 QRect rectAfterViewItemJobStep = mView->visualRect(q->index(mCurrentItemToRestoreAfterViewItemJobStep, 0));
4101 mView->verticalScrollBar()->setValue(mView->verticalScrollBar()->value() + rectAfterViewItemJobStep.y() - rectBeforeViewItemJobStep.y());
4113 // Either there was no current item before, or it was lost in a cleanup step and another candidate for
4145 // and the messages created... no need to care anymore: the invariant row mapper will do the job.
4187 // The second part ranges from "from" to job->endIndex() that are now shifted up by count steps.
4190 auto newJob = new ViewItemJob(from + count, job->endIndex() + count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount());
4327 auto newJob = new ViewItemJob(from, job->endIndex() - count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount());
4334 } // else the change includes completely the end of the job and no other part of it can be completed.
4339 // The change starts below (or exactly on the beginning of) the job. ( from <= job->currentIndex() )
4386 // qCDebug(MESSAGELIST_LOG) << "Appending " << invalidatedIndexes->count() << " invalidated indexes to existing cleanup job";
4399 // qCDebug(MESSAGELIST_LOG) << "Creating new cleanup job for " << invalidatedIndexes->count() << " invalidated indexes";
4419 void ModelPrivate::slotStorageModelDataChanged(const QModelIndex &fromIndex, const QModelIndex &toIndex)
4421 Q_ASSERT(mStorageModel); // must exist (and be the sender of the signal connected to this slot)
const QString & receiver() const
Returns the receiver associated to this item.
Definition: item.cpp:501
void append(const T &value)
@ PerfectReferencesAndSubject
Thread by all of the above and try to match subjects too.
Definition: aggregation.h:69
@ GroupBySenderOrReceiver
Group by sender (incoming) or receiver (outgoing) field.
Definition: aggregation.h:40
size_t size() const
Returns the size of this item (size of the Message, mainly)
Definition: item.cpp:456
int month() const const
@ SortGroupsByReceiver
Sort groups by receiver (makes sense only with GroupByReceiver)
Definition: sortorder.h:65
UserRole
void modelReset()
AKONADICORE_EXPORT Collection fromIndex(const QModelIndex &index)
void setStorageModel(StorageModel *storageModel, PreSelectionMode preSelectionMode=PreSelectLastSelected)
Sets the storage model from that the messages to be displayed should be fetched.
Definition: model.cpp:742
QVariant fromValue(const T &value)
SortDirection
The "generic" sort direction: used for groups and for messages If you add values here please look at ...
Definition: sortorder.h:68
void * internalPointer() const const
The MessageList::View is the real display of the message list.
Definition: view.h:47
@ SortMessagesByActionItemStatus
Sort the messages by the "Action Item" flag of status.
Definition: sortorder.h:84
int column() const const
void layoutChanged(const QList< QPersistentModelIndex > &parents, QAbstractItemModel::LayoutChangeHint hint)
@ PerfectThreadingOnly
Only the data for messageIdMD5 and inReplyToMD5 is needed.
Definition: storagemodelbase.h:79
int year() const const
Qt::DayOfWeek firstDayOfWeek() const const
@ SortGroupsByDateTimeOfMostRecent
Sort groups by date/time of the most recent message.
Definition: sortorder.h:62
QIcon fromTheme(const QString &name)
static const MessageStatus statusWatched()
KGuiItem clear()
Item * rootItem() const
Returns the hidden root item that all the messages are (or will be) attached to.
Definition: model.cpp:4523
This class is an optimizing helper for dealing with large flat QAbstractItemModel objects.
Definition: modelinvariantrowmapper.h:87
int y() const const
@ TopmostMessage
The thread grouping is computed from the topmost message (very similar to least recent,...
Definition: aggregation.h:79
@ ExpandRecentGroups
Makes sense only with GroupByDate or GroupByDateRange.
Definition: aggregation.h:55
void deletePersistentSet(MessageItemSetReference ref)
Deletes the persistent set pointed by the specified reference.
Definition: model.cpp:4568
void setStatus(Akonadi::MessageStatus status)
Sets the status associated to this Item.
Definition: item.cpp:451
void setSecsSinceEpoch(qint64 secs)
@ InvisibleRoot
This item is just Item and it's the only InvisibleRoot per Model.
Definition: item.h:59
QString standaloneMonthName(int month, QLocale::FormatType type) const const
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
Item * parent() const
Returns the parent Item in the tree, or 0 if this item isn't attached to the tree.
Definition: item.cpp:436
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
@ ExpandThreadsWithUnreadMessages
Expand threads with unread messages (this includes new)
Definition: aggregation.h:93
Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) class ControlPrivate
bool isToAct() const
time_t maxDate() const
Returns the maximum date in the subtree originating from this item.
Definition: item.cpp:476
QLocale system()
void takeChildItem(Model *model, Item *child)
Removes a child from this item's child list without deleting it.
Definition: item.cpp:637
@ ImperfectParentFound
this message found an imperfect parent to attach to (might be fixed later)
Definition: messageitem.h:62
bool isWatched() const
QModelIndex createIndex(int row, int column, void *ptr) const const
typedef ItemFlags
QString i18n(const char *text, const TYPE &arg...)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
char * toString(const T &value)
bool isIgnored() const
Orientation
void timeout()
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
WaitCursor
QByteArray toUtf8() const const
Item * childItem(int idx) const
Returns the child item at position idx or 0 if idx is out of the allowable range.
Definition: item.cpp:64
const T & at(int i) const const
@ PerfectThreadingReferencesAndSubject
All of the above plus subject stuff.
Definition: storagemodelbase.h:81
MessageItem * messageItemByStorageRow(int row) const
Returns the message item that is at the current storage row index or zero if no such storage item is ...
Definition: model.cpp:4533
QString toString(qlonglong i) const const
@ ExpandThreadsWithUnreadOrImportantMessages
Expand threads with "hot" messages (this includes new, unread, important, todo)
Definition: aggregation.h:95
bool isValid() const const
static const MessageStatus statusIgnored()
void headerDataChanged(Qt::Orientation orientation, int first, int last)
PreSelectionMode
Pre-selection is the action of automatically selecting a message just after the folder has finished l...
Definition: messagelist/src/core/enums.h:40
QDate currentDate()
A class which holds information about sorting, e.g.
Definition: sortorder.h:34
@ ParentMissing
this message might belong to a thread but its parent is actually missing
Definition: messageitem.h:63
QMimeData * mimeData(const QModelIndexList &indexes) const override
Called when user initiates a drag from the messagelist.
Definition: model.cpp:4509
void setAggregation(const Aggregation *aggregation)
Sets the Aggregation mode.
Definition: model.cpp:370
bool useReceiver() const
Returns whether sender or receiver is supposed to be displayed.
Definition: item.cpp:526
qint64 elapsed() const const
bool isRead() const
bool isValid() const const
@ SortGroupsBySenderOrReceiver
Sort groups by sender or receiver (makes sense only with GroupBySenderOrReceiver)
Definition: sortorder.h:63
@ SortMessagesByUnreadStatus
Sort the messages by the "Unread" flags of status.
Definition: sortorder.h:85
bool recomputeMaxDate()
Recompute the maximum date from the current children list.
Definition: item.cpp:323
@ MostRecentMessage
The thread grouping is computed from the most recent message.
Definition: aggregation.h:81
int row() const const
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Definition: model.cpp:487
Definition: aggregation.h:21
The Theme class defines the visual appearance of the MessageList.
Definition: theme.h:48
bool isEmpty() const const
ShortFormat
void start()
void rowsInserted(const QModelIndex &parent, int first, int last)
void setOverrideCursor(const QCursor &cursor)
QString & insert(int position, QChar ch)
int elapsed() const const
void rowsRemoved(const QModelIndex &parent, int first, int last)
bool isValid(QStringView ifopt)
@ SortMessagesByAttachmentStatus
Sort the messages By "Important" flags of status.
Definition: sortorder.h:87
QDate date() const const
void setPreSelectionMode(PreSelectionMode preSelect)
Sets the pre-selection mode.
Definition: model.cpp:1003
The QAbstractItemModel based interface that you need to provide for your storage to work with Message...
Definition: storagemodelbase.h:28
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QSet::iterator insert(const T &value)
QList::iterator begin()
InitialExpandStatus initialExpandStatus() const
The initial expand status we have to honor when attaching to the viewable root.
Definition: item.cpp:347
const Akonadi::MessageStatus & status() const
Returns the status associated to this Item.
Definition: item.cpp:446
@ SortMessagesByDateTimeOfMostRecent
Sort the messages by date and time of the most recent message in subtree.
Definition: sortorder.h:78
@ FavorInteractivity
Do small chunks of work, small intervals between chunks to allow for UI event processing.
Definition: aggregation.h:105
qint32 toQInt32() const
This class manages sets of messageitem references.
Definition: messageitemsetmanager.h:45
void setInitialExpandStatus(InitialExpandStatus initialExpandStatus)
Set the initial expand status we have to honor when attaching to the viewable root.
Definition: item.cpp:352
void restoreOverrideCursor()
This class is responsible of matching messages that should be displayed in the View.
Definition: filter.h:44
int appendChildItem(Model *model, Item *child)
Appends an Item to this item's child list.
Definition: item.cpp:597
~Model() override
Destroys the mighty model along with the tree of items it manages.
Definition: model.cpp:352
A single item of the MessageList tree managed by MessageList::Model.
Definition: item.h:47
QList::iterator end()
int dayOfWeek() const const
@ SortGroupsBySender
Sort groups by sender (makes sense only with GroupBySender)
Definition: sortorder.h:64
QString standaloneDayName(int day, QLocale::FormatType type) const const
bool hasAncestor(const Item *it) const
Return true if Item pointed by it is an ancestor of this item (that is, if it is its parent,...
Definition: item.cpp:362
@ ExpandThreadsWithNewMessages
DEPRECATED. New message status no longer exists.
Definition: aggregation.h:92
void setFilter(const Filter *filter)
Sets the Filter to be applied on messages.
Definition: model.cpp:391
void setMaxDate(time_t date)
Sets the maximum date in the subtree originating from this item.
Definition: item.cpp:481
QList< MessageItem * > persistentSetCurrentMessageItemList(MessageItemSetReference ref)
Returns the list of MessageItems that are still existing in the set pointed by the specified referenc...
Definition: model.cpp:4560
A set of aggregation options that can be applied to the MessageList::Model in a single shot.
Definition: aggregation.h:28
bool isImportant() const
QObject * parent() const const
QString message
qint64 daysTo(const QDate &d) const const
@ GroupByDateRange
Use smart (thread leader) date ranges ("Today","Yesterday","Last Week"...)
Definition: aggregation.h:39
const QList< QKeySequence > & end()
char * data()
@ PerfectThreadingPlusReferences
messageIdMD5, inReplyToMD5, referencesIdMD5
Definition: storagemodelbase.h:80
void start()
MessageItemSetReference createPersistentSet(const QVector< MessageItem * > &items)
Creates a persistent set for the specified MessageItems and returns its reference.
Definition: model.cpp:4546
bool isLoading() const
Returns true if the view is currently loading, that is it's in the first (possibly lengthy) job batch...
Definition: model.cpp:4528
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue May 17 2022 04:00:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue May 17 2022 04:00:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.