[kde-doc-english] [trojita] src/Gui: GUI: refactor the message envelope widget into a standalone class

Jan Kundrát jkt at flaska.net
Fri May 3 14:08:13 UTC 2013


Git commit 4566a329aeb79adbcfe745c678c2dbdb16499754 by Jan Kundrát.
Committed on 03/05/2013 at 15:30.
Pushed by jkt into branch 'master'.

GUI: refactor the message envelope widget into a standalone class

A  +139  -0    src/Gui/EnvelopeView.cpp     [License: GPL (v2/3)]
A  +51   -0    src/Gui/EnvelopeView.h     [License: GPL (v2/3)]
M  +4    -2    src/Gui/Gui.pro
M  +7    -108  src/Gui/MessageView.cpp
M  +2    -3    src/Gui/MessageView.h

http://commits.kde.org/trojita/4566a329aeb79adbcfe745c678c2dbdb16499754

diff --git a/src/Gui/EnvelopeView.cpp b/src/Gui/EnvelopeView.cpp
new file mode 100644
index 0000000..4322deb
--- /dev/null
+++ b/src/Gui/EnvelopeView.cpp
@@ -0,0 +1,139 @@
+/* Copyright (C) 2006 - 2013 Jan Kundrát <jkt at flaska.net>
+
+   This file is part of the Trojita Qt IMAP e-mail client,
+   http://trojita.flaska.net/
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License or (at your option) version 3 or any later version
+   accepted by the membership of KDE e.V. (or its successor approved
+   by the membership of KDE e.V.), which shall act as a proxy
+   defined in Section 14 of version 3 of the license.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "EnvelopeView.h"
+#include <QHeaderView>
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+#  include <QTextDocument>
+#else
+#  include <QUrlQuery>
+#endif
+#include "Imap/Model/ItemRoles.h"
+#include "Imap/Model/MailboxTree.h"
+#include "Imap/Model/Model.h"
+
+namespace Gui {
+
+EnvelopeView::EnvelopeView(QWidget *parent): QLabel(parent)
+{
+    // we create a dummy header, pass it through the style and the use it's color roles so we
+    // know what headers in general look like in the system
+    QHeaderView helpingHeader(Qt::Horizontal);
+    helpingHeader.ensurePolished();
+
+    setBackgroundRole(helpingHeader.backgroundRole());
+    setForegroundRole(helpingHeader.foregroundRole());
+    setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
+    setIndent(5);
+    setWordWrap(true);
+    connect(this, SIGNAL(linkHovered(QString)), this, SLOT(onLinkHovered(QString)));
+}
+
+/** @short */
+void EnvelopeView::setMessage(const QModelIndex &index)
+{
+    setText(headerText(index));
+}
+
+QString EnvelopeView::headerText(const QModelIndex &index)
+{
+    if (!index.isValid())
+        return QString();
+
+    const Imap::Message::Envelope e = index.data(Imap::Mailbox::RoleMessageEnvelope).value<Imap::Message::Envelope>();
+
+    QString res;
+    if (!e.from.isEmpty())
+        res += tr("<b>From:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.from, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.sender.isEmpty() && e.sender != e.from)
+        res += tr("<b>Sender:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.sender, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.replyTo.isEmpty() && e.replyTo != e.from)
+        res += tr("<b>Reply-To:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.replyTo, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    QVariantList headerListPost = index.data(Imap::Mailbox::RoleMessageHeaderListPost).toList();
+    if (!headerListPost.isEmpty()) {
+        QStringList buf;
+        Q_FOREACH(const QVariant &item, headerListPost) {
+            const QString scheme = item.toUrl().scheme().toLower();
+            if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme == QLatin1String("mailto")) {
+                QString target = item.toUrl().toString();
+                QString caption = item.toUrl().toString(scheme == QLatin1String("mailto") ? QUrl::RemoveScheme : QUrl::None);
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+                target = Qt::escape(target);
+                caption = Qt::escape(caption);
+#else
+                target = target.toHtmlEscaped();
+                caption = caption.toHtmlEscaped();
+#endif
+                buf << tr("<a href=\"%1\">%2</a>").arg(target, caption);
+            } else {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+                buf << Qt::escape(item.toUrl().toString());
+#else
+                buf << item.toUrl().toString().toHtmlEscaped();
+#endif
+            }
+        }
+        res += tr("<b>List-Post:</b> %1<br/>").arg(buf.join(tr(", ")));
+    }
+    if (!e.to.isEmpty())
+        res += tr("<b>To:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.to, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.cc.isEmpty())
+        res += tr("<b>Cc:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.cc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.bcc.isEmpty())
+        res += tr("<b>Bcc:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.bcc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    res += tr("<b>Subject:</b> %1").arg(Qt::escape(e.subject));
+#else
+    res += tr("<b>Subject:</b> %1").arg(e.subject.toHtmlEscaped());
+#endif
+    if (e.date.isValid())
+        res += tr("<br/><b>Date:</b> %1").arg(e.date.toLocalTime().toString(Qt::SystemLocaleLongDate));
+    return res;
+}
+
+void EnvelopeView::onLinkHovered(const QString &target)
+{
+    QUrl url(target);
+
+    if (target.isEmpty() || url.scheme().toLower() != QLatin1String("mailto")) {
+        setToolTip(QString());
+        return;
+    }
+
+    QString frontOfAtSign, afterAtSign;
+    if (url.path().indexOf(QLatin1String("@")) != -1) {
+        QStringList chunks = url.path().split(QLatin1String("@"));
+        frontOfAtSign = chunks[0];
+        afterAtSign = QStringList(chunks.mid(1)).join(QLatin1String("@"));
+    }
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    Imap::Message::MailAddress addr(url.queryItemValue(QLatin1String("X-Trojita-DisplayName")), QString(),
+                                    frontOfAtSign, afterAtSign);
+    setToolTip(Qt::escape(addr.prettyName(Imap::Message::MailAddress::FORMAT_READABLE)));
+#else
+    QUrlQuery q(url);
+    Imap::Message::MailAddress addr(q.queryItemValue(QLatin1String("X-Trojita-DisplayName")), QString(),
+                                    frontOfAtSign, afterAtSign);
+    setToolTip(addr.prettyName(Imap::Message::MailAddress::FORMAT_READABLE).toHtmlEscaped());
+#endif
+}
+
+}
diff --git a/src/Gui/EnvelopeView.h b/src/Gui/EnvelopeView.h
new file mode 100644
index 0000000..699825b
--- /dev/null
+++ b/src/Gui/EnvelopeView.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2006 - 2013 Jan Kundrát <jkt at flaska.net>
+
+   This file is part of the Trojita Qt IMAP e-mail client,
+   http://trojita.flaska.net/
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License or (at your option) version 3 or any later version
+   accepted by the membership of KDE e.V. (or its successor approved
+   by the membership of KDE e.V.), which shall act as a proxy
+   defined in Section 14 of version 3 of the license.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef GUI_ENVELOPEVIEW_H
+#define GUI_ENVELOPEVIEW_H
+
+#include <QModelIndex>
+#include <QLabel>
+
+namespace Gui {
+
+/** @short Widget displaying the message envelope */
+class EnvelopeView : public QLabel
+{
+    Q_OBJECT
+public:
+    explicit EnvelopeView(QWidget *parent=0);
+
+    void setMessage(const QModelIndex &index);
+
+private slots:
+    void onLinkHovered(const QString &target);
+
+private:
+    QString headerText(const QModelIndex &index);
+
+    EnvelopeView(const EnvelopeView &); // don't implement
+    EnvelopeView &operator=(const EnvelopeView &); // don't implement
+};
+
+}
+
+#endif // GUI_ENVELOPEVIEW_H
diff --git a/src/Gui/Gui.pro b/src/Gui/Gui.pro
index 25c01b3..2cb70b9 100644
--- a/src/Gui/Gui.pro
+++ b/src/Gui/Gui.pro
@@ -57,7 +57,8 @@ SOURCES += \
     LineEdit.cpp \
     PasswordDialog.cpp \
     ProgressPopUp.cpp \
-    OverlayWidget.cpp
+    OverlayWidget.cpp \
+    EnvelopeView.cpp
 HEADERS += \
     ../Imap/Model/ModelTest/modeltest.h \
     ComposeWidget.h \
@@ -100,7 +101,8 @@ HEADERS += \
     LineEdit.h \
     PasswordDialog.h \
     ProgressPopUp.h \
-    OverlayWidget.h
+    OverlayWidget.h \
+    EnvelopeView.h
 FORMS += CreateMailboxDialog.ui \
     ComposeWidget.ui \
     SettingsImapPage.ui \
diff --git a/src/Gui/MessageView.cpp b/src/Gui/MessageView.cpp
index d6fa19d..08f89dc 100644
--- a/src/Gui/MessageView.cpp
+++ b/src/Gui/MessageView.cpp
@@ -23,15 +23,10 @@
 #include <QDesktopServices>
 #include <QHeaderView>
 #include <QKeyEvent>
-#include <QLabel>
 #include <QMenu>
 #include <QMessageBox>
-#include <QTextDocument>
 #include <QTimer>
 #include <QUrl>
-#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
-#include <QUrlQuery>
-#endif
 #include <QVBoxLayout>
 #include <QWebFrame>
 #include <QWebHistory>
@@ -42,6 +37,7 @@
 #include "AbstractPartWidget.h"
 #include "Composer/SubjectMangling.h"
 #include "EmbeddedWebView.h"
+#include "EnvelopeView.h"
 #include "ExternalElementsWidget.h"
 #include "PartWidgetFactory.h"
 #include "SimplePartWidget.h"
@@ -93,14 +89,8 @@ MessageView::MessageView(QWidget *parent): QWidget(parent)
     headerSection->setAutoFillBackground(true);
 
     // the actual mail header
-    header = new QLabel(headerSection);
-    header->setBackgroundRole(helpingHeader.backgroundRole());
-    header->setForegroundRole(helpingHeader.foregroundRole());
-    header->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
-    header->setIndent(5);
-    header->setWordWrap(true);
-    connect(header, SIGNAL(linkHovered(QString)), this, SLOT(linkInTitleHovered(QString)));
-    connect(header, SIGNAL(linkActivated(QString)), this, SLOT(headerLinkActivated(QString)));
+    m_envelope = new EnvelopeView(headerSection);
+    connect(m_envelope, SIGNAL(linkActivated(QString)), this, SLOT(headerLinkActivated(QString)));
 
     // the tag bar
     tags = new TagListWidget(headerSection);
@@ -117,7 +107,7 @@ MessageView::MessageView(QWidget *parent): QWidget(parent)
 
     // layout the header
     layout = new QVBoxLayout(headerSection);
-    layout->addWidget(header, 1);
+    layout->addWidget(m_envelope, 1);
     layout->addWidget(tags, 3);
     layout->addWidget(externalElements, 1);
 
@@ -170,7 +160,7 @@ MessageView::~MessageView()
 void MessageView::setEmpty()
 {
     markAsReadTimer->stop();
-    header->setText(QString());
+    m_envelope->setMessage(QModelIndex());
     headerSection->hide();
     message = QModelIndex();
     disconnect(this, SLOT(handleDataChanged(QModelIndex,QModelIndex)));
@@ -229,7 +219,7 @@ void MessageView::setMessage(const QModelIndex &index)
         viewer->setParent(this);
         layout->addWidget(viewer);
         viewer->show();
-        header->setText(headerText());
+        m_envelope->setMessage(message);
 
         tags->show();
         tags->setTagList(messageIndex.data(Imap::Mailbox::RoleMessageFlags).toStringList());
@@ -289,70 +279,6 @@ bool MessageView::eventFilter(QObject *object, QEvent *event)
     }
 }
 
-Imap::Message::Envelope MessageView::envelope() const
-{
-    // Accessing the envelope via QVariant is just too much work here; it's way easier to just get the raw pointer
-    Imap::Mailbox::Model *model = dynamic_cast<Imap::Mailbox::Model *>(const_cast<QAbstractItemModel *>(message.model()));
-    Imap::Mailbox::TreeItemMessage *messagePtr = dynamic_cast<Imap::Mailbox::TreeItemMessage *>(static_cast<Imap::Mailbox::TreeItem *>(message.internalPointer()));
-    return messagePtr->envelope(model);
-}
-
-QString MessageView::headerText()
-{
-    if (!message.isValid())
-        return QString();
-
-    const Imap::Message::Envelope &e = envelope();
-
-    QString res;
-    if (!e.from.isEmpty())
-        res += tr("<b>From:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.from, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!e.sender.isEmpty() && e.sender != e.from)
-        res += tr("<b>Sender:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.sender, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!e.replyTo.isEmpty() && e.replyTo != e.from)
-        res += tr("<b>Reply-To:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.replyTo, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    QVariantList headerListPost = message.data(Imap::Mailbox::RoleMessageHeaderListPost).toList();
-    if (!headerListPost.isEmpty()) {
-        QStringList buf;
-        Q_FOREACH(const QVariant &item, headerListPost) {
-            const QString scheme = item.toUrl().scheme().toLower();
-            if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme == QLatin1String("mailto")) {
-                QString target = item.toUrl().toString();
-                QString caption = item.toUrl().toString(scheme == QLatin1String("mailto") ? QUrl::RemoveScheme : QUrl::None);
-#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
-                target = Qt::escape(target);
-                caption = Qt::escape(caption);
-#else
-                target = target.toHtmlEscaped();
-                caption = caption.toHtmlEscaped();
-#endif
-                buf << tr("<a href=\"%1\">%2</a>").arg(target, caption);
-            } else {
-#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
-                buf << Qt::escape(item.toUrl().toString());
-#else
-                buf << item.toUrl().toString().toHtmlEscaped();
-#endif
-            }
-        }
-        res += tr("<b>List-Post:</b> %1<br/>").arg(buf.join(tr(", ")));
-    }
-    if (!e.to.isEmpty())
-        res += tr("<b>To:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.to, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!e.cc.isEmpty())
-        res += tr("<b>Cc:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.cc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!e.bcc.isEmpty())
-        res += tr("<b>Bcc:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(e.bcc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
-    res += tr("<b>Subject:</b> %1").arg(Qt::escape(e.subject));
-#else
-    res += tr("<b>Subject:</b> %1").arg(e.subject.toHtmlEscaped());
-#endif
-    if (e.date.isValid())
-        res += tr("<br/><b>Date:</b> %1").arg(e.date.toLocalTime().toString(Qt::SystemLocaleLongDate));
-    return res;
-}
-
 QString MessageView::quoteText() const
 {
     if (const AbstractPartWidget *w = dynamic_cast<const AbstractPartWidget *>(viewer)) {
@@ -408,7 +334,7 @@ QString MessageView::quoteText() const
             }
             quote << quotemarks + line->mid(lastSpace);
         }
-        const Imap::Message::Envelope &e = envelope();
+        const Imap::Message::Envelope &e = message.data(Imap::Mailbox::RoleMessageEnvelope).value<Imap::Message::Envelope>();
         QString sender;
         if (!e.from.isEmpty())
             sender = e.from[0].prettyName(Imap::Message::MailAddress::FORMAT_JUST_NAME);
@@ -476,33 +402,6 @@ void MessageView::externalsEnabled()
         w->reloadContents();
 }
 
-void MessageView::linkInTitleHovered(const QString &target)
-{
-    QUrl url(target);
-
-    if (target.isEmpty() || url.scheme().toLower() != QLatin1String("mailto")) {
-        header->setToolTip(QString());
-        return;
-    }
-
-    QString frontOfAtSign, afterAtSign;
-    if (url.path().indexOf(QLatin1String("@")) != -1) {
-        QStringList chunks = url.path().split(QLatin1String("@"));
-        frontOfAtSign = chunks[0];
-        afterAtSign = QStringList(chunks.mid(1)).join(QLatin1String("@"));
-    }
-#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
-    Imap::Message::MailAddress addr(url.queryItemValue(QLatin1String("X-Trojita-DisplayName")), QString(),
-                                    frontOfAtSign, afterAtSign);
-    header->setToolTip(Qt::escape(addr.prettyName(Imap::Message::MailAddress::FORMAT_READABLE)));
-#else
-    QUrlQuery q(url);
-    Imap::Message::MailAddress addr(q.queryItemValue(QLatin1String("X-Trojita-DisplayName")), QString(),
-                                    frontOfAtSign, afterAtSign);
-    header->setToolTip(addr.prettyName(Imap::Message::MailAddress::FORMAT_READABLE).toHtmlEscaped());
-#endif
-}
-
 void MessageView::newLabelAction(const QString &tag)
 {
     if (!message.isValid())
diff --git a/src/Gui/MessageView.h b/src/Gui/MessageView.h
index 41dcf15..bdbad36 100644
--- a/src/Gui/MessageView.h
+++ b/src/Gui/MessageView.h
@@ -48,6 +48,7 @@ class Envelope;
 namespace Gui
 {
 
+class EnvelopeView;
 class MainWindow;
 class PartWidgetFactory;
 class ExternalElementsWidget;
@@ -78,7 +79,6 @@ private slots:
     void markAsRead();
     void externalsRequested(const QUrl &url);
     void externalsEnabled();
-    void linkInTitleHovered(const QString &target);
     void newLabelAction(const QString &tag);
     void deleteLabelAction(const QString &tag);
     void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
@@ -93,12 +93,11 @@ signals:
 private:
     bool eventFilter(QObject *object, QEvent *event);
     Imap::Message::Envelope envelope() const;
-    QString headerText();
     QString quoteText() const;
 
     QWidget *viewer;
     QWidget *headerSection;
-    QLabel *header;
+    EnvelopeView *m_envelope;
     ExternalElementsWidget *externalElements;
     QBoxLayout *layout;
     TagListWidget *tags;



More information about the kde-doc-english mailing list