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

0001 // SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
0002 //
0003 // SPDX-License-Identifier: GPL-2.0-or-later
0004 
0005 import QtQuick
0006 import QtQuick.Layouts
0007 import QtQuick.Controls as Controls
0008 import org.kde.kirigami as Kirigami
0009 
0010 import org.kde.kirigamifilepicker
0011 
0012 /**
0013  * The FilePicker type provides a file picker wrapped in a Kirigmi.Page.
0014  * It can be directly pushed to the pageStack.
0015  */
0016 Kirigami.ScrollablePage {
0017     id: root
0018 
0019     property bool selectMultiple
0020     property bool selectExisting
0021     property var nameFilters: []
0022     property var mimeTypeFilters: []
0023     property alias folder: dirModel.folder
0024     property bool showHiddenFiles: false
0025     property string currentFile
0026     property string acceptLabel
0027     property bool selectFolder
0028 
0029     property alias createDirectorySheet: createDirectorySheet
0030 
0031     CreateDirectorySheet {
0032         id: createDirectorySheet
0033         parentPath: dirModel.folder
0034     }
0035 
0036     onCurrentFileChanged: {
0037         if (root.currentFile) {
0038             // Switch into directory of preselected file
0039             fileNameField.text = DirModelUtils.fileNameOfUrl(root.currentFile)
0040             dirModel.folder = DirModelUtils.directoryOfUrl(root.currentFile)
0041         }
0042     }
0043 
0044     // result
0045     property var fileUrls: []
0046 
0047     signal accepted(var urls)
0048 
0049     function addOrRemoveUrl(url) {
0050         var index = root.fileUrls.indexOf(url)
0051         if (index > -1) {
0052             // remove element
0053             root.fileUrls.splice(index, 1)
0054         } else {
0055             root.fileUrls.push(url)
0056         }
0057         root.fileUrlsChanged()
0058     }
0059 
0060     header: ColumnLayout {
0061         spacing: 0
0062         Controls.ToolBar {
0063             Layout.fillWidth: true
0064             Row {
0065                 Controls.ToolButton {
0066                     icon.name: "folder-root-symbolic"
0067                     height: parent.height
0068                     width: height
0069                     onClicked: dirModel.folder = "file:///"
0070                 }
0071                 Repeater {
0072                     model: DirModelUtils.getUrlParts(dirModel.folder)
0073 
0074                     Controls.ToolButton {
0075                         icon.name: "arrow-right"
0076                         text: modelData
0077                         onClicked: dirModel.folder = DirModelUtils.partialUrlForIndex(
0078                                         dirModel.folder, index)
0079                     }
0080                 }
0081             }
0082         }
0083         Kirigami.InlineMessage {
0084             id: errorMessage
0085             Layout.fillWidth: true
0086             type: Kirigami.MessageType.Error
0087             text: dirModel.lastError
0088             showCloseButton: true
0089         }
0090     }
0091     footer: Controls.ToolBar {
0092         visible: !root.selectExisting
0093         height: visible ? Kirigami.Units.gridUnit * 2 : 0
0094 
0095         RowLayout {
0096             anchors.fill: parent
0097             Controls.TextField {
0098                 Layout.fillHeight: true
0099                 Layout.fillWidth: true
0100                 id: fileNameField
0101                 placeholderText: i18n("File name")
0102             }
0103             Controls.ToolButton {
0104                 Layout.fillHeight: true
0105                 icon.name: "dialog-ok-apply"
0106                 onClicked: {
0107                     root.fileUrls = [dirModel.folder + "/" + fileNameField.text]
0108                     root.accepted(root.fileUrls)
0109                 }
0110             }
0111         }
0112     }
0113 
0114     actions: [
0115         Kirigami.Action {
0116             visible: (root.selectMultiple || root.selectFolder) && root.selectExisting
0117             text: root.acceptLabel ? root.acceptLabel : i18n("Select")
0118             icon.name: "dialog-ok"
0119 
0120             onTriggered: {
0121                 if (root.selectFolder) {
0122                     root.accepted([dirModel.folder])
0123                 } else {
0124                     root.accepted(root.fileUrls)
0125                 }
0126             }
0127         }
0128     ]
0129 
0130     DirModel {
0131         id: dirModel
0132         showDotFiles: root.showHiddenFiles
0133         mimeFilters: root.mimeTypeFilters
0134         onLastErrorChanged: errorMessage.visible = true
0135         onFolderChanged: errorMessage.visible = false
0136     }
0137 
0138     Controls.BusyIndicator {
0139         anchors.centerIn: parent
0140 
0141         width: Kirigami.Units.gridUnit * 4
0142         height: width
0143 
0144         visible: dirModel.isLoading
0145     }
0146 
0147     ListView {
0148         model: dirModel
0149         clip: true
0150 
0151         delegate: Controls.ItemDelegate {
0152             required property string name
0153             required property string iconName
0154             required property url url
0155             required property bool isDir
0156 
0157             text: name
0158             icon.name: checked ? "emblem-checked" : iconName
0159             checkable: root.selectExisting && root.selectMultiple
0160             checked: root.fileUrls.includes(url)
0161             highlighted: false
0162             width: ListView.view.width
0163 
0164             onClicked: {
0165                 // open
0166                 if (root.selectExisting) {
0167                     // The delegate being clicked on represents a directory
0168                     if (isDir) {
0169                         // Change into folder
0170                         dirModel.folder = url
0171                     }
0172                     // The delegate represents a file
0173                     else {
0174                         if (root.selectMultiple) {
0175                             // add the file to the list of accepted files
0176                             // (or remove it if it is already there)
0177                             root.addOrRemoveUrl(url)
0178                         } else {
0179                             // If we only want to select one file,
0180                             // Write it into the output variable and close the dialog
0181                             root.fileUrls = [url]
0182                             root.accepted(root.fileUrls)
0183                         }
0184                     }
0185                 }
0186                 // save
0187                 else {
0188                     if (isDir) {
0189                         dirModel.folder = url
0190                     } else {
0191                         fileNameField.text = name
0192                     }
0193                 }
0194             }
0195         }
0196     }
0197 }