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 }