Warning, /pim/kube/framework/qml/MailViewer.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 * Copyright (C) 2016 Michael Bohlender, <michael.bohlender@kdemail.net>
0003 * Copyright (C) 2017 Christian Mollekopf, <mollekopf@kolabsys.com>
0004 *
0005 * This program is free software; you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation; either version 2 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License along
0016 * with this program; if not, write to the Free Software Foundation, Inc.,
0017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0018 */
0019
0020 import QtQuick 2.7
0021 import QtQuick.Controls 1.4 as Controls1
0022 import QtQuick.Controls 2
0023 import QtQuick.Layouts 1.1
0024
0025 import "mailpartview" as MPV
0026 import org.kube.framework 1.0 as Kube
0027
0028 Rectangle {
0029 id: root
0030
0031 property var mail
0032 property var message
0033 property string subject
0034 property string sender
0035 property string senderName
0036 property string to
0037 property string cc
0038 property string bcc
0039 property date date
0040 property bool trash
0041 property bool draft
0042 property bool sent
0043 property bool busy: false
0044 property string busyMessage: qsTr("Incomplete body...")
0045 property bool current: false
0046 property bool unread
0047 property alias searchString: mailViewer.searchString
0048 property alias autoLoadImages: mailViewer.autoLoadImages
0049 property alias loaded: messageParser.loaded
0050 property bool collapsed: false
0051
0052 implicitHeight: mainLayout.height + 2 * Kube.Units.largeSpacing
0053
0054 Shortcut {
0055 sequence: "V"
0056 onActivated: debugPopupComponent.createObject(root).open()
0057 enabled: root.current
0058 }
0059
0060 //highlight active mails
0061 border.width: current ? 1 : 0
0062 border.color: Kube.Colors.highlightColor
0063
0064 color: Kube.Colors.viewBackgroundColor
0065
0066 Kube.MessageParser {
0067 id: messageParser
0068 message: root.message
0069 }
0070 property var partModel: messageParser.parts
0071 property var attachmentModel: messageParser.attachments
0072
0073 states: [
0074 State {
0075 name: "busy"; when: root.busy || !root.loaded
0076 PropertyChanges { target: buttonContainer; visible: false}
0077 PropertyChanges { target: body; visible: false}
0078 PropertyChanges { target: footer; visible: false}
0079 PropertyChanges { target: busyBody; visible: true}
0080 },
0081 State {
0082 name: "collapsed"; when: root.collapsed
0083 PropertyChanges { target: buttonContainer; visible: false}
0084 PropertyChanges { target: body; visible: false}
0085 PropertyChanges { target: footer; visible: false}
0086 PropertyChanges { target: collapsedBody; visible: true}
0087 },
0088 State {
0089 name: "full"; when: !root.collapsed && !root.busy && root.loaded
0090 PropertyChanges { target: buttonContainer; visible: true}
0091 PropertyChanges { target: body; visible: true}
0092 PropertyChanges { target: footer; visible: true}
0093 PropertyChanges { target: collapsedBody; visible: false}
0094 }
0095 ]
0096 state: "full"
0097
0098 //Must be lower in the stacking order than TextContent, otherwise link hovering breaks
0099 MouseArea {
0100 enabled: root.collapsed
0101 hoverEnabled: root.collapsed
0102 anchors.fill: parent
0103 onClicked: {
0104 root.collapsed = !root.collapsed
0105 }
0106
0107 Rectangle {
0108 anchors.fill: parent
0109 color: Kube.Colors.highlightColor
0110 opacity: 0.4
0111 visible: root.collapsed && parent.containsMouse
0112 }
0113 }
0114
0115 Column {
0116 id: mainLayout
0117 anchors {
0118 top: parent.top
0119 left: parent.left
0120 right: parent.right
0121 margins: Kube.Units.largeSpacing
0122 }
0123 height: childrenRect.height
0124
0125 spacing: Kube.Units.smallSpacing
0126
0127 //BEGIN header
0128 Item {
0129 id: header
0130
0131 Layout.fillWidth: true
0132 anchors {
0133 left: parent.left
0134 right: parent.right
0135 }
0136 height: headerContent.height + Kube.Units.smallSpacing
0137
0138 states: [
0139 State {
0140 name: "small"
0141 PropertyChanges { target: subject; wrapMode: Text.NoWrap}
0142 PropertyChanges { target: recipients; visible: true}
0143 PropertyChanges { target: to; visible: false}
0144 PropertyChanges { target: cc; visible: false}
0145 PropertyChanges { target: bcc; visible: false}
0146 },
0147 State {
0148 name: "details"
0149 PropertyChanges { target: subject; wrapMode: Text.WrapAnywhere}
0150 PropertyChanges { target: recipients; visible: false}
0151 PropertyChanges { target: to; visible: true}
0152 PropertyChanges { target: cc; visible: root.cc}
0153 PropertyChanges { target: bcc; visible: root.bcc}
0154 }
0155 ]
0156
0157 state: "small"
0158
0159 Kube.Label {
0160 id: date_label
0161
0162 anchors {
0163 right: seperator.right
0164 top: parent.top
0165 }
0166
0167 text: Qt.formatDateTime(root.date, "dd MMM yyyy hh:mm")
0168
0169 font.pointSize: Kube.Units.tinyFontSize
0170 opacity: 0.75
0171 }
0172
0173 Column {
0174 id: headerContent
0175
0176 anchors {
0177 //left: to_l.right
0178 horizontalCenter: parent.horizontalCenter
0179 }
0180
0181 //spacing: Kube.Units.smallSpacing
0182
0183 width: parent.width
0184
0185 Row{
0186 id: from
0187
0188 width: parent.width
0189
0190 spacing: Kube.Units.smallSpacing
0191 clip: true
0192
0193 Kube.SelectableLabel {
0194 id: senderName
0195
0196 text: root.senderName
0197 font.weight: Font.DemiBold
0198 opacity: 0.75
0199 states: [
0200 State {
0201 name: "sent"; when: root.sent
0202 PropertyChanges { target: senderName; text: qsTr("Sent from") }
0203 },
0204 State {
0205 name: "draft"; when: root.draft
0206 PropertyChanges { target: senderName; text: qsTr("Draft from") }
0207 }
0208 ]
0209 }
0210
0211 Kube.SelectableLabel {
0212 width: parent.width - senderName.width - date_label.width - Kube.Units.largeSpacing
0213
0214 text: root.sender
0215 elide: Text.ElideRight
0216 opacity: 0.75
0217 clip: true
0218
0219 Kube.TextButton {
0220 text: qsTr("Send mail to")
0221 onClicked: Kube.Fabric.postMessage(Kube.Messages.compose, {"recipients": [root.sender]})
0222 }
0223 }
0224 }
0225
0226 Kube.SelectableLabel {
0227 id: subject
0228
0229 width: to.width
0230
0231 text: root.subject
0232 elide: Text.ElideRight
0233 opacity: 0.75
0234 font.italic: true
0235 states: [
0236 State {
0237 name: "trash"; when: root.trash
0238 PropertyChanges { target: subject; text: qsTr("Trash: %1").arg(root.subject) }
0239 }
0240 ]
0241 }
0242
0243 Kube.SelectableLabel {
0244 id: recipients
0245
0246 width: parent.width - goDown.width - Kube.Units.smallSpacing
0247
0248 text: "to: "+ root.to + " " + root.cc + " " + root.bcc
0249 copyText: [root.to, root.cc, root.bcc].filter(s => !!s).join()
0250 elide: Text.ElideRight
0251 opacity: 0.75
0252
0253 Kube.TextButton {
0254 text: qsTr("Send mail to")
0255 onClicked: Kube.Fabric.postMessage(Kube.Messages.compose, {"recipients": [[root.to, root.cc, root.bcc].filter(s => !!s).join()]})
0256 }
0257 }
0258
0259 Kube.SelectableLabel {
0260 id: to
0261
0262 width: parent.width - goDown.width - Kube.Units.smallSpacing
0263
0264 text: "to: " + root.to
0265 copyText: root.to
0266 wrapMode: Text.WordWrap
0267 opacity: 0.75
0268 }
0269
0270 Kube.SelectableLabel {
0271 id: cc
0272
0273 width: parent.width - goDown.width - Kube.Units.smallSpacing
0274
0275 text: "cc: " + root.cc
0276 copyText: root.cc
0277 wrapMode: Text.WordWrap
0278 opacity: 0.75
0279 }
0280
0281 Kube.SelectableLabel {
0282 id: bcc
0283
0284 width: parent.width - goDown.width - Kube.Units.smallSpacing
0285
0286 text: "bcc: " + root.bcc
0287 copyText: root.bcc
0288 wrapMode: Text.WordWrap
0289 opacity: 0.75
0290 }
0291
0292 }
0293
0294 Rectangle {
0295 id: goDown
0296 anchors {
0297 bottom: seperator.top
0298 right: seperator.right
0299 }
0300
0301 //Only show the expand button if there is something to expand
0302 visible: recipients.truncated || root.cc || root.bcc
0303
0304 height: Kube.Units.gridUnit
0305 width: height
0306
0307 color: Kube.Colors.backgroundColor
0308
0309 Kube.IconButton {
0310 anchors.fill: parent
0311 activeFocusOnTab: false
0312
0313 iconName: header.state === "details" ? Kube.Icons.goUp : Kube.Icons.goDown
0314
0315 onClicked: {
0316 header.state === "details" ? header.state = "small" : header.state = "details"
0317 }
0318 }
0319 }
0320
0321 Rectangle {
0322 id: seperator
0323
0324 anchors {
0325 left: parent.left
0326 right: parent.right
0327 bottom: parent.bottom
0328 }
0329
0330 height: 1
0331
0332 color: Kube.Colors.textColor
0333 opacity: 0.5
0334 }
0335 }
0336 //END header
0337
0338 Item {
0339 anchors {
0340 left: parent.left
0341 right: parent.right
0342 }
0343 id: buttonContainer
0344 //We're not setting visible, because setting the parent property (of buttonContainer),
0345 //while also depending on the child-property values (htmlButton and attachments) does not work.
0346 height: (attachments.visible || htmlButton.visible) ? Math.max(attachments.height, htmlButton.height) : 0
0347 Kube.TextButton {
0348 id: htmlButton
0349 objectName: "htmlButton"
0350 anchors {
0351 left: parent.left
0352 top: parent.top
0353 }
0354 opacity: 0.5
0355 visible: root.partModel ? root.partModel.containsHtml : false
0356 text: root.partModel ? (root.partModel.showHtml ? "Plain" : "Html") : ""
0357 onClicked: {
0358 root.partModel.showHtml = !root.partModel.showHtml
0359 }
0360 }
0361
0362 Flow {
0363 id: attachments
0364
0365 anchors {
0366 left: parent.left
0367 right: parent.right
0368 }
0369
0370 width: header.width - Kube.Units.largeSpacing
0371 height: visible ? implicitHeight : 0
0372
0373 layoutDirection: Qt.RightToLeft
0374 spacing: Kube.Units.smallSpacing
0375 clip: true
0376 visible: attachmentRepeater.count
0377
0378 Repeater {
0379 id: attachmentRepeater
0380 model: root.attachmentModel
0381
0382 delegate: AttachmentDelegate {
0383 name: model.name
0384 type: model.type
0385 icon: model.iconName
0386
0387 clip: true
0388
0389 actionIcon: Kube.Icons.save_inverted
0390 actionTooltip: qsTr("Save attachment")
0391 onExecute: root.attachmentModel.saveAttachmentToDisk(root.attachmentModel.index(index, 0))
0392 onClicked: root.attachmentModel.openAttachment(root.attachmentModel.index(index, 0))
0393 onPublicKeyImport: root.attachmentModel.importPublicKey(root.attachmentModel.index(index, 0))
0394 }
0395 }
0396 }
0397 }
0398
0399 Item {
0400 id: body
0401
0402 visible: true
0403 anchors {
0404 left: parent.left
0405 right: parent.right
0406 }
0407 height: visible ? mailViewer.height + 20 : 0
0408 MPV.MailPartView {
0409 id: mailViewer
0410 objectName: "mailViewer"
0411 anchors.top: body.top
0412 anchors.left: body.left
0413 anchors.right: body.right
0414 model: root.partModel
0415 }
0416
0417 }
0418
0419 Kube.Label {
0420 id: busyBody
0421 anchors {
0422 left: parent.left
0423 right: parent.right
0424 }
0425 visible: false
0426 height: visible ? implicitHeight : 0
0427 text: root.busyMessage
0428 color: Kube.Colors.textColor
0429 enabled: false
0430 }
0431
0432 Kube.IconButton {
0433 id: collapsedBody
0434 anchors {
0435 left: parent.left
0436 right: parent.right
0437 }
0438 visible: false
0439 enabled: false
0440 iconName: Kube.Icons.goDown
0441 }
0442
0443 Kube.TextButton {
0444 anchors {
0445 left: parent.left
0446 }
0447 width: Kube.Units.gridUnit
0448 height: Kube.Units.gridUnit
0449 padding: 0
0450 visible: root.partModel && root.partModel.isTrimmed && !root.collapsed
0451 // Center dots instead of ...
0452 text: "\u00B7\u00B7\u00B7"
0453 opacity: 50
0454 onClicked: {
0455 root.partModel.trimMail = !root.partModel.trimMail
0456 }
0457 }
0458
0459 Item {
0460 id: footer
0461 property var mail: root.mail
0462 property string subject: root.subject
0463
0464 anchors {
0465 left: parent.left
0466 right: parent.right
0467 }
0468
0469 visible: true
0470 height: visible ? Kube.Units.gridUnit : 0
0471 width: parent.width
0472
0473 Kube.TextButton {
0474 anchors{
0475 verticalCenter: parent.verticalCenter
0476 left: parent.left
0477 }
0478 activeFocusOnTab: false
0479
0480 text: root.trash ? qsTr("Delete Mail") : root.draft ? qsTr("Discard") : qsTr("Move to trash")
0481 opacity: 0.5
0482 onClicked: {
0483 if (root.trash) {
0484 Kube.Fabric.postMessage(Kube.Messages.remove, {"mail": root.mail})
0485 } else {
0486 Kube.Fabric.postMessage(Kube.Messages.moveToTrash, {"mail": root.mail})
0487 }
0488 }
0489 }
0490
0491 Row {
0492 anchors {
0493 verticalCenter: parent.verticalCenter
0494 right: parent.right
0495 }
0496 spacing: Kube.Units.smallSpacing
0497
0498 Kube.Button {
0499 visible: !root.trash && !root.draft
0500 activeFocusOnTab: false
0501
0502 text: qsTr("Share")
0503 onClicked: {
0504 Kube.Fabric.postMessage(Kube.Messages.forward, {"mail": root.mail})
0505 }
0506 }
0507
0508 Kube.Button {
0509 visible: !root.trash
0510 activeFocusOnTab: false
0511
0512 text: root.draft ? qsTr("Edit") : qsTr("Reply")
0513 onClicked: {
0514 if (root.draft) {
0515 Kube.Fabric.postMessage(Kube.Messages.edit, {"mail": root.mail})
0516 } else {
0517 Kube.Fabric.postMessage(Kube.Messages.reply, {"mail": root.mail})
0518 }
0519 }
0520 }
0521 Row {
0522 Kube.ExtensionPoint {
0523 extensionPoint: "extensions/mailview"
0524 context: {"mail": footer.mail, "subject": footer.subject, "accountId": Kube.Context.currentAccountId}
0525 }
0526 }
0527 }
0528 }
0529 } //ColumnLayout
0530
0531 //Dimm unread messages (but never treat messages as unread that we have sent ourselves)
0532 Rectangle {
0533 anchors.fill: parent
0534 color: Kube.Colors.buttonColor
0535 opacity: 0.4
0536 visible: root.unread && !root.sent
0537 }
0538
0539 Component {
0540 id: debugPopupComponent
0541 Kube.Popup {
0542 id: debugPopup
0543 modal: true
0544 parent: ApplicationWindow.overlay
0545 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
0546 x: (parent.width - width)/2
0547 y: Kube.Units.largeSpacing
0548 width: parent.width / 2
0549 height: parent.height - Kube.Units.largeSpacing * 2
0550 clip: true
0551
0552 Flickable {
0553 id: flickable
0554 anchors.fill: parent
0555 ScrollBar.vertical: Kube.ScrollBar {}
0556 contentHeight: content.height
0557 contentWidth: parent.width
0558 Column {
0559 id: content
0560 width: flickable.width
0561 height: childrenRect.height
0562
0563 TextEdit {
0564 id: structure
0565 width: parent.width
0566 readOnly: true
0567 selectByMouse: true
0568 textFormat: TextEdit.PlainText
0569 wrapMode: TextEdit.Wrap
0570 height: implicitHeight
0571 text: messageParser.structureAsString
0572 }
0573
0574 TextEdit {
0575 id: rawContent
0576 width: parent.width
0577 readOnly: true
0578 selectByMouse: true
0579 textFormat: TextEdit.PlainText
0580 wrapMode: TextEdit.Wrap
0581 height: implicitHeight
0582 text: messageParser.rawContent.substring(0, 100000) //The TextEdit deals poorly with messages that are too large.
0583 }
0584 Rectangle {
0585 color: "black"
0586 height: 2
0587 }
0588 Controls1.TreeView {
0589 id: mailStructure
0590 width: parent.width
0591 height: implicitHeight
0592 Controls1.TableViewColumn {
0593 role: "type"
0594 title: "Type"
0595 }
0596 Controls1.TableViewColumn {
0597 role: "embedded"
0598 title: "Embedded"
0599 }
0600 Controls1.TableViewColumn {
0601 role: "securityLevel"
0602 title: "SecurityLevel"
0603 }
0604 Controls1.TableViewColumn {
0605 role: "content"
0606 title: "Content"
0607 }
0608 model: messageParser.parts
0609 itemDelegate: Item {
0610 property variant currentData: styleData.value
0611 Text {
0612 anchors.fill: parent
0613 color: styleData.textColor
0614 elide: Text.ElideRight
0615 text: styleData.value ? styleData.value : ""
0616 textFormat: Text.PlainText
0617 }
0618 MouseArea {
0619 anchors.fill: parent
0620 onClicked: {
0621 textEdit.text = styleData.value
0622 }
0623 }
0624 }
0625 }
0626 Controls1.TreeView {
0627 id: attachmentsTree
0628 width: parent.width
0629 height: implicitHeight
0630 Controls1.TableViewColumn {
0631 role: "type"
0632 title: "Type"
0633 }
0634 Controls1.TableViewColumn {
0635 role: "name"
0636 title: "Name"
0637 }
0638 Controls1.TableViewColumn {
0639 role: "size"
0640 title: "Size"
0641 }
0642 model: messageParser.attachments
0643 }
0644 TextEdit {
0645 id: textEdit
0646 width: parent.width
0647 readOnly: true
0648 selectByMouse: true
0649 textFormat: TextEdit.PlainText
0650 wrapMode: TextEdit.Wrap
0651 height: implicitHeight
0652 }
0653 }
0654 }
0655 Kube.ScrollHelper {
0656 id: scrollHelper
0657 flickable: flickable
0658 anchors.fill: parent
0659 }
0660 }
0661 }
0662 }