MauiKit File Browsing

FileDialog.qml
1/*
2 * Copyright 2018 Camilo Higuita <milo.h@aol.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20import QtQuick
21import QtQml
22
23import QtQuick.Controls
24import QtQuick.Layouts
25
26import org.mauikit.controls as Maui
27import org.mauikit.filebrowsing as FB
28
29/**
30 * @inherit org::mauikit::controls::PopupPage
31 *
32 * @brief A dialog to quickly select files for opening or saving.
33 *
34 * This controls inherits from MauiKit PopupPage, to checkout its inherited properties refer to the docs.
35 * @see MauiKit::PopupPage
36 *
37 * @note This component makes use of the FileBrowser.
38 *
39 * The FileDialog can be in two modes, one for Opening and other for Saving files.
40 *
41 * The file dialog allows to have multiple or single selection,
42 * and filtering content specific to a file type or arbitrary name filters.
43 *
44 * @image html filedialog.png
45 *
46 * @code
47 * Maui.Page
48 * {
49 * Maui.Controls.showCSD: true
50 * anchors.fill: parent
51 *
52 * Column
53 * {
54 * width: 100
55 * anchors.centerIn: parent
56 *
57 * Button
58 * {
59 * text: "Open"
60 * onClicked:
61 * {
62 * _dialog.mode = FB.FileDialog.Modes.Open
63 * _dialog.callback = (paths) =>
64 * {
65 * console.log("Selected Paths", paths)
66 * _text.text = paths.join("\n")
67 * }
68 * _dialog.open()
69 * }
70 * }
71 *
72 * Button
73 * {
74 * text: "Save"
75 * onClicked:
76 * {
77 * _dialog.mode = FB.FileDialog.Modes.Save
78 * _dialog.callback = (paths) =>
79 * {
80 * console.log("Save to", paths)
81 * _text.text = paths.join("\n")
82 * }
83 * _dialog.open()
84 * }
85 * }
86 *
87 * Text
88 * {
89 * id: _text
90 * }
91 * }
92 * }
93 *
94 * FB.FileDialog
95 * {
96 * id: _dialog
97 * }
98 * @endcode
99 *
100 * <a href="https://invent.kde.org/maui/mauikit-filebrowser/examples/FileDialog.qml">You can find a more complete example at this link.</a>
101 */
102Maui.PopupPage
103{
104 id: control
105
106 maxHeight: Maui.Handy.isMobile ? parent.height * 0.95 : 500
107 maxWidth: 700
108
109 hint: 1
111 page.padding: 0
112 closeButtonVisible: false
113 headBar.visible: false
114
115 /**
116 * @brief The current path of the directory URL.
117 * @see FileBrowser::currentPath
118 */
119 property alias currentPath : _browser.currentPath
120
121 /**
122 * @brief The FileBrowser used for listing.
123 * For more details on how it works check its documentation.
124 * @property FileBrowser FileDialog::browser
125 */
126 readonly property alias browser : _browser
127
128 /**
129 * @see FileBrowser::selectionBar
130 * This control already has a predefined SelectionBar, and can be accessed via this alias.
131 * @property MauiKit::SelectionBar FileDialog::selectionBar
132 */
133 readonly property alias selectionBar: _selectionBar
135 /**
136 * @brief If true then only one item can be selected, either for saving or for opening.
137 * @property bool FileDialog::singleSelection
138 */
139 property alias singleSelection : _selectionBar.singleSelection
140
141 /**
142 * @brief On save mode a text field is visible and this property is used to assign its default text value.
143 * By default this is set to empty string
144 */
145 property string suggestedFileName : ""
146
147 /**
148 * @brief Show the search bar to enter a search query.
149 */
150 property bool searchBar : false
151 onSearchBarChanged: if(!searchBar) _browser.quitSearch()
152
153 /**
154 * @brief The two different modes to use with this dialog.
155 */
156 enum Modes
157 {
158 /**
159 * To use this dialog for selecting one or multiple entries for opening.
160 */
161 Open,
162
163 /**
164 * To use this dialog to select a single directory where to save a file entry with a given name.
165 */
166 Save
168
169 /**
170 * @brief The current mode in use.
171 * By default this is set to `FileDialog.Modes.Open`
172 * @see Modes
173 */
174 property int mode : FileDialog.Modes.Open
175
176 /**
177 * @brief A callback function that will be invoked once the user is done selecting the files.
178 * This is useful when the file dialog is going to be used for multiple purposes.
179 * Otherwise you might want to use the `urlsSelected` signal.
180 * @see urlsSelected
181 */
182 property var callback
183
184 /**
185 * @brief On Save mode a text field is visible, this property gives access to it.
186 */
187 readonly property alias textField: _textField
188
189 /**
190 * @brief Emitted once the URLs have been selected.
191 * @param urls the selected list of URLs
192 */
193 signal urlsSelected(var urls)
194
195 /**
196 * @brief Emitted once the selection has been done.
197 * @param urls the selected list of URLs
198 */
199 signal finished(var urls)
200
201 actions:
202 [
203 Action
204 {
205 text: i18nd("mauikitfilebrowsing", "Cancel")
206 onTriggered: control.close()
207 },
208
209 Action
210 {
211 text: control.mode === FileDialog.Modes.Save ? i18nd("mauikitfilebrowsing", "Save") : i18nd("mauikitfilebrowsing", "Open")
212 onTriggered:
213 {
214 console.log("CURRENT PATHb", _browser.currentPath+"/"+textField.text)
215 if(control.mode === FileDialog.Modes.Save && textField.text.length === 0)
216 return
217
218 if(control.mode === FileDialog.Modes.Save && FB.FM.fileExists(_browser.currentPath+"/"+textField.text))
219 {
220 _confirmationDialog.open()
221 }else
222 {
223 done()
224 }
225 }
226 }
227 ]
228
229 page.footerColumn: [
230
231 Maui.ToolBar
232 {
233 visible: control.mode === FileDialog.Modes.Save
234 width: parent.width
235 position: ToolBar.Footer
236
237 middleContent: TextField
238 {
239 id: _textField
240 Layout.fillWidth: true
241 placeholderText: i18nd("mauikitfilebrowsing", "File name...")
242 text: suggestedFileName
243 }
244 }
245 ]
246
247 Maui.InfoDialog
248 {
249 id: _confirmationDialog
250
251 title: i18nd("mauikitfilebrowsing", "Error")
252 message: i18nd("mauikitfilebrowsing", "A file named '%1' already exists!\n This action will overwrite '%1'. Are you sure you want to do this?", control.textField.text)
253 template.iconSource: "dialog-warning"
254
255 standardButtons: Dialog.Ok | Dialog.Cancel
256
257 onAccepted: control.done()
258 onRejected: close()
259 }
260
261 stack: Maui.SideBarView
262 {
263 id: pageRow
264
265 Layout.fillHeight: true
266 Layout.fillWidth: true
267
268 sideBar.preferredWidth: 200
269 sideBar.minimumWidth: 200
270 sideBarContent: Loader
271 {
272 id: sidebarLoader
273 asynchronous: true
274 anchors.fill: parent
275
276 sourceComponent: FB.PlacesListBrowser
277 {
278 onPlaceClicked: (path) =>
279 {
280 //pageRow.currentIndex = 1
281 _browser.openFolder(path)
282 }
283
284 currentPath: _browser.currentPath
285
286 list.groups: [
287 FB.FMList.BOOKMARKS_PATH,
288 FB.FMList.REMOTE_PATH,
289 FB.FMList.CLOUD_PATH,
290 FB.FMList.DRIVES_PATH]
291 }
292 }
293
294 Maui.Page
295 {
296 id: _browserLayout
297 anchors.fill: parent
298
299 floatingFooter: true
300 flickable: _browser.flickable
301 headBar.visible: true
302 headerColorSet: Maui.Theme.Header
303 headBar.farLeftContent: ToolButton
304 {
305 icon.name: pageRow.sideBar.visible ? "sidebar-collapse" : "sidebar-expand"
306 onClicked: pageRow.sideBar.toggle()
307 checked: pageRow.sideBar.visible
308 ToolTip.delay: 1000
309 ToolTip.timeout: 5000
310 ToolTip.visible: hovered
311 ToolTip.text: i18nd("mauikitfilebrowsing", "Toogle SideBar")
312 }
313
314 headBar.rightContent:[
315
316 ToolButton
317 {
318 id: searchButton
319 icon.name: "edit-find"
320 onClicked: browser.toggleSearchBar()
321 checked: browser.headBar.visible
322 },
323
324 Loader
325 {
326 asynchronous: true
327 sourceComponent: Maui.ToolButtonMenu
328 {
329 icon.name: browser.settings.viewType === FB.FMList.LIST_VIEW ? "view-list-details" : "view-list-icons"
330
331 Maui.MenuItemActionRow
332 {
333 Action
334 {
335 icon.name: "view-hidden"
336 // text: i18nd("mauikitfilebrowsing", "Hidden Files")
337 checkable: true
338 checked: browser.settings.showHiddenFiles
339 onTriggered: browser.settings.showHiddenFiles = !browser.settings.showHiddenFiles
340 }
341
342 Action
343 {
344 icon.name: "folder-new"
345 onTriggered: browser.newItem()
346 }
347 }
348
349 Maui.LabelDelegate
350 {
351 width: parent.width
352 isSection: true
353 text: i18nd("mauikitfilebrowsing", "View type")
354 }
355
356 Action
357 {
358 text: i18nd("mauikitfilebrowsing", "List")
359 icon.name: "view-list-details"
360 checked: browser.settings.viewType === FB.FMList.LIST_VIEW
361 checkable: true
362 onTriggered:
363 {
364 if(browser)
365 {
366 browser.settings.viewType = FB.FMList.LIST_VIEW
367 }
368 }
369 }
370
371 Action
372 {
373 text: i18nd("mauikitfilebrowsing", "Grid")
374 icon.name: "view-list-icons"
375 checked: browser.settings.viewType === FB.FMList.ICON_VIEW
376 checkable: true
377
378 onTriggered:
379 {
380 if(browser)
381 {
382 browser.settings.viewType = FB.FMList.ICON_VIEW
383 }
384 }
385 }
386
387 MenuSeparator {}
388
389 Maui.LabelDelegate
390 {
391 width: parent.width
392 isSection: true
393 text: i18nd("mauikitfilebrowsing", "Sort by")
394 }
395
396 Action
397 {
398 text: i18nd("mauikitfilebrowsing", "Type")
399 checked: browser.settings.sortBy === FB.FMList.MIME
400 checkable: true
401
402 onTriggered:
403 {
404 browser.settings.sortBy = FB.FMList.MIME
405 }
406 }
407
408 Action
409 {
410 text: i18nd("mauikitfilebrowsing", "Date")
411 checked: browser.settings.sortBy === FB.FMList.DATE
412 checkable: true
413
414 onTriggered:
415 {
416 browser.settings.sortBy = FB.FMList.DATE
417 }
418 }
419
420 Action
421 {
422 text: i18nd("mauikitfilebrowsing", "Modified")
423 checked: browser.settings.sortBy === FB.FMList.MODIFIED
424 checkable: true
425
426 onTriggered:
427 {
428 browser.settings.sortBy = FB.FMList.MODIFIED
429 }
430 }
431
432 Action
433 {
434 text: i18nd("mauikitfilebrowsing", "Size")
435 checked: browser.settings.sortBy === FB.FMList.SIZE
436 checkable: true
437
438 onTriggered:
439 {
440 browser.settings.sortBy = FB.FMList.SIZE
441 }
442 }
443
444 Action
445 {
446 text: i18nd("mauikitfilebrowsing", "Name")
447 checked: browser.settings.sortBy === FB.FMList.LABEL
448 checkable: true
449
450 onTriggered:
451 {
452 browser.settings.sortBy = FB.FMList.LABEL
453 }
454 }
455
456 MenuSeparator{}
457
458 MenuItem
459 {
460 text: i18nd("mauikitfilebrowsing", "Show Folders First")
461 checked: browser.settings.foldersFirst
462 checkable: true
463
464 onTriggered:
465 {
466 browser.settings.foldersFirst = !browser.settings.foldersFirst
467 }
468 }
469
470 MenuItem
471 {
472 id: groupAction
473 text: i18nd("mauikitfilebrowsing", "Group")
474 checkable: true
475 checked: browser.settings.group
476 onTriggered:
477 {
478 browser.settings.group = !browser.settings.group
479 }
480 }
481 }
482 }
483 ]
484
485 headBar.leftContent: Loader
486 {
487 asynchronous: true
488 sourceComponent: Maui.ToolActions
489 {
490 expanded: true
491 autoExclusive: false
492 checkable: false
493
494 Action
495 {
496 icon.name: "go-previous"
497 onTriggered : browser.goBack()
498 }
499
500 Action
501 {
502 icon.name: "go-up"
503 onTriggered : browser.goUp()
504 }
505
506 Action
507 {
508 icon.name: "go-next"
509 onTriggered: browser.goNext()
510 }
511 }
512 }
513
514 footer: Maui.SelectionBar
515 {
516 id: _selectionBar
517
518 anchors.horizontalCenter: parent.horizontalCenter
519 width: Math.min(parent.width-(Maui.Style.space.medium*2), implicitWidth)
520 maxListHeight: control.height - (Maui.Style.contentMargins*2)
521
522 listDelegate: Maui.ListBrowserDelegate
523 {
524 width: ListView.view.width
525 iconSource: model.icon
526 imageSource: model.thumbnail
527 label1.text: model.label
528 label2.text: model.url
529 }
530
531 onExitClicked:
532 {
533 _selectionBar.clear()
534 }
535 }
536
537 FB.FileBrowser
538 {
539 id: _browser
540 anchors.fill: parent
541
542 selectionBar: _selectionBar
543 settings.viewType: FB.FMList.LIST_VIEW
544 currentPath: FB.FM.homePath()
545 selectionMode: control.mode === FileDialog.Modes.Open
546 onItemClicked: (index) =>
547 {
548 if(Maui.Handy.singleClick)
549 {
550 performAction(index)
551 }
552 }
553
554 onItemDoubleClicked: (index) =>
555 {
556 if(!Maui.Handy.singleClick)
557 {
558 performAction(index)
559 }
560 }
561
562 function performAction(index)
563 {
564 if(currentFMModel.get(index).isdir == "true")
565 {
566 openItem(index)
567 }
568
569 switch(control.mode)
570 {
571 case FileDialog.Modes.Open :
572 addToSelection(currentFMModel.get(index))
573 break;
574
575 case FileDialog.Modes.Save:
576 textField.text = currentFMModel.get(index).label
577 break;
578 }
579 }
580 }
581 }
582 }
583
584 onClosed:
585 {
586 _selectionBar.clear()
587 }
588
589 /**
590 * @private
591 */
592 function done()
593 {
594 var paths = _browser.selectionBar && _browser.selectionBar.visible ? _browser.selectionBar.uris : [_browser.currentPath]
595
596 if(control.mode === FileDialog.Modes.Save)
597 {
598 for(var i in paths)
599 {
600 paths[i] = paths[i] + "/" + textField.text
601 }
602
603 // _tagsBar.list.urls = paths
604 // _tagsBar.list.updateToUrls(_tagsBar.getTags())
605 }
606
607 control.finished(paths)
608
609 // if(control.mode === modes.SAVE) //do it after finished in cas ethe files need to be saved aka exists, before tryign to insert tags
610 // {
611 // _tagsBar.list.urls = paths
612 // _tagsBar.list.updateToUrls(_tagsBar.getTags())
613 // }
614
615 if(control.callback)
616 {
617 control.callback(paths)
618 }
619
620 control.urlsSelected(paths)
621 control.close()
622 }
623}
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:53:26 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.