diff options
Diffstat (limited to 'framework/src/domain/mime/partmodel.cpp')
-rw-r--r-- | framework/src/domain/mime/partmodel.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/framework/src/domain/mime/partmodel.cpp b/framework/src/domain/mime/partmodel.cpp new file mode 100644 index 00000000..b86251ef --- /dev/null +++ b/framework/src/domain/mime/partmodel.cpp | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | Copyright (c) 2016 Sandro Knauß <knauss@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 | #include "partmodel.h" | ||
21 | |||
22 | #include <mimetreeparser/objecttreeparser.h> | ||
23 | #include "htmlutils.h" | ||
24 | |||
25 | #include <QDebug> | ||
26 | #include <QMimeDatabase> | ||
27 | #include <QTextDocument> | ||
28 | |||
29 | class PartModelPrivate | ||
30 | { | ||
31 | public: | ||
32 | PartModelPrivate(PartModel *q_ptr, const std::shared_ptr<MimeTreeParser::ObjectTreeParser> &parser); | ||
33 | ~PartModelPrivate(); | ||
34 | |||
35 | void createTree(); | ||
36 | PartModel *q; | ||
37 | QVector<MimeTreeParser::MessagePartPtr> mParts; | ||
38 | std::shared_ptr<MimeTreeParser::ObjectTreeParser> mParser; | ||
39 | }; | ||
40 | |||
41 | PartModelPrivate::PartModelPrivate(PartModel *q_ptr, const std::shared_ptr<MimeTreeParser::ObjectTreeParser> &parser) | ||
42 | : q(q_ptr) | ||
43 | , mParser(parser) | ||
44 | { | ||
45 | mParts = mParser->collectContentParts(); | ||
46 | qWarning() << "Collected content parts: " << mParts.size(); | ||
47 | } | ||
48 | |||
49 | PartModelPrivate::~PartModelPrivate() | ||
50 | { | ||
51 | } | ||
52 | |||
53 | PartModel::PartModel(std::shared_ptr<MimeTreeParser::ObjectTreeParser> parser) | ||
54 | : d(std::unique_ptr<PartModelPrivate>(new PartModelPrivate(this, parser))) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | PartModel::~PartModel() | ||
59 | { | ||
60 | } | ||
61 | |||
62 | QHash<int, QByteArray> PartModel::roleNames() const | ||
63 | { | ||
64 | QHash<int, QByteArray> roles; | ||
65 | roles[TypeRole] = "type"; | ||
66 | roles[ContentRole] = "content"; | ||
67 | roles[IsEmbededRole] = "embeded"; | ||
68 | roles[IsEncryptedRole] = "encrypted"; | ||
69 | roles[IsSignedRole] = "signed"; | ||
70 | roles[SecurityLevelRole] = "securityLevel"; | ||
71 | roles[EncryptionErrorType] = "errorType"; | ||
72 | roles[EncryptionErrorString] = "errorString"; | ||
73 | roles[IsErrorRole] = "error"; | ||
74 | return roles; | ||
75 | } | ||
76 | |||
77 | QModelIndex PartModel::index(int row, int column, const QModelIndex &parent) const | ||
78 | { | ||
79 | if (row < 0 || column != 0) { | ||
80 | return QModelIndex(); | ||
81 | } | ||
82 | if (row < d->mParts.size()) { | ||
83 | return createIndex(row, column, d->mParts.at(row).data()); | ||
84 | } | ||
85 | return QModelIndex(); | ||
86 | } | ||
87 | |||
88 | QVariant PartModel::data(const QModelIndex &index, int role) const | ||
89 | { | ||
90 | if (!index.isValid()) { | ||
91 | switch (role) { | ||
92 | case Qt::DisplayRole: | ||
93 | return QString("root"); | ||
94 | case IsEmbededRole: | ||
95 | return false; | ||
96 | } | ||
97 | return QVariant(); | ||
98 | } | ||
99 | |||
100 | if (index.internalPointer()) { | ||
101 | const auto messagePart = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer()); | ||
102 | qWarning() << "Found message part " << messagePart->metaObject()->className() << messagePart->partMetaData()->status << messagePart->error(); | ||
103 | Q_ASSERT(messagePart); | ||
104 | switch(role) { | ||
105 | case Qt::DisplayRole: | ||
106 | return QStringLiteral("Content%1"); | ||
107 | case TypeRole: { | ||
108 | if (messagePart->error()) { | ||
109 | return "error"; | ||
110 | } | ||
111 | //For simple html we don't need a browser | ||
112 | auto complexHtml = [&] { | ||
113 | if (messagePart->isHtml()) { | ||
114 | const auto text = messagePart->text(); | ||
115 | if (text.contains("<!DOCTYPE html PUBLIC")) { | ||
116 | return true; | ||
117 | } | ||
118 | //Media queries are too advanced | ||
119 | if (text.contains("@media")) { | ||
120 | return true; | ||
121 | } | ||
122 | if (text.contains("<style")) { | ||
123 | return true; | ||
124 | } | ||
125 | return false; | ||
126 | } else { | ||
127 | return false; | ||
128 | } | ||
129 | }(); | ||
130 | if (complexHtml) { | ||
131 | return "html"; | ||
132 | } | ||
133 | return "plain"; | ||
134 | } | ||
135 | case IsEmbededRole: | ||
136 | return false; | ||
137 | case IsErrorRole: | ||
138 | return messagePart->error(); | ||
139 | case ContentRole: { | ||
140 | auto errorText = messagePart->partMetaData()->errorText; | ||
141 | if (!errorText.isEmpty()) { | ||
142 | return errorText; | ||
143 | } | ||
144 | const auto text = messagePart->isHtml() ? messagePart->htmlContent() : messagePart->text(); | ||
145 | if (messagePart->isHtml()) { | ||
146 | return d->mParser->resolveCidLinks(text); | ||
147 | } else { //We assume plain | ||
148 | //We alwas do richtext (so we get highlighted links and stuff). | ||
149 | return HtmlUtils::linkify(Qt::convertFromPlainText(text)); | ||
150 | } | ||
151 | return text; | ||
152 | } | ||
153 | case IsEncryptedRole: | ||
154 | return messagePart->encryptions().size() > 0; | ||
155 | case IsSignedRole: | ||
156 | return messagePart->signatures().size() > 0; | ||
157 | case EncryptionErrorType: | ||
158 | return messagePart->error(); | ||
159 | case EncryptionErrorString: | ||
160 | return messagePart->errorString(); | ||
161 | } | ||
162 | } | ||
163 | return QVariant(); | ||
164 | } | ||
165 | |||
166 | QModelIndex PartModel::parent(const QModelIndex &index) const | ||
167 | { | ||
168 | return QModelIndex(); | ||
169 | } | ||
170 | |||
171 | int PartModel::rowCount(const QModelIndex &parent) const | ||
172 | { | ||
173 | return d->mParts.count(); | ||
174 | } | ||
175 | |||
176 | int PartModel::columnCount(const QModelIndex &parent) const | ||
177 | { | ||
178 | return 1; | ||
179 | } | ||