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)
26 function openForLoad() {
28 if (_mobileDlg && folder.length !== 0) {
29 mobileFileOpenDialogFactory.open()
30 } else if (selectFolder) {
31 fullFolderDialog.open()
33 fullFileDialog.fileMode = FileDialog.OpenFile
38 function openForSave() {
40 if (_mobileDlg && folder.length !== 0) {
41 mobileFileSaveDialogFactory.open()
43 fullFileDialog.fileMode = FileDialog.SaveFile
49 fullFileDialog.close()
52 property bool _openForLoad: true
53 property real _margins: ScreenTools.defaultFontPixelHeight / 2
54 property bool _mobileDlg: QGroundControl.corePlugin.options.useMobileFileDialog
55 property var _rgExtensions
56 property string _mobileShortPath
58 Component.onCompleted: {
59 _setupFileExtensions()
60 _updateMobileShortPath()
63 onFolderChanged: _updateMobileShortPath()
64 onNameFiltersChanged: _setupFileExtensions()
66 function _updateMobileShortPath() {
67 if (ScreenTools.isMobile) {
68 _mobileShortPath = QGCFileDialogController.fullFolderPathToShortMobilePath(folder);
72 function _setupFileExtensions() {
74 for (var i=0; i<_root.nameFilters.length; i++) {
75 var filter = _root.nameFilters[i]
76 var regExp = /^.*\((.*)\)$/
77 var result = regExp.exec(filter)
78 if (result.length === 2) {
81 var rgFilters = filter.split(" ")
82 for (var j=0; j<rgFilters.length; j++) {
83 if (!_mobileDlg || (rgFilters[j] !== "*" && rgFilters[j] !== "*.*")) {
84 _rgExtensions.push(rgFilters[j])
90 QGCPalette { id: qgcPal; colorGroupEnabled: true }
94 currentFolder: "file:///" + _root.folder
95 nameFilters: _root.nameFilters ? _root.nameFilters : []
97 defaultSuffix: _root.defaultSuffix
100 var fullPath = QGCFileDialogController.urlToLocalFile(selectedFile)
101 if (fileMode == FileDialog.OpenFile) {
102 _root.acceptedForLoad(fullPath)
104 _root.acceptedForSave(fullPath)
107 onRejected: _root.rejected()
112 currentFolder: "file:///" + _root.folder
115 onAccepted: _root.acceptedForLoad(QGCFileDialogController.urlToLocalFile(folder))
116 onRejected: _root.rejected()
119 QGCPopupDialogFactory {
120 id: mobileFileOpenDialogFactory
122 dialogComponent: mobileFileOpenDialogComponent
126 id: mobileFileOpenDialogComponent
129 id: mobileFileOpenDialog
131 buttons: Dialog.Cancel
135 width: 40 * ScreenTools.defaultFontPixelWidth
136 spacing: ScreenTools.defaultFontPixelHeight / 2
138 QGCLabel { text: qsTr("Path: %1").arg(_mobileShortPath) }
142 model: QGCFileDialogController.getFiles(folder, _rgExtensions)
146 anchors.left: parent.left
147 anchors.right: parent.right
151 mobileFileOpenDialog.close()
152 _root.acceptedForLoad(QGCFileDialogController.fullyQualifiedFilename(folder, modelData))
155 onHamburgerClicked: {
157 hamburgerMenu.fileToDelete = QGCFileDialogController.fullyQualifiedFilename(folder, modelData)
158 hamburgerMenu.popup()
164 property string fileToDelete
166 onAboutToHide: fileButton.highlight = false
171 QGCFileDialogController.deleteFile(hamburgerMenu.fileToDelete)
172 fileRepeater.model = QGCFileDialogController.getFiles(folder, _rgExtensions)
180 text: qsTr("No files")
181 visible: fileRepeater.model.length === 0
187 QGCPopupDialogFactory {
188 id: mobileFileSaveDialogFactory
190 dialogComponent: mobileFileSaveDialogComponent
194 id: mobileFileSaveDialogComponent
197 id: mobileFileSaveDialog
199 buttons: Dialog.Cancel | Dialog.Ok
202 if (filenameTextField.text == "") {
203 mobileFileSaveDialog.preventClose = true
206 if (!replaceMessage.visible) {
207 if (QGCFileDialogController.fileExists(QGCFileDialogController.fullyQualifiedFilename(folder, filenameTextField.text, _rgExtensions))) {
208 replaceMessage.visible = true
209 mobileFileSaveDialog.preventClose = true
213 _root.acceptedForSave(QGCFileDialogController.fullyQualifiedFilename(folder, filenameTextField.text, _rgExtensions))
218 width: 40 * ScreenTools.defaultFontPixelWidth
219 spacing: ScreenTools.defaultFontPixelHeight / 2
222 anchors.left: parent.left
223 anchors.right: parent.right
224 spacing: ScreenTools.defaultFontPixelWidth
226 QGCLabel { text: qsTr("New file name:") }
229 id: filenameTextField
230 Layout.fillWidth: true
231 onTextChanged: replaceMessage.visible = false
237 anchors.left: parent.left
238 anchors.right: parent.right
239 wrapMode: Text.WordWrap
240 text: qsTr("The file %1 exists. Click Save again to replace it.").arg(filenameTextField.text)
242 color: qgcPal.warningText
246 anchors.left: parent.left
247 anchors.right: parent.right
248 text: qsTr("Save to existing file:")
253 model: QGCFileDialogController.getFiles(folder, [ _rgExtensions ])
257 anchors.left: parent.left
258 anchors.right: parent.right
262 mobileFileSaveDialog.close()
263 _root.acceptedForSave(QGCFileDialogController.fullyQualifiedFilename(folder, modelData))
266 onHamburgerClicked: {
268 hamburgerMenu.fileToDelete = QGCFileDialogController.fullyQualifiedFilename(folder, modelData)
269 hamburgerMenu.popup()
275 property string fileToDelete
277 onAboutToHide: fileButton.highlight = false
282 QGCFileDialogController.deleteFile(hamburgerMenu.fileToDelete)
283 fileRepeater.model = QGCFileDialogController.getFiles(folder, [ _rgExtensions ])