GUI: Profile-specific icon for systray
[trojita.git] / src / Cryptography / MessageModel.cpp
blob9333e402fea400fa2315b92cf503a1d78a1a86cd
1 /* Copyright (C) 2014 - 2015 Stephan Platz <trojita@paalsteek.de>
2 Copyright (C) 2006 - 2016 Jan Kundrát <jkt@kde.org>
4 This file is part of the Trojita Qt IMAP e-mail client,
5 http://trojita.flaska.net/
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of
10 the License or (at your option) version 3 or any later version
11 accepted by the membership of KDE e.V. (or its successor approved
12 by the membership of KDE e.V.), which shall act as a proxy
13 defined in Section 14 of version 3 of the license.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "Cryptography/MessageModel.h"
25 #include "Cryptography/MessagePart.h"
26 #include "Cryptography/PartReplacer.h"
27 #include "Common/MetaTypes.h"
28 #include "Imap/Model/ItemRoles.h"
29 #include "Imap/Model/MailboxTree.h"
31 namespace Cryptography {
33 MessageModel::MessageModel(QObject *parent, const QModelIndex &message)
34 : QAbstractItemModel(parent)
35 , m_message(message)
36 , m_rootPart(std::move(new TopLevelMessage(m_message, this)))
38 Q_ASSERT(m_message.isValid());
39 connect(m_message.model(), &QAbstractItemModel::dataChanged, this, &MessageModel::mapDataChanged);
42 void MessageModel::mapDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
44 if (!m_message.isValid()) {
45 return;
48 Q_ASSERT(m_message.model());
49 Q_ASSERT(topLeft.parent() == bottomRight.parent());
51 QModelIndex root = index(0,0);
52 if (!root.isValid())
53 return;
55 auto topLeftIt = m_map.constFind(topLeft);
56 auto bottomRightIt = m_map.constFind(bottomRight);
57 if (topLeftIt != m_map.constEnd() && bottomRightIt != m_map.constEnd()) {
58 emit dataChanged(
59 createIndex(topLeft.row(), topLeft.column(), *topLeftIt),
60 createIndex(bottomRight.row(), bottomRight.column(), *bottomRightIt)
65 QModelIndex MessageModel::index(int row, int column, const QModelIndex &parent) const
67 Q_ASSERT(!parent.isValid() || parent.model() == this);
68 auto parentPart = translatePtr(parent);
69 Q_ASSERT(parentPart);
70 auto childPtr = parentPart->child(const_cast<MessageModel *>(this), row, column);
71 if (!childPtr) {
72 return QModelIndex();
73 } else {
74 return createIndex(row, column, childPtr);
78 QModelIndex MessageModel::parent(const QModelIndex &child) const
80 if (!child.isValid())
81 return QModelIndex();
82 Q_ASSERT(child.model() == this);
83 auto childPart = translatePtr(child);
84 Q_ASSERT(childPart);
85 auto parentPart = childPart->parent();
86 return (parentPart && parentPart != m_rootPart.get()) ? createIndex(parentPart->row(), 0, parentPart) : QModelIndex();
89 QVariant MessageModel::data(const QModelIndex &index, int role) const
91 if (!index.isValid()) {
92 return QVariant();
95 Q_ASSERT(index.model() == this);
97 return translatePtr(index)->data(role);
100 QModelIndex MessageModel::message() const
102 return m_message;
105 void MessageModel::insertSubtree(const QModelIndex &parent, MessagePart::Ptr tree)
107 std::vector<MessagePart::Ptr> parts;
108 parts.emplace_back(std::move(tree));
109 insertSubtree(parent, std::move(parts));
112 void MessageModel::insertSubtree(const QModelIndex &parent, std::vector<Cryptography::MessagePart::Ptr> &&parts)
114 Q_ASSERT(!parent.isValid() || parent.model() == this);
115 auto *part = translatePtr(parent);
116 Q_ASSERT(part);
118 #ifdef MIME_TREE_DEBUG
119 qDebug() << "Whole tree:\n" << *m_rootPart;
120 qDebug() << "Inserting at:\n" << (void*)(part);
121 #endif
123 beginInsertRows(parent, 0, parts.size());
125 Q_ASSERT(part->m_children.empty());
126 for (size_t i = 0; i < parts.size(); ++i) {
127 #ifdef MIME_TREE_DEBUG
128 qDebug() << "New item[" << i << "]:\n" << *(parts[i].get());
129 #endif
130 parts[i]->m_parent = part;
131 part->m_children[i] = std::move(parts[i]);
134 bool needsDataChanged = false;
135 if (LocalMessagePart *localPart = dynamic_cast<LocalMessagePart*>(part)) {
136 localPart->m_localState = MessagePart::FetchingState::DONE;
137 needsDataChanged = true;
140 endInsertRows();
142 if (needsDataChanged) {
143 emit dataChanged(parent, parent);
147 void MessageModel::replaceMeWithSubtree(const QModelIndex &parent, MessagePart *partToReplace, MessagePart::Ptr tree)
149 Q_ASSERT(!parent.isValid() || parent.model() == this);
150 auto *part = translatePtr(parent);
151 Q_ASSERT(part);
153 #ifdef MIME_TREE_DEBUG
154 qDebug() << "Whole tree:\n" << *m_rootPart;
155 qDebug() << "Replacing:\n" << (void*)(partToReplace);
156 qDebug() << "New items:\n" << *(tree.get());
157 #endif
159 Q_ASSERT(partToReplace);
160 Q_ASSERT(tree->row() == partToReplace->row());
162 auto it = part->m_children.find(partToReplace->row());
163 Q_ASSERT(it != part->m_children.end());
164 Q_ASSERT(it->second->row() == partToReplace->row());
165 Q_ASSERT(partToReplace->row() == tree->row());
167 emit layoutAboutToBeChanged(QList<QPersistentModelIndex>() << parent);
169 auto oldIndexes = persistentIndexList();
170 auto newIndexes = oldIndexes;
171 for (int i = 0; i < oldIndexes.size(); ++i) {
172 const auto &index = oldIndexes[i];
173 if (index.parent() == parent && index.column() == 0 && index.row() == tree->row()) {
174 newIndexes[i] = createIndex(tree->row(), 0, tree.get());
177 changePersistentIndexList(oldIndexes, newIndexes);
179 tree->m_parent = part;
180 MessagePart::Ptr partGoingAway = std::move(it->second);
181 it->second = std::move(tree);
182 emit layoutChanged(QList<QPersistentModelIndex>() << parent);
184 emit dataChanged(parent, parent);
186 #ifdef MIME_TREE_DEBUG
187 qDebug() << "After replacement:\n" << *m_rootPart;
188 #endif
191 /** @short Get the underlying MessagePart * for the passed index */
192 MessagePart *MessageModel::translatePtr(const QModelIndex &part) const
194 if (!part.isValid())
195 return m_rootPart.get();
196 return static_cast<MessagePart *>(part.internalPointer());
199 int MessageModel::rowCount(const QModelIndex &parent) const
201 return translatePtr(parent)->rowCount(const_cast<MessageModel *>(this));
204 int MessageModel::columnCount(const QModelIndex &parent) const
206 return translatePtr(parent)->columnCount(const_cast<MessageModel *>(this));
209 void MessageModel::registerPartHandler(std::shared_ptr<PartReplacer> module)
211 m_partHandlers.push_back(module);
214 #ifdef MIME_TREE_DEBUG
215 void MessageModel::debugDump()
217 qDebug() << "MIME tree:\n" << *m_rootPart;
219 #endif