File indexing completed on 2024-11-24 04:53:13
0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 0002 0003 This file is part of the Trojita Qt IMAP e-mail client, 0004 http://trojita.flaska.net/ 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License or (at your option) version 3 or any later version 0010 accepted by the membership of KDE e.V. (or its successor approved 0011 by the membership of KDE e.V.), which shall act as a proxy 0012 defined in Section 14 of version 3 of the license. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 #include "OneMessageModel.h" 0024 #include "kdeui-itemviews/kdescendantsproxymodel.h" 0025 #include "FindInterestingPart.h" 0026 #include "ItemRoles.h" 0027 #include "Model.h" 0028 #include "SubtreeModel.h" 0029 #include "Imap/Network/MsgPartNetAccessManager.h" 0030 0031 namespace Imap 0032 { 0033 namespace Mailbox 0034 { 0035 0036 OneMessageModel::OneMessageModel(Model *model): QObject(model), m_subtree(0) 0037 { 0038 m_subtree = new SubtreeModelOfModel(this); 0039 m_subtree->setSourceModel(model); 0040 connect(m_subtree, &QAbstractItemModel::modelReset, this, &OneMessageModel::envelopeChanged); 0041 connect(m_subtree, &QAbstractItemModel::dataChanged, this, &OneMessageModel::envelopeChanged); 0042 connect(this, &OneMessageModel::envelopeChanged, this, &OneMessageModel::flagsChanged); 0043 connect(model, &QAbstractItemModel::dataChanged, this, &OneMessageModel::handleModelDataChanged); 0044 m_flatteningModel = new KDescendantsProxyModel(this); 0045 m_flatteningModel->setSourceModel(m_subtree); 0046 QHash<int, QByteArray> roleNames; 0047 roleNames[RoleIsFetched] = "isFetched"; 0048 roleNames[RolePartMimeType] = "mimeType"; 0049 roleNames[RolePartCharset] = "charset"; 0050 roleNames[RolePartContentFormat] = "contentFormat"; 0051 roleNames[RolePartTransferEncoding] = "transferEncoding"; 0052 roleNames[RolePartBodyFldId] = "bodyFldId"; 0053 roleNames[RolePartBodyDisposition] = "bodyDisposition"; 0054 roleNames[RolePartFileName] = "fileName"; 0055 roleNames[RolePartOctets] = "size"; 0056 roleNames[RolePartId] = "partId"; 0057 roleNames[RolePartPathToPart] = "pathToPart"; 0058 m_flatteningModel->proxySetRoleNames(roleNames); 0059 } 0060 0061 void OneMessageModel::setMessage(const QString &mailbox, const uint uid) 0062 { 0063 m_mainPartUrl = QUrl(QStringLiteral("about:blank")); 0064 emit mainPartUrlChanged(); 0065 QAbstractItemModel *abstractModel = qobject_cast<QAbstractItemModel*>(QObject::parent()); 0066 Q_ASSERT(abstractModel); 0067 Model *model = qobject_cast<Model*>(abstractModel); 0068 Q_ASSERT(model); 0069 setMessage(model->messageIndexByUid(mailbox, uid)); 0070 } 0071 0072 void OneMessageModel::setMessage(const QModelIndex &message) 0073 { 0074 Q_ASSERT(!message.isValid() || message.model() == QObject::parent()); 0075 m_message = message; 0076 m_subtree->setRootItem(message); 0077 0078 // Now try to locate the interesting part of the current message 0079 QModelIndex idx; 0080 QString partMessage; 0081 FindInterestingPart::MainPartReturnCode res = FindInterestingPart::findMainPartOfMessage(m_message, idx, partMessage, 0); 0082 switch (res) { 0083 case Imap::Mailbox::FindInterestingPart::MAINPART_FOUND: 0084 case Imap::Mailbox::FindInterestingPart::MAINPART_PART_LOADING: 0085 Q_ASSERT(idx.isValid()); 0086 m_mainPartUrl = QLatin1String("trojita-imap://msg") + idx.data(RolePartPathToPart).toString(); 0087 break; 0088 case Imap::Mailbox::FindInterestingPart::MAINPART_MESSAGE_NOT_LOADED: 0089 Q_ASSERT(false); 0090 m_mainPartUrl = QLatin1String("data:text/plain;charset=utf-8;base64,") + QString::fromLocal8Bit(QByteArray("").toBase64()); 0091 break; 0092 case Imap::Mailbox::FindInterestingPart::MAINPART_PART_CANNOT_DETERMINE: 0093 // FIXME: show a decent message here 0094 m_mainPartUrl = QLatin1String("data:text/plain;charset=utf-8;base64,") + QString::fromLocal8Bit(QByteArray(partMessage.toUtf8()).toBase64()); 0095 break; 0096 } 0097 emit mainPartUrlChanged(); 0098 } 0099 0100 QDateTime OneMessageModel::date() const 0101 { 0102 return m_message.data(RoleMessageDate).toDateTime(); 0103 } 0104 0105 QDateTime OneMessageModel::receivedDate() const 0106 { 0107 return m_message.data(RoleMessageInternalDate).toDateTime(); 0108 } 0109 0110 QString OneMessageModel::subject() const 0111 { 0112 return m_message.data(RoleMessageSubject).toString(); 0113 } 0114 0115 QVariantList OneMessageModel::from() const 0116 { 0117 return m_message.data(RoleMessageFrom).toList(); 0118 } 0119 0120 QVariantList OneMessageModel::to() const 0121 { 0122 return m_message.data(RoleMessageTo).toList(); 0123 } 0124 0125 QVariantList OneMessageModel::cc() const 0126 { 0127 return m_message.data(RoleMessageCc).toList(); 0128 } 0129 0130 QVariantList OneMessageModel::bcc() const 0131 { 0132 return m_message.data(RoleMessageBcc).toList(); 0133 } 0134 0135 QVariantList OneMessageModel::sender() const 0136 { 0137 return m_message.data(RoleMessageSender).toList(); 0138 } 0139 0140 QVariantList OneMessageModel::replyTo() const 0141 { 0142 return m_message.data(RoleMessageReplyTo).toList(); 0143 } 0144 0145 QByteArray OneMessageModel::inReplyTo() const 0146 { 0147 return m_message.data(RoleMessageInReplyTo).toByteArray(); 0148 } 0149 0150 QByteArray OneMessageModel::messageId() const 0151 { 0152 return m_message.data(RoleMessageMessageId).toByteArray(); 0153 } 0154 0155 bool OneMessageModel::isMarkedDeleted() const 0156 { 0157 return m_message.data(RoleMessageIsMarkedDeleted).toBool(); 0158 } 0159 0160 bool OneMessageModel::isMarkedRead() const 0161 { 0162 return m_message.data(RoleMessageIsMarkedRead).toBool(); 0163 } 0164 0165 bool OneMessageModel::isMarkedForwarded() const 0166 { 0167 return m_message.data(RoleMessageIsMarkedForwarded).toBool(); 0168 } 0169 0170 bool OneMessageModel::isMarkedReplied() const 0171 { 0172 return m_message.data(RoleMessageIsMarkedReplied).toBool(); 0173 } 0174 0175 bool OneMessageModel::isMarkedRecent() const 0176 { 0177 return m_message.data(RoleMessageIsMarkedRecent).toBool(); 0178 } 0179 0180 bool OneMessageModel::isMarkedFlagged() const 0181 { 0182 return m_message.data(RoleMessageIsMarkedFlagged).toBool(); 0183 } 0184 0185 bool OneMessageModel::isMarkedJunk() const 0186 { 0187 return m_message.data(RoleMessageIsMarkedJunk).toBool() && 0188 !m_message.data(RoleMessageIsMarkedNotJunk).toBool(); 0189 } 0190 0191 bool OneMessageModel::isMarkedNotJunk() const 0192 { 0193 return (m_message.data(RoleMessageIsMarkedNotJunk).toBool() && 0194 !m_message.data(RoleMessageIsMarkedJunk).toBool()); 0195 } 0196 0197 0198 QUrl OneMessageModel::mainPartUrl() const 0199 { 0200 return m_mainPartUrl; 0201 } 0202 0203 QObject *OneMessageModel::attachmentsModel() const 0204 { 0205 return m_flatteningModel; 0206 } 0207 0208 QModelIndex OneMessageModel::mainPartModelIndex() 0209 { 0210 return Imap::Network::MsgPartNetAccessManager::pathToPart( 0211 m_message, m_mainPartUrl.path().toUtf8()); 0212 } 0213 0214 void OneMessageModel::setMarkedDeleted(const bool marked) 0215 { 0216 if (!m_message.isValid()) 0217 return; 0218 0219 qobject_cast<Model*>(parent())->markMessagesDeleted(QList<QModelIndex>() << m_message, marked ? FLAG_ADD : FLAG_REMOVE); 0220 } 0221 0222 void OneMessageModel::setMarkedRead(const bool marked) 0223 { 0224 if (!m_message.isValid()) 0225 return; 0226 0227 qobject_cast<Model*>(parent())->markMessagesRead(QList<QModelIndex>() << m_message, marked ? FLAG_ADD : FLAG_REMOVE); 0228 } 0229 0230 void OneMessageModel::handleModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) 0231 { 0232 Q_ASSERT(topLeft.row() == bottomRight.row()); 0233 Q_ASSERT(topLeft.parent() == bottomRight.parent()); 0234 Q_ASSERT(topLeft.model() == bottomRight.model()); 0235 0236 if (m_message.isValid() && topLeft == m_message) 0237 emit flagsChanged(); 0238 } 0239 0240 bool OneMessageModel::hasValidIndex() const 0241 { 0242 return m_message.isValid(); 0243 } 0244 0245 } 0246 }