Warning, /plasma/plasma-desktop/desktoppackage/contents/configuration/AppletConfiguration.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org> 0003 SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de> 0004 SPDX-FileCopyrightText: 2020 Carl Schwan <carlschwan@kde.org> 0005 SPDX-FileCopyrightText: 2022-2023 ivan tkachenko <me@ratijas.tk> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 import QtQuick 2.15 0011 import QtQuick.Controls 2.15 as QQC2 0012 import QtQuick.Layouts 1.15 0013 0014 import org.kde.kirigami as Kirigami 0015 import org.kde.kitemmodels 1.0 as KItemModels 0016 import org.kde.plasma.configuration 2.0 0017 import org.kde.plasma.plasmoid 2.0 0018 0019 Rectangle { 0020 id: root 0021 0022 implicitWidth: Kirigami.Units.gridUnit * 40 0023 implicitHeight: Kirigami.Units.gridUnit * 30 0024 0025 Layout.minimumWidth: Kirigami.Units.gridUnit * 30 0026 Layout.minimumHeight: Kirigami.Units.gridUnit * 21 0027 0028 LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft 0029 LayoutMirroring.childrenInherit: true 0030 0031 color: Kirigami.Theme.backgroundColor 0032 0033 property bool isContainment: false 0034 0035 property ConfigModel globalConfigModel: globalAppletConfigModel 0036 0037 property url currentSource 0038 0039 function closing() { 0040 if (applyButton.enabled) { 0041 messageDialog.item = null; 0042 messageDialog.open(); 0043 return false; 0044 } 0045 return true; 0046 } 0047 0048 function saveConfig() { 0049 const config = Plasmoid.configuration; // type: KConfigPropertyMap 0050 0051 config.keys().forEach(key => { 0052 const cfgKey = "cfg_" + key; 0053 if (cfgKey in app.pageStack.currentItem) { 0054 config[key] = app.pageStack.currentItem[cfgKey]; 0055 } 0056 }) 0057 0058 plasmoid.configuration.writeConfig(); 0059 0060 // For ConfigurationContainmentActions.qml 0061 if (app.pageStack.currentItem.hasOwnProperty("saveConfig")) { 0062 app.pageStack.currentItem.saveConfig() 0063 } 0064 } 0065 0066 Connections { 0067 target: configDialog 0068 function onClosing(event) { 0069 event.accepted = closing(); 0070 } 0071 } 0072 0073 ConfigModel { 0074 id: globalAppletConfigModel 0075 ConfigCategory { 0076 name: i18nd("plasma_shell_org.kde.plasma.desktop", "Keyboard Shortcuts") 0077 icon: "preferences-desktop-keyboard" 0078 source: Qt.resolvedUrl("ConfigurationShortcuts.qml") 0079 } 0080 } 0081 0082 KItemModels.KSortFilterProxyModel { 0083 id: configDialogFilterModel 0084 sourceModel: configDialog.configModel 0085 filterRowCallback: (row, parent) => { 0086 return sourceModel.data(sourceModel.index(row, 0), ConfigModel.VisibleRole); 0087 } 0088 } 0089 0090 function settingValueChanged() { 0091 applyButton.enabled = true; 0092 } 0093 0094 function pushReplace(item, config) { 0095 let page; 0096 if (app.pageStack.depth === 0) { 0097 page = app.pageStack.push(item, config); 0098 } else { 0099 page = app.pageStack.replace(item, config); 0100 } 0101 app.currentConfigPage = page; 0102 } 0103 Component { 0104 id: configurationKcmPageComponent 0105 ConfigurationKcmPage { 0106 } 0107 } 0108 0109 function open(item) { 0110 app.isAboutPage = false; 0111 root.currentSource = item.source 0112 0113 if (item.source) { 0114 app.isAboutPage = item.source === Qt.resolvedUrl("AboutPlugin.qml"); 0115 0116 if (isContainment) { 0117 pushReplace(Qt.resolvedUrl("ConfigurationAppletPage.qml"), {configItem: item}); 0118 } else { 0119 0120 const config = Plasmoid.configuration; // type: KConfigPropertyMap 0121 0122 const props = { 0123 "title": item.name 0124 }; 0125 0126 config.keys().forEach(key => { 0127 props["cfg_" + key] = config[key]; 0128 }); 0129 0130 pushReplace(item.source, props); 0131 } 0132 0133 } else if (item.kcm) { 0134 pushReplace(configurationKcmPageComponent, {kcm: item.kcm, internalPage: item.kcm.mainUi}); 0135 } else { 0136 app.pageStack.pop(); 0137 } 0138 0139 applyButton.enabled = false 0140 } 0141 0142 Connections { 0143 target: app.currentConfigPage 0144 0145 function onSettingValueChanged() { 0146 applyButton.enabled = true; 0147 } 0148 } 0149 0150 Connections { 0151 target: app.pageStack 0152 0153 function onCurrentItemChanged() { 0154 if (app.pageStack.currentItem !== null && !isContainment) { 0155 const config = Plasmoid.configuration; // type: KConfigPropertyMap 0156 0157 config.keys().forEach(key => { 0158 const changedSignal = app.pageStack.currentItem["cfg_" + key + "Changed"]; 0159 if (changedSignal) { 0160 changedSignal.connect(() => root.settingValueChanged()); 0161 } 0162 }); 0163 0164 const configurationChangedSignal = app.pageStack.currentItem.configurationChanged; 0165 if (configurationChangedSignal) { 0166 configurationChangedSignal.connect(() => root.settingValueChanged()); 0167 } 0168 } 0169 } 0170 } 0171 0172 Component.onCompleted: { 0173 // if we are a containment then the first item will be ConfigurationContainmentAppearance 0174 // if the applet does not have own configs then the first item will be Shortcuts 0175 if (isContainment || !configDialog.configModel || configDialog.configModel.count === 0) { 0176 open(root.globalConfigModel.get(0)) 0177 } else { 0178 open(configDialog.configModel.get(0)) 0179 } 0180 } 0181 0182 function applicationWindow() { 0183 return app; 0184 } 0185 0186 0187 QQC2.ScrollView { 0188 id: categoriesScroll 0189 anchors { 0190 left: parent.left 0191 top: parent.top 0192 bottom: parent.bottom 0193 } 0194 width: Kirigami.Units.gridUnit * 7 0195 contentWidth: availableWidth 0196 Kirigami.Theme.colorSet: Kirigami.Theme.View 0197 Kirigami.Theme.inherit: false 0198 activeFocusOnTab: true 0199 focus: true 0200 Accessible.role: Accessible.MenuBar 0201 background: Rectangle { 0202 color: Kirigami.Theme.backgroundColor 0203 } 0204 0205 Keys.onUpPressed: { 0206 const buttons = categories.children 0207 0208 let foundPrevious = false 0209 for (let i = buttons.length - 1; i >= 0; --i) { 0210 const button = buttons[i]; 0211 if (!button.hasOwnProperty("highlighted")) { 0212 // not a ConfigCategoryDelegate 0213 continue; 0214 } 0215 0216 if (foundPrevious) { 0217 categories.openCategory(button.item) 0218 categoriesScroll.forceActiveFocus(Qt.TabFocusReason) 0219 return 0220 } else if (button.highlighted) { 0221 foundPrevious = true 0222 } 0223 } 0224 0225 event.accepted = false 0226 } 0227 0228 Keys.onDownPressed: { 0229 const buttons = categories.children 0230 0231 let foundNext = false 0232 for (let i = 0, length = buttons.length; i < length; ++i) { 0233 const button = buttons[i]; 0234 if (!button.hasOwnProperty("highlighted")) { 0235 continue; 0236 } 0237 0238 if (foundNext) { 0239 categories.openCategory(button.item) 0240 categoriesScroll.forceActiveFocus(Qt.TabFocusReason) 0241 return 0242 } else if (button.highlighted) { 0243 foundNext = true 0244 } 0245 } 0246 0247 event.accepted = false 0248 } 0249 0250 ColumnLayout { 0251 id: categories 0252 0253 spacing: 0 0254 width: categoriesScroll.contentWidth 0255 focus: true 0256 0257 function openCategory(item) { 0258 if (applyButton.enabled) { 0259 messageDialog.item = item; 0260 messageDialog.open(); 0261 return; 0262 } 0263 open(item) 0264 } 0265 0266 Component { 0267 id: categoryDelegate 0268 ConfigCategoryDelegate { 0269 id: delegate 0270 onActivated: categories.openCategory(model); 0271 highlighted: { 0272 if (app.pageStack.currentItem) { 0273 if (model.kcm && app.pageStack.currentItem.kcm) { 0274 return model.kcm == app.pageStack.currentItem.kcm 0275 } else { 0276 return root.currentSource == model.source 0277 } 0278 } 0279 return false 0280 } 0281 item: model 0282 } 0283 } 0284 0285 Repeater { 0286 Layout.fillWidth: true 0287 model: root.isContainment ? globalConfigModel : undefined 0288 delegate: categoryDelegate 0289 } 0290 Repeater { 0291 Layout.fillWidth: true 0292 model: configDialogFilterModel 0293 delegate: categoryDelegate 0294 } 0295 Repeater { 0296 Layout.fillWidth: true 0297 model: !root.isContainment ? globalConfigModel : undefined 0298 delegate: categoryDelegate 0299 } 0300 Repeater { 0301 Layout.fillWidth: true 0302 model: ConfigModel { 0303 ConfigCategory{ 0304 name: i18nd("plasma_shell_org.kde.plasma.desktop", "About") 0305 icon: "help-about" 0306 source: Qt.resolvedUrl("AboutPlugin.qml") 0307 } 0308 } 0309 delegate: categoryDelegate 0310 } 0311 } 0312 } 0313 0314 Kirigami.Separator { 0315 anchors { 0316 left: parent.left 0317 right: parent.right 0318 top: parent.top 0319 } 0320 z: 1 0321 } 0322 Kirigami.Separator { 0323 id: verticalSeparator 0324 anchors { 0325 top: parent.top 0326 left: categoriesScroll.right 0327 bottom: parent.bottom 0328 } 0329 z: 1 0330 } 0331 0332 Kirigami.ApplicationItem { 0333 id: app 0334 anchors { 0335 top: parent.top 0336 left: verticalSeparator.right 0337 right: parent.right 0338 bottom: parent.bottom 0339 } 0340 0341 pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.Breadcrumb 0342 wideScreen: true 0343 pageStack.globalToolBar.separatorVisible: bottomSeparator.visible 0344 pageStack.globalToolBar.colorSet: Kirigami.Theme.Window 0345 0346 property var currentConfigPage: null 0347 property bool isAboutPage: false 0348 0349 Kirigami.PromptDialog { 0350 id: messageDialog 0351 property var item 0352 title: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply Settings") 0353 subtitle: i18nd("plasma_shell_org.kde.plasma.desktop", "The settings of the current module have changed. Do you want to apply the changes or discard them?") 0354 standardButtons: Kirigami.Dialog.Apply | Kirigami.Dialog.Discard | Kirigami.Dialog.Cancel 0355 onApplied: { 0356 applyAction.trigger() 0357 discarded(); 0358 } 0359 onDiscarded: { 0360 if (item) { 0361 root.open(item); 0362 messageDialog.close(); 0363 } else { 0364 applyButton.enabled = false; 0365 configDialog.close(); 0366 } 0367 } 0368 } 0369 0370 footer: QQC2.Pane { 0371 0372 padding: Kirigami.Units.largeSpacing 0373 0374 contentItem: RowLayout { 0375 id: buttonsRow 0376 spacing: Kirigami.Units.smallSpacing 0377 0378 Item { 0379 Layout.fillWidth: true 0380 } 0381 0382 QQC2.Button { 0383 icon.name: "dialog-ok" 0384 text: i18nd("plasma_shell_org.kde.plasma.desktop", "OK") 0385 onClicked: acceptAction.trigger() 0386 KeyNavigation.tab: categories 0387 } 0388 QQC2.Button { 0389 id: applyButton 0390 enabled: false 0391 icon.name: "dialog-ok-apply" 0392 text: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply") 0393 visible: !app.isAboutPage && app.pageStack.currentItem && (!app.pageStack.currentItem.kcm || app.pageStack.currentItem.kcm.buttons & 4) // 4 = Apply button 0394 onClicked: applyAction.trigger() 0395 } 0396 QQC2.Button { 0397 icon.name: "dialog-cancel" 0398 text: i18nd("plasma_shell_org.kde.plasma.desktop", "Cancel") 0399 onClicked: cancelAction.trigger() 0400 visible: !app.isAboutPage 0401 } 0402 } 0403 background: Item { 0404 Kirigami.Separator { 0405 id: bottomSeparator 0406 visible: app.pageStack.currentItem 0407 && app.pageStack.currentItem.flickable 0408 && !(app.pageStack.currentItem.flickable.atYBeginning 0409 && app.pageStack.currentItem.flickable.atYEnd) 0410 anchors { 0411 left: parent.left 0412 right: parent.right 0413 top: parent.top 0414 } 0415 } 0416 } 0417 } 0418 0419 QQC2.Action { 0420 id: acceptAction 0421 onTriggered: { 0422 applyAction.trigger(); 0423 configDialog.close(); 0424 } 0425 } 0426 0427 QQC2.Action { 0428 id: applyAction 0429 onTriggered: { 0430 if (isContainment) { 0431 app.pageStack.get(0).saveConfig() 0432 } else { 0433 root.saveConfig() 0434 } 0435 0436 applyButton.enabled = false; 0437 } 0438 } 0439 0440 QQC2.Action { 0441 id: cancelAction 0442 onTriggered: { 0443 if (root.closing()) { 0444 configDialog.close(); 0445 } 0446 } 0447 } 0448 0449 Keys.onReturnPressed: acceptAction.trigger(); 0450 Keys.onEscapePressed: cancelAction.trigger(); 0451 } 0452 }