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 }