Messagelib
model.cpp
140 * That's why we in fact have Pass1Fill, Pass1Cleanup, Pass1Update, Pass2, Pass3, Pass4 and Pass5 below.
141 * Pass1Fill, Pass1Cleanup and Pass1Update are exclusive and all of them proceed with Pass2 when finished.
147 Pass1Fill = 0, ///< Build threading caches, *TRY* to do some threading, try to attach something to the view
198 ViewItemJob(int startIndex, int endIndex, int chunkTimeout, int idleInterval, int messageCheckCount, bool disconnectUI = false)
214 ViewItemJob(Pass pass, QList<ModelInvariantIndex *> *invariantIndexList, int chunkTimeout, int idleInterval, int messageCheckCount)
339 d->mCachedWatchedOrIgnoredStatusBits = Akonadi::MessageStatus::statusIgnored().toQInt32() | Akonadi::MessageStatus::statusWatched().toQInt32();
371 d->mView->setRootIsDecorated((d->mAggregation->grouping() == Aggregation::NoGrouping) && (d->mAggregation->threading() != Aggregation::NoThreading));
576 // FIXME: This function is a bottleneck (the caching in indexOfChildItem only works 30% of the time)
600 return QModelIndex(); // senseless column (we could optimize by skipping this check but ModelTest from trolltech is pedantic)
753 std::for_each(d->mStorageModelConnections.cbegin(), d->mStorageModelConnections.cend(), [](const QMetaObject::Connection &c) -> bool {
776 qCDebug(MESSAGELIST_LOG) << "Threading disabled in previous folder, not saving threading cache";
788 qCDebug(MESSAGELIST_LOG) << "Threading disabled in folder" << d->mStorageModel->id() << ", not using threading cache";
824 connect(d->mStorageModel, &StorageModel::headerDataChanged, this, [this](Qt::Orientation orientation, int first, int last) {
848 // adjusted by the second job. For instance, in my kernel mailing list folder this "smart" approach
904 (d->mAggregation->threadExpandPolicy() == Aggregation::NeverExpandThreads) || // or we expand threads but we'll be going to expand really only a few
907 (d->mAggregation->threadExpandPolicy() != Aggregation::AlwaysExpandThreads) && // and we'd expand only a few in fact
914 // First a small job with the most recent messages. Large chunk, small (but non zero) idle interval
917 new ViewItemJob(d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 200, 20, 100, canDoFirstSmallChunkWithDisconnectedUI);
919 // Then a larger job with older messages. Small chunk, bigger idle interval, small number of messages to
930 auto job = new ViewItemJob(0, d->mStorageModel->rowCount() - 1, 150, 30, 30, canDoJobWithDisconnectedUI);
939 new ViewItemJob(d->mStorageModel->rowCount() - 1000, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoFirstSmallChunkWithDisconnectedUI);
946 auto job = new ViewItemJob(0, d->mStorageModel->rowCount() - 1, 250, 0, 100, canDoJobWithDisconnectedUI);
952 auto job = new ViewItemJob(0, d->mStorageModel->rowCount() - 1, 60000, 0, 100000, canDoJobWithDisconnectedUI);
969 // This function is called by MessageList::Core::Manager once in a while (every 1 minute or sth).
973 // on the fly would be too expensive). We also cache the labels of the groups which often display dates.
1008 // The "view fill" algorithm implemented in the functions below is quite smart but also quite complex.
1011 // - Be flexible: allow different configurations from "unsorted flat list" to a "grouped and threaded
1015 // - Be interruptible: user must be able to abort the execution and just switch to another folder in the middle
1039 // Something may *also* be in mUnassignedMessageListForPass3 and mUnassignedMessageListForPass4
1097 // mUnassignedMessageListForPass4 is empty so we must be at the end of a very special kind of Pass2
1164 mModelForItemFunctions = q; // make sure it's true, as there remains no job with disconnected UI
1225 if (ghi->initialExpandStatus() == Item::ExpandNeeded) { // this actually is a "non viewable expanded state"
1268 // - 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)
1272 // if ( !mView->isExpanded( idx ) ) // this is O(logN!) in Qt.... very ugly... but it should never happen here
1322 auto dayName = mCachedDayNameLabel.find(dDate.dayOfWeek()); // non-const call, but non-shared container
1324 dayName = mCachedDayNameLabel.insert(dDate.dayOfWeek(), QLocale::system().standaloneDayName(dDate.dayOfWeek()));
1327 } else if (mAggregation->grouping() == Aggregation::GroupByDate) { // GroupByDate seven days or more ago
1331 int startOfWeekDaysAgo = (daysInWeek + mTodayDate.dayOfWeek() - QLocale().firstDayOfWeek()) % daysInWeek;
1356 auto monthName = mCachedMonthNameLabel.find(dDate.month()); // non-const call, but non-shared container
1358 monthName = mCachedMonthNameLabel.insert(dDate.month(), QLocale::system().standaloneMonthName(dDate.month()));
1362 auto monthName = mCachedMonthNameLabel.find(dDate.month()); // non-const call, but non-shared container
1364 monthName = mCachedMonthNameLabel.insert(dDate.month(), QLocale::system().standaloneMonthName(dDate.month()));
1460 Q_ASSERT(mAggregation->threading() != Aggregation::NoThreading); // caller must take care of this
1493 qCWarning(MESSAGELIST_LOG) << "Circular In-Reply-To reference loop detected in the message tree";
1506 mi->setThreadingStatus(bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable);
1539 auto messagesWithTheSameReferences = mThreadingCacheMessageReferencesIdMD5ToMessageItem.value(md5, nullptr);
1555 mi->setThreadingStatus(bMessageWasThreadable ? MessageItem::ParentMissing : MessageItem::NonThreadable);
1567 mi->setThreadingStatus((bMessageWasThreadable || mi->subjectIsPrefixed()) ? MessageItem::ParentMissing : MessageItem::NonThreadable);
1575 void dump_iterator_and_list(QList< MessageItem * >::Iterator &iter, QList< MessageItem * > *list)
1581 qCDebug(MESSAGELIST_LOG) << "Iterator pointing to " << *iter << " subject [" << (*iter)->subject() << "] date [" << (*iter)->date() << "]";
1585 qCDebug(MESSAGELIST_LOG) << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]";
1596 qCDebug(MESSAGELIST_LOG) << "List element " << *it << " subject [" << (*it)->subject() << "] date [" << (*it)->date() << "]";
1623 // Messages in this cache are sorted by date, and if dates are equal then they are sorted by pointer value.
1630 auto messagesWithTheSameReference = mThreadingCacheMessageReferencesIdMD5ToMessageItem.value(mi->referencesIdMD5(), nullptr);
1634 mThreadingCacheMessageReferencesIdMD5ToMessageItem.insert(mi->referencesIdMD5(), messagesWithTheSameReference);
1643 auto it = std::lower_bound(messagesWithTheSameReference->begin(), messagesWithTheSameReference->end(), mi, MessageLessThanByDate());
1652 auto messagesWithTheSameReference = mThreadingCacheMessageReferencesIdMD5ToMessageItem.value(mi->referencesIdMD5(), nullptr);
1658 auto it = std::lower_bound(messagesWithTheSameReference->begin(), messagesWithTheSameReference->end(), mi, MessageLessThanByDate());
1678 // Messages in this cache are sorted by date, and if dates are equal then they are sorted by pointer value.
1686 auto messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value(mi->strippedSubjectMD5(), nullptr);
1691 mThreadingCacheMessageSubjectMD5ToMessageItem.insert(mi->strippedSubjectMD5(), messagesWithTheSameStrippedSubject);
1700 auto it = std::lower_bound(messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate());
1712 auto messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value(mi->strippedSubjectMD5(), nullptr);
1718 auto it = std::lower_bound(messagesWithTheSameStrippedSubject->begin(), messagesWithTheSameStrippedSubject->end(), mi, MessageLessThanByDate());
1745 Q_ASSERT(mAggregation->threading() == Aggregation::PerfectReferencesAndSubject); // caller must take care of this
1752 auto messagesWithTheSameStrippedSubject = mThreadingCacheMessageSubjectMD5ToMessageItem.value(md5, nullptr);
1828 static bool messageItemNeedsReSorting(SortOrder::SortDirection messageSortDirection, ItemPrivate *parent, MessageItem *messageItem)
1841 // - If we're sorting messages by min/max date then at each level the messages might need resorting.
1869 mGroupHeadersThatNeedUpdate.insert(static_cast<GroupHeaderItem *>(item), static_cast<GroupHeaderItem *>(item));
1881 if (messageItemNeedsReSorting<ItemDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1888 if (messageItemNeedsReSorting<ItemMaxDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1895 if (messageItemNeedsReSorting<ItemActionItemStatusComparator>(mSortOrder->messageSortDirection(),
1913 if (messageItemNeedsReSorting<ItemImportantStatusComparator>(mSortOrder->messageSortDirection(),
1922 if (messageItemNeedsReSorting<ItemAttachmentStatusComparator>(mSortOrder->messageSortDirection(),
1969 if (messageItemNeedsReSorting<ItemDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1976 if (messageItemNeedsReSorting<ItemMaxDateComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1983 if (messageItemNeedsReSorting<ItemActionItemStatusComparator>(mSortOrder->messageSortDirection(),
1992 if (messageItemNeedsReSorting<ItemUnreadStatusComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
1999 if (messageItemNeedsReSorting<ItemImportantStatusComparator>(mSortOrder->messageSortDirection(), parent->d_ptr, static_cast<MessageItem *>(item))) {
2006 if (messageItemNeedsReSorting<ItemAttachmentStatusComparator>(mSortOrder->messageSortDirection(),
2067 mGroupHeadersThatNeedUpdate.insert(static_cast<GroupHeaderItem *>(oldParent), static_cast<GroupHeaderItem *>(oldParent));
2115 void ModelPrivate::attachMessageToParent(Item *pParent, MessageItem *mi, AttachOptions attachOptions)
2207 Q_ASSERT(!mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains(mi->inReplyToIdMD5(), mi));
2242 if ((mSortOrder->messageSortDirection() == SortOrder::Ascending) || (pParent->type() == Item::Message)) { \
2303 case Aggregation::ExpandThreadsWithNewMessages: // No more new status. fall through to unread if it exists in config
2313 if (childNeedsExpanding || !mi->status().isRead() || mi->status().isImportant() || mi->status().isToAct()) {
2416 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass5(ViewItemJob *job, QElapsedTimer elapsedTimer)
2454 needsReSorting = (*it)->parent()->d_ptr->childItemNeedsReSorting<_ItemDateComparator, true>(*it); \
2457 needsReSorting = (*it)->parent()->d_ptr->childItemNeedsReSorting<_ItemDateComparator, false>(*it); \
2514 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass4(ViewItemJob *job, QElapsedTimer elapsedTimer)
2555 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass3(ViewItemJob *job, QElapsedTimer elapsedTimer)
2599 // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable)
2600 Q_ASSERT((mi->threadingStatus() == MessageItem::ParentMissing) || (mi->threadingStatus() == MessageItem::NonThreadable));
2606 Q_ASSERT((mi->threadingStatus() == MessageItem::ParentMissing) || (mi->threadingStatus() == MessageItem::NonThreadable));
2612 // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent.
2636 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass2(ViewItemJob *job, QElapsedTimer elapsedTimer)
2641 // to attach in Pass1Fill and their children (which we find here) will make it to the small Pass3
2658 // If it has no parent or it has a temporary one (mi->parent() && mi->threadingStatus() == MessageItem::ParentMissing)
2659 // then we attempt to (re-)thread it. Otherwise we just do nothing (the job has already been done by the previous steps).
2699 // so parent not found, (threadingStatus() is either MessageItem::ParentMissing or MessageItem::NonThreadable)
2716 qCWarning(MESSAGELIST_LOG) << "ERROR: Invalid message threading status returned by findMessageParent()!";
2724 // Since we don't end here if mi has status of parent missing then mi must not have imperfect parent.
2727 qCWarning(MESSAGELIST_LOG) << "Non viewable message " << mi << " subject " << mi->subject().toUtf8().data();
2751 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Fill(ViewItemJob *job, QElapsedTimer elapsedTimer)
2770 unsigned long msgToSelect = mPreSelectionMode == PreSelectLastSelected ? mStorageModel->preSelectedMessage() : 0;
2785 qCWarning(MESSAGELIST_LOG) << "Fill of the MessageItem at storage row index " << curIndex << " failed";
2823 mStorageModel->fillMessageItemThreadingData(mi, curIndex, StorageModel::PerfectThreadingReferencesAndSubject);
2830 mStorageModel->fillMessageItemThreadingData(mi, curIndex, StorageModel::PerfectThreadingPlusReferences);
2870 const auto lImperfectlyThreaded = mThreadingCacheMessageInReplyToIdMD5ToMessageItem.values(mi->messageIdMD5());
2875 if (!((it->threadingStatus() == MessageItem::ImperfectParentFound) || (it->threadingStatus() == MessageItem::ParentMissing))) {
2877 Q_ASSERT_X(false, "ModelPrivate::viewItemJobStepInternalForJobPass1Fill", "Wrong threading status");
2922 qCWarning(MESSAGELIST_LOG) << "Circular In-Reply-To reference loop detected in the message tree";
2965 if ((mAggregation->grouping() == Aggregation::NoGrouping) || (mAggregation->threadLeader() == Aggregation::TopmostMessage)) {
2968 // qCDebug(MESSAGELIST_LOG) << "Setting message status from " << mi->threadingStatus() << " to non threadable (1) " << mi;
2993 // qCDebug(MESSAGELIST_LOG) << "Setting message status from " << mi->threadingStatus() << " to non threadable (2) " << mi;
3023 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Cleanup(ViewItemJob *job, QElapsedTimer elapsedTimer)
3082 mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemAfter(dyingMessage, MessageTypeAny, false);
3088 mCurrentItemToRestoreAfterViewItemJobStep = mView->messageItemBefore(dyingMessage, MessageTypeAny, false);
3091 Q_ASSERT((!mCurrentItemToRestoreAfterViewItemJobStep) || mCurrentItemToRestoreAfterViewItemJobStep->isViewable());
3114 mOrphanChildrenHash.remove(dyingMessage); // this can turn to a no-op (dyingMessage not present in fact)
3132 // If we also have a cache for subject/reference-based threading then remove the message from there too
3149 Q_ASSERT(!mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains(dyingMessage->inReplyToIdMD5(), dyingMessage));
3166 Q_ASSERT(!mThreadingCacheMessageInReplyToIdMD5ToMessageItem.contains(childMessage->inReplyToIdMD5(), childMessage));
3167 mThreadingCacheMessageInReplyToIdMD5ToMessageItem.insert(childMessage->inReplyToIdMD5(), childMessage);
3257 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJobPass1Update(ViewItemJob *job, QElapsedTimer elapsedTimer)
3356 } // else there is no parent so the item isn't attached to the view: re-grouping/re-sorting not needed.
3361 // In all the other cases we (re-)apply the filter to the topmost subtree that this message is in.
3375 // above and climb up eventually hiding parents (without descending the sibling subtrees again).
3403 ModelPrivate::ViewItemJobResult ModelPrivate::viewItemJobStepInternalForJob(ViewItemJob *job, QElapsedTimer elapsedTimer)
3611 static const char *jobDescription[numberOfPasses] = {"Creating items from messages and simple threading",
3660 messagesWithSameSubjectAvg = messagesWithSameSubjectAvg / (float)mThreadingCacheMessageSubjectMD5ToMessageItem.size();
3672 qCDebug(MESSAGELIST_LOG) << "That took" << totalTotalTime << "msecs inside the model and" << completeTime << "in total.";
3673 qCDebug(MESSAGELIST_LOG) << (totalTotalTime / (float)completeTime) * 100.0f << "percent of the time was spent in the model.";
3674 qCDebug(MESSAGELIST_LOG) << "Time for layoutChanged(), in msecs:" << layoutChangeTime << "(" << (layoutChangeTime / (float)totalTotalTime) * 100.0f
3676 qCDebug(MESSAGELIST_LOG) << "Time to expand tree, in msecs:" << expandingTreeTime << "(" << (expandingTreeTime / (float)totalTotalTime) * 100.0f
3683 qCDebug(MESSAGELIST_LOG) << "Threads per group:" << totalThreads / (float)mGroupHeaderItemHash.size();
3699 qCDebug(MESSAGELIST_LOG) << "Number of elements:" << numElements[i]; // TODO: map of element string
3761 // With a connected UI we need to avoid the view to update the scrollbars at EVERY insertion or expansion.
3762 // QTreeViewPrivate::updateScrollBars() is very expensive as it loops through ALL the items in the view every time.
3763 // We can't disable the function directly as it's hidden in the private data object of QTreeView
3932 Item *currentItemBeforeStep = currentIndexBeforeStep.isValid() ? static_cast<Item *>(currentIndexBeforeStep.internalPointer()) : nullptr;
3943 // This is generally SLOW AS HELL... (so we avoid it if we lock the view and thus don't need it)
3961 mFillStepTimer.start(mViewItemJobStepIdleInterval); // this is a single shot timer connected to viewItemJobStep()
4005 qCWarning(MESSAGELIST_LOG) << "ERROR: Unrecognized pre-selection mode " << static_cast<int>(mPreSelectionMode);
4052 Item *currentAfterStep = currentIndexAfterStep.isValid() ? static_cast<Item *>(currentIndexAfterStep.internalPointer()) : nullptr;
4070 qCDebug(MESSAGELIST_LOG) << "Gonna restore current here" << mCurrentItemToRestoreAfterViewItemJobStep->subject();
4084 qCDebug(MESSAGELIST_LOG) << "Gonna restore selection here" << mCurrentItemToRestoreAfterViewItemJobStep->subject();
4088 mView->selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
4093 // FIXME: If it was selected before the change, then re-select it (it may happen that it's not)
4096 QRect rectAfterViewItemJobStep = mView->visualRect(q->index(mCurrentItemToRestoreAfterViewItemJobStep, 0));
4099 mView->verticalScrollBar()->setValue(mView->verticalScrollBar()->value() + rectAfterViewItemJobStep.y() - rectBeforeViewItemJobStep.y());
4111 // Either there was no current item before, or it was lost in a cleanup step and another candidate for
4143 // and the messages created... no need to care anymore: the invariant row mapper will do the job.
4185 // The second part ranges from "from" to job->endIndex() that are now shifted up by count steps.
4188 auto newJob = new ViewItemJob(from + count, job->endIndex() + count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount());
4325 auto newJob = new ViewItemJob(from, job->endIndex() - count, job->chunkTimeout(), job->idleInterval(), job->messageCheckCount());
4332 } // else the change includes completely the end of the job and no other part of it can be completed.
4337 // The change starts below (or exactly on the beginning of) the job. ( from <= job->currentIndex() )
4384 // qCDebug(MESSAGELIST_LOG) << "Appending " << invalidatedIndexes->count() << " invalidated indexes to existing cleanup job";
4397 // qCDebug(MESSAGELIST_LOG) << "Creating new cleanup job for " << invalidatedIndexes->count() << " invalidated indexes";
4417 void ModelPrivate::slotStorageModelDataChanged(const QModelIndex &fromIndex, const QModelIndex &toIndex)
4419 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:740
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:87
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()
Item * rootItem() const
Returns the hidden root item that all the messages are (or will be) attached to.
Definition: model.cpp:4521
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:4566
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()
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
Q_SCRIPTABLE CaptureState status()
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:4531
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:4507
void setAggregation(const Aggregation *aggregation)
Sets the Aggregation mode.
Definition: model.cpp:368
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:88
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:485
Definition: aggregation.h:21
The Theme class defines the visual appearance of the MessageList.
Definition: theme.h:48
QAction * clear(const QObject *recvr, const char *slot, QObject *parent)
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:90
QDate date() const const
void setPreSelectionMode(PreSelectionMode preSelect)
Sets the pre-selection mode.
Definition: model.cpp:1001
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:81
@ 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:350
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:389
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:4558
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:4544
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:4526
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:08:18 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:08:18 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.