Warning, /plasma/kwin/src/kcms/rules/ui/main.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2020 Ismael Asensio <isma.af@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 import QtQuick
0008 import QtQuick.Layouts
0009 import QtQuick.Controls as QQC2
0010 import QtQml.Models
0011 import org.kde.kcmutils as KCM
0012 import org.kde.kirigami 2.12 as Kirigami
0013 
0014 KCM.ScrollViewKCM {
0015     id: rulesListKCM
0016 
0017     // FIXME: ScrollViewKCM.qml:73:13: QML Control: Binding loop detected for property "implicitHeight"
0018     implicitWidth: Kirigami.Units.gridUnit * 35
0019     implicitHeight: Kirigami.Units.gridUnit * 25
0020 
0021     KCM.ConfigModule.columnWidth: Kirigami.Units.gridUnit * 23
0022     KCM.ConfigModule.buttons: KCM.ConfigModule.Help | KCM.ConfigModule.Apply
0023 
0024     property var selectedIndexes: []
0025 
0026     // Manage KCM pages
0027     Connections {
0028         target: kcm
0029         function onEditIndexChanged() {
0030             if (kcm.editIndex < 0) {
0031                 // If no rule is being edited, hide RulesEdidor page
0032                 kcm.pop();
0033             } else if (kcm.depth < 2) {
0034                 // Add the RulesEditor page if it wasn't already
0035                 kcm.push("RulesEditor.qml");
0036             }
0037         }
0038     }
0039 
0040     view: ListView {
0041         id: ruleBookView
0042         clip: true
0043 
0044         model: kcm.ruleBookModel
0045         currentIndex: kcm.editIndex
0046         delegate: RuleBookDelegate {}
0047         reuseItems: true
0048 
0049         highlightMoveDuration: Kirigami.Units.longDuration
0050 
0051         displaced: Transition {
0052             NumberAnimation {
0053                 properties: "y"
0054                 duration: Kirigami.Units.longDuration
0055             }
0056         }
0057 
0058         Kirigami.PlaceholderMessage {
0059             visible: ruleBookView.count === 0
0060             anchors.centerIn: parent
0061             width: parent.width - (Kirigami.Units.largeSpacing * 4)
0062             text: i18n("No rules for specific windows are currently set");
0063             explanation: xi18nc("@info", "Click the <interface>Add New…</interface> button below to add some")
0064         }
0065     }
0066 
0067     header: Kirigami.InlineMessage {
0068         id: exportInfo
0069         icon.source: "document-export"
0070         showCloseButton: true
0071         text: i18n("Select the rules to export")
0072         actions: [
0073             Kirigami.Action {
0074                 icon.name: "dialog-ok-apply"
0075                 text: checked ? i18n("Unselect All") : i18n("Select All")
0076                 checkable: true
0077                 checked: selectedIndexes.length === ruleBookView.count
0078                 onToggled: {
0079                     if (checked) {
0080                         selectedIndexes = [...Array(ruleBookView.count).keys()]
0081                     } else {
0082                         selectedIndexes = [];
0083                     }
0084                 }
0085             }
0086             ,
0087             Kirigami.Action {
0088                 icon.name: "document-save"
0089                 text: i18n("Save Rules")
0090                 enabled: selectedIndexes.length > 0
0091                 onTriggered: {
0092                     exportDialog.active = true;
0093                 }
0094             }
0095         ]
0096     }
0097 
0098     footer: RowLayout {
0099         QQC2.Button {
0100             text: i18n("Add New…")
0101             icon.name: "list-add"
0102             enabled: !exportInfo.visible
0103             onClicked: {
0104                 kcm.createRule();
0105             }
0106         }
0107         Item {
0108             Layout.fillWidth: true
0109         }
0110         QQC2.Button {
0111             text: i18n("Import…")
0112             icon.name: "document-import"
0113             enabled: !exportInfo.visible
0114             onClicked: {
0115                 importDialog.active = true;
0116             }
0117         }
0118         QQC2.Button {
0119             text: checked ? i18n("Cancel Export") : i18n("Export…")
0120             icon.name: exportInfo.visible ? "dialog-cancel" : "document-export"
0121             enabled: ruleBookView.count > 0
0122             checkable: true
0123             checked: exportInfo.visible
0124             onToggled: {
0125                 selectedIndexes = [];
0126                 exportInfo.visible = checked;
0127             }
0128         }
0129     }
0130 
0131     component RuleBookDelegate : Item {
0132         // External item required to make Kirigami.ListItemDragHandle work
0133         width: ruleBookView.width
0134         implicitHeight: ruleBookItem.implicitHeight
0135 
0136         ListView.onPooled: {
0137             if (descriptionField.activeFocus) {
0138                 // If the description was being edited when the item is pooled, finish the edition
0139                 ruleBookItem.forceActiveFocus();
0140             }
0141         }
0142 
0143         QQC2.ItemDelegate {
0144             id: ruleBookItem
0145 
0146             width: ruleBookView.width
0147             down: false  // Disable press effect
0148 
0149             contentItem: RowLayout {
0150                 Kirigami.ListItemDragHandle {
0151                     visible: !exportInfo.visible
0152                     listItem: ruleBookItem
0153                     listView: ruleBookView
0154                     onMoveRequested: (oldIndex, newIndex) => {
0155                         kcm.moveRule(oldIndex, newIndex);
0156                     }
0157                 }
0158 
0159                 QQC2.TextField {
0160                     id: descriptionField
0161                     Layout.minimumWidth: Kirigami.Units.gridUnit * 2
0162                     Layout.fillWidth: true
0163                     background: Item {}
0164                     horizontalAlignment: Text.AlignLeft
0165                     text: model && model.display
0166                     onEditingFinished: {
0167                         kcm.setRuleDescription(index, text);
0168                     }
0169                     Keys.onPressed: event => {
0170                         switch (event.key) {
0171                         case Qt.Key_Escape:
0172                             // On <Esc> key reset to model data before losing focus
0173                             text = model.display;
0174                         case Qt.Key_Enter:
0175                         case Qt.Key_Return:
0176                         case Qt.Key_Tab:
0177                             ruleBookItem.forceActiveFocus();
0178                             event.accepted = true;
0179                             break;
0180                         }
0181                     }
0182 
0183                     MouseArea {
0184                         anchors.fill: parent
0185                         enabled: exportInfo.visible
0186                         cursorShape: enabled ? Qt.PointingHandCursor : Qt.IBeamCursor
0187                         onClicked: {
0188                             itemSelectionCheck.toggle();
0189                             itemSelectionCheck.toggled();
0190                         }
0191                     }
0192                 }
0193 
0194                 DelegateButton {
0195                     text: i18n("Edit")
0196                     icon.name: "edit-entry"
0197                     onClicked: kcm.editRule(index);
0198                 }
0199 
0200                 DelegateButton {
0201                     text: i18n("Duplicate")
0202                     icon.name: "edit-duplicate"
0203                     onClicked: kcm.duplicateRule(index);
0204                 }
0205 
0206                 DelegateButton {
0207                     text: i18n("Delete")
0208                     icon.name: "entry-delete"
0209                     onClicked: kcm.removeRule(index);
0210                 }
0211 
0212                 QQC2.CheckBox {
0213                     id: itemSelectionCheck
0214                     visible: exportInfo.visible
0215                     checked: selectedIndexes.includes(index)
0216                     onToggled: {
0217                         var position = selectedIndexes.indexOf(index);
0218                         if (checked) {
0219                             if (position < 0) { selectedIndexes.push(index); }
0220                         } else {
0221                             if (position >= 0) { selectedIndexes.splice(position, 1); }
0222                         }
0223                         selectedIndexesChanged();
0224                     }
0225                 }
0226             }
0227         }
0228     }
0229 
0230     component DelegateButton: QQC2.ToolButton {
0231         visible: !exportInfo.visible
0232         display: QQC2.AbstractButton.IconOnly
0233         QQC2.ToolTip.text: text
0234         QQC2.ToolTip.visible: hovered
0235     }
0236 
0237     FileDialogLoader {
0238         id: importDialog
0239         title: i18n("Import Rules")
0240         isSaveDialog: false
0241         onLastFolderChanged: {
0242             exportDialog.lastFolder = lastFolder;
0243         }
0244         onFileSelected: path => {
0245             kcm.importFromFile(path);
0246         }
0247     }
0248 
0249     FileDialogLoader {
0250         id: exportDialog
0251         title: i18n("Export Rules")
0252         isSaveDialog: true
0253         onLastFolderChanged: {
0254             importDialog.lastFolder = lastFolder;
0255         }
0256         onFileSelected: path => {
0257             selectedIndexes.sort();
0258             kcm.exportToFile(path, selectedIndexes);
0259             exportInfo.visible = false;
0260         }
0261     }
0262 }