20#include "messagethreaderproxymodel.h"
21#include "messagethreadingattribute.h"
22#include "messagemodel.h"
24#include <akonadi/attributefactory.h>
25#include <akonadi/itemfetchjob.h>
26#include <akonadi/itemfetchscope.h>
28#include <QtCore/QDebug>
29#include <QtCore/QString>
30#include <QtCore/QStringList>
31#include <QtCore/QHash>
32#include <QtCore/QTime>
33#include <QtCore/QModelIndex>
37class MessageThreaderProxyModel::Private
47 return dynamic_cast<MessageModel *
>(mParent->sourceModel());
53 void slotCollectionChanged()
58 realPerfectParentsMap.clear();
59 realUnperfectParentsMap.clear();
60 realSubjectParentsMap.clear();
62 realPerfectChildrenMap.clear();
63 realUnperfectChildrenMap.clear();
64 realSubjectChildrenMap.clear();
73 void slotInsertRows(
const QModelIndex &sourceIndex,
int begin,
int end)
75 Q_UNUSED(sourceIndex);
79 for (
int i = begin; i <= end; i++) {
81 Item item = sourceMessageModel()->itemForIndex(sourceMessageModel()->
index(i, 0));
84 readParentsFromParts(item);
85 Entity::Id parentId = parentForItem(item.id());
90 int row = childrenMap[parentId].count();
91 mParent->beginInsertRows(indexMap[parentId], row, row);
92 childrenMap[parentId] << item.id();
93 parentMap[id] = parentId;
94 QModelIndex
index = mParent->createIndex(childrenMap[parentId].count() - 1, 0,
id);
95 mParent->endInsertRows();
100 QList<Entity::Id> potentialChildren = realPerfectChildrenMap[id]
101 << realUnperfectChildrenMap[id]
102 << realSubjectChildrenMap[id];
103 foreach (
Entity::Id potentialChildId, potentialChildren) {
108 if (potentialChildId !=
id &&
109 parentMap.constFind(potentialChildId) != parentMap.constEnd() &&
110 parentMap[potentialChildId] !=
id &&
111 parentMap[potentialChildId]) {
113 QList<Entity::Id> realParentsList = realPerfectParentsMap[potentialChildId]
114 << realUnperfectParentsMap[potentialChildId]
115 << realSubjectParentsMap[potentialChildId];
116 int currentParentPos = realParentsList.indexOf(parentMap[potentialChildId]);
118 if (currentParentPos == 0 || (currentParentPos != -1 && realParentsList.indexOf(
id) > currentParentPos)) {
124 int childRow = childrenMap[parentMap[potentialChildId]].indexOf(potentialChildId);
125 mParent->beginRemoveRows(indexMap[parentMap[potentialChildId]], childRow, childRow);
126 mParent->endRemoveRows();
127 childrenMap[parentMap[potentialChildId]].removeAt(childRow);
130 mParent->beginInsertRows(
index, childrenMap[
id].count(), childrenMap[
id].count());
131 parentMap[potentialChildId] = id;
132 childrenMap[id] << potentialChildId;
135 mParent->createIndex(childrenMap[
id].count() - 1, 0, potentialChildId);
136 mParent->endInsertRows();
141 qDebug() << time.elapsed() <<
"ms for" << end - begin + 1 <<
"items";
148 void slotRemoveRows(
const QModelIndex &sourceIndex,
int begin,
int end)
150 Q_UNUSED(sourceIndex);
151 for (
int i = begin; i <= end; i++) {
152 Item item = sourceMessageModel()->itemForIndex(sourceMessageModel()->
index(i, 0));
155 int row = childrenMap[parentId].indexOf(
id);
158 foreach (
Entity::Id childId, childrenMap[
id]) {
159 int childRow = childrenMap[id].indexOf(childId);
160 mParent->beginRemoveRows(indexMap[
id], childRow, childRow);
161 childrenMap[id].removeAll(childId);
162 mParent->endRemoveRows();
164 mParent->beginInsertRows(indexMap[parentId], childrenMap[parentId].count(),
165 childrenMap[parentId].count());
166 parentMap[childId] = parentId;
167 childrenMap[parentId] << childId;
168 mParent->endInsertRows();
170 mParent->createIndex(childrenMap[parentId].count() - 1, 0, childId);
173 mParent->beginRemoveRows(indexMap[parentId], row, row);
174 childrenMap[parentId].removeAll(
id);
175 parentMap.remove(
id);
177 mParent->endRemoveRows();
191 void readParentsFromParts(
const Item &item)
195 QList<Entity::Id> realPerfectParentsList = attr->
perfectParents();
197 QList<Entity::Id> realSubjectParentsList = attr->
subjectParents();
199 realPerfectParentsMap[item.id()] = realPerfectParentsList;
200 realUnperfectParentsMap[item.id()] = realUnperfectParentsList;
201 realSubjectParentsMap[item.id()] = realSubjectParentsList;
204 foreach (
Entity::Id parentId, realPerfectParentsList) {
205 realPerfectChildrenMap[parentId] << item.id();
207 foreach (
Entity::Id parentId, realUnperfectParentsList) {
208 realUnperfectChildrenMap[parentId] << item.id();
210 foreach (
Entity::Id parentId, realSubjectParentsList) {
211 realSubjectChildrenMap[parentId] << item.id();
224 QList<Entity::Id> parentsIds;
225 parentsIds << realPerfectParentsMap[id] << realUnperfectParentsMap[id] << realSubjectParentsMap[id];
230 if (sourceMessageModel()->indexForItem(Item(parentId), 0).isValid()) {
242 return index.isValid() ?
index.internalId() : -1;
252 QHash<Entity::Id, QList<Entity::Id> > childrenMap;
253 QHash<Entity::Id, Entity::Id> parentMap;
254 QHash<Entity::Id, QModelIndex> indexMap;
261 QHash<Entity::Id, QList<Entity::Id> > realPerfectParentsMap;
262 QHash<Entity::Id, QList<Entity::Id> > realUnperfectParentsMap;
263 QHash<Entity::Id, QList<Entity::Id> > realSubjectParentsMap;
265 QHash<Entity::Id, QList<Entity::Id> > realPerfectChildrenMap;
266 QHash<Entity::Id, QList<Entity::Id> > realUnperfectChildrenMap;
267 QHash<Entity::Id, QList<Entity::Id> > realSubjectChildrenMap;
271 : QAbstractProxyModel(parent)
272 , d(new Private(this))
274 AttributeFactory::registerAttribute<MessageThreadingAttribute>();
288 || row >= d->childrenMap[parentId].count()
290 return QModelIndex();
293 Entity::Id id = d->childrenMap[parentId].at(row);
300 if (!
index.isValid()) {
301 return QModelIndex();
306 if (parentId == -1) {
307 return QModelIndex();
312 return d->indexMap[d->parentMap[
index.internalId()]];
319 return d->sourceMessageModel()->indexForItem(Item(
index.internalId()),
index.column());
324 Item item = d->sourceMessageModel()->itemForIndex(
index);
332 QModelIndex
index = QAbstractProxyModel::createIndex(row, column, internalId);
334 d->indexMap[internalId] =
index;
342 QAbstractProxyModel::setSourceModel(model);
347 connect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,
int,
int)), SLOT(slotInsertRows(QModelIndex,
int,
int)));
348 connect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,
int,
int)), SLOT(slotRemoveRows(QModelIndex,
int,
int)));
349 connect(d->sourceMessageModel(), SIGNAL(collectionChanged(
Akonadi::Collection)), SLOT(slotCollectionChanged()));
361 return sourceModel()->columnCount(QModelIndex());
368 return d->childrenMap[-1].count();
371 if (
index.column() == 0) {
372 return d->childrenMap[id].count();
380 return d->sourceMessageModel()->mimeTypes();
385 QModelIndexList sourceIndexes;
386 for (
int i = 0; i < indexes.count(); i++) {
390 return sourceModel()->mimeData(sourceIndexes);
393#include "moc_messagethreaderproxymodel.cpp"
Represents a collection of PIM items.
qint64 Id
Describes the unique id type.
A flat self-updating message model.
Proxy to thread message using the Mailthreader agent.
QModelIndex mapToSource(const QModelIndex &index) const
Reimplemented.
QModelIndex index(int row, int column, const QModelIndex &parent) const
Reimplemented.
QModelIndex mapFromSource(const QModelIndex &index) const
Reimplemented.
QModelIndex parent(const QModelIndex &index) const
Reimplemented to actually do the threading.
int columnCount(const QModelIndex &index) const
Reimplemented.
virtual ~MessageThreaderProxyModel()
Destroy the model.
QMimeData * mimeData(const QModelIndexList &indexes) const
Reimplemented.
int rowCount(const QModelIndex &index) const
Reimplemented.
void setSourceModel(QAbstractItemModel *sourceMessageModel)
Set the source model.
bool hasChildren(const QModelIndex &index) const
Reimplemented.
QStringList mimeTypes() const
Reimplemented.
MessageThreaderProxyModel(QObject *parent=0)
Create a new MessageThreaderProxyModel.
QModelIndex createIndex(int row, int column, quint32 internalId) const
Reimplemented.
Message threading information.
QList< Item::Id > subjectParents() const
Returns the list of possible parent message ids based on analyzing the subject.
QList< Item::Id > perfectParents() const
Returns the list of perfect parent message ids.
QList< Item::Id > unperfectParents() const
Returns the list of non-perfect parent message ids.
FreeBusyManager::Singleton.