Warning, /plasma/xdg-desktop-portal-kde/src/AppChooserDialog.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * SPDX-FileCopyrightText: 2019 Red Hat Inc
0003  * SPDX-License-Identifier: LGPL-2.0-or-later
0004  *
0005  * SPDX-FileCopyrightText: 2019 Jan Grulich <jgrulich@redhat.com>
0006  * SPDX-FileCopyrightText: 2022 Nate Graham <nate@kde.org>
0007  */
0008 
0009 
0010 import QtQuick 2.15
0011 import Qt.labs.platform 1.1
0012 import QtQuick.Controls 2.15
0013 import QtQuick.Layouts 1.12
0014 import org.kde.kirigami 2.19 as Kirigami
0015 import org.kde.plasma.workspace.dialogs 1.0 as PWD
0016 
0017 import org.kde.xdgdesktopportal 1.0
0018 
0019 PWD.SystemDialog
0020 {
0021     id: root
0022     iconName: "applications-all"
0023 
0024     property bool remember: false
0025 
0026 
0027     ColumnLayout {
0028         spacing: Kirigami.Units.smallSpacing
0029 
0030         CheckBox {
0031             text: i18nc("@option:check %1 is description of a file type, like 'PNG image'", "Always open %1 files with the chosen app", AppChooserData.mimeDesc)
0032             checked: root.remember
0033             onToggled: { root.remember = checked }
0034         }
0035 
0036         RowLayout {
0037             spacing: Kirigami.Units.smallSpacing
0038 
0039             Kirigami.SearchField {
0040                 id: searchField
0041                 implicitWidth: Kirigami.Units.gridUnit * 20
0042                 Layout.fillWidth: true
0043                 focus: true
0044                 // We don't want auto-accept here because it would cause the
0045                 // selected app in the grid view to be immediately launched
0046                 // without user input
0047                 autoAccept: false
0048 
0049                 Keys.onDownPressed: {
0050                     grid.forceActiveFocus();
0051                     grid.currentIndex = 0;
0052                 }
0053                 onTextChanged: {
0054                     AppModel.filter = text;
0055                     if (text.length > 0 && grid.count === 1) {
0056                         grid.currentIndex = 0;
0057                     }
0058                 }
0059                 onAccepted: grid.currentItem.activate();
0060             }
0061 
0062             Button {
0063                 icon.name: "view-more-symbolic"
0064                 text: i18n("Show All Installed Applications")
0065 
0066                 checkable: true
0067                 checked: !AppModel.showOnlyPreferredApps
0068                 visible: AppModel.sourceModel.hasPreferredApps
0069                 onVisibleChanged: AppModel.showOnlyPreferredApps = visible
0070 
0071                 onClicked: {
0072                     AppModel.showOnlyPreferredApps = !AppModel.showOnlyPreferredApps
0073                 }
0074             }
0075         }
0076 
0077 
0078         ScrollView {
0079             id: scrollView
0080 
0081             readonly property int viewWidth: width - (ScrollBar.vertical.visible ? ScrollBar.vertical.width : 0)
0082 
0083             Layout.fillWidth: true
0084             Layout.fillHeight: true
0085             Layout.preferredHeight: grid.cellHeight * 3
0086 
0087             Component.onCompleted: background.visible = true
0088 
0089             GridView {
0090                 id: grid
0091 
0092                 readonly property int gridDelegateSize: Kirigami.Units.iconSizes.huge + (Kirigami.Units.gridUnit * 4)
0093 
0094                 Keys.onReturnPressed: currentItem.activate();
0095                 Keys.onEnterPressed: currentItem.activate();
0096 
0097                 currentIndex: -1 // Don't pre-select anything as that doesn't make sense here
0098 
0099                 cellWidth: {
0100                     let columns = Math.max(Math.floor(scrollView.viewWidth / gridDelegateSize), 2);
0101                     return Math.floor(scrollView.viewWidth / columns) - 1;
0102                 }
0103                 cellHeight: gridDelegateSize
0104 
0105                 model: AppModel
0106                 delegate: Item {
0107                     id: delegate
0108 
0109                     height: grid.cellHeight
0110                     width: grid.cellWidth
0111 
0112                     function activate() {
0113                         AppChooserData.applicationSelected(model.applicationDesktopFile, root.remember)
0114                     }
0115 
0116                     HoverHandler {
0117                         id: hoverhandler
0118                     }
0119                     TapHandler {
0120                         id: taphandler
0121                         onTapped: delegate.activate()
0122                     }
0123 
0124                     Rectangle {
0125                         readonly property color theColor: Kirigami.Theme.highlightColor
0126                         anchors.fill: parent
0127                         visible: hoverhandler.hovered || delegate == grid.currentItem
0128                         border.color: theColor
0129                         border.width: 1
0130                         color: taphandler.pressed ? theColor
0131                                                   : Qt.rgba(theColor.r, theColor.g, theColor.b, 0.3)
0132                         radius: Kirigami.Units.smallSpacing
0133                     }
0134 
0135                     ColumnLayout {
0136                         anchors {
0137                             top: parent.top
0138                             left: parent.left
0139                             right: parent.right
0140                             margins: Kirigami.Units.largeSpacing
0141                         }
0142                         spacing: 0 // Items add their own as needed here
0143 
0144                         Kirigami.Icon {
0145                             Layout.preferredWidth: Kirigami.Units.iconSizes.huge
0146                             Layout.preferredHeight: Kirigami.Units.iconSizes.huge
0147                             Layout.bottomMargin: Kirigami.Units.largeSpacing
0148                             Layout.alignment: Qt.AlignHCenter
0149                             source: model.applicationIcon
0150                             smooth: true
0151                         }
0152 
0153                         Label {
0154                             Layout.fillWidth: true
0155                             Layout.alignment: Qt.AlignTop
0156                             horizontalAlignment: Text.AlignHCenter
0157                             text: model.applicationName
0158                             font.bold: model.applicationDesktopFile === AppChooserData.defaultApp
0159                             elide: Text.ElideRight
0160                             maximumLineCount: 2
0161                             wrapMode: Text.WordWrap
0162                         }
0163 
0164                         Label {
0165                             Layout.fillWidth: true
0166                             Layout.alignment: Qt.AlignTop
0167                             horizontalAlignment: Text.AlignHCenter
0168                             visible: model.applicationDesktopFile === AppChooserData.defaultApp
0169                             font.bold: true
0170                             opacity: 0.7
0171                             text: i18n("Default app for this file type")
0172                             elide: Text.ElideRight
0173                             maximumLineCount: 2
0174                             wrapMode: Text.WordWrap
0175                         }
0176                     }
0177                 }
0178 
0179                 Loader {
0180                     id: placeholderLoader
0181 
0182                     anchors.centerIn: parent
0183                     width: parent.width -(Kirigami.Units.gridUnit - 8)
0184 
0185                     active: grid.count === 0
0186                     sourceComponent:Kirigami.PlaceholderMessage {
0187                         anchors.centerIn: parent
0188 
0189                         icon.name: "edit-none"
0190                         text: searchField.text.length > 0 ? i18n("No matches") : xi18nc("@info", "No installed applications can open <filename>%1</filename>", AppChooserData.fileName)
0191 
0192                         helpfulAction: Kirigami.Action {
0193                             iconName: "plasmadiscover"
0194                             text: i18nc("Find some more apps that can open this content using the Discover app", "Find More in Discover")
0195                             onTriggered: AppChooserData.openDiscover()
0196                         }
0197                     }
0198                 }
0199             }
0200         }
0201 
0202         // Using a TextEdit here instead of a Label because it can know when any
0203         // links are hovered, which is needed for us to be able to use the correct
0204         // cursor shape for it.
0205 
0206         TextEdit {
0207             visible: !placeholderLoader.active && StandardPaths.findExecutable("plasma-discover") != ""
0208             Layout.fillWidth: true
0209             text: xi18nc("@info", "Don't see the right app? Find more in <link>Discover</link>.")
0210             textFormat: Text.RichText
0211             wrapMode: Text.WordWrap
0212             readOnly: true
0213             color: Kirigami.Theme.textColor
0214             selectedTextColor: Kirigami.Theme.highlightedTextColor
0215             selectionColor: Kirigami.Theme.highlightColor
0216 
0217             onLinkActivated: {
0218                 AppChooserData.openDiscover()
0219             }
0220 
0221             HoverHandler {
0222                 acceptedButtons: Qt.NoButton
0223                 cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
0224             }
0225         }
0226     }
0227 }
0228