Warning, /plasma/flatpak-kcm/ui/main.qml is written in an unsupported language. File is not indexed.
0001 /** 0002 * SPDX-FileCopyrightText: 2022 Suhaas Joshi <joshiesuhaas0@gmail.com> 0003 * SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 pragma ComponentBehavior: Bound 0008 0009 import QtQuick 0010 import QtQuick.Layouts 0011 import QtQuick.Controls as QQC2 0012 import org.kde.kirigami as Kirigami 0013 import org.kde.kcmutils as KCM 0014 import org.kde.kitemmodels as KItemModels 0015 import org.kde.plasma.kcm.flatpakpermissions 0016 0017 KCM.ScrollViewKCM { 0018 id: root 0019 title: i18n("Flatpak Applications") 0020 Kirigami.ColumnView.fillWidth: false 0021 implicitWidth: Kirigami.Units.gridUnit * 40 0022 implicitHeight: Kirigami.Units.gridUnit * 20 0023 framedView: false 0024 0025 function shouldChange(toAppAtFilteredRowIndex: int) { 0026 const fromAppAtSourceRowIndex = KCM.ConfigModule.currentIndex(); 0027 0028 const toAppAtSourceRowIndex = (toAppAtFilteredRowIndex === -1) 0029 ? toAppAtFilteredRowIndex 0030 : filteredRefsModel.mapToSource(filteredRefsModel.index(toAppAtFilteredRowIndex, 0)).row; 0031 0032 if (toAppAtSourceRowIndex === KCM.ConfigModule.currentIndex()) { 0033 // Don't reload if it's current anyway. 0034 return; 0035 } 0036 0037 if (fromAppAtSourceRowIndex !== -1 && KCM.ConfigModule.isSaveNeeded()) { 0038 const m = KCM.ConfigModule.refsModel; 0039 const fromAppAtSourceIndex = m.index(fromAppAtSourceRowIndex, 0); 0040 const applicationName = m.data(fromAppAtSourceIndex, FlatpakReferencesModel.Name); 0041 const applicationIcon = m.data(fromAppAtSourceIndex, FlatpakReferencesModel.Icon); 0042 const dialog = applyOrDiscardDialogComponent.createObject(this, { 0043 applicationName, 0044 applicationIcon, 0045 fromAppAtSourceRowIndex, 0046 toAppAtSourceRowIndex, 0047 }); 0048 dialog.open(); 0049 } else { 0050 changeApp(toAppAtSourceRowIndex) 0051 } 0052 } 0053 0054 function changeApp(toAppAtSourceRowIndex) { 0055 let ref = null; 0056 if (toAppAtSourceRowIndex !== -1) { 0057 const sourceIndex = KCM.ConfigModule.refsModel.index(toAppAtSourceRowIndex, 0); 0058 ref = KCM.ConfigModule.refsModel.data(sourceIndex, FlatpakReferencesModel.Ref) as FlatpakReference; 0059 appsListView.setCurrentIndexLater(toAppAtSourceRowIndex); 0060 } 0061 KCM.ConfigModule.pop(); 0062 KCM.ConfigModule.setIndex(toAppAtSourceRowIndex); 0063 KCM.ConfigModule.push("permissions.qml", { ref }); 0064 } 0065 0066 Component.onCompleted: { 0067 KCM.ConfigModule.columnWidth = Kirigami.Units.gridUnit * 15 0068 changeApp(KCM.ConfigModule.currentIndex()); 0069 } 0070 0071 KCM.ConfigModule.buttons: KCM.ConfigModule.Apply | KCM.ConfigModule.Default 0072 0073 Component { 0074 id: applyOrDiscardDialogComponent 0075 0076 Kirigami.PromptDialog { 0077 id: dialog 0078 0079 required property string applicationName 0080 required property url applicationIcon 0081 0082 // source model indices 0083 required property int fromAppAtSourceRowIndex 0084 required property int toAppAtSourceRowIndex 0085 0086 readonly property bool narrow: (parent.width - leftMargin - rightMargin) < Kirigami.Units.gridUnit * 20 0087 0088 parent: root.Kirigami.ColumnView.view 0089 title: i18n("Apply Permissions") 0090 subtitle: i18n("The permissions of application %1 have been changed. Do you want to apply these changes or discard them?", applicationName) 0091 standardButtons: QQC2.Dialog.Apply | QQC2.Dialog.Discard 0092 0093 GridLayout { 0094 columns: dialog.narrow ? 1 : 2 0095 columnSpacing: Kirigami.Units.largeSpacing 0096 rowSpacing: Kirigami.Units.largeSpacing 0097 0098 Kirigami.Icon { 0099 source: dialog.applicationIcon.toString() !== "" ? dialog.applicationIcon : "application-vnd.flatpak.ref" 0100 0101 Layout.alignment: Qt.AlignCenter 0102 Layout.preferredWidth: Kirigami.Units.iconSizes.large 0103 Layout.preferredHeight: Kirigami.Units.iconSizes.large 0104 } 0105 Kirigami.SelectableLabel { 0106 text: dialog.subtitle 0107 wrapMode: Text.Wrap 0108 0109 Layout.fillWidth: true 0110 Layout.fillHeight: true 0111 } 0112 } 0113 0114 QQC2.Overlay.modal: KcmPopupModal {} 0115 0116 onOpened: { 0117 const button = standardButton(QQC2.Dialog.Apply); 0118 button.forceActiveFocus(Qt.TabFocusReason); 0119 } 0120 0121 onApplied: { 0122 root.KCM.ConfigModule.save() 0123 root.changeApp(toAppAtSourceRowIndex) 0124 dialog.close() 0125 } 0126 0127 onDiscarded: { 0128 root.KCM.ConfigModule.load() 0129 root.changeApp(fromAppAtSourceRowIndex) 0130 dialog.close() 0131 } 0132 0133 onRejected: { 0134 appsListView.currentIndex = root.KCM.ConfigModule.currentIndex() 0135 } 0136 0137 onClosed: destroy() 0138 } 0139 } 0140 0141 header: Kirigami.SearchField { 0142 id: filterField 0143 KeyNavigation.tab: appsListView 0144 KeyNavigation.down: appsListView 0145 autoAccept: false 0146 onAccepted: { 0147 if (text === "") { 0148 // The signal also fires when user clicks the "Clear" action/icon/button. 0149 // In this case don't treat it as a command to open first app. 0150 return; 0151 } 0152 if (filteredRefsModel.count >= 0) { 0153 appsListView.setCurrentIndexLater(0); 0154 root.shouldChange(0); 0155 } 0156 } 0157 } 0158 0159 view: ListView { 0160 id: appsListView 0161 0162 function setCurrentIndexLater(sourceRowIndex) { 0163 // View has not updated yet, and alas -- we don't have suitable 0164 // hooks here. Note that ListView::onCountChanged WON'T WORK, as 0165 // unlike KSortFilterProxyModel it won't trigger when changing 0166 // from e.g. 2 rows [a, b] to another 2 rows [d, c]. 0167 0168 const sourceIndex = filteredRefsModel.sourceModel.index(sourceRowIndex, 0); 0169 const filteredIndex = filteredRefsModel.mapFromSource(sourceIndex); 0170 const filteredRowIndex = filteredIndex.valid ? filteredIndex.row : -1; 0171 0172 delayedCurrentIndexSetter.index = filteredRowIndex; 0173 delayedCurrentIndexSetter.start(); 0174 } 0175 0176 // Using Timer object instead of Qt.callLater to get deduplication for free. 0177 Timer { 0178 id: delayedCurrentIndexSetter 0179 0180 property int index: -1 0181 0182 interval: 0 0183 running: false 0184 0185 onTriggered: { 0186 appsListView.currentIndex = index; 0187 } 0188 } 0189 0190 model: KItemModels.KSortFilterProxyModel { 0191 id: filteredRefsModel 0192 sourceModel: root.KCM.ConfigModule.refsModel 0193 sortOrder: Qt.AscendingOrder 0194 sortCaseSensitivity: Qt.CaseInsensitive 0195 sortRole: FlatpakReferencesModel.Name 0196 filterRole: FlatpakReferencesModel.Name 0197 filterString: filterField.text 0198 filterCaseSensitivity: Qt.CaseInsensitive 0199 onCountChanged: { 0200 if (count >= 0) { 0201 const sourceRowIndex = root.KCM.ConfigModule.currentIndex(); 0202 appsListView.setCurrentIndexLater(sourceRowIndex); 0203 } 0204 } 0205 } 0206 currentIndex: -1 0207 delegate: QQC2.ItemDelegate { 0208 required property int index 0209 required property var model 0210 0211 width: ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin 0212 0213 highlighted: ListView.isCurrentItem 0214 0215 text: model.name 0216 // Prefer source, fallback to name. This is unusual for QtQuick.Controls. 0217 icon.name: model.icon.toString() !== "" ? "" : "application-vnd.flatpak.ref" 0218 icon.source: model.icon.toString() === "" ? "" : model.icon 0219 0220 onClicked: root.shouldChange(index) 0221 } 0222 } 0223 }