File indexing completed on 2024-04-28 05:26:02

0001 // SPDX-FileCopyrightText: 2021 Simon Schmeisser <s.schmeisser@gmx.net>
0002 // SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
0003 // SPDX-License-Identifier: GPL-3.0-or-later
0004 
0005 #include "mailmodel.h"
0006 
0007 #include "messagestatus.h"
0008 #include <Akonadi/EntityTreeModel>
0009 #include <Akonadi/ItemModifyJob>
0010 #include <Akonadi/MessageStatus>
0011 #include <KFormat>
0012 #include <KLocalizedString>
0013 #include <KMime/Message>
0014 #include <QQmlEngine>
0015 
0016 MailModel::MailModel(QObject *parent)
0017     : QSortFilterProxyModel(parent)
0018 {
0019 }
0020 
0021 QHash<int, QByteArray> MailModel::roleNames() const
0022 {
0023     return {
0024         {TitleRole, QByteArrayLiteral("title")},
0025         {DateRole, QByteArrayLiteral("date")},
0026         {DateTimeRole, QByteArrayLiteral("datetime")},
0027         {SenderRole, QByteArrayLiteral("sender")},
0028         {FromRole, QByteArrayLiteral("from")},
0029         {ToRole, QByteArrayLiteral("to")},
0030         {StatusRole, QByteArrayLiteral("status")},
0031         {FavoriteRole, QByteArrayLiteral("favorite")},
0032         {TextColorRole, QByteArrayLiteral("textColor")},
0033         {BackgroundColorRole, QByteArrayLiteral("backgroudColor")},
0034         {ItemRole, QByteArrayLiteral("item")},
0035     };
0036 }
0037 
0038 QVariant MailModel::data(const QModelIndex &index, int role) const
0039 {
0040     QVariant itemVariant = sourceModel()->data(mapToSource(index), Akonadi::EntityTreeModel::ItemRole);
0041 
0042     Akonadi::Item item = itemVariant.value<Akonadi::Item>();
0043 
0044     if (!item.hasPayload<KMime::Message::Ptr>()) {
0045         return {};
0046     }
0047     const KMime::Message::Ptr mail = item.payload<KMime::Message::Ptr>();
0048 
0049     // Static for speed reasons
0050     static const QString noSubject = i18nc("displayed as subject when the subject of a mail is empty", "No Subject");
0051     static const QString unknown(i18nc("displayed when a mail has unknown sender, receiver or date", "Unknown"));
0052 
0053     QString subject = mail->subject()->asUnicodeString();
0054     if (subject.isEmpty()) {
0055         subject = QLatin1Char('(') + noSubject + QLatin1Char(')');
0056     }
0057 
0058     MessageStatus stat;
0059     stat.setStatusFromFlags(item.flags());
0060 
0061     // NOTE: remember to update AkonadiBrowserSortModel::lessThan if you insert/move columns
0062     switch (role) {
0063     case TitleRole:
0064         if (mail->subject()) {
0065             return mail->subject()->asUnicodeString();
0066         } else {
0067             return noSubject;
0068         }
0069     case FromRole:
0070         if (mail->from()) {
0071             return mail->from()->asUnicodeString();
0072         } else {
0073             return QString();
0074         }
0075     case SenderRole:
0076         if (mail->sender()) {
0077             return mail->sender()->asUnicodeString();
0078         } else {
0079             return QString();
0080         }
0081     case ToRole:
0082         if (mail->to()) {
0083             return mail->to()->asUnicodeString();
0084         } else {
0085             return unknown;
0086         }
0087     case DateRole:
0088         if (mail->date()) {
0089             KFormat format;
0090             return format.formatRelativeDate(mail->date()->dateTime().date(), QLocale::LongFormat);
0091         } else {
0092             return QString();
0093         }
0094     case DateTimeRole:
0095         if (mail->date()) {
0096             return mail->date()->dateTime();
0097         } else {
0098             return QString();
0099         }
0100     case StatusRole:
0101         return QVariant::fromValue(stat);
0102     case ItemRole:
0103         return QVariant::fromValue(item);
0104     }
0105 
0106     return {};
0107 }
0108 
0109 Akonadi::Item MailModel::itemForRow(int row) const
0110 {
0111     return data(index(row, 0), ItemRole).value<Akonadi::Item>();
0112 }
0113 
0114 void MailModel::updateMessageStatus(int row, MessageStatus messageStatus)
0115 {
0116     Akonadi::Item item = itemForRow(row);
0117     item.setFlags(messageStatus.statusFlags());
0118     auto job = new Akonadi::ItemModifyJob(item, this);
0119     job->disableRevisionCheck();
0120     job->setIgnorePayload(true);
0121 
0122     Q_EMIT dataChanged(index(row, 0), index(row, 0), {StatusRole});
0123 }
0124 
0125 MessageStatus MailModel::copyMessageStatus(MessageStatus messageStatus)
0126 {
0127     MessageStatus newStatus;
0128     newStatus.set(messageStatus);
0129     return messageStatus;
0130 }
0131 
0132 QString MailModel::searchString() const
0133 {
0134     return m_searchString;
0135 }
0136 
0137 void MailModel::setSearchString(const QString &searchString)
0138 {
0139     if (searchString == m_searchString) {
0140         return;
0141     }
0142     m_searchString = searchString;
0143     invalidateFilter();
0144     Q_EMIT searchStringChanged();
0145 }
0146 
0147 bool MailModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
0148 {
0149     Q_UNUSED(sourceParent)
0150     if (m_searchString.isEmpty()) {
0151         return true;
0152     }
0153     QVariant itemVariant = sourceModel()->index(sourceRow, 0).data(Akonadi::EntityTreeModel::ItemRole);
0154 
0155     Akonadi::Item item = itemVariant.value<Akonadi::Item>();
0156 
0157     if (!item.hasPayload<KMime::Message::Ptr>()) {
0158         return false;
0159     }
0160     const KMime::Message::Ptr mail = item.payload<KMime::Message::Ptr>();
0161 
0162     if (mail->subject() && mail->subject()->asUnicodeString().contains(m_searchString)) {
0163         return true;
0164     }
0165     if (mail->from() && mail->from()->asUnicodeString().contains(m_searchString)) {
0166         return true;
0167     }
0168     return false;
0169 }