5import Qt.labs.platform as Labs
8import QGroundControl.Controls
10/// This control is meant to be a direct replacement for the standard Qml FileDialog control.
11/// It differs for mobile builds which uses a completely custom file picker.
16 property string folder // Due to Qt bug with file url parsing this must be an absolute path
17 property var nameFilters: [] // Important: Only name filters with simple wildcarding like *.foo are supported.
19 property bool selectFolder: false
20 property string defaultSuffix: ""
22 signal acceptedForLoad(string file)
23 signal acceptedForSave(string file)
25 signal fileImportedNotify // Emitted on a successful import so the open dialog can refresh its list.
27 function openForLoad() {
29 if (_mobileDlg && folder.length !== 0) {
30 mobileFileOpenDialogFactory.open()
31 } else if (selectFolder) {
32 fullFolderDialog.open()
34 fullFileDialog.fileMode = FileDialog.OpenFile
39 function openForSave() {
41 if (_mobileDlg && folder.length !== 0) {
42 mobileFileSaveDialogFactory.open()
44 fullFileDialog.fileMode = FileDialog.SaveFile
50 fullFileDialog.close()
53 property bool _openForLoad: true
54 property real _margins: ScreenTools.defaultFontPixelHeight / 2
55 property bool _mobileDlg: QGroundControl.corePlugin.options.useMobileFileDialog
56 property var _rgExtensions
57 property string _mobileShortPath
58 property bool _importPending: false
60 Component.onCompleted: {
61 _setupFileExtensions()
62 _updateMobileShortPath()
65 onFolderChanged: _updateMobileShortPath()
66 onNameFiltersChanged: _setupFileExtensions()
68 function _updateMobileShortPath() {
69 if (ScreenTools.isMobile) {
70 _mobileShortPath = QGCFileDialogController.fullFolderPathToShortMobilePath(folder);
74 function _setupFileExtensions() {
76 for (var i=0; i<_root.nameFilters.length; i++) {
77 var filter = _root.nameFilters[i]
78 var regExp = /^.*\((.*)\)$/
79 var result = regExp.exec(filter)
80 if (result.length === 2) {
83 var rgFilters = filter.split(" ")
84 for (var j=0; j<rgFilters.length; j++) {
85 if (!_mobileDlg || (rgFilters[j] !== "*" && rgFilters[j] !== "*.*")) {
86 _rgExtensions.push(rgFilters[j])
92 QGCPalette { id: qgcPal; colorGroupEnabled: true }
95 target: QGCFileDialogController
96 enabled: Qt.platform.os === "android" && _root._importPending
98 function onFileImported() {
99 _root._importPending = false
100 _root.fileImportedNotify()
103 function onImportFailed(errorMessage) {
104 _root._importPending = false
105 QGroundControl.showMessageDialog(_root, qsTr("Import"), errorMessage)
111 currentFolder: "file:///" + _root.folder
112 nameFilters: _root.nameFilters ? _root.nameFilters : []
114 defaultSuffix: _root.defaultSuffix
117 var fullPath = QGCFileDialogController.urlToLocalFile(selectedFile)
118 if (fileMode == FileDialog.OpenFile) {
119 _root.acceptedForLoad(fullPath)
121 _root.acceptedForSave(fullPath)
124 onRejected: _root.rejected()
129 currentFolder: "file:///" + _root.folder
132 onAccepted: _root.acceptedForLoad(QGCFileDialogController.urlToLocalFile(folder))
133 onRejected: _root.rejected()
136 QGCPopupDialogFactory {
137 id: mobileFileOpenDialogFactory
139 dialogComponent: mobileFileOpenDialogComponent
143 id: mobileFileOpenDialogComponent
146 id: mobileFileOpenDialog
148 buttons: Dialog.Cancel
152 function onFileImportedNotify() {
153 fileRepeater.model = QGCFileDialogController.getFiles(folder, _rgExtensions)
159 width: 40 * ScreenTools.defaultFontPixelWidth
160 spacing: ScreenTools.defaultFontPixelHeight / 2
162 QGCLabel { text: qsTr("Path: %1").arg(_mobileShortPath) }
166 model: QGCFileDialogController.getFiles(folder, _rgExtensions)
170 anchors.left: parent.left
171 anchors.right: parent.right
175 mobileFileOpenDialog.close()
176 _root.acceptedForLoad(QGCFileDialogController.fullyQualifiedFilename(folder, modelData))
179 onHamburgerClicked: {
181 hamburgerMenu.fileToDelete = QGCFileDialogController.fullyQualifiedFilename(folder, modelData)
182 hamburgerMenu.popup()
188 property string fileToDelete
190 onAboutToHide: fileButton.highlight = false
195 QGCFileDialogController.deleteFile(hamburgerMenu.fileToDelete)
196 fileRepeater.model = QGCFileDialogController.getFiles(folder, _rgExtensions)
204 text: qsTr("No files")
205 visible: fileRepeater.model.length === 0
209 anchors.left: parent.left
210 anchors.right: parent.right
212 visible: Qt.platform.os === "android"
215 _root._importPending = true
216 QGCFileDialogController.importFromNativePicker()
223 QGCPopupDialogFactory {
224 id: mobileFileSaveDialogFactory
226 dialogComponent: mobileFileSaveDialogComponent
230 id: mobileFileSaveDialogComponent
233 id: mobileFileSaveDialog
235 buttons: Dialog.Cancel | Dialog.Ok
238 if (filenameTextField.text == "") {
239 mobileFileSaveDialog.preventClose = true
242 if (!replaceMessage.visible) {
243 if (QGCFileDialogController.fileExists(QGCFileDialogController.fullyQualifiedFilename(folder, filenameTextField.text, _rgExtensions))) {
244 replaceMessage.visible = true
245 mobileFileSaveDialog.preventClose = true
249 _root.acceptedForSave(QGCFileDialogController.fullyQualifiedFilename(folder, filenameTextField.text, _rgExtensions))
254 width: 40 * ScreenTools.defaultFontPixelWidth
255 spacing: ScreenTools.defaultFontPixelHeight / 2
258 anchors.left: parent.left
259 anchors.right: parent.right
260 spacing: ScreenTools.defaultFontPixelWidth
262 QGCLabel { text: qsTr("New file name:") }
265 id: filenameTextField
266 Layout.fillWidth: true
267 onTextChanged: replaceMessage.visible = false
273 anchors.left: parent.left
274 anchors.right: parent.right
275 wrapMode: Text.WordWrap
276 text: qsTr("The file %1 exists. Click Save again to replace it.").arg(filenameTextField.text)
278 color: qgcPal.warningText
282 anchors.left: parent.left
283 anchors.right: parent.right
284 text: qsTr("Save to existing file:")
289 model: QGCFileDialogController.getFiles(folder, [ _rgExtensions ])
293 anchors.left: parent.left
294 anchors.right: parent.right
298 mobileFileSaveDialog.close()
299 _root.acceptedForSave(QGCFileDialogController.fullyQualifiedFilename(folder, modelData))
302 onHamburgerClicked: {
304 hamburgerMenu.fileToDelete = QGCFileDialogController.fullyQualifiedFilename(folder, modelData)
305 hamburgerMenu.popup()
311 property string fileToDelete
313 onAboutToHide: fileButton.highlight = false
318 QGCFileDialogController.deleteFile(hamburgerMenu.fileToDelete)
319 fileRepeater.model = QGCFileDialogController.getFiles(folder, [ _rgExtensions ])