Warning, /plasma/plasma-bigscreen/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 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.6
0008 import QtQuick.Controls 2.3 as QtControls
0009 import QtQuick.Layouts 1.0
0010 import QtQuick.Window 2.2
0011 
0012 import org.kde.kirigami 2.5 as Kirigami
0013 import org.kde.plasma.core 2.1 as PlasmaCore
0014 import org.kde.plasma.configuration 2.0
0015 
0016 
0017 //TODO: all of this will be done with desktop components
0018 Rectangle {
0019     id: root
0020     Layout.minimumWidth:  plasmoid.availableScreenRect.width
0021     Layout.minimumHeight: plasmoid.availableScreenRect.height
0022     
0023 
0024     LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
0025     LayoutMirroring.childrenInherit: true
0026 
0027     color: Qt.rgba(0, 0, 0, 0.6 * dialog.position)
0028 
0029 //BEGIN properties
0030     property bool isContainment: false
0031     property alias internalDialog: dialog
0032 //END properties
0033 
0034 //BEGIN model
0035     property ConfigModel globalConfigModel:  globalAppletConfigModel
0036 
0037     ConfigModel {
0038         id: globalAppletConfigModel
0039     }
0040 
0041     PlasmaCore.SortFilterModel {
0042         id: configDialogFilterModel
0043         sourceModel: configDialog.configModel
0044         filterRole: "visible"
0045         filterCallback: function(source_row, value) { return value; }
0046     }
0047 //END model
0048 
0049 //BEGIN functions
0050     function saveConfig() {
0051         if (pageStack.currentItem.saveConfig) {
0052             pageStack.currentItem.saveConfig()
0053         }
0054         for (var key in plasmoid.configuration) {
0055             if (pageStack.currentItem["cfg_"+key] !== undefined) {
0056                 plasmoid.configuration[key] = pageStack.currentItem["cfg_"+key]
0057             }
0058         }
0059     }
0060 
0061     function configurationHasChanged() {
0062         for (var key in plasmoid.configuration) {
0063             if (pageStack.currentItem["cfg_"+key] !== undefined) {
0064                 //for objects == doesn't work
0065                 if (typeof plasmoid.configuration[key] == 'object') {
0066                     for (var i in plasmoid.configuration[key]) {
0067                         if (plasmoid.configuration[key][i] != pageStack.currentItem["cfg_"+key][i]) {
0068                             return true;
0069                         }
0070                     }
0071                     return false;
0072                 } else if (pageStack.currentItem["cfg_"+key] != plasmoid.configuration[key]) {
0073                     return true;
0074                 }
0075             }
0076         }
0077         return false;
0078     }
0079 
0080 
0081     function settingValueChanged() {
0082         if (pageStack.currentItem.saveConfig !== undefined) {
0083             pageStack.currentItem.saveConfig();
0084         } else {
0085             root.saveConfig();
0086         }
0087     }
0088 //END functions
0089 
0090 
0091 //BEGIN connections
0092     Component.onCompleted: {
0093         if (!isContainment && configDialog.configModel && configDialog.configModel.count > 0) {
0094             if (configDialog.configModel.get(0).source) {
0095                 pageStack.sourceFile = configDialog.configModel.get(0).source
0096             } else if (configDialog.configModel.get(0).kcm) {
0097                 pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml");
0098                 pageStack.currentItem.kcm = configDialog.configModel.get(0).kcm;
0099             } else {
0100                 pageStack.sourceFile = "";
0101             }
0102             pageStack.title = configDialog.configModel.get(0).name
0103         } else {
0104             pageStack.sourceFile = globalConfigModel.get(0).source
0105             pageStack.title = globalConfigModel.get(0).name
0106         }
0107 //         root.width = dialogRootItem.implicitWidth
0108 //         root.height = dialogRootItem.implicitHeight
0109     }
0110 //END connections
0111 
0112 //BEGIN UI components
0113 
0114     QtControls.Drawer {
0115         id: dialog
0116         visible: true
0117         edge: Qt.BottomEdge
0118         onClosed: configDialog.close()
0119         x: parent.width/2 - width/2
0120 
0121         opacity: position
0122         width: Math.min(Math.max(units.gridUnit * 35, dialogRootItem.implicitWidth + leftPadding + rightPadding), root.width)
0123         height: Math.min(root.height - units.gridUnit * 2, dialogRootItem.implicitHeight + topPadding + bottomPadding + units.gridUnit, root.height)
0124 
0125         leftPadding: background.margins.left
0126         topPadding: background.margins.top
0127         rightPadding: background.margins.right
0128         bottomPadding: 0
0129         background: PlasmaCore.FrameSvgItem {
0130             imagePath: "widgets/background"
0131             enabledBorders: PlasmaCore.FrameSvgItem.LeftBorder | PlasmaCore.FrameSvgItem.TopBorder | PlasmaCore.FrameSvgItem.RightBorder
0132         }
0133         contentItem: ColumnLayout {
0134             id: dialogRootItem
0135 
0136             spacing: 0
0137             implicitWidth: scroll.implicitWidth
0138 
0139             QtControls.ScrollView {
0140                 id: scroll
0141 
0142                 activeFocusOnTab: false
0143 
0144                 Layout.fillWidth: true
0145                 Layout.fillHeight: true
0146 
0147                 implicitWidth: pageColumn.implicitWidth
0148                 implicitHeight: pageColumn.implicitHeight
0149 
0150                 property Item flickableItem: pageFlickable
0151                 // this horrible code below ensures the control with active focus stays visible in the window
0152                 // by scrolling the view up or down as needed when tabbing through the window
0153                 Window.onActiveFocusItemChanged: {
0154                     var flickable = scroll.flickableItem;
0155 
0156                     var item = Window.activeFocusItem;
0157                     if (!item) {
0158                         return;
0159                     }
0160 
0161                     // when an item within ScrollView has active focus the ScrollView,
0162                     // as FocusScope, also has it, so we only scroll in this case
0163                     if (!scroll.activeFocus) {
0164                         return;
0165                     }
0166 
0167                     var padding = units.gridUnit * 2 // some padding to the top/bottom when we scroll
0168 
0169                     var yPos = item.mapToItem(scroll.contentItem, 0, 0).y;
0170                     if (yPos < flickable.contentY) {
0171                         flickable.contentY = Math.max(0, yPos - padding);
0172 
0173                     // The "Math.min(padding, item.height)" ensures that we only scroll the item into view
0174                     // when it's barely visible. The logic was mostly meant for keyboard navigating through
0175                     // a list of CheckBoxes, so this check keeps us from trying to scroll an inner ScrollView
0176                     // into view when it implicitly gains focus (like plasma-pa config dialog has).
0177                     } else if (yPos + Math.min(padding, item.height) > flickable.contentY + flickable.height) {
0178                         flickable.contentY = Math.min(flickable.contentHeight - flickable.height,
0179                                                     yPos - flickable.height + item.height + padding);
0180                     }
0181                 }
0182                 Flickable {
0183                     id: pageFlickable
0184                     anchors {
0185                         fill: parent
0186                         margins: units.smallSpacing
0187                     }
0188                     contentHeight: pageColumn.height
0189                     contentWidth: width
0190                     ColumnLayout {
0191                         id: pageColumn
0192                         spacing: units.largeSpacing / 2
0193                         width: pageFlickable.width
0194                         height: Math.max(implicitHeight, pageFlickable.height)
0195 
0196                         Kirigami.Heading {
0197                             id: pageTitle
0198                             Layout.fillWidth: true
0199                             level: 1
0200                             text: pageStack.title
0201                         }
0202 
0203                         QtControls.StackView {
0204                             id: pageStack
0205                             property string title: ""
0206                             property bool invertAnimations: false
0207 
0208                             Layout.fillWidth: true
0209                             Layout.fillHeight: true
0210                             implicitWidth: Math.max(currentItem ? Math.max(currentItem.Layout.minimumWidth, currentItem.Layout.preferredWidth, currentItem.implicitWidth) : 0, units.gridUnit * 15)
0211                             implicitHeight: Math.max(currentItem ? Math.max(currentItem.Layout.minimumHeight, currentItem.Layout.preferredHeight, currentItem.implicitHeight) : 0, units.gridUnit * 15)
0212 
0213                             property string sourceFile
0214 
0215                             onSourceFileChanged: {
0216                                 if (!sourceFile) {
0217                                     return;
0218                                 }
0219 
0220                                 //in a StackView pages need to be initialized with stackviews size, or have none
0221                                 var props = {"width": width, "height": height}
0222 
0223                                 var plasmoidConfig = plasmoid.configuration
0224                                 for (var key in plasmoidConfig) {
0225                                     props["cfg_" + key] = plasmoid.configuration[key]
0226                                 }
0227 
0228                                 var newItem = replace(Qt.resolvedUrl(sourceFile), props)
0229 
0230                                 for (var key in plasmoidConfig) {
0231                                     var changedSignal = newItem["cfg_" + key + "Changed"]
0232                                     if (changedSignal) {
0233                                         changedSignal.connect(root.settingValueChanged)
0234                                     }
0235                                 }
0236 
0237                                 var configurationChangedSignal = newItem.configurationChanged
0238                                 if (configurationChangedSignal) {
0239                                     configurationChangedSignal.connect(root.settingValueChanged)
0240                                 }
0241 
0242                                 scroll.flickableItem.contentY = 0
0243 
0244                                 /*
0245                                 for (var prop in currentItem) {
0246                                     if (prop.indexOf("cfg_") === 0) {
0247                                         currentItem[prop+"Changed"].connect(root.pageChanged)
0248                                     }
0249                                 }*/
0250                             }
0251 
0252                             replaceEnter: Transition {
0253                                 ParallelAnimation {
0254                                     //OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)
0255                                     NumberAnimation {
0256                                         property: "opacity"
0257                                         from: 0
0258                                         to: 1
0259                                         duration: units.longDuration
0260                                         easing.type: Easing.InOutQuad
0261                                     }
0262                                     XAnimator {
0263                                         from: pageStack.invertAnimations ? -scroll.width/3: scroll.width/3
0264                                         to: 0
0265                                         duration: units.longDuration
0266                                         easing.type: Easing.InOutQuad
0267                                     }
0268                                 }
0269                             }
0270                             replaceExit: Transition {
0271                                 ParallelAnimation {
0272                                     OpacityAnimator {
0273                                         from: 1
0274                                         to: 0
0275                                         duration: units.longDuration
0276                                         easing.type: Easing.InOutQuad
0277                                     }
0278                                     XAnimator {
0279                                         from: 0
0280                                         to: pageStack.invertAnimations ? scroll.width/3 : -scroll.width/3
0281                                         duration: units.longDuration
0282                                         easing.type: Easing.InOutQuad
0283                                     }
0284                                 }
0285                             }
0286                         }
0287                     }
0288                 }
0289             }
0290 
0291             Rectangle {
0292                 id: separator
0293                 Layout.fillWidth: true
0294                 Layout.preferredHeight: 1
0295                 color: Kirigami.Theme.highlightColor
0296                 visible: categoriesScroll.visible
0297                 Behavior on color {
0298                     ColorAnimation {
0299                         duration: units.longDuration
0300                         easing.type: Easing.InOutQuad
0301                     }
0302                 }
0303             }
0304 
0305             QtControls.ScrollView {
0306                 id: categoriesScroll
0307 
0308                 Layout.fillWidth: true
0309                 Layout.preferredHeight: categories.implicitHeight
0310 
0311                 visible: (configDialog.configModel ? configDialog.configModel.count : 0) + globalConfigModel.count > 1
0312 
0313                 Keys.onLeftPressed: {
0314                     var buttons = categories.children
0315 
0316                     var foundPrevious = false
0317                     for (var i = buttons.length - 1; i >= 0; --i) {
0318                         var button = buttons[i];
0319                         if (!button.hasOwnProperty("current")) {
0320                             // not a ConfigCategoryDelegate
0321                             continue;
0322                         }
0323 
0324                         if (foundPrevious) {
0325                             button.openCategory()
0326                             return
0327                         } else if (button.current) {
0328                             foundPrevious = true
0329                         }
0330                     }
0331                 }
0332 
0333                 Keys.onRightPressed: {
0334                     var buttons = categories.children
0335 
0336                     var foundNext = false
0337                     for (var i = 0, length = buttons.length; i < length; ++i) {
0338                         var button = buttons[i];
0339                         console.log(button)
0340                         if (!button.hasOwnProperty("current")) {
0341                             continue;
0342                         }
0343 
0344                         if (foundNext) {
0345                             button.openCategory()
0346                             return
0347                         } else if (button.current) {
0348                             foundNext = true
0349                         }
0350                     }
0351                 }
0352 
0353                 RowLayout {
0354                     id: categories
0355                     spacing: 0
0356                     width: categoriesScroll.width
0357                     height: implicitHeight
0358 
0359                     property Item currentItem: children[1]
0360 
0361                     Repeater {
0362                         model: root.isContainment ? globalConfigModel : undefined
0363                         delegate: ConfigCategoryDelegate {}
0364                     }
0365                     Repeater {
0366                         model: configDialogFilterModel
0367                         delegate: ConfigCategoryDelegate {}
0368                     }
0369                     Repeater {
0370                         model: !root.isContainment ? globalConfigModel : undefined
0371                         delegate: ConfigCategoryDelegate {}
0372                     }
0373                 }
0374             }
0375 
0376         }
0377     }
0378 //END UI components
0379 }