1
0
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:
bbedward
2025-09-03 00:00:25 -04:00
parent 93da303967
commit ae6a1b77c2
13 changed files with 354 additions and 475 deletions

View File

@@ -34,8 +34,7 @@ Item {
clearConfirmDialog.show("Clear All History?", "This will permanently delete all clipboard history.", function () { clearConfirmDialog.show("Clear All History?", "This will permanently delete all clipboard history.", function () {
modal.clearAll() modal.clearAll()
modal.hide() modal.hide()
}, function () {} // No action on cancel }, function () {})
)
} }
onCloseClicked: modal.hide() onCloseClicked: modal.hide()
} }

View File

@@ -7,7 +7,7 @@ import Quickshell.Io
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modals.Clipboard import qs.Modals
DankModal { DankModal {
id: clipboardHistoryModal id: clipboardHistoryModal
@@ -170,6 +170,7 @@ DankModal {
property alias filteredClipboardModel: filteredClipboardModel property alias filteredClipboardModel: filteredClipboardModel
property alias clipboardModel: clipboardModel property alias clipboardModel: clipboardModel
property var confirmDialog: clearConfirmDialog
ListModel { ListModel {
id: clipboardModel id: clipboardModel
@@ -209,7 +210,7 @@ DankModal {
ClipboardContent { ClipboardContent {
modal: clipboardHistoryModal modal: clipboardHistoryModal
filteredModel: filteredClipboardModel filteredModel: filteredClipboardModel
clearConfirmDialog: clipboardHistoryModal.clearConfirmDialog clearConfirmDialog: clipboardHistoryModal.confirmDialog
} }
} }
} }

View File

@@ -1,9 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Io
import qs.Common import qs.Common
import qs.Services
import qs.Widgets import qs.Widgets
DankModal { DankModal {
@@ -14,10 +10,9 @@ DankModal {
property string confirmButtonText: "Confirm" property string confirmButtonText: "Confirm"
property string cancelButtonText: "Cancel" property string cancelButtonText: "Cancel"
property color confirmButtonColor: Theme.primary property color confirmButtonColor: Theme.primary
property var onConfirm: function() {} property var onConfirm: function () {}
property var onCancel: function() {} property var onCancel: function () {}
property int selectedButton: -1
property int selectedButton: -1 // -1 = none, 0 = Cancel, 1 = Confirm
property bool keyboardNavigation: false property bool keyboardNavigation: false
function show(title, message, onConfirmCallback, onCancelCallback) { function show(title, message, onConfirmCallback, onCancelCallback) {
@@ -26,33 +21,36 @@ DankModal {
confirmButtonText = "Confirm" confirmButtonText = "Confirm"
cancelButtonText = "Cancel" cancelButtonText = "Cancel"
confirmButtonColor = Theme.primary confirmButtonColor = Theme.primary
onConfirm = onConfirmCallback || function() {} onConfirm = onConfirmCallback || (() => {})
onCancel = onCancelCallback || function() {} onCancel = onCancelCallback || (() => {})
selectedButton = -1 selectedButton = -1
keyboardNavigation = false keyboardNavigation = false
open() open()
} }
function showWithOptions(options) { function showWithOptions(options) {
confirmTitle = options.title || "" confirmTitle = options.title || ""
confirmMessage = options.message || "" confirmMessage = options.message || ""
confirmButtonText = options.confirmText || "Confirm" confirmButtonText = options.confirmText || "Confirm"
cancelButtonText = options.cancelText || "Cancel" cancelButtonText = options.cancelText || "Cancel"
confirmButtonColor = options.confirmColor || Theme.primary confirmButtonColor = options.confirmColor || Theme.primary
onConfirm = options.onConfirm || function() {} onConfirm = options.onConfirm || (() => {})
onCancel = options.onCancel || function() {} onCancel = options.onCancel || (() => {})
selectedButton = -1 selectedButton = -1
keyboardNavigation = false keyboardNavigation = false
open() open()
} }
function selectButton() { function selectButton() {
close()
if (selectedButton === 0) { if (selectedButton === 0) {
close() if (onCancel) {
if (onCancel) onCancel() onCancel()
}
} else { } else {
close() if (onConfirm) {
if (onConfirm) onConfirm() onConfirm()
}
} }
} }
@@ -64,18 +62,22 @@ DankModal {
shouldHaveFocus: true shouldHaveFocus: true
onBackgroundClicked: { onBackgroundClicked: {
close() close()
if (onCancel) onCancel() if (onCancel) {
onCancel()
}
} }
onOpened: { onOpened: {
modalFocusScope.forceActiveFocus() modalFocusScope.forceActiveFocus()
modalFocusScope.focus = true modalFocusScope.focus = true
shouldHaveFocus = true shouldHaveFocus = true
} }
modalFocusScope.Keys.onPressed: function(event) { modalFocusScope.Keys.onPressed: function (event) {
switch (event.key) { switch (event.key) {
case Qt.Key_Escape: case Qt.Key_Escape:
close() close()
if (onCancel) onCancel() if (onCancel) {
onCancel()
}
event.accepted = true event.accepted = true
break break
case Qt.Key_Left: case Qt.Key_Left:
@@ -148,12 +150,13 @@ DankModal {
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (keyboardNavigation && selectedButton === 0) if (keyboardNavigation && selectedButton === 0) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) 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 return Theme.surfacePressed
else } else {
return Theme.surfaceVariantAlpha return Theme.surfaceVariantAlpha
}
} }
border.color: (keyboardNavigation && selectedButton === 0) ? Theme.primary : "transparent" border.color: (keyboardNavigation && selectedButton === 0) ? Theme.primary : "transparent"
border.width: (keyboardNavigation && selectedButton === 0) ? 1 : 0 border.width: (keyboardNavigation && selectedButton === 0) ? 1 : 0
@@ -177,7 +180,6 @@ DankModal {
selectButton() selectButton()
} }
} }
} }
Rectangle { Rectangle {
@@ -185,13 +187,14 @@ DankModal {
height: 40 height: 40
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
let baseColor = confirmButtonColor const baseColor = confirmButtonColor
if (keyboardNavigation && selectedButton === 1) if (keyboardNavigation && selectedButton === 1) {
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 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) return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 0.9)
else } else {
return baseColor return baseColor
}
} }
border.color: (keyboardNavigation && selectedButton === 1) ? "white" : "transparent" border.color: (keyboardNavigation && selectedButton === 1) ? "white" : "transparent"
border.width: (keyboardNavigation && selectedButton === 1) ? 1 : 0 border.width: (keyboardNavigation && selectedButton === 1) ? 1 : 0
@@ -215,15 +218,9 @@ DankModal {
selectButton() selectButton()
} }
} }
} }
} }
} }
} }
} }
} }

