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 }