Warning, /plasma/plasma-systemmonitor/src/page/PageContents.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 0008 import QtQuick.Controls 0009 import QtQuick.Layouts 0010 0011 0012 import org.kde.kirigami as Kirigami 0013 import org.kde.ksysguard.faces as Faces 0014 import org.kde.ksysguard.page 0015 0016 ColumnLayout { 0017 id: root 0018 0019 property PageDataObject pageData 0020 property var actionsFace 0021 property var missingSensors: [] 0022 0023 property var faceMapping: new Object() 0024 0025 signal showMissingSensors() 0026 0027 function replaceSensors(replacement) { 0028 if (!replacement) { 0029 return 0030 } 0031 0032 missingSensors = [] 0033 0034 let modifiedControllers = [] 0035 0036 for (let entry of replacement) { 0037 let controller = faceMapping[entry.face].controller 0038 controller.replaceSensors(entry.sensor, entry.replacement) 0039 modifiedControllers.push(controller) 0040 } 0041 0042 for (let c of modifiedControllers) { 0043 c.reloadConfig() 0044 } 0045 } 0046 0047 spacing: rowSpacing // From parent Loader 0048 0049 readonly property real balancedRowHeight: { 0050 let reservedSpace = 0; 0051 let minimumSpace = 0; 0052 let balancedCount = 0; 0053 let maximumCount = 0; 0054 0055 for (let i in children) { 0056 let child = children[i] 0057 if (!child.hasOwnProperty("heightMode") || !child.hasOwnProperty("minimumContentHeight")) { 0058 continue 0059 } 0060 0061 switch(child.heightMode) { 0062 case "minimum": 0063 reservedSpace += child.minimumContentHeight 0064 break; 0065 case "balanced": 0066 minimumSpace = Math.max(child.minimumContentHeight, minimumSpace) 0067 balancedCount += 1 0068 break; 0069 case "maximum": 0070 maximumCount += 1 0071 break; 0072 } 0073 } 0074 0075 // If there's nothing to balance, we can ignore the rest. 0076 if (balancedCount == 0) { 0077 return 0 0078 } 0079 0080 // If there's any rows that are set to "maximum", use the largest 0081 // minimum size for balanced rows. 0082 if (maximumCount > 0) { 0083 return minimumSpace 0084 } 0085 0086 // Note that "availableHeight" here comes from the parent loader and 0087 // represents the available size of the content area of the page. 0088 let balancedHeight = (availableHeight - reservedSpace - root.spacing * (children.length - 1)) / balancedCount 0089 return Math.max(balancedHeight, minimumSpace) 0090 } 0091 0092 Kirigami.InlineMessage { 0093 id: missingMessage 0094 0095 Layout.fillWidth: true 0096 0097 visible: root.missingSensors.length > 0 0098 type: Kirigami.MessageType.Error 0099 text: i18n("This page is missing some sensors and will not display correctly."); 0100 0101 actions: Kirigami.Action { 0102 icon.name: "document-edit" 0103 text: i18nc("@action:button", "Fix…") 0104 onTriggered: root.showMissingSensors() 0105 } 0106 } 0107 0108 Repeater { 0109 model: PageDataModel { data: root.pageData } 0110 0111 ConditionalLoader { 0112 required property var model 0113 0114 readonly property real minimumContentHeight: model.data.isTitle ? item.height : item.Layout.minimumHeight 0115 0116 readonly property string heightMode: { 0117 if (model.data.heightMode) { 0118 return model.data.heightMode 0119 } 0120 0121 if (model.data.isTitle) { 0122 return "minimum" 0123 } 0124 0125 return "balanced" 0126 } 0127 0128 Layout.fillWidth: true 0129 Layout.fillHeight: heightMode != "minimum" 0130 Layout.preferredHeight: 0 0131 Layout.minimumHeight: { 0132 if (heightMode == "minimum") { 0133 return minimumContentHeight 0134 } 0135 0136 if (heightMode == "balanced") { 0137 return root.balancedRowHeight 0138 } 0139 0140 return -1 0141 } 0142 Layout.maximumHeight: { 0143 if (heightMode == "minimum") { 0144 return minimumContentHeight 0145 } 0146 0147 if (heightMode == "balanced") { 0148 return root.balancedRowHeight 0149 } 0150 0151 return -1 0152 } 0153 0154 condition: model.data.isTitle 0155 0156 sourceTrue: Kirigami.Heading { 0157 anchors.left: parent.left 0158 level: 2 0159 text: model.data.title ? model.data.title : "" 0160 } 0161 0162 sourceFalse: GridLayout { 0163 id: rowContents 0164 0165 anchors.fill: parent 0166 0167 columnSpacing: Kirigami.Units.largeSpacing 0168 rowSpacing: Kirigami.Units.largeSpacing 0169 0170 Repeater { 0171 model: PageDataModel { data: model.data } 0172 0173 ConditionalLoader { 0174 required property var model 0175 0176 Layout.fillWidth: true 0177 Layout.fillHeight: true 0178 Layout.minimumHeight: item.Layout.minimumHeight + (model.data.noMargins ? 0 : Kirigami.Units.largeSpacing * 2) 0179 Layout.preferredWidth: 0 0180 0181 component ColumnContents: RowLayout { 0182 id: columnContents 0183 0184 anchors.fill: parent 0185 anchors.margins: model.data.noMargins ? 0 : Kirigami.Units.largeSpacing 0186 0187 spacing: Kirigami.Units.largeSpacing 0188 0189 layer.enabled: (model.data.showBackground && model.data.noMargins) ?? false 0190 layer.effect: Kirigami.ShadowedTexture { 0191 radius: Kirigami.Units.smallSpacing 0192 } 0193 0194 Repeater { 0195 model: PageDataModel { data: model.data } 0196 0197 ConditionalLoader { 0198 required property var model 0199 0200 Layout.fillHeight: true 0201 Layout.fillWidth: item?.Layout.fillWidth ?? true 0202 Layout.preferredWidth: item?.Layout.preferredWidth ?? 0 0203 Layout.minimumHeight: item?.Layout.minimumHeight ?? 0 0204 0205 condition: model.data.isSeparator 0206 0207 sourceTrue: Kirigami.Separator { Layout.preferredWidth: 1 } 0208 0209 sourceFalse: faceComponent 0210 } 0211 } 0212 } 0213 0214 condition: model.data.showBackground 0215 0216 sourceTrue: Kirigami.AbstractCard { 0217 anchors.fill: parent 0218 0219 Layout.minimumHeight: contents.Layout.minimumHeight 0220 0221 ColumnContents { id: contents } 0222 } 0223 0224 sourceFalse: ColumnContents { } 0225 } 0226 } 0227 } 0228 } 0229 } 0230 0231 Component { 0232 id: faceComponent 0233 0234 Control { 0235 leftPadding: 0 0236 rightPadding: 0 0237 topPadding: 0 0238 bottomPadding: 0 0239 0240 Layout.preferredWidth: 0 0241 Layout.minimumHeight: contentItem ? contentItem.Layout.minimumHeight : 0 0242 Layout.fillWidth: true 0243 0244 FaceLoader { 0245 id: loader 0246 dataObject: model.data 0247 0248 Component.onCompleted: { 0249 root.faceMapping[model.data.face] = loader 0250 } 0251 } 0252 0253 Connections { 0254 target: loader.controller 0255 0256 function onMissingSensorsChanged() { 0257 for (let i of missingSensors) { 0258 root.missingSensors.push({ 0259 "face": model.data.face, 0260 "title": loader.controller.title, 0261 "sensor": i 0262 }) 0263 } 0264 root.missingSensorsChanged() 0265 } 0266 0267 Component.onCompleted: { 0268 root.faceMapping[model.data.face] = loader 0269 } 0270 } 0271 0272 Component.onCompleted: { 0273 loader.controller.fullRepresentation.formFactor = Faces.SensorFace.Constrained; 0274 contentItem = loader.controller.fullRepresentation 0275 0276 if (root.pageData.actionsFace == model.data.face) { 0277 root.actionsFace = loader.controller.fullRepresentation 0278 } 0279 } 0280 TapHandler { 0281 acceptedButtons: Qt.RightButton 0282 enabled: WidgetExporter.plasmashellAvailable 0283 onTapped: eventPoint => { 0284 const point = parent.mapToItem(contextMenu.parent, eventPoint.position) 0285 contextMenu.x = point.x 0286 contextMenu.y = point.y 0287 contextMenu.loader = loader 0288 contextMenu.open() 0289 } 0290 } 0291 } 0292 } 0293 Menu { 0294 id: contextMenu 0295 property QtObject loader 0296 MenuItem { 0297 icon.name: "document-export" 0298 text: i18nc("@action", "Add Chart as Desktop Widget") 0299 onTriggered: { 0300 WidgetExporter.exportAsWidget(contextMenu.loader) 0301 } 0302 } 0303 } 0304 }