summaryrefslogtreecommitdiffstats
path: root/views/composer/qml/View.qml
diff options
context:
space:
mode:
Diffstat (limited to 'views/composer/qml/View.qml')
-rw-r--r--views/composer/qml/View.qml533
1 files changed, 533 insertions, 0 deletions
diff --git a/views/composer/qml/View.qml b/views/composer/qml/View.qml
new file mode 100644
index 00000000..1eb88bb4
--- /dev/null
+++ b/views/composer/qml/View.qml
@@ -0,0 +1,533 @@
1/*
2 * Copyright (C) 2017 Michael Bohlender, <michael.bohlender@kdemail.net>
3 * Copyright (C) 2017 Christian Mollekopf, <mollekopf@kolabsys.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20
21import QtQuick 2.7
22import QtQuick.Controls 1.3
23import QtQuick.Controls 2.0 as Controls2
24import QtQuick.Layouts 1.1
25import QtQuick.Dialogs 1.0 as Dialogs
26
27import org.kube.framework 1.0 as Kube
28
29Kube.View {
30 id: root
31
32 property bool newMessage: false
33 property bool loadAsDraft: false
34 property variant message: {}
35 property variant recipients: []
36
37 resources: [
38 Kube.ComposerController {
39 id: composerController
40 htmlBody: html.checked
41 sign: signCheckbox.checked
42 encrypt: encryptCheckbox.checked
43 onDone: Kube.Fabric.postMessage(Kube.Messages.componentDone, {})
44
45 property bool foundAllKeys: to.foundAllKeys && cc.foundAllKeys && bcc.foundAllKeys
46
47 sendAction.enabled: composerController.accountId && composerController.subject && (!composerController.encrypt || composerController.foundAllKeys) && (!composerController.sign && !composerController.encrypt || composerController.foundPersonalKeys)
48 saveAsDraftAction.enabled: composerController.accountId
49 }
50 ]
51
52 Component.onCompleted: loadMessage(root.message, root.loadAsDraft)
53
54 Controls2.StackView.onActivated: {
55 Kube.Fabric.postMessage(Kube.Messages.synchronize, {"type": "mail", "specialPurpose": "drafts"})
56 //For autocompletion
57 Kube.Fabric.postMessage(Kube.Messages.synchronize, {"type": "contacts"})
58 }
59
60 function loadMessage(message, loadAsDraft) {
61 if (message) {
62 composerController.loadMessage(message, loadAsDraft)
63 //Forward focus for replies directly
64 if (!loadAsDraft) {
65 subject.forceActiveFocus()
66 }
67 } else if (newMessage) {
68 composerController.clear()
69 if (root.recipients) {
70 for (var i = 0; i < root.recipients.length; ++i) {
71 composerController.to.add({name: root.recipients[i]})
72 }
73 }
74 subject.forceActiveFocus()
75 }
76 }
77
78 function closeFirstSplitIfNecessary() {
79 //Move the view forward
80 if (root.currentIndex == 0) {
81 root.incrementCurrentIndex()
82 }
83 }
84
85 //Drafts
86 Rectangle {
87
88 anchors {
89 top: parent.top
90 bottom: parent.bottom
91 }
92
93 width: Kube.Units.gridUnit * 10
94 Layout.minimumWidth: Kube.Units.gridUnit * 5
95
96 color: Kube.Colors.textColor
97
98 ColumnLayout {
99
100 anchors {
101 fill: parent
102 margins: Kube.Units.largeSpacing
103 }
104
105 spacing: Kube.Units.largeSpacing
106
107 Kube.PositiveButton {
108 objectName: "newMailButton"
109 anchors {
110 left: parent.left
111 right: parent.right
112 }
113 focus: true
114 text: qsTr("New Email")
115 onClicked: {
116 listView.currentIndex = -1
117 composerController.clear()
118 subject.forceActiveFocus()
119 }
120 }
121
122 Kube.Label{
123 text: qsTr("Drafts")
124 color: Kube.Colors.highlightedTextColor
125 }
126
127 Kube.ListView {
128 id: listView
129 activeFocusOnTab: true
130
131 anchors {
132 left: parent.left
133 right: parent.right
134 }
135
136 Layout.fillHeight: true
137 clip: true
138 currentIndex: -1
139 highlightFollowsCurrentItem: false
140
141 //BEGIN keyboard nav
142 onActiveFocusChanged: {
143 if (activeFocus && currentIndex < 0) {
144 currentIndex = 0
145 }
146 }
147 Keys.onDownPressed: {
148 listView.incrementCurrentIndex()
149 }
150 Keys.onUpPressed: {
151 listView.decrementCurrentIndex()
152 }
153 //END keyboard nav
154
155 onCurrentItemChanged: {
156 if (currentItem) {
157 root.loadMessage(currentItem.currentData.domainObject, true)
158 }
159 }
160
161 model: Kube.MailListModel {
162 id: mailListModel
163 showDrafts: true
164 }
165
166 delegate: Kube.ListDelegate {
167 id: delegateRoot
168
169 color: Kube.Colors.textColor
170 border.width: 0
171
172 Item {
173 id: content
174
175 anchors {
176 fill: parent
177 margins: Kube.Units.smallSpacing
178 }
179
180 Kube.Label {
181 width: content.width
182 text: model.subject == "" ? "no subject" : model.subject
183 color: Kube.Colors.highlightedTextColor
184 maximumLineCount: 2
185 wrapMode: Text.WrapAnywhere
186 elide: Text.ElideRight
187 }
188
189 Kube.Label {
190 anchors {
191 right: parent.right
192 bottom: parent.bottom
193 }
194 text: Qt.formatDateTime(model.date, "dd MMM yyyy")
195 font.italic: true
196 color: Kube.Colors.disabledTextColor
197 font.pointSize: Kube.Units.smallFontSize
198 visible: !delegateRoot.hovered
199 }
200 }
201 Row {
202 id: buttons
203
204 anchors {
205 right: parent.right
206 bottom: parent.bottom
207 margins: Kube.Units.smallSpacing
208 }
209
210 visible: delegateRoot.hovered
211 spacing: Kube.Units.smallSpacing
212 opacity: 0.7
213
214 Kube.IconButton {
215 id: deleteButton
216 activeFocusOnTab: true
217 iconName: Kube.Icons.moveToTrash
218 visible: enabled
219 enabled: !!model.mail
220 onClicked: Kube.Fabric.postMessage(Kube.Messages.moveToTrash, {"mail": model.mail})
221 }
222 }
223 }
224 }
225 }
226 }
227
228 //Content
229 Rectangle {
230 Layout.fillWidth: true
231 Layout.minimumWidth: Kube.Units.gridUnit * 5
232 anchors {
233 top: parent.top
234 bottom: parent.bottom
235 }
236 color: Kube.Colors.backgroundColor
237
238 ColumnLayout {
239 anchors {
240 fill: parent
241 margins: Kube.Units.largeSpacing
242 leftMargin: Kube.Units.largeSpacing + Kube.Units.gridUnit * 2
243 rightMargin: Kube.Units.largeSpacing + Kube.Units.gridUnit * 2
244 }
245
246 spacing: Kube.Units.smallSpacing
247
248 Kube.TextField {
249 id: subject
250 Layout.fillWidth: true
251 activeFocusOnTab: true
252
253 placeholderText: qsTr("Enter Subject...")
254 text: composerController.subject
255 onTextChanged: composerController.subject = text;
256 onActiveFocusChanged: {
257 if (activeFocus) {
258 closeFirstSplitIfNecessary()
259 }
260 }
261 }
262
263 Flow {
264 id: attachments
265
266 Layout.fillWidth: true
267 layoutDirection: Qt.RightToLeft
268 spacing: Kube.Units.smallSpacing
269 clip: true
270
271 Repeater {
272 model: composerController.attachments.model
273 delegate: Kube.AttachmentDelegate {
274 name: model.filename
275 icon: model.iconname
276 clip: true
277 actionIcon: Kube.Icons.remove
278 onExecute: composerController.attachments.remove(model.id)
279 }
280 }
281 }
282
283 RowLayout {
284
285 spacing: Kube.Units.largeSpacing
286
287 Kube.Switch {
288 id: html
289 text: checked ? qsTr("plain") : qsTr("html")
290 focusPolicy: Qt.TabFocus
291 focus: false
292 checked: composerController.htmlBody
293 }
294
295 Row {
296 visible: html.checked
297 spacing: 1
298
299 Kube.IconButton {
300 iconName: Kube.Icons.bold
301 checkable: true
302 checked: textEditor.bold
303 onClicked: textEditor.bold = !textEditor.bold
304 focusPolicy: Qt.TabFocus
305 focus: false
306 }
307 Kube.IconButton {
308 iconName: Kube.Icons.italic
309 checkable: true
310 checked: textEditor.italic
311 onClicked: textEditor.italic = !textEditor.italic
312 focusPolicy: Qt.TabFocus
313 focus: false
314 }
315 Kube.IconButton {
316 iconName: Kube.Icons.underline
317 checkable: true
318 checked: textEditor.underline
319 onClicked: textEditor.underline = !textEditor.underline
320 focusPolicy: Qt.TabFocus
321 focus: false
322 }
323 }
324
325 Item {
326 height: 1
327 Layout.fillWidth: true
328 }
329
330 Kube.Button {
331 text: qsTr("Attach file")
332
333 onClicked: {
334 fileDialogComponent.createObject(parent)
335 }
336
337 Component {
338 id: fileDialogComponent
339 Dialogs.FileDialog {
340 id: fileDialog
341 visible: true
342 title: "Choose a file to attach"
343 selectFolder: false
344 onAccepted: {
345 composerController.attachments.add({url: fileDialog.fileUrl})
346 }
347 }
348 }
349 }
350 }
351
352 Kube.TextEditor {
353 id: textEditor
354
355 Layout.fillWidth: true
356 Layout.fillHeight: true
357 htmlEnabled: html.checked
358
359 onActiveFocusChanged: closeFirstSplitIfNecessary()
360 Keys.onEscapePressed: recipients.forceActiveFocus()
361 initialText: composerController.body
362 onTextChanged: composerController.body = text;
363 }
364 }
365 }
366
367 //Recepients
368 FocusScope {
369 id: recipients
370 anchors {
371 top: parent.top
372 bottom: parent.bottom
373 }
374 width: Kube.Units.gridUnit * 15
375 activeFocusOnTab: true
376
377 //background
378 Rectangle {
379 anchors.fill: parent
380 color: Kube.Colors.backgroundColor
381
382 Rectangle {
383 height: parent.height
384 width: 1
385 color: Kube.Colors.buttonColor
386 }
387 }
388
389 //Content
390 ColumnLayout {
391 anchors {
392 fill: parent
393 margins: Kube.Units.largeSpacing
394 }
395
396 spacing: Kube.Units.largeSpacing
397 ColumnLayout {
398 Layout.maximumWidth: parent.width
399 Layout.fillWidth: true
400 Layout.fillHeight: true
401
402 Kube.Label {
403 text: qsTr("Sending Email to:")
404 }
405
406 AddresseeListEditor {
407 Layout.preferredHeight: implicitHeight
408 Layout.fillWidth: true
409 focus: true
410 activeFocusOnTab: true
411 encrypt: composerController.encrypt
412 controller: composerController.to
413 completer: composerController.recipientCompleter
414 }
415
416 Kube.Label {
417 text: qsTr("Sending Copy to (CC):")
418 }
419 AddresseeListEditor {
420 id: cc
421 Layout.preferredHeight: cc.implicitHeight
422 Layout.fillWidth: true
423 activeFocusOnTab: true
424 encrypt: composerController.encrypt
425 controller: composerController.cc
426 completer: composerController.recipientCompleter
427 }
428
429 Kube.Label {
430 text: qsTr("Sending Secret Copy to (Bcc):")
431 }
432 AddresseeListEditor {
433 id: bcc
434 Layout.preferredHeight: bcc.implicitHeight
435 Layout.fillWidth: true
436 activeFocusOnTab: true
437 encrypt: composerController.encrypt
438 controller: composerController.bcc
439 completer: composerController.recipientCompleter
440 }
441 Item {
442 width: parent.width
443 Layout.fillHeight: true
444 }
445 }
446
447 RowLayout {
448 enabled: composerController.foundPersonalKeys
449 Kube.CheckBox {
450 id: encryptCheckbox
451 checked: composerController.encrypt
452 }
453 Kube.Label {
454 text: qsTr("encrypt")
455 }
456 }
457
458 RowLayout {
459 enabled: composerController.foundPersonalKeys
460 Kube.CheckBox {
461 id: signCheckbox
462 checked: composerController.sign
463 }
464 Kube.Label {
465 text: qsTr("sign")
466 }
467 }
468 Kube.Label {
469 visible: !composerController.foundPersonalKeys
470 Layout.maximumWidth: parent.width
471 text: qsTr("Encryption is not available because your personal key has not been found.")
472 wrapMode: Text.Wrap
473 }
474
475 RowLayout {
476 Layout.maximumWidth: parent.width
477 width: parent.width
478 height: Kube.Units.gridUnit
479
480 Kube.Button {
481 width: saveDraftButton.width
482 text: qsTr("Discard")
483 onClicked: Kube.Fabric.postMessage(Kube.Messages.componentDone, {})
484 }
485
486 Kube.Button {
487 id: saveDraftButton
488
489 text: qsTr("Save as Draft")
490 enabled: composerController.saveAsDraftAction.enabled
491 onClicked: {
492 composerController.saveAsDraftAction.execute()
493 }
494 }
495 }
496
497 ColumnLayout {
498 Layout.maximumWidth: parent.width
499 Layout.fillWidth: true
500 Kube.Label {
501 id: fromLabel
502 text: qsTr("You are sending this from:")
503 }
504
505 Kube.ComboBox {
506 id: identityCombo
507
508 width: parent.width - Kube.Units.largeSpacing * 2
509
510 model: composerController.identitySelector.model
511 textRole: "address"
512 Layout.fillWidth: true
513 onCurrentIndexChanged: {
514 composerController.identitySelector.currentIndex = currentIndex
515 }
516 }
517 }
518
519 Kube.PositiveButton {
520 objectName: "sendButton"
521 id: sendButton
522
523 width: parent.width
524
525 text: qsTr("Send")
526 enabled: composerController.sendAction.enabled
527 onClicked: {
528 composerController.sendAction.execute()
529 }
530 }
531 }
532 }//FocusScope
533}