summaryrefslogtreecommitdiffstats
path: root/framework/src/domain/mime/attachmentmodel.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-05-29 16:17:04 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-06-04 12:57:04 +0200
commite452707fdfbd61be1e5633b516b653b7337e7865 (patch)
tree1e1d4b48ebf8d381f292436f2ba04b8763edc5de /framework/src/domain/mime/attachmentmodel.cpp
parent5a1033bdace740799a6e03389bee30e5a4de5d44 (diff)
downloadkube-e452707fdfbd61be1e5633b516b653b7337e7865.tar.gz
kube-e452707fdfbd61be1e5633b516b653b7337e7865.zip
Reduced the messagetreeparser to aproximately what we actually require
While in a much more managable state it's still not pretty. However, further refactoring can now gradually happen as we need to do further work on it. Things that should happen eventually: * Simplify the logic that creates the messageparts (we don't need the whole formatter plugin complexity) * Get rid of the nodehelper (let the parts hold the necessary data) * Get rid of partmetadata (let the part handleit)
Diffstat (limited to 'framework/src/domain/mime/attachmentmodel.cpp')
-rw-r--r--framework/src/domain/mime/attachmentmodel.cpp76
1 files changed, 46 insertions, 30 deletions
diff --git a/framework/src/domain/mime/attachmentmodel.cpp b/framework/src/domain/mime/attachmentmodel.cpp
index 99745796..68180afe 100644
--- a/framework/src/domain/mime/attachmentmodel.cpp
+++ b/framework/src/domain/mime/attachmentmodel.cpp
@@ -1,5 +1,6 @@
1/* 1/*
2 Copyright (c) 2016 Sandro Knauß <knauss@kolabsys.com> 2 Copyright (c) 2016 Sandro Knauß <knauss@kolabsys.com>
3 Copyright (c) 2017 Christian Mollekopf <mollekopf@kolabsys.com>
3 4
4 This library is free software; you can redistribute it and/or modify it 5 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 under the terms of the GNU Library General Public License as published by
@@ -17,8 +18,9 @@
17 02110-1301, USA. 18 02110-1301, USA.
18*/ 19*/
19 20
20#include "messageparser.h" 21#include "attachmentmodel.h"
21#include "mimetreeparser/interface.h" 22
23#include <mimetreeparser/objecttreeparser.h>
22 24
23#include <QDebug> 25#include <QDebug>
24#include <KMime/Content> 26#include <KMime/Content>
@@ -26,47 +28,48 @@
26#include <QStandardPaths> 28#include <QStandardPaths>
27#include <QDesktopServices> 29#include <QDesktopServices>
28#include <QDir> 30#include <QDir>
31#include <QUrl>
32#include <QMimeDatabase>
29 33
30QString sizeHuman(const Content::Ptr &content) 34QString sizeHuman(float size)
31{ 35{
32 float num = content->content().size();
33 QStringList list; 36 QStringList list;
34 list << "KB" << "MB" << "GB" << "TB"; 37 list << "KB" << "MB" << "GB" << "TB";
35 38
36 QStringListIterator i(list); 39 QStringListIterator i(list);
37 QString unit("Bytes"); 40 QString unit("Bytes");
38 41
39 while(num >= 1024.0 && i.hasNext()) 42 while(size >= 1024.0 && i.hasNext())
40 { 43 {
41 unit = i.next(); 44 unit = i.next();
42 num /= 1024.0; 45 size /= 1024.0;
43 } 46 }
44 47
45 if (unit == "Bytes") { 48 if (unit == "Bytes") {
46 return QString().setNum(num) + " " + unit; 49 return QString().setNum(size) + " " + unit;
47 } else { 50 } else {
48 return QString().setNum(num,'f',2)+" "+unit; 51 return QString().setNum(size,'f',2)+" "+unit;
49 } 52 }
50} 53}
51 54
52class AttachmentModelPrivate 55class AttachmentModelPrivate
53{ 56{
54public: 57public:
55 AttachmentModelPrivate(AttachmentModel *q_ptr, const std::shared_ptr<Parser> &parser); 58 AttachmentModelPrivate(AttachmentModel *q_ptr, const std::shared_ptr<MimeTreeParser::ObjectTreeParser> &parser);
56 59
57 AttachmentModel *q; 60 AttachmentModel *q;
58 std::shared_ptr<Parser> mParser; 61 std::shared_ptr<MimeTreeParser::ObjectTreeParser> mParser;
59 QVector<Part::Ptr> mAttachments; 62 QVector<MimeTreeParser::MessagePartPtr> mAttachments;
60}; 63};
61 64
62AttachmentModelPrivate::AttachmentModelPrivate(AttachmentModel* q_ptr, const std::shared_ptr<Parser>& parser) 65AttachmentModelPrivate::AttachmentModelPrivate(AttachmentModel* q_ptr, const std::shared_ptr<MimeTreeParser::ObjectTreeParser>& parser)
63 : q(q_ptr) 66 : q(q_ptr)
64 , mParser(parser) 67 , mParser(parser)
65{ 68{
66 mAttachments = mParser->collectAttachmentParts(); 69 mAttachments = mParser->collectAttachmentParts();
67} 70}
68 71
69AttachmentModel::AttachmentModel(std::shared_ptr<Parser> parser) 72AttachmentModel::AttachmentModel(std::shared_ptr<MimeTreeParser::ObjectTreeParser> parser)
70 : d(std::unique_ptr<AttachmentModelPrivate>(new AttachmentModelPrivate(this, parser))) 73 : d(std::unique_ptr<AttachmentModelPrivate>(new AttachmentModelPrivate(this, parser)))
71{ 74{
72} 75}
@@ -94,7 +97,7 @@ QModelIndex AttachmentModel::index(int row, int column, const QModelIndex &paren
94 } 97 }
95 98
96 if (row < d->mAttachments.size()) { 99 if (row < d->mAttachments.size()) {
97 return createIndex(row, column, d->mAttachments.at(row).get()); 100 return createIndex(row, column, d->mAttachments.at(row).data());
98 } 101 }
99 return QModelIndex(); 102 return QModelIndex();
100} 103}
@@ -110,44 +113,57 @@ QVariant AttachmentModel::data(const QModelIndex &index, int role) const
110 } 113 }
111 114
112 if (index.internalPointer()) { 115 if (index.internalPointer()) {
113 const auto entry = static_cast<Part *>(index.internalPointer()); 116 const auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer());
114 const auto content = entry->content().at(0); 117 Q_ASSERT(part);
118 auto node = part->node();
119 if (!node) {
120 qWarning() << "no content for attachment";
121 return {};
122 }
123 QMimeDatabase mimeDb;
124 const auto mimetype = mimeDb.mimeTypeForName(QString::fromLatin1(part->mimeType()));
125 const auto content = node->encodedContent();
115 switch(role) { 126 switch(role) {
116 case TypeRole: 127 case TypeRole:
117 return content->mailMime()->mimetype().name(); 128 return mimetype.name();
118 case NameRole: 129 case NameRole:
119 return entry->mailMime()->filename(); 130 return part->filename();
120 case IconRole: 131 case IconRole:
121 return content->mailMime()->mimetype().iconName(); 132 return mimetype.iconName();
122 case SizeRole: 133 case SizeRole:
123 return sizeHuman(content); 134 return sizeHuman(content.size());
124 case IsEncryptedRole: 135 case IsEncryptedRole:
125 return content->encryptions().size() > 0; 136 return part->encryptions().size() > 0;
126 case IsSignedRole: 137 case IsSignedRole:
127 return content->signatures().size() > 0; 138 return part->signatures().size() > 0;
128 } 139 }
129 } 140 }
130 return QVariant(); 141 return QVariant();
131} 142}
132 143
133static QString saveAttachmentToDisk(const QModelIndex &index, const QString &path) 144static QString saveAttachmentToDisk(const QModelIndex &index, const QString &path, bool readonly = false)
134{ 145{
135 if (index.internalPointer()) { 146 if (index.internalPointer()) {
136 const auto entry = static_cast<Part *>(index.internalPointer()); 147 const auto part = static_cast<MimeTreeParser::MessagePart*>(index.internalPointer());
137 const auto content = entry->content().at(0); 148 Q_ASSERT(part);
138 auto filename = entry->mailMime()->filename(); 149 auto node = part->node();
139 auto data = content->mailMime()->decodedContent(); 150 auto data = node->decodedContent();
140 if (content->mailMime()->isText() && !data.isEmpty()) { 151 if (part->isText()) {
141 // convert CRLF to LF before writing text attachments to disk 152 // convert CRLF to LF before writing text attachments to disk
142 data = KMime::CRLFtoLF(data); 153 data = KMime::CRLFtoLF(data);
143 } 154 }
144 auto fname = path + filename; 155 auto fname = path + part->filename();
145 QFile f(fname); 156 QFile f(fname);
146 if (!f.open(QIODevice::ReadWrite)) { 157 if (!f.open(QIODevice::ReadWrite)) {
147 qWarning() << "Failed to write attachment to file:" << fname << " Error: " << f.errorString(); 158 qWarning() << "Failed to write attachment to file:" << fname << " Error: " << f.errorString();
148 return {}; 159 return {};
149 } 160 }
150 f.write(data); 161 f.write(data);
162 if (readonly) {
163 // make file read-only so that nobody gets the impression that he migh edit attached files
164 f.setPermissions(QFileDevice::ReadUser);
165 }
166 f.close();
151 qInfo() << "Wrote attachment to file: " << fname; 167 qInfo() << "Wrote attachment to file: " << fname;
152 return fname; 168 return fname;
153 } 169 }
@@ -170,7 +186,7 @@ bool AttachmentModel::openAttachment(const QModelIndex &index)
170{ 186{
171 auto downloadDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation)+ "/kube/"; 187 auto downloadDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation)+ "/kube/";
172 QDir{}.mkpath(downloadDir); 188 QDir{}.mkpath(downloadDir);
173 const auto filePath = ::saveAttachmentToDisk(index, downloadDir); 189 const auto filePath = ::saveAttachmentToDisk(index, downloadDir, true);
174 if (!filePath.isEmpty()) { 190 if (!filePath.isEmpty()) {
175 QDesktopServices::openUrl(QUrl("file://" + filePath)); 191 QDesktopServices::openUrl(QUrl("file://" + filePath));
176 return true; 192 return true;