View File

@@ -27,7 +27,6 @@ PanelWindow {
property real borderWidth: 1 property real borderWidth: 1
property real cornerRadius: Theme.cornerRadius property real cornerRadius: Theme.cornerRadius
property bool enableShadow: false property bool enableShadow: false
// Expose the focusScope for external access
property alias modalFocusScope: focusScope property alias modalFocusScope: focusScope
property bool shouldBeVisible: false property bool shouldBeVisible: false
property bool shouldHaveFocus: shouldBeVisible property bool shouldHaveFocus: shouldBeVisible
@@ -38,15 +37,6 @@ PanelWindow {
signal dialogClosed signal dialogClosed
signal backgroundClicked signal backgroundClicked
Connections {
target: ModalManager
function onCloseAllModalsExcept(excludedModal) {
if (excludedModal !== root && !allowStacking && shouldBeVisible) {
close()
}
}
}
function open() { function open() {
ModalManager.openModal(root) ModalManager.openModal(root)
closeTimer.stop() closeTimer.stop()
@@ -61,10 +51,11 @@ PanelWindow {
} }
function toggle() { function toggle() {
if (shouldBeVisible) if (shouldBeVisible) {
close() close()
else } else {
open() open()
}
} }
visible: shouldBeVisible visible: shouldBeVisible
@@ -84,6 +75,16 @@ PanelWindow {
} }
} }
Connections {
function onCloseAllModalsExcept(excludedModal) {
if (excludedModal !== root && !allowStacking && shouldBeVisible) {
close()
}
}
target: ModalManager
}
Timer { Timer {
id: closeTimer id: closeTimer
@@ -112,13 +113,10 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
enabled: root.closeOnBackgroundClick enabled: root.closeOnBackgroundClick
onClicked: mouse => { onClicked: mouse => {
var localPos = mapToItem(contentContainer, const localPos = mapToItem(contentContainer, mouse.x, mouse.y)
mouse.x, mouse.y) if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height) {
if (localPos.x < 0 root.backgroundClicked()
|| localPos.x > contentContainer.width }
|| localPos.y < 0
|| localPos.y > contentContainer.height)
root.backgroundClicked()
} }
} }
@@ -137,19 +135,20 @@ PanelWindow {
height: root.height height: root.height
anchors.centerIn: positioning === "center" ? parent : undefined anchors.centerIn: positioning === "center" ? parent : undefined
x: { x: {
if (positioning === "top-right") if (positioning === "top-right") {
return Math.max(Theme.spacingL, return Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL)
root.screenWidth - width - Theme.spacingL) } else if (positioning === "custom") {
else if (positioning === "custom")
return root.customPosition.x return root.customPosition.x
return 0 // Will be overridden by anchors.centerIn when positioning === "center" }
return 0
} }
y: { y: {
if (positioning === "top-right") if (positioning === "top-right") {
return Theme.barHeight + Theme.spacingXS return Theme.barHeight + Theme.spacingXS
else if (positioning === "custom") } else if (positioning === "custom") {
return root.customPosition.y return root.customPosition.y
return 0 // Will be overridden by anchors.centerIn when positioning === "center" }
return 0
} }
color: root.backgroundColor color: root.backgroundColor
radius: root.cornerRadius radius: root.cornerRadius
@@ -157,12 +156,7 @@ PanelWindow {
border.width: root.borderWidth border.width: root.borderWidth
layer.enabled: root.enableShadow layer.enabled: root.enableShadow
opacity: root.shouldBeVisible ? 1 : 0 opacity: root.shouldBeVisible ? 1 : 0
scale: { scale: root.animationType === "scale" ? (root.shouldBeVisible ? 1 : 0.9) : 1
if (root.animationType === "scale")
return root.shouldBeVisible ? 1 : 0.9
return 1
}
transform: root.animationType === "slide" ? slideTransform : null transform: root.animationType === "slide" ? slideTransform : null
Translate { Translate {
@@ -214,28 +208,25 @@ PanelWindow {
visible: root.visible // Only active when the modal is visible visible: root.visible // Only active when the modal is visible
focus: root.visible focus: root.visible
Keys.onEscapePressed: event => { Keys.onEscapePressed: event => {
if (root.closeOnEscapeKey if (root.closeOnEscapeKey && shouldHaveFocus) {
&& shouldHaveFocus) {
root.close() root.close()
event.accepted = true event.accepted = true
} }
} }
onVisibleChanged: { onVisibleChanged: {
if (visible && shouldHaveFocus) if (visible && shouldHaveFocus) {
Qt.callLater(function () { Qt.callLater(() => focusScope.forceActiveFocus())
focusScope.forceActiveFocus() }
})
} }
Connections { Connections {
target: root
function onShouldHaveFocusChanged() { function onShouldHaveFocusChanged() {
if (shouldHaveFocus && visible) { if (shouldHaveFocus && visible) {
Qt.callLater(function () { Qt.callLater(() => focusScope.forceActiveFocus())
focusScope.forceActiveFocus()
})
} }
} }
target: root
} }
} }
} }

View File

@@ -1,20 +1,16 @@
import Qt.labs.folderlistmodel
import QtCore
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtCore
import Qt.labs.folderlistmodel
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Modals
import qs.Widgets import qs.Widgets
DankModal { DankModal {
id: fileBrowserModal 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 string currentPath: ""
property var fileExtensions: ["*.*"] property var fileExtensions: ["*.*"]
property alias filterExtensions: fileBrowserModal.fileExtensions property alias filterExtensions: fileBrowserModal.fileExtensions
@@ -25,39 +21,29 @@ DankModal {
property int selectedIndex: -1 property int selectedIndex: -1
property bool keyboardNavigationActive: false property bool keyboardNavigationActive: false
property bool backButtonFocused: false property bool backButtonFocused: false
property bool saveMode: false // Enable save functionality property bool saveMode: false // Enable save functionality
property string defaultFileName: "" // Default filename for save mode 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 { signal fileSelected(string path)
id: folderModel
showDirsFirst: true
showDotAndDotDot: false
showHidden: fileBrowserModal.showHiddenFiles
nameFilters: fileExtensions
showFiles: true
showDirs: true
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
}
function isImageFile(fileName) { function isImageFile(fileName) {
if (!fileName) if (!fileName) {
return false return false
var ext = fileName.toLowerCase().split('.').pop() }
const ext = fileName.toLowerCase().split('.').pop()
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext) return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
} }
function getLastPath() { function getLastPath() {
var lastPath = "" const lastPath = browserType === "wallpaper" ? SessionData.wallpaperLastPath : browserType === "profile" ? SessionData.profileLastPath : ""
if (browserType === "wallpaper") { return (lastPath && lastPath !== "") ? lastPath : homeDir
lastPath = SessionData.wallpaperLastPath
} else if (browserType === "profile") {
lastPath = SessionData.profileLastPath
}
if (lastPath && lastPath !== "") {
return lastPath
}
return homeDir
} }
function saveLastPath(path) { function saveLastPath(path) {
@@ -68,86 +54,122 @@ DankModal {
} }
} }
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: { Component.onCompleted: {
currentPath = getLastPath() currentPath = getLastPath()
} }
width: 800 width: 800
height: 600 height: 600
enableShadow: true enableShadow: true
visible: false visible: false
onBackgroundClicked: close() onBackgroundClicked: close()
onOpened: { onOpened: {
modalFocusScope.forceActiveFocus() modalFocusScope.forceActiveFocus()
} }
modalFocusScope.Keys.onPressed: function (event) {
modalFocusScope.Keys.onPressed: function(event) {
keyboardController.handleKey(event) keyboardController.handleKey(event)
} }
onVisibleChanged: { onVisibleChanged: {
if (visible) { if (visible) {
var startPath = getLastPath() currentPath = getLastPath()
currentPath = startPath
selectedIndex = -1 selectedIndex = -1
keyboardNavigationActive = false keyboardNavigationActive = false
backButtonFocused = false backButtonFocused = false
} }
} }
onCurrentPathChanged: { onCurrentPathChanged: {
selectedFilePath = "" selectedFilePath = ""
selectedFileName = "" selectedFileName = ""
selectedFileIsDir = false selectedFileIsDir = false
} }
onSelectedIndexChanged: { onSelectedIndexChanged: {
// Update selected file data when index changes
if (selectedIndex >= 0 && folderModel && selectedIndex < folderModel.count) { 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 = "" selectedFilePath = ""
selectedFileName = "" selectedFileName = ""
selectedFileIsDir = false selectedFileIsDir = false
} }
} }
// Function to update file data from delegates FolderListModel {
function setSelectedFileData(path, name, isDir) { id: folderModel
selectedFilePath = path
selectedFileName = name showDirsFirst: true
selectedFileIsDir = isDir showDotAndDotDot: false
showHidden: fileBrowserModal.showHiddenFiles
nameFilters: fileExtensions
showFiles: true
showDirs: true
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
} }
QtObject { QtObject {
id: keyboardController id: keyboardController
property int totalItems: folderModel.count 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) { function handleKey(event) {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {
close() close()
event.accepted = true event.accepted = true
return return
} }
// F10 toggles keyboard hints // F10 toggles keyboard hints
if (event.key === Qt.Key_F10) { if (event.key === Qt.Key_F10) {
showKeyboardHints = !showKeyboardHints showKeyboardHints = !showKeyboardHints
event.accepted = true event.accepted = true
return return
} }
// F1 or I key for file information // F1 or I key for file information
if (event.key === Qt.Key_F1 || event.key === Qt.Key_I) { if (event.key === Qt.Key_F1 || event.key === Qt.Key_I) {
showFileInfo = !showFileInfo showFileInfo = !showFileInfo
event.accepted = true event.accepted = true
return return
} }
// Alt+Left or Backspace to go back // Alt+Left or Backspace to go back
if ((event.modifiers & Qt.AltModifier && event.key === Qt.Key_Left) || event.key === Qt.Key_Backspace) { if ((event.modifiers & Qt.AltModifier && event.key === Qt.Key_Left) || event.key === Qt.Key_Backspace) {
if (currentPath !== homeDir) { if (currentPath !== homeDir) {
@@ -156,7 +178,6 @@ DankModal {
} }
return return
} }
if (!keyboardNavigationActive) { if (!keyboardNavigationActive) {
if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down || event.key === Qt.Key_Right) { if (event.key === Qt.Key_Tab || event.key === Qt.Key_Down || event.key === Qt.Key_Right) {
keyboardNavigationActive = true keyboardNavigationActive = true
@@ -171,207 +192,124 @@ DankModal {
} }
return return
} }
switch (event.key) { switch (event.key) {
case Qt.Key_Tab: case Qt.Key_Tab:
if (backButtonFocused) { if (backButtonFocused) {
backButtonFocused = false backButtonFocused = false
selectedIndex = 0 selectedIndex = 0
} else if (selectedIndex < totalItems - 1) { } else if (selectedIndex < totalItems - 1) {
selectedIndex++ selectedIndex++
} else if (currentPath !== homeDir) { } else if (currentPath !== homeDir) {
backButtonFocused = true backButtonFocused = true
selectedIndex = -1 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_Left:
if (backButtonFocused)
return
if (selectedIndex > 0) {
selectedIndex--
} else if (currentPath !== homeDir) {
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
break
case Qt.Key_Right:
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else if (selectedIndex < totalItems - 1) {
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)
} else if (selectedIndex >= gridColumns) {
// Move up one row
selectedIndex -= gridColumns
} else if (currentPath !== homeDir) {
// At top row, go to back button
backButtonFocused = true
selectedIndex = -1
}
event.accepted = true
break
case Qt.Key_Down:
if (backButtonFocused) {
backButtonFocused = false
selectedIndex = 0
} else {
// Move down one row if possible
var newIndex = selectedIndex + gridColumns
if (newIndex < totalItems) {
selectedIndex = newIndex
} else { } else {
selectedIndex = 0 // 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
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_Left:
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 var col = selectedIndex % gridColumns
selectedIndex = Math.min(col, totalItems - 1) var targetIndex = lastRowStart + col
updateFileInfoForIndex(selectedIndex) if (targetIndex < totalItems && targetIndex > selectedIndex) {
} else if (selectedIndex >= gridColumns) { selectedIndex = targetIndex
// Move up one row
selectedIndex -= gridColumns
updateFileInfoForIndex(selectedIndex)
} else if (currentPath !== homeDir) {
// At top row, go to back button
backButtonFocused = true
selectedIndex = -1
}
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
var col = selectedIndex % gridColumns
var targetIndex = lastRowStart + col
if (targetIndex < totalItems && targetIndex > selectedIndex) {
selectedIndex = targetIndex
updateFileInfoForIndex(selectedIndex)
}
} }
} }
event.accepted = true }
break event.accepted = true
break
case Qt.Key_Return: case Qt.Key_Return:
case Qt.Key_Enter: case Qt.Key_Enter:
case Qt.Key_Space: case Qt.Key_Space:
if (backButtonFocused) { if (backButtonFocused)
navigateUp() 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 // Trigger selection by setting the grid's current index and using signal
fileBrowserModal.keyboardFileSelection(selectedIndex) fileBrowserModal.keyboardFileSelection(selectedIndex)
} event.accepted = true
event.accepted = true break
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 { Timer {
id: keyboardSelectionTimer id: keyboardSelectionTimer
interval: 1
property int targetIndex: -1 property int targetIndex: -1
interval: 1
onTriggered: { onTriggered: {
// Access the currently selected item through model role names // Access the currently selected item through model role names
// This will work because QML models expose role data // This will work because QML models expose role data
executeKeyboardSelection(targetIndex) executeKeyboardSelection(targetIndex)
} }
} }
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 { content: Component {
Item { Item {
anchors.fill: parent anchors.fill: parent
Column { Column {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingM anchors.margins: Theme.spacingM
@@ -405,7 +343,7 @@ DankModal {
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS spacing: Theme.spacingS
DankActionButton { DankActionButton {
circular: false circular: false
iconName: "help" iconName: "help"
@@ -414,7 +352,7 @@ DankModal {
hoverColor: Theme.surfacePressed hoverColor: Theme.surfacePressed
onClicked: fileBrowserModal.showKeyboardHints = !fileBrowserModal.showKeyboardHints onClicked: fileBrowserModal.showKeyboardHints = !fileBrowserModal.showKeyboardHints
} }
DankActionButton { DankActionButton {
circular: false circular: false
iconName: "close" iconName: "close"
@@ -434,9 +372,8 @@ DankModal {
width: 32 width: 32
height: 32 height: 32
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: (backButtonMouseArea.containsMouse || (backButtonFocused && keyboardNavigationActive)) color: (backButtonMouseArea.containsMouse || (backButtonFocused && keyboardNavigationActive)) && currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
&& currentPath !== homeDir ? Theme.surfaceVariant : "transparent" opacity: currentPath !== homeDir ? 1 : 0
opacity: currentPath !== homeDir ? 1.0 : 0.0
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -447,10 +384,10 @@ DankModal {
MouseArea { MouseArea {
id: backButtonMouseArea id: backButtonMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: currentPath !== homeDir hoverEnabled: currentPath !== homeDir
cursorShape: currentPath cursorShape: currentPath !== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
!== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: currentPath !== homeDir enabled: currentPath !== homeDir
onClicked: navigateUp() onClicked: navigateUp()
} }
@@ -478,19 +415,17 @@ DankModal {
cellWidth: 150 cellWidth: 150
cellHeight: 130 cellHeight: 130
cacheBuffer: 260 cacheBuffer: 260
model: folderModel model: folderModel
currentIndex: selectedIndex currentIndex: selectedIndex
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (keyboardNavigationActive && currentIndex >= 0) { if (keyboardNavigationActive && currentIndex >= 0)
positionViewAtIndex(currentIndex, GridView.Contain) positionViewAtIndex(currentIndex, GridView.Contain)
}
} }
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded policy: ScrollBar.AsNeeded
} }
ScrollBar.horizontal: ScrollBar { ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff policy: ScrollBar.AlwaysOff
} }
@@ -508,29 +443,27 @@ DankModal {
height: 120 height: 120
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (keyboardNavigationActive && delegateRoot.index === selectedIndex) { if (keyboardNavigationActive && delegateRoot.index === selectedIndex)
return Theme.surfacePressed return Theme.surfacePressed
}
return mouseArea.containsMouse ? Theme.surfaceVariant : "transparent" return mouseArea.containsMouse ? Theme.surfaceVariant : "transparent"
} }
border.color: keyboardNavigationActive && delegateRoot.index === selectedIndex ? Theme.primary : Theme.outline border.color: keyboardNavigationActive && delegateRoot.index === selectedIndex ? Theme.primary : Theme.outline
border.width: (mouseArea.containsMouse || (keyboardNavigationActive && delegateRoot.index === selectedIndex)) ? 1 : 0 border.width: (mouseArea.containsMouse || (keyboardNavigationActive && delegateRoot.index === selectedIndex)) ? 1 : 0
// Update file info when this item gets selected via keyboard or initially // Update file info when this item gets selected via keyboard or initially
Component.onCompleted: { Component.onCompleted: {
if (keyboardNavigationActive && delegateRoot.index === selectedIndex) { if (keyboardNavigationActive && delegateRoot.index === selectedIndex)
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir) setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
}
} }
// Watch for selectedIndex changes to update file info during keyboard navigation // Watch for selectedIndex changes to update file info during keyboard navigation
Connections { Connections {
target: fileBrowserModal
function onSelectedIndexChanged() { function onSelectedIndexChanged() {
if (keyboardNavigationActive && selectedIndex === delegateRoot.index) { if (keyboardNavigationActive && selectedIndex === delegateRoot.index)
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir) setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
}
} }
target: fileBrowserModal
} }
Column { Column {
@@ -555,8 +488,7 @@ DankModal {
name: "description" name: "description"
size: Theme.iconSizeLarge size: Theme.iconSizeLarge
color: Theme.primary color: Theme.primary
visible: !delegateRoot.fileIsDir visible: !delegateRoot.fileIsDir && !isImageFile(delegateRoot.fileName)
&& !isImageFile(delegateRoot.fileName)
} }
DankIcon { DankIcon {
@@ -583,35 +515,30 @@ DankModal {
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
// Update selected file info and index first // Update selected file info and index first
selectedIndex = delegateRoot.index selectedIndex = delegateRoot.index
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir) setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
if (delegateRoot.fileIsDir) { if (delegateRoot.fileIsDir) {
navigateTo(delegateRoot.filePath) navigateTo(delegateRoot.filePath)
} else { } else {
fileSelected(delegateRoot.filePath) fileSelected(delegateRoot.filePath)
fileBrowserModal.close() // Close modal after file selection fileBrowserModal.close() // Close modal after file selection
} }
} }
} }
// Handle keyboard selection // Handle keyboard selection
Connections { Connections {
target: fileBrowserModal
function onKeyboardSelectionRequestedChanged() { function onKeyboardSelectionRequestedChanged() {
if (fileBrowserModal.keyboardSelectionRequested && fileBrowserModal.keyboardSelectionIndex === delegateRoot.index) { if (fileBrowserModal.keyboardSelectionRequested && fileBrowserModal.keyboardSelectionIndex === delegateRoot.index) {
// Reset the flag first
fileBrowserModal.keyboardSelectionRequested = false fileBrowserModal.keyboardSelectionRequested = false
// Update selected file info and index first
selectedIndex = delegateRoot.index selectedIndex = delegateRoot.index
setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir) setSelectedFileData(delegateRoot.filePath, delegateRoot.fileName, delegateRoot.fileIsDir)
// Trigger the same action as mouse click
if (delegateRoot.fileIsDir) { if (delegateRoot.fileIsDir) {
navigateTo(delegateRoot.filePath) navigateTo(delegateRoot.filePath)
} else { } else {
@@ -620,89 +547,91 @@ DankModal {
} }
} }
} }
target: fileBrowserModal
} }
} }
} }
} }
// Save functionality - positioned at bottom in save mode
Row { Row {
id: saveRow id: saveRow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: Theme.spacingL anchors.margins: Theme.spacingL
height: saveMode ? 40 : 0 height: saveMode ? 40 : 0
visible: saveMode visible: saveMode
spacing: Theme.spacingM spacing: Theme.spacingM
DankTextField { DankTextField {
id: fileNameInput id: fileNameInput
width: parent.width - saveButton.width - Theme.spacingM width: parent.width - saveButton.width - Theme.spacingM
height: 36 height: 36
text: defaultFileName text: defaultFileName
placeholderText: "Enter filename..." placeholderText: "Enter filename..."
ignoreLeftRightKeys: false // Allow arrow key navigation ignoreLeftRightKeys: false
focus: saveMode // Auto-focus when in save mode focus: saveMode
Component.onCompleted: { Component.onCompleted: {
if (saveMode) { if (saveMode)
Qt.callLater(() => { Qt.callLater(() => {
forceActiveFocus(); forceActiveFocus()
}); })
}
} }
onAccepted: { onAccepted: {
if (text.trim() !== "") { if (text.trim() !== "") {
var fullPath = currentPath + "/" + text.trim(); var fullPath = currentPath + "/" + text.trim()
fileSelected(fullPath); fileSelected(fullPath)
fileBrowserModal.close(); fileBrowserModal.close()
} }
} }
} }
StyledRect { StyledRect {
id: saveButton id: saveButton
width: 80 width: 80
height: 36 height: 36
color: fileNameInput.text.trim() !== "" ? Theme.primary : Theme.surfaceVariant color: fileNameInput.text.trim() !== "" ? Theme.primary : Theme.surfaceVariant
radius: Theme.cornerRadius radius: Theme.cornerRadius
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
text: "Save" text: "Save"
color: fileNameInput.text.trim() !== "" ? Theme.primaryText : Theme.surfaceVariantText color: fileNameInput.text.trim() !== "" ? Theme.primaryText : Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
} }
StateLayer { StateLayer {
stateColor: Theme.primary stateColor: Theme.primary
cornerRadius: Theme.cornerRadius cornerRadius: Theme.cornerRadius
enabled: fileNameInput.text.trim() !== "" enabled: fileNameInput.text.trim() !== ""
onClicked: { onClicked: {
if (fileNameInput.text.trim() !== "") { if (fileNameInput.text.trim() !== "") {
var fullPath = currentPath + "/" + fileNameInput.text.trim(); var fullPath = currentPath + "/" + fileNameInput.text.trim()
fileSelected(fullPath); fileSelected(fullPath)
fileBrowserModal.close(); fileBrowserModal.close()
} }
} }
} }
} }
} }
FileBrowserKeyboardHints { KeyboardHints {
id: keyboardHints id: keyboardHints
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: Theme.spacingL anchors.margins: Theme.spacingL
showHints: fileBrowserModal.showKeyboardHints showHints: fileBrowserModal.showKeyboardHints
} }
FileBrowserFileInfo { FileInfo {
id: fileInfo id: fileInfo
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
anchors.margins: Theme.spacingL anchors.margins: Theme.spacingL
@@ -711,16 +640,15 @@ DankModal {
selectedIndex: fileBrowserModal.selectedIndex selectedIndex: fileBrowserModal.selectedIndex
sourceFolderModel: folderModel sourceFolderModel: folderModel
currentPath: fileBrowserModal.currentPath currentPath: fileBrowserModal.currentPath
// Bind directly to the modal's selected file properties
currentFileName: fileBrowserModal.selectedFileName currentFileName: fileBrowserModal.selectedFileName
currentFileIsDir: fileBrowserModal.selectedFileIsDir currentFileIsDir: fileBrowserModal.selectedFileIsDir
currentFileExtension: { currentFileExtension: {
if (fileBrowserModal.selectedFileIsDir || !fileBrowserModal.selectedFileName) return "" if (fileBrowserModal.selectedFileIsDir || !fileBrowserModal.selectedFileName)
return ""
var lastDot = fileBrowserModal.selectedFileName.lastIndexOf('.') var lastDot = fileBrowserModal.selectedFileName.lastIndexOf('.')
return lastDot > 0 ? fileBrowserModal.selectedFileName.substring(lastDot + 1).toLowerCase() : "" return lastDot > 0 ? fileBrowserModal.selectedFileName.substring(lastDot + 1).toLowerCase() : ""
} }
} }
} }
} }

View File

@@ -1,7 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtCore import QtCore
import Qt.labs.folderlistmodel
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
@@ -16,8 +14,7 @@ Rectangle {
height: 200 height: 200
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
Theme.surfaceContainer.b, 0.95)
border.color: Theme.secondary border.color: Theme.secondary
border.width: 2 border.width: 2
opacity: showFileInfo ? 1 : 0 opacity: showFileInfo ? 1 : 0
@@ -25,7 +22,7 @@ Rectangle {
onShowFileInfoChanged: { onShowFileInfoChanged: {
if (showFileInfo && currentFileName && currentPath) { if (showFileInfo && currentFileName && currentPath) {
var fullPath = currentPath + "/" + currentFileName const fullPath = currentPath + "/" + currentFileName
fileStatProcess.selectedFilePath = fullPath fileStatProcess.selectedFilePath = fullPath
fileStatProcess.running = true fileStatProcess.running = true
} }
@@ -37,64 +34,24 @@ Rectangle {
property string selectedFilePath: "" property string selectedFilePath: ""
property var fileStats: null property var fileStats: null
running: false running: false
stdout: StdioCollector { stdout: StdioCollector {
onStreamFinished: { onStreamFinished: {
if (text && text.trim()) { if (text && text.trim()) {
var parts = text.trim().split('|') const parts = text.trim().split('|')
if (parts.length >= 4) { if (parts.length >= 4) {
fileStatProcess.fileStats = { fileStatProcess.fileStats = {
modifiedTime: parts[0], "modifiedTime": parts[0],
permissions: parts[1], "permissions": parts[1],
size: parseInt(parts[2]) || 0, "size": parseInt(parts[2]) || 0,
fullPath: parts[3] "fullPath": parts[3]
} }
} }
} }
} }
} }
onExited: function(exitCode) {}
}
readonly property var currentFileData: { onExited: function (exitCode) {}
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"
}
} }
property string currentFileName: "" property string currentFileName: ""
@@ -103,7 +60,7 @@ Rectangle {
onCurrentFileNameChanged: { onCurrentFileNameChanged: {
if (showFileInfo && currentFileName && currentPath) { if (showFileInfo && currentFileName && currentPath) {
var fullPath = currentPath + "/" + currentFileName const fullPath = currentPath + "/" + currentFileName
if (fullPath !== fileStatProcess.selectedFilePath) { if (fullPath !== fileStatProcess.selectedFilePath) {
fileStatProcess.selectedFilePath = fullPath fileStatProcess.selectedFilePath = fullPath
fileStatProcess.running = true fileStatProcess.running = true
@@ -116,16 +73,16 @@ Rectangle {
fileStatProcess.selectedFilePath = filePath fileStatProcess.selectedFilePath = filePath
currentFileName = fileName || "" currentFileName = fileName || ""
currentFileIsDir = isDirectory || false currentFileIsDir = isDirectory || false
var ext = "" let ext = ""
if (!isDirectory && fileName) { if (!isDirectory && fileName) {
var lastDot = fileName.lastIndexOf('.') const lastDot = fileName.lastIndexOf('.')
if (lastDot > 0) { if (lastDot > 0) {
ext = fileName.substring(lastDot + 1).toLowerCase() ext = fileName.substring(lastDot + 1).toLowerCase()
} }
} }
currentFileExtension = ext currentFileExtension = ext
if (showFileInfo) { if (showFileInfo) {
fileStatProcess.running = true fileStatProcess.running = true
} }
@@ -135,27 +92,27 @@ Rectangle {
readonly property var currentFileDisplayData: { readonly property var currentFileDisplayData: {
if (selectedIndex < 0 || !sourceFolderModel) { if (selectedIndex < 0 || !sourceFolderModel) {
return { return {
exists: false, "exists": false,
name: "No selection", "name": "No selection",
type: "", "type": "",
size: "", "size": "",
modified: "", "modified": "",
permissions: "", "permissions": "",
extension: "", "extension": "",
position: "N/A" "position": "N/A"
} }
} }
var hasValidFile = currentFileName !== "" const hasValidFile = currentFileName !== ""
return { return {
exists: hasValidFile, "exists": hasValidFile,
name: hasValidFile ? currentFileName : "Loading...", "name": hasValidFile ? currentFileName : "Loading...",
type: currentFileIsDir ? "Directory" : "File", "type": currentFileIsDir ? "Directory" : "File",
size: fileStatProcess.fileStats ? formatFileSize(fileStatProcess.fileStats.size) : "Calculating...", "size": fileStatProcess.fileStats ? formatFileSize(fileStatProcess.fileStats.size) : "Calculating...",
modified: fileStatProcess.fileStats ? formatDateTime(fileStatProcess.fileStats.modifiedTime) : "Loading...", "modified": fileStatProcess.fileStats ? formatDateTime(fileStatProcess.fileStats.modifiedTime) : "Loading...",
permissions: fileStatProcess.fileStats ? fileStatProcess.fileStats.permissions : "Loading...", "permissions": fileStatProcess.fileStats ? fileStatProcess.fileStats.permissions : "Loading...",
extension: currentFileExtension, "extension": currentFileExtension,
position: sourceFolderModel ? ((selectedIndex + 1) + " of " + sourceFolderModel.count) : "N/A" "position": sourceFolderModel ? ((selectedIndex + 1) + " of " + sourceFolderModel.count) : "N/A"
} }
} }
@@ -251,16 +208,20 @@ Rectangle {
} }
function formatFileSize(bytes) { function formatFileSize(bytes) {
if (bytes === 0 || !bytes) return "0 B" if (bytes === 0 || !bytes) {
var k = 1024 return "0 B"
var sizes = ['B', 'KB', 'MB', 'GB', 'TB'] }
var i = Math.floor(Math.log(bytes) / Math.log(k)) 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] return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
} }
function formatDateTime(dateTimeString) { function formatDateTime(dateTimeString) {
if (!dateTimeString) return "Unknown" if (!dateTimeString) {
var parts = dateTimeString.split(' ') return "Unknown"
}
const parts = dateTimeString.split(' ')
if (parts.length >= 2) { if (parts.length >= 2) {
return parts[0] + " " + parts[1].split('.')[0] return parts[0] + " " + parts[1].split('.')[0]
} }
@@ -273,4 +234,4 @@ Rectangle {
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -9,8 +9,7 @@ Rectangle {
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
Theme.surfaceContainer.b, 0.95)
border.color: Theme.primary border.color: Theme.primary
border.width: 2 border.width: 2
opacity: showHints ? 1 : 0 opacity: showHints ? 1 : 0
@@ -48,4 +47,4 @@ Rectangle {
easing.type: Theme.standardEasing easing.type: Theme.standardEasing
} }
} }
} }

View File

@@ -6,6 +6,7 @@ import Quickshell.Io
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
import qs.Modals.FileBrowser
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound

View File

@@ -4,6 +4,7 @@ import QtQuick.Effects
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Modals.FileBrowser
import qs.Modules.Settings import qs.Modules.Settings
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets

View File

@@ -4,6 +4,7 @@ import QtQuick.Effects
import Quickshell import Quickshell
import qs.Common import qs.Common
import qs.Modals import qs.Modals
import qs.Modals.FileBrowser
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets

View File

@@ -4,6 +4,7 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import qs.Common import qs.Common
import qs.Modals import qs.Modals
import qs.Modals.FileBrowser
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets

View File

@@ -13,7 +13,7 @@ StyledText {
property int weight: filled ? 500 : 400 property int weight: filled ? 500 : 400
font.family: "Material Symbols Rounded" font.family: "Material Symbols Rounded"
font.pixelSize: Appearance.fontSize.normal font.pixelSize: Theme.fontSizeMedium
font.weight: weight font.weight: weight
color: Theme.surfaceText color: Theme.surfaceText
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@@ -27,17 +27,15 @@ StyledText {
Behavior on fill { Behavior on fill {
NumberAnimation { NumberAnimation {
duration: Appearance.anim.durations.quick duration: Theme.shortDuration
easing.type: Easing.BezierSpline easing.type: Theme.standardEasing
easing.bezierCurve: Appearance.anim.curves.standard
} }
} }
Behavior on weight { Behavior on weight {
NumberAnimation { NumberAnimation {
duration: Appearance.anim.durations.quick duration: Theme.shortDuration
easing.type: Easing.BezierSpline easing.type: Theme.standardEasing
easing.bezierCurve: Appearance.anim.curves.standard
} }
} }
} }

View File

@@ -5,6 +5,7 @@ import Quickshell.Io
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
import qs.Modals import qs.Modals
import qs.Modals.Clipboard
import qs.Modules import qs.Modules
import qs.Modules.AppDrawer import qs.Modules.AppDrawer
import qs.Modules.CentcomCenter import qs.Modules.CentcomCenter