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 }