mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-08 06:25:37 -05:00
filebrowser: improved file browser
This commit is contained in:
@@ -22,6 +22,57 @@ Singleton {
|
|||||||
property string wallpaperLastPath: ""
|
property string wallpaperLastPath: ""
|
||||||
property string profileLastPath: ""
|
property string profileLastPath: ""
|
||||||
|
|
||||||
|
property var fileBrowserSettings: ({
|
||||||
|
"wallpaper": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "grid",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "grid",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
},
|
||||||
|
"notepad_save": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "list",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
},
|
||||||
|
"notepad_load": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "list",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
},
|
||||||
|
"generic": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "list",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "list",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!isGreeterMode) {
|
if (!isGreeterMode) {
|
||||||
loadCache()
|
loadCache()
|
||||||
@@ -43,6 +94,37 @@ Singleton {
|
|||||||
wallpaperLastPath = cache.wallpaperLastPath !== undefined ? cache.wallpaperLastPath : ""
|
wallpaperLastPath = cache.wallpaperLastPath !== undefined ? cache.wallpaperLastPath : ""
|
||||||
profileLastPath = cache.profileLastPath !== undefined ? cache.profileLastPath : ""
|
profileLastPath = cache.profileLastPath !== undefined ? cache.profileLastPath : ""
|
||||||
|
|
||||||
|
if (cache.fileBrowserSettings !== undefined) {
|
||||||
|
fileBrowserSettings = cache.fileBrowserSettings
|
||||||
|
} else if (cache.fileBrowserViewMode !== undefined) {
|
||||||
|
fileBrowserSettings = {
|
||||||
|
"wallpaper": {
|
||||||
|
"lastPath": cache.wallpaperLastPath || "",
|
||||||
|
"viewMode": cache.fileBrowserViewMode || "grid",
|
||||||
|
"sortBy": cache.fileBrowserSortBy || "name",
|
||||||
|
"sortAscending": cache.fileBrowserSortAscending !== undefined ? cache.fileBrowserSortAscending : true,
|
||||||
|
"iconSizeIndex": cache.fileBrowserIconSizeIndex !== undefined ? cache.fileBrowserIconSizeIndex : 1,
|
||||||
|
"showSidebar": cache.fileBrowserShowSidebar !== undefined ? cache.fileBrowserShowSidebar : true
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"lastPath": cache.profileLastPath || "",
|
||||||
|
"viewMode": cache.fileBrowserViewMode || "grid",
|
||||||
|
"sortBy": cache.fileBrowserSortBy || "name",
|
||||||
|
"sortAscending": cache.fileBrowserSortAscending !== undefined ? cache.fileBrowserSortAscending : true,
|
||||||
|
"iconSizeIndex": cache.fileBrowserIconSizeIndex !== undefined ? cache.fileBrowserIconSizeIndex : 1,
|
||||||
|
"showSidebar": cache.fileBrowserShowSidebar !== undefined ? cache.fileBrowserShowSidebar : true
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"lastPath": "",
|
||||||
|
"viewMode": "list",
|
||||||
|
"sortBy": "name",
|
||||||
|
"sortAscending": true,
|
||||||
|
"iconSizeIndex": 1,
|
||||||
|
"showSidebar": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cache.configVersion === undefined) {
|
if (cache.configVersion === undefined) {
|
||||||
migrateFromUndefinedToV1(cache)
|
migrateFromUndefinedToV1(cache)
|
||||||
cleanupUnusedKeys()
|
cleanupUnusedKeys()
|
||||||
@@ -62,6 +144,7 @@ Singleton {
|
|||||||
cacheFile.setText(JSON.stringify({
|
cacheFile.setText(JSON.stringify({
|
||||||
"wallpaperLastPath": wallpaperLastPath,
|
"wallpaperLastPath": wallpaperLastPath,
|
||||||
"profileLastPath": profileLastPath,
|
"profileLastPath": profileLastPath,
|
||||||
|
"fileBrowserSettings": fileBrowserSettings,
|
||||||
"configVersion": cacheConfigVersion
|
"configVersion": cacheConfigVersion
|
||||||
}, null, 2))
|
}, null, 2))
|
||||||
}
|
}
|
||||||
@@ -74,6 +157,7 @@ Singleton {
|
|||||||
const validKeys = [
|
const validKeys = [
|
||||||
"wallpaperLastPath",
|
"wallpaperLastPath",
|
||||||
"profileLastPath",
|
"profileLastPath",
|
||||||
|
"fileBrowserSettings",
|
||||||
"configVersion"
|
"configVersion"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
214
Modals/FileBrowser/FileBrowserGridDelegate.qml
Normal file
214
Modals/FileBrowser/FileBrowserGridDelegate.qml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: delegateRoot
|
||||||
|
|
||||||
|
required property bool fileIsDir
|
||||||
|
required property string filePath
|
||||||
|
required property string fileName
|
||||||
|
required property int index
|
||||||
|
|
||||||
|
property bool weMode: false
|
||||||
|
property var iconSizes: [80, 120, 160, 200]
|
||||||
|
property int iconSizeIndex: 1
|
||||||
|
property int selectedIndex: -1
|
||||||
|
property bool keyboardNavigationActive: false
|
||||||
|
|
||||||
|
signal itemClicked(int index, string path, string name, bool isDir)
|
||||||
|
signal itemSelected(int index, string path, string name, bool isDir)
|
||||||
|
|
||||||
|
function isImageFile(fileName) {
|
||||||
|
if (!fileName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const ext = fileName.toLowerCase().split('.').pop()
|
||||||
|
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileIcon(fileName, isDir) {
|
||||||
|
if (isDir) {
|
||||||
|
return "folder"
|
||||||
|
}
|
||||||
|
if (!fileName) {
|
||||||
|
return "description"
|
||||||
|
}
|
||||||
|
const ext = fileName.toLowerCase().split('.').pop()
|
||||||
|
const iconMap = {
|
||||||
|
"mp3": 'music_note',
|
||||||
|
"wav": 'music_note',
|
||||||
|
"flac": 'music_note',
|
||||||
|
"ogg": 'music_note',
|
||||||
|
"aac": 'music_note',
|
||||||
|
"mp4": 'movie',
|
||||||
|
"mkv": 'movie',
|
||||||
|
"avi": 'movie',
|
||||||
|
"mov": 'movie',
|
||||||
|
"webm": 'movie',
|
||||||
|
"flv": 'movie',
|
||||||
|
"wmv": 'movie',
|
||||||
|
"jpg": 'image',
|
||||||
|
"jpeg": 'image',
|
||||||
|
"png": 'image',
|
||||||
|
"gif": 'image',
|
||||||
|
"bmp": 'image',
|
||||||
|
"webp": 'image',
|
||||||
|
"svg": 'image',
|
||||||
|
"pdf": 'picture_as_pdf',
|
||||||
|
"zip": 'folder_zip',
|
||||||
|
"rar": 'folder_zip',
|
||||||
|
"7z": 'folder_zip',
|
||||||
|
"tar": 'folder_zip',
|
||||||
|
"gz": 'folder_zip',
|
||||||
|
"bz2": 'folder_zip',
|
||||||
|
"xz": 'folder_zip',
|
||||||
|
"txt": 'description',
|
||||||
|
"md": 'description',
|
||||||
|
"doc": 'description',
|
||||||
|
"docx": 'description',
|
||||||
|
"odt": 'description',
|
||||||
|
"rtf": 'description',
|
||||||
|
"sh": 'terminal',
|
||||||
|
"py": 'code',
|
||||||
|
"js": 'code',
|
||||||
|
"ts": 'code',
|
||||||
|
"cpp": 'code',
|
||||||
|
"c": 'code',
|
||||||
|
"h": 'code',
|
||||||
|
"java": 'code',
|
||||||
|
"go": 'code',
|
||||||
|
"rs": 'code',
|
||||||
|
"php": 'code',
|
||||||
|
"rb": 'code',
|
||||||
|
"qml": 'code',
|
||||||
|
"html": 'code',
|
||||||
|
"css": 'code',
|
||||||
|
"json": 'data_object',
|
||||||
|
"xml": 'data_object',
|
||||||
|
"yaml": 'data_object',
|
||||||
|
"yml": 'data_object',
|
||||||
|
"toml": 'data_object'
|
||||||
|
}
|
||||||
|
return iconMap[ext] || 'description'
|
||||||
|
}
|
||||||
|
|
||||||
|
width: weMode ? 245 : iconSizes[iconSizeIndex] + 16
|
||||||
|
height: weMode ? 205 : iconSizes[iconSizeIndex] + 48
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: {
|
||||||
|
if (keyboardNavigationActive && delegateRoot.index === selectedIndex)
|
||||||
|
return Theme.surfacePressed
|
||||||
|
|
||||||
|
return mouseArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
|
||||||
|
}
|
||||||
|
border.color: keyboardNavigationActive && delegateRoot.index === selectedIndex ? Theme.primary : "transparent"
|
||||||
|
border.width: (keyboardNavigationActive && delegateRoot.index === selectedIndex) ? 2 : 0
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (keyboardNavigationActive && delegateRoot.index === selectedIndex)
|
||||||
|
itemSelected(delegateRoot.index, delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectedIndexChanged: {
|
||||||
|
if (keyboardNavigationActive && selectedIndex === delegateRoot.index)
|
||||||
|
itemSelected(delegateRoot.index, delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: weMode ? 225 : (iconSizes[iconSizeIndex] - 8)
|
||||||
|
height: weMode ? 165 : (iconSizes[iconSizeIndex] - 8)
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
CachingImage {
|
||||||
|
id: gridPreviewImage
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 2
|
||||||
|
property var weExtensions: [".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp", ".tga"]
|
||||||
|
property int weExtIndex: 0
|
||||||
|
source: {
|
||||||
|
if (weMode && delegateRoot.fileIsDir) {
|
||||||
|
return "file://" + delegateRoot.filePath + "/preview" + weExtensions[weExtIndex]
|
||||||
|
}
|
||||||
|
return (!delegateRoot.fileIsDir && isImageFile(delegateRoot.fileName)) ? ("file://" + delegateRoot.filePath) : ""
|
||||||
|
}
|
||||||
|
onStatusChanged: {
|
||||||
|
if (weMode && delegateRoot.fileIsDir && status === Image.Error) {
|
||||||
|
if (weExtIndex < weExtensions.length - 1) {
|
||||||
|
weExtIndex++
|
||||||
|
source = "file://" + delegateRoot.filePath + "/preview" + weExtensions[weExtIndex]
|
||||||
|
} else {
|
||||||
|
source = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
maxCacheSize: weMode ? 225 : iconSizes[iconSizeIndex]
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiEffect {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 2
|
||||||
|
source: gridPreviewImage
|
||||||
|
maskEnabled: true
|
||||||
|
maskSource: gridImageMask
|
||||||
|
visible: gridPreviewImage.status === Image.Ready && ((!delegateRoot.fileIsDir && isImageFile(delegateRoot.fileName)) || (weMode && delegateRoot.fileIsDir))
|
||||||
|
maskThresholdMin: 0.5
|
||||||
|
maskSpreadAtMin: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: gridImageMask
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 2
|
||||||
|
layer.enabled: true
|
||||||
|
layer.smooth: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: "black"
|
||||||
|
antialiasing: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: getFileIcon(delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||||
|
size: iconSizes[iconSizeIndex] * 0.45
|
||||||
|
color: delegateRoot.fileIsDir ? Theme.primary : Theme.surfaceText
|
||||||
|
visible: (!delegateRoot.fileIsDir && !isImageFile(delegateRoot.fileName)) || (delegateRoot.fileIsDir && !weMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: delegateRoot.fileName || ""
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
width: delegateRoot.width - Theme.spacingM
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
maximumLineCount: 2
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
itemClicked(delegateRoot.index, delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
219
Modals/FileBrowser/FileBrowserListDelegate.qml
Normal file
219
Modals/FileBrowser/FileBrowserListDelegate.qml
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: listDelegateRoot
|
||||||
|
|
||||||
|
required property bool fileIsDir
|
||||||
|
required property string filePath
|
||||||
|
required property string fileName
|
||||||
|
required property int index
|
||||||
|
required property var fileModified
|
||||||
|
required property int fileSize
|
||||||
|
|
||||||
|
property int selectedIndex: -1
|
||||||
|
property bool keyboardNavigationActive: false
|
||||||
|
|
||||||
|
signal itemClicked(int index, string path, string name, bool isDir)
|
||||||
|
signal itemSelected(int index, string path, string name, bool isDir)
|
||||||
|
|
||||||
|
function isImageFile(fileName) {
|
||||||
|
if (!fileName) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const ext = fileName.toLowerCase().split('.').pop()
|
||||||
|
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileIcon(fileName, isDir) {
|
||||||
|
if (isDir) {
|
||||||
|
return "folder"
|
||||||
|
}
|
||||||
|
if (!fileName) {
|
||||||
|
return "description"
|
||||||
|
}
|
||||||
|
const ext = fileName.toLowerCase().split('.').pop()
|
||||||
|
const iconMap = {
|
||||||
|
"mp3": 'music_note',
|
||||||
|
"wav": 'music_note',
|
||||||
|
"flac": 'music_note',
|
||||||
|
"ogg": 'music_note',
|
||||||
|
"aac": 'music_note',
|
||||||
|
"mp4": 'movie',
|
||||||
|
"mkv": 'movie',
|
||||||
|
"avi": 'movie',
|
||||||
|
"mov": 'movie',
|
||||||
|
"webm": 'movie',
|
||||||
|
"flv": 'movie',
|
||||||
|
"wmv": 'movie',
|
||||||
|
"jpg": 'image',
|
||||||
|
"jpeg": 'image',
|
||||||
|
"png": 'image',
|
||||||
|
"gif": 'image',
|
||||||
|
"bmp": 'image',
|
||||||
|
"webp": 'image',
|
||||||
|
"svg": 'image',
|
||||||
|
"pdf": 'picture_as_pdf',
|
||||||
|
"zip": 'folder_zip',
|
||||||
|
"rar": 'folder_zip',
|
||||||
|
"7z": 'folder_zip',
|
||||||
|
"tar": 'folder_zip',
|
||||||
|
"gz": 'folder_zip',
|
||||||
|
"bz2": 'folder_zip',
|
||||||
|
"xz": 'folder_zip',
|
||||||
|
"txt": 'description',
|
||||||
|
"md": 'description',
|
||||||
|
"doc": 'description',
|
||||||
|
"docx": 'description',
|
||||||
|
"odt": 'description',
|
||||||
|
"rtf": 'description',
|
||||||
|
"sh": 'terminal',
|
||||||
|
"py": 'code',
|
||||||
|
"js": 'code',
|
||||||
|
"ts": 'code',
|
||||||
|
"cpp": 'code',
|
||||||
|
"c": 'code',
|
||||||
|
"h": 'code',
|
||||||
|
"java": 'code',
|
||||||
|
"go": 'code',
|
||||||
|
"rs": 'code',
|
||||||
|
"php": 'code',
|
||||||
|
"rb": 'code',
|
||||||
|
"qml": 'code',
|
||||||
|
"html": 'code',
|
||||||
|
"css": 'code',
|
||||||
|
"json": 'data_object',
|
||||||
|
"xml": 'data_object',
|
||||||
|
"yaml": 'data_object',
|
||||||
|
"yml": 'data_object',
|
||||||
|
"toml": 'data_object'
|
||||||
|
}
|
||||||
|
return iconMap[ext] || 'description'
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatFileSize(size) {
|
||||||
|
if (size < 1024)
|
||||||
|
return size + " B"
|
||||||
|
if (size < 1024 * 1024)
|
||||||
|
return (size / 1024).toFixed(1) + " KB"
|
||||||
|
if (size < 1024 * 1024 * 1024)
|
||||||
|
return (size / (1024 * 1024)).toFixed(1) + " MB"
|
||||||
|
return (size / (1024 * 1024 * 1024)).toFixed(1) + " GB"
|
||||||
|
}
|
||||||
|
|
||||||
|
height: 44
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: {
|
||||||
|
if (keyboardNavigationActive && listDelegateRoot.index === selectedIndex)
|
||||||
|
return Theme.surfacePressed
|
||||||
|
return listMouseArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
|
||||||
|
}
|
||||||
|
border.color: keyboardNavigationActive && listDelegateRoot.index === selectedIndex ? Theme.primary : "transparent"
|
||||||
|
border.width: (keyboardNavigationActive && listDelegateRoot.index === selectedIndex) ? 2 : 0
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (keyboardNavigationActive && listDelegateRoot.index === selectedIndex)
|
||||||
|
itemSelected(listDelegateRoot.index, listDelegateRoot.filePath, listDelegateRoot.fileName, listDelegateRoot.fileIsDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectedIndexChanged: {
|
||||||
|
if (keyboardNavigationActive && selectedIndex === listDelegateRoot.index)
|
||||||
|
itemSelected(listDelegateRoot.index, listDelegateRoot.filePath, listDelegateRoot.fileName, listDelegateRoot.fileIsDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: 28
|
||||||
|
height: 28
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
CachingImage {
|
||||||
|
id: listPreviewImage
|
||||||
|
anchors.fill: parent
|
||||||
|
source: (!listDelegateRoot.fileIsDir && isImageFile(listDelegateRoot.fileName)) ? ("file://" + listDelegateRoot.filePath) : ""
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
maxCacheSize: 32
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiEffect {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: listPreviewImage
|
||||||
|
maskEnabled: true
|
||||||
|
maskSource: listImageMask
|
||||||
|
visible: listPreviewImage.status === Image.Ready && !listDelegateRoot.fileIsDir && isImageFile(listDelegateRoot.fileName)
|
||||||
|
maskThresholdMin: 0.5
|
||||||
|
maskSpreadAtMin: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: listImageMask
|
||||||
|
anchors.fill: parent
|
||||||
|
layer.enabled: true
|
||||||
|
layer.smooth: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: "black"
|
||||||
|
antialiasing: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: getFileIcon(listDelegateRoot.fileName, listDelegateRoot.fileIsDir)
|
||||||
|
size: Theme.iconSize - 2
|
||||||
|
color: listDelegateRoot.fileIsDir ? Theme.primary : Theme.surfaceText
|
||||||
|
visible: listDelegateRoot.fileIsDir || !isImageFile(listDelegateRoot.fileName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: listDelegateRoot.fileName || ""
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
width: parent.width - 280
|
||||||
|
elide: Text.ElideRight
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
maximumLineCount: 1
|
||||||
|
clip: true
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: listDelegateRoot.fileIsDir ? "" : formatFileSize(listDelegateRoot.fileSize)
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
width: 70
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: Qt.formatDateTime(listDelegateRoot.fileModified, "MMM d, yyyy h:mm AP")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
width: 140
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: listMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
itemClicked(listDelegateRoot.index, listDelegateRoot.filePath, listDelegateRoot.fileName, listDelegateRoot.fileIsDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
130
Modals/FileBrowser/FileBrowserNavigation.qml
Normal file
130
Modals/FileBrowser/FileBrowserNavigation.qml
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: navigation
|
||||||
|
|
||||||
|
property string currentPath: ""
|
||||||
|
property string homeDir: ""
|
||||||
|
property bool backButtonFocused: false
|
||||||
|
property bool keyboardNavigationActive: false
|
||||||
|
property bool showSidebar: true
|
||||||
|
property bool pathEditMode: false
|
||||||
|
property bool pathInputHasFocus: false
|
||||||
|
|
||||||
|
signal navigateUp()
|
||||||
|
signal navigateTo(string path)
|
||||||
|
signal pathInputFocusChanged(bool hasFocus)
|
||||||
|
|
||||||
|
height: 40
|
||||||
|
leftPadding: Theme.spacingM
|
||||||
|
rightPadding: Theme.spacingM
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: (backButtonMouseArea.containsMouse || (backButtonFocused && keyboardNavigationActive)) && currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
|
||||||
|
opacity: currentPath !== homeDir ? 1 : 0
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
name: "arrow_back"
|
||||||
|
size: Theme.iconSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: backButtonMouseArea
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: currentPath !== homeDir
|
||||||
|
cursorShape: currentPath !== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
enabled: currentPath !== homeDir
|
||||||
|
onClicked: navigation.navigateUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: Math.max(0, (parent?.width ?? 0) - 40 - Theme.spacingS - (showSidebar ? 0 : 80))
|
||||||
|
height: 32
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: pathEditMode ? Theme.surfaceContainer : "transparent"
|
||||||
|
border.color: pathEditMode ? Theme.primary : "transparent"
|
||||||
|
border.width: pathEditMode ? 1 : 0
|
||||||
|
visible: !pathEditMode
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: pathDisplay
|
||||||
|
text: currentPath.replace("file://", "")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
anchors.rightMargin: Theme.spacingS
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
maximumLineCount: 1
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.IBeamCursor
|
||||||
|
onClicked: {
|
||||||
|
pathEditMode = true
|
||||||
|
pathInput.text = currentPath.replace("file://", "")
|
||||||
|
Qt.callLater(() => pathInput.forceActiveFocus())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: pathInput
|
||||||
|
anchors.fill: parent
|
||||||
|
visible: pathEditMode
|
||||||
|
topPadding: Theme.spacingXS
|
||||||
|
bottomPadding: Theme.spacingXS
|
||||||
|
onAccepted: {
|
||||||
|
const newPath = text.trim()
|
||||||
|
if (newPath !== "") {
|
||||||
|
navigation.navigateTo(newPath)
|
||||||
|
}
|
||||||
|
pathEditMode = false
|
||||||
|
}
|
||||||
|
Keys.onEscapePressed: {
|
||||||
|
pathEditMode = false
|
||||||
|
}
|
||||||
|
Keys.onDownPressed: {
|
||||||
|
pathEditMode = false
|
||||||
|
}
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
navigation.pathInputFocusChanged(activeFocus)
|
||||||
|
if (!activeFocus && pathEditMode) {
|
||||||
|
pathEditMode = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
visible: !showSidebar
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
circular: false
|
||||||
|
iconName: "sort"
|
||||||
|
iconSize: Theme.iconSize - 6
|
||||||
|
iconColor: Theme.surfaceText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
127
Modals/FileBrowser/FileBrowserOverwriteDialog.qml
Normal file
127
Modals/FileBrowser/FileBrowserOverwriteDialog.qml
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: overwriteDialog
|
||||||
|
|
||||||
|
property bool showDialog: false
|
||||||
|
property string pendingFilePath: ""
|
||||||
|
|
||||||
|
signal confirmed(string filePath)
|
||||||
|
signal cancelled()
|
||||||
|
|
||||||
|
visible: showDialog
|
||||||
|
focus: showDialog
|
||||||
|
|
||||||
|
Keys.onEscapePressed: {
|
||||||
|
cancelled()
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
confirmed(pendingFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Theme.shadowStrong
|
||||||
|
opacity: 0.8
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
cancelled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 400
|
||||||
|
height: 160
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Theme.outlineMedium
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - Theme.spacingL * 2
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("File Already Exists")
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
font.weight: Font.Medium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("A file with this name already exists. Do you want to overwrite it?")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: 80
|
||||||
|
height: 36
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: cancelArea.containsMouse ? Theme.surfaceVariantHover : Theme.surfaceVariant
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: I18n.tr("Cancel")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: cancelArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
cancelled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: 90
|
||||||
|
height: 36
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: overwriteArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: I18n.tr("Overwrite")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.background
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: overwriteArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
confirmed(pendingFilePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
Modals/FileBrowser/FileBrowserSaveRow.qml
Normal file
74
Modals/FileBrowser/FileBrowserSaveRow.qml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: saveRow
|
||||||
|
|
||||||
|
property bool saveMode: false
|
||||||
|
property string defaultFileName: ""
|
||||||
|
property string currentPath: ""
|
||||||
|
|
||||||
|
signal saveRequested(string filePath)
|
||||||
|
|
||||||
|
height: saveMode ? 40 : 0
|
||||||
|
visible: saveMode
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
DankTextField {
|
||||||
|
id: fileNameInput
|
||||||
|
|
||||||
|
width: parent.width - saveButton.width - Theme.spacingM
|
||||||
|
height: 40
|
||||||
|
text: defaultFileName
|
||||||
|
placeholderText: I18n.tr("Enter filename...")
|
||||||
|
ignoreLeftRightKeys: false
|
||||||
|
focus: saveMode
|
||||||
|
topPadding: Theme.spacingS
|
||||||
|
bottomPadding: Theme.spacingS
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (saveMode)
|
||||||
|
Qt.callLater(() => {
|
||||||
|
forceActiveFocus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onAccepted: {
|
||||||
|
if (text.trim() !== "") {
|
||||||
|
var basePath = currentPath.replace(/^file:\/\//, '')
|
||||||
|
var fullPath = basePath + "/" + text.trim()
|
||||||
|
fullPath = fullPath.replace(/\/+/g, '/')
|
||||||
|
saveRequested(fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
|
width: 80
|
||||||
|
height: 40
|
||||||
|
color: fileNameInput.text.trim() !== "" ? Theme.primary : Theme.surfaceVariant
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: I18n.tr("Save")
|
||||||
|
color: fileNameInput.text.trim() !== "" ? Theme.primaryText : Theme.surfaceVariantText
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
stateColor: Theme.primary
|
||||||
|
cornerRadius: Theme.cornerRadius
|
||||||
|
enabled: fileNameInput.text.trim() !== ""
|
||||||
|
onClicked: {
|
||||||
|
if (fileNameInput.text.trim() !== "") {
|
||||||
|
var basePath = currentPath.replace(/^file:\/\//, '')
|
||||||
|
var fullPath = basePath + "/" + fileNameInput.text.trim()
|
||||||
|
fullPath = fullPath.replace(/\/+/g, '/')
|
||||||
|
saveRequested(fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
Modals/FileBrowser/FileBrowserSidebar.qml
Normal file
70
Modals/FileBrowser/FileBrowserSidebar.qml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: sidebar
|
||||||
|
|
||||||
|
property var quickAccessLocations: []
|
||||||
|
property string currentPath: ""
|
||||||
|
signal locationSelected(string path)
|
||||||
|
|
||||||
|
width: 200
|
||||||
|
color: Theme.surface
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Theme.spacingS
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Quick Access"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
font.weight: Font.Medium
|
||||||
|
leftPadding: Theme.spacingS
|
||||||
|
bottomPadding: Theme.spacingXS
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: quickAccessLocations
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: parent?.width ?? 0
|
||||||
|
height: 38
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: quickAccessMouseArea.containsMouse ? Theme.surfaceContainerHigh : (currentPath === modelData?.path ? Theme.surfacePressed : "transparent")
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Theme.spacingM
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: modelData?.icon ?? ""
|
||||||
|
size: Theme.iconSize - 2
|
||||||
|
color: currentPath === modelData?.path ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: modelData?.name ?? ""
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: currentPath === modelData?.path ? Theme.primary : Theme.surfaceText
|
||||||
|
font.weight: currentPath === modelData?.path ? Font.Medium : Font.Normal
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: quickAccessMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: locationSelected(modelData?.path ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
183
Modals/FileBrowser/FileBrowserSortMenu.qml
Normal file
183
Modals/FileBrowser/FileBrowserSortMenu.qml
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import QtQuick
|
||||||
|
import qs.Common
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
id: sortMenu
|
||||||
|
|
||||||
|
property string sortBy: "name"
|
||||||
|
property bool sortAscending: true
|
||||||
|
|
||||||
|
signal sortBySelected(string value)
|
||||||
|
signal sortOrderSelected(bool ascending)
|
||||||
|
|
||||||
|
width: 200
|
||||||
|
height: sortColumn.height + Theme.spacingM * 2
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.color: Theme.outlineMedium
|
||||||
|
border.width: 1
|
||||||
|
visible: false
|
||||||
|
z: 100
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: sortColumn
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.margins: Theme.spacingM
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Sort By"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: [{
|
||||||
|
"name": "Name",
|
||||||
|
"value": "name"
|
||||||
|
}, {
|
||||||
|
"name": "Size",
|
||||||
|
"value": "size"
|
||||||
|
}, {
|
||||||
|
"name": "Modified",
|
||||||
|
"value": "modified"
|
||||||
|
}, {
|
||||||
|
"name": "Type",
|
||||||
|
"value": "type"
|
||||||
|
}]
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: sortColumn?.width ?? 0
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: sortMouseArea.containsMouse ? Theme.surfaceVariant : (sortBy === modelData?.value ? Theme.surfacePressed : "transparent")
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: sortBy === modelData?.value ? "check" : ""
|
||||||
|
size: Theme.iconSizeSmall
|
||||||
|
color: Theme.primary
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
visible: sortBy === modelData?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: modelData?.name ?? ""
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: sortBy === modelData?.value ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: sortMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
sortMenu.sortBySelected(modelData?.value ?? "name")
|
||||||
|
sortMenu.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: sortColumn.width
|
||||||
|
height: 1
|
||||||
|
color: Theme.outline
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Order"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceTextMedium
|
||||||
|
font.weight: Font.Medium
|
||||||
|
topPadding: Theme.spacingXS
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: sortColumn?.width ?? 0
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: ascMouseArea.containsMouse ? Theme.surfaceVariant : (sortAscending ? Theme.surfacePressed : "transparent")
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "arrow_upward"
|
||||||
|
size: Theme.iconSizeSmall
|
||||||
|
color: sortAscending ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Ascending"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: sortAscending ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: ascMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
sortMenu.sortOrderSelected(true)
|
||||||
|
sortMenu.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledRect {
|
||||||
|
width: sortColumn?.width ?? 0
|
||||||
|
height: 32
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: descMouseArea.containsMouse ? Theme.surfaceVariant : (!sortAscending ? Theme.surfacePressed : "transparent")
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Theme.spacingS
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "arrow_downward"
|
||||||
|
size: Theme.iconSizeSmall
|
||||||
|
color: !sortAscending ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "Descending"
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: !sortAscending ? Theme.primary : Theme.surfaceText
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: descMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
sortMenu.sortOrderSelected(false)
|
||||||
|
sortMenu.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user