summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--framework/qml/ConversationView.qml342
-rw-r--r--framework/qml/MailViewer.qml386
-rw-r--r--framework/src/domain/messageparser.cpp6
3 files changed, 368 insertions, 366 deletions
diff --git a/framework/qml/ConversationView.qml b/framework/qml/ConversationView.qml
index 5850d2c7..f59704d0 100644
--- a/framework/qml/ConversationView.qml
+++ b/framework/qml/ConversationView.qml
@@ -207,339 +207,23 @@ Rectangle {
207 } 207 }
208 } 208 }
209 209
210 Rectangle { 210 MailViewer {
211 id: sheet 211 id: sheet
212 anchors.centerIn: parent 212 anchors.centerIn: parent
213 implicitHeight: header.height + attachments.height + body.height + incompleteBody.height + footer.height + Kube.Units.largeSpacing
214 width: parent.width - Kube.Units.gridUnit * 2 213 width: parent.width - Kube.Units.gridUnit * 2
215 214
216 //Overlay for non-active mails 215 message: model.mimeMessage
217 Rectangle { 216 subject: model.subject
218 anchors.fill: parent 217 sender: model.sender
219 visible: !wrapper.isCurrent 218 senderName: model.senderName
220 color: "lightGrey" 219 to: model.to
221 z: 1 220 cc: model.cc
222 opacity: 0.2 221 bcc: model.bcc
223 } 222 date: model.date
224 223 trash: model.trash
225 color: Kube.Colors.viewBackgroundColor 224 draft: model.draft
226 225 sent: model.sent
227 //BEGIN header 226 incomplete: model.incomplete
228 Item {
229 id: header
230
231 anchors {
232 top: parent.top
233 left: parent.left
234 right: parent.right
235 margins: Kube.Units.largeSpacing
236 }
237
238 height: headerContent.height + Kube.Units.smallSpacing
239
240 states: [
241 State {
242 name: "small"
243 PropertyChanges { target: subject; wrapMode: Text.NoWrap}
244 PropertyChanges { target: recipients; visible: true}
245 PropertyChanges { target: to; visible: false}
246 PropertyChanges { target: cc; visible: false}
247 PropertyChanges { target: bcc; visible: false}
248 },
249 State {
250 name: "details"
251 PropertyChanges { target: subject; wrapMode: Text.WrapAnywhere}
252 PropertyChanges { target: recipients; visible: false}
253 PropertyChanges { target: to; visible: true}
254 PropertyChanges { target: cc; visible: true}
255 PropertyChanges { target: bcc; visible: true}
256 }
257 ]
258
259 state: "small"
260
261 Kube.Label {
262 id: date_label
263
264 anchors {
265 right: seperator.right
266 top: parent.top
267 }
268
269 text: Qt.formatDateTime(model.date, "dd MMM yyyy hh:mm")
270
271 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.7
272 opacity: 0.75
273 }
274
275 Column {
276 id: headerContent
277
278 anchors {
279 //left: to_l.right
280 horizontalCenter: parent.horizontalCenter
281 }
282
283 //spacing: Kube.Units.smallSpacing
284
285 width: parent.width
286
287 Row{
288 id: from
289
290 width: parent.width
291
292 spacing: Kube.Units.smallSpacing
293 clip: true
294
295 Kube.Label {
296 id: senderName
297
298 text: model.senderName
299 font.weight: Font.DemiBold
300 opacity: 0.75
301 }
302
303 Kube.Label {
304 width: parent.width - senderName.width - date_label.width - Kube.Units.largeSpacing
305
306
307 text: model.sender
308 elide: Text.ElideRight
309 opacity: 0.75
310 clip: true
311 }
312 }
313
314 Kube.Label {
315 id: subject
316
317 width: to.width
318
319 text: model.subject
320 elide: Text.ElideRight
321 opacity: 0.75
322 font.italic: true
323 states: [
324 State {
325 name: "trash"; when: model.trash
326 PropertyChanges { target: subject; text: "Trash: " + model.subject }
327 },
328 State {
329 name: "draft"; when: model.draft
330 PropertyChanges { target: subject; text: "Draft: " + model.subject }
331 },
332 State {
333 name: "sent"; when: model.sent
334 PropertyChanges { target: subject; text: "Sent: " + model.subject }
335 }
336 ]
337 }
338
339 Kube.Label {
340 id: recipients
341
342 width: parent.width - goDown.width - Kube.Units.smallSpacing
343
344 text:"to: "+ model.to + " " + model.cc + " " + model.bcc
345 elide: Text.ElideRight
346 opacity: 0.75
347 }
348
349 Kube.Label {
350 id: to
351
352 width: parent.width - goDown.width - Kube.Units.smallSpacing
353
354 text:"to: " + model.to
355 wrapMode: Text.WordWrap
356 opacity: 0.75
357 }
358
359 Kube.Label {
360 id: cc
361
362 width: parent.width - goDown.width - Kube.Units.smallSpacing
363
364 text:"cc: " + model.cc
365 wrapMode: Text.WordWrap
366 opacity: 0.75
367 }
368
369 Kube.Label {
370 id: bcc
371
372 width: parent.width - goDown.width - Kube.Units.smallSpacing
373
374 text:"bcc: " + model.bcc
375 wrapMode: Text.WordWrap
376 opacity: 0.75
377 }
378
379 }
380
381 Rectangle {
382 id: goDown
383
384 anchors {
385 bottom: seperator.top
386 right: seperator.right
387 }
388
389 height: Kube.Units.gridUnit
390 width: height
391
392 color: Kube.Colors.backgroundColor
393
394 Controls1.ToolButton {
395 anchors.fill: parent
396
397 iconName: header.state === "details" ? Kube.Icons.goUp : Kube.Icons.goDown
398
399 onClicked: {
400 header.state === "details" ? header.state = "small" : header.state = "details"
401 }
402 }
403 }
404
405 Rectangle {
406 id: seperator
407
408 anchors {
409 left: parent.left
410 right: parent.right
411 bottom: parent.bottom
412 }
413
414 height: 1
415
416 color: Kube.Colors.textColor
417 opacity: 0.5
418 }
419 }
420 //END header
421
422 Flow {
423 id: attachments
424
425 anchors {
426 top: header.bottom
427 topMargin: Kube.Units.smallSpacing
428 right: header.right
429 }
430
431 width: header.width - Kube.Units.largeSpacing
432
433 layoutDirection: Qt.RightToLeft
434 spacing: Kube.Units.smallSpacing
435 clip: true
436
437 Repeater {
438 model: body.attachments
439
440 delegate: AttachmentDelegate {
441 name: model.name
442 icon: "mail-attachment"
443
444 clip: true
445
446 //TODO size encrypted signed type
447 }
448 }
449 }
450
451 MailViewer {
452 id: body
453
454 anchors {
455 top: header.bottom
456 left: header.left
457 right: header.right
458 leftMargin: Kube.Units.largeSpacing
459 rightMargin: Kube.Units.largeSpacing
460 topMargin: Math.max(attachments.height, Kube.Units.largeSpacing)
461 }
462
463 width: header.width - Kube.Units.largeSpacing * 2
464 height: desiredHeight
465
466 message: model.mimeMessage
467 visible: !model.incomplete
468 }
469
470 Kube.Label {
471 id: incompleteBody
472 anchors {
473 top: header.bottom
474 left: header.left
475 right: header.right
476 leftMargin: Kube.Units.largeSpacing
477 rightMargin: Kube.Units.largeSpacing
478 topMargin: Math.max(attachments.height, Kube.Units.largeSpacing)
479 }
480 visible: model.incomplete
481 text: "Incomplete body..."
482 color: Kube.Colors.textColor
483 enabled: false
484 states: [
485 State {
486 name: "inprogress"; when: model.status == Kube.MailListModel.InProgressStatus
487 PropertyChanges { target: incompleteBody; text: "Downloading message..." }
488 },
489 State {
490 name: "error"; when: model.status == Kube.MailListModel.ErrorStatus
491 PropertyChanges { target: incompleteBody; text: "Failed to download message..." }
492 }
493 ]
494 }
495 Item {
496 id: footer
497
498 anchors.bottom: parent.bottom
499
500 height: Kube.Units.gridUnit * 2
501 width: parent.width
502
503 Kube.Label {
504 anchors{
505 verticalCenter: parent.verticalCenter
506 left: parent.left
507 leftMargin: Kube.Units.largeSpacing
508 }
509
510 text: model.trash ? qsTr("Delete Mail") : qsTr("Move to trash")
511 opacity: 0.5
512 MouseArea {
513 anchors.fill: parent
514 enabled: parent.enabled
515 onClicked: {
516 if (model.trash) {
517 Kube.Fabric.postMessage(Kube.Messages.remove, {"mail": model.mail})
518 } else {
519 Kube.Fabric.postMessage(Kube.Messages.moveToTrash, {"mail": model.mail})
520 }
521 }
522 }
523 }
524
525 Controls1.ToolButton {
526 visible: !model.trash
527 anchors{
528 verticalCenter: parent.verticalCenter
529 right: parent.right
530 rightMargin: Kube.Units.largeSpacing
531 }
532
533 iconName: model.draft ? Kube.Icons.edit : Kube.Icons.replyToSender
534 onClicked: {
535 if (model.draft) {
536 Kube.Fabric.postMessage(Kube.Messages.edit, {"mail": model.mail, "isDraft": model.draft})
537 } else {
538 Kube.Fabric.postMessage(Kube.Messages.reply, {"mail": model.mail, "isDraft": model.draft})
539 }
540 }
541 }
542 }
543 } 227 }
544 } 228 }
545 } 229 }
diff --git a/framework/qml/MailViewer.qml b/framework/qml/MailViewer.qml
index 3e118a8d..b6ea4502 100644
--- a/framework/qml/MailViewer.qml
+++ b/framework/qml/MailViewer.qml
@@ -18,59 +18,371 @@
18 18
19import QtQuick 2.7 19import QtQuick 2.7
20import QtQuick.Controls 1.4 as Controls1 20import QtQuick.Controls 1.4 as Controls1
21import QtQuick.Controls 2
21import QtQuick.Layouts 1.1 22import QtQuick.Layouts 1.1
22 23
23import org.kube.components.mailviewer 1.0 as MV 24import org.kube.components.mailviewer 1.0 as MV
24import org.kube.framework 1.0 as Kube 25import org.kube.framework 1.0 as Kube
25 26
26Item { 27import QtQuick.Layouts 1.1
28import org.kde.kirigami 1.0 as Kirigami
29
30Rectangle {
27 id: root 31 id: root
32
28 property variant message; 33 property variant message;
29 property int desiredHeight: mailViewer.height + 20 34 property variant subject;
30 property variant attachments: messageParser.attachments 35 property variant sender;
36 property variant senderName;
37 property variant to;
38 property variant cc;
39 property variant bcc;
40 property variant date;
41 property variant trash;
42 property variant draft;
43 property variant sent;
44 property bool incomplete: false;
31 45
32 clip: true 46 implicitHeight: header.height + attachments.height + body.height + incompleteBody.height + footer.height + Kube.Units.largeSpacing
33 47
34 MV.MailViewer { 48 //Overlay for non-active mails
35 anchors.top: root.top 49 Rectangle {
36 id: mailViewer 50 anchors.fill: parent
37 model: messageParser.newTree 51 visible: !wrapper.isCurrent
38 debug: false 52 color: "lightGrey"
39 width: parent.width 53 z: 1
54 opacity: 0.2
40 } 55 }
41 56
42 Controls1.TreeView { 57 color: Kube.Colors.viewBackgroundColor
43 id: mailStructure 58
44 // anchors.fill: parent 59 Kube.MessageParser {
45 // anchors.top: root.attachments.rowCount() > 0 ? attachments.bottom : mailViewer.bottom 60 id: messageParser
46 visible: mailViewer.debug 61 message: root.message
47 width: parent.width 62 }
48 height: 400 63
49 Controls1.TableViewColumn { 64 //BEGIN header
50 role: "type" 65 Item {
51 title: "Type" 66 id: header
52 width: 300 67
68 anchors {
69 top: parent.top
70 left: parent.left
71 right: parent.right
72 margins: Kube.Units.largeSpacing
73 }
74
75 height: headerContent.height + Kube.Units.smallSpacing
76
77 states: [
78 State {
79 name: "small"
80 PropertyChanges { target: subject; wrapMode: Text.NoWrap}
81 PropertyChanges { target: recipients; visible: true}
82 PropertyChanges { target: to; visible: false}
83 PropertyChanges { target: cc; visible: false}
84 PropertyChanges { target: bcc; visible: false}
85 },
86 State {
87 name: "details"
88 PropertyChanges { target: subject; wrapMode: Text.WrapAnywhere}
89 PropertyChanges { target: recipients; visible: false}
90 PropertyChanges { target: to; visible: true}
91 PropertyChanges { target: cc; visible: true}
92 PropertyChanges { target: bcc; visible: true}
93 }
94 ]
95
96 state: "small"
97
98 Kube.Label {
99 id: date_label
100
101 anchors {
102 right: seperator.right
103 top: parent.top
104 }
105
106 text: Qt.formatDateTime(root.date, "dd MMM yyyy hh:mm")
107
108 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.7
109 opacity: 0.75
110 }
111
112 Column {
113 id: headerContent
114
115 anchors {
116 //left: to_l.right
117 horizontalCenter: parent.horizontalCenter
118 }
119
120 //spacing: Kube.Units.smallSpacing
121
122 width: parent.width
123
124 Row{
125 id: from
126
127 width: parent.width
128
129 spacing: Kube.Units.smallSpacing
130 clip: true
131
132 Kube.Label {
133 id: senderName
134
135 text: root.senderName
136 font.weight: Font.DemiBold
137 opacity: 0.75
138 }
139
140 Kube.Label {
141 width: parent.width - senderName.width - date_label.width - Kube.Units.largeSpacing
142
143
144 text: root.sender
145 elide: Text.ElideRight
146 opacity: 0.75
147 clip: true
148 }
149 }
150
151 Kube.Label {
152 id: subject
153
154 width: to.width
155
156 text: root.subject
157 elide: Text.ElideRight
158 opacity: 0.75
159 font.italic: true
160 states: [
161 State {
162 name: "trash"; when: root.trash
163 PropertyChanges { target: subject; text: "Trash: " + root.subject }
164 },
165 State {
166 name: "draft"; when: root.draft
167 PropertyChanges { target: subject; text: "Draft: " + root.subject }
168 },
169 State {
170 name: "sent"; when: root.sent
171 PropertyChanges { target: subject; text: "Sent: " + root.subject }
172 }
173 ]
174 }
175
176 Kube.Label {
177 id: recipients
178
179 width: parent.width - goDown.width - Kube.Units.smallSpacing
180
181 text:"to: "+ root.to + " " + root.cc + " " + root.bcc
182 elide: Text.ElideRight
183 opacity: 0.75
184 }
185
186 Kube.Label {
187 id: to
188
189 width: parent.width - goDown.width - Kube.Units.smallSpacing
190
191 text:"to: " + root.to
192 wrapMode: Text.WordWrap
193 opacity: 0.75
194 }
195
196 Kube.Label {
197 id: cc
198
199 width: parent.width - goDown.width - Kube.Units.smallSpacing
200
201 text:"cc: " + root.cc
202 wrapMode: Text.WordWrap
203 opacity: 0.75
204 }
205
206 Kube.Label {
207 id: bcc
208
209 width: parent.width - goDown.width - Kube.Units.smallSpacing
210
211 text:"bcc: " + root.bcc
212 wrapMode: Text.WordWrap
213 opacity: 0.75
214 }
215
216 }
217
218 Rectangle {
219 id: goDown
220
221 anchors {
222 bottom: seperator.top
223 right: seperator.right
224 }
225
226 height: Kube.Units.gridUnit
227 width: height
228
229 color: Kube.Colors.backgroundColor
230
231 Controls1.ToolButton {
232 anchors.fill: parent
233
234 iconName: header.state === "details" ? Kube.Icons.goUp : Kube.Icons.goDown
235
236 onClicked: {
237 header.state === "details" ? header.state = "small" : header.state = "details"
238 }
239 }
240 }
241
242 Rectangle {
243 id: seperator
244
245 anchors {
246 left: parent.left
247 right: parent.right
248 bottom: parent.bottom
249 }
250
251 height: 1
252
253 color: Kube.Colors.textColor
254 opacity: 0.5
255 }
256 }
257 //END header
258
259 Flow {
260 id: attachments
261
262 anchors {
263 top: header.bottom
264 topMargin: Kube.Units.smallSpacing
265 right: header.right
266 }
267
268 width: header.width - Kube.Units.largeSpacing
269
270 layoutDirection: Qt.RightToLeft
271 spacing: Kube.Units.smallSpacing
272 clip: true
273
274 Repeater {
275 model: messageParser.attachments
276
277 delegate: AttachmentDelegate {
278 name: model.name
279 icon: "mail-attachment"
280
281 clip: true
282
283 //TODO size encrypted signed type
284 }
53 } 285 }
54 Controls1.TableViewColumn { 286 }
55 role: "embeded" 287
56 title: "Embeded" 288 Item {
57 width: 60 289 id: body
290
291 visible: !root.incomplete
292 anchors {
293 top: header.bottom
294 left: header.left
295 right: header.right
296 leftMargin: Kube.Units.largeSpacing
297 rightMargin: Kube.Units.largeSpacing
298 topMargin: Math.max(attachments.height, Kube.Units.largeSpacing)
58 } 299 }
59 Controls1.TableViewColumn { 300 height: mailViewer.height + 20
60 role: "securityLevel" 301
61 title: "SecurityLevel" 302 clip: true
62 width: 60 303
304 MV.MailViewer {
305 id: mailViewer
306 anchors.top: body.top
307 anchors.left: body.left
308 anchors.right: body.right
309 model: messageParser.newTree
310 debug: false
63 } 311 }
64 Controls1.TableViewColumn { 312
65 role: "content" 313 }
66 title: "Content" 314
67 width: 200 315 Kube.Label {
316 id: incompleteBody
317 anchors {
318 top: header.bottom
319 left: header.left
320 right: header.right
321 leftMargin: Kube.Units.largeSpacing
322 rightMargin: Kube.Units.largeSpacing
323 topMargin: Math.max(attachments.height, Kube.Units.largeSpacing)
68 } 324 }
69 model: messageParser.newTree 325 visible: root.incomplete
326 text: "Incomplete body..."
327 color: Kube.Colors.textColor
328 enabled: false
329 states: [
330 State {
331 name: "inprogress"; when: model.status == Kube.MailListModel.InProgressStatus
332 PropertyChanges { target: incompleteBody; text: "Downloading message..." }
333 },
334 State {
335 name: "error"; when: model.status == Kube.MailListModel.ErrorStatus
336 PropertyChanges { target: incompleteBody; text: "Failed to download message..." }
337 }
338 ]
70 } 339 }
340 Item {
341 id: footer
71 342
72 Kube.MessageParser { 343 anchors.bottom: parent.bottom
73 id: messageParser 344
74 message: root.message 345 height: Kube.Units.gridUnit * 2
346 width: parent.width
347
348 Kube.Label {
349 anchors{
350 verticalCenter: parent.verticalCenter
351 left: parent.left
352 leftMargin: Kube.Units.largeSpacing
353 }
354
355 text: model.trash ? qsTr("Delete Mail") : qsTr("Move to trash")
356 opacity: 0.5
357 MouseArea {
358 anchors.fill: parent
359 enabled: parent.enabled
360 onClicked: {
361 if (model.trash) {
362 Kube.Fabric.postMessage(Kube.Messages.remove, {"mail": model.mail})
363 } else {
364 Kube.Fabric.postMessage(Kube.Messages.moveToTrash, {"mail": model.mail})
365 }
366 }
367 }
368 }
369
370 Controls1.ToolButton {
371 visible: !model.trash
372 anchors{
373 verticalCenter: parent.verticalCenter
374 right: parent.right
375 rightMargin: Kube.Units.largeSpacing
376 }
377
378 iconName: model.draft ? Kube.Icons.edit : Kube.Icons.replyToSender
379 onClicked: {
380 if (model.draft) {
381 Kube.Fabric.postMessage(Kube.Messages.edit, {"mail": model.mail, "isDraft": model.draft})
382 } else {
383 Kube.Fabric.postMessage(Kube.Messages.reply, {"mail": model.mail, "isDraft": model.draft})
384 }
385 }
386 }
75 } 387 }
76} 388}
diff --git a/framework/src/domain/messageparser.cpp b/framework/src/domain/messageparser.cpp
index 6df50ebd..76c060f0 100644
--- a/framework/src/domain/messageparser.cpp
+++ b/framework/src/domain/messageparser.cpp
@@ -54,6 +54,9 @@ void MessageParser::setMessage(const QVariant &message)
54 54
55QAbstractItemModel *MessageParser::newTree() const 55QAbstractItemModel *MessageParser::newTree() const
56{ 56{
57 if (!d->mParser) {
58 return nullptr;
59 }
57 const auto model = new NewModel(d->mParser); 60 const auto model = new NewModel(d->mParser);
58 // new ModelTest(model, model); 61 // new ModelTest(model, model);
59 return model; 62 return model;
@@ -61,6 +64,9 @@ QAbstractItemModel *MessageParser::newTree() const
61 64
62QAbstractItemModel *MessageParser::attachments() const 65QAbstractItemModel *MessageParser::attachments() const
63{ 66{
67 if (!d->mParser) {
68 return nullptr;
69 }
64 const auto model = new AttachmentModel(d->mParser); 70 const auto model = new AttachmentModel(d->mParser);
65 // new ModelTest(model, model); 71 // new ModelTest(model, model);
66 return model; 72 return model;