1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00
Files
DankMaterialShell/Modals/FileBrowser/FileBrowserModal.qml
Aziz Hasanain 414ce5610d Remove wallpaper engine support in favor of plugin (#601)
* Remove wallpaper engine support in favor of plugin

* i18n: update source strings from codebase

* Add migration notification for WallpaperEngine support

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-11-02 13:44:06 -05:00

933 lines
38 KiB
QML

import Qt.labs.folderlistmodel
import QtCore
import QtQuick
import QtQuick.Controls
import Quickshell.Io
import qs.Common
import qs.Modals.Common
import qs.Modals.FileBrowser
import qs.Widgets
DankModal {
id: fileBrowserModal
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)
property string docsDir: StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
property string musicDir: StandardPaths.writableLocation(StandardPaths.MusicLocation)
property string videosDir: StandardPaths.writableLocation(StandardPaths.MoviesLocation)
property string picsDir: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
property string downloadDir: StandardPaths.writableLocation(StandardPaths.DownloadLocation)
property string desktopDir: StandardPaths.writableLocation(StandardPaths.DesktopLocation)
property string currentPath: ""
property var fileExtensions: ["*.*"]
property alias filterExtensions: fileBrowserModal.fileExtensions
property string browserTitle: "Select File"
property string browserIcon: "folder_open"
property string browserType: "generic"
property bool showHiddenFiles: false
property int selectedIndex: -1
property bool keyboardNavigationActive: false
property bool backButtonFocused: false
property bool saveMode: false
property string defaultFileName: ""
property int keyboardSelectionIndex: -1
property bool keyboardSelectionRequested: false
property bool showKeyboardHints: false
property bool showFileInfo: false
property string selectedFilePath: ""
property string selectedFileName: ""
property bool selectedFileIsDir: false
property bool showOverwriteConfirmation: false
property string pendingFilePath: ""
property var parentModal: null
property bool showSidebar: true
property string viewMode: "grid"
property string sortBy: "name"
property bool sortAscending: true
property int iconSizeIndex: 1
property var iconSizes: [80, 120, 160, 200]
property bool pathEditMode: false
property bool pathInputHasFocus: false
property int actualGridColumns: 5
property bool _initialized: false
signal fileSelected(string path)
function loadSettings() {
const type = browserType || "default"
const settings = CacheData.fileBrowserSettings[type]
const isImageBrowser = ["wallpaper", "profile"].includes(browserType)
if (settings) {
viewMode = settings.viewMode || (isImageBrowser ? "grid" : "list")
sortBy = settings.sortBy || "name"
sortAscending = settings.sortAscending !== undefined ? settings.sortAscending : true
iconSizeIndex = settings.iconSizeIndex !== undefined ? settings.iconSizeIndex : 1
showSidebar = settings.showSidebar !== undefined ? settings.showSidebar : true
} else {
viewMode = isImageBrowser ? "grid" : "list"
}
}
function saveSettings() {
if (!_initialized)
return
const type = browserType || "default"
let settings = CacheData.fileBrowserSettings
if (!settings[type]) {
settings[type] = {}
}
settings[type].viewMode = viewMode
settings[type].sortBy = sortBy
settings[type].sortAscending = sortAscending
settings[type].iconSizeIndex = iconSizeIndex
settings[type].showSidebar = showSidebar
settings[type].lastPath = currentPath
CacheData.fileBrowserSettings = settings
if (browserType === "wallpaper") {
CacheData.wallpaperLastPath = currentPath
} else if (browserType === "profile") {
CacheData.profileLastPath = currentPath
}
CacheData.saveCache()
}
onViewModeChanged: saveSettings()
onSortByChanged: saveSettings()
onSortAscendingChanged: saveSettings()
onIconSizeIndexChanged: saveSettings()
onShowSidebarChanged: saveSettings()
function isImageFile(fileName) {
if (!fileName) {
return false
}
const ext = fileName.toLowerCase().split('.').pop()
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
}
function getLastPath() {
const type = browserType || "default"
const settings = CacheData.fileBrowserSettings[type]
const lastPath = settings?.lastPath || ""
return (lastPath && lastPath !== "") ? lastPath : homeDir
}
function saveLastPath(path) {
const type = browserType || "default"
let settings = CacheData.fileBrowserSettings
if (!settings[type]) {
settings[type] = {}
}
settings[type].lastPath = path
CacheData.fileBrowserSettings = settings
CacheData.saveCache()
if (browserType === "wallpaper") {
CacheData.wallpaperLastPath = path
} else if (browserType === "profile") {
CacheData.profileLastPath = path
}
}
function setSelectedFileData(path, name, isDir) {
selectedFilePath = path
selectedFileName = name
selectedFileIsDir = isDir
}
function navigateUp() {
const path = currentPath
if (path === homeDir)
return
const lastSlash = path.lastIndexOf('/')
if (lastSlash > 0) {
const newPath = path.substring(0, lastSlash)
if (newPath.length < homeDir.length) {
currentPath = homeDir
saveLastPath(homeDir)
} else {
currentPath = newPath
saveLastPath(newPath)
}
}
}
function navigateTo(path) {
currentPath = path
saveLastPath(path)
selectedIndex = -1
backButtonFocused = false
}
function keyboardFileSelection(index) {
if (index >= 0) {
keyboardSelectionTimer.targetIndex = index
keyboardSelectionTimer.start()
}
}
function executeKeyboardSelection(index) {
keyboardSelectionIndex = index
keyboardSelectionRequested = true
}
function handleSaveFile(filePath) {
var normalizedPath = filePath
if (!normalizedPath.startsWith("file://")) {
normalizedPath = "file://" + filePath
}
var exists = false
var fileName = filePath.split('/').pop()
for (var i = 0; i < folderModel.count; i++) {
if (folderModel.get(i, "fileName") === fileName && !folderModel.get(i, "fileIsDir")) {
exists = true
break
}
}
if (exists) {
pendingFilePath = normalizedPath
showOverwriteConfirmation = true
} else {
fileSelected(normalizedPath)
fileBrowserModal.close()
}
}
objectName: "fileBrowserModal"
allowStacking: true
closeOnEscapeKey: false
shouldHaveFocus: shouldBeVisible
Component.onCompleted: {
loadSettings()
currentPath = getLastPath()
_initialized = true
}
property var steamPaths: [StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/.steam/steam/steamapps/workshop/content/431960", StandardPaths.writableLocation(
StandardPaths.HomeLocation) + "/.local/share/Steam/steamapps/workshop/content/431960", StandardPaths.writableLocation(
StandardPaths.HomeLocation) + "/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/workshop/content/431960", StandardPaths.writableLocation(
StandardPaths.HomeLocation) + "/snap/steam/common/.local/share/Steam/steamapps/workshop/content/431960"]
property int currentPathIndex: 0
width: 800
height: 600
enableShadow: true
visible: false
onBackgroundClicked: close()
onOpened: {
if (parentModal) {
parentModal.shouldHaveFocus = false
parentModal.allowFocusOverride = true
}
Qt.callLater(() => {
if (contentLoader && contentLoader.item) {
contentLoader.item.forceActiveFocus()
}
})
}
onDialogClosed: {
if (parentModal) {
parentModal.allowFocusOverride = false
parentModal.shouldHaveFocus = Qt.binding(() => {
return parentModal.shouldBeVisible
})
}
}
onVisibleChanged: {
if (visible) {
currentPath = getLastPath()
selectedIndex = -1
keyboardNavigationActive = false
backButtonFocused = false
}
}
onCurrentPathChanged: {
selectedFilePath = ""
selectedFileName = ""
selectedFileIsDir = false
saveSettings()
}
onSelectedIndexChanged: {
if (selectedIndex >= 0 && folderModel && selectedIndex < folderModel.count) {
selectedFilePath = ""
selectedFileName = ""
selectedFileIsDir = false
}
}
FolderListModel {
id: folderModel
showDirsFirst: true
showDotAndDotDot: false
showHidden: fileBrowserModal.showHiddenFiles
nameFilters: fileExtensions
showFiles: true
showDirs: true
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
sortField: {
switch (sortBy) {
case "name":
return FolderListModel.Name
case "size":
return FolderListModel.Size
case "modified":
return FolderListModel.Time
case "type":
return FolderListModel.Type
default:
return FolderListModel.Name
}
}
sortReversed: !sortAscending
}
property var quickAccessLocations: [{
"name": "Home",
"path": homeDir,
"icon": "home"
}, {
"name": "Documents",
"path": docsDir,
"icon": "description"
}, {
"name": "Downloads",
"path": downloadDir,
"icon": "download"
}, {
"name": "Pictures",
"path": picsDir,
"icon": "image"
}, {
"name": "Music",
"path": musicDir,
"icon": "music_note"
}, {
"name": "Videos",
"path": videosDir,
"icon": "movie"
}, {
"name": "Desktop",
"path": desktopDir,
"icon": "computer"
}]
QtObject {
id: keyboardController
property int totalItems: folderModel.count
property int gridColumns: viewMode === "list" ? 1 : Math.max(1, actualGridColumns)
function handleKey(event) {
if (event.key === Qt.Key_Escape) {
close()
event.accepted = true
return
}
if (event.key === Qt.Key_F10) {
showKeyboardHints = !showKeyboardHints
event.accepted = true
return
}
if (event.key === Qt.Key_F1 || event.key === Qt.Key_I) {
showFileInfo = !showFileInfo
event.accepted = true
return
}
if ((event.modifiers & Qt.AltModifier && event.key === Qt.Key_Left) || event.key === Qt.Key_Backspace) {
if (currentPath !== homeDir) {
navigateUp()
event.accepted = true
}
return
}
if (!keyboardNavigationActive) {
const isInitKey = event.key === Qt.Key_Tab || event.key === Qt.Key_Down || event.key
=== Qt.Key_Right || (event.key === Qt.Key_N && event.modifiers & Qt.ControlModifier) || (event.key === Qt.Key_J && event.modifiers & Qt.ControlModifier) || (event.key === Qt.Key_L && event.modifiers & Qt.ControlModifier)
if (isInitKey) {
keyboardNavigationActive = true
if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
} else {
backButtonFocused = false
selectedIndex = 0
}
event.accepted = true
}
return
}
switch (event.key) {
case Qt.Key_Tab:
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else if (selectedIndex < totalItems - 1) {
selectedIndex++
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
} else {
selectedIndex = 0
}
event.accepted = true
break
case Qt.Key_Backtab:
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = totalItems - 1
} else if (selectedIndex > 0) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
} else {
selectedIndex = totalItems - 1
}
event.accepted = true
break
case Qt.Key_N:
if (event.modifiers & Qt.ControlModifier) {
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else if (selectedIndex < totalItems - 1) {
selectedIndex++
}
event.accepted = true
}
break
case Qt.Key_P:
if (event.modifiers & Qt.ControlModifier) {
if (selectedIndex > 0) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
}
break
case Qt.Key_J:
if (event.modifiers & Qt.ControlModifier) {
if (selectedIndex < totalItems - 1) {
selectedIndex++
}
event.accepted = true
}
break
case Qt.Key_K:
if (event.modifiers & Qt.ControlModifier) {
if (selectedIndex > 0) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
}
break
case Qt.Key_H:
if (event.modifiers & Qt.ControlModifier) {
if (!backButtonFocused && selectedIndex > 0) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
}
break
case Qt.Key_L:
if (event.modifiers & Qt.ControlModifier) {
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else if (selectedIndex < totalItems - 1) {
selectedIndex++
}
event.accepted = true
}
break
case Qt.Key_Left:
if (pathInputHasFocus)
return
if (backButtonFocused)
return
if (selectedIndex > 0) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
break
case Qt.Key_Right:
if (pathInputHasFocus)
return
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else if (selectedIndex < totalItems - 1) {
selectedIndex++
}
event.accepted = true
break
case Qt.Key_Up:
if (backButtonFocused) {
backButtonFocused = false
if (gridColumns === 1) {
selectedIndex = 0
} else {
var col = selectedIndex % gridColumns
selectedIndex = Math.min(col, totalItems - 1)
}
} else if (selectedIndex >= gridColumns) {
selectedIndex -= gridColumns
} else if (selectedIndex > 0 && gridColumns === 1) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
break
case Qt.Key_Down:
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else if (gridColumns === 1) {
if (selectedIndex < totalItems - 1) {
selectedIndex++
}
} else {
var newIndex = selectedIndex + gridColumns
if (newIndex < totalItems) {
selectedIndex = newIndex
} else {
var lastRowStart = Math.floor((totalItems - 1) / gridColumns) * gridColumns
var col = selectedIndex % gridColumns
var targetIndex = lastRowStart + col
if (targetIndex < totalItems && targetIndex > selectedIndex) {
selectedIndex = targetIndex
}
}
}
event.accepted = true
break
case Qt.Key_Return:
case Qt.Key_Enter:
case Qt.Key_Space:
if (backButtonFocused)
navigateUp()
else if (selectedIndex >= 0 && selectedIndex < totalItems)
fileBrowserModal.keyboardFileSelection(selectedIndex)
event.accepted = true
break
}
}
}
Timer {
id: keyboardSelectionTimer
property int targetIndex: -1
interval: 1
onTriggered: {
executeKeyboardSelection(targetIndex)
}
}
content: Component {
Item {
anchors.fill: parent
Keys.onPressed: event => {
keyboardController.handleKey(event)
}
onVisibleChanged: {
if (visible) {
forceActiveFocus()
}
}
Column {
anchors.fill: parent
spacing: 0
Item {
width: parent.width
height: 48
Row {
spacing: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Theme.spacingL
DankIcon {
name: browserIcon
size: Theme.iconSizeLarge
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: browserTitle
font.pixelSize: Theme.fontSizeXLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankActionButton {
circular: false
iconName: showHiddenFiles ? "visibility_off" : "visibility"
iconSize: Theme.iconSize - 4
iconColor: showHiddenFiles ? Theme.primary : Theme.surfaceText
onClicked: showHiddenFiles = !showHiddenFiles
}
DankActionButton {
circular: false
iconName: viewMode === "grid" ? "view_list" : "grid_view"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: viewMode = viewMode === "grid" ? "list" : "grid"
}
DankActionButton {
circular: false
iconName: iconSizeIndex === 0 ? "photo_size_select_small" : iconSizeIndex === 1 ? "photo_size_select_large" : iconSizeIndex === 2 ? "photo_size_select_actual" : "zoom_in"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
visible: viewMode === "grid"
onClicked: iconSizeIndex = (iconSizeIndex + 1) % iconSizes.length
}
DankActionButton {
circular: false
iconName: "info"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: fileBrowserModal.showKeyboardHints = !fileBrowserModal.showKeyboardHints
}
DankActionButton {
circular: false
iconName: "close"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: fileBrowserModal.close()
}
}
}
StyledRect {
width: parent.width
height: 1
color: Theme.outline
}
Item {
width: parent.width
height: parent.height - 49
Row {
anchors.fill: parent
spacing: 0
Row {
width: showSidebar ? 201 : 0
height: parent.height
spacing: 0
visible: showSidebar
FileBrowserSidebar {
height: parent.height
quickAccessLocations: fileBrowserModal.quickAccessLocations
currentPath: fileBrowserModal.currentPath
onLocationSelected: path => navigateTo(path)
}
StyledRect {
width: 1
height: parent.height
color: Theme.outline
}
}
Column {
width: parent.width - (showSidebar ? 201 : 0)
height: parent.height
spacing: 0
FileBrowserNavigation {
width: parent.width
currentPath: fileBrowserModal.currentPath
homeDir: fileBrowserModal.homeDir
backButtonFocused: fileBrowserModal.backButtonFocused
keyboardNavigationActive: fileBrowserModal.keyboardNavigationActive
showSidebar: fileBrowserModal.showSidebar
pathEditMode: fileBrowserModal.pathEditMode
onNavigateUp: fileBrowserModal.navigateUp()
onNavigateTo: path => fileBrowserModal.navigateTo(path)
onPathInputFocusChanged: hasFocus => {
fileBrowserModal.pathInputHasFocus = hasFocus
if (hasFocus) {
fileBrowserModal.pathEditMode = true
}
}
}
StyledRect {
width: parent.width
height: 1
color: Theme.outline
}
Item {
id: gridContainer
width: parent.width
height: parent.height - 41
clip: true
property real gridCellWidth: iconSizes[iconSizeIndex] + 24
property real gridCellHeight: iconSizes[iconSizeIndex] + 56
property real availableGridWidth: width - Theme.spacingM * 2
property int gridColumns: Math.max(1, Math.floor(availableGridWidth / gridCellWidth))
property real gridLeftMargin: Theme.spacingM + Math.max(0, (availableGridWidth - (gridColumns * gridCellWidth)) / 2)
onGridColumnsChanged: {
fileBrowserModal.actualGridColumns = gridColumns
}
Component.onCompleted: {
fileBrowserModal.actualGridColumns = gridColumns
}
DankGridView {
id: fileGrid
anchors.fill: parent
anchors.leftMargin: gridContainer.gridLeftMargin
anchors.rightMargin: Theme.spacingM
anchors.topMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
visible: viewMode === "grid"
cellWidth: gridContainer.gridCellWidth
cellHeight: gridContainer.gridCellHeight
cacheBuffer: 260
model: folderModel
currentIndex: selectedIndex
onCurrentIndexChanged: {
if (keyboardNavigationActive && currentIndex >= 0)
positionViewAtIndex(currentIndex, GridView.Contain)
}
ScrollBar.vertical: DankScrollbar {
id: gridScrollbar
}
ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff
}
delegate: FileBrowserGridDelegate {
iconSizes: fileBrowserModal.iconSizes
iconSizeIndex: fileBrowserModal.iconSizeIndex
selectedIndex: fileBrowserModal.selectedIndex
keyboardNavigationActive: fileBrowserModal.keyboardNavigationActive
onItemClicked: (index, path, name, isDir) => {
selectedIndex = index
setSelectedFileData(path, name, isDir)
if (isDir) {
navigateTo(path)
} else {
fileSelected(path)
fileBrowserModal.close()
}
}
onItemSelected: (index, path, name, isDir) => {
setSelectedFileData(path, name, isDir)
}
Connections {
function onKeyboardSelectionRequestedChanged() {
if (fileBrowserModal.keyboardSelectionRequested && fileBrowserModal.keyboardSelectionIndex === index) {
fileBrowserModal.keyboardSelectionRequested = false
selectedIndex = index
setSelectedFileData(filePath, fileName, fileIsDir)
if (fileIsDir) {
navigateTo(filePath)
} else {
fileSelected(filePath)
fileBrowserModal.close()
}
}
}
target: fileBrowserModal
}
}
}
DankListView {
id: fileList
anchors.fill: parent
anchors.leftMargin: Theme.spacingM
anchors.rightMargin: Theme.spacingM
anchors.topMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
visible: viewMode === "list"
spacing: 2
model: folderModel
currentIndex: selectedIndex
onCurrentIndexChanged: {
if (keyboardNavigationActive && currentIndex >= 0)
positionViewAtIndex(currentIndex, ListView.Contain)
}
ScrollBar.vertical: DankScrollbar {
id: listScrollbar
}
delegate: FileBrowserListDelegate {
width: fileList.width
selectedIndex: fileBrowserModal.selectedIndex
keyboardNavigationActive: fileBrowserModal.keyboardNavigationActive
onItemClicked: (index, path, name, isDir) => {
selectedIndex = index
setSelectedFileData(path, name, isDir)
if (isDir) {
navigateTo(path)
} else {
fileSelected(path)
fileBrowserModal.close()
}
}
onItemSelected: (index, path, name, isDir) => {
setSelectedFileData(path, name, isDir)
}
Connections {
function onKeyboardSelectionRequestedChanged() {
if (fileBrowserModal.keyboardSelectionRequested && fileBrowserModal.keyboardSelectionIndex === index) {
fileBrowserModal.keyboardSelectionRequested = false
selectedIndex = index
setSelectedFileData(filePath, fileName, fileIsDir)
if (fileIsDir) {
navigateTo(filePath)
} else {
fileSelected(filePath)
fileBrowserModal.close()
}
}
}
target: fileBrowserModal
}
}
}
}
}
}
FileBrowserSaveRow {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Theme.spacingL
saveMode: fileBrowserModal.saveMode
defaultFileName: fileBrowserModal.defaultFileName
currentPath: fileBrowserModal.currentPath
onSaveRequested: filePath => handleSaveFile(filePath)
}
KeyboardHints {
id: keyboardHints
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Theme.spacingL
showHints: fileBrowserModal.showKeyboardHints
}
FileInfo {
id: fileInfo
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Theme.spacingL
width: 300
showFileInfo: fileBrowserModal.showFileInfo
selectedIndex: fileBrowserModal.selectedIndex
sourceFolderModel: folderModel
currentPath: fileBrowserModal.currentPath
currentFileName: fileBrowserModal.selectedFileName
currentFileIsDir: fileBrowserModal.selectedFileIsDir
currentFileExtension: {
if (fileBrowserModal.selectedFileIsDir || !fileBrowserModal.selectedFileName)
return ""
var lastDot = fileBrowserModal.selectedFileName.lastIndexOf('.')
return lastDot > 0 ? fileBrowserModal.selectedFileName.substring(lastDot + 1).toLowerCase() : ""
}
}
FileBrowserSortMenu {
id: sortMenu
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: 120
anchors.rightMargin: Theme.spacingL
sortBy: fileBrowserModal.sortBy
sortAscending: fileBrowserModal.sortAscending
onSortBySelected: value => {
fileBrowserModal.sortBy = value
}
onSortOrderSelected: ascending => {
fileBrowserModal.sortAscending = ascending
}
}
}
}
FileBrowserOverwriteDialog {
anchors.fill: parent
showDialog: showOverwriteConfirmation
pendingFilePath: fileBrowserModal.pendingFilePath
onConfirmed: filePath => {
showOverwriteConfirmation = false
fileSelected(filePath)
pendingFilePath = ""
Qt.callLater(() => fileBrowserModal.close())
}
onCancelled: {
showOverwriteConfirmation = false
pendingFilePath = ""
}
}
}
}
}