File indexing completed on 2024-12-22 05:01:14
0001 /* 0002 * SPDX-FileCopyrightText: 2011-2024 Laurent Montel <montel@kde.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only 0005 */ 0006 #include "kmsearchmessagemodel.h" 0007 #include <MailCommon/MailUtil> 0008 #include <MessageList/MessageListUtil> 0009 0010 #include <MessageCore/StringUtil> 0011 0012 #include <Akonadi/ItemFetchScope> 0013 #include <Akonadi/Monitor> 0014 #include <Akonadi/Session> 0015 0016 #include <Akonadi/MessageParts> 0017 #include <KMime/KMimeMessage> 0018 0019 #include <KLocalizedString> 0020 #include <QApplication> 0021 #include <QColor> 0022 #include <QPalette> 0023 0024 KMSearchMessageModel::KMSearchMessageModel(Akonadi::Monitor *monitor, QObject *parent) 0025 : Akonadi::MessageModel(monitor, parent) 0026 { 0027 monitor->itemFetchScope().fetchFullPayload(); 0028 monitor->itemFetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::All); 0029 } 0030 0031 KMSearchMessageModel::~KMSearchMessageModel() = default; 0032 0033 static QString toolTip(const Akonadi::Item &item) 0034 { 0035 auto msg = item.payload<KMime::Message::Ptr>(); 0036 0037 const QColor bckColor = QApplication::palette().color(QPalette::ToolTipBase); 0038 const QColor txtColor = QApplication::palette().color(QPalette::ToolTipText); 0039 0040 const QString bckColorName = bckColor.name(); 0041 const QString txtColorName = txtColor.name(); 0042 const bool textIsLeftToRight = (QApplication::layoutDirection() == Qt::LeftToRight); 0043 const QString textDirection = textIsLeftToRight ? QStringLiteral("left") : QStringLiteral("right"); 0044 0045 QString tip = QStringLiteral("<table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">"); 0046 QString subject; 0047 if (auto msgSubject = msg->subject(false)) { 0048 subject = msgSubject->asUnicodeString(); 0049 } 0050 tip += QStringLiteral( 0051 "<tr>" 0052 "<td bgcolor=\"%1\" align=\"%4\" valign=\"middle\">" 0053 "<div style=\"color: %2; font-weight: bold;\">" 0054 "%3" 0055 "</div>" 0056 "</td>" 0057 "</tr>") 0058 .arg(txtColorName, bckColorName, subject.toHtmlEscaped(), textDirection); 0059 0060 tip += QStringLiteral( 0061 "<tr>" 0062 "<td align=\"center\" valign=\"middle\">" 0063 "<table width=\"100%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">"); 0064 0065 const QString htmlCodeForStandardRow = QStringLiteral( 0066 "<tr>" 0067 "<td align=\"right\" valign=\"top\" width=\"45\">" 0068 "<div style=\"font-weight: bold;\"><nobr>" 0069 "%1:" 0070 "</nobr></div>" 0071 "</td>" 0072 "<td align=\"left\" valign=\"top\">" 0073 "%2" 0074 "</td>" 0075 "</tr>"); 0076 0077 QString content = MessageList::Util::contentSummary(item); 0078 0079 if (textIsLeftToRight) { 0080 tip += htmlCodeForStandardRow.arg(i18n("From"), msg->from()->displayString()); 0081 tip += htmlCodeForStandardRow.arg(i18nc("Receiver of the email", "To"), msg->to()->displayString()); 0082 tip += htmlCodeForStandardRow.arg(i18n("Date"), QLocale().toString(msg->date()->dateTime())); 0083 if (!content.isEmpty()) { 0084 tip += htmlCodeForStandardRow.arg(i18n("Preview"), content.replace(QLatin1Char('\n'), QStringLiteral("<br>"))); 0085 } 0086 } else { 0087 tip += htmlCodeForStandardRow.arg(msg->from()->displayString(), i18n("From")); 0088 tip += htmlCodeForStandardRow.arg(msg->to()->displayString(), i18nc("Receiver of the email", "To")); 0089 tip += htmlCodeForStandardRow.arg(QLocale().toString(msg->date()->dateTime()), i18n("Date")); 0090 if (!content.isEmpty()) { 0091 tip += htmlCodeForStandardRow.arg(content.replace(QLatin1Char('\n'), QStringLiteral("<br>")), i18n("Preview")); 0092 } 0093 } 0094 tip += QLatin1StringView( 0095 "</table" 0096 "</td>" 0097 "</tr>"); 0098 return tip; 0099 } 0100 0101 int KMSearchMessageModel::entityColumnCount(HeaderGroup headerGroup) const 0102 { 0103 if (headerGroup == Akonadi::EntityTreeModel::ItemListHeaders) { 0104 return 6; // keep in sync with the column type enum 0105 } 0106 0107 return Akonadi::MessageModel::entityColumnCount(headerGroup); 0108 } 0109 0110 QString KMSearchMessageModel::fullCollectionPath(Akonadi::Collection::Id id) const 0111 { 0112 QString path = m_collectionFullPathCache.value(id); 0113 if (path.isEmpty()) { 0114 path = MailCommon::Util::fullCollectionPath(Akonadi::Collection(id)); 0115 m_collectionFullPathCache.insert(id, path); 0116 } 0117 return path; 0118 } 0119 0120 QVariant KMSearchMessageModel::entityData(const Akonadi::Item &item, int column, int role) const 0121 { 0122 if (!item.isValid()) { 0123 QVariant(); 0124 } 0125 0126 if (role == Qt::ToolTipRole) { 0127 return toolTip(item); 0128 } 0129 0130 // The Collection column is first and is added by this model 0131 if (column == Collection) { 0132 if (role == Qt::DisplayRole || role == Qt::EditRole) { 0133 if (item.storageCollectionId() >= 0) { 0134 return fullCollectionPath(item.storageCollectionId()); 0135 } 0136 return fullCollectionPath(item.parentCollection().id()); 0137 } 0138 return {}; 0139 } else { 0140 // Delegate the remaining columns to the MessageModel 0141 return Akonadi::MessageModel::entityData(item, column - 1, role); 0142 } 0143 } 0144 0145 QVariant KMSearchMessageModel::entityHeaderData(int section, Qt::Orientation orientation, int role, HeaderGroup headerGroup) const 0146 { 0147 if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == Collection) { 0148 return i18nc("@title:column, folder (e.g. email)", "Folder"); 0149 } 0150 return Akonadi::MessageModel::entityHeaderData((section - 1), orientation, role, headerGroup); 0151 } 0152 0153 #include "moc_kmsearchmessagemodel.cpp"