mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
settings: redesign
This commit is contained in:
296
Modals/FileBrowserModal.qml
Normal file
296
Modals/FileBrowserModal.qml
Normal file
@@ -0,0 +1,296 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtCore
|
||||
import Qt.labs.folderlistmodel
|
||||
import Quickshell.Io
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
DankModal {
|
||||
id: fileBrowserModal
|
||||
|
||||
signal fileSelected(string path)
|
||||
|
||||
property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)
|
||||
property string currentPath: ""
|
||||
property var fileExtensions: ["*.*"]
|
||||
property string browserTitle: "Select File"
|
||||
property string browserIcon: "folder_open"
|
||||
property string browserType: "generic" // "wallpaper" or "profile" for last path memory
|
||||
|
||||
FolderListModel {
|
||||
id: folderModel
|
||||
showDirsFirst: true
|
||||
showDotAndDotDot: false
|
||||
showHidden: false
|
||||
nameFilters: fileExtensions
|
||||
showFiles: true
|
||||
showDirs: true
|
||||
folder: currentPath ? "file://" + currentPath : "file://" + homeDir
|
||||
}
|
||||
|
||||
function isImageFile(fileName) {
|
||||
if (!fileName) return false
|
||||
var ext = fileName.toLowerCase().split('.').pop()
|
||||
return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext)
|
||||
}
|
||||
|
||||
function getLastPath() {
|
||||
var lastPath = "";
|
||||
if (browserType === "wallpaper") {
|
||||
lastPath = Prefs.wallpaperLastPath;
|
||||
} else if (browserType === "profile") {
|
||||
lastPath = Prefs.profileLastPath;
|
||||
}
|
||||
|
||||
// Check if last path exists, otherwise use home
|
||||
if (lastPath && lastPath !== "") {
|
||||
// TODO: Could add directory existence check here
|
||||
return lastPath;
|
||||
}
|
||||
return homeDir;
|
||||
}
|
||||
|
||||
function saveLastPath(path) {
|
||||
if (browserType === "wallpaper") {
|
||||
Prefs.wallpaperLastPath = path;
|
||||
} else if (browserType === "profile") {
|
||||
Prefs.profileLastPath = path;
|
||||
}
|
||||
Prefs.saveSettings();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentPath = getLastPath();
|
||||
}
|
||||
|
||||
width: 800
|
||||
height: 600
|
||||
keyboardFocus: "ondemand"
|
||||
enableShadow: true
|
||||
visible: false
|
||||
|
||||
onBackgroundClicked: visible = false
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
var startPath = getLastPath();
|
||||
currentPath = startPath;
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentPathChanged: {
|
||||
// Path changed, model will update automatically
|
||||
}
|
||||
|
||||
function navigateUp() {
|
||||
var path = currentPath;
|
||||
|
||||
// Don't go above home directory
|
||||
if (path === homeDir) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lastSlash = path.lastIndexOf('/');
|
||||
if (lastSlash > 0) {
|
||||
var newPath = path.substring(0, lastSlash);
|
||||
if (newPath.startsWith(homeDir)) {
|
||||
currentPath = newPath;
|
||||
saveLastPath(newPath);
|
||||
} else {
|
||||
currentPath = homeDir;
|
||||
saveLastPath(homeDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function navigateTo(path) {
|
||||
currentPath = path;
|
||||
saveLastPath(path); // Save the path when navigating
|
||||
}
|
||||
|
||||
content: Component {
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Header
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
DankIcon {
|
||||
name: browserIcon
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: browserTitle
|
||||
font.pixelSize: Theme.fontSizeXLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
// Close button positioned at right
|
||||
DankActionButton {
|
||||
circular: false
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||
onClicked: fileBrowserModal.visible = false
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
// Current path display and navigation
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledRect {
|
||||
width: 32
|
||||
height: 32
|
||||
radius: Theme.cornerRadius
|
||||
color: mouseArea.containsMouse && currentPath !== homeDir ? Theme.surfaceVariant : "transparent"
|
||||
opacity: currentPath !== homeDir ? 1.0 : 0.0
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "arrow_back"
|
||||
size: Theme.iconSizeSmall
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: currentPath !== homeDir
|
||||
cursorShape: currentPath !== homeDir ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
enabled: currentPath !== homeDir
|
||||
onClicked: navigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Current folder: " + fileBrowserModal.currentPath
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width - 40 - Theme.spacingS
|
||||
elide: Text.ElideMiddle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
maximumLineCount: 1
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
}
|
||||
|
||||
// File grid
|
||||
ScrollView {
|
||||
width: parent.width
|
||||
height: parent.height - 80
|
||||
clip: true
|
||||
|
||||
GridView {
|
||||
id: fileGrid
|
||||
|
||||
cellWidth: 150
|
||||
cellHeight: 130
|
||||
cacheBuffer: 260 // Only cache ~2 rows worth of items
|
||||
|
||||
model: folderModel
|
||||
|
||||
delegate: StyledRect {
|
||||
id: delegateRoot
|
||||
|
||||
required property bool fileIsDir
|
||||
required property string filePath
|
||||
required property string fileName
|
||||
required property url fileURL
|
||||
|
||||
width: 140
|
||||
height: 120
|
||||
radius: Theme.cornerRadius
|
||||
color: mouseArea.containsMouse ? Theme.surfaceVariant : "transparent"
|
||||
border.color: Theme.outline
|
||||
border.width: mouseArea.containsMouse ? 1 : 0
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
// Image preview or folder icon
|
||||
Item {
|
||||
width: 80
|
||||
height: 60
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
CachingImage {
|
||||
anchors.fill: parent
|
||||
imagePath: !delegateRoot.fileIsDir ? delegateRoot.filePath : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: !delegateRoot.fileIsDir && isImageFile(delegateRoot.fileName)
|
||||
maxCacheSize: 80
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "description"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: !delegateRoot.fileIsDir && !isImageFile(delegateRoot.fileName)
|
||||
}
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "folder"
|
||||
size: Theme.iconSizeLarge
|
||||
color: Theme.primary
|
||||
visible: delegateRoot.fileIsDir
|
||||
}
|
||||
}
|
||||
|
||||
// File name
|
||||
StyledText {
|
||||
text: delegateRoot.fileName || ""
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
width: 120
|
||||
elide: Text.ElideMiddle
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
maximumLineCount: 2
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (delegateRoot.fileIsDir) {
|
||||
navigateTo(delegateRoot.filePath);
|
||||
} else {
|
||||
fileSelected(delegateRoot.filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,31 +77,31 @@ DankModal {
|
||||
anchors.margins: Theme.spacingXL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
height: 40
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "System Monitor"
|
||||
font.pixelSize: Theme.fontSizeLarge + 4
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width - 280
|
||||
height: 1
|
||||
Layout.fillWidth: true // Spacer to push close button to the right
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: SysMonitorService.processes.length + " processes"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
width: Math.min(implicitWidth, 120)
|
||||
elide: Text.ElideRight
|
||||
// Close button
|
||||
DankActionButton {
|
||||
circular: false
|
||||
iconName: "close"
|
||||
iconSize: Theme.iconSize - 4
|
||||
iconColor: Theme.surfaceText
|
||||
hoverColor: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
|
||||
onClicked: processListModal.hide()
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ DankModal {
|
||||
width: 650
|
||||
height: 750
|
||||
keyboardFocus: "ondemand"
|
||||
enableShadow: true
|
||||
onBackgroundClicked: {
|
||||
settingsVisible = false;
|
||||
}
|
||||
@@ -101,64 +100,54 @@ DankModal {
|
||||
width: parent.width
|
||||
height: parent.height - settingsTabBar.height
|
||||
|
||||
// Personalization Tab
|
||||
Loader {
|
||||
// Content container with proper padding
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 0
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
PersonalizationTab {}
|
||||
}
|
||||
}
|
||||
|
||||
// Time & Weather Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 1
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
Column {
|
||||
spacing: Theme.spacingL
|
||||
topPadding: Theme.spacingM
|
||||
|
||||
ClockTab {
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: Theme.spacingL
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
WeatherTab {
|
||||
width: parent.width
|
||||
}
|
||||
anchors.margins: Theme.spacingL
|
||||
color: "transparent"
|
||||
|
||||
// Personalization Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 0
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
PersonalizationTab {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// System Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 2
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
SystemTab {}
|
||||
|
||||
// Time & Weather Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 1
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
TimeWeatherTab {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Appearance Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 3
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
AppearanceTab {}
|
||||
|
||||
// System Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 2
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
WidgetsTab {}
|
||||
}
|
||||
}
|
||||
|
||||
// Appearance Tab
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: settingsTabBar.currentIndex === 3
|
||||
visible: active
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
AppearanceTab {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user