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;");
+ content.replace("<", "§lt;");
+ content.replace(link, "<a href=\"\\1\">\\1</a>");
+ content.replace(mail, "<a href=\"mailto:\\1\">\\1</a>");
+ content.replace("§gt;", ">");
+ content.replace("§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> %1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.from, Imap::Message::MailAddress::FORMAT_CLICKABLE));
- if (!envelope.to.isEmpty())
- res += tr("<b>To:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.to, Imap::Message::MailAddress::FORMAT_CLICKABLE));
- if (!envelope.cc.isEmpty())
- res += tr("<b>Cc:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.cc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
- if (!envelope.bcc.isEmpty())
- res += tr("<b>Bcc:</b> %1<br/>").arg(Imap::Message::MailAddress::prettyList(envelope.bcc, Imap::Message::MailAddress::FORMAT_CLICKABLE));
+ 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.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(envelope.subject));
+ res += tr("<b>Subject:</b> %1").arg(Qt::escape(e.subject));
#else
- res += tr("<b>Subject:</b> %1").arg(envelope.subject.toHtmlEscaped());
+ res += tr("<b>Subject:</b> %1").arg(e.subject.toHtmlEscaped());
#endif
- if (envelope.date.isValid())
- res += tr("<br/><b>Date:</b> %1").arg(envelope.date.toLocalTime().toString(Qt::SystemLocaleLongDate));
+ if (e.date.isValid())
+ res += tr("<br/><b>Date:</b> %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