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 }