mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-08 06:25:37 -05:00
systematic cleanups and qmlfmt file browser modal
This commit is contained in:
@@ -34,8 +34,7 @@ Item {
|
||||
clearConfirmDialog.show("Clear All History?", "This will permanently delete all clipboard history.", function () {
|
||||
modal.clearAll()
|
||||
modal.hide()
|
||||
}, function () {} // No action on cancel
|
||||
)
|
||||
}, function () {})
|
||||
}
|
||||
onCloseClicked: modal.hide()
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modals.Clipboard
|
||||
import qs.Modals
|
||||
|
||||
DankModal {
|
||||
id: clipboardHistoryModal
|
||||
@@ -170,6 +170,7 @@ DankModal {
|
||||
|
||||
property alias filteredClipboardModel: filteredClipboardModel
|
||||
property alias clipboardModel: clipboardModel
|
||||
property var confirmDialog: clearConfirmDialog
|
||||
|
||||
ListModel {
|
||||
id: clipboardModel
|
||||
@@ -209,7 +210,7 @@ DankModal {
|
||||
ClipboardContent {
|
||||
modal: clipboardHistoryModal
|
||||
filteredModel: filteredClipboardModel
|
||||
clearConfirmDialog: clipboardHistoryModal.clearConfirmDialog
|
||||
clearConfirmDialog: clipboardHistoryModal.confirmDialog
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
@@ -14,10 +10,9 @@ DankModal {
|
||||
property string confirmButtonText: "Confirm"
|
||||
property string cancelButtonText: "Cancel"
|
||||
property color confirmButtonColor: Theme.primary
|
||||
property var onConfirm: function() {}
|
||||
property var onCancel: function() {}
|
||||
|
||||
property int selectedButton: -1 // -1 = none, 0 = Cancel, 1 = Confirm
|
||||
property var onConfirm: function () {}
|
||||
property var onCancel: function () {}
|
||||
property int selectedButton: -1
|
||||
property bool keyboardNavigation: false
|
||||
|
||||
function show(title, message, onConfirmCallback, onCancelCallback) {
|
||||
@@ -26,8 +21,8 @@ DankModal {
|
||||
confirmButtonText = "Confirm"
|
||||
cancelButtonText = "Cancel"
|
||||
confirmButtonColor = Theme.primary
|
||||
onConfirm = onConfirmCallback || function() {}
|
||||
onCancel = onCancelCallback || function() {}
|
||||
onConfirm = onConfirmCallback || (() => {})
|
||||
onCancel = onCancelCallback || (() => {})
|
||||
selectedButton = -1
|
||||
keyboardNavigation = false
|
||||
open()
|
||||
@@ -39,20 +34,23 @@ DankModal {
|
||||
confirmButtonText = options.confirmText || "Confirm"
|
||||
cancelButtonText = options.cancelText || "Cancel"
|
||||
confirmButtonColor = options.confirmColor || Theme.primary
|
||||
onConfirm = options.onConfirm || function() {}
|
||||
onCancel = options.onCancel || function() {}
|
||||
onConfirm = options.onConfirm || (() => {})
|
||||
onCancel = options.onCancel || (() => {})
|
||||
selectedButton = -1
|
||||
keyboardNavigation = false
|
||||
open()
|
||||
}
|
||||
|
||||
function selectButton() {
|
||||
close()
|
||||
if (selectedButton === 0) {
|
||||
close()
|
||||
if (onCancel) onCancel()
|
||||
if (onCancel) {
|
||||
onCancel()
|
||||
}
|
||||
} else {
|
||||
close()
|
||||
if (onConfirm) onConfirm()
|
||||
if (onConfirm) {
|
||||
onConfirm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,18 +62,22 @@ DankModal {
|
||||
shouldHaveFocus: true
|
||||
onBackgroundClicked: {
|
||||
close()
|
||||
if (onCancel) onCancel()
|
||||
if (onCancel) {
|
||||
onCancel()
|
||||
}
|
||||
}
|
||||
onOpened: {
|
||||
modalFocusScope.forceActiveFocus()
|
||||
modalFocusScope.focus = true
|
||||
shouldHaveFocus = true
|
||||
}
|
||||
modalFocusScope.Keys.onPressed: function(event) {
|
||||
modalFocusScope.Keys.onPressed: function (event) {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
close()
|
||||
if (onCancel) onCancel()
|
||||
if (onCancel) {
|
||||
onCancel()
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
case Qt.Key_Left:
|
||||
@@ -148,13 +150,14 @@ DankModal {
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
if (keyboardNavigation && selectedButton === 0)
|
||||
if (keyboardNavigation && selectedButton === 0) {
|
||||
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||
else if (cancelButton.containsMouse)
|
||||
} else if (cancelButton.containsMouse) {
|
||||
return Theme.surfacePressed
|
||||
else
|
||||
} else {
|
||||
return Theme.surfaceVariantAlpha
|
||||
}
|
||||
}
|
||||
border.color: (keyboardNavigation && selectedButton === 0) ? Theme.primary : "transparent"
|
||||
border.width: (keyboardNavigation && selectedButton === 0) ? 1 : 0
|
||||
|
||||
@@ -177,7 +180,6 @@ DankModal {
|
||||
selectButton()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -185,14 +187,15 @@ DankModal {
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
let baseColor = confirmButtonColor
|
||||
if (keyboardNavigation && selectedButton === 1)
|
||||
const baseColor = confirmButtonColor
|
||||
if (keyboardNavigation && selectedButton === 1) {
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 1)
|
||||
else if (confirmButton.containsMouse)
|
||||
} else if (confirmButton.containsMouse) {
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 0.9)
|
||||
else
|
||||
} else {
|
||||
return baseColor
|
||||
}
|
||||
}
|
||||
border.color: (keyboardNavigation && selectedButton === 1) ? "white" : "transparent"
|
||||
border.width: (keyboardNavigation && selectedButton === 1) ? 1 : 0
|
||||
|
||||
@@ -215,15 +218,9 @@ DankModal {
|
||||
selectButton()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ PanelWindow {
|
||||
property real borderWidth: 1
|
||||
property real cornerRadius: Theme.cornerRadius
|
||||
property bool enableShadow: false
|
||||
// Expose the focusScope for external access
|
||||
property alias modalFocusScope: focusScope
|
||||
property bool shouldBeVisible: false
|
||||
property bool shouldHaveFocus: shouldBeVisible
|
||||
@@ -38,15 +37,6 @@ PanelWindow {
|
||||
signal dialogClosed
|
||||
signal backgroundClicked
|
||||
|
||||
Connections {
|
||||
target: ModalManager
|
||||
function onCloseAllModalsExcept(excludedModal) {
|
||||
if (excludedModal !== root && !allowStacking && shouldBeVisible) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function open() {
|
||||
ModalManager.openModal(root)
|
||||
closeTimer.stop()
|
||||
@@ -61,11 +51,12 @@ PanelWindow {
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (shouldBeVisible)
|
||||
if (shouldBeVisible) {
|
||||
close()
|
||||
else
|
||||
} else {
|
||||
open()
|
||||
}
|
||||
}
|
||||
|
||||
visible: shouldBeVisible
|
||||
color: "transparent"
|
||||
@@ -84,6 +75,16 @@ PanelWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onCloseAllModalsExcept(excludedModal) {
|
||||
if (excludedModal !== root && !allowStacking && shouldBeVisible) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
target: ModalManager
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: closeTimer
|
||||
|
||||
@@ -112,15 +113,12 @@ PanelWindow {
|
||||
anchors.fill: parent
|
||||
enabled: root.closeOnBackgroundClick
|
||||
onClicked: mouse => {
|
||||
var localPos = mapToItem(contentContainer,
|
||||
mouse.x, mouse.y)
|
||||
if (localPos.x < 0
|
||||
|| localPos.x > contentContainer.width
|
||||
|| localPos.y < 0
|
||||
|| localPos.y > contentContainer.height)
|
||||
const localPos = mapToItem(contentContainer, mouse.x, mouse.y)
|
||||
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height) {
|
||||
root.backgroundClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
@@ -137,19 +135,20 @@ PanelWindow {
|
||||
height: root.height
|
||||
anchors.centerIn: positioning === "center" ? parent : undefined
|
||||
x: {
|
||||
if (positioning === "top-right")
|
||||
return Math.max(Theme.spacingL,
|
||||
root.screenWidth - width - Theme.spacingL)
|
||||
else if (positioning === "custom")
|
||||
if (positioning === "top-right") {
|
||||
return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL)
|
||||
} else if (positioning === "custom") {
|
||||
return root.customPosition.x
|
||||
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
y: {
|
||||
if (positioning === "top-right")
|
||||
if (positioning === "top-right") {
|
||||
return Theme.barHeight + Theme.spacingXS
|
||||
else if (positioning === "custom")
|
||||
} else if (positioning === "custom") {
|
||||
return root.customPosition.y
|
||||
return 0 // Will be overridden by anchors.centerIn when positioning === "center"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
color: root.backgroundColor
|
||||
radius: root.cornerRadius
|
||||
@@ -157,12 +156,7 @@ PanelWindow {
|
||||
border.width: root.borderWidth
|
||||
layer.enabled: root.enableShadow
|
||||
opacity: root.shouldBeVisible ? 1 : 0
|
||||
scale: {
|
||||
if (root.animationType === "scale")
|
||||
return root.shouldBeVisible ? 1 : 0.9
|
||||
|
||||
return 1
|
||||
}
|
||||
scale: root.animationType === "scale" ? (root.shouldBeVisible ? 1 : 0.9) : 1
|
||||
transform: root.animationType === "slide" ? slideTransform : null
|
||||
|
||||
Translate {
|
||||
@@ -214,28 +208,25 @@ PanelWindow {
|
||||
visible: root.visible // Only active when the modal is visible
|
||||
focus: root.visible
|
||||
Keys.onEscapePressed: event => {
|
||||
if (root.closeOnEscapeKey
|
||||
&& shouldHaveFocus) {
|
||||
if (root.closeOnEscapeKey && shouldHaveFocus) {
|
||||
root.close()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (visible && shouldHaveFocus)
|
||||
Qt.callLater(function () {
|
||||
focusScope.forceActiveFocus()
|
||||
})
|
||||
if (visible && shouldHaveFocus) {
|
||||
Qt.callLater(() => focusScope.forceActiveFocus())
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onShouldHaveFocusChanged() {
|
||||
if (shouldHaveFocus && visible) {
|
||||
Qt.callLater(function () {
|
||||
focusScope.forceActiveFocus()
|
||||
})
|
||||
Qt.callLater(() => focusScope.forceActiveFocus())
|
||||
}
|
||||
}
|
||||
|
||||
target: root
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
import Qt.labs.folderlistmodel
|
||||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtCore
|
||||
import Qt.labs.folderlistmodel
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Modals
|
||||
import qs.Widgets
|
||||
|
||||
DankModal {
|
||||
id: fileBrowserModal
|
||||
objectName: "fileBrowserModal"
|
||||
allowStacking: true
|
||||
|
||||
signal fileSelected(string path)
|
||||
|
||||
property string homeDir: StandardPaths.writableLocation(
|
||||
StandardPaths.HomeLocation)
|
||||
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
||||
property string currentPath: ""
|
||||
property var fileExtensions: ["*.*"]
|
||||
property alias filterExtensions: fileBrowserModal.fileExtensions
|
||||
@@ -27,37 +23,27 @@ DankModal {
|
||||
property bool backButtonFocused: false
|
||||
property bool saveMode: false // Enable save functionality
|
||||
property string defaultFileName: "" // Default filename for save mode
|
||||
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
|
||||
|
||||
FolderListModel {
|
||||
id: folderModel
|
||||
showDirsFirst: true
|
||||
showDotAndDotDot: false
|
||||
showHidden: fileBrowserModal.showHiddenFiles
|
||||
nameFilters: fileExtensions
|
||||
showFiles: true
|
||||
showDirs: true
|
||||
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
|
||||
}
|
||||
signal fileSelected(string path)
|
||||
|
||||
function isImageFile(fileName) {
|
||||
if (!fileName)
|
||||
if (!fileName) {
|
||||
return false
|
||||
var ext = fileName.toLowerCase().split('.').pop()
|
||||
}
|
||||
const ext = fileName.toLowerCase().split('.').pop()
|
||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
|
||||
}
|
||||
|
||||
function getLastPath() {
|
||||
var lastPath = ""
|
||||
if (browserType === "wallpaper") {
|
||||
lastPath = SessionData.wallpaperLastPath
|
||||
} else if (browserType === "profile") {
|
||||
lastPath = SessionData.profileLastPath
|
||||
}
|
||||
|
||||
if (lastPath && lastPath !== "") {
|
||||
return lastPath
|
||||
}
|
||||
return homeDir
|
||||
const lastPath = browserType === "wallpaper" ? SessionData.wallpaperLastPath : browserType === "profile" ? SessionData.profileLastPath : ""
|
||||
return (lastPath && lastPath !== "") ? lastPath : homeDir
|
||||
}
|
||||
|
||||
function saveLastPath(path) {
|
||||
@@ -68,64 +54,103 @@ DankModal {
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentPath = getLastPath()
|
||||
}
|
||||
|
||||
width: 800
|
||||
height: 600
|
||||
enableShadow: true
|
||||
visible: false
|
||||
|
||||
onBackgroundClicked: close()
|
||||
|
||||
onOpened: {
|
||||
modalFocusScope.forceActiveFocus()
|
||||
}
|
||||
|
||||
modalFocusScope.Keys.onPressed: function(event) {
|
||||
keyboardController.handleKey(event)
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
var startPath = getLastPath()
|
||||
currentPath = startPath
|
||||
selectedIndex = -1
|
||||
keyboardNavigationActive = false
|
||||
backButtonFocused = false
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentPathChanged: {
|
||||
selectedFilePath = ""
|
||||
selectedFileName = ""
|
||||
selectedFileIsDir = false
|
||||
}
|
||||
|
||||
onSelectedIndexChanged: {
|
||||
// Update selected file data when index changes
|
||||
if (selectedIndex >= 0 && folderModel && selectedIndex < folderModel.count) {
|
||||
// We need to get the file data from the model for this index
|
||||
// This is a bit tricky with FolderListModel, so we'll use a different approach
|
||||
selectedFilePath = ""
|
||||
selectedFileName = ""
|
||||
selectedFileIsDir = false
|
||||
}
|
||||
}
|
||||
|
||||
// Function to update file data from delegates
|
||||
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
|
||||
}
|
||||
|
||||
objectName: "fileBrowserModal"
|
||||
allowStacking: true
|
||||
Component.onCompleted: {
|
||||
currentPath = getLastPath()
|
||||
}
|
||||
width: 800
|
||||
height: 600
|
||||
enableShadow: true
|
||||
visible: false
|
||||
onBackgroundClicked: close()
|
||||
onOpened: {
|
||||
modalFocusScope.forceActiveFocus()
|
||||
}
|
||||
modalFocusScope.Keys.onPressed: function (event) {
|
||||
keyboardController.handleKey(event)
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
currentPath = getLastPath()
|
||||
selectedIndex = -1
|
||||
keyboardNavigationActive = false
|
||||
backButtonFocused = false
|
||||
}
|
||||
}
|
||||
onCurrentPathChanged: {
|
||||
selectedFilePath = ""
|
||||
selectedFileName = ""
|
||||
selectedFileIsDir = false
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: keyboardController
|
||||
|
||||
property int totalItems: folderModel.count
|
||||
property int gridColumns: 5 // Fixed number of columns for the grid (matches actual display)
|
||||
property int gridColumns: 5
|
||||
|
||||
function handleKey(event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
@@ -133,21 +158,18 @@ DankModal {
|
||||
event.accepted = true
|
||||
return
|
||||
}
|
||||
|
||||
// F10 toggles keyboard hints
|
||||
if (event.key === Qt.Key_F10) {
|
||||
showKeyboardHints = !showKeyboardHints
|
||||
event.accepted = true
|
||||
return
|
||||
}
|
||||
|
||||
// F1 or I key for file information
|
||||
if (event.key === Qt.Key_F1 || event.key === Qt.Key_I) {
|
||||
showFileInfo = !showFileInfo
|
||||
event.accepted = true
|
||||
return
|
||||
}
|
||||
|
||||
// Alt+Left or Backspace to go back
|
||||
if ((event.modifiers & Qt.AltModifier && event.key === Qt.Key_Left) || event.key === Qt.Key_Backspace) {
|
||||
if (currentPath !== homeDir) {
|
||||
@@ -156,7 +178,6 @@ DankModal {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (!keyboardNavigationActive) {
|
||||
if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down || event.key === Qt.Key_Right) {
|
||||
keyboardNavigationActive = true
|
||||
@@ -171,7 +192,6 @@ DankModal {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case Qt.Key_Tab:
|
||||
if (backButtonFocused) {
|
||||
@@ -187,7 +207,6 @@ DankModal {
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Backtab:
|
||||
if (backButtonFocused) {
|
||||
backButtonFocused = false
|
||||
@@ -202,45 +221,36 @@ DankModal {
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Left:
|
||||
if (backButtonFocused) {
|
||||
if (backButtonFocused)
|
||||
return
|
||||
}
|
||||
|
||||
if (selectedIndex > 0) {
|
||||
selectedIndex--
|
||||
// Update file info for navigation
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
} else if (currentPath !== homeDir) {
|
||||
backButtonFocused = true
|
||||
selectedIndex = -1
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Right:
|
||||
if (backButtonFocused) {
|
||||
backButtonFocused = false
|
||||
selectedIndex = 0
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
} else if (selectedIndex < totalItems - 1) {
|
||||
selectedIndex++
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Up:
|
||||
if (backButtonFocused) {
|
||||
backButtonFocused = false
|
||||
// Go to first row, appropriate column
|
||||
var col = selectedIndex % gridColumns
|
||||
selectedIndex = Math.min(col, totalItems - 1)
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
} else if (selectedIndex >= gridColumns) {
|
||||
// Move up one row
|
||||
selectedIndex -= gridColumns
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
} else if (currentPath !== homeDir) {
|
||||
// At top row, go to back button
|
||||
backButtonFocused = true
|
||||
@@ -248,18 +258,15 @@ DankModal {
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Down:
|
||||
if (backButtonFocused) {
|
||||
backButtonFocused = false
|
||||
selectedIndex = 0
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
} else {
|
||||
// Move down one row if possible
|
||||
var newIndex = selectedIndex + gridColumns
|
||||
if (newIndex < totalItems) {
|
||||
selectedIndex = newIndex
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
} else {
|
||||
// If can't go down a full row, go to last item in the column if exists
|
||||
var lastRowStart = Math.floor((totalItems - 1) / gridColumns) * gridColumns
|
||||
@@ -267,83 +274,31 @@ DankModal {
|
||||
var targetIndex = lastRowStart + col
|
||||
if (targetIndex < totalItems && targetIndex > selectedIndex) {
|
||||
selectedIndex = targetIndex
|
||||
updateFileInfoForIndex(selectedIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
|
||||
case Qt.Key_Return:
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Space:
|
||||
if (backButtonFocused) {
|
||||
if (backButtonFocused)
|
||||
navigateUp()
|
||||
} else if (selectedIndex >= 0 && selectedIndex < totalItems) {
|
||||
else if (selectedIndex >= 0 && selectedIndex < totalItems)
|
||||
// Trigger selection by setting the grid's current index and using signal
|
||||
fileBrowserModal.keyboardFileSelection(selectedIndex)
|
||||
}
|
||||
event.accepted = true
|
||||
break
|
||||
}
|
||||
|
||||
// Scroll handling is done in the grid's onCurrentIndexChanged
|
||||
}
|
||||
}
|
||||
|
||||
function navigateUp() {
|
||||
var path = currentPath
|
||||
|
||||
if (path === homeDir) {
|
||||
return
|
||||
}
|
||||
|
||||
var lastSlash = path.lastIndexOf('/')
|
||||
if (lastSlash > 0) {
|
||||
var 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) // Save the path when navigating
|
||||
selectedIndex = -1
|
||||
backButtonFocused = false
|
||||
}
|
||||
|
||||
function keyboardFileSelection(index) {
|
||||
if (index >= 0) {
|
||||
keyboardSelectionTimer.targetIndex = index
|
||||
keyboardSelectionTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
function updateSelectedFileInfo(index) {
|
||||
// This will be called when we need to update file info for the selected index
|
||||
// The delegate will handle the actual file info updates
|
||||
}
|
||||
|
||||
function updateFileInfoForIndex(index) {
|
||||
// We can't directly access FolderListModel data by index from here
|
||||
// Instead, we'll rely on the delegate's Component.onCompleted and mouse clicks
|
||||
// to call setSelectedFileData() with the proper file information
|
||||
|
||||
// For keyboard navigation, we need a different approach
|
||||
// The selectedIndex change will trigger delegate updates
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: keyboardSelectionTimer
|
||||
interval: 1
|
||||
|
||||
property int targetIndex: -1
|
||||
|
||||
interval: 1
|
||||
onTriggered: {
|
||||
// Access the currently selected item through model role names
|
||||
// This will work because QML models expose role data
|
||||
@@ -351,23 +306,6 @@ DankModal {
|
||||
}
|
||||
}
|
||||
|
||||
function executeKeyboardSelection(index) {
|
||||
// This is a simplified version that just needs to work
|
||||
// We'll handle this in the mouse area of each delegate
|
||||
// For now, signal that keyboard selection was requested
|
||||
keyboardSelectionIndex = index
|
||||
keyboardSelectionRequested = true
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
content: Component {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
@@ -434,9 +372,8 @@ DankModal {
|
||||
width: 32
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: (backButtonMouseArea.containsMouse || (backButtonFocused && keyboardNavigationActive))
|
||||
&& currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
|
||||
opacity: currentPath !== homeDir ? 1.0 : 0.0
|
||||
color: (backButtonMouseArea.containsMouse || (backButtonFocused && keyboardNavigationActive)) && currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
|
||||
opacity: currentPath !== homeDir ? 1 : 0
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
@@ -447,10 +384,10 @@ DankModal {
|
||||
|
||||
MouseArea {
|
||||
id: backButtonMouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: currentPath !== homeDir
|
||||
cursorShape: currentPath
|
||||
!== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
cursorShape: currentPath !== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
enabled: currentPath !== homeDir
|
||||
onClicked: navigateUp()
|
||||
}
|
||||
@@ -478,19 +415,17 @@ DankModal {
|
||||
cellWidth: 150
|
||||
cellHeight: 130
|
||||
cacheBuffer: 260
|
||||
|
||||
model: folderModel
|
||||
currentIndex: selectedIndex
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (keyboardNavigationActive && currentIndex >= 0) {
|
||||
if (keyboardNavigationActive && currentIndex >= 0)
|
||||
positionViewAtIndex(currentIndex, GridView.Contain)
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
ScrollBar.horizontal: ScrollBar {
|
||||
policy: ScrollBar.AlwaysOff
|
||||
}
|
||||
@@ -508,29 +443,27 @@ DankModal {
|
||||
height: 120
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
if (keyboardNavigationActive && delegateRoot.index === selectedIndex) {
|
||||
if (keyboardNavigationActive && delegateRoot.index === selectedIndex)
|
||||
return Theme.surfacePressed
|
||||
}
|
||||
|
||||
return mouseArea.containsMouse ? Theme.surfaceVariant : "transparent"
|
||||
}
|
||||
border.color: keyboardNavigationActive && delegateRoot.index === selectedIndex ? Theme.primary : Theme.outline
|
||||
border.width: (mouseArea.containsMouse || (keyboardNavigationActive && delegateRoot.index === selectedIndex)) ? 1 : 0
|
||||
|
||||
// Update file info when this item gets selected via keyboard or initially
|
||||
Component.onCompleted: {
|
||||
if (keyboardNavigationActive && delegateRoot.index === selectedIndex) {
|
||||
if (keyboardNavigationActive && delegateRoot.index === selectedIndex)
|
||||
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||
}
|
||||
}
|
||||
|
||||
// Watch for selectedIndex changes to update file info during keyboard navigation
|
||||
Connections {
|
||||
target: fileBrowserModal
|
||||
function onSelectedIndexChanged() {
|
||||
if (keyboardNavigationActive && selectedIndex === delegateRoot.index) {
|
||||
if (keyboardNavigationActive && selectedIndex === delegateRoot.index)
|
||||
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||
}
|
||||
}
|
||||
|
||||
target: fileBrowserModal
|
||||
}
|
||||
|
||||
Column {
|
||||
@@ -555,8 +488,7 @@ DankModal {
|
||||
name: "description"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: !delegateRoot.fileIsDir
|
||||
&& !isImageFile(delegateRoot.fileName)
|
||||
visible: !delegateRoot.fileIsDir && !isImageFile(delegateRoot.fileName)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
@@ -583,15 +515,14 @@ DankModal {
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
// Update selected file info and index first
|
||||
selectedIndex = delegateRoot.index
|
||||
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||
|
||||
if (delegateRoot.fileIsDir) {
|
||||
navigateTo(delegateRoot.filePath)
|
||||
} else {
|
||||
@@ -603,15 +534,11 @@ DankModal {
|
||||
|
||||
// Handle keyboard selection
|
||||
Connections {
|
||||
target: fileBrowserModal
|
||||
function onKeyboardSelectionRequestedChanged() {
|
||||
if (fileBrowserModal.keyboardSelectionRequested && fileBrowserModal.keyboardSelectionIndex === delegateRoot.index) {
|
||||
// Reset the flag first
|
||||
fileBrowserModal.keyboardSelectionRequested = false
|
||||
// Update selected file info and index first
|
||||
selectedIndex = delegateRoot.index
|
||||
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
|
||||
// Trigger the same action as mouse click
|
||||
if (delegateRoot.fileIsDir) {
|
||||
navigateTo(delegateRoot.filePath)
|
||||
} else {
|
||||
@@ -620,15 +547,16 @@ DankModal {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target: fileBrowserModal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save functionality - positioned at bottom in save mode
|
||||
Row {
|
||||
id: saveRow
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -639,32 +567,31 @@ DankModal {
|
||||
|
||||
DankTextField {
|
||||
id: fileNameInput
|
||||
|
||||
width: parent.width - saveButton.width - Theme.spacingM
|
||||
height: 36
|
||||
text: defaultFileName
|
||||
placeholderText: "Enter filename..."
|
||||
ignoreLeftRightKeys: false // Allow arrow key navigation
|
||||
focus: saveMode // Auto-focus when in save mode
|
||||
|
||||
ignoreLeftRightKeys: false
|
||||
focus: saveMode
|
||||
Component.onCompleted: {
|
||||
if (saveMode) {
|
||||
if (saveMode)
|
||||
Qt.callLater(() => {
|
||||
forceActiveFocus();
|
||||
});
|
||||
forceActiveFocus()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
if (text.trim() !== "") {
|
||||
var fullPath = currentPath + "/" + text.trim();
|
||||
fileSelected(fullPath);
|
||||
fileBrowserModal.close();
|
||||
var fullPath = currentPath + "/" + text.trim()
|
||||
fileSelected(fullPath)
|
||||
fileBrowserModal.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
id: saveButton
|
||||
|
||||
width: 80
|
||||
height: 36
|
||||
color: fileNameInput.text.trim() !== "" ? Theme.primary : Theme.surfaceVariant
|
||||
@@ -683,17 +610,18 @@ DankModal {
|
||||
enabled: fileNameInput.text.trim() !== ""
|
||||
onClicked: {
|
||||
if (fileNameInput.text.trim() !== "") {
|
||||
var fullPath = currentPath + "/" + fileNameInput.text.trim();
|
||||
fileSelected(fullPath);
|
||||
fileBrowserModal.close();
|
||||
var fullPath = currentPath + "/" + fileNameInput.text.trim()
|
||||
fileSelected(fullPath)
|
||||
fileBrowserModal.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileBrowserKeyboardHints {
|
||||
KeyboardHints {
|
||||
id: keyboardHints
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
@@ -701,8 +629,9 @@ DankModal {
|
||||
showHints: fileBrowserModal.showKeyboardHints
|
||||
}
|
||||
|
||||
FileBrowserFileInfo {
|
||||
FileInfo {
|
||||
id: fileInfo
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.margins: Theme.spacingL
|
||||
@@ -711,16 +640,15 @@ DankModal {
|
||||
selectedIndex: fileBrowserModal.selectedIndex
|
||||
sourceFolderModel: folderModel
|
||||
currentPath: fileBrowserModal.currentPath
|
||||
|
||||
// Bind directly to the modal's selected file properties
|
||||
currentFileName: fileBrowserModal.selectedFileName
|
||||
currentFileIsDir: fileBrowserModal.selectedFileIsDir
|
||||
currentFileExtension: {
|
||||
if (fileBrowserModal.selectedFileIsDir || !fileBrowserModal.selectedFileName) return ""
|
||||
if (fileBrowserModal.selectedFileIsDir || !fileBrowserModal.selectedFileName)
|
||||
return ""
|
||||
|
||||
var lastDot = fileBrowserModal.selectedFileName.lastIndexOf('.')
|
||||
return lastDot > 0 ? fileBrowserModal.selectedFileName.substring(lastDot + 1).toLowerCase() : ""
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtCore
|
||||
import Qt.labs.folderlistmodel
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
@@ -16,8 +14,7 @@ Rectangle {
|
||||
|
||||
height: 200
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b, 0.95)
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
|
||||
border.color: Theme.secondary
|
||||
border.width: 2
|
||||
opacity: showFileInfo ? 1 : 0
|
||||
@@ -25,7 +22,7 @@ Rectangle {
|
||||
|
||||
onShowFileInfoChanged: {
|
||||
if (showFileInfo && currentFileName && currentPath) {
|
||||
var fullPath = currentPath + "/" + currentFileName
|
||||
const fullPath = currentPath + "/" + currentFileName
|
||||
fileStatProcess.selectedFilePath = fullPath
|
||||
fileStatProcess.running = true
|
||||
}
|
||||
@@ -41,60 +38,20 @@ Rectangle {
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
if (text && text.trim()) {
|
||||
var parts = text.trim().split('|')
|
||||
const parts = text.trim().split('|')
|
||||
if (parts.length >= 4) {
|
||||
fileStatProcess.fileStats = {
|
||||
modifiedTime: parts[0],
|
||||
permissions: parts[1],
|
||||
size: parseInt(parts[2]) || 0,
|
||||
fullPath: parts[3]
|
||||
"modifiedTime": parts[0],
|
||||
"permissions": parts[1],
|
||||
"size": parseInt(parts[2]) || 0,
|
||||
"fullPath": parts[3]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onExited: function(exitCode) {}
|
||||
}
|
||||
|
||||
readonly property var currentFileData: {
|
||||
if (!sourceFolderModel || selectedIndex < 0 || selectedIndex >= sourceFolderModel.count) {
|
||||
return {
|
||||
exists: false,
|
||||
name: "No selection",
|
||||
type: "",
|
||||
size: "",
|
||||
modified: "",
|
||||
permissions: "",
|
||||
extension: "",
|
||||
position: selectedIndex >= 0 ? (selectedIndex + 1) + " of " + (sourceFolderModel ? sourceFolderModel.count : 0) : "N/A"
|
||||
}
|
||||
}
|
||||
|
||||
var path = currentPath
|
||||
if (path && selectedIndex >= 0) {
|
||||
return {
|
||||
exists: true,
|
||||
name: "Loading...",
|
||||
type: "file",
|
||||
size: "Calculating...",
|
||||
modified: "Loading...",
|
||||
permissions: "Loading...",
|
||||
extension: "",
|
||||
position: (selectedIndex + 1) + " of " + sourceFolderModel.count
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
exists: false,
|
||||
name: "No selection",
|
||||
type: "",
|
||||
size: "",
|
||||
modified: "",
|
||||
permissions: "",
|
||||
extension: "",
|
||||
position: "N/A"
|
||||
}
|
||||
onExited: function (exitCode) {}
|
||||
}
|
||||
|
||||
property string currentFileName: ""
|
||||
@@ -103,7 +60,7 @@ Rectangle {
|
||||
|
||||
onCurrentFileNameChanged: {
|
||||
if (showFileInfo && currentFileName && currentPath) {
|
||||
var fullPath = currentPath + "/" + currentFileName
|
||||
const fullPath = currentPath + "/" + currentFileName
|
||||
if (fullPath !== fileStatProcess.selectedFilePath) {
|
||||
fileStatProcess.selectedFilePath = fullPath
|
||||
fileStatProcess.running = true
|
||||
@@ -117,9 +74,9 @@ Rectangle {
|
||||
currentFileName = fileName || ""
|
||||
currentFileIsDir = isDirectory || false
|
||||
|
||||
var ext = ""
|
||||
let ext = ""
|
||||
if (!isDirectory && fileName) {
|
||||
var lastDot = fileName.lastIndexOf('.')
|
||||
const lastDot = fileName.lastIndexOf('.')
|
||||
if (lastDot > 0) {
|
||||
ext = fileName.substring(lastDot + 1).toLowerCase()
|
||||
}
|
||||
@@ -135,27 +92,27 @@ Rectangle {
|
||||
readonly property var currentFileDisplayData: {
|
||||
if (selectedIndex < 0 || !sourceFolderModel) {
|
||||
return {
|
||||
exists: false,
|
||||
name: "No selection",
|
||||
type: "",
|
||||
size: "",
|
||||
modified: "",
|
||||
permissions: "",
|
||||
extension: "",
|
||||
position: "N/A"
|
||||
"exists": false,
|
||||
"name": "No selection",
|
||||
"type": "",
|
||||
"size": "",
|
||||
"modified": "",
|
||||
"permissions": "",
|
||||
"extension": "",
|
||||
"position": "N/A"
|
||||
}
|
||||
}
|
||||
|
||||
var hasValidFile = currentFileName !== ""
|
||||
const hasValidFile = currentFileName !== ""
|
||||
return {
|
||||
exists: hasValidFile,
|
||||
name: hasValidFile ? currentFileName : "Loading...",
|
||||
type: currentFileIsDir ? "Directory" : "File",
|
||||
size: fileStatProcess.fileStats ? formatFileSize(fileStatProcess.fileStats.size) : "Calculating...",
|
||||
modified: fileStatProcess.fileStats ? formatDateTime(fileStatProcess.fileStats.modifiedTime) : "Loading...",
|
||||
permissions: fileStatProcess.fileStats ? fileStatProcess.fileStats.permissions : "Loading...",
|
||||
extension: currentFileExtension,
|
||||
position: sourceFolderModel ? ((selectedIndex + 1) + " of " + sourceFolderModel.count) : "N/A"
|
||||
"exists": hasValidFile,
|
||||
"name": hasValidFile ? currentFileName : "Loading...",
|
||||
"type": currentFileIsDir ? "Directory" : "File",
|
||||
"size": fileStatProcess.fileStats ? formatFileSize(fileStatProcess.fileStats.size) : "Calculating...",
|
||||
"modified": fileStatProcess.fileStats ? formatDateTime(fileStatProcess.fileStats.modifiedTime) : "Loading...",
|
||||
"permissions": fileStatProcess.fileStats ? fileStatProcess.fileStats.permissions : "Loading...",
|
||||
"extension": currentFileExtension,
|
||||
"position": sourceFolderModel ? ((selectedIndex + 1) + " of " + sourceFolderModel.count) : "N/A"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,16 +208,20 @@ Rectangle {
|
||||
}
|
||||
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0 || !bytes) return "0 B"
|
||||
var k = 1024
|
||||
var sizes = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
var i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
if (bytes === 0 || !bytes) {
|
||||
return "0 B"
|
||||
}
|
||||
const k = 1024
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
function formatDateTime(dateTimeString) {
|
||||
if (!dateTimeString) return "Unknown"
|
||||
var parts = dateTimeString.split(' ')
|
||||
if (!dateTimeString) {
|
||||
return "Unknown"
|
||||
}
|
||||
const parts = dateTimeString.split(' ')
|
||||
if (parts.length >= 2) {
|
||||
return parts[0] + " " + parts[1].split('.')[0]
|
||||
}
|
||||
@@ -9,8 +9,7 @@ Rectangle {
|
||||
|
||||
height: 80
|
||||
radius: Theme.cornerRadius
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
|
||||
Theme.surfaceContainer.b, 0.95)
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
|
||||
border.color: Theme.primary
|
||||
border.width: 2
|
||||
opacity: showHints ? 1 : 0
|
||||
@@ -6,6 +6,7 @@ import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import qs.Modals.FileBrowser
|
||||
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Modals.FileBrowser
|
||||
import qs.Modules.Settings
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Effects
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Modals
|
||||
import qs.Modals.FileBrowser
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Modals
|
||||
import qs.Modals.FileBrowser
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ StyledText {
|
||||
property int weight: filled ? 500 : 400
|
||||
|
||||
font.family: "Material Symbols Rounded"
|
||||
font.pixelSize: Appearance.fontSize.normal
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: weight
|
||||
color: Theme.surfaceText
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -27,17 +27,15 @@ StyledText {
|
||||
|
||||
Behavior on fill {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.quick
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on weight {
|
||||
NumberAnimation {
|
||||
duration: Appearance.anim.durations.quick
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user