Warning, /plasma/plasma-systemmonitor/src/page/EditablePage.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 import QtQuick 2.12 0008 import QtQuick.Controls 2.12 0009 import QtQuick.Layouts 1.12 0010 0011 import org.kde.kirigami 2.12 as Kirigami 0012 0013 import org.kde.ksysguard.page 1.0 0014 0015 Kirigami.ScrollablePage { 0016 id: page 0017 0018 property PageDataObject pageData 0019 property bool edit: false 0020 0021 title: pageData.title 0022 0023 leftPadding: pageData.margin * Kirigami.Units.largeSpacing 0024 rightPadding: pageData.margin * Kirigami.Units.largeSpacing 0025 topPadding: pageData.margin * Kirigami.Units.largeSpacing 0026 bottomPadding: pageData.margin * Kirigami.Units.largeSpacing 0027 0028 Kirigami.ColumnView.fillWidth: true 0029 Kirigami.ColumnView.reservedSpace: edit ? applicationWindow().pageStack.columnView.columnWidth : 0 0030 0031 Binding { 0032 target: globalToolBarItem 0033 property: "enabled" 0034 value: contentLoader.status != Loader.Loading 0035 } 0036 0037 readonly property real heightForContent: (parent ? parent.height : 0) - topPadding - bottomPadding - (globalToolBarItem ? globalToolBarItem.height : 0) 0038 0039 readonly property var actionsFace: contentLoader.item && contentLoader.item.actionsFace ? contentLoader.item.actionsFace : null 0040 onActionsFaceChanged: Qt.callLater(updateActions) 0041 Connections { 0042 target: page.actionsFace 0043 function onPrimaryActionsChanged() { Qt.callLater(page.updateActions) } 0044 function onSecondaryActionsChanged() { Qt.callLater(page.updateActions) } 0045 } 0046 0047 function updateActions() { 0048 actions.main = null 0049 actions.left = null 0050 actions.right = null 0051 0052 if (!actionsFace || page.edit) { 0053 actions.contextualActions = defaultActions 0054 return 0055 } 0056 0057 let primary = page.actionsFace.primaryActions 0058 let secondary = page.actionsFace.secondaryActions 0059 0060 if (primary.length == 0 && secondary.length == 0) { 0061 if (actions.contextualActions == defaultActions) { 0062 return; 0063 } 0064 0065 actions.contextualActions = defaultActions 0066 return 0067 } 0068 0069 if (primary.length >= 1) { 0070 actions.main = primary[0] 0071 } 0072 0073 if (primary.length >= 2) { 0074 actions.left = primary[1] 0075 } 0076 0077 if (primary.length >= 3) { 0078 actions.right = primary[2] 0079 } 0080 0081 let contextual = [] 0082 0083 if (primary.length >= 4) { 0084 contextual = Array.prototype.map.call(primary, i => i).slice(4) 0085 } 0086 0087 if (secondary.length > 0) { 0088 contextual = contextual.concat(Array.prototype.map.call(secondary, i => i)) 0089 } 0090 0091 actions.contextualActions = contextual.concat(defaultActions) 0092 } 0093 0094 // Scroll the contents of the page based on the position of a rect (in scene 0095 // coordinates). If any part of the rect is above the visible area, contents 0096 // will be scrolled down. If any part of the rect is below the visible area, 0097 // contents will be scrolled up instead. This mimics dragging behaviour of 0098 // file managers and similar things. 0099 function scrollContents(rect) { 0100 let visibleRect = page.flickable.mapToItem(null, Qt.rect(page.flickable.x, page.flickable.y, page.flickable.width, page.flickable.height - page.bottomPadding)) 0101 0102 let minY = rect.y 0103 let maxY = rect.y + rect.height 0104 0105 let visibleTop = visibleRect.y 0106 let visibleBottom = visibleRect.y + visibleRect.height 0107 0108 if (minY >= visibleTop && maxY <= visibleBottom) { 0109 return 0110 } 0111 0112 if (maxY > visibleBottom && !page.flickable.atYEnd) { 0113 page.flickable.contentY += (maxY - visibleBottom) 0114 } else if (minY < visibleTop && !page.flickable.atYBeginning) { 0115 page.flickable.contentY += (minY - visibleTop) 0116 } 0117 page.flickable.returnToBounds() 0118 } 0119 0120 Kirigami.Action { 0121 id: editAction 0122 0123 text: i18nc("@action", "Edit Page") 0124 icon.name: "document-edit" 0125 visible: !page.edit 0126 0127 displayHint: page.actionsFace ? Kirigami.Action.DisplayHint.AlwaysHide : Kirigami.Action.DisplayHint.NoPreference 0128 0129 onTriggered: page.edit = !page.edit 0130 } 0131 Kirigami.Action { 0132 id: saveAction 0133 text: i18nc("@action", "Save Changes") 0134 icon.name: "document-save" 0135 visible: page.edit 0136 onTriggered: { 0137 page.edit = false 0138 page.pageData.savePage() 0139 } 0140 } 0141 Kirigami.Action { 0142 id: discardAction 0143 text: i18nc("@action", "Discard Changes") 0144 icon.name: "edit-delete-remove" 0145 visible: page.edit 0146 onTriggered: { 0147 page.edit = false 0148 page.pageData.resetPage() 0149 } 0150 } 0151 Kirigami.Action { 0152 id: configureAction 0153 0154 text: i18nc("@action", "Configure Pageā¦") 0155 icon.name: "configure" 0156 visible: page.edit 0157 0158 onTriggered: pageDialog.open() 0159 } 0160 Kirigami.Action { 0161 id: addRowAction 0162 0163 text: i18nc("@action", "Add Row") 0164 icon.name: "edit-table-insert-row-under" 0165 visible: page.edit 0166 0167 onTriggered: contentLoader.item.addRow(-1) 0168 } 0169 0170 Kirigami.Action { 0171 id: addTitleAction 0172 text: i18nc("@action", "Add Title") 0173 icon.name: "insert-text-frame" 0174 visible: page.edit 0175 0176 onTriggered: contentLoader.item.addTitle(-1) 0177 } 0178 0179 readonly property var defaultActions: [editAction, saveAction, discardAction, addRowAction, addTitleAction, configureAction] 0180 0181 Component { 0182 id: pageEditor 0183 0184 PageEditor { 0185 parentPage: page 0186 pageData: page.pageData 0187 } 0188 } 0189 0190 Component { 0191 id: pageContents 0192 0193 PageContents { 0194 pageData: page.pageData 0195 } 0196 } 0197 0198 data: [ 0199 DialogLoader { 0200 id: pageDialog 0201 sourceComponent: PageDialog { 0202 title: i18nc("@title:window %1 is page title", "Configure Page \"%1\"", page.pageData.title) 0203 0204 acceptText: i18nc("@action:button", "Save") 0205 acceptIcon: "document-save" 0206 0207 onAboutToShow: { 0208 name = page.pageData.title 0209 iconName = page.pageData.icon 0210 margin = page.pageData.margin 0211 pageData = page.pageData 0212 actionsFace = page.pageData.actionsFace ? page.pageData.actionsFace : "" 0213 loadType = page.pageData.loadType ? page.pageData.loadType : "ondemand" 0214 } 0215 0216 onAccepted: { 0217 pageData.title = name 0218 pageData.icon = iconName 0219 pageData.margin = margin 0220 pageData.actionsFace = actionsFace 0221 pageData.loadType = loadType 0222 } 0223 } 0224 }, 0225 DialogLoader { 0226 id: missingSensorsDialog 0227 0228 sourceComponent: MissingSensorsDialog { 0229 missingSensors: contentLoader.item ? contentLoader.item.missingSensors : [] 0230 0231 onSensorReplacementChanged: { 0232 contentLoader.item.replaceSensors(sensorReplacement) 0233 } 0234 } 0235 } 0236 ] 0237 0238 Rectangle { 0239 id: loadOverlay 0240 0241 parent: page.overlay 0242 anchors.fill: parent 0243 anchors.margins: -pageData.margin * Kirigami.Units.largeSpacing 0244 color: Kirigami.Theme.backgroundColor 0245 0246 opacity: 1 0247 visible: opacity > 0 0248 Behavior on opacity { OpacityAnimator { duration: Kirigami.Units.shortDuration } } 0249 0250 BusyIndicator { 0251 anchors.centerIn: parent 0252 running: loadOverlay.visible 0253 } 0254 } 0255 0256 Loader { 0257 id: contentLoader 0258 0259 width: page.width 0260 height: item ? Math.max(item.Layout.minimumHeight, page.heightForContent) : page.heightForContent 0261 0262 property real availableHeight: page.heightForContent 0263 property real rowSpacing: page.pageData.margin * Kirigami.Units.smallSpacing 0264 0265 sourceComponent: page.edit ? pageEditor : pageContents 0266 asynchronous: true 0267 0268 onStatusChanged: { 0269 if (status == Loader.Loading) { 0270 loadOverlay.opacity = 1 0271 if (!edit && applicationWindow().pageStack.columnView.containsItem(page)) { 0272 // Pop any pages that might have been opened during editing 0273 applicationWindow().pageStack.pop(page) 0274 } 0275 } else { 0276 Qt.callLater(updateActions) 0277 page.flickable.returnToBounds() 0278 loadOverlay.opacity = 0 0279 } 0280 } 0281 0282 Connections { 0283 target: contentLoader.item 0284 0285 function onShowMissingSensors() { 0286 missingSensorsDialog.open() 0287 } 0288 } 0289 } 0290 }