File indexing completed on 2024-11-24 04:53:00

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 #include "EnvelopeView.h"
0023 #include <QFontMetrics>
0024 #include <QLabel>
0025 #include <QUrlQuery>
0026 #include <QGridLayout>
0027 #include <QLayoutItem>
0028 #include <QVBoxLayout>
0029 #include "Gui/AddressRowWidget.h"
0030 #include "Gui/MessageView.h"
0031 #include "Gui/Util.h"
0032 #include "Imap/Model/ItemRoles.h"
0033 #include "Imap/Model/MailboxTree.h"
0034 #include "Imap/Model/Model.h"
0035 #include "UiUtils/Formatting.h"
0036 
0037 namespace Gui {
0038 
0039 EnvelopeView::EnvelopeView(QWidget *parent, MessageView *messageView): QWidget(parent), m_messageView(messageView)
0040 {
0041     QVBoxLayout *lay = new QVBoxLayout(this);
0042     lay->setContentsMargins(0, 0, 0, 0);
0043     setLayout(lay);
0044 
0045 }
0046 
0047 #define SET_LABEL_OPTIONS(LBL) \
0048 { \
0049     LBL->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); \
0050     LBL->setWordWrap(true); \
0051     LBL->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); \
0052 }
0053 
0054 #define ADD_ROW(LBL, WDG) \
0055 { \
0056     QLabel *l = new QLabel(LBL, this); \
0057     l->setAlignment(Qt::AlignRight); \
0058     form->addWidget(l, form->rowCount(), 0, Qt::AlignTop); \
0059     form->addWidget(WDG, form->rowCount()-1, 1, Qt::AlignTop); \
0060 }
0061 
0062 /** @short */
0063 void EnvelopeView::setMessage(const QModelIndex &index)
0064 {
0065     while (QLayoutItem *item = layout()->takeAt(0)) {
0066         if (item->widget()) {
0067             item->widget()->deleteLater();
0068         } else if (item->layout()) {
0069             item->layout()->deleteLater();
0070         } else {
0071             delete item;
0072         }
0073     }
0074     Q_FOREACH(QWidget *w, findChildren<QWidget*>()) {
0075         w->deleteLater();
0076     }
0077 
0078     if (!index.isValid()) {
0079         return;
0080     }
0081 
0082     const Imap::Message::Envelope e = index.data(Imap::Mailbox::RoleMessageEnvelope).value<Imap::Message::Envelope>();
0083 
0084     // Subject & date
0085     QString subDate;
0086     // Date
0087     if (e.date.isValid()) {
0088         subDate = QStringLiteral("<table style=\"margin:0px; margin-left:4em; float:right;\"><tr style=\"margin:0px;\"><td style=\"margin:0px;\">%1</td></tr></table>")
0089                       .arg(QLocale::system().toString(e.date.toLocalTime(), QLocale::LongFormat));
0090     }
0091     subDate += QStringLiteral("<span style=\"font:bold large;\">%1</span>").arg(e.subject.toHtmlEscaped());
0092     auto lbl = new QLabel(subDate, this);
0093     SET_LABEL_OPTIONS(lbl)
0094     layout()->addWidget(lbl);
0095 
0096     QGridLayout *form = new QGridLayout();
0097     form->setSpacing(0);
0098     form->setContentsMargins(0, 0, 0, 0);
0099     static_cast<QBoxLayout*>(layout())->addLayout(form);
0100 
0101     // Sender
0102     AddressRowWidget *senderWidget = 0;
0103     QString senderLabel;
0104     if (!e.from.isEmpty()) {
0105         senderLabel = tr("From");
0106         senderWidget = new AddressRowWidget(this, QString(), e.from, m_messageView);
0107     }
0108     if (!e.sender.isEmpty() && e.sender != e.from) {
0109         if (senderWidget) {
0110             senderWidget->addAddresses(QStringLiteral(" %1").arg(tr("sent via")), e.sender, m_messageView);
0111         } else {
0112             senderLabel = tr("Sender");
0113             senderWidget = new AddressRowWidget(this, QString(), e.sender, m_messageView);
0114         }
0115     }
0116     if (!e.replyTo.isEmpty() && e.replyTo != e.from) {
0117         if (senderWidget) {
0118             senderWidget->addAddresses(QStringLiteral(", %1").arg(tr("replies to")), e.replyTo, m_messageView);
0119         } else {
0120             senderLabel = tr("Reply-To");
0121             senderWidget = new AddressRowWidget(this, QString(), e.replyTo, m_messageView);
0122         }
0123     }
0124     if (senderWidget)
0125         ADD_ROW(senderLabel, senderWidget)
0126 
0127     // Receiver
0128     AddressRowWidget *receiverWidget = 0;
0129     QString receiverLabel;
0130     if (!e.to.isEmpty()) {
0131         receiverLabel = tr("To");
0132         receiverWidget = new AddressRowWidget(this, QString(), e.to, m_messageView);
0133     }
0134     if (!e.cc.isEmpty()) {
0135         if (receiverWidget) {
0136             receiverWidget->addAddresses(QStringLiteral(" %1").arg(tr("Cc'd to")), e.cc, m_messageView);
0137         } else {
0138             receiverLabel = tr("Cc");
0139             receiverWidget = new AddressRowWidget(this, QString(), e.cc, m_messageView);
0140         }
0141     }
0142     if (!e.bcc.isEmpty()) {
0143         if (receiverWidget) {
0144             receiverWidget->addAddresses(QStringLiteral(" %1").arg(tr("Bcc'd to")), e.bcc, m_messageView);
0145         } else {
0146             receiverLabel = tr("Bcc");
0147             receiverWidget = new AddressRowWidget(this, QString(), e.bcc, m_messageView);
0148         }
0149     }
0150     if (receiverWidget)
0151         ADD_ROW(receiverLabel, receiverWidget)
0152 
0153     // Mailing list
0154     QVariantList headerListPost = index.data(Imap::Mailbox::RoleMessageHeaderListPost).toList();
0155     if (!headerListPost.isEmpty()) {
0156         QStringList buf;
0157         bool elided = false;
0158         Q_FOREACH(const QVariant &item, headerListPost) {
0159             const QString scheme = item.toUrl().scheme().toLower();
0160             const bool isMailTo = scheme == QLatin1String("mailto");
0161             if (isMailTo || scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
0162                 QString target = item.toUrl().toString();
0163                 // eg. github uses reply+<some hash>@reply.github.com
0164                 QString caption = isMailTo ? item.toUrl().toString(QUrl::RemoveScheme) : target;
0165                 elided = elided || UiUtils::elideAddress(caption);
0166                 target = target.toHtmlEscaped();
0167                 buf << tr("<a href=\"%1\">%2</a>").arg(target, caption.toHtmlEscaped());
0168             } else {
0169                 buf << item.toUrl().toString().toHtmlEscaped();
0170             }
0171         }
0172         auto lbl = new QLabel(QString(QLatin1String("<html>&nbsp;%1</html>")).arg(buf.join(tr(", "))));
0173         SET_LABEL_OPTIONS(lbl)
0174         lbl->setOpenExternalLinks(true);
0175         if (elided)
0176             connect(lbl, &QLabel::linkHovered, lbl, &QLabel::setToolTip);
0177         ADD_ROW(tr("Mailing List"), lbl)
0178     }
0179 
0180     // separating the message
0181     QFrame *line = new QFrame(this);
0182     line->setFrameStyle(QFrame::HLine|QFrame::Plain);
0183     layout()->addWidget(line);
0184 }
0185 
0186 
0187 }