File indexing completed on 2024-11-24 04:50:44

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