summaryrefslogtreecommitdiffstats
path: root/framework/src/domain/mime/partmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/domain/mime/partmodel.cpp')
-rw-r--r--framework/src/domain/mime/partmodel.cpp179
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
29class PartModelPrivate
30{
31public:
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
41PartModelPrivate::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
49PartModelPrivate::~PartModelPrivate()
50{
51}
52
53PartModel::PartModel(std::shared_ptr<MimeTreeParser::ObjectTreeParser> parser)
54 : d(std::unique_ptr<PartModelPrivate>(new PartModelPrivate(this, parser)))
55{
56}
57
58PartModel::~PartModel()
59{
60}
61
62QHash<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
77QModelIndex 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
88QVariant 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
166QModelIndex PartModel::parent(const QModelIndex &index) const
167{
168 return QModelIndex();
169}
170
171int PartModel::rowCount(const QModelIndex &parent) const
172{
173 return d->mParts.count();
174}
175
176int PartModel::columnCount(const QModelIndex &parent) const
177{
178 return 1;
179}