On Freitag, 5. Oktober 2012 00:39:26 CEST Jan Kundrát wrote:

> Let's use the multiple widgets approach at first to see how that works.
Not if you'd in general prefer the container model - adding interim stuff ends 
up in bit rot and makes gittannoyance when having to be reverted out of 
follow-up patches.

Please state whether this is for technical (strict MVC) or visual reasons.
In the latter case, it's also possible to have the splitter appear like a giant 
itemview (with separate scrollers and custom headers) - no problem.

In the meantime, let's test trojitás attachement abilities.
Attached are two small patches to
a) markup plain text messages (*bold*, /italic/, _underline_ and http://url a 
href support)
b) replytext extension (marks the quote by "> " and prepends a header)

> made them only today), so you'll likely have to rebase.
yes, but was ok since i now can am -3 ;-)

Cheers,
Thomas
From 55318714fe1758fffb26d9b87853f58d4e1d362a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20L=C3=BCbking?= <[email protected]>
Date: Thu, 4 Oct 2012 21:05:21 +0200
Subject: [PATCH 1/4] add plaintext markup

---
 src/Gui/SimplePartWidget.cpp | 26 ++++++++++++++++++++++++++
 src/Gui/SimplePartWidget.h   |  1 +
 2 Dateien geändert, 27 Zeilen hinzugefügt(+)

diff --git a/src/Gui/SimplePartWidget.cpp b/src/Gui/SimplePartWidget.cpp
index 79904fc..79dae96 100644
--- a/src/Gui/SimplePartWidget.cpp
+++ b/src/Gui/SimplePartWidget.cpp
@@ -39,6 +39,8 @@ SimplePartWidget::SimplePartWidget(QWidget *parent, Imap::Network::MsgPartNetAcc
     url.setScheme(QLatin1String("trojita-imap"));
     url.setHost(QLatin1String("msg"));
     url.setPath(partIndex.data(Imap::Mailbox::RolePartPathToPart).toString());
+    if (partIndex.data(Imap::Mailbox::RolePartMimeType).toString() == "text/plain")
+        connect(this, SIGNAL(loadFinished(bool)), this, SLOT(slotMarkupPlainText()));
     load(url);
 
     fileDownloadManager = new Imap::Network::FileDownloadManager(this, manager, partIndex);
@@ -51,6 +53,30 @@ SimplePartWidget::SimplePartWidget(QWidget *parent, Imap::Network::MsgPartNetAcc
     setContextMenuPolicy(Qt::ActionsContextMenu);
 }
 
+void SimplePartWidget::slotMarkupPlainText() {
+    // NOTICE "single shot", we get a recursion otherwise!
+    disconnect(this, SIGNAL(loadFinished(bool)), this, SLOT(slotMarkupPlainText()));
+
+    static const QRegExp link("(https*://[;/?:@=&$\\-_.+!'(),0-9a-zA-Z%#]*)");
+    static const QRegExp mail("([a-zA-Z0-9\\.\\-_]*@[a-zA-Z0-9\\.\\-_]*)");
+    static QString intro("([\\s\\(\\[\\{])");
+    static QString extro("([\\s\\),;.\\]\\}])");
+    static const QRegExp bold(intro + "\\*(\\S*)\\*" + extro);
+    static const QRegExp italic(intro + "/(\\S*)/" + extro);
+    static const QRegExp underline(intro + "_(\\S*)_" + extro);
+    QString content = page()->mainFrame()->toHtml();
+    content.replace("&gt;", "§gt;");
+    content.replace("&lt;", "§lt;");
+    content.replace(link, "<a href=\"\\1\">\\1</a>");
+    content.replace(mail, "<a href=\"mailto:\\1\">\\1</a>");
+    content.replace("§gt;", "&gt;");
+    content.replace("§lt;", "&lt;");
+    content.replace(bold, "\\1<b>\\2</b>\\3");
+    content.replace(italic, "\\1<i>\\2</i>\\3");
+    content.replace(underline, "\\1<u>\\2</u>\\3");
+    page()->mainFrame()->setHtml(content);
+}
+
 void SimplePartWidget::slotFileNameRequested(QString *fileName)
 {
     *fileName = QFileDialog::getSaveFileName(this, tr("Save Attachment"),
diff --git a/src/Gui/SimplePartWidget.h b/src/Gui/SimplePartWidget.h
index d57bb87..07723cf 100644
--- a/src/Gui/SimplePartWidget.h
+++ b/src/Gui/SimplePartWidget.h
@@ -57,6 +57,7 @@ public:
 private slots:
     void slotTransferError(const QString &errorString);
     void slotFileNameRequested(QString *fileName);
+    void slotMarkupPlainText();
 private:
     QAction *saveAction;
     Imap::Network::FileDownloadManager *fileDownloadManager;
-- 
1.7.12.1

From f6b6bd045e216c2890f219eef9a7aa373f23ee81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20L=C3=BCbking?= <[email protected]>
Date: Fri, 5 Oct 2012 21:53:41 +0200
Subject: [PATCH 2/4] add reply header and '>' quote marks on reply

---
 src/Gui/MessageView.cpp | 66 +++++++++++++++++++++++++++++--------------------
 src/Gui/MessageView.h   |  5 ++++
 2 Dateien geändert, 44 Zeilen hinzugefügt(+), 27 Zeilen entfernt(-)

diff --git a/src/Gui/MessageView.cpp b/src/Gui/MessageView.cpp
index 1e4acb1..22a8c7e 100644
--- a/src/Gui/MessageView.cpp
+++ b/src/Gui/MessageView.cpp
@@ -269,39 +269,55 @@ 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();
 
-    // 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()));
-    const Imap::Message::Envelope &envelope = messagePtr->envelope(model);
+    const Imap::Message::Envelope &e = envelope();
 
     QString res;
-    if (!envelope.from.isEmpty())
-        res += tr("<b>From:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.from, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!envelope.to.isEmpty())
-        res += tr("<b>To:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.to, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!envelope.cc.isEmpty())
-        res += tr("<b>Cc:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.cc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
-    if (!envelope.bcc.isEmpty())
-        res += tr("<b>Bcc:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.bcc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.from.isEmpty())
+        res += tr("<b>From:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(e.from, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.to.isEmpty())
+        res += tr("<b>To:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(e.to, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.cc.isEmpty())
+        res += tr("<b>Cc:</b>&nbsp;%1<br/>").arg(Imap::Message::MailAddress::prettyList(e.cc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+    if (!e.bcc.isEmpty())
+        res += tr("<b>Bcc:</b>&nbsp;%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>&nbsp;%1").arg(Qt::escape(envelope.subject));
+    res += tr("<b>Subject:</b>&nbsp;%1").arg(Qt::escape(e.subject));
 #else
-    res += tr("<b>Subject:</b>&nbsp;%1").arg(envelope.subject.toHtmlEscaped());
+    res += tr("<b>Subject:</b>&nbsp;%1").arg(e.subject.toHtmlEscaped());
 #endif
-    if (envelope.date.isValid())
-        res += tr("<br/><b>Date:</b>&nbsp;%1").arg(envelope.date.toLocalTime().toString(Qt::SystemLocaleLongDate));
+    if (e.date.isValid())
+        res += tr("<br/><b>Date:</b>&nbsp;%1").arg(e.date.toLocalTime().toString(Qt::SystemLocaleLongDate));
     return res;
 }
 
 QString MessageView::quoteText() const
 {
-    const AbstractPartWidget *w = dynamic_cast<const AbstractPartWidget *>(viewer);
-    return w ? w->quoteMe() : QString();
+    if (const AbstractPartWidget *w = dynamic_cast<const AbstractPartWidget *>(viewer)) {
+        QString quote = w->quoteMe();
+        quote.replace('\n', "\n> ");
+        const Imap::Message::Envelope &e = envelope();
+        QString sender;
+        if (!e.from.isEmpty())
+            sender = e.from.at(0).name;
+        if (e.from.isEmpty())
+            sender = tr("you");
+        quote.prepend(tr("On %1 %2 wrote:\n\n").arg(e.date.toLocalTime().toString(Qt::SystemLocaleLongDate)).arg(sender));
+        return quote;
+    }
+    return QString();
 }
 
 void MessageView::reply(MainWindow *mainWindow, ReplyMode mode)
@@ -309,25 +325,21 @@ void MessageView::reply(MainWindow *mainWindow, ReplyMode mode)
     if (!message.isValid())
         return;
 
-    // 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()));
-    const Imap::Message::Envelope &envelope = messagePtr->envelope(model);
-    // ...now imagine how that would look like on just a single line :)
+    const Imap::Message::Envelope &e = envelope();
 
     QList<QPair<Imap::Mailbox::MessageComposer::RecipientKind,QString> > recipients;
-    for (QList<Imap::Message::MailAddress>::const_iterator it = envelope.from.begin(); it != envelope.from.end(); ++it) {
+    for (QList<Imap::Message::MailAddress>::const_iterator it = e.from.begin(); it != e.from.end(); ++it) {
         recipients << qMakePair(Imap::Mailbox::MessageComposer::Recipient_To, QString::fromUtf8("%1@%2").arg(it->mailbox, it->host));
     }
     if (mode == REPLY_ALL) {
-        for (QList<Imap::Message::MailAddress>::const_iterator it = envelope.to.begin(); it != envelope.to.end(); ++it) {
+        for (QList<Imap::Message::MailAddress>::const_iterator it = e.to.begin(); it != e.to.end(); ++it) {
             recipients << qMakePair(Imap::Mailbox::MessageComposer::Recipient_Cc, QString::fromUtf8("%1@%2").arg(it->mailbox, it->host));
         }
-        for (QList<Imap::Message::MailAddress>::const_iterator it = envelope.cc.begin(); it != envelope.cc.end(); ++it) {
+        for (QList<Imap::Message::MailAddress>::const_iterator it = e.cc.begin(); it != e.cc.end(); ++it) {
             recipients << qMakePair(Imap::Mailbox::MessageComposer::Recipient_To, QString::fromUtf8("%1@%2").arg(it->mailbox, it->host));
         }
     }
-    mainWindow->invokeComposeDialog(replySubject(envelope.subject), quoteText(), recipients, envelope.messageId);
+    mainWindow->invokeComposeDialog(replySubject(e.subject), quoteText(), recipients, e.messageId);
 }
 
 QString MessageView::replySubject(const QString &subject)
diff --git a/src/Gui/MessageView.h b/src/Gui/MessageView.h
index 526673c..72c2643 100644
--- a/src/Gui/MessageView.h
+++ b/src/Gui/MessageView.h
@@ -37,6 +37,10 @@ namespace Network
 {
 class MsgPartNetAccessManager;
 }
+namespace Message
+{
+class Envelope;
+}
 }
 
 namespace Gui
@@ -82,6 +86,7 @@ signals:
     void messageChanged();
 private:
     bool eventFilter(QObject *object, QEvent *event);
+    Imap::Message::Envelope envelope() const;
     QString headerText();
     QString quoteText() const;
     static QString replySubject(const QString &subject);
-- 
1.7.12.1

Reply via email to