diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-12-04 00:02:58 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-12-04 10:19:23 +0100 |
commit | 243f18fed2ee9b8f2778e83ee4fbe2b3275b0370 (patch) | |
tree | ac60f61ad7aaf9c997410ae2f7dcab1a128e157a /framework/src/domain/composercontroller.cpp | |
parent | 8455e38d9269cfeeb33cbf123688e19186c8be4c (diff) | |
download | kube-243f18fed2ee9b8f2778e83ee4fbe2b3275b0370.tar.gz kube-243f18fed2ee9b8f2778e83ee4fbe2b3275b0370.zip |
Subcontrollers for list properties
Diffstat (limited to 'framework/src/domain/composercontroller.cpp')
-rw-r--r-- | framework/src/domain/composercontroller.cpp | 426 |
1 files changed, 127 insertions, 299 deletions
diff --git a/framework/src/domain/composercontroller.cpp b/framework/src/domain/composercontroller.cpp index f1e84019..d09dcd79 100644 --- a/framework/src/domain/composercontroller.cpp +++ b/framework/src/domain/composercontroller.cpp | |||
@@ -41,7 +41,11 @@ | |||
41 | #include "mime/mailtemplates.h" | 41 | #include "mime/mailtemplates.h" |
42 | #include "mime/mailcrypto.h" | 42 | #include "mime/mailcrypto.h" |
43 | 43 | ||
44 | Q_DECLARE_METATYPE(GpgME::Key); | 44 | std::vector<GpgME::Key> &operator+=(std::vector<GpgME::Key> &list, const std::vector<GpgME::Key> &add) |
45 | { | ||
46 | list.insert(std::end(list), std::begin(add), std::end(add)); | ||
47 | return list; | ||
48 | } | ||
45 | 49 | ||
46 | class IdentitySelector : public Selector { | 50 | class IdentitySelector : public Selector { |
47 | public: | 51 | public: |
@@ -93,14 +97,6 @@ public: | |||
93 | } | 97 | } |
94 | }; | 98 | }; |
95 | 99 | ||
96 | static void traverse(const QStandardItemModel *model, const std::function<void(QStandardItem *item)> &f) | ||
97 | { | ||
98 | auto root = model->invisibleRootItem(); | ||
99 | for (int row = 0; row < root->rowCount(); row++) { | ||
100 | f(root->child(row, 0)); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | template<typename T> | 100 | template<typename T> |
105 | void asyncRun(QObject *object, std::function<T()> run, std::function<void(T)> continuation) | 101 | void asyncRun(QObject *object, std::function<T()> run, std::function<void(T)> continuation) |
106 | { | 102 | { |
@@ -116,33 +112,22 @@ void asyncRun(QObject *object, std::function<T()> run, std::function<void(T)> co | |||
116 | watcher->setFuture(future); | 112 | watcher->setFuture(future); |
117 | } | 113 | } |
118 | 114 | ||
119 | class AddresseeModel : public QStandardItemModel | 115 | class AddresseeController : public Kube::ListPropertyController |
120 | { | 116 | { |
121 | public: | 117 | public: |
122 | AddresseeModel() | ||
123 | :QStandardItemModel() | ||
124 | { | ||
125 | setItemRoleNames({{ComposerController::AddresseeNameRole, "addresseeName"}, | ||
126 | {ComposerController::KeyFoundRole, "keyFound"}, | ||
127 | {ComposerController::KeyMissingRole, "keyMissing"}, | ||
128 | {ComposerController::KeyRole, "key"}}); | ||
129 | } | ||
130 | 118 | ||
131 | void add(const QString &addressee) | 119 | QSet<QByteArray> mMissingKeys; |
120 | AddresseeController() | ||
121 | : Kube::ListPropertyController{{"name", "keyFound", "key"}} | ||
132 | { | 122 | { |
133 | auto item = new QStandardItem; | 123 | QObject::connect(this, &Kube::ListPropertyController::added, this, [this] (const QByteArray &id, const QVariantMap &map) { |
134 | item->setText(addressee); | 124 | findKey(id, map.value("name").toString()); |
135 | item->setData(QVariant::fromValue(addressee), ComposerController::AddresseeNameRole); | 125 | }); |
136 | item->setData(false, ComposerController::KeyFoundRole); | ||
137 | item->setData(mCryptoEnabled, ComposerController::KeyMissingRole); | ||
138 | appendRow(QList<QStandardItem*>() << item); | ||
139 | if (mCryptoEnabled) { | ||
140 | findKey(addressee); | ||
141 | } | ||
142 | } | 126 | } |
143 | 127 | ||
144 | void findKey(const QString &addressee) | 128 | void findKey(const QByteArray &id, const QString &addressee) |
145 | { | 129 | { |
130 | mMissingKeys << id; | ||
146 | KMime::Types::Mailbox mb; | 131 | KMime::Types::Mailbox mb; |
147 | mb.fromUnicodeString(addressee); | 132 | mb.fromUnicodeString(addressee); |
148 | 133 | ||
@@ -150,126 +135,88 @@ public: | |||
150 | asyncRun<std::vector<GpgME::Key>>(this, [mb] { | 135 | asyncRun<std::vector<GpgME::Key>>(this, [mb] { |
151 | return MailCrypto::findKeys(QStringList{} << mb.address(), false, false, MailCrypto::OPENPGP); | 136 | return MailCrypto::findKeys(QStringList{} << mb.address(), false, false, MailCrypto::OPENPGP); |
152 | }, | 137 | }, |
153 | [this, addressee](const std::vector<GpgME::Key> &keys) { | 138 | [this, addressee, id](const std::vector<GpgME::Key> &keys) { |
154 | if (!keys.empty()) { | 139 | if (!keys.empty()) { |
155 | if (keys.size() > 1 ) { | 140 | if (keys.size() > 1 ) { |
156 | SinkWarning() << "Found more than one key, encrypting to all of them."; | 141 | SinkWarning() << "Found more than one key, encrypting to all of them."; |
157 | } | 142 | } |
158 | SinkLog() << "Found key: " << keys.front().primaryFingerprint(); | 143 | SinkLog() << "Found key: " << keys.front().primaryFingerprint(); |
159 | for (auto item : findItems(addressee)) { | 144 | setValue(id, "keyFound", true); |
160 | item->setData(true, ComposerController::KeyFoundRole); | 145 | setValue(id, "key", QVariant::fromValue(keys)); |
161 | item->setData(QVariant::fromValue(keys), ComposerController::KeyRole); | 146 | mMissingKeys.remove(id); |
162 | } | 147 | setProperty("foundAllKeys", mMissingKeys.isEmpty()); |
163 | } else { | 148 | } else { |
164 | SinkWarning() << "Failed to find key for recipient."; | 149 | SinkWarning() << "Failed to find key for recipient."; |
165 | } | 150 | } |
166 | }); | 151 | }); |
167 | } | 152 | } |
168 | 153 | ||
169 | void remove(const QString &addressee) | 154 | void set(const QStringList &list) |
170 | { | 155 | { |
171 | auto root = invisibleRootItem(); | 156 | for (const auto &email: list) { |
172 | for (int row = 0; row < root->rowCount(); row++) { | 157 | add({{"name", email}}); |
173 | if (root->child(row, 0)->text() == addressee) { | ||
174 | root->removeRow(row); | ||
175 | return; | ||
176 | } | ||
177 | } | 158 | } |
178 | } | 159 | } |
160 | }; | ||
179 | 161 | ||
180 | bool foundAllKeys() | 162 | class AttachmentController : public Kube::ListPropertyController |
181 | { | 163 | { |
182 | std::vector<GpgME::Key> keys; | 164 | public: |
183 | auto root = invisibleRootItem(); | ||
184 | for (int row = 0; row < root->rowCount(); row++) { | ||
185 | auto item = root->child(row, 0); | ||
186 | if (!item->data(ComposerController::KeyFoundRole).toBool()) { | ||
187 | return false; | ||
188 | } | ||
189 | } | ||
190 | return true; | ||
191 | } | ||
192 | 165 | ||
193 | std::vector<GpgME::Key> getKeys() | 166 | AttachmentController() |
167 | : Kube::ListPropertyController{{"name", "filename", "content", "mimetype", "description", "iconname", "url", "inline"}} | ||
194 | { | 168 | { |
195 | std::vector<GpgME::Key> keys; | 169 | QObject::connect(this, &Kube::ListPropertyController::added, this, [this] (const QByteArray &id, const QVariantMap &map) { |
196 | traverse(this, [&] (QStandardItem *item) { | 170 | auto url = map.value("url").toUrl(); |
197 | auto l = item->data(ComposerController::KeyRole).value<std::vector<GpgME::Key>>(); | 171 | setAttachmentProperties(id, url); |
198 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | ||
199 | }); | 172 | }); |
200 | return keys; | ||
201 | } | 173 | } |
202 | 174 | ||
203 | void setStringList(const QStringList &list) | 175 | void setAttachmentProperties(const QByteArray &id, const QUrl &url) |
204 | { | 176 | { |
205 | clear(); | 177 | QMimeDatabase db; |
206 | for (const auto &s : list) { | 178 | auto mimeType = db.mimeTypeForUrl(url); |
207 | add(s); | 179 | if (mimeType.name() == QLatin1String("inode/directory")) { |
208 | } | 180 | qWarning() << "Can't deal with directories yet."; |
209 | } | 181 | } else { |
210 | 182 | if (!url.isLocalFile()) { | |
211 | QStringList stringList() const | 183 | qWarning() << "Cannot attach remote file: " << url; |
212 | { | 184 | return; |
213 | QStringList list; | 185 | } |
214 | traverse(this, [&] (QStandardItem *item) { | ||
215 | list << item->text(); | ||
216 | }); | ||
217 | return list; | ||
218 | } | ||
219 | 186 | ||
220 | void setCryptoEnabled(bool enabled) | 187 | QFileInfo fileInfo(url.toLocalFile()); |
221 | { | 188 | if (!fileInfo.exists()) { |
222 | mCryptoEnabled = enabled; | 189 | qWarning() << "The file doesn't exist: " << url; |
223 | traverse(this, [&] (QStandardItem *item) { | ||
224 | item->setData(mCryptoEnabled, ComposerController::KeyMissingRole); | ||
225 | if (mCryptoEnabled) { | ||
226 | findKey(item->text()); | ||
227 | } | 190 | } |
228 | }); | ||
229 | } | ||
230 | 191 | ||
231 | bool mCryptoEnabled = false; | 192 | QFile file{fileInfo.filePath()}; |
193 | file.open(QIODevice::ReadOnly); | ||
194 | const auto data = file.readAll(); | ||
195 | QVariantMap map; | ||
196 | map.insert("filename", fileInfo.fileName()); | ||
197 | map.insert("mimetype", mimeType.name().toLatin1()); | ||
198 | map.insert("filename", fileInfo.fileName().toLatin1()); | ||
199 | map.insert("inline", false); | ||
200 | map.insert("iconname", mimeType.iconName()); | ||
201 | map.insert("url", url); | ||
202 | map.insert("content", data); | ||
203 | setValues(id, map); | ||
204 | } | ||
205 | } | ||
232 | }; | 206 | }; |
233 | 207 | ||
234 | |||
235 | ComposerController::ComposerController() | 208 | ComposerController::ComposerController() |
236 | : Kube::Controller(), | 209 | : Kube::Controller(), |
210 | controller_to{new AddresseeController}, | ||
211 | controller_cc{new AddresseeController}, | ||
212 | controller_bcc{new AddresseeController}, | ||
213 | controller_attachments{new AttachmentController}, | ||
237 | action_send{new Kube::ControllerAction{this, &ComposerController::send}}, | 214 | action_send{new Kube::ControllerAction{this, &ComposerController::send}}, |
238 | action_saveAsDraft{new Kube::ControllerAction{this, &ComposerController::saveAsDraft}}, | 215 | action_saveAsDraft{new Kube::ControllerAction{this, &ComposerController::saveAsDraft}}, |
239 | mRecipientCompleter{new RecipientCompleter}, | 216 | mRecipientCompleter{new RecipientCompleter}, |
240 | mIdentitySelector{new IdentitySelector{*this}}, | 217 | mIdentitySelector{new IdentitySelector{*this}} |
241 | mToModel{new AddresseeModel}, | ||
242 | mCcModel{new AddresseeModel}, | ||
243 | mBccModel{new AddresseeModel}, | ||
244 | mAttachmentModel{new QStandardItemModel} | ||
245 | { | 218 | { |
246 | mAttachmentModel->setItemRoleNames({{NameRole, "name"}, | ||
247 | {FilenameRole, "filename"}, | ||
248 | {ContentRole, "content"}, | ||
249 | {MimeTypeRole, "mimetype"}, | ||
250 | {DescriptionRole, "description"}, | ||
251 | {IconNameRole, "iconName"}, | ||
252 | {UrlRole, "url"}, | ||
253 | {InlineRole, "inline"}}); | ||
254 | updateSaveAsDraftAction(); | ||
255 | // mSendAction->monitorProperty<To>(); | ||
256 | // mSendAction->monitorProperty<Send>([] (const QString &) -> bool{ | ||
257 | // //validate | ||
258 | // }); | ||
259 | // registerAction<ControllerAction>(&ComposerController::send); | ||
260 | // actionDepends<ControllerAction, To, Subject>(); | ||
261 | // TODO do in constructor | ||
262 | |||
263 | QObject::connect(this, &ComposerController::subjectChanged, &ComposerController::updateSendAction); | ||
264 | QObject::connect(this, &ComposerController::accountIdChanged, &ComposerController::updateSendAction); | ||
265 | QObject::connect(this, &ComposerController::subjectChanged, &ComposerController::updateSaveAsDraftAction); | ||
266 | QObject::connect(this, &ComposerController::accountIdChanged, &ComposerController::updateSaveAsDraftAction); | ||
267 | QObject::connect(this, &ComposerController::identityChanged, &ComposerController::findPersonalKey); | 219 | QObject::connect(this, &ComposerController::identityChanged, &ComposerController::findPersonalKey); |
268 | updateSendAction(); | ||
269 | |||
270 | QObject::connect(this, &ComposerController::encryptChanged, [&] () { mToModel->setCryptoEnabled(getEncrypt()); }); | ||
271 | QObject::connect(this, &ComposerController::encryptChanged, [&] () { mCcModel->setCryptoEnabled(getEncrypt()); }); | ||
272 | QObject::connect(this, &ComposerController::encryptChanged, [&] () { mBccModel->setCryptoEnabled(getEncrypt()); }); | ||
273 | } | 220 | } |
274 | 221 | ||
275 | void ComposerController::findPersonalKey() | 222 | void ComposerController::findPersonalKey() |
@@ -280,18 +227,17 @@ void ComposerController::findPersonalKey() | |||
280 | return MailCrypto::findKeys(QStringList{} << identity.address(), true); | 227 | return MailCrypto::findKeys(QStringList{} << identity.address(), true); |
281 | }, | 228 | }, |
282 | [this](const std::vector<GpgME::Key> &keys) { | 229 | [this](const std::vector<GpgME::Key> &keys) { |
283 | mPersonalKeys = keys; | 230 | if (keys.empty()) { |
284 | if (mPersonalKeys.empty()) { | ||
285 | SinkWarning() << "Failed to find a personal key."; | 231 | SinkWarning() << "Failed to find a personal key."; |
286 | } | 232 | } |
287 | if (mPersonalKeys.size() > 1) { | 233 | if (keys.size() > 1) { |
288 | SinkWarning() << "Found multiple keys, using first one:"; | 234 | SinkWarning() << "Found multiple keys, using first one:"; |
289 | SinkWarning() << " " << mPersonalKeys.front().primaryFingerprint(); | 235 | SinkWarning() << " " << keys.front().primaryFingerprint(); |
290 | } else { | 236 | } else { |
291 | SinkLog() << "Found personal key: " << mPersonalKeys.front().primaryFingerprint(); | 237 | SinkLog() << "Found personal key: " << keys.front().primaryFingerprint(); |
292 | } | 238 | } |
293 | updateSendAction(); | 239 | setPersonalKeys(QVariant::fromValue(keys)); |
294 | setEncryptionAvailable(!mPersonalKeys.empty()); | 240 | setFoundPersonalKeys(!keys.empty()); |
295 | }); | 241 | }); |
296 | } | 242 | } |
297 | 243 | ||
@@ -300,111 +246,10 @@ void ComposerController::clear() | |||
300 | Controller::clear(); | 246 | Controller::clear(); |
301 | //Reapply account and identity from selection | 247 | //Reapply account and identity from selection |
302 | mIdentitySelector->reapplyCurrentIndex(); | 248 | mIdentitySelector->reapplyCurrentIndex(); |
303 | mToModel->clear(); | 249 | //FIXME implement in Controller::clear instead |
304 | mCcModel->clear(); | 250 | toController()->clear(); |
305 | mBccModel->clear(); | 251 | ccController()->clear(); |
306 | } | 252 | bccController()->clear(); |
307 | |||
308 | QAbstractItemModel *ComposerController::toModel() const | ||
309 | { | ||
310 | return mToModel.data(); | ||
311 | } | ||
312 | |||
313 | void ComposerController::addTo(const QString &s) | ||
314 | { | ||
315 | mToModel->add(s); | ||
316 | updateSendAction(); | ||
317 | } | ||
318 | |||
319 | void ComposerController::removeTo(const QString &s) | ||
320 | { | ||
321 | mToModel->remove(s); | ||
322 | updateSendAction(); | ||
323 | } | ||
324 | |||
325 | QAbstractItemModel *ComposerController::ccModel() const | ||
326 | { | ||
327 | return mCcModel.data(); | ||
328 | } | ||
329 | |||
330 | void ComposerController::addCc(const QString &s) | ||
331 | { | ||
332 | mCcModel->add(s); | ||
333 | updateSendAction(); | ||
334 | } | ||
335 | |||
336 | void ComposerController::removeCc(const QString &s) | ||
337 | { | ||
338 | mCcModel->remove(s); | ||
339 | updateSendAction(); | ||
340 | } | ||
341 | |||
342 | QAbstractItemModel *ComposerController::bccModel() const | ||
343 | { | ||
344 | return mBccModel.data(); | ||
345 | } | ||
346 | |||
347 | void ComposerController::addBcc(const QString &s) | ||
348 | { | ||
349 | mBccModel->add(s); | ||
350 | updateSendAction(); | ||
351 | } | ||
352 | |||
353 | void ComposerController::removeBcc(const QString &s) | ||
354 | { | ||
355 | mBccModel->remove(s); | ||
356 | updateSendAction(); | ||
357 | } | ||
358 | |||
359 | QAbstractItemModel *ComposerController::attachmentModel() const | ||
360 | { | ||
361 | return mAttachmentModel.data(); | ||
362 | } | ||
363 | |||
364 | void ComposerController::addAttachment(const QUrl &url) | ||
365 | { | ||
366 | QMimeDatabase db; | ||
367 | auto mimeType = db.mimeTypeForUrl(url); | ||
368 | if (mimeType.name() == QLatin1String("inode/directory")) { | ||
369 | qWarning() << "Can't deal with directories yet."; | ||
370 | } else { | ||
371 | if (!url.isLocalFile()) { | ||
372 | qWarning() << "Cannot attach remote file: " << url; | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | QFileInfo fileInfo(url.toLocalFile()); | ||
377 | if (!fileInfo.exists()) { | ||
378 | qWarning() << "The file doesn't exist: " << url; | ||
379 | } | ||
380 | |||
381 | QFile file{fileInfo.filePath()}; | ||
382 | file.open(QIODevice::ReadOnly); | ||
383 | const auto data = file.readAll(); | ||
384 | auto item = new QStandardItem; | ||
385 | item->setData(fileInfo.fileName(), NameRole); | ||
386 | item->setData(mimeType.name().toLatin1(), MimeTypeRole); | ||
387 | item->setData(fileInfo.fileName(), FilenameRole); | ||
388 | item->setData(false, InlineRole); | ||
389 | item->setData(mimeType.iconName(), IconNameRole); | ||
390 | item->setData(url, UrlRole); | ||
391 | item->setData(data, ContentRole); | ||
392 | mAttachmentModel->appendRow(item); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | void ComposerController::removeAttachment(const QUrl &url) | ||
397 | { | ||
398 | auto root = mAttachmentModel->invisibleRootItem(); | ||
399 | if (root->hasChildren()) { | ||
400 | for (int row = 0; row < root->rowCount(); row++) { | ||
401 | auto item = root->child(row, 0); | ||
402 | if (url == item->data(UrlRole).toUrl()) { | ||
403 | root->removeRow(row); | ||
404 | return; | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | } | 253 | } |
409 | 254 | ||
410 | Completer *ComposerController::recipientCompleter() const | 255 | Completer *ComposerController::recipientCompleter() const |
@@ -450,24 +295,23 @@ static QStringList getStringListFromAddresses(const KMime::Types::Mailbox::List | |||
450 | 295 | ||
451 | void ComposerController::addAttachmentPart(KMime::Content *partToAttach) | 296 | void ComposerController::addAttachmentPart(KMime::Content *partToAttach) |
452 | { | 297 | { |
453 | auto item = new QStandardItem; | 298 | QVariantMap map; |
454 | |||
455 | if (partToAttach->contentType()->mimeType() == "multipart/digest" || | 299 | if (partToAttach->contentType()->mimeType() == "multipart/digest" || |
456 | partToAttach->contentType()->mimeType() == "message/rfc822") { | 300 | partToAttach->contentType()->mimeType() == "message/rfc822") { |
457 | // if it is a digest or a full message, use the encodedContent() of the attachment, | 301 | // if it is a digest or a full message, use the encodedContent() of the attachment, |
458 | // which already has the proper headers | 302 | // which already has the proper headers |
459 | item->setData(partToAttach->encodedContent(), ContentRole); | 303 | map.insert("content", partToAttach->encodedContent()); |
460 | } else { | 304 | } else { |
461 | item->setData(partToAttach->decodedContent(), ContentRole); | 305 | map.insert("content", partToAttach->decodedContent()); |
462 | } | 306 | } |
463 | item->setData(partToAttach->contentType()->mimeType(), MimeTypeRole); | 307 | map.insert("mimetype", partToAttach->contentType()->mimeType()); |
464 | 308 | ||
465 | QMimeDatabase db; | 309 | QMimeDatabase db; |
466 | auto mimeType = db.mimeTypeForName(partToAttach->contentType()->mimeType()); | 310 | auto mimeType = db.mimeTypeForName(partToAttach->contentType()->mimeType()); |
467 | item->setData(mimeType.iconName(), IconNameRole); | 311 | map.insert("iconname", mimeType.iconName()); |
468 | 312 | ||
469 | if (partToAttach->contentDescription(false)) { | 313 | if (partToAttach->contentDescription(false)) { |
470 | item->setData(partToAttach->contentDescription()->asUnicodeString(), DescriptionRole); | 314 | map.insert("description", partToAttach->contentDescription()->asUnicodeString()); |
471 | } | 315 | } |
472 | QString name; | 316 | QString name; |
473 | QString filename; | 317 | QString filename; |
@@ -478,7 +322,7 @@ void ComposerController::addAttachmentPart(KMime::Content *partToAttach) | |||
478 | } | 322 | } |
479 | if (partToAttach->contentDisposition(false)) { | 323 | if (partToAttach->contentDisposition(false)) { |
480 | filename = partToAttach->contentDisposition()->filename(); | 324 | filename = partToAttach->contentDisposition()->filename(); |
481 | item->setData(partToAttach->contentDisposition()->disposition() == KMime::Headers::CDinline, InlineRole); | 325 | map.insert("inline", partToAttach->contentDisposition()->disposition() == KMime::Headers::CDinline); |
482 | } | 326 | } |
483 | 327 | ||
484 | if (name.isEmpty() && !filename.isEmpty()) { | 328 | if (name.isEmpty() && !filename.isEmpty()) { |
@@ -489,20 +333,19 @@ void ComposerController::addAttachmentPart(KMime::Content *partToAttach) | |||
489 | } | 333 | } |
490 | 334 | ||
491 | if (!filename.isEmpty()) { | 335 | if (!filename.isEmpty()) { |
492 | item->setData(filename, FilenameRole); | 336 | map.insert("filename", filename); |
493 | } | 337 | } |
494 | if (!name.isEmpty()) { | 338 | if (!name.isEmpty()) { |
495 | item->setData(name, NameRole); | 339 | map.insert("name", name); |
496 | } | 340 | } |
497 | 341 | attachmentsController()->add(map); | |
498 | mAttachmentModel->appendRow(item); | ||
499 | } | 342 | } |
500 | 343 | ||
501 | void ComposerController::setMessage(const KMime::Message::Ptr &msg) | 344 | void ComposerController::setMessage(const KMime::Message::Ptr &msg) |
502 | { | 345 | { |
503 | mToModel->setStringList(getStringListFromAddresses(msg->to(true)->mailboxes())); | 346 | static_cast<AddresseeController*>(toController())->set(getStringListFromAddresses(msg->to(true)->mailboxes())); |
504 | mCcModel->setStringList(getStringListFromAddresses(msg->cc(true)->mailboxes())); | 347 | static_cast<AddresseeController*>(ccController())->set(getStringListFromAddresses(msg->cc(true)->mailboxes())); |
505 | mBccModel->setStringList(getStringListFromAddresses(msg->bcc(true)->mailboxes())); | 348 | static_cast<AddresseeController*>(bccController())->set(getStringListFromAddresses(msg->bcc(true)->mailboxes())); |
506 | 349 | ||
507 | setSubject(msg->subject(true)->asUnicodeString()); | 350 | setSubject(msg->subject(true)->asUnicodeString()); |
508 | bool isHtml = false; | 351 | bool isHtml = false; |
@@ -563,75 +406,66 @@ void ComposerController::recordForAutocompletion(const QByteArray &addrSpec, con | |||
563 | } | 406 | } |
564 | } | 407 | } |
565 | 408 | ||
409 | std::vector<GpgME::Key> ComposerController::getRecipientKeys() | ||
410 | { | ||
411 | std::vector<GpgME::Key> keys; | ||
412 | { | ||
413 | const auto list = toController()->getList<std::vector<GpgME::Key>>("key"); | ||
414 | for (const auto &l: list) { | ||
415 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | ||
416 | } | ||
417 | } | ||
418 | { | ||
419 | const auto list = ccController()->getList<std::vector<GpgME::Key>>("key"); | ||
420 | for (const auto &l: list) { | ||
421 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | ||
422 | } | ||
423 | } | ||
424 | { | ||
425 | const auto list = bccController()->getList<std::vector<GpgME::Key>>("key"); | ||
426 | for (const auto &l: list) { | ||
427 | keys.insert(std::end(keys), std::begin(l), std::end(l)); | ||
428 | } | ||
429 | } | ||
430 | return keys; | ||
431 | } | ||
432 | |||
566 | KMime::Message::Ptr ComposerController::assembleMessage() | 433 | KMime::Message::Ptr ComposerController::assembleMessage() |
567 | { | 434 | { |
568 | applyAddresses(mToModel->stringList(), [&](const QByteArray &addrSpec, const QByteArray &displayName) { | 435 | auto toAddresses = toController()->getList<QString>("name"); |
569 | recordForAutocompletion(addrSpec, displayName); | 436 | auto ccAddresses = toController()->getList<QString>("name"); |
570 | }); | 437 | auto bccAddresses = toController()->getList<QString>("name"); |
571 | applyAddresses(mCcModel->stringList(), [&](const QByteArray &addrSpec, const QByteArray &displayName) { | 438 | applyAddresses(toAddresses + ccAddresses + bccAddresses, [&](const QByteArray &addrSpec, const QByteArray &displayName) { |
572 | recordForAutocompletion(addrSpec, displayName); | ||
573 | }); | ||
574 | applyAddresses(mBccModel->stringList(), [&](const QByteArray &addrSpec, const QByteArray &displayName) { | ||
575 | recordForAutocompletion(addrSpec, displayName); | 439 | recordForAutocompletion(addrSpec, displayName); |
576 | }); | 440 | }); |
577 | 441 | ||
578 | QList<Attachment> attachments; | 442 | QList<Attachment> attachments; |
579 | auto root = mAttachmentModel->invisibleRootItem(); | 443 | attachmentsController()->traverse([&](const QVariantMap &value) { |
580 | for (int row = 0; row < root->rowCount(); row++) { | ||
581 | auto item = root->child(row, 0); | ||
582 | attachments << Attachment{ | 444 | attachments << Attachment{ |
583 | item->data(NameRole).toString(), | 445 | value["name"].toString(), |
584 | item->data(FilenameRole).toString(), | 446 | value["filename"].toString(), |
585 | item->data(MimeTypeRole).toByteArray(), | 447 | value["mimetype"].toByteArray(), |
586 | item->data(InlineRole).toBool(), | 448 | value["inline"].toBool(), |
587 | item->data(ContentRole).toByteArray() | 449 | value["content"].toByteArray() |
588 | }; | 450 | }; |
589 | } | 451 | }); |
590 | 452 | ||
591 | std::vector<GpgME::Key> signingKeys; | 453 | std::vector<GpgME::Key> signingKeys; |
592 | if (getSign()) { | 454 | if (getSign()) { |
593 | signingKeys = mPersonalKeys; | 455 | signingKeys = getPersonalKeys().value<std::vector<GpgME::Key>>(); |
594 | } | 456 | } |
595 | std::vector<GpgME::Key> encryptionKeys; | 457 | std::vector<GpgME::Key> encryptionKeys; |
596 | if (getEncrypt()) { | 458 | if (getEncrypt()) { |
597 | if (!mToModel->foundAllKeys() || !mCcModel->foundAllKeys() || !mBccModel->foundAllKeys()) { | ||
598 | qWarning() << "Can't encrypt with missing keys"; | ||
599 | return nullptr; | ||
600 | } | ||
601 | //Encrypt to self so we can read the sent message | 459 | //Encrypt to self so we can read the sent message |
602 | encryptionKeys.insert(std::end(encryptionKeys), std::begin(mPersonalKeys), std::end(mPersonalKeys)); | 460 | encryptionKeys += getPersonalKeys().value<std::vector<GpgME::Key>>(); |
603 | auto toKeys = mToModel->getKeys(); | 461 | encryptionKeys += getRecipientKeys(); |
604 | encryptionKeys.insert(std::end(encryptionKeys), std::begin(toKeys), std::end(toKeys)); | ||
605 | auto ccKeys = mCcModel->getKeys(); | ||
606 | encryptionKeys.insert(std::end(encryptionKeys), std::begin(ccKeys), std::end(ccKeys)); | ||
607 | auto bccKeys = mBccModel->getKeys(); | ||
608 | encryptionKeys.insert(std::end(encryptionKeys), std::begin(bccKeys), std::end(bccKeys)); | ||
609 | } | 462 | } |
610 | 463 | ||
611 | return MailTemplates::createMessage(mExistingMessage, mToModel->stringList(), mCcModel->stringList(), mBccModel->stringList(), getIdentity(), getSubject(), getBody(), getHtmlBody(), attachments, signingKeys, encryptionKeys); | 464 | return MailTemplates::createMessage(mExistingMessage, toAddresses, ccAddresses, bccAddresses, getIdentity(), getSubject(), getBody(), getHtmlBody(), attachments, signingKeys, encryptionKeys); |
612 | } | ||
613 | |||
614 | void ComposerController::updateSendAction() | ||
615 | { | ||
616 | auto enabled = !mToModel->stringList().isEmpty() && !getSubject().isEmpty() && !getAccountId().isEmpty(); | ||
617 | if (getEncrypt()) { | ||
618 | if (!mToModel->foundAllKeys() || !mCcModel->foundAllKeys() || !mBccModel->foundAllKeys()) { | ||
619 | SinkWarning() << "Don't have all keys"; | ||
620 | enabled = false; | ||
621 | } | ||
622 | } | ||
623 | if (getSign()) { | ||
624 | if (mPersonalKeys.empty()) { | ||
625 | enabled = false; | ||
626 | } | ||
627 | } | ||
628 | sendAction()->setEnabled(enabled); | ||
629 | } | 465 | } |
630 | 466 | ||
631 | void ComposerController::send() | 467 | void ComposerController::send() |
632 | { | 468 | { |
633 | // verify<To, Subject>() | ||
634 | // && verify<Subject>(); | ||
635 | auto message = assembleMessage(); | 469 | auto message = assembleMessage(); |
636 | if (!message) { | 470 | if (!message) { |
637 | SinkWarning() << "Failed to assemble the message."; | 471 | SinkWarning() << "Failed to assemble the message."; |
@@ -670,12 +504,6 @@ void ComposerController::send() | |||
670 | run(job); | 504 | run(job); |
671 | } | 505 | } |
672 | 506 | ||
673 | void ComposerController::updateSaveAsDraftAction() | ||
674 | { | ||
675 | bool enabled = !getAccountId().isEmpty(); | ||
676 | sendAction()->setEnabled(enabled); | ||
677 | } | ||
678 | |||
679 | void ComposerController::saveAsDraft() | 507 | void ComposerController::saveAsDraft() |
680 | { | 508 | { |
681 | SinkLog() << "Save as draft"; | 509 | SinkLog() << "Save as draft"; |
@@ -683,9 +511,8 @@ void ComposerController::saveAsDraft() | |||
683 | auto existingMail = getExistingMail(); | 511 | auto existingMail = getExistingMail(); |
684 | 512 | ||
685 | auto message = assembleMessage(); | 513 | auto message = assembleMessage(); |
686 | //FIXME this is something for the validation | ||
687 | if (!message) { | 514 | if (!message) { |
688 | SinkWarning() << "Failed to get the mail: "; | 515 | SinkWarning() << "Failed to assemble the message."; |
689 | return; | 516 | return; |
690 | } | 517 | } |
691 | 518 | ||
@@ -720,3 +547,4 @@ void ComposerController::saveAsDraft() | |||
720 | }); | 547 | }); |
721 | run(job); | 548 | run(job); |
722 | } | 549 | } |
550 | |||