Warning, /plasma/plasma-sdk/plasmoidviewer/qmlpackages/shell/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 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 2.20 as Kirigami
0015 import org.kde.kitemmodels 1.0 as KItemModels
0016 import org.kde.plasma.configuration 2.0
0017 
0018 Rectangle {
0019     id: root
0020 
0021     implicitWidth: Kirigami.Units.gridUnit * 40
0022     implicitHeight: Kirigami.Units.gridUnit * 30
0023 
0024     Layout.minimumWidth: Kirigami.Units.gridUnit * 30
0025     Layout.minimumHeight: Kirigami.Units.gridUnit * 21
0026 
0027     LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
0028     LayoutMirroring.childrenInherit: true
0029 
0030     color: Kirigami.Theme.backgroundColor
0031 
0032     property bool isContainment: false
0033 
0034     property ConfigModel globalConfigModel:  globalAppletConfigModel
0035 
0036     function closing() {
0037         if (applyButton.enabled) {
0038             messageDialog.item = null;
0039             messageDialog.open();
0040             return false;
0041         }
0042         return true;
0043     }
0044 
0045     Connections {
0046         target: configDialog
0047         function onClosing(event) {
0048             event.accepted = closing();
0049         }
0050     }
0051 
0052     ConfigModel {
0053         id: globalAppletConfigModel
0054         ConfigCategory {
0055             name: i18nd("plasma_shell_org.kde.plasma.desktop", "Keyboard Shortcuts")
0056             icon: "preferences-desktop-keyboard"
0057             source: "ConfigurationShortcuts.qml"
0058         }
0059     }
0060 
0061     KItemModels.KSortFilterProxyModel {
0062         id: configDialogFilterModel
0063         sourceModel: configDialog.configModel
0064         filterRowCallback: (row, parent) => {
0065             return sourceModel.data(sourceModel.index(row, 0), ConfigModel.VisibleRole);
0066         }
0067     }
0068 
0069     function settingValueChanged() {
0070         applyButton.enabled = true;
0071     }
0072 
0073     function pushReplace(item, config) {
0074         let page;
0075         if (app.pageStack.depth === 0) {
0076             page = app.pageStack.push(item, config);
0077         } else {
0078             page = app.pageStack.replace(item, config);
0079         }
0080         app.currentConfigPage = page;
0081     }
0082     Component {
0083         id: configurationKcmPageComponent
0084         ConfigurationKcmPage {
0085         }
0086     }
0087 
0088     function open(item) {
0089         app.isAboutPage = false;
0090         if (item.source) {
0091             app.isAboutPage = item.source === "AboutPlugin.qml";
0092             pushReplace(Qt.resolvedUrl("ConfigurationAppletPage.qml"), {configItem: item, title: item.name});
0093         } else if (item.kcm) {
0094             pushReplace(configurationKcmPageComponent, {kcm: item.kcm, internalPage: item.kcm.mainUi});
0095         } else {
0096             app.pageStack.pop();
0097         }
0098 
0099         applyButton.enabled = false
0100     }
0101 
0102     Connections {
0103         target: app.currentConfigPage
0104 
0105         function onSettingValueChanged() {
0106             applyButton.enabled = true;
0107         }
0108     }
0109 
0110     Component.onCompleted: {
0111         // if we are a containment then the first item will be ConfigurationContainmentAppearance
0112         // if the applet does not have own configs then the first item will be Shortcuts
0113         if (isContainment || !configDialog.configModel || configDialog.configModel.count === 0) {
0114             open(root.globalConfigModel.get(0))
0115         } else {
0116             open(configDialog.configModel.get(0))
0117         }
0118     }
0119 
0120     function applicationWindow() {
0121         return app;
0122     }
0123 
0124 
0125     QQC2.ScrollView {
0126         id: categoriesScroll
0127         anchors {
0128             left: parent.left
0129             top: parent.top
0130             bottom: parent.bottom
0131         }
0132         width: Kirigami.Units.gridUnit * 7
0133         Kirigami.Theme.colorSet: Kirigami.Theme.View
0134         Kirigami.Theme.inherit: false
0135         leftPadding: 0
0136         rightPadding: 0
0137         topPadding: 0
0138         bottomPadding: 0
0139         activeFocusOnTab: true
0140         focus: true
0141         Accessible.role: Accessible.MenuBar
0142         background: Rectangle {
0143             color: Kirigami.Theme.backgroundColor
0144         }
0145 
0146         Keys.onUpPressed: {
0147             const buttons = categories.children
0148 
0149             let foundPrevious = false
0150             for (let i = buttons.length - 1; i >= 0; --i) {
0151                 const button = buttons[i];
0152                 if (!button.hasOwnProperty("highlighted")) {
0153                     // not a ConfigCategoryDelegate
0154                     continue;
0155                 }
0156 
0157                 if (foundPrevious) {
0158                     categories.openCategory(button.item)
0159                     categoriesScroll.forceActiveFocus(Qt.TabFocusReason)
0160                     return
0161                 } else if (button.highlighted) {
0162                     foundPrevious = true
0163                 }
0164             }
0165 
0166             event.accepted = false
0167         }
0168 
0169         Keys.onDownPressed: {
0170             const buttons = categories.children
0171 
0172             let foundNext = false
0173             for (let i = 0, length = buttons.length; i < length; ++i) {
0174                 const button = buttons[i];
0175                 if (!button.hasOwnProperty("highlighted")) {
0176                     continue;
0177                 }
0178 
0179                 if (foundNext) {
0180                     categories.openCategory(button.item)
0181                     categoriesScroll.forceActiveFocus(Qt.TabFocusReason)
0182                     return
0183                 } else if (button.highlighted) {
0184                     foundNext = true
0185                 }
0186             }
0187 
0188             event.accepted = false
0189         }
0190 
0191         ColumnLayout {
0192             id: categories
0193 
0194             spacing: 0
0195             width: categoriesScroll.width
0196             focus: true
0197 
0198             function openCategory(item) {
0199                 if (applyButton.enabled) {
0200                     messageDialog.item = item;
0201                     messageDialog.open();
0202                     return;
0203                 }
0204                 open(item)
0205             }
0206 
0207             Component {
0208                 id: categoryDelegate
0209                 ConfigCategoryDelegate {
0210                     id: delegate
0211                     onActivated: categories.openCategory(model);
0212                     highlighted: {
0213                         if (app.pageStack.currentItem) {
0214                             if (model.kcm && app.pageStack.currentItem.kcm) {
0215                                 return model.kcm == app.pageStack.currentItem.kcm
0216                             } else if (app.pageStack.currentItem.configItem) {
0217                                 return model.source == app.pageStack.currentItem.configItem.source
0218                             } else {
0219                                 return app.pageStack.currentItem.source == Qt.resolvedUrl(model.source)
0220                             }
0221                         }
0222                         return false
0223                     }
0224                     item: model
0225                 }
0226             }
0227 
0228             Repeater {
0229                 Layout.fillWidth: true
0230                 model: root.isContainment ? globalConfigModel : undefined
0231                 delegate: categoryDelegate
0232             }
0233             Repeater {
0234                 Layout.fillWidth: true
0235                 model: configDialogFilterModel
0236                 delegate: categoryDelegate
0237             }
0238             Repeater {
0239                 Layout.fillWidth: true
0240                 model: !root.isContainment ? globalConfigModel : undefined
0241                 delegate: categoryDelegate
0242             }
0243             Repeater {
0244                 Layout.fillWidth: true
0245                 model: ConfigModel {
0246                     ConfigCategory{
0247                         name: i18nd("plasma_shell_org.kde.plasma.desktop", "About")
0248                         icon: "help-about"
0249                         source: "AboutPlugin.qml"
0250                     }
0251                 }
0252                 delegate: categoryDelegate
0253             }
0254         }
0255     }
0256 
0257     Kirigami.Separator {
0258         anchors {
0259             left: parent.left
0260             right: parent.right
0261             top: parent.top
0262         }
0263         z: 1
0264     }
0265     Kirigami.Separator {
0266         anchors {
0267             right: categoriesScroll.right
0268             top: parent.top
0269             bottom: parent.bottom
0270         }
0271         z: 1
0272     }
0273 
0274     Kirigami.ApplicationItem {
0275         id: app
0276         anchors {
0277             left: categoriesScroll.right
0278             top: parent.top
0279             right: parent.right
0280             bottom: parent.bottom
0281         }
0282 
0283         pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.Breadcrumb
0284         wideScreen: true
0285         pageStack.globalToolBar.separatorVisible: bottomSeparator.visible
0286         pageStack.globalToolBar.colorSet: Kirigami.Theme.Window
0287 
0288         property var currentConfigPage: null
0289         property bool isAboutPage: false
0290 
0291         QQC2.Dialog {
0292             id: messageDialog
0293             property var item
0294             title: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply Settings")
0295             QQC2.Label {
0296                 anchors.fill:parent
0297                 text: 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?")
0298             }
0299             standardButtons: QQC2.Dialog.Apply | QQC2.Dialog.Discard | QQC2.Dialog.Cancel
0300             onAccepted: {
0301                 applyAction.trigger()
0302                 discard();
0303             }
0304             onRejected: {
0305                 if (item) {
0306                     root.open(item);
0307                 } else {
0308                     applyButton.enabled = false;
0309                     configDialog.close();
0310                 }
0311             }
0312         }
0313 
0314         footer: QQC2.Pane {
0315 
0316             padding: Kirigami.Units.largeSpacing
0317 
0318             contentItem: RowLayout {
0319                 id: buttonsRow
0320                 spacing: Kirigami.Units.smallSpacing
0321 
0322                 Item {
0323                     Layout.fillWidth: true
0324                 }
0325 
0326                 QQC2.Button {
0327                     icon.name: "dialog-ok"
0328                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "OK")
0329                     onClicked: acceptAction.trigger()
0330                     KeyNavigation.tab: categories
0331                 }
0332                 QQC2.Button {
0333                     id: applyButton
0334                     enabled: false
0335                     icon.name: "dialog-ok-apply"
0336                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply")
0337                     visible: !app.isAboutPage && app.pageStack.currentItem && (!app.pageStack.currentItem.kcm || app.pageStack.currentItem.kcm.buttons & 4) // 4 = Apply button
0338                     onClicked: applyAction.trigger()
0339                 }
0340                 QQC2.Button {
0341                     icon.name: "dialog-cancel"
0342                     text: i18nd("plasma_shell_org.kde.plasma.desktop", "Cancel")
0343                     onClicked: cancelAction.trigger()
0344                     visible: !app.isAboutPage
0345                 }
0346             }
0347             background: Item {
0348                 Kirigami.Separator {
0349                     id: bottomSeparator
0350                     visible: app.pageStack.currentItem
0351                         && app.pageStack.currentItem.flickable
0352                         && !(app.pageStack.currentItem.flickable.atYBeginning
0353                         && app.pageStack.currentItem.flickable.atYEnd)
0354                     anchors {
0355                         left: parent.left
0356                         right: parent.right
0357                         top: parent.top
0358                     }
0359                 }
0360             }
0361         }
0362 
0363         QQC2.Action {
0364             id: acceptAction
0365             onTriggered: {
0366                 applyAction.trigger();
0367                 configDialog.close();
0368             }
0369         }
0370 
0371         QQC2.Action {
0372             id: applyAction
0373             onTriggered: {
0374                 app.pageStack.get(0).saveConfig()
0375 
0376                 applyButton.enabled = false;
0377             }
0378         }
0379 
0380         QQC2.Action {
0381             id: cancelAction
0382             onTriggered: {
0383                 if (root.closing()) {
0384                     configDialog.close();
0385                 }
0386             }
0387         }
0388 
0389         Keys.onReturnPressed: acceptAction.trigger();
0390         Keys.onEscapePressed: cancelAction.trigger();
0391     }
0392 }