summaryrefslogtreecommitdiffstats
path: root/framework/domain
diff options
context:
space:
mode:
Diffstat (limited to 'framework/domain')
-rw-r--r--framework/domain/CMakeLists.txt32
-rw-r--r--framework/domain/actions/mailactions.cpp48
-rw-r--r--framework/domain/actions/sinkactions.cpp106
-rw-r--r--framework/domain/composer.cpp199
-rw-r--r--framework/domain/composer.h93
-rw-r--r--framework/domain/csshelper.cpp64
-rw-r--r--framework/domain/csshelper.h44
-rw-r--r--framework/domain/data/mail.css298
-rw-r--r--framework/domain/folderlistcontroller.cpp69
-rw-r--r--framework/domain/folderlistcontroller.h56
-rw-r--r--framework/domain/folderlistmodel.cpp65
-rw-r--r--framework/domain/folderlistmodel.h50
-rw-r--r--framework/domain/maillistcontroller.cpp101
-rw-r--r--framework/domain/maillistcontroller.h61
-rw-r--r--framework/domain/maillistmodel.cpp149
-rw-r--r--framework/domain/maillistmodel.h66
-rw-r--r--framework/domain/mailplugin.cpp40
-rw-r--r--framework/domain/mailplugin.h33
-rw-r--r--framework/domain/mailtemplates.cpp804
-rw-r--r--framework/domain/mailtemplates.h28
-rw-r--r--framework/domain/mailtransport.cpp160
-rw-r--r--framework/domain/mailtransport.h28
-rw-r--r--framework/domain/messageparser.cpp76
-rw-r--r--framework/domain/messageparser.h51
-rw-r--r--framework/domain/objecttreesource.cpp144
-rw-r--r--framework/domain/objecttreesource.h57
-rw-r--r--framework/domain/qmldir3
-rw-r--r--framework/domain/retriever.cpp55
-rw-r--r--framework/domain/retriever.h55
-rw-r--r--framework/domain/singlemailcontroller.cpp46
-rw-r--r--framework/domain/singlemailcontroller.h49
-rw-r--r--framework/domain/stringhtmlwriter.cpp145
-rw-r--r--framework/domain/stringhtmlwriter.h70
33 files changed, 3345 insertions, 0 deletions
diff --git a/framework/domain/CMakeLists.txt b/framework/domain/CMakeLists.txt
new file mode 100644
index 00000000..822b2981
--- /dev/null
+++ b/framework/domain/CMakeLists.txt
@@ -0,0 +1,32 @@
1set(mailplugin_SRCS
2 mailplugin.cpp
3 maillistcontroller.cpp
4 maillistmodel.cpp
5 singlemailcontroller.cpp
6 folderlistmodel.cpp
7 folderlistcontroller.cpp
8 actions/sinkactions.cpp
9 actions/mailactions.cpp
10 objecttreesource.cpp
11 stringhtmlwriter.cpp
12 csshelper.cpp
13 composer.cpp
14 messageparser.cpp
15 mailtransport.cpp
16 mailtemplates.cpp
17 retriever.cpp
18)
19add_definitions(-DMAIL_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data")
20
21find_package(CURL 7.20.0 REQUIRED)
22
23include_directories(${CURL_INCLUDE_DIRS})
24
25add_library(mailplugin SHARED ${mailplugin_SRCS})
26
27qt5_use_modules(mailplugin Core Quick Qml WebKitWidgets)
28
29target_link_libraries(mailplugin actionplugin settingsplugin sink KF5::Otp KF5::Codecs ${CURL_LIBRARIES})
30
31install(TARGETS mailplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kube/mail)
32install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/kube/mail)
diff --git a/framework/domain/actions/mailactions.cpp b/framework/domain/actions/mailactions.cpp
new file mode 100644
index 00000000..dab0533e
--- /dev/null
+++ b/framework/domain/actions/mailactions.cpp
@@ -0,0 +1,48 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19#include <actions/context.h>
20#include <actions/actionhandler.h>
21
22#include "../mailtransport.h"
23#include <KMime/Message>
24#include <QByteArray>
25#include <QVariant>
26#include <QDebug>
27
28using namespace Kube;
29
30static ActionHandlerHelper sendMailHandler("org.kde.kube.actions.sendmail",
31 [](Context *context) -> bool {
32 auto username = context->property("username").value<QByteArray>();
33 auto password = context->property("password").value<QByteArray>();
34 auto server = context->property("server").value<QByteArray>();
35 auto message = context->property("message").value<KMime::Message::Ptr>();
36 return !username.isEmpty() && !password.isEmpty() && !server.isEmpty() && message;
37 },
38 [](Context *context) {
39 auto username = context->property("username").value<QByteArray>();
40 auto password = context->property("password").value<QByteArray>();
41 auto server = context->property("server").value<QByteArray>();
42 //For ssl use "smtps://mainserver.example.net
43 QByteArray cacert; // = "/path/to/certificate.pem";
44 auto message = context->property("message").value<KMime::Message::Ptr>();
45 qWarning() << "Sending a mail: ";
46 MailTransport::sendMessage(message, server, username, password, cacert);
47 }
48);
diff --git a/framework/domain/actions/sinkactions.cpp b/framework/domain/actions/sinkactions.cpp
new file mode 100644
index 00000000..a19ab149
--- /dev/null
+++ b/framework/domain/actions/sinkactions.cpp
@@ -0,0 +1,106 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19#include <actions/context.h>
20#include <actions/actionhandler.h>
21
22#include <sink/store.h>
23
24using namespace Kube;
25
26static ActionHandlerHelper markAsReadHandler("org.kde.kube.actions.mark-as-read",
27 [](Context *context) -> bool {
28 return context->property("mail").isValid();
29 },
30 [](Context *context) {
31 auto mail = context->property("mail").value<Sink::ApplicationDomain::Mail::Ptr>();
32 if (!mail) {
33 qWarning() << "Failed to get the mail mail: " << context->property("mail");
34 return;
35 }
36 mail->setProperty("unread", false);
37 qDebug() << "Mark as read " << mail->identifier();
38 Sink::Store::modify(*mail).exec();
39 }
40);
41
42static ActionHandlerHelper deleteHandler("org.kde.kube.actions.delete",
43 [](Context *context) -> bool {
44 return context->property("mail").isValid();
45 },
46 [](Context *context) {
47 auto mail = context->property("mail").value<Sink::ApplicationDomain::Mail::Ptr>();
48 if (!mail) {
49 qWarning() << "Failed to get the mail mail: " << context->property("mail");
50 return;
51 }
52 mail->setProperty("unread", false);
53 qDebug() << "Remove " << mail->identifier();
54 Sink::Store::remove(*mail).exec();
55 }
56);
57
58static ActionHandlerHelper synchronizeHandler("org.kde.kube.actions.synchronize",
59 [](Context *context) -> bool {
60 return context->property("folder").isValid();
61 },
62 [](Context *context) {
63 auto folder = context->property("folder").value<Sink::ApplicationDomain::Folder::Ptr>();
64 if (!folder) {
65 qWarning() << "Failed to get the folder: " << context->property("folder");
66 return;
67 }
68 Sink::Store::synchronize(Sink::Query::ResourceFilter(folder->resourceInstanceIdentifier())).exec();
69 }
70);
71
72// static ActionHandlerHelper saveAsDraft("org.kde.kube.actions.save-as-draft",
73// [](Context *context) -> bool {
74// return context->property("mail").isValid();
75// },
76// [](Context *context) {
77// Sink::Query query;
78// query += Sink::Query::RequestedProperties(QByteArrayList() << "name")
79// //FIXME do something like specialuse?
80// query += Sink::Query::PropertyFilter("name", "Drafts");
81// // query += Sink::Query::PropertyContainsFilter("specialuser", "drafts");
82// query += Sink::Query::PropertyFilter("drafts", true);
83// //TODO Use drafts folder of that specific account
84// Sink::Store::fetchAll<Sink::ApplicationDomain::Folder>(query)
85// .then<void, QList<Sink::ApplicationDomain::Folder>>([](const QList<Sink::ApplicationDomain::Folder> folders) {
86// if (folders.isEmpty()) {
87// return KAsync::start([]() {
88// //If message is already existing, modify, otherwise create
89// });
90// }
91// });
92// //TODO
93// // * Find drafts folder
94// // * Store KMime::Message on disk for use in blob property
95// // * Check if message is already existing and either create or update
96// // *
97// // auto mail = context->property("mail").value<Sink::ApplicationDomain::Mail::Ptr>();
98// // if (!mail) {
99// // qWarning() << "Failed to get the mail mail: " << context->property("mail");
100// // return;
101// // }
102// // mail->setProperty("unread", false);
103// // qDebug() << "Mark as read " << mail->identifier();
104// // Sink::Store::modify(*mail).exec();
105// }
106// );
diff --git a/framework/domain/composer.cpp b/framework/domain/composer.cpp
new file mode 100644
index 00000000..2f4fe2e9
--- /dev/null
+++ b/framework/domain/composer.cpp
@@ -0,0 +1,199 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20
21#include "composer.h"
22#include <actions/context.h>
23#include <actions/action.h>
24#include <settings/settings.h>
25#include <KMime/Message>
26#include <KCodecs/KEmailAddress>
27#include <QVariant>
28#include <QDebug>
29
30#include "mailtemplates.h"
31
32Composer::Composer(QObject *parent) : QObject(parent)
33{
34 m_identityModel << "Kuberich <kuberich@kolabnow.com>" << "Uni <kuberich@university.edu>" << "Spam <hello.spam@spam.to>";
35}
36
37QString Composer::to() const
38{
39 return m_to;
40}
41
42void Composer::setTo(const QString &to)
43{
44 if(m_to != to) {
45 m_to = to;
46 emit toChanged();
47 }
48}
49
50QString Composer::cc() const
51{
52 return m_cc;
53}
54
55void Composer::setCc(const QString &cc)
56{
57 if(m_cc != cc) {
58 m_cc = cc;
59 emit ccChanged();
60 }
61}
62
63QString Composer::bcc() const
64{
65 return m_bcc;
66}
67
68void Composer::setBcc(const QString &bcc)
69{
70 if(m_bcc != bcc) {
71 m_bcc = bcc;
72 emit bccChanged();
73 }
74}
75
76QString Composer::subject() const
77{
78 return m_subject;
79}
80
81void Composer::setSubject(const QString &subject)
82{
83 if(m_subject != subject) {
84 m_subject = subject;
85 emit subjectChanged();
86 }
87}
88
89QString Composer::body() const
90{
91 return m_body;
92}
93
94void Composer::setBody(const QString &body)
95{
96 if(m_body != body) {
97 m_body = body;
98 emit bodyChanged();
99 }
100}
101
102QStringList Composer::identityModel() const
103{
104 return m_identityModel;
105}
106
107int Composer::fromIndex() const
108{
109 return m_fromIndex;
110}
111
112void Composer::setFromIndex(int fromIndex)
113{
114 if(m_fromIndex != fromIndex) {
115 m_fromIndex = fromIndex;
116 emit fromIndexChanged();
117 }
118}
119
120QVariant Composer::originalMessage() const
121{
122 return m_originalMessage;
123}
124
125void Composer::setOriginalMessage(const QVariant &originalMessage)
126{
127 const auto mailData = KMime::CRLFtoLF(originalMessage.toByteArray());
128 if (!mailData.isEmpty()) {
129 KMime::Message::Ptr mail(new KMime::Message);
130 mail->setContent(mailData);
131 mail->parse();
132 auto reply = MailTemplates::reply(mail);
133 //We assume reply
134 setTo(reply->to(true)->asUnicodeString());
135 setCc(reply->cc(true)->asUnicodeString());
136 setSubject(reply->subject(true)->asUnicodeString());
137 setBody(reply->body());
138 m_msg = QVariant::fromValue(reply);
139 } else {
140 m_msg = QVariant();
141 }
142}
143
144KMime::Message::Ptr Composer::assembleMessage()
145{
146 auto mail = m_msg.value<KMime::Message::Ptr>();
147 if (!mail) {
148 mail = KMime::Message::Ptr::create();
149 }
150 for (const auto &to : KEmailAddress::splitAddressList(m_to)) {
151 QByteArray displayName;
152 QByteArray addrSpec;
153 QByteArray comment;
154 KEmailAddress::splitAddress(to.toUtf8(), displayName, addrSpec, comment);
155 mail->to(true)->addAddress(addrSpec, displayName);
156 }
157 mail->subject(true)->fromUnicodeString(m_subject, "utf-8");
158 mail->setBody(m_body.toUtf8());
159 mail->assemble();
160 return mail;
161}
162
163void Composer::send()
164{
165 auto mail = assembleMessage();
166 Kube::ApplicationContext settings;
167 auto account = settings.currentAccount();
168 auto identity = account.primaryIdentity();
169 auto transport = identity.transport();
170
171 Kube::Context context;
172 context.setProperty("message", QVariant::fromValue(mail));
173
174 context.setProperty("username", transport.username());
175 context.setProperty("password", transport.password());
176 context.setProperty("server", transport.server());
177
178 Kube::Action("org.kde.kube.actions.sendmail", context).execute();
179 clear();
180}
181
182void Composer::saveAsDraft()
183{
184 auto mail = assembleMessage();
185 Kube::Context context;
186 context.setProperty("message", QVariant::fromValue(mail));
187 Kube::Action("org.kde.kube.actions.saveasdraft", context).execute();
188 clear();
189}
190
191void Composer::clear()
192{
193 setSubject("");
194 setBody("");
195 setTo("");
196 setCc("");
197 setBcc("");
198 setFromIndex(-1);
199}
diff --git a/framework/domain/composer.h b/framework/domain/composer.h
new file mode 100644
index 00000000..dd066b2e
--- /dev/null
+++ b/framework/domain/composer.h
@@ -0,0 +1,93 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#pragma once
21
22#include <QObject>
23#include <QString>
24#include <QStringList>
25#include <QVariant>
26
27namespace KMime {
28class Message;
29}
30
31class Composer : public QObject
32{
33 Q_OBJECT
34 Q_PROPERTY (QVariant originalMessage READ originalMessage WRITE setOriginalMessage)
35 Q_PROPERTY (QString to READ to WRITE setTo NOTIFY toChanged)
36 Q_PROPERTY (QString cc READ cc WRITE setCc NOTIFY ccChanged)
37 Q_PROPERTY (QString bcc READ bcc WRITE setBcc NOTIFY bccChanged)
38 Q_PROPERTY (QString subject READ subject WRITE setSubject NOTIFY subjectChanged)
39 Q_PROPERTY (QString body READ body WRITE setBody NOTIFY bodyChanged)
40 Q_PROPERTY (QStringList identityModel READ identityModel)
41 Q_PROPERTY (int fromIndex READ fromIndex WRITE setFromIndex NOTIFY fromIndexChanged)
42
43public:
44 explicit Composer(QObject *parent = Q_NULLPTR);
45
46 QString to() const;
47 void setTo(const QString &to);
48
49 QString cc() const;
50 void setCc(const QString &cc);
51
52 QString bcc() const;
53 void setBcc(const QString &bcc);
54
55 QString subject() const;
56 void setSubject(const QString &subject);
57
58 QString body() const;
59 void setBody(const QString &body);
60
61 QStringList identityModel() const;
62
63 int fromIndex() const;
64 void setFromIndex(int fromIndex);
65
66 QVariant originalMessage() const;
67 void setOriginalMessage(const QVariant &originalMessage);
68
69signals:
70 void subjectChanged();
71 void bodyChanged();
72 void toChanged();
73 void ccChanged();
74 void bccChanged();
75 void fromIndexChanged();
76
77public slots:
78 void send();
79 void saveAsDraft();
80 void clear();
81
82private:
83 QSharedPointer<KMime::Message> assembleMessage();
84 QString m_to;
85 QString m_cc;
86 QString m_bcc;
87 QString m_subject;
88 QString m_body;
89 QStringList m_identityModel;
90 int m_fromIndex;
91 QVariant m_originalMessage;
92 QVariant m_msg;
93};
diff --git a/framework/domain/csshelper.cpp b/framework/domain/csshelper.cpp
new file mode 100644
index 00000000..a6355c57
--- /dev/null
+++ b/framework/domain/csshelper.cpp
@@ -0,0 +1,64 @@
1/*
2 csshelper.cpp
3
4 This file is part of KMail, the KDE mail client.
5 Copyright (c) 2003 Marc Mutz <mutz@kde.org>
6
7 KMail is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License, version 2, as
9 published by the Free Software Foundation.
10
11 KMail is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20 In addition, as a special exception, the copyright holders give
21 permission to link the code of this program with any edition of
22 the Qt library by Trolltech AS, Norway (or with modified versions
23 of Qt that use the same license as Qt), and distribute linked
24 combinations including the two. You must obey the GNU General
25 Public License in all respects for all of the code used other than
26 Qt. If you modify this file, you may extend this exception to
27 your version of the file, but you are not obligated to do so. If
28 you do not wish to do so, delete this exception statement from
29 your version.
30*/
31
32#include "csshelper.h"
33
34#include <QColor>
35#include <QDebug>
36#include <QFile>
37#include <QFont>
38#include <QFont>
39#include <QPalette>
40
41CSSHelper::CSSHelper(const QPaintDevice *pd) :
42 MessageViewer::CSSHelperBase(pd)
43{
44
45}
46
47QString cssDefinitions()
48{
49 QFile file(QLatin1String(MAIL_DATA_DIR) + QLatin1Char('/') + "mail.css");
50 if (file.open(QFile::ReadOnly)) {
51 return file.readAll();
52 }
53 return QString();
54}
55
56QString CSSHelper::htmlHead(bool fixed) const
57{
58 return
59 QLatin1String("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
60 "<html><head><title></title><style>\n")
61 + ::cssDefinitions() +
62 QLatin1String("</style></head>\n"
63 "<body>\n");
64} \ No newline at end of file
diff --git a/framework/domain/csshelper.h b/framework/domain/csshelper.h
new file mode 100644
index 00000000..775014e3
--- /dev/null
+++ b/framework/domain/csshelper.h
@@ -0,0 +1,44 @@
1/* -*- c++ -*-
2 csshelper.h
3
4 This file is part of KMail, the KDE mail client.
5 Copyright (c) 2003 Marc Mutz <mutz@kde.org>
6
7 KMail is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License, version 2, as
9 published by the Free Software Foundation.
10
11 KMail is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20 In addition, as a special exception, the copyright holders give
21 permission to link the code of this program with any edition of
22 the Qt library by Trolltech AS, Norway (or with modified versions
23 of Qt that use the same license as Qt), and distribute linked
24 combinations including the two. You must obey the GNU General
25 Public License in all respects for all of the code used other than
26 Qt. If you modify this file, you may extend this exception to
27 your version of the file, but you are not obligated to do so. If
28 you do not wish to do so, delete this exception statement from
29 your version.
30*/
31
32#pragma once
33
34#include <MessageViewer/CSSHelperBase>
35
36class CSSHelper : public MessageViewer::CSSHelperBase
37{
38public:
39 explicit CSSHelper(const QPaintDevice *pd);
40
41 /** @return HTML head including style sheet definitions and the
42 &gt;body&lt; tag */
43 QString htmlHead(bool fixedFont = false) const Q_DECL_OVERRIDE;
44}; \ No newline at end of file
diff --git a/framework/domain/data/mail.css b/framework/domain/data/mail.css
new file mode 100644
index 00000000..b77e36ee
--- /dev/null
+++ b/framework/domain/data/mail.css
@@ -0,0 +1,298 @@
1div.header {
2 margin-bottom: 10pt ! important;
3}
4
5table.textAtm {
6 margin-top: 10pt ! important;
7 margin-bottom: 10pt ! important;
8}
9
10tr.textAtmH,
11tr.textAtmB,
12tr.rfc822B {
13 font-weight: normal ! important;
14}
15
16tr.signInProgressH,
17tr.rfc822H,
18tr.encrH,
19tr.signOkKeyOkH,
20tr.signOkKeyBadH,
21tr.signWarnH,
22tr.sign
23ErrH {
24 font-weight: bold ! important;
25}
26
27tr.textAtmH td,
28tr.textAtmB td {
29 padding: 3px ! important;
30}
31
32table.rfc822 {
33 width: 100% ! important;
34 border: solid 1px black ! important;
35 margin-top: 10pt ! important;
36 margin-bottom: 10pt ! important;
37}
38
39table.textAtm,
40table.encr,
41table.signWarn,
42table.signErr,
43table.signOkKeyBad,
44table.signOkKeyOk,
45table.signInProgress,
46div.fancy.header table {
47 width: 100% ! important;
48 border-width: 0px ! important;
49 line-height: normal;
50}
51
52div.htmlWarn {
53 margin: 0px 5% ! important;
54 padding: 10px ! important;
55 text-align: left ! important;
56 line-height: normal;
57}
58
59div.fancy.header > div {
60 font-weight: bold ! important;
61 padding: 4px ! important;
62 line-height: normal;
63}
64
65div.fancy.header table {
66 padding: 2px ! important;
67 text-align: left ! important;
68 border-collapse: separate ! important;
69}
70
71div.fancy.header table th {
72 font-family: "Helvetica" ! important;
73 font-size: 12pt;
74 padding: 0px ! important;
75 white-space: nowrap ! important;
76 border-spacing: 0px ! important;
77 text-align: left ! important;
78 vertical-align: top ! important;
79 background-color: #efebe7 ! important;
80 color: #000000 ! important;
81 border: 1px ! important;
82}
83
84div.fancy.header table td {
85 font-family: "Helvetica" ! important;
86 font-size: 12pt;
87 padding: 0px ! important;
88 border-spacing: 0px ! important;
89 text-align: left ! important;
90 vertical-align: top ! important;
91 width: 100% ! important;
92 background-color: #efebe7 ! important;
93 color: #000000 ! important;
94 border: 1px ! important;
95}
96
97div.fancy.header table a:hover {
98 background-color: transparent ! important;
99}
100
101span.pimsmileytext {
102 position: absolute;
103 top: 0px;
104 left: 0px;
105 visibility: hidden;
106}
107
108img.pimsmileyimg {
109}
110
111div.quotelevelmark {
112 position: absolute;
113 margin-left:-10px;
114}
115
116body {
117 font-family: "Helvetica" ! important;
118 font-size: 12pt;
119 color: #000000 ! important;
120 background-color: #ffffff ! important;
121}
122
123a {
124 color: #0000cc ! important;
125 text-decoration: none ! important;
126}
127
128a.white {
129 color: white ! important;
130}
131
132a.black {
133 color: black ! important;
134}
135
136table.textAtm { background-color: #000000 ! important; }
137
138tr.textAtmH {
139 background-color: #ffffff ! important;
140 font-family: "Helvetica" ! important;
141 font-size: 12pt;
142}
143
144tr.textAtmB {
145 background-color: #ffffff ! important;
146}
147
148table.signInProgress,
149table.rfc822 {
150 background-color: #ffffff ! important
151;
152}
153
154tr.signInProgressH,
155tr.rfc822H {
156 font-family: "Helvetica" ! important;
157 font-size: 12pt;
158}
159
160table.encr {
161 background-color: #0010cc ! important;
162}
163
164tr.encrH {
165 background-color: #1010ee ! important;
166 color: #aaaaaa ! important;
167 font-family: "Helvetica" ! important;
168 font-size: 12pt;
169}
170
171tr.encrB { background-color: #ffe0e0 ! important; }
172
173table.signOkKeyOk {
174 background-color: #00cc00 ! important;
175}
176
177tr.signOkKeyOkH {
178 background-color: #00ff00 ! important;
179 color: #000000 ! important;
180 font-family: "Helvetica" ! important;
181 font-size: 12pt;
182}
183
184tr.signOkKeyOkB { background-color: #e0ffe0 ! important; }
185
186table.signOkKeyBad {
187 background-color: #00cc00 ! important;
188}
189
190tr.signOkKeyBadH {
191 background-color: #00ff00 ! important;
192 color: #000000 ! important;
193 font-family: "Helvetica" ! important;
194 font-size: 12pt;
195}
196
197tr.signOkKeyBadB { background-color: #e0ffe0 ! important; }
198
199table.signWarn {
200 background-color: #cc0 ! important;
201}
202
203tr.signWarnH {
204 background-color: #fc0 ! important;
205 color: #000000 ! important;
206 font-family: "Helvetica" ! imp
207ortant;
208 font-size: 12pt;
209}
210
211tr.signWarnB { background-color: #e0e0ff ! important; }
212
213table.signErr {
214 background-color: #c00 ! important;
215}
216
217tr.signErrH {
218 background-color: #0f00 ! important;
219 color: #0000
22000 ! important;
221 font-family: "Helvetica" ! important;
222 font-size: 12pt;
223}
224
225tr.signErrB { background-color: #d3d3f0 ! important; }
226
227div.htmlWarn {
228 border: 2px solid #00001a ! important;
229 line-height: normal;
230}
231
232div.header {
233 font-family: "Helvetica" ! important;
234 font-size: 12pt;
235}
236
237div.fancy.header > div {
238 background-color: #308cc6 ! important;
239 color: #ffffff ! important;
240 border: solid #000000 1px ! important;
241 line-height: normal;
242}
243
244div.fancy.header > div a[href] { color: #ffffff ! important; }
245
246div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }
247
248div.fancy.header > div.spamheader {
249 background-color: #cdcdcd ! important;
250 border-top: 0px ! important;
251 padding: 3px ! important;
252 color: black ! important;
253 font-weight: bold ! important;
254 font-size: 12pt;
255}
256
257div.fancy.header > table.outer {
258 background-color: #efebe7 ! important;
259 color: #000000 ! important;
260 border-bottom: solid #000000 1px ! important;
261 border-left: solid #000000 1px ! important;
262 border-right: solid #000000 1px ! important;
263}
264
265div.senderpic{
266 padding: 0px ! important;
267 font-size:0.8em ! important;
268 border:1px solid #b8b5b2 ! important;
269 background-color:#efebe7 ! important;
270}
271
272div.senderstatus{
273 text-align:center ! important;
274}
275
276div.quotelevel1 {
277 color: #100000 ! important;
278}
279
280div.quotelevel2 {
281 color: #200000 ! important;
282}
283
284div.quotelevel3 {
285 color: #300000 ! important;
286}
287
288div.deepquotelevel1 {
289 color: #100000 ! important;
290}
291
292div.deepquotelevel2 {
293 color: #200000 ! important;
294}
295
296div.deepquotelevel3 {
297 color: #300000 ! important;
298}
diff --git a/framework/domain/folderlistcontroller.cpp b/framework/domain/folderlistcontroller.cpp
new file mode 100644
index 00000000..46a6f648
--- /dev/null
+++ b/framework/domain/folderlistcontroller.cpp
@@ -0,0 +1,69 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#include "folderlistcontroller.h"
22
23#include "folderlistmodel.h"
24
25#include <QDebug>
26
27FolderListController::FolderListController(QObject *parent) : QObject(parent), m_model(new FolderListModel)
28{
29
30}
31
32QString FolderListController::accountId() const
33{
34 return m_accountId;
35}
36
37void FolderListController::setAccountId(const QString &id)
38{
39 if(m_accountId != id) {
40 m_accountId = id;
41
42 loadFolders(id);
43
44 emit accountIdChanged();
45 }
46}
47
48FolderListModel* FolderListController::model() const
49{
50 return m_model.data();
51}
52
53void FolderListController::loadFolders(const QString &id)
54{
55 //load foldermodel from sink
56
57}
58
59
60void FolderListController::addFolder(const QString &name)
61{
62 qDebug() << "User Action: add folder " << name;
63}
64
65void FolderListController::deleteFolder(const QString &id)
66{
67 qDebug() << "User Action: delete folder " << id;
68}
69
diff --git a/framework/domain/folderlistcontroller.h b/framework/domain/folderlistcontroller.h
new file mode 100644
index 00000000..11057f21
--- /dev/null
+++ b/framework/domain/folderlistcontroller.h
@@ -0,0 +1,56 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#pragma once
22
23#include "folderlistmodel.h"
24
25#include <QObject>
26#include <QScopedPointer>
27#include <QString>
28
29class FolderListController : public QObject
30{
31 Q_OBJECT
32 Q_PROPERTY (QString accountId READ accountId WRITE setAccountId NOTIFY accountIdChanged)
33 Q_PROPERTY (FolderListModel *model READ model CONSTANT)
34
35public:
36 explicit FolderListController(QObject *parent = Q_NULLPTR);
37
38 QString accountId() const;
39 void setAccountId(const QString &id);
40
41 FolderListModel *model() const;
42
43 void loadFolders(const QString &id);
44
45signals:
46 void accountIdChanged();
47
48public slots:
49 void deleteFolder(const QString &id);
50 void addFolder(const QString &name);
51
52
53private:
54 QString m_accountId;
55 QScopedPointer<FolderListModel> m_model;
56};
diff --git a/framework/domain/folderlistmodel.cpp b/framework/domain/folderlistmodel.cpp
new file mode 100644
index 00000000..ce6fb4fd
--- /dev/null
+++ b/framework/domain/folderlistmodel.cpp
@@ -0,0 +1,65 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#include "folderlistmodel.h"
22#include <sink/store.h>
23
24FolderListModel::FolderListModel(QObject *parent) : QIdentityProxyModel()
25{
26 Sink::Query query;
27 query.liveQuery = true;
28 query.requestedProperties << "name" << "icon" << "parent";
29 query.parentProperty = "parent";
30 mModel = Sink::Store::loadModel<Sink::ApplicationDomain::Folder>(query);
31 setSourceModel(mModel.data());
32}
33
34FolderListModel::~FolderListModel()
35{
36
37}
38
39QHash< int, QByteArray > FolderListModel::roleNames() const
40{
41 QHash<int, QByteArray> roles;
42
43 roles[Name] = "name";
44 roles[Icon] = "icon";
45 roles[Id] = "id";
46 roles[DomainObject] = "domainObject";
47
48 return roles;
49}
50
51QVariant FolderListModel::data(const QModelIndex &idx, int role) const
52{
53 auto srcIdx = mapToSource(idx);
54 switch (role) {
55 case Name:
56 return srcIdx.sibling(srcIdx.row(), 0).data(Qt::DisplayRole).toString();
57 case Icon:
58 return srcIdx.sibling(srcIdx.row(), 1).data(Qt::DisplayRole).toString();
59 case Id:
60 return srcIdx.data(Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>()->identifier();
61 case DomainObject:
62 return srcIdx.data(Sink::Store::DomainObjectRole);
63 }
64 return QIdentityProxyModel::data(idx, role);
65}
diff --git a/framework/domain/folderlistmodel.h b/framework/domain/folderlistmodel.h
new file mode 100644
index 00000000..7844e59a
--- /dev/null
+++ b/framework/domain/folderlistmodel.h
@@ -0,0 +1,50 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#pragma once
22
23#include <QObject>
24#include <QIdentityProxyModel>
25#include <QSharedPointer>
26#include <QStringList>
27
28class FolderListModel : public QIdentityProxyModel
29{
30 Q_OBJECT
31
32public:
33 FolderListModel(QObject *parent = Q_NULLPTR);
34 ~FolderListModel();
35
36 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
37
38 enum Roles {
39 Name = Qt::UserRole + 1,
40 Icon,
41 Id,
42 DomainObject
43 };
44 Q_ENUMS(Roles)
45
46 QHash<int, QByteArray> roleNames() const;
47
48private:
49 QSharedPointer<QAbstractItemModel> mModel;
50};
diff --git a/framework/domain/maillistcontroller.cpp b/framework/domain/maillistcontroller.cpp
new file mode 100644
index 00000000..a4bd6436
--- /dev/null
+++ b/framework/domain/maillistcontroller.cpp
@@ -0,0 +1,101 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#include "maillistcontroller.h"
22
23#include <QStringList>
24
25#include <sink/store.h>
26
27#include "maillistmodel.h"
28
29MailListController::MailListController(QObject *parent) : QObject(parent), m_model(new MailListModel)
30{
31}
32
33MailListModel *MailListController::model() const
34{
35 return m_model.data();
36
37}
38
39void MailListController::loadAllMail()
40{
41 Sink::Query query;
42 query.liveQuery = true;
43 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important";
44 m_model->runQuery(query);
45}
46
47void MailListController::loadMailFolder(const QString &folderId)
48{
49 Sink::Query query;
50 query.liveQuery = true;
51 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder";
52 query.propertyFilter.insert("folder", folderId.toLatin1());
53 m_model->runQuery(query);
54}
55
56void MailListController::loadUnreadMail()
57{
58 Sink::Query query;
59 query.liveQuery = true;
60 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important";
61 query.propertyFilter.insert("unread", true);
62 m_model->runQuery(query);
63}
64
65void MailListController::loadImportantMail()
66{
67 Sink::Query query;
68 query.liveQuery = true;
69 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important";
70 query.propertyFilter.insert("important", true);
71 m_model->runQuery(query);
72}
73
74QString MailListController::selectedMail() const
75{
76 return m_selectedMail;
77}
78
79void MailListController::setSelectedMail(const QString& id)
80{
81 if (m_selectedMail != id) {
82 m_selectedMail = id;
83 emit selectedMailChanged();
84 }
85}
86
87void MailListController::markMailImportant(bool important)
88{
89 qDebug() << "user action: mark mail important ";
90}
91
92void MailListController::markMailUnread(bool unread)
93{
94 qDebug() << "user action: mark mail unread ";
95}
96
97void MailListController::deleteMail()
98{
99 qDebug() << "user action: delete mail";
100}
101
diff --git a/framework/domain/maillistcontroller.h b/framework/domain/maillistcontroller.h
new file mode 100644
index 00000000..959c63a3
--- /dev/null
+++ b/framework/domain/maillistcontroller.h
@@ -0,0 +1,61 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#pragma once
22
23#include "maillistmodel.h"
24
25#include <QObject>
26#include <QScopedPointer>
27#include <QString>
28#include <QAbstractItemModel>
29
30class MailListController : public QObject
31{
32 Q_OBJECT
33 Q_PROPERTY (MailListModel *model READ model CONSTANT)
34 Q_PROPERTY (QString selectedMail READ selectedMail WRITE setSelectedMail NOTIFY selectedMailChanged)
35
36public:
37 explicit MailListController(QObject *parent = Q_NULLPTR);
38
39 MailListModel *model() const;
40
41 QString selectedMail() const;
42 void setSelectedMail(const QString &id);
43
44signals:
45 void selectedMailChanged();
46
47public slots:
48 void loadAllMail();
49 void loadUnreadMail();
50 void loadImportantMail();
51 void loadMailFolder(const QString &folderId);
52
53 void markMailImportant(bool important);
54 void markMailUnread(bool unread);
55 void deleteMail();
56
57private:
58 QScopedPointer<MailListModel> m_model;
59
60 QString m_selectedMail;
61};
diff --git a/framework/domain/maillistmodel.cpp b/framework/domain/maillistmodel.cpp
new file mode 100644
index 00000000..b46fabf8
--- /dev/null
+++ b/framework/domain/maillistmodel.cpp
@@ -0,0 +1,149 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#include "maillistmodel.h"
22
23#include <QFile>
24#include <QDateTime>
25
26
27MailListModel::MailListModel(QObject *parent)
28 : QSortFilterProxyModel()
29{
30 setDynamicSortFilter(true);
31 sort(0, Qt::DescendingOrder);
32}
33
34MailListModel::~MailListModel()
35{
36
37}
38
39QHash< int, QByteArray > MailListModel::roleNames() const
40{
41 QHash<int, QByteArray> roles;
42
43 roles[Subject] = "subject";
44 roles[Sender] = "sender";
45 roles[SenderName] = "senderName";
46 roles[Date] = "date";
47 roles[Unread] = "unread";
48 roles[Important] = "important";
49 roles[Id] = "id";
50 roles[MimeMessage] = "mimeMessage";
51 roles[DomainObject] = "domainObject";
52
53 return roles;
54}
55
56QVariant MailListModel::data(const QModelIndex &idx, int role) const
57{
58 auto srcIdx = mapToSource(idx);
59 switch (role) {
60 case Subject:
61 return srcIdx.sibling(srcIdx.row(), 0).data(Qt::DisplayRole).toString();
62 case Sender:
63 return srcIdx.sibling(srcIdx.row(), 1).data(Qt::DisplayRole).toString();
64 case SenderName:
65 return srcIdx.sibling(srcIdx.row(), 2).data(Qt::DisplayRole).toString();
66 case Date:
67 return srcIdx.sibling(srcIdx.row(), 3).data(Qt::DisplayRole).toString();
68 case Unread:
69 return srcIdx.sibling(srcIdx.row(), 4).data(Qt::DisplayRole).toBool();
70 case Important:
71 return srcIdx.sibling(srcIdx.row(), 5).data(Qt::DisplayRole).toBool();
72 case Id:
73 return srcIdx.data(Sink::Store::DomainObjectBaseRole).value<Sink::ApplicationDomain::ApplicationDomainType::Ptr>()->identifier();
74 case DomainObject:
75 return srcIdx.data(Sink::Store::DomainObjectRole);
76 case MimeMessage: {
77 auto filename = srcIdx.sibling(srcIdx.row(), 6).data(Qt::DisplayRole).toString();
78 QFile file(filename);
79 if (file.open(QFile::ReadOnly)) {
80 auto content = file.readAll();
81 qWarning() << filename << content;
82 return content;
83 } else {
84 qWarning() << "Failed to open the file";
85 }
86 return "Failed to read mail.";
87 }
88 }
89 return QSortFilterProxyModel::data(idx, role);
90}
91
92bool MailListModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
93{
94 const QVariant leftData = left.sibling(left.row(), 3).data(Qt::DisplayRole);
95 const QVariant rightData = right.sibling(right.row(), 3).data(Qt::DisplayRole);
96 return leftData.toDateTime() < rightData.toDateTime();
97}
98
99void MailListModel::runQuery(const Sink::Query &query)
100{
101 m_model = Sink::Store::loadModel<Sink::ApplicationDomain::Mail>(query);
102 setSourceModel(m_model.data());
103}
104
105void MailListModel::setParentFolder(const QVariant &parentFolder)
106{
107 auto folder = parentFolder.value<Sink::ApplicationDomain::Folder::Ptr>();
108 if (!folder) {
109 qWarning() << "No folder: " << parentFolder;
110 return;
111 }
112 Sink::Query query;
113 query.liveQuery = true;
114 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "folder";
115 query.propertyFilter.insert("folder", folder->identifier());
116 query.resources << folder->resourceInstanceIdentifier();
117 query.sortProperty = "date";
118 query.limit = 100;
119 qWarning() << "Running folder query: " << folder->resourceInstanceIdentifier() << folder->identifier();
120 runQuery(query);
121}
122
123QVariant MailListModel::parentFolder() const
124{
125 return QVariant();
126}
127
128void MailListModel::setMail(const QVariant &variant)
129{
130 auto mail = variant.value<Sink::ApplicationDomain::Mail::Ptr>();
131 if (!mail) {
132 qWarning() << "No mail: " << mail;
133 return;
134 }
135 Sink::Query query;
136 query.liveQuery = false;
137 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "mimeMessage";
138 query.ids << mail->identifier();
139 query.resources << mail->resourceInstanceIdentifier();
140 qWarning() << "Running mail query: " << mail->resourceInstanceIdentifier() << mail->identifier();
141 runQuery(query);
142}
143
144QVariant MailListModel::mail() const
145{
146 return QVariant();
147}
148
149
diff --git a/framework/domain/maillistmodel.h b/framework/domain/maillistmodel.h
new file mode 100644
index 00000000..47a2a091
--- /dev/null
+++ b/framework/domain/maillistmodel.h
@@ -0,0 +1,66 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#pragma once
22
23#include <sink/store.h>
24
25#include <QSortFilterProxyModel>
26#include <QSharedPointer>
27#include <QStringList>
28
29class MailListModel : public QSortFilterProxyModel
30{
31 Q_OBJECT
32 Q_PROPERTY (QVariant parentFolder READ parentFolder WRITE setParentFolder)
33 Q_PROPERTY (QVariant mail READ mail WRITE setMail)
34
35public:
36 MailListModel(QObject *parent = Q_NULLPTR);
37 ~MailListModel();
38
39 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
40
41 bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE;
42
43 enum Roles {
44 Subject = Qt::UserRole + 1,
45 Sender,
46 SenderName,
47 Date,
48 Unread,
49 Important,
50 Id,
51 MimeMessage,
52 DomainObject
53 };
54
55 QHash<int, QByteArray> roleNames() const;
56
57 void runQuery(const Sink::Query &query);
58
59 void setParentFolder(const QVariant &parentFolder);
60 QVariant parentFolder() const;
61
62 void setMail(const QVariant &mail);
63 QVariant mail() const;
64private:
65 QSharedPointer<QAbstractItemModel> m_model;
66};
diff --git a/framework/domain/mailplugin.cpp b/framework/domain/mailplugin.cpp
new file mode 100644
index 00000000..2d19a437
--- /dev/null
+++ b/framework/domain/mailplugin.cpp
@@ -0,0 +1,40 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#include "mailplugin.h"
22
23#include "maillistmodel.h"
24#include "folderlistmodel.h"
25#include "composer.h"
26#include "messageparser.h"
27#include "retriever.h"
28
29#include <QtQml>
30
31void MailPlugin::registerTypes (const char *uri)
32{
33 Q_ASSERT(uri == QLatin1String("org.kde.kube.mail"));
34
35 qmlRegisterType<FolderListModel>(uri, 1, 0, "FolderListModel");
36 qmlRegisterType<MailListModel>(uri, 1, 0, "MailListModel");
37 qmlRegisterType<Composer>(uri, 1, 0, "Composer");
38 qmlRegisterType<MessageParser>(uri, 1, 0, "MessageParser");
39 qmlRegisterType<Retriever>(uri, 1, 0, "Retriever");
40}
diff --git a/framework/domain/mailplugin.h b/framework/domain/mailplugin.h
new file mode 100644
index 00000000..ebd091ee
--- /dev/null
+++ b/framework/domain/mailplugin.h
@@ -0,0 +1,33 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#pragma once
22
23#include <QQmlEngine>
24#include <QQmlExtensionPlugin>
25
26class MailPlugin : public QQmlExtensionPlugin
27{
28 Q_OBJECT
29 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
30
31public:
32 virtual void registerTypes(const char *uri);
33}; \ No newline at end of file
diff --git a/framework/domain/mailtemplates.cpp b/framework/domain/mailtemplates.cpp
new file mode 100644
index 00000000..e5ee8533
--- /dev/null
+++ b/framework/domain/mailtemplates.cpp
@@ -0,0 +1,804 @@
1/*
2 Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
3 Copyright (c) 2010 Leo Franchi <lfranchi@kde.org>
4 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at your
9 option) any later version.
10
11 This library is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14 License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.
20*/
21#include "mailtemplates.h"
22
23#include <QByteArray>
24#include <QList>
25#include <QDebug>
26#include <QImage>
27#include <QWebPage>
28#include <QWebFrame>
29#include <QSysInfo>
30#include <QTextCodec>
31#include <QApplication>
32
33#include <KCodecs/KCharsets>
34#include <KMime/Types>
35
36#include "stringhtmlwriter.h"
37#include "objecttreesource.h"
38#include "csshelper.h"
39
40#include <MessageViewer/ObjectTreeParser>
41
42namespace KMime {
43 namespace Types {
44static bool operator==(const KMime::Types::AddrSpec &left, const KMime::Types::AddrSpec &right)
45{
46 return (left.asString() == right.asString());
47}
48
49static bool operator==(const KMime::Types::Mailbox &left, const KMime::Types::Mailbox &right)
50{
51 return (left.addrSpec().asString() == right.addrSpec().asString());
52}
53 }
54}
55
56static KMime::Types::Mailbox::List stripMyAddressesFromAddressList(const KMime::Types::Mailbox::List &list, const KMime::Types::AddrSpecList me)
57{
58 KMime::Types::Mailbox::List addresses(list);
59 for (KMime::Types::Mailbox::List::Iterator it = addresses.begin(); it != addresses.end();) {
60 if (me.contains(it->addrSpec())) {
61 it = addresses.erase(it);
62 } else {
63 ++it;
64 }
65 }
66
67 return addresses;
68}
69
70void initHeader(const KMime::Message::Ptr &message)
71{
72 message->removeHeader<KMime::Headers::To>();
73 message->removeHeader<KMime::Headers::Subject>();
74 message->date()->setDateTime(QDateTime::currentDateTime());
75
76 const QStringList extraInfo = QStringList() << QSysInfo::prettyProductName();
77 message->userAgent()->fromUnicodeString(QString("%1/%2(%3)").arg(QString::fromLocal8Bit("Kube")).arg("0.1").arg(extraInfo.join(",")), "utf-8");
78 // This will allow to change Content-Type:
79 message->contentType()->setMimeType("text/plain");
80}
81
82QString replacePrefixes(const QString &str, const QStringList &prefixRegExps,
83 bool replace, const QString &newPrefix)
84{
85 bool recognized = false;
86 // construct a big regexp that
87 // 1. is anchored to the beginning of str (sans whitespace)
88 // 2. matches at least one of the part regexps in prefixRegExps
89 QString bigRegExp = QStringLiteral("^(?:\\s+|(?:%1))+\\s*").arg(prefixRegExps.join(QStringLiteral(")|(?:")));
90 QRegExp rx(bigRegExp, Qt::CaseInsensitive);
91 if (rx.isValid()) {
92 QString tmp = str;
93 if (rx.indexIn(tmp) == 0) {
94 recognized = true;
95 if (replace) {
96 return tmp.replace(0, rx.matchedLength(), newPrefix + QLatin1String(" "));
97 }
98 }
99 } else {
100 qWarning() << "bigRegExp = \""
101 << bigRegExp << "\"\n"
102 << "prefix regexp is invalid!";
103 // try good ole Re/Fwd:
104 recognized = str.startsWith(newPrefix);
105 }
106
107 if (!recognized) {
108 return newPrefix + QLatin1String(" ") + str;
109 } else {
110 return str;
111 }
112}
113
114QString cleanSubject(const KMime::Message::Ptr &msg, const QStringList &prefixRegExps, bool replace, const QString &newPrefix)
115{
116 return replacePrefixes(msg->subject()->asUnicodeString(), prefixRegExps, replace, newPrefix);
117}
118
119QString forwardSubject(const KMime::Message::Ptr &msg)
120{
121 bool replaceForwardPrefix = true;
122 QStringList forwardPrefixes;
123 forwardPrefixes << "Fwd:";
124 forwardPrefixes << "FW:";
125 return cleanSubject(msg, forwardPrefixes, replaceForwardPrefix, QStringLiteral("Fwd:"));
126}
127
128QString replySubject(const KMime::Message::Ptr &msg)
129{
130 bool replaceReplyPrefix = true;
131 QStringList replyPrefixes;
132 //We're escaping the regex escape sequences. awesome
133 replyPrefixes << "Re\\\\s*:";
134 replyPrefixes << "Re[\\\\d+\\\\]:";
135 replyPrefixes << "Re\\\\d+:";
136 return cleanSubject(msg, replyPrefixes, replaceReplyPrefix, QStringLiteral("Re:"));
137}
138
139QByteArray getRefStr(const KMime::Message::Ptr &msg)
140{
141 QByteArray firstRef, lastRef, refStr, retRefStr;
142 int i, j;
143
144 if (auto hdr = msg->references(false)) {
145 refStr = hdr->as7BitString(false).trimmed();
146 }
147
148 if (refStr.isEmpty()) {
149 return msg->messageID()->as7BitString(false);
150 }
151
152 i = refStr.indexOf('<');
153 j = refStr.indexOf('>');
154 firstRef = refStr.mid(i, j - i + 1);
155 if (!firstRef.isEmpty()) {
156 retRefStr = firstRef + ' ';
157 }
158
159 i = refStr.lastIndexOf('<');
160 j = refStr.lastIndexOf('>');
161
162 lastRef = refStr.mid(i, j - i + 1);
163 if (!lastRef.isEmpty() && lastRef != firstRef) {
164 retRefStr += lastRef + ' ';
165 }
166
167 retRefStr += msg->messageID()->as7BitString(false);
168 return retRefStr;
169}
170
171KMime::Content *createPlainPartContent(const KMime::Message::Ptr &msg, const QString &plainBody)
172{
173 KMime::Content *textPart = new KMime::Content(msg.data());
174 textPart->contentType()->setMimeType("text/plain");
175 //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text
176 // QTextCodec *charset = selectCharset(m_charsets, plainBody);
177 // textPart->contentType()->setCharset(charset->name());
178 textPart->contentType()->setCharset("utf-8");
179 textPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit);
180 textPart->fromUnicodeString(plainBody);
181 return textPart;
182}
183
184KMime::Content *createMultipartAlternativeContent(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody)
185{
186 KMime::Content *multipartAlternative = new KMime::Content(msg.data());
187 multipartAlternative->contentType()->setMimeType("multipart/alternative");
188 const QByteArray boundary = KMime::multiPartBoundary();
189 multipartAlternative->contentType()->setBoundary(boundary);
190
191 KMime::Content *textPart = createPlainPartContent(msg, plainBody);
192 multipartAlternative->addContent(textPart);
193
194 KMime::Content *htmlPart = new KMime::Content(msg.data());
195 htmlPart->contentType()->setMimeType("text/html");
196 //FIXME This is supposed to select a charset out of the available charsets that contains all necessary characters to render the text
197 // QTextCodec *charset = selectCharset(m_charsets, htmlBody);
198 // htmlPart->contentType()->setCharset(charset->name());
199 textPart->contentType()->setCharset("utf-8");
200 htmlPart->contentTransferEncoding()->setEncoding(KMime::Headers::CE8Bit);
201 htmlPart->fromUnicodeString(htmlBody);
202 multipartAlternative->addContent(htmlPart);
203
204 return multipartAlternative;
205}
206
207void addProcessedBodyToMessage(const KMime::Message::Ptr &msg, const QString &plainBody, const QString &htmlBody, bool forward)
208{
209 //FIXME
210 // MessageCore::ImageCollector ic;
211 // ic.collectImagesFrom(mOrigMsg.data());
212
213 // Now, delete the old content and set the new content, which
214 // is either only the new text or the new text with some attachments.
215 auto parts = msg->contents();
216 foreach (KMime::Content *content, parts) {
217 msg->removeContent(content, true/*delete*/);
218 }
219
220 msg->contentType()->clear(); // to get rid of old boundary
221
222 const QByteArray boundary = KMime::multiPartBoundary();
223 KMime::Content *const mainTextPart =
224 htmlBody.isEmpty() ?
225 createPlainPartContent(msg, plainBody) :
226 createMultipartAlternativeContent(msg, plainBody, htmlBody);
227 mainTextPart->assemble();
228
229 KMime::Content *textPart = mainTextPart;
230 // if (!ic.images().empty()) {
231 // textPart = createMultipartRelated(ic, mainTextPart);
232 // textPart->assemble();
233 // }
234
235 // If we have some attachments, create a multipart/mixed mail and
236 // add the normal body as well as the attachments
237 KMime::Content *mainPart = textPart;
238 //FIXME
239 // if (forward) {
240 // auto attachments = mOrigMsg->attachments();
241 // attachments += mOtp->nodeHelper()->attachmentsOfExtraContents();
242 // if (!attachments.isEmpty()) {
243 // mainPart = createMultipartMixed(attachments, textPart);
244 // mainPart->assemble();
245 // }
246 // }
247
248 msg->setBody(mainPart->encodedBody());
249 msg->setHeader(mainPart->contentType());
250 msg->setHeader(mainPart->contentTransferEncoding());
251 msg->assemble();
252 msg->parse();
253}
254
255QString plainToHtml(const QString &body)
256{
257 QString str = body;
258 str = str.toHtmlEscaped();
259 str.replace(QStringLiteral("\n"), QStringLiteral("<br />\n"));
260 return str;
261}
262
263//TODO implement this function using a DOM tree parser
264void makeValidHtml(QString &body, const QString &headElement)
265{
266 QRegExp regEx;
267 regEx.setMinimal(true);
268 regEx.setPattern(QStringLiteral("<html.*>"));
269
270 if (!body.isEmpty() && !body.contains(regEx)) {
271 regEx.setPattern(QStringLiteral("<body.*>"));
272 if (!body.contains(regEx)) {
273 body = QLatin1String("<body>") + body + QLatin1String("<br/></body>");
274 }
275 regEx.setPattern(QStringLiteral("<head.*>"));
276 if (!body.contains(regEx)) {
277 body = QLatin1String("<head>") + headElement + QLatin1String("</head>") + body;
278 }
279 body = QLatin1String("<html>") + body + QLatin1String("</html>");
280 }
281}
282
283QString stripSignature(const QString &msg)
284{
285 // Following RFC 3676, only > before --
286 // I prefer to not delete a SB instead of delete good mail content.
287 const QRegExp sbDelimiterSearch = QRegExp(QLatin1String("(^|\n)[> ]*-- \n"));
288 // The regular expression to look for prefix change
289 const QRegExp commonReplySearch = QRegExp(QLatin1String("^[ ]*>"));
290
291 QString res = msg;
292 int posDeletingStart = 1; // to start looking at 0
293
294 // While there are SB delimiters (start looking just before the deleted SB)
295 while ((posDeletingStart = res.indexOf(sbDelimiterSearch, posDeletingStart - 1)) >= 0) {
296 QString prefix; // the current prefix
297 QString line; // the line to check if is part of the SB
298 int posNewLine = -1;
299
300 // Look for the SB beginning
301 int posSignatureBlock = res.indexOf(QLatin1Char('-'), posDeletingStart);
302 // The prefix before "-- "$
303 if (res.at(posDeletingStart) == QLatin1Char('\n')) {
304 ++posDeletingStart;
305 }
306
307 prefix = res.mid(posDeletingStart, posSignatureBlock - posDeletingStart);
308 posNewLine = res.indexOf(QLatin1Char('\n'), posSignatureBlock) + 1;
309
310 // now go to the end of the SB
311 while (posNewLine < res.size() && posNewLine > 0) {
312 // handle the undefined case for mid ( x , -n ) where n>1
313 int nextPosNewLine = res.indexOf(QLatin1Char('\n'), posNewLine);
314
315 if (nextPosNewLine < 0) {
316 nextPosNewLine = posNewLine - 1;
317 }
318
319 line = res.mid(posNewLine, nextPosNewLine - posNewLine);
320
321 // check when the SB ends:
322 // * does not starts with prefix or
323 // * starts with prefix+(any substring of prefix)
324 if ((prefix.isEmpty() && line.indexOf(commonReplySearch) < 0) ||
325 (!prefix.isEmpty() && line.startsWith(prefix) &&
326 line.mid(prefix.size()).indexOf(commonReplySearch) < 0)) {
327 posNewLine = res.indexOf(QLatin1Char('\n'), posNewLine) + 1;
328 } else {
329 break; // end of the SB
330 }
331 }
332
333 // remove the SB or truncate when is the last SB
334 if (posNewLine > 0) {
335 res.remove(posDeletingStart, posNewLine - posDeletingStart);
336 } else {
337 res.truncate(posDeletingStart);
338 }
339 }
340
341 return res;
342}
343
344QString plainMessageText(MessageViewer::ObjectTreeParser &otp, bool aStripSignature)
345{
346 QString result = otp.plainTextContent();
347 if (result.isEmpty()) { //HTML-only mails
348 QWebPage doc;
349 doc.mainFrame()->setHtml(otp.htmlContent());
350 result = doc.mainFrame()->toPlainText();
351 }
352
353 if (aStripSignature) {
354 result = stripSignature(result);
355 }
356
357 return result;
358}
359
360QString htmlMessageText(MessageViewer::ObjectTreeParser &otp, bool aStripSignature, QString &headElement)
361{
362 QString htmlElement = otp.htmlContent();
363
364 if (htmlElement.isEmpty()) { //plain mails only
365 QString htmlReplace = otp.plainTextContent().toHtmlEscaped();
366 htmlReplace = htmlReplace.replace(QStringLiteral("\n"), QStringLiteral("<br />"));
367 htmlElement = QStringLiteral("<html><head></head><body>%1</body></html>\n").arg(htmlReplace);
368 }
369
370 //QWebPage relies on this
371 Q_ASSERT(QApplication::style());
372 QWebPage page;
373 page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false);
374 page.settings()->setAttribute(QWebSettings::JavaEnabled, false);
375 page.settings()->setAttribute(QWebSettings::PluginsEnabled, false);
376 page.settings()->setAttribute(QWebSettings::AutoLoadImages, false);
377
378 page.currentFrame()->setHtml(htmlElement);
379
380 //TODO to be tested/verified if this is not an issue
381 page.settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
382 const QString bodyElement = page.currentFrame()->evaluateJavaScript(
383 QStringLiteral("document.getElementsByTagName('body')[0].innerHTML")).toString();
384
385 headElement = page.currentFrame()->evaluateJavaScript(
386 QStringLiteral("document.getElementsByTagName('head')[0].innerHTML")).toString();
387
388 page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false);
389
390 if (!bodyElement.isEmpty()) {
391 if (aStripSignature) {
392 //FIXME strip signature works partially for HTML mails
393 return stripSignature(bodyElement);
394 }
395 return bodyElement;
396 }
397
398 if (aStripSignature) {
399 //FIXME strip signature works partially for HTML mails
400 return stripSignature(htmlElement);
401 }
402 return htmlElement;
403}
404
405QString formatQuotePrefix(const QString &wildString, const QString &fromDisplayString)
406{
407 QString result;
408
409 if (wildString.isEmpty()) {
410 return wildString;
411 }
412
413 unsigned int strLength(wildString.length());
414 for (uint i = 0; i < strLength;) {
415 QChar ch = wildString[i++];
416 if (ch == QLatin1Char('%') && i < strLength) {
417 ch = wildString[i++];
418 switch (ch.toLatin1()) {
419 case 'f': { // sender's initals
420 if (fromDisplayString.isEmpty()) {
421 break;
422 }
423
424 uint j = 0;
425 const unsigned int strLength(fromDisplayString.length());
426 for (; j < strLength && fromDisplayString[j] > QLatin1Char(' '); ++j)
427 ;
428 for (; j < strLength && fromDisplayString[j] <= QLatin1Char(' '); ++j)
429 ;
430 result += fromDisplayString[0];
431 if (j < strLength && fromDisplayString[j] > QLatin1Char(' ')) {
432 result += fromDisplayString[j];
433 } else if (strLength > 1) {
434 if (fromDisplayString[1] > QLatin1Char(' ')) {
435 result += fromDisplayString[1];
436 }
437 }
438 }
439 break;
440 case '_':
441 result += QLatin1Char(' ');
442 break;
443 case '%':
444 result += QLatin1Char('%');
445 break;
446 default:
447 result += QLatin1Char('%');
448 result += ch;
449 break;
450 }
451 } else {
452 result += ch;
453 }
454 }
455 return result;
456}
457
458QString quotedPlainText(const QString &selection, const QString &fromDisplayString)
459{
460 QString content = selection;
461 // Remove blank lines at the beginning:
462 const int firstNonWS = content.indexOf(QRegExp(QLatin1String("\\S")));
463 const int lineStart = content.lastIndexOf(QLatin1Char('\n'), firstNonWS);
464 if (lineStart >= 0) {
465 content.remove(0, static_cast<unsigned int>(lineStart));
466 }
467
468 const auto quoteString = QStringLiteral("> ");
469 const QString indentStr = formatQuotePrefix(quoteString, fromDisplayString);
470 //FIXME
471 // if (TemplateParserSettings::self()->smartQuote() && mWrap) {
472 // content = MessageCore::StringUtil::smartQuote(content, mColWrap - indentStr.length());
473 // }
474 content.replace(QLatin1Char('\n'), QLatin1Char('\n') + indentStr);
475 content.prepend(indentStr);
476 content += QLatin1Char('\n');
477
478 return content;
479}
480
481QString quotedHtmlText(const QString &selection)
482{
483 QString content = selection;
484 //TODO 1) look for all the variations of <br> and remove the blank lines
485 //2) implement vertical bar for quoted HTML mail.
486 //3) After vertical bar is implemented, If a user wants to edit quoted message,
487 // then the <blockquote> tags below should open and close as when required.
488
489 //Add blockquote tag, so that quoted message can be differentiated from normal message
490 content = QLatin1String("<blockquote>") + content + QLatin1String("</blockquote>");
491 return content;
492}
493
494void applyCharset(const KMime::Message::Ptr msg, const KMime::Message::Ptr &origMsg)
495{
496 // first convert the body from its current encoding to unicode representation
497 QTextCodec *bodyCodec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset()));
498 if (!bodyCodec) {
499 bodyCodec = KCharsets::charsets()->codecForName(QStringLiteral("UTF-8"));
500 }
501
502 const QString body = bodyCodec->toUnicode(msg->body());
503
504 // then apply the encoding of the original message
505 msg->contentType()->setCharset(origMsg->contentType()->charset());
506
507 QTextCodec *codec = KCharsets::charsets()->codecForName(QString::fromLatin1(msg->contentType()->charset()));
508 if (!codec) {
509 qCritical() << "Could not get text codec for charset" << msg->contentType()->charset();
510 } else if (!codec->canEncode(body)) { // charset can't encode body, fall back to preferred
511 const QStringList charsets /*= preferredCharsets() */;
512
513 QList<QByteArray> chars;
514 chars.reserve(charsets.count());
515 foreach (const QString &charset, charsets) {
516 chars << charset.toLatin1();
517 }
518
519 //FIXME
520 QByteArray fallbackCharset/* = selectCharset(chars, body)*/;
521 if (fallbackCharset.isEmpty()) { // UTF-8 as fall-through
522 fallbackCharset = "UTF-8";
523 }
524
525 codec = KCharsets::charsets()->codecForName(QString::fromLatin1(fallbackCharset));
526 msg->setBody(codec->fromUnicode(body));
527 } else {
528 msg->setBody(codec->fromUnicode(body));
529 }
530}
531
532enum ReplyStrategy {
533 ReplyList,
534 ReplySmart,
535 ReplyAll,
536 ReplyAuthor,
537 ReplyNone
538};
539
540KMime::Message::Ptr MailTemplates::reply(const KMime::Message::Ptr &origMsg)
541{
542 //FIXME
543 const bool alwaysPlain = true;
544 //FIXME
545 const ReplyStrategy replyStrategy = ReplySmart;
546 KMime::Message::Ptr msg(new KMime::Message);
547 //FIXME
548 //Personal email addresses
549 KMime::Types::AddrSpecList me;
550 KMime::Types::Mailbox::List toList;
551 KMime::Types::Mailbox::List replyToList;
552 KMime::Types::Mailbox::List mailingListAddresses;
553
554 // const uint originalIdentity = identityUoid(origMsg);
555 initHeader(msg);
556 replyToList = origMsg->replyTo()->mailboxes();
557
558 msg->contentType()->setCharset("utf-8");
559
560 if (origMsg->headerByType("List-Post") &&
561 origMsg->headerByType("List-Post")->asUnicodeString().contains(QStringLiteral("mailto:"), Qt::CaseInsensitive)) {
562
563 const QString listPost = origMsg->headerByType("List-Post")->asUnicodeString();
564 QRegExp rx(QStringLiteral("<mailto:([^@>]+)@([^>]+)>"), Qt::CaseInsensitive);
565 if (rx.indexIn(listPost, 0) != -1) { // matched
566 KMime::Types::Mailbox mailbox;
567 mailbox.fromUnicodeString(rx.cap(1) + QLatin1Char('@') + rx.cap(2));
568 mailingListAddresses << mailbox;
569 }
570 }
571
572 switch (replyStrategy) {
573 case ReplySmart: {
574 if (auto hdr = origMsg->headerByType("Mail-Followup-To")) {
575 toList << KMime::Types::Mailbox::listFrom7BitString(hdr->as7BitString(false));
576 } else if (!replyToList.isEmpty()) {
577 toList = replyToList;
578 } else if (!mailingListAddresses.isEmpty()) {
579 toList = (KMime::Types::Mailbox::List() << mailingListAddresses.at(0));
580 } else {
581 // doesn't seem to be a mailing list, reply to From: address
582 toList = origMsg->from()->mailboxes();
583
584 bool listContainsMe = false;
585 for (const auto &m : me) {
586 KMime::Types::Mailbox mailbox;
587 mailbox.setAddress(m);
588 if (toList.contains(mailbox)) {
589 listContainsMe = true;
590 }
591 }
592 if (listContainsMe) {
593 // sender seems to be one of our own identities, so we assume that this
594 // is a reply to a "sent" mail where the users wants to add additional
595 // information for the recipient.
596 toList = origMsg->to()->mailboxes();
597 }
598 }
599 // strip all my addresses from the list of recipients
600 const KMime::Types::Mailbox::List recipients = toList;
601
602 toList = stripMyAddressesFromAddressList(recipients, me);
603
604 // ... unless the list contains only my addresses (reply to self)
605 if (toList.isEmpty() && !recipients.isEmpty()) {
606 toList << recipients.first();
607 }
608 }
609 break;
610 case ReplyList: {
611 if (auto hdr = origMsg->headerByType("Mail-Followup-To")) {
612 KMime::Types::Mailbox mailbox;
613 mailbox.from7BitString(hdr->as7BitString(false));
614 toList << mailbox;
615 } else if (!mailingListAddresses.isEmpty()) {
616 toList << mailingListAddresses[ 0 ];
617 } else if (!replyToList.isEmpty()) {
618 // assume a Reply-To header mangling mailing list
619 toList = replyToList;
620 }
621
622 //FIXME
623 // strip all my addresses from the list of recipients
624 const KMime::Types::Mailbox::List recipients = toList;
625 toList = stripMyAddressesFromAddressList(recipients, me);
626 }
627 break;
628 case ReplyAll: {
629 KMime::Types::Mailbox::List recipients;
630 KMime::Types::Mailbox::List ccRecipients;
631
632 // add addresses from the Reply-To header to the list of recipients
633 if (!replyToList.isEmpty()) {
634 recipients = replyToList;
635
636 // strip all possible mailing list addresses from the list of Reply-To addresses
637 foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) {
638 foreach (const KMime::Types::Mailbox &recipient, recipients) {
639 if (mailbox == recipient) {
640 recipients.removeAll(recipient);
641 }
642 }
643 }
644 }
645
646 if (!mailingListAddresses.isEmpty()) {
647 // this is a mailing list message
648 if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) {
649 // The sender didn't set a Reply-to address, so we add the From
650 // address to the list of CC recipients.
651 ccRecipients += origMsg->from()->mailboxes();
652 qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of CC recipients";
653 }
654
655 // if it is a mailing list, add the posting address
656 recipients.prepend(mailingListAddresses[ 0 ]);
657 } else {
658 // this is a normal message
659 if (recipients.isEmpty() && !origMsg->from()->asUnicodeString().isEmpty()) {
660 // in case of replying to a normal message only then add the From
661 // address to the list of recipients if there was no Reply-to address
662 recipients += origMsg->from()->mailboxes();
663 qDebug() << "Added" << origMsg->from()->asUnicodeString() << "to the list of recipients";
664 }
665 }
666
667 // strip all my addresses from the list of recipients
668 toList = stripMyAddressesFromAddressList(recipients, me);
669
670 // merge To header and CC header into a list of CC recipients
671 if (!origMsg->cc()->asUnicodeString().isEmpty() || !origMsg->to()->asUnicodeString().isEmpty()) {
672 KMime::Types::Mailbox::List list;
673 if (!origMsg->to()->asUnicodeString().isEmpty()) {
674 list += origMsg->to()->mailboxes();
675 }
676 if (!origMsg->cc()->asUnicodeString().isEmpty()) {
677 list += origMsg->cc()->mailboxes();
678 }
679
680 foreach (const KMime::Types::Mailbox &mailbox, list) {
681 if (!recipients.contains(mailbox) &&
682 !ccRecipients.contains(mailbox)) {
683 ccRecipients += mailbox;
684 qDebug() << "Added" << mailbox.prettyAddress() << "to the list of CC recipients";
685 }
686 }
687 }
688
689 if (!ccRecipients.isEmpty()) {
690 // strip all my addresses from the list of CC recipients
691 ccRecipients = stripMyAddressesFromAddressList(ccRecipients, me);
692
693 // in case of a reply to self, toList might be empty. if that's the case
694 // then propagate a cc recipient to To: (if there is any).
695 if (toList.isEmpty() && !ccRecipients.isEmpty()) {
696 toList << ccRecipients.at(0);
697 ccRecipients.pop_front();
698 }
699
700 foreach (const KMime::Types::Mailbox &mailbox, ccRecipients) {
701 msg->cc()->addAddress(mailbox);
702 }
703 }
704
705 if (toList.isEmpty() && !recipients.isEmpty()) {
706 // reply to self without other recipients
707 toList << recipients.at(0);
708 }
709 }
710 break;
711 case ReplyAuthor: {
712 if (!replyToList.isEmpty()) {
713 KMime::Types::Mailbox::List recipients = replyToList;
714
715 // strip the mailing list post address from the list of Reply-To
716 // addresses since we want to reply in private
717 foreach (const KMime::Types::Mailbox &mailbox, mailingListAddresses) {
718 foreach (const KMime::Types::Mailbox &recipient, recipients) {
719 if (mailbox == recipient) {
720 recipients.removeAll(recipient);
721 }
722 }
723 }
724
725 if (!recipients.isEmpty()) {
726 toList = recipients;
727 } else {
728 // there was only the mailing list post address in the Reply-To header,
729 // so use the From address instead
730 toList = origMsg->from()->mailboxes();
731 }
732 } else if (!origMsg->from()->asUnicodeString().isEmpty()) {
733 toList = origMsg->from()->mailboxes();
734 }
735 }
736 break;
737 case ReplyNone:
738 // the addressees will be set by the caller
739 break;
740 }
741
742 foreach (const KMime::Types::Mailbox &mailbox, toList) {
743 msg->to()->addAddress(mailbox);
744 }
745
746 const QByteArray refStr = getRefStr(origMsg);
747 if (!refStr.isEmpty()) {
748 msg->references()->fromUnicodeString(QString::fromLocal8Bit(refStr), "utf-8");
749 }
750
751 //In-Reply-To = original msg-id
752 msg->inReplyTo()->from7BitString(origMsg->messageID()->as7BitString(false));
753
754 msg->subject()->fromUnicodeString(replySubject(origMsg), "utf-8");
755
756 auto definedLocale = QLocale::system();
757
758 //TODO set empty source instead
759 StringHtmlWriter htmlWriter;
760 QImage paintDevice;
761 CSSHelper cssHelper(&paintDevice);
762 MessageViewer::NodeHelper nodeHelper;
763 ObjectTreeSource source(&htmlWriter, &cssHelper);
764 MessageViewer::ObjectTreeParser otp(&source, &nodeHelper);
765 otp.setAllowAsync(false);
766 otp.parseObjectTree(origMsg.data());
767
768 //Add quoted body
769 QString plainBody;
770 QString htmlBody;
771
772 //On $datetime you wrote:
773 const QDateTime date = origMsg->date()->dateTime();
774 const auto dateTimeString = QString("%1 %2").arg(definedLocale.toString(date.date(), QLocale::LongFormat)).arg(definedLocale.toString(date.time(), QLocale::LongFormat));
775 const auto onDateYouWroteLine = QString("On %1 you wrote:").arg(dateTimeString);
776 plainBody.append(onDateYouWroteLine);
777 htmlBody.append(plainToHtml(onDateYouWroteLine));
778
779 //Strip signature for replies
780 const bool stripSignature = true;
781
782 //Quoted body
783 QString plainQuote = quotedPlainText(plainMessageText(otp, stripSignature), origMsg->from()->displayString());
784 if (plainQuote.endsWith(QLatin1Char('\n'))) {
785 plainQuote.chop(1);
786 }
787 plainBody.append(plainQuote);
788 QString headElement;
789 htmlBody.append(quotedHtmlText(htmlMessageText(otp, stripSignature, headElement)));
790
791 if (alwaysPlain) {
792 htmlBody.clear();
793 } else {
794 makeValidHtml(htmlBody, headElement);
795 }
796
797 addProcessedBodyToMessage(msg, plainBody, htmlBody, false);
798
799 applyCharset(msg, origMsg);
800
801 msg->assemble();
802
803 return msg;
804}
diff --git a/framework/domain/mailtemplates.h b/framework/domain/mailtemplates.h
new file mode 100644
index 00000000..6519122a
--- /dev/null
+++ b/framework/domain/mailtemplates.h
@@ -0,0 +1,28 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#pragma once
21
22#include <QByteArray>
23#include <KMime/Message>
24
25namespace MailTemplates
26{
27 KMime::Message::Ptr reply(const KMime::Message::Ptr &message);
28};
diff --git a/framework/domain/mailtransport.cpp b/framework/domain/mailtransport.cpp
new file mode 100644
index 00000000..49d858e1
--- /dev/null
+++ b/framework/domain/mailtransport.cpp
@@ -0,0 +1,160 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19#include "mailtransport.h"
20
21#include <QByteArray>
22#include <QList>
23#include <QDebug>
24
25extern "C" {
26
27#include <stdio.h>
28#include <string.h>
29#include <curl/curl.h>
30
31struct upload_status {
32 int offset;
33 const char *data;
34};
35
36static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
37{
38 struct upload_status *upload_ctx = (struct upload_status *)userp;
39 const char *data;
40
41 if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
42 return 0;
43 }
44
45 data = &upload_ctx->data[upload_ctx->offset];
46 if(data) {
47 size_t len = strlen(data);
48 if (len > size * nmemb) {
49 len = size * nmemb;
50 }
51 fprintf(stderr, "read n bytes: %d\n",len);
52 memcpy(ptr, data, len);
53 upload_ctx->offset += len;
54 return len;
55 }
56
57 return 0;
58}
59
60
61void sendMessageCurl(const char *to[], int numTos, const char *cc[], int numCcs, const char *msg, bool useTls, const char* from, const char *username, const char *password, const char *server, bool verifyPeer)
62{
63 //For ssl use "smtps://mainserver.example.net
64 const char* cacert = 0; // = "/path/to/certificate.pem";
65
66 CURL *curl;
67 CURLcode res = CURLE_OK;
68 struct curl_slist *recipients = NULL;
69 struct upload_status upload_ctx;
70
71 upload_ctx.offset = 0;
72 upload_ctx.data = msg;
73
74 curl = curl_easy_init();
75 if(curl) {
76 curl_easy_setopt(curl, CURLOPT_USERNAME, username);
77 curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
78
79 curl_easy_setopt(curl, CURLOPT_URL, server);
80
81 if (useTls) {
82 curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
83 }
84
85 if (!verifyPeer) {
86 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
87 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
88 }
89 if (cacert) {
90 curl_easy_setopt(curl, CURLOPT_CAINFO, cacert);
91 }
92
93 if (from) {
94 curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from);
95 }
96
97 for (int i = 0; i < numTos; i++) {
98 recipients = curl_slist_append(recipients, to[i]);
99 }
100 for (int i = 0; i < numCcs; i++) {
101 recipients = curl_slist_append(recipients, cc[i]);
102 }
103 curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
104
105 /* We're using a callback function to specify the payload (the headers and
106 * body of the message). You could just use the CURLOPT_READDATA option to
107 * specify a FILE pointer to read from. */
108 curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
109 curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
110 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
111
112 /* Since the traffic will be encrypted, it is very useful to turn on debug
113 * information within libcurl to see what is happening during the transfer.
114 */
115 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
116
117 res = curl_easy_perform(curl);
118 if(res != CURLE_OK) {
119 fprintf(stderr, "curl_easy_perform() failed: %s\n",
120 curl_easy_strerror(res));
121 }
122 curl_slist_free_all(recipients);
123 curl_easy_cleanup(curl);
124 }
125}
126
127};
128
129void MailTransport::sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert)
130{
131 QByteArray msg = message->encodedContent();
132 qWarning() << "Sending message " << msg;
133
134 QByteArray from(message->from(true)->mailboxes().isEmpty() ? QByteArray() : message->from(true)->mailboxes().first().address());
135 QList<QByteArray> toList;
136 for (const auto &mb : message->to(true)->mailboxes()) {
137 toList << mb.address();
138 }
139 QList<QByteArray> ccList;
140 for (const auto &mb : message->cc(true)->mailboxes()) {
141 ccList << mb.address();
142 }
143 bool useTls = true;
144 bool verifyPeer = false;
145
146 const int numTos = toList.size();
147 const char* to[numTos];
148 for (int i = 0; i < numTos; i++) {
149 to[i] = toList.at(i);
150 }
151
152 const int numCcs = ccList.size();
153 const char* cc[numCcs];
154 for (int i = 0; i < numCcs; i++) {
155 cc[i] = ccList.at(i);
156 }
157
158 sendMessageCurl(to, numTos, cc, numCcs, msg, useTls, from.isEmpty() ? nullptr : from, username, password, server, verifyPeer);
159 qWarning() << "Message sent";
160}
diff --git a/framework/domain/mailtransport.h b/framework/domain/mailtransport.h
new file mode 100644
index 00000000..2eb30a03
--- /dev/null
+++ b/framework/domain/mailtransport.h
@@ -0,0 +1,28 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#pragma once
21
22#include <QByteArray>
23#include <KMime/Message>
24
25namespace MailTransport
26{
27 void sendMessage(const KMime::Message::Ptr &message, const QByteArray &server, const QByteArray &username, const QByteArray &password, const QByteArray &cacert);
28};
diff --git a/framework/domain/messageparser.cpp b/framework/domain/messageparser.cpp
new file mode 100644
index 00000000..89f67f38
--- /dev/null
+++ b/framework/domain/messageparser.cpp
@@ -0,0 +1,76 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19#include "messageparser.h"
20
21#include "stringhtmlwriter.h"
22#include "objecttreesource.h"
23#include "csshelper.h"
24
25#include <QFile>
26#include <QImage>
27#include <QDebug>
28#include <QTime>
29#include <MessageViewer/ObjectTreeParser>
30
31MessageParser::MessageParser(QObject *parent)
32 : QObject(parent)
33{
34
35}
36
37QString MessageParser::html() const
38{
39 return mHtml;
40}
41
42QVariant MessageParser::message() const
43{
44 return QVariant();
45}
46
47void MessageParser::setMessage(const QVariant &message)
48{
49 QTime time;
50 time.start();
51 const auto mailData = KMime::CRLFtoLF(message.toByteArray());
52 KMime::Message::Ptr msg(new KMime::Message);
53 msg->setContent(mailData);
54 msg->parse();
55 qWarning() << "parsed: " << time.elapsed();
56
57 // render the mail
58 StringHtmlWriter htmlWriter;
59 QImage paintDevice;
60 CSSHelper cssHelper(&paintDevice);
61 //temporary files only have the lifetime of the nodehelper, so we keep it around until the mail changes.
62 mNodeHelper = std::make_shared<MessageViewer::NodeHelper>();
63 ObjectTreeSource source(&htmlWriter, &cssHelper);
64 MessageViewer::ObjectTreeParser otp(&source, mNodeHelper.get());
65
66 htmlWriter.begin(QString());
67 htmlWriter.queue(cssHelper.htmlHead(false));
68
69 otp.parseObjectTree(msg.data());
70
71 htmlWriter.queue(QStringLiteral("</body></html>"));
72 htmlWriter.end();
73
74 mHtml = htmlWriter.html();
75 emit htmlChanged();
76}
diff --git a/framework/domain/messageparser.h b/framework/domain/messageparser.h
new file mode 100644
index 00000000..ba08a5ec
--- /dev/null
+++ b/framework/domain/messageparser.h
@@ -0,0 +1,51 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#pragma once
21
22#include <QObject>
23#include <QString>
24#include <QStringList>
25#include <memory>
26
27namespace MessageViewer {
28 class NodeHelper;
29};
30
31class MessageParser : public QObject
32{
33 Q_OBJECT
34 Q_PROPERTY (QVariant message READ message WRITE setMessage)
35 Q_PROPERTY (QString html READ html NOTIFY htmlChanged)
36
37public:
38 explicit MessageParser(QObject *parent = Q_NULLPTR);
39
40 QString html() const;
41
42 QVariant message() const;
43 void setMessage(const QVariant &to);
44
45signals:
46 void htmlChanged();
47
48private:
49 QString mHtml;
50 std::shared_ptr<MessageViewer::NodeHelper> mNodeHelper;
51};
diff --git a/framework/domain/objecttreesource.cpp b/framework/domain/objecttreesource.cpp
new file mode 100644
index 00000000..d14b7b9b
--- /dev/null
+++ b/framework/domain/objecttreesource.cpp
@@ -0,0 +1,144 @@
1/*
2 Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
3 Copyright (c) 2009 Andras Mantia <andras@kdab.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#include "objecttreesource.h"
21
22#include <MessageViewer/AttachmentStrategy>
23
24class ObjectSourcePrivate
25{
26public:
27 ObjectSourcePrivate()
28 : mWriter(0)
29 , mCSSHelper(0)
30 , mAllowDecryption(true)
31 , mHtmlLoadExternal(true)
32 , mHtmlMail(true)
33 {
34
35 }
36 MessageViewer::HtmlWriter *mWriter;
37 MessageViewer::CSSHelperBase *mCSSHelper;
38 bool mAllowDecryption;
39 bool mHtmlLoadExternal;
40 bool mHtmlMail;
41};
42
43ObjectTreeSource::ObjectTreeSource(MessageViewer::HtmlWriter *writer,
44 MessageViewer::CSSHelperBase *cssHelper)
45 : MessageViewer::ObjectTreeSourceIf()
46 , d(new ObjectSourcePrivate)
47 {
48 d->mWriter = writer;
49 d->mCSSHelper = cssHelper;
50 }
51
52ObjectTreeSource::~ObjectTreeSource()
53{
54 delete d;
55}
56
57void ObjectTreeSource::setAllowDecryption(bool allowDecryption)
58{
59 d->mAllowDecryption = allowDecryption;
60}
61
62MessageViewer::HtmlWriter *ObjectTreeSource::htmlWriter()
63{
64 return d->mWriter;
65}
66MessageViewer::CSSHelperBase *ObjectTreeSource::cssHelper()
67{
68 return d->mCSSHelper;
69}
70
71bool ObjectTreeSource::htmlLoadExternal() const
72{
73 return d->mHtmlLoadExternal;
74}
75
76void ObjectTreeSource::setHtmlLoadExternal(bool loadExternal)
77{
78 d->mHtmlLoadExternal = loadExternal;
79}
80
81bool ObjectTreeSource::htmlMail() const
82{
83 return d->mHtmlMail;
84}
85
86void ObjectTreeSource::setHtmlMail(bool htmlMail)
87{
88 d->mHtmlMail = htmlMail;
89}
90
91bool ObjectTreeSource::decryptMessage() const
92{
93 return d->mAllowDecryption;
94}
95
96bool ObjectTreeSource::showSignatureDetails() const
97{
98 return true;
99}
100
101int ObjectTreeSource::levelQuote() const
102{
103 return 1;
104}
105
106const QTextCodec *ObjectTreeSource::overrideCodec()
107{
108 return Q_NULLPTR;
109}
110
111QString ObjectTreeSource::createMessageHeader(KMime::Message *message)
112{
113 return QString();
114}
115
116const MessageViewer::AttachmentStrategy *ObjectTreeSource::attachmentStrategy()
117{
118 return MessageViewer::AttachmentStrategy::smart();
119}
120
121QObject *ObjectTreeSource::sourceObject()
122{
123 return Q_NULLPTR;
124}
125
126void ObjectTreeSource::setHtmlMode(MessageViewer::Util::HtmlMode mode)
127{
128 Q_UNUSED(mode);
129}
130
131bool ObjectTreeSource::autoImportKeys() const
132{
133 return false;
134}
135
136bool ObjectTreeSource::showEmoticons() const
137{
138 return false;
139}
140
141bool ObjectTreeSource::showExpandQuotesMark() const
142{
143 return false;
144}
diff --git a/framework/domain/objecttreesource.h b/framework/domain/objecttreesource.h
new file mode 100644
index 00000000..db14e3ff
--- /dev/null
+++ b/framework/domain/objecttreesource.h
@@ -0,0 +1,57 @@
1/*
2 Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
3 Copyright (c) 2009 Andras Mantia <andras@kdab.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#ifndef MAILVIEWER_OBJECTTREEEMPTYSOURCE_H
21#define MAILVIEWER_OBJECTTREEEMPTYSOURCE_H
22
23#include <MessageViewer/ObjectTreeSourceIf>
24
25class QString;
26
27class ObjectSourcePrivate;
28class ObjectTreeSource : public MessageViewer::ObjectTreeSourceIf
29{
30public:
31 ObjectTreeSource(MessageViewer::HtmlWriter *writer,
32 MessageViewer::CSSHelperBase *cssHelper);
33 virtual ~ObjectTreeSource();
34 void setHtmlLoadExternal(bool loadExternal);
35 void setHtmlMail(bool htmlMail);
36 bool htmlMail() const Q_DECL_OVERRIDE;
37 bool decryptMessage() const Q_DECL_OVERRIDE;
38 bool htmlLoadExternal() const Q_DECL_OVERRIDE;
39 bool showSignatureDetails() const Q_DECL_OVERRIDE;
40 void setHtmlMode(MessageViewer::Util::HtmlMode mode) Q_DECL_OVERRIDE;
41 void setAllowDecryption(bool allowDecryption);
42 int levelQuote() const Q_DECL_OVERRIDE;
43 const QTextCodec *overrideCodec() Q_DECL_OVERRIDE;
44 QString createMessageHeader(KMime::Message *message) Q_DECL_OVERRIDE;
45 const MessageViewer::AttachmentStrategy *attachmentStrategy() Q_DECL_OVERRIDE;
46 MessageViewer::HtmlWriter *htmlWriter() Q_DECL_OVERRIDE;
47 MessageViewer::CSSHelperBase *cssHelper() Q_DECL_OVERRIDE;
48 QObject *sourceObject() Q_DECL_OVERRIDE;
49 bool autoImportKeys() const Q_DECL_OVERRIDE;
50 bool showEmoticons() const Q_DECL_OVERRIDE;
51 bool showExpandQuotesMark() const Q_DECL_OVERRIDE;
52private:
53 ObjectSourcePrivate *const d;
54};
55
56#endif
57
diff --git a/framework/domain/qmldir b/framework/domain/qmldir
new file mode 100644
index 00000000..fd54e5ee
--- /dev/null
+++ b/framework/domain/qmldir
@@ -0,0 +1,3 @@
1module org.kde.kube.mail
2
3plugin mailplugin
diff --git a/framework/domain/retriever.cpp b/framework/domain/retriever.cpp
new file mode 100644
index 00000000..b8e29523
--- /dev/null
+++ b/framework/domain/retriever.cpp
@@ -0,0 +1,55 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsystems.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20
21#include "retriever.h"
22
23Retriever::Retriever(QObject *parent) : QObject(parent)
24{
25}
26
27QAbstractItemModel* Retriever::model() const
28{
29 return mModel;
30}
31
32void Retriever::setModel(QAbstractItemModel* model)
33{
34 mValue = QVariant();
35 mModel = model;
36 connect(model, &QAbstractItemModel::rowsInserted, this, &Retriever::onRowsInserted);
37 connect(model, &QAbstractItemModel::modelReset, this, &Retriever::onModelReset);
38 if (model->rowCount(QModelIndex())) {
39 mValue = model->index(0, 0, QModelIndex()).data(mModel->roleNames().key(mPropertyName.toLatin1()));
40 emit valueChanged();
41 }
42}
43
44void Retriever::onRowsInserted(const QModelIndex &parent, int first, int last)
45{
46 if (!mValue.isValid()) {
47 mValue = mModel->index(0, 0, QModelIndex()).data(mModel->roleNames().key(mPropertyName.toLatin1()));
48 emit valueChanged();
49 }
50}
51
52void Retriever::onModelReset()
53{
54 mValue = QVariant();
55}
diff --git a/framework/domain/retriever.h b/framework/domain/retriever.h
new file mode 100644
index 00000000..e454532d
--- /dev/null
+++ b/framework/domain/retriever.h
@@ -0,0 +1,55 @@
1/*
2 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsystems.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#pragma once
21
22#include <QObject>
23#include <QAbstractItemModel>
24#include <QVariant>
25
26/**
27 * A wrapper for a QAbstractItemModel to retrieve a value from a single index via property binding
28 *
29 * Assign a model that retrieves the index, set the property your interested in, and propery-bind "value".
30 */
31class Retriever : public QObject
32{
33 Q_OBJECT
34 Q_PROPERTY(QAbstractItemModel* model READ model WRITE setModel)
35 Q_PROPERTY(QString propertyName MEMBER mPropertyName)
36 Q_PROPERTY(QVariant value MEMBER mValue NOTIFY valueChanged)
37
38public:
39 explicit Retriever(QObject *parent = Q_NULLPTR);
40
41 QAbstractItemModel* model() const;
42 void setModel(QAbstractItemModel* model);
43
44signals:
45 void valueChanged();
46
47private slots:
48 void onRowsInserted(const QModelIndex &parent, int first, int last);
49 void onModelReset();
50
51private:
52 QString mPropertyName;
53 QVariant mValue;
54 QAbstractItemModel *mModel;
55};
diff --git a/framework/domain/singlemailcontroller.cpp b/framework/domain/singlemailcontroller.cpp
new file mode 100644
index 00000000..8ee4acbb
--- /dev/null
+++ b/framework/domain/singlemailcontroller.cpp
@@ -0,0 +1,46 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#include "singlemailcontroller.h"
22
23SingleMailController::SingleMailController(QObject *parent) : QObject(parent), m_model(new MailListModel)
24{
25
26}
27
28SingleMailController::~SingleMailController()
29{
30
31}
32
33MailListModel* SingleMailController::model() const
34{
35 return m_model.data();
36}
37
38
39void SingleMailController::loadMail(const QString &id)
40{
41 Sink::Query query;
42 query.liveQuery = false;
43 query.requestedProperties << "subject" << "sender" << "senderName" << "date" << "unread" << "important" << "mimeMessage";
44 query.ids << id.toLatin1();
45 m_model->runQuery(query);
46} \ No newline at end of file
diff --git a/framework/domain/singlemailcontroller.h b/framework/domain/singlemailcontroller.h
new file mode 100644
index 00000000..283b03c4
--- /dev/null
+++ b/framework/domain/singlemailcontroller.h
@@ -0,0 +1,49 @@
1/*
2 Copyright (c) 2016 Michael Bohlender <michael.bohlender@kdemail.net>
3 Copyright (c) 2016 Christian Mollekopf <mollekopf@kolabsys.com>
4
5 This library is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or (at your
8 option) any later version.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301, USA.
19*/
20
21#pragma once
22
23#include "maillistmodel.h"
24
25#include <QObject>
26#include <QString>
27#include <QDateTime>
28#include <QScopedPointer>
29
30class SingleMailController : public QObject
31{
32 Q_OBJECT
33 Q_PROPERTY (MailListModel *model READ model CONSTANT)
34
35public:
36 explicit SingleMailController(QObject *parent = Q_NULLPTR);
37 ~SingleMailController();
38
39 MailListModel *model() const;
40
41Q_SIGNALS:
42 void messageChanged();
43
44public slots:
45 void loadMail(const QString &id);
46
47private:
48 QScopedPointer<MailListModel> m_model;
49};
diff --git a/framework/domain/stringhtmlwriter.cpp b/framework/domain/stringhtmlwriter.cpp
new file mode 100644
index 00000000..df108946
--- /dev/null
+++ b/framework/domain/stringhtmlwriter.cpp
@@ -0,0 +1,145 @@
1/* -*- c++ -*-
2 filehtmlwriter.cpp
3
4 This file is part of KMail, the KDE mail client.
5 Copyright (c) 2003 Marc Mutz <mutz@kde.org>
6
7 KMail is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License, version 2, as
9 published by the Free Software Foundation.
10
11 KMail is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20 In addition, as a special exception, the copyright holders give
21 permission to link the code of this program with any edition of
22 the Qt library by Trolltech AS, Norway (or with modified versions
23 of Qt that use the same license as Qt), and distribute linked
24 combinations including the two. You must obey the GNU General
25 Public License in all respects for all of the code used other than
26 Qt. If you modify this file, you may extend this exception to
27 your version of the file, but you are not obligated to do so. If
28 you do not wish to do so, delete this exception statement from
29 your version.
30*/
31
32#include "stringhtmlwriter.h"
33
34#include <QDebug>
35#include <QTextStream>
36#include <QUrl>
37
38StringHtmlWriter::StringHtmlWriter()
39 : MessageViewer::HtmlWriter()
40 , mState(Ended)
41{
42}
43
44StringHtmlWriter::~StringHtmlWriter()
45{
46}
47
48void StringHtmlWriter::begin(const QString &css)
49{
50 if (mState != Ended) {
51 qWarning() << "begin() called on non-ended session!";
52 reset();
53 }
54
55 mState = Begun;
56 mExtraHead.clear();
57 mHtml.clear();
58
59 if (!css.isEmpty()) {
60 write(QLatin1String("<!-- CSS Definitions \n") + css + QLatin1String("-->\n"));
61 }
62}
63
64void StringHtmlWriter::end()
65{
66 if (mState != Begun) {
67 qWarning() << "Called on non-begun or queued session!";
68 }
69
70 if (!mExtraHead.isEmpty()) {
71 insertExtraHead();
72 mExtraHead.clear();
73 }
74 resolveCidUrls();
75 mState = Ended;
76}
77
78void StringHtmlWriter::reset()
79{
80 if (mState != Ended) {
81 mHtml.clear();
82 mExtraHead.clear();
83 mState = Begun; // don't run into end()'s warning
84 end();
85 mState = Ended;
86 }
87}
88
89void StringHtmlWriter::write(const QString &str)
90{
91 if (mState != Begun) {
92 qWarning() << "Called in Ended or Queued state!";
93 }
94 mHtml.append(str);
95}
96
97void StringHtmlWriter::queue(const QString &str)
98{
99 write(str);
100}
101
102void StringHtmlWriter::flush()
103{
104 mState = Begun; // don't run into end()'s warning
105 end();
106}
107
108void StringHtmlWriter::embedPart(const QByteArray &contentId, const QString &url)
109{
110 write("<!-- embedPart(contentID=" + contentId + ", url=" + url + ") -->\n");
111 mEmbeddedPartMap.insert(contentId, url);
112}
113
114void StringHtmlWriter::resolveCidUrls()
115{
116 for (const auto &cid : mEmbeddedPartMap.keys()) {
117 mHtml.replace(QString("src=\"cid:%1\"").arg(QString(cid)), QString("src=\"%1\"").arg(mEmbeddedPartMap.value(cid).toString()));
118 }
119}
120
121void StringHtmlWriter::extraHead(const QString &extraHead)
122{
123 if (mState != Ended) {
124 qWarning() << "Called on non-started session!";
125 }
126 mExtraHead.append(extraHead);
127}
128
129
130void StringHtmlWriter::insertExtraHead()
131{
132 const QString headTag(QStringLiteral("<head>"));
133 const int index = mHtml.indexOf(headTag);
134 if (index != -1) {
135 mHtml.insert(index + headTag.length(), mExtraHead);
136 }
137}
138
139QString StringHtmlWriter::html() const
140{
141 if (mState != Ended) {
142 qWarning() << "Called on non-ended session!";
143 }
144 return mHtml;
145}
diff --git a/framework/domain/stringhtmlwriter.h b/framework/domain/stringhtmlwriter.h
new file mode 100644
index 00000000..fa0a7aa5
--- /dev/null
+++ b/framework/domain/stringhtmlwriter.h
@@ -0,0 +1,70 @@
1/* -*- c++ -*-
2
3 Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
4
5 Kube is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License, version 2, as
7 published by the Free Software Foundation.
8
9 Kube is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 In addition, as a special exception, the copyright holders give
19 permission to link the code of this program with any edition of
20 the Qt library by Trolltech AS, Norway (or with modified versions
21 of Qt that use the same license as Qt), and distribute linked
22 combinations including the two. You must obey the GNU General
23 Public License in all respects for all of the code used other than
24 Qt. If you modify this file, you may extend this exception to
25 your version of the file, but you are not obligated to do so. If
26 you do not wish to do so, delete this exception statement from
27 your version.
28*/
29
30#ifndef __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__
31#define __KUBE_FRAMEWORK_MAIL_STRINGHTMLWRITER_H__
32
33#include <MessageViewer/HtmlWriter>
34
35#include <QFile>
36#include <QTextStream>
37
38class QString;
39
40class StringHtmlWriter : public MessageViewer::HtmlWriter
41{
42public:
43 explicit StringHtmlWriter();
44 virtual ~StringHtmlWriter();
45
46 void begin(const QString &cssDefs) Q_DECL_OVERRIDE;
47 void end() Q_DECL_OVERRIDE;
48 void reset() Q_DECL_OVERRIDE;
49 void write(const QString &str) Q_DECL_OVERRIDE;
50 void queue(const QString &str) Q_DECL_OVERRIDE;
51 void flush() Q_DECL_OVERRIDE;
52 void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE;
53 void extraHead(const QString &str) Q_DECL_OVERRIDE;
54
55 QString html() const;
56private:
57 void insertExtraHead();
58 void resolveCidUrls();
59
60 QString mHtml;
61 QString mExtraHead;
62 enum State {
63 Begun,
64 Queued,
65 Ended
66 } mState;
67 QMap<QByteArray, QUrl> mEmbeddedPartMap;
68};
69
70#endif // __MESSAGEVIEWER_FILEHTMLWRITER_H__