Warning, /plasma/kscreen/kcm/ui/main.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 import QtQuick 2.15 0007 import QtQuick.Layouts 1.15 0008 import QtQuick.Controls 2.15 as QQC2 0009 import org.kde.kirigami 2.20 as Kirigami 0010 import org.kde.kirigami.delegates as KD 0011 import org.kde.kitemmodels 1.0 0012 0013 import org.kde.kcmutils as KCM 0014 import org.kde.private.kcm.kscreen 1.0 as KScreen 0015 0016 KCM.SimpleKCM { 0017 id: root 0018 0019 property int selectedOutput: 0 0020 property int revertCountdown: 15 0021 readonly property int topMargins: Kirigami.Units.smallSpacing 0022 readonly property bool anyMessagesShown: invalidConfigMsg.visible 0023 || errBackendMsg.visible 0024 || errSaveMsg.visible 0025 || scaleMsg.visible 0026 || connectMsg.visible 0027 || revertMsg.visible 0028 0029 implicitWidth: Kirigami.Units.gridUnit * 32 0030 implicitHeight: Kirigami.Units.gridUnit * 30 0031 0032 topPadding: anyMessagesShown ? topMargins : 0 0033 leftPadding: 0 0034 rightPadding: 0 0035 0036 // This is to fix Output dragging 0037 flickable.interactive: Kirigami.Settings.hasTransientTouchInput 0038 0039 Kirigami.OverlaySheet { 0040 id: confirmMsg 0041 title: i18n("Keep display configuration?") 0042 onVisibleChanged: { 0043 if (visible) { 0044 revertButton.forceActiveFocus() 0045 } else { 0046 revertTimer.stop(); 0047 } 0048 } 0049 showCloseButton: false 0050 ColumnLayout { 0051 QQC2.Label { 0052 Layout.fillWidth: true 0053 Layout.maximumWidth: Math.round(root.width * 0.75) 0054 topPadding: Kirigami.Units.largeSpacing 0055 bottomPadding: Kirigami.Units.largeSpacing 0056 text: i18np("Will revert to previous configuration in %1 second.", 0057 "Will revert to previous configuration in %1 seconds.", 0058 revertCountdown); 0059 wrapMode: Text.WordWrap 0060 } 0061 } 0062 footer: QQC2.DialogButtonBox { 0063 id: confirmDialogButtonBox 0064 QQC2.Button { 0065 QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole 0066 Keys.onPressed: event => { 0067 if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { 0068 event.accepted = true; 0069 clicked(); 0070 } 0071 } 0072 icon.name: "dialog-ok" 0073 text: i18n("&Keep") 0074 } 0075 QQC2.Button { 0076 id: revertButton 0077 QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole 0078 Keys.onPressed: event => { 0079 if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) { 0080 event.accepted = true; 0081 clicked(); 0082 } 0083 } 0084 action: QQC2.Action { 0085 icon.name: "edit-undo" 0086 text: i18n("&Revert") 0087 shortcut: "Escape" 0088 enabled: confirmMsg.visible 0089 } 0090 } 0091 onAccepted: { 0092 confirmMsg.close(); 0093 } 0094 onRejected: { 0095 revertTimer.stop(); 0096 kcm.setStopUpdatesFromBackend(false); 0097 kcm.revertSettings(); 0098 } 0099 } 0100 } 0101 0102 Connections { 0103 target: kcm 0104 function onInvalidConfig(reason) { 0105 if (reason === KScreen.KCMKScreen.NoEnabledOutputs) { 0106 invalidConfigMsg.text = i18nc("@info", "All displays are disabled. Enable at least one.") 0107 } else if (reason === KScreen.KCMKScreen.ConfigHasGaps) { 0108 invalidConfigMsg.text = i18nc("@info", "Gaps between displays are not supported. Make sure all displays are touching.") 0109 } 0110 invalidConfigMsg.visible = true; 0111 } 0112 function onErrorOnSave() { 0113 errSaveMsg.visible = true; 0114 } 0115 function onGlobalScaleWritten() { 0116 scaleMsg.visible = true; 0117 } 0118 function onOutputConnect(connected) { 0119 if (connected) { 0120 connectMsg.text = i18n("A new output has been added. Settings have been reloaded."); 0121 } else { 0122 connectMsg.text = i18n("An output has been removed. Settings have been reloaded."); 0123 } 0124 connectMsg.visible = true; 0125 } 0126 function onBackendError() { 0127 errBackendMsg.visible = true; 0128 } 0129 function onSettingsReverted() { 0130 confirmMsg.close(); 0131 revertMsg.visible = true; 0132 } 0133 function onShowRevertWarning() { 0134 revertCountdown = 15; 0135 confirmMsg.open(); 0136 revertTimer.restart(); 0137 } 0138 function onChanged() { 0139 invalidConfigMsg.visible = false; 0140 errSaveMsg.visible = false; 0141 scaleMsg.visible = false; 0142 revertMsg.visible = false; 0143 } 0144 } 0145 0146 0147 ColumnLayout { 0148 spacing: Kirigami.Units.smallSpacing 0149 0150 Kirigami.InlineMessage { 0151 // Note1: There is an implicit height binding loop error on 0152 // first invocation. Seems to be an issue in Kirigami. 0153 // Note2: This should maybe go in header component of the KCM, 0154 // but there seems to be another issue in Kirigami then 0155 // being always hidden. Compare Night Color KCM with 0156 // the same issue. 0157 id: invalidConfigMsg 0158 0159 Layout.fillWidth: true 0160 Layout.leftMargin: root.topMargins 0161 Layout.rightMargin: root.topMargins 0162 type: Kirigami.MessageType.Error 0163 showCloseButton: true 0164 0165 } 0166 Kirigami.InlineMessage { 0167 id: errBackendMsg 0168 Layout.fillWidth: true 0169 Layout.leftMargin: root.topMargins 0170 Layout.rightMargin: root.topMargins 0171 type: Kirigami.MessageType.Error 0172 text: i18n("No KScreen backend found. Please check your KScreen installation.") 0173 visible: false 0174 showCloseButton: false 0175 } 0176 Kirigami.InlineMessage { 0177 id: errSaveMsg 0178 Layout.fillWidth: true 0179 Layout.leftMargin: root.topMargins 0180 Layout.rightMargin: root.topMargins 0181 type: Kirigami.MessageType.Error 0182 text: i18n("Outputs could not be saved due to error.") 0183 visible: false 0184 showCloseButton: true 0185 } 0186 Kirigami.InlineMessage { 0187 id: scaleMsg 0188 Layout.fillWidth: true 0189 Layout.leftMargin: root.topMargins 0190 Layout.rightMargin: root.topMargins 0191 type: Kirigami.MessageType.Information 0192 text: i18n("Global scale changes will come into effect after the system is restarted.") 0193 visible: false 0194 showCloseButton: true 0195 actions: [ 0196 Kirigami.Action { 0197 icon.name: "system-reboot" 0198 text: i18n("Restart") 0199 onTriggered: kcm.requestReboot(); 0200 } 0201 ] 0202 } 0203 Kirigami.InlineMessage { 0204 id: connectMsg 0205 Layout.fillWidth: true 0206 Layout.leftMargin: root.topMargins 0207 Layout.rightMargin: root.topMargins 0208 type: Kirigami.MessageType.Information 0209 visible: false 0210 showCloseButton: true 0211 } 0212 Kirigami.InlineMessage { 0213 id: revertMsg 0214 Layout.fillWidth: true 0215 Layout.leftMargin: root.topMargins 0216 Layout.rightMargin: root.topMargins 0217 type: Kirigami.MessageType.Information 0218 text: i18n("Display configuration reverted.") 0219 visible: false 0220 showCloseButton: true 0221 } 0222 0223 Kirigami.Dialog { 0224 id: reorderDialog 0225 0226 title: i18nc("@title:window", "Change Priorities") 0227 showCloseButton: true 0228 standardButtons: Kirigami.Dialog.Ok 0229 0230 contentItem: ListView { 0231 id: reorderView 0232 0233 implicitWidth: Math.min(root.width * 0.75, Kirigami.Units.gridUnit * 32) 0234 implicitHeight: contentHeight 0235 0236 reuseItems: true 0237 model: KSortFilterProxyModel { 0238 id: enabledOutputsModel 0239 sourceModel: kcm.outputModel 0240 filterRoleName: "enabled" 0241 filterString: "true" 0242 sortRoleName: "priority" 0243 sortOrder: Qt.AscendingOrder 0244 } 0245 delegate: Kirigami.SwipeListItem { 0246 id: delegate 0247 0248 property var output: model 0249 0250 width: ListView.view.width 0251 0252 background: null 0253 contentItem: KD.TitleSubtitle { 0254 title: delegate.output.display 0255 subtitle: (delegate.output.priority === 1) ? i18n("Primary") : "" 0256 } 0257 actions: [ 0258 Kirigami.Action { 0259 icon.name: "arrow-up" 0260 text: i18n("Raise priority") 0261 enabled: delegate.output.priority > 1 0262 onTriggered: { 0263 if (enabled) { 0264 delegate.output.priority -= 1; 0265 } 0266 } 0267 }, 0268 Kirigami.Action { 0269 icon.name: "arrow-down" 0270 text: i18n("Lower priority") 0271 enabled: delegate.output.priority < reorderView.count 0272 onTriggered: { 0273 if (enabled) { 0274 delegate.output.priority += 1; 0275 } 0276 } 0277 } 0278 ] 0279 } 0280 } 0281 } 0282 0283 Connections { 0284 target: kcm 0285 function onInvalidConfig(reason) { 0286 if (reason === KScreen.KCMKScreen.NoEnabledOutputs) { 0287 invalidConfigMsg.text = i18nc("@info", "All displays are disabled. Enable at least one.") 0288 } else if (reason === KScreen.KCMKScreen.ConfigHasGaps) { 0289 invalidConfigMsg.text = i18nc("@info", "Gaps between displays are not supported. Make sure all displays are touching.") 0290 } 0291 invalidConfigMsg.visible = true; 0292 } 0293 function onErrorOnSave() { 0294 errSaveMsg.visible = true; 0295 } 0296 function onGlobalScaleWritten() { 0297 scaleMsg.visible = true; 0298 } 0299 function onOutputConnect(connected) { 0300 root.selectedOutput = 0; 0301 if (connected) { 0302 connectMsg.text = i18n("A new output has been added. Settings have been reloaded."); 0303 } else { 0304 connectMsg.text = i18n("An output has been removed. Settings have been reloaded."); 0305 } 0306 connectMsg.visible = true; 0307 } 0308 function onBackendError() { 0309 errBackendMsg.visible = true; 0310 } 0311 function onSettingsReverted() { 0312 confirmMsg.close(); 0313 revertMsg.visible = true; 0314 } 0315 function onShowRevertWarning() { 0316 revertCountdown = 15; 0317 confirmMsg.open(); 0318 revertTimer.restart(); 0319 } 0320 function onChanged() { 0321 invalidConfigMsg.visible = false; 0322 errSaveMsg.visible = false; 0323 scaleMsg.visible = false; 0324 revertMsg.visible = false; 0325 } 0326 } 0327 0328 Rectangle { 0329 Layout.preferredHeight: Math.max(root.height * 0.4, Kirigami.Units.gridUnit * 13) 0330 Layout.fillWidth: true 0331 Kirigami.Theme.inherit: false 0332 Kirigami.Theme.colorSet: Kirigami.Theme.View 0333 color: Kirigami.Theme.backgroundColor 0334 0335 Kirigami.Separator { 0336 anchors { 0337 top: parent.top 0338 left: parent.left 0339 right: parent.right 0340 } 0341 visible: root.anyMessagesShown 0342 } 0343 0344 ScreenView { 0345 id: screen 0346 0347 anchors.fill: parent 0348 enabled: kcm.outputModel && kcm.backendReady 0349 outputs: kcm.outputModel 0350 } 0351 0352 Kirigami.Separator { 0353 anchors { 0354 bottom: parent.bottom 0355 left: parent.left 0356 right: parent.right 0357 } 0358 } 0359 } 0360 0361 Panel { 0362 enabled: kcm.outputModel && kcm.backendReady 0363 Layout.fillWidth: true 0364 enabledOutputs: enabledOutputsModel 0365 selectedOutput: root.selectedOutput 0366 onSelectedOutputChanged: { 0367 root.selectedOutput = selectedOutput; 0368 selectedOutput = Qt.binding(() => root.selectedOutput); 0369 } 0370 onReorder: reorderDialog.open() 0371 } 0372 0373 Timer { 0374 id: revertTimer 0375 interval: 1000 0376 running: false 0377 repeat: true 0378 0379 onTriggered: { 0380 revertCountdown -= 1; 0381 if (revertCountdown < 1) { 0382 confirmDialogButtonBox.rejected(); 0383 } 0384 } 0385 } 0386 } 0387 }