1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-25 05:52:50 -05:00

Compare commits

..

26 Commits

Author SHA1 Message Date
bbedward
db28879185 Reparations for drag and drop control center edits 2025-09-25 21:29:14 -04:00
purian23
92bb5b90aa Merge branch 'master' of github.com:AvengeMedia/DankMaterialShell 2025-09-25 19:32:42 -04:00
purian23
a207ed74ff refactor: Add Drag & Drop to Control Center 2025-09-25 19:29:36 -04:00
bbedward
9d224113c4 use a matugen template for dms-colors.json 2025-09-25 18:27:25 -04:00
bbedward
934f4b2210 ControlCenter styling consistency fixes 2025-09-25 18:19:07 -04:00
bbedward
a6a41d4de1 Re-work theme approach to watch a file from matugen-worker 2025-09-25 16:49:57 -04:00
bbedward
185ee20f2d Fix idle monitor creation 2025-09-25 16:30:46 -04:00
bbedward
778b960130 Fix hibernate manual option 2025-09-25 16:11:18 -04:00
bbedward
184938d10a Merge branch 'master' of github.com:bbedward/DankMaterialShell 2025-09-25 15:59:21 -04:00
bbedward
25565af5f9 Some styling consistencies 2025-09-25 15:57:56 -04:00
purian23
0bd9a4f860 fix Control Center IPC via Escape key 2025-09-25 14:52:21 -04:00
purian23
fe64dd1dea Add IPC for Control Center 2025-09-25 14:23:45 -04:00
bbedward
a4a59fd586 Theme consistency overhaul:
- Add surface shift option, start from surface by default (previously
  was surfaceContainer). Old colors can be attained by changing it back
to "container" in theme colors
- Remove borders on surface elements, mostly
- Fix popup distances
- Use surfaceContainer/sch by default on widgets
2025-09-25 12:46:37 -04:00
bbedward
7ccd2d9418 Add random transition effect 2025-09-25 09:06:38 -04:00
bbedward
974dd70a06 Correct top bar bg color 2025-09-25 08:36:23 -04:00
sam
1690e4f63b feat: expose matugen palette selection (#251)
Looks good, thanks!
2025-09-25 08:27:54 -04:00
bbedward
ec75ef468b Remove obsolete setting 2025-09-24 19:15:37 -04:00
bbedward
a57c1e6451 Fix edit mode of multiple disk usage widgets in control center 2025-09-24 18:13:36 -04:00
bbedward
bdc79a13a9 just show mount path - wasted space = less 2025-09-24 18:09:36 -04:00
bbedward
b893694977 Add disk usage component for TopBar and ControlCenter 2025-09-24 18:06:46 -04:00
bbedward
9be7d44765 disable matugen env var support, also dont reload ghostty if not
configured with dms theme
2025-09-24 17:09:15 -04:00
bbedward
3f8d8ca379 Update ghostty readme blurb to disable annoying popups 2025-09-24 16:39:33 -04:00
bbedward
e50c3cceeb Add grouped apps option to the dock 2025-09-24 16:15:38 -04:00
bbedward
14e648911d Hyprland: fix focused app logic for empty workspaces 2025-09-24 15:08:22 -04:00
bbedward
3c42a618d4 auto-reload ghostty config on matugen generation 2025-09-24 14:38:45 -04:00
lonerorz
bed2259944 Refactor workspaceSwitcher (#246)
* Refactor WorkspaceSwitcher

Implement async data loading, dynamic UI, and fix QML connection
warnings.

* Enhance WorkspaceSwitcher

Adjust width dynamically based on icon count for better space
utilization

* fix(WorkspaceSwitcher): correct ternary logic for placeholder workspaces
2025-09-24 14:36:38 -04:00
105 changed files with 3063 additions and 1729 deletions

View File

@@ -47,6 +47,8 @@ Singleton {
property string lastBrightnessDevice: "" property string lastBrightnessDevice: ""
property string launchPrefix: "" property string launchPrefix: ""
property string wallpaperTransition: "fade" property string wallpaperTransition: "fade"
readonly property var availableWallpaperTransitions: ["none", "fade", "wipe", "disc", "stripes", "iris bloom", "pixelate", "portal"]
property var includedTransitions: availableWallpaperTransitions.filter(t => t !== "none")
// Power management settings - AC Power // Power management settings - AC Power
property int acMonitorTimeout: 0 // Never property int acMonitorTimeout: 0 // Never
@@ -119,6 +121,7 @@ Singleton {
lastBrightnessDevice = settings.lastBrightnessDevice !== undefined ? settings.lastBrightnessDevice : "" lastBrightnessDevice = settings.lastBrightnessDevice !== undefined ? settings.lastBrightnessDevice : ""
launchPrefix = settings.launchPrefix !== undefined ? settings.launchPrefix : "" launchPrefix = settings.launchPrefix !== undefined ? settings.launchPrefix : ""
wallpaperTransition = settings.wallpaperTransition !== undefined ? settings.wallpaperTransition : "fade" wallpaperTransition = settings.wallpaperTransition !== undefined ? settings.wallpaperTransition : "fade"
includedTransitions = settings.includedTransitions !== undefined ? settings.includedTransitions : availableWallpaperTransitions.filter(t => t !== "none")
acMonitorTimeout = settings.acMonitorTimeout !== undefined ? settings.acMonitorTimeout : 0 acMonitorTimeout = settings.acMonitorTimeout !== undefined ? settings.acMonitorTimeout : 0
acLockTimeout = settings.acLockTimeout !== undefined ? settings.acLockTimeout : 0 acLockTimeout = settings.acLockTimeout !== undefined ? settings.acLockTimeout : 0
@@ -173,6 +176,7 @@ Singleton {
"lastBrightnessDevice": lastBrightnessDevice, "lastBrightnessDevice": lastBrightnessDevice,
"launchPrefix": launchPrefix, "launchPrefix": launchPrefix,
"wallpaperTransition": wallpaperTransition, "wallpaperTransition": wallpaperTransition,
"includedTransitions": includedTransitions,
"acMonitorTimeout": acMonitorTimeout, "acMonitorTimeout": acMonitorTimeout,
"acLockTimeout": acLockTimeout, "acLockTimeout": acLockTimeout,
"acSuspendTimeout": acSuspendTimeout, "acSuspendTimeout": acSuspendTimeout,
@@ -263,9 +267,6 @@ Singleton {
saveSettings() saveSettings()
if (typeof Theme !== "undefined") { if (typeof Theme !== "undefined") {
if (Theme.currentTheme === Theme.dynamic) {
Theme.extractColors()
}
Theme.generateSystemThemesFromCurrentTheme() Theme.generateSystemThemesFromCurrentTheme()
} }
} }
@@ -275,9 +276,6 @@ Singleton {
saveSettings() saveSettings()
if (typeof Theme !== "undefined") { if (typeof Theme !== "undefined") {
if (Theme.currentTheme === Theme.dynamic) {
Theme.extractColors()
}
Theme.generateSystemThemesFromCurrentTheme() Theme.generateSystemThemesFromCurrentTheme()
} }
} }
@@ -426,9 +424,6 @@ Singleton {
// Refresh dynamic theming when per-monitor mode changes // Refresh dynamic theming when per-monitor mode changes
if (typeof Theme !== "undefined") { if (typeof Theme !== "undefined") {
if (Theme.currentTheme === Theme.dynamic) {
Theme.extractColors()
}
Theme.generateSystemThemesFromCurrentTheme() Theme.generateSystemThemesFromCurrentTheme()
} }
} }
@@ -447,10 +442,6 @@ Singleton {
if (typeof Theme !== "undefined" && typeof Quickshell !== "undefined") { if (typeof Theme !== "undefined" && typeof Quickshell !== "undefined") {
var screens = Quickshell.screens var screens = Quickshell.screens
if (screens.length > 0 && screenName === screens[0].name) { if (screens.length > 0 && screenName === screens[0].name) {
if (typeof SettingsData !== "undefined" && SettingsData.wallpaperDynamicTheming) {
Theme.switchTheme("dynamic")
Theme.extractColors()
}
Theme.generateSystemThemesFromCurrentTheme() Theme.generateSystemThemesFromCurrentTheme()
} }
} }

View File

@@ -15,9 +15,10 @@ Singleton {
// Theme settings // Theme settings
property string currentThemeName: "blue" property string currentThemeName: "blue"
property string customThemeFile: "" property string customThemeFile: ""
property string matugenScheme: "scheme-tonal-spot"
property real topBarTransparency: 0.75 property real topBarTransparency: 0.75
property real topBarWidgetTransparency: 0.85 property real topBarWidgetTransparency: 0.85
property real popupTransparency: 0.92 property real popupTransparency: 1.0
property real dockTransparency: 1 property real dockTransparency: 1
property bool use24HourClock: true property bool use24HourClock: true
property bool useFahrenheit: false property bool useFahrenheit: false
@@ -88,7 +89,6 @@ Singleton {
property string osLogoColorOverride: "" property string osLogoColorOverride: ""
property real osLogoBrightness: 0.5 property real osLogoBrightness: 0.5
property real osLogoContrast: 1 property real osLogoContrast: 1
property bool wallpaperDynamicTheming: true
property bool weatherEnabled: true property bool weatherEnabled: true
property string fontFamily: "Inter Variable" property string fontFamily: "Inter Variable"
property string monoFontFamily: "Fira Code" property string monoFontFamily: "Fira Code"
@@ -116,6 +116,7 @@ Singleton {
property bool qtThemingEnabled: false property bool qtThemingEnabled: false
property bool showDock: false property bool showDock: false
property bool dockAutoHide: false property bool dockAutoHide: false
property bool dockGroupByApp: false
property real cornerRadius: 12 property real cornerRadius: 12
property bool notificationOverlayEnabled: false property bool notificationOverlayEnabled: false
property bool topBarAutoHide: false property bool topBarAutoHide: false
@@ -129,7 +130,8 @@ Singleton {
property bool topBarGothCornersEnabled: false property bool topBarGothCornersEnabled: false
property bool lockScreenShowPowerActions: true property bool lockScreenShowPowerActions: true
property bool hideBrightnessSlider: false property bool hideBrightnessSlider: false
property string widgetBackgroundColor: "sth" property string widgetBackgroundColor: "sch"
property string surfaceBase: "s"
property int notificationTimeoutLow: 5000 property int notificationTimeoutLow: 5000
property int notificationTimeoutNormal: 5000 property int notificationTimeoutNormal: 5000
property int notificationTimeoutCritical: 0 property int notificationTimeoutCritical: 0
@@ -170,7 +172,8 @@ Singleton {
"enabled": true, "enabled": true,
"size": 20, "size": 20,
"selectedGpuIndex": 0, "selectedGpuIndex": 0,
"pciId": "" "pciId": "",
"mountPath": "/"
} }
leftWidgetsModel.append(dummyItem) leftWidgetsModel.append(dummyItem)
centerWidgetsModel.append(dummyItem) centerWidgetsModel.append(dummyItem)
@@ -205,9 +208,10 @@ Singleton {
currentThemeName = settings.currentThemeName !== undefined ? settings.currentThemeName : "blue" currentThemeName = settings.currentThemeName !== undefined ? settings.currentThemeName : "blue"
} }
customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : "" customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : ""
matugenScheme = settings.matugenScheme !== undefined ? settings.matugenScheme : "scheme-tonal-spot"
topBarTransparency = settings.topBarTransparency !== undefined ? (settings.topBarTransparency > 1 ? settings.topBarTransparency / 100 : settings.topBarTransparency) : 0.75 topBarTransparency = settings.topBarTransparency !== undefined ? (settings.topBarTransparency > 1 ? settings.topBarTransparency / 100 : settings.topBarTransparency) : 0.75
topBarWidgetTransparency = settings.topBarWidgetTransparency !== undefined ? (settings.topBarWidgetTransparency > 1 ? settings.topBarWidgetTransparency / 100 : settings.topBarWidgetTransparency) : 0.85 topBarWidgetTransparency = settings.topBarWidgetTransparency !== undefined ? (settings.topBarWidgetTransparency > 1 ? settings.topBarWidgetTransparency / 100 : settings.topBarWidgetTransparency) : 0.85
popupTransparency = settings.popupTransparency !== undefined ? (settings.popupTransparency > 1 ? settings.popupTransparency / 100 : settings.popupTransparency) : 0.92 popupTransparency = settings.popupTransparency !== undefined ? (settings.popupTransparency > 1 ? settings.popupTransparency / 100 : settings.popupTransparency) : 1.0
dockTransparency = settings.dockTransparency !== undefined ? (settings.dockTransparency > 1 ? settings.dockTransparency / 100 : settings.dockTransparency) : 1 dockTransparency = settings.dockTransparency !== undefined ? (settings.dockTransparency > 1 ? settings.dockTransparency / 100 : settings.dockTransparency) : 1
use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true
useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false
@@ -289,7 +293,6 @@ Singleton {
osLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : "" osLogoColorOverride = settings.osLogoColorOverride !== undefined ? settings.osLogoColorOverride : ""
osLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5 osLogoBrightness = settings.osLogoBrightness !== undefined ? settings.osLogoBrightness : 0.5
osLogoContrast = settings.osLogoContrast !== undefined ? settings.osLogoContrast : 1 osLogoContrast = settings.osLogoContrast !== undefined ? settings.osLogoContrast : 1
wallpaperDynamicTheming = settings.wallpaperDynamicTheming !== undefined ? settings.wallpaperDynamicTheming : true
fontFamily = settings.fontFamily !== undefined ? settings.fontFamily : defaultFontFamily fontFamily = settings.fontFamily !== undefined ? settings.fontFamily : defaultFontFamily
monoFontFamily = settings.monoFontFamily !== undefined ? settings.monoFontFamily : defaultMonoFontFamily monoFontFamily = settings.monoFontFamily !== undefined ? settings.monoFontFamily : defaultMonoFontFamily
fontWeight = settings.fontWeight !== undefined ? settings.fontWeight : Font.Normal fontWeight = settings.fontWeight !== undefined ? settings.fontWeight : Font.Normal
@@ -304,6 +307,7 @@ Singleton {
qtThemingEnabled = settings.qtThemingEnabled !== undefined ? settings.qtThemingEnabled : false qtThemingEnabled = settings.qtThemingEnabled !== undefined ? settings.qtThemingEnabled : false
showDock = settings.showDock !== undefined ? settings.showDock : false showDock = settings.showDock !== undefined ? settings.showDock : false
dockAutoHide = settings.dockAutoHide !== undefined ? settings.dockAutoHide : false dockAutoHide = settings.dockAutoHide !== undefined ? settings.dockAutoHide : false
dockGroupByApp = settings.dockGroupByApp !== undefined ? settings.dockGroupByApp : false
cornerRadius = settings.cornerRadius !== undefined ? settings.cornerRadius : 12 cornerRadius = settings.cornerRadius !== undefined ? settings.cornerRadius : 12
notificationOverlayEnabled = settings.notificationOverlayEnabled !== undefined ? settings.notificationOverlayEnabled : false notificationOverlayEnabled = settings.notificationOverlayEnabled !== undefined ? settings.notificationOverlayEnabled : false
topBarAutoHide = settings.topBarAutoHide !== undefined ? settings.topBarAutoHide : false topBarAutoHide = settings.topBarAutoHide !== undefined ? settings.topBarAutoHide : false
@@ -320,7 +324,8 @@ Singleton {
topBarGothCornersEnabled = settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : false topBarGothCornersEnabled = settings.topBarGothCornersEnabled !== undefined ? settings.topBarGothCornersEnabled : false
lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true lockScreenShowPowerActions = settings.lockScreenShowPowerActions !== undefined ? settings.lockScreenShowPowerActions : true
hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false hideBrightnessSlider = settings.hideBrightnessSlider !== undefined ? settings.hideBrightnessSlider : false
widgetBackgroundColor = settings.widgetBackgroundColor !== undefined ? settings.widgetBackgroundColor : "sth" widgetBackgroundColor = settings.widgetBackgroundColor !== undefined ? settings.widgetBackgroundColor : "sch"
surfaceBase = settings.surfaceBase !== undefined ? settings.surfaceBase : "s"
screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({}) screenPreferences = settings.screenPreferences !== undefined ? settings.screenPreferences : ({})
applyStoredTheme() applyStoredTheme()
detectAvailableIconThemes() detectAvailableIconThemes()
@@ -343,6 +348,7 @@ Singleton {
settingsFile.setText(JSON.stringify({ settingsFile.setText(JSON.stringify({
"currentThemeName": currentThemeName, "currentThemeName": currentThemeName,
"customThemeFile": customThemeFile, "customThemeFile": customThemeFile,
"matugenScheme": matugenScheme,
"topBarTransparency": topBarTransparency, "topBarTransparency": topBarTransparency,
"topBarWidgetTransparency": topBarWidgetTransparency, "topBarWidgetTransparency": topBarWidgetTransparency,
"popupTransparency": popupTransparency, "popupTransparency": popupTransparency,
@@ -400,7 +406,6 @@ Singleton {
"osLogoColorOverride": osLogoColorOverride, "osLogoColorOverride": osLogoColorOverride,
"osLogoBrightness": osLogoBrightness, "osLogoBrightness": osLogoBrightness,
"osLogoContrast": osLogoContrast, "osLogoContrast": osLogoContrast,
"wallpaperDynamicTheming": wallpaperDynamicTheming,
"fontFamily": fontFamily, "fontFamily": fontFamily,
"monoFontFamily": monoFontFamily, "monoFontFamily": monoFontFamily,
"fontWeight": fontWeight, "fontWeight": fontWeight,
@@ -415,6 +420,7 @@ Singleton {
"qtThemingEnabled": qtThemingEnabled, "qtThemingEnabled": qtThemingEnabled,
"showDock": showDock, "showDock": showDock,
"dockAutoHide": dockAutoHide, "dockAutoHide": dockAutoHide,
"dockGroupByApp": dockGroupByApp,
"cornerRadius": cornerRadius, "cornerRadius": cornerRadius,
"notificationOverlayEnabled": notificationOverlayEnabled, "notificationOverlayEnabled": notificationOverlayEnabled,
"topBarAutoHide": topBarAutoHide, "topBarAutoHide": topBarAutoHide,
@@ -429,6 +435,7 @@ Singleton {
"lockScreenShowPowerActions": lockScreenShowPowerActions, "lockScreenShowPowerActions": lockScreenShowPowerActions,
"hideBrightnessSlider": hideBrightnessSlider, "hideBrightnessSlider": hideBrightnessSlider,
"widgetBackgroundColor": widgetBackgroundColor, "widgetBackgroundColor": widgetBackgroundColor,
"surfaceBase": surfaceBase,
"notificationTimeoutLow": notificationTimeoutLow, "notificationTimeoutLow": notificationTimeoutLow,
"notificationTimeoutNormal": notificationTimeoutNormal, "notificationTimeoutNormal": notificationTimeoutNormal,
"notificationTimeoutCritical": notificationTimeoutCritical, "notificationTimeoutCritical": notificationTimeoutCritical,
@@ -566,6 +573,19 @@ Singleton {
saveSettings() saveSettings()
} }
function setMatugenScheme(scheme) {
var normalized = scheme || "scheme-tonal-spot"
if (matugenScheme === normalized)
return
matugenScheme = normalized
saveSettings()
if (typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme()
}
}
function setTopBarTransparency(transparency) { function setTopBarTransparency(transparency) {
topBarTransparency = transparency topBarTransparency = transparency
saveSettings() saveSettings()
@@ -738,6 +758,7 @@ Singleton {
var size = typeof order[i] === "string" ? undefined : order[i].size var size = typeof order[i] === "string" ? undefined : order[i].size
var selectedGpuIndex = typeof order[i] === "string" ? undefined : order[i].selectedGpuIndex var selectedGpuIndex = typeof order[i] === "string" ? undefined : order[i].selectedGpuIndex
var pciId = typeof order[i] === "string" ? undefined : order[i].pciId var pciId = typeof order[i] === "string" ? undefined : order[i].pciId
var mountPath = typeof order[i] === "string" ? undefined : order[i].mountPath
var item = { var item = {
"widgetId": widgetId, "widgetId": widgetId,
"enabled": enabled "enabled": enabled
@@ -748,6 +769,8 @@ Singleton {
item.selectedGpuIndex = selectedGpuIndex item.selectedGpuIndex = selectedGpuIndex
if (pciId !== undefined) if (pciId !== undefined)
item.pciId = pciId item.pciId = pciId
if (mountPath !== undefined)
item.mountPath = mountPath
listModel.append(item) listModel.append(item)
} }
@@ -890,11 +913,6 @@ Singleton {
saveSettings() saveSettings()
} }
function setWallpaperDynamicTheming(enabled) {
wallpaperDynamicTheming = enabled
saveSettings()
}
function setFontFamily(family) { function setFontFamily(family) {
fontFamily = family fontFamily = family
saveSettings() saveSettings()
@@ -941,6 +959,11 @@ Singleton {
saveSettings() saveSettings()
} }
function setDockGroupByApp(enabled) {
dockGroupByApp = enabled
saveSettings()
}
function setCornerRadius(radius) { function setCornerRadius(radius) {
cornerRadius = radius cornerRadius = radius
saveSettings() saveSettings()
@@ -1031,6 +1054,14 @@ Singleton {
saveSettings() saveSettings()
} }
function setSurfaceBase(base) {
surfaceBase = base
saveSettings()
if (typeof Theme !== "undefined") {
Theme.generateSystemThemesFromCurrentTheme()
}
}
function setScreenPreferences(prefs) { function setScreenPreferences(prefs) {
screenPreferences = prefs screenPreferences = prefs
saveSettings() saveSettings()

View File

@@ -10,7 +10,8 @@ const CatppuccinMocha = {
backgroundText: "#cdd6f4", backgroundText: "#cdd6f4",
outline: "#6c7086", outline: "#6c7086",
surfaceContainer: "#313244", surfaceContainer: "#313244",
surfaceContainerHigh: "#585b70" surfaceContainerHigh: "#585b70",
surfaceContainerHighest: "#7f849c"
} }
const CatppuccinLatte = { const CatppuccinLatte = {
@@ -22,7 +23,8 @@ const CatppuccinLatte = {
backgroundText: "#4c4f69", backgroundText: "#4c4f69",
outline: "#9ca0b0", outline: "#9ca0b0",
surfaceContainer: "#ccd0da", surfaceContainer: "#ccd0da",
surfaceContainerHigh: "#acb0be" surfaceContainerHigh: "#acb0be",
surfaceContainerHighest: "#8c8fa1"
} }
const CatppuccinVariants = { const CatppuccinVariants = {
@@ -118,16 +120,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#0d47a1", primaryContainer: "#0d47a1",
secondary: "#8ab4f8", secondary: "#8ab4f8",
surface: "#1a1c1e", surface: "#101418",
surfaceText: "#e3e8ef", surfaceText: "#e0e2e8",
surfaceVariant: "#44464f", surfaceVariant: "#42474e",
surfaceVariantText: "#c4c7c5", surfaceVariantText: "#c2c7cf",
surfaceTint: "#8ab4f8", surfaceTint: "#8ab4f8",
background: "#1a1c1e", background: "#101418",
backgroundText: "#e3e8ef", backgroundText: "#e0e2e8",
outline: "#8e918f", outline: "#8c9199",
surfaceContainer: "#1e2023", surfaceContainer: "#1d2024",
surfaceContainerHigh: "#292b2f" surfaceContainerHigh: "#272a2f",
surfaceContainerHighest: "#32353a"
}, },
purple: { purple: {
name: "Purple", name: "Purple",
@@ -135,16 +138,17 @@ const StockThemes = {
primaryText: "#381E72", primaryText: "#381E72",
primaryContainer: "#4F378B", primaryContainer: "#4F378B",
secondary: "#CCC2DC", secondary: "#CCC2DC",
surface: "#10121E", surface: "#141218",
surfaceText: "#E6E0E9", surfaceText: "#e6e0e9",
surfaceVariant: "#49454F", surfaceVariant: "#49454e",
surfaceVariantText: "#CAC4D0", surfaceVariantText: "#cac4cf",
surfaceTint: "#D0BCFF", surfaceTint: "#D0BCFF",
background: "#10121E", background: "#141218",
backgroundText: "#E6E0E9", backgroundText: "#e6e0e9",
outline: "#938F99", outline: "#948f99",
surfaceContainer: "#1D1B20", surfaceContainer: "#211f24",
surfaceContainerHigh: "#2B2930" surfaceContainerHigh: "#2b292f",
surfaceContainerHighest: "#36343a"
}, },
green: { green: {
name: "Green", name: "Green",
@@ -152,16 +156,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#1b5e20", primaryContainer: "#1b5e20",
secondary: "#81c995", secondary: "#81c995",
surface: "#0f1411", surface: "#10140f",
surfaceText: "#e1f5e3", surfaceText: "#e0e4db",
surfaceVariant: "#404943", surfaceVariant: "#424940",
surfaceVariantText: "#c1cbc4", surfaceVariantText: "#c2c9bd",
surfaceTint: "#81c995", surfaceTint: "#81c995",
background: "#0f1411", background: "#10140f",
backgroundText: "#e1f5e3", backgroundText: "#e0e4db",
outline: "#8b938c", outline: "#8c9388",
surfaceContainer: "#1a1f1b", surfaceContainer: "#1d211b",
surfaceContainerHigh: "#252a26" surfaceContainerHigh: "#272b25",
surfaceContainerHighest: "#323630"
}, },
orange: { orange: {
name: "Orange", name: "Orange",
@@ -169,16 +174,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#3e2723", primaryContainer: "#3e2723",
secondary: "#ffb74d", secondary: "#ffb74d",
surface: "#1c1410", surface: "#1a120e",
surfaceText: "#f5f1ea", surfaceText: "#f0dfd8",
surfaceVariant: "#4a453a", surfaceVariant: "#52443d",
surfaceVariantText: "#cbc5b8", surfaceVariantText: "#d7c2b9",
surfaceTint: "#ffb74d", surfaceTint: "#ffb74d",
background: "#1c1410", background: "#1a120e",
backgroundText: "#f5f1ea", backgroundText: "#f0dfd8",
outline: "#958f84", outline: "#a08d85",
surfaceContainer: "#211e17", surfaceContainer: "#271e1a",
surfaceContainerHigh: "#2c291f" surfaceContainerHigh: "#322824",
surfaceContainerHighest: "#3d332e"
}, },
red: { red: {
name: "Red", name: "Red",
@@ -186,16 +192,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#4a0e0e", primaryContainer: "#4a0e0e",
secondary: "#f28b82", secondary: "#f28b82",
surface: "#1c1011", surface: "#1a1110",
surfaceText: "#f5e8ea", surfaceText: "#f1dedc",
surfaceVariant: "#4a3f41", surfaceVariant: "#534341",
surfaceVariantText: "#cbc2c4", surfaceVariantText: "#d8c2be",
surfaceTint: "#f28b82", surfaceTint: "#f28b82",
background: "#1c1011", background: "#1a1110",
backgroundText: "#f5e8ea", backgroundText: "#f1dedc",
outline: "#958b8d", outline: "#a08c89",
surfaceContainer: "#211b1c", surfaceContainer: "#271d1c",
surfaceContainerHigh: "#2c2426" surfaceContainerHigh: "#322826",
surfaceContainerHighest: "#3d3231"
}, },
cyan: { cyan: {
name: "Cyan", name: "Cyan",
@@ -203,16 +210,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#004d5c", primaryContainer: "#004d5c",
secondary: "#4dd0e1", secondary: "#4dd0e1",
surface: "#0f1617", surface: "#0e1416",
surfaceText: "#e8f4f5", surfaceText: "#dee3e5",
surfaceVariant: "#3f474a", surfaceVariant: "#3f484a",
surfaceVariantText: "#c2c9cb", surfaceVariantText: "#bfc8ca",
surfaceTint: "#4dd0e1", surfaceTint: "#4dd0e1",
background: "#0f1617", background: "#0e1416",
backgroundText: "#e8f4f5", backgroundText: "#dee3e5",
outline: "#8c9194", outline: "#899295",
surfaceContainer: "#1a1f20", surfaceContainer: "#1b2122",
surfaceContainerHigh: "#252b2c" surfaceContainerHigh: "#252b2c",
surfaceContainerHighest: "#303637"
}, },
pink: { pink: {
name: "Pink", name: "Pink",
@@ -220,16 +228,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#4a0e2f", primaryContainer: "#4a0e2f",
secondary: "#f8bbd9", secondary: "#f8bbd9",
surface: "#1a1014", surface: "#191112",
surfaceText: "#f3e8ee", surfaceText: "#f0dee0",
surfaceVariant: "#483f45", surfaceVariant: "#524345",
surfaceVariantText: "#c9c2c7", surfaceVariantText: "#d6c2c3",
surfaceTint: "#f8bbd9", surfaceTint: "#f8bbd9",
background: "#1a1014", background: "#191112",
backgroundText: "#f3e8ee", backgroundText: "#f0dee0",
outline: "#938a90", outline: "#9f8c8e",
surfaceContainer: "#1f1b1e", surfaceContainer: "#261d1e",
surfaceContainerHigh: "#2a2428" surfaceContainerHigh: "#312829",
surfaceContainerHighest: "#3c3233"
}, },
amber: { amber: {
name: "Amber", name: "Amber",
@@ -237,16 +246,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#4a3c00", primaryContainer: "#4a3c00",
secondary: "#ffd54f", secondary: "#ffd54f",
surface: "#1a1710", surface: "#17130b",
surfaceText: "#f3f0e8", surfaceText: "#ebe1d4",
surfaceVariant: "#49453a", surfaceVariant: "#4d4639",
surfaceVariantText: "#cac5b8", surfaceVariantText: "#d0c5b4",
surfaceTint: "#ffd54f", surfaceTint: "#ffd54f",
background: "#1a1710", background: "#17130b",
backgroundText: "#f3f0e8", backgroundText: "#ebe1d4",
outline: "#949084", outline: "#998f80",
surfaceContainer: "#1f1e17", surfaceContainer: "#231f17",
surfaceContainerHigh: "#2a281f" surfaceContainerHigh: "#2e2921",
surfaceContainerHighest: "#39342b"
}, },
coral: { coral: {
name: "Coral", name: "Coral",
@@ -255,15 +265,16 @@ const StockThemes = {
primaryContainer: "#8c1d18", primaryContainer: "#8c1d18",
secondary: "#f9dedc", secondary: "#f9dedc",
surface: "#1a1110", surface: "#1a1110",
surfaceText: "#f1e8e7", surfaceText: "#f1dedc",
surfaceVariant: "#4a4142", surfaceVariant: "#534341",
surfaceVariantText: "#cdc2c1", surfaceVariantText: "#d8c2bf",
surfaceTint: "#ffb4ab", surfaceTint: "#ffb4ab",
background: "#1a1110", background: "#1a1110",
backgroundText: "#f1e8e7", backgroundText: "#f1dedc",
outline: "#968b8a", outline: "#a08c8a",
surfaceContainer: "#201a19", surfaceContainer: "#271d1c",
surfaceContainerHigh: "#2b2221" surfaceContainerHigh: "#322826",
surfaceContainerHighest: "#3d3231"
}, },
monochrome: { monochrome: {
name: "Monochrome", name: "Monochrome",
@@ -281,6 +292,7 @@ const StockThemes = {
outline: "#929092", outline: "#929092",
surfaceContainer: "#2a2a2a", surfaceContainer: "#2a2a2a",
surfaceContainerHigh: "#2a2a2b", surfaceContainerHigh: "#2a2a2b",
surfaceContainerHighest: "#353535",
error: "#ffb4ab", error: "#ffb4ab",
warning: "#3f4759", warning: "#3f4759",
info: "#595e6c", info: "#595e6c",
@@ -294,16 +306,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#e3f2fd", primaryContainer: "#e3f2fd",
secondary: "#42a5f5", secondary: "#42a5f5",
surface: "#fefefe", surface: "#f7f9ff",
surfaceText: "#1a1c1e", surfaceText: "#181c20",
surfaceVariant: "#e7e0ec", surfaceVariant: "#dee3eb",
surfaceVariantText: "#49454f", surfaceVariantText: "#42474e",
surfaceTint: "#1976d2", surfaceTint: "#1976d2",
background: "#fefefe", background: "#f7f9ff",
backgroundText: "#1a1c1e", backgroundText: "#181c20",
outline: "#79747e", outline: "#72777f",
surfaceContainer: "#f3f3f3", surfaceContainer: "#eceef4",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#e6e8ee",
surfaceContainerHighest: "#e0e2e8"
}, },
purple: { purple: {
name: "Purple Light", name: "Purple Light",
@@ -311,16 +324,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#EADDFF", primaryContainer: "#EADDFF",
secondary: "#625B71", secondary: "#625B71",
surface: "#FFFBFE", surface: "#fef7ff",
surfaceText: "#1C1B1F", surfaceText: "#1d1b20",
surfaceVariant: "#E7E0EC", surfaceVariant: "#e7e0eb",
surfaceVariantText: "#49454F", surfaceVariantText: "#49454e",
surfaceTint: "#6750A4", surfaceTint: "#6750A4",
background: "#FFFBFE", background: "#fef7ff",
backgroundText: "#1C1B1F", backgroundText: "#1d1b20",
outline: "#79747E", outline: "#7a757f",
surfaceContainer: "#F3EDF7", surfaceContainer: "#f2ecf4",
surfaceContainerHigh: "#ECE6F0" surfaceContainerHigh: "#ece6ee",
surfaceContainerHighest: "#e6e0e9"
}, },
green: { green: {
name: "Green Light", name: "Green Light",
@@ -328,16 +342,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#e8f5e8", primaryContainer: "#e8f5e8",
secondary: "#4caf50", secondary: "#4caf50",
surface: "#fefefe", surface: "#f7fbf1",
surfaceText: "#1a1c1e", surfaceText: "#191d17",
surfaceVariant: "#e7e0ec", surfaceVariant: "#dee5d8",
surfaceVariantText: "#49454f", surfaceVariantText: "#424940",
surfaceTint: "#2e7d32", surfaceTint: "#2e7d32",
background: "#fefefe", background: "#f7fbf1",
backgroundText: "#1a1c1e", backgroundText: "#191d17",
outline: "#79747e", outline: "#72796f",
surfaceContainer: "#f3f3f3", surfaceContainer: "#ecefe6",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#e6e9e0",
surfaceContainerHighest: "#e0e4db"
}, },
orange: { orange: {
name: "Orange Light", name: "Orange Light",
@@ -345,16 +360,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#ffecb3", primaryContainer: "#ffecb3",
secondary: "#ff9800", secondary: "#ff9800",
surface: "#fefefe", surface: "#fff8f6",
surfaceText: "#1a1c1e", surfaceText: "#221a16",
surfaceVariant: "#e7e0ec", surfaceVariant: "#f4ded5",
surfaceVariantText: "#49454f", surfaceVariantText: "#52443d",
surfaceTint: "#e65100", surfaceTint: "#e65100",
background: "#fefefe", background: "#fff8f6",
backgroundText: "#1a1c1e", backgroundText: "#221a16",
outline: "#79747e", outline: "#85736c",
surfaceContainer: "#f3f3f3", surfaceContainer: "#fceae3",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#f6e5de",
surfaceContainerHighest: "#f0dfd8"
}, },
red: { red: {
name: "Red Light", name: "Red Light",
@@ -362,16 +378,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#ffebee", primaryContainer: "#ffebee",
secondary: "#f44336", secondary: "#f44336",
surface: "#fefefe", surface: "#fff8f7",
surfaceText: "#1a1c1e", surfaceText: "#231918",
surfaceVariant: "#e7e0ec", surfaceVariant: "#f5ddda",
surfaceVariantText: "#49454f", surfaceVariantText: "#534341",
surfaceTint: "#d32f2f", surfaceTint: "#d32f2f",
background: "#fefefe", background: "#fff8f7",
backgroundText: "#1a1c1e", backgroundText: "#231918",
outline: "#79747e", outline: "#857370",
surfaceContainer: "#f3f3f3", surfaceContainer: "#fceae7",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#f7e4e1",
surfaceContainerHighest: "#f1dedc"
}, },
cyan: { cyan: {
name: "Cyan Light", name: "Cyan Light",
@@ -379,16 +396,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#e0f2f1", primaryContainer: "#e0f2f1",
secondary: "#00bcd4", secondary: "#00bcd4",
surface: "#fefefe", surface: "#f5fafc",
surfaceText: "#1a1c1e", surfaceText: "#171d1e",
surfaceVariant: "#e7e0ec", surfaceVariant: "#dbe4e6",
surfaceVariantText: "#49454f", surfaceVariantText: "#3f484a",
surfaceTint: "#0097a7", surfaceTint: "#0097a7",
background: "#fefefe", background: "#f5fafc",
backgroundText: "#1a1c1e", backgroundText: "#171d1e",
outline: "#79747e", outline: "#6f797b",
surfaceContainer: "#f3f3f3", surfaceContainer: "#e9eff0",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#e3e9eb",
surfaceContainerHighest: "#dee3e5"
}, },
pink: { pink: {
name: "Pink Light", name: "Pink Light",
@@ -396,16 +414,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#fce4ec", primaryContainer: "#fce4ec",
secondary: "#e91e63", secondary: "#e91e63",
surface: "#fefefe", surface: "#fff8f7",
surfaceText: "#1a1c1e", surfaceText: "#22191a",
surfaceVariant: "#e7e0ec", surfaceVariant: "#f3dddf",
surfaceVariantText: "#49454f", surfaceVariantText: "#524345",
surfaceTint: "#c2185b", surfaceTint: "#c2185b",
background: "#fefefe", background: "#fff8f7",
backgroundText: "#1a1c1e", backgroundText: "#22191a",
outline: "#79747e", outline: "#847375",
surfaceContainer: "#f3f3f3", surfaceContainer: "#fbeaeb",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#f5e4e5",
surfaceContainerHighest: "#f0dee0"
}, },
amber: { amber: {
name: "Amber Light", name: "Amber Light",
@@ -413,16 +432,17 @@ const StockThemes = {
primaryText: "#000000", primaryText: "#000000",
primaryContainer: "#fff8e1", primaryContainer: "#fff8e1",
secondary: "#ffc107", secondary: "#ffc107",
surface: "#fefefe", surface: "#fff8f2",
surfaceText: "#1a1c1e", surfaceText: "#1f1b13",
surfaceVariant: "#e7e0ec", surfaceVariant: "#ede1cf",
surfaceVariantText: "#49454f", surfaceVariantText: "#4d4639",
surfaceTint: "#ff8f00", surfaceTint: "#ff8f00",
background: "#fefefe", background: "#fff8f2",
backgroundText: "#1a1c1e", backgroundText: "#1f1b13",
outline: "#79747e", outline: "#7f7667",
surfaceContainer: "#f3f3f3", surfaceContainer: "#f6ecdf",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#f1e7d9",
surfaceContainerHighest: "#ebe1d4"
}, },
coral: { coral: {
name: "Coral Light", name: "Coral Light",
@@ -430,16 +450,17 @@ const StockThemes = {
primaryText: "#ffffff", primaryText: "#ffffff",
primaryContainer: "#ffdad6", primaryContainer: "#ffdad6",
secondary: "#ff5449", secondary: "#ff5449",
surface: "#fefefe", surface: "#fff8f7",
surfaceText: "#1a1c1e", surfaceText: "#231918",
surfaceVariant: "#e7e0ec", surfaceVariant: "#f5ddda",
surfaceVariantText: "#49454f", surfaceVariantText: "#534341",
surfaceTint: "#8c1d18", surfaceTint: "#8c1d18",
background: "#fefefe", background: "#fff8f7",
backgroundText: "#1a1c1e", backgroundText: "#231918",
outline: "#79747e", outline: "#857371",
surfaceContainer: "#f3f3f3", surfaceContainer: "#fceae7",
surfaceContainerHigh: "#ececec" surfaceContainerHigh: "#f6e4e2",
surfaceContainerHighest: "#f1dedc"
}, },
monochrome: { monochrome: {
name: "Monochrome Light", name: "Monochrome Light",

View File

@@ -14,6 +14,10 @@ import "StockThemes.js" as StockThemes
Singleton { Singleton {
id: root id: root
readonly property bool envDisableMatugen: Quickshell.env("DMS_DISABLE_MATUGEN") === "1" || Quickshell.env("DMS_DISABLE_MATUGEN") === "true"
readonly property real popupDistance: 4
property string currentTheme: "blue" property string currentTheme: "blue"
property string currentThemeCategory: "generic" property string currentThemeCategory: "generic"
property bool isLightMode: false property bool isLightMode: false
@@ -70,7 +74,6 @@ Singleton {
property bool qtThemingEnabled: typeof SettingsData !== "undefined" ? (SettingsData.qt5ctAvailable || SettingsData.qt6ctAvailable) : false property bool qtThemingEnabled: typeof SettingsData !== "undefined" ? (SettingsData.qt5ctAvailable || SettingsData.qt6ctAvailable) : false
property var workerRunning: false property var workerRunning: false
property var matugenColors: ({}) property var matugenColors: ({})
property bool extractionRequested: false
property int colorUpdateTrigger: 0 property int colorUpdateTrigger: 0
property var customThemeData: null property var customThemeData: null
@@ -118,6 +121,7 @@ Singleton {
"outline": getMatugenColor("outline", "#8e918f"), "outline": getMatugenColor("outline", "#8e918f"),
"surfaceContainer": getMatugenColor("surface_container", "#1e2023"), "surfaceContainer": getMatugenColor("surface_container", "#1e2023"),
"surfaceContainerHigh": getMatugenColor("surface_container_high", "#292b2f"), "surfaceContainerHigh": getMatugenColor("surface_container_high", "#292b2f"),
"surfaceContainerHighest": getMatugenColor("surface_container_highest", "#343740"),
"error": "#F2B8B5", "error": "#F2B8B5",
"warning": "#FF9800", "warning": "#FF9800",
"info": "#2196F3", "info": "#2196F3",
@@ -128,11 +132,36 @@ Singleton {
} }
} }
readonly property var availableMatugenSchemes: [
({ "value": "scheme-tonal-spot", "label": "Tonal Spot", "description": "Balanced palette with focused accents (default)." }),
({ "value": "scheme-content", "label": "Content", "description": "Derives colors that closely match the underlying image." }),
({ "value": "scheme-expressive", "label": "Expressive", "description": "Vibrant palette with playful saturation." }),
({ "value": "scheme-fidelity", "label": "Fidelity", "description": "High-fidelity palette that preserves source hues." }),
({ "value": "scheme-fruit-salad", "label": "Fruit Salad", "description": "Colorful mix of bright contrasting accents." }),
({ "value": "scheme-monochrome", "label": "Monochrome", "description": "Minimal palette built around a single hue." }),
({ "value": "scheme-neutral", "label": "Neutral", "description": "Muted palette with subdued, calming tones." }),
({ "value": "scheme-rainbow", "label": "Rainbow", "description": "Diverse palette spanning the full spectrum." })
]
function getMatugenScheme(value) {
const schemes = availableMatugenSchemes
for (let i = 0; i < schemes.length; i++) {
if (schemes[i].value === value)
return schemes[i]
}
return schemes[0]
}
property color primary: currentThemeData.primary property color primary: currentThemeData.primary
property color primaryText: currentThemeData.primaryText property color primaryText: currentThemeData.primaryText
property color primaryContainer: currentThemeData.primaryContainer property color primaryContainer: currentThemeData.primaryContainer
property color secondary: currentThemeData.secondary property color secondary: currentThemeData.secondary
property color surface: currentThemeData.surface property color surface: {
if (typeof SettingsData !== "undefined" && SettingsData.surfaceBase === "s") {
return currentThemeData.background
}
return currentThemeData.surface
}
property color surfaceText: currentThemeData.surfaceText property color surfaceText: currentThemeData.surfaceText
property color surfaceVariant: currentThemeData.surfaceVariant property color surfaceVariant: currentThemeData.surfaceVariant
property color surfaceVariantText: currentThemeData.surfaceVariantText property color surfaceVariantText: currentThemeData.surfaceVariantText
@@ -141,8 +170,24 @@ Singleton {
property color backgroundText: currentThemeData.backgroundText property color backgroundText: currentThemeData.backgroundText
property color outline: currentThemeData.outline property color outline: currentThemeData.outline
property color outlineVariant: currentThemeData.outlineVariant || Qt.rgba(outline.r, outline.g, outline.b, 0.6) property color outlineVariant: currentThemeData.outlineVariant || Qt.rgba(outline.r, outline.g, outline.b, 0.6)
property color surfaceContainer: currentThemeData.surfaceContainer property color surfaceContainer: {
property color surfaceContainerHigh: currentThemeData.surfaceContainerHigh if (typeof SettingsData !== "undefined" && SettingsData.surfaceBase === "s") {
return currentThemeData.surface
}
return currentThemeData.surfaceContainer
}
property color surfaceContainerHigh: {
if (typeof SettingsData !== "undefined" && SettingsData.surfaceBase === "s") {
return currentThemeData.surfaceContainer
}
return currentThemeData.surfaceContainerHigh
}
property color surfaceContainerHighest: {
if (typeof SettingsData !== "undefined" && SettingsData.surfaceBase === "s") {
return currentThemeData.surfaceContainerHigh
}
return currentThemeData.surfaceContainerHighest
}
property color onSurface: surfaceText property color onSurface: surfaceText
property color onSurfaceVariant: surfaceVariantText property color onSurfaceVariant: surfaceVariantText
@@ -225,7 +270,6 @@ Singleton {
if (themeName === dynamic) { if (themeName === dynamic) {
currentTheme = dynamic currentTheme = dynamic
currentThemeCategory = dynamic currentThemeCategory = dynamic
extractColors()
} else if (themeName === custom) { } else if (themeName === custom) {
currentTheme = custom currentTheme = custom
currentThemeCategory = custom currentThemeCategory = custom
@@ -263,9 +307,6 @@ Singleton {
function forceGenerateSystemThemes() { function forceGenerateSystemThemes() {
screenTransition() screenTransition()
if (!matugenAvailable) { if (!matugenAvailable) {
if (typeof ToastService !== "undefined") {
ToastService.showWarning("matugen not available - cannot generate system themes")
}
return return
} }
generateSystemThemesFromCurrentTheme() generateSystemThemesFromCurrentTheme()
@@ -348,7 +389,7 @@ Singleton {
property real notepadTransparency: SettingsData.notepadTransparencyOverride >= 0 ? SettingsData.notepadTransparencyOverride : popupTransparency property real notepadTransparency: SettingsData.notepadTransparencyOverride >= 0 ? SettingsData.notepadTransparencyOverride : popupTransparency
property var widgetBaseBackgroundColor: { property var widgetBaseBackgroundColor: {
const colorMode = typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundColor : "sth" const colorMode = typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundColor : "sch"
switch (colorMode) { switch (colorMode) {
case "s": case "s":
return surface return surface
@@ -369,7 +410,7 @@ Singleton {
} }
property var widgetBackground: { property var widgetBackground: {
const colorMode = typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundColor : "sth" const colorMode = typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundColor : "sch"
switch (colorMode) { switch (colorMode) {
case "s": case "s":
return Qt.rgba(surface.r, surface.g, surface.b, widgetTransparency) return Qt.rgba(surface.r, surface.g, surface.b, widgetTransparency)
@@ -485,17 +526,6 @@ Singleton {
} }
} }
function extractColors() {
extractionRequested = true
if (matugenAvailable)
if (rawWallpaperPath.startsWith("we:")) {
fileCheckerTimer.start()
} else {
fileChecker.running = true
}
else
matugenCheck.running = true
}
function onLightModeChanged() { function onLightModeChanged() {
if (matugenColors && Object.keys(matugenColors).length > 0) { if (matugenColors && Object.keys(matugenColors).length > 0) {
@@ -509,7 +539,7 @@ Singleton {
function setDesiredTheme(kind, value, isLight, iconTheme, matugenType) { function setDesiredTheme(kind, value, isLight, iconTheme, matugenType) {
if (!matugenAvailable) { if (!matugenAvailable) {
console.warn("matugen not available - cannot set system theme") console.warn("matugen not available or disabled - cannot set system theme")
return return
} }
@@ -522,7 +552,8 @@ Singleton {
"value": value, "value": value,
"mode": isLight ? "light" : "dark", "mode": isLight ? "light" : "dark",
"iconTheme": iconTheme || "System Default", "iconTheme": iconTheme || "System Default",
"matugenType": matugenType || "scheme-tonal-spot" "matugenType": matugenType || "scheme-tonal-spot",
"surfaceBase": (typeof SettingsData !== "undefined" && SettingsData.surfaceBase) ? SettingsData.surfaceBase : "sc"
} }
const json = JSON.stringify(desired) const json = JSON.stringify(desired)
@@ -553,10 +584,11 @@ Singleton {
if (!wallpaperPath) { if (!wallpaperPath) {
return return
} }
const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"
if (wallpaperPath.startsWith("#")) { if (wallpaperPath.startsWith("#")) {
setDesiredTheme("hex", wallpaperPath, isLight, iconTheme) setDesiredTheme("hex", wallpaperPath, isLight, iconTheme, selectedMatugenType)
} else { } else {
setDesiredTheme("image", wallpaperPath, isLight, iconTheme) setDesiredTheme("image", wallpaperPath, isLight, iconTheme, selectedMatugenType)
} }
} else { } else {
let primaryColor let primaryColor
@@ -584,7 +616,7 @@ Singleton {
function applyGtkColors() { function applyGtkColors() {
if (!matugenAvailable) { if (!matugenAvailable) {
if (typeof ToastService !== "undefined") { if (typeof ToastService !== "undefined") {
ToastService.showError("matugen not available - cannot apply GTK colors") ToastService.showError("matugen not available or disabled - cannot apply GTK colors")
} }
return return
} }
@@ -597,7 +629,7 @@ Singleton {
function applyQtColors() { function applyQtColors() {
if (!matugenAvailable) { if (!matugenAvailable) {
if (typeof ToastService !== "undefined") { if (typeof ToastService !== "undefined") {
ToastService.showError("matugen not available - cannot apply Qt colors") ToastService.showError("matugen not available or disabled - cannot apply Qt colors")
} }
return return
} }
@@ -606,81 +638,16 @@ Singleton {
qtApplier.running = true qtApplier.running = true
} }
function extractJsonFromText(text) {
if (!text)
return null
const start = text.search(/[{\[]/)
if (start === -1)
return null
const open = text[start]
const pairs = {
"{": '}',
"[": ']'
}
const close = pairs[open]
if (!close)
return null
let inString = false
let escape = false
const stack = [open]
for (var i = start + 1; i < text.length; i++) {
const ch = text[i]
if (inString) {
if (escape) {
escape = false
} else if (ch === '\\') {
escape = true
} else if (ch === '"') {
inString = false
}
continue
}
if (ch === '"') {
inString = true
continue
}
if (ch === '{' || ch === '[') {
stack.push(ch)
continue
}
if (ch === '}' || ch === ']') {
const last = stack.pop()
if (!last || pairs[last] !== ch) {
return null
}
if (stack.length === 0) {
return text.slice(start, i + 1)
}
}
}
return null
}
Process { Process {
id: matugenCheck id: matugenCheck
command: ["which", "matugen"] command: ["which", "matugen"]
onExited: code => { onExited: code => {
matugenAvailable = (code === 0) matugenAvailable = (code === 0) && !envDisableMatugen
if (!matugenAvailable) { if (!matugenAvailable) {
if (typeof ToastService !== "undefined") { console.log("matugen not not available in path or disabled via DMS_DISABLE_MATUGEN")
ToastService.wallpaperErrorStatus = "matugen_missing"
ToastService.showWarning("matugen not found - dynamic theming disabled")
}
return return
} }
if (extractionRequested) {
if (rawWallpaperPath.startsWith("we:")) {
fileCheckerTimer.start()
} else {
fileChecker.running = true
}
}
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode)
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default" const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
@@ -688,10 +655,11 @@ Singleton {
if (currentTheme === dynamic) { if (currentTheme === dynamic) {
if (wallpaperPath) { if (wallpaperPath) {
Quickshell.execDetached(["rm", "-f", stateDir + "/matugen.key"]) Quickshell.execDetached(["rm", "-f", stateDir + "/matugen.key"])
const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"
if (wallpaperPath.startsWith("#")) { if (wallpaperPath.startsWith("#")) {
setDesiredTheme("hex", wallpaperPath, isLight, iconTheme) setDesiredTheme("hex", wallpaperPath, isLight, iconTheme, selectedMatugenType)
} else { } else {
setDesiredTheme("image", wallpaperPath, isLight, iconTheme) setDesiredTheme("image", wallpaperPath, isLight, iconTheme, selectedMatugenType)
} }
} }
} else { } else {
@@ -715,122 +683,7 @@ Singleton {
} }
} }
Process {
id: fileChecker
command: ["test", "-r", wallpaperPath]
onExited: code => {
if (code === 0) {
matugenProcess.running = true
} else if (wallpaperPath.startsWith("#")) {
colorMatugenProcess.running = true
}
}
}
Timer {
id: fileCheckerTimer
interval: 1000
repeat: false
onTriggered: {
fileChecker.running = true
}
}
Process {
id: matugenProcess
command: ["matugen", "image", wallpaperPath, "--json", "hex"]
stdout: StdioCollector {
id: matugenCollector
onStreamFinished: {
if (!matugenCollector.text) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed: Empty JSON extracted from matugen output.")
}
return
}
const extractedJson = extractJsonFromText(matugenCollector.text)
if (!extractedJson) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed: Invalid JSON extracted from matugen output.")
}
console.log("Raw matugen output:", matugenCollector.text)
return
}
try {
root.matugenColors = JSON.parse(extractedJson)
root.colorUpdateTrigger++
if (typeof ToastService !== "undefined") {
ToastService.clearWallpaperError()
}
} catch (e) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper processing failed (JSON parse error after extraction)")
}
}
}
}
onExited: code => {
if (code !== 0) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Matugen command failed with exit code " + code)
}
}
}
}
Process {
id: colorMatugenProcess
command: ["matugen", "color", "hex", wallpaperPath, "--json", "hex"]
stdout: StdioCollector {
id: colorMatugenCollector
onStreamFinished: {
if (!colorMatugenCollector.text) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Color Processing Failed: Empty JSON extracted from matugen output.")
}
return
}
const extractedJson = extractJsonFromText(colorMatugenCollector.text)
if (!extractedJson) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Color Processing Failed: Invalid JSON extracted from matugen output.")
}
console.log("Raw matugen output:", colorMatugenCollector.text)
return
}
try {
root.matugenColors = JSON.parse(extractedJson)
root.colorUpdateTrigger++
if (typeof ToastService !== "undefined") {
ToastService.clearWallpaperError()
}
} catch (e) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Color processing failed (JSON parse error after extraction)")
}
}
}
}
onExited: code => {
if (code !== 0) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Matugen color command failed with exit code " + code)
}
}
}
}
Process { Process {
id: ensureStateDir id: ensureStateDir
@@ -933,6 +786,48 @@ Singleton {
} }
} }
FileView {
id: dynamicColorsFileView
path: stateDir + "/dms-colors.json"
watchChanges: currentTheme === dynamic
function parseAndLoadColors() {
try {
const colorsText = dynamicColorsFileView.text()
if (colorsText) {
root.matugenColors = JSON.parse(colorsText)
root.colorUpdateTrigger++
if (typeof ToastService !== "undefined") {
ToastService.clearWallpaperError()
}
}
} catch (e) {
if (typeof ToastService !== "undefined") {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Dynamic colors parse error: " + e.message)
}
}
}
onLoaded: {
if (currentTheme === dynamic) {
parseAndLoadColors()
}
}
onFileChanged: {
if (currentTheme === dynamic) {
dynamicColorsFileView.reload()
}
}
onLoadFailed: function (error) {
if (currentTheme === dynamic && typeof ToastService !== "undefined") {
ToastService.showError("Failed to read dynamic colors: " + error)
}
}
}
IpcHandler { IpcHandler {
target: "theme" target: "theme"

View File

@@ -77,15 +77,12 @@ Item {
width: parent.width width: parent.width
height: parent.height - ClipboardConstants.headerHeight - 70 height: parent.height - ClipboardConstants.headerHeight - 70
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceLight color: "transparent"
border.color: Theme.outlineLight
border.width: 1
clip: true clip: true
DankListView { DankListView {
id: clipboardListView id: clipboardListView
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS
model: filteredModel model: filteredModel
currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0 currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0

View File

@@ -24,17 +24,10 @@ Rectangle {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (isSelected) { if (isSelected) {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) return Theme.primaryPressed
} }
return mouseArea.containsMouse ? Theme.primaryHover : Theme.primaryBackground return mouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
} }
border.color: {
if (isSelected) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.5)
}
return Theme.outlineStrong
}
border.width: isSelected ? 1.5 : 1
Row { Row {
anchors.fill: parent anchors.fill: parent

View File

@@ -181,7 +181,7 @@ DankModal {
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
height: 52 height: 52
color: Theme.surfaceSelected color: Theme.surfaceContainerHigh
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Theme.outlineLight border.color: Theme.outlineLight
border.width: 1 border.width: 1
@@ -281,7 +281,7 @@ DankModal {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceLight color: Theme.surfaceContainerHigh
border.color: Theme.outlineLight border.color: Theme.outlineLight
border.width: 1 border.width: 1

View File

@@ -31,7 +31,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: timeoutSection id: timeoutSection

View File

@@ -59,23 +59,21 @@ Item {
Column { Column {
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingL anchors.margins: Theme.spacingM
spacing: Theme.spacingL spacing: Theme.spacingM
Rectangle { Rectangle {
width: parent.width width: parent.width
height: categorySelector.height + Theme.spacingM * 2 height: categorySelector.height + Theme.spacingS * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceVariantAlpha color: "transparent"
border.color: Theme.outlineMedium
border.width: 1
visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0 visible: appLauncher.categories.length > 1 || appLauncher.model.count > 0
CategorySelector { CategorySelector {
id: categorySelector id: categorySelector
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width - Theme.spacingM * 2 width: parent.width - Theme.spacingS * 2
categories: appLauncher.categories categories: appLauncher.categories
selectedCategory: appLauncher.selectedCategory selectedCategory: appLauncher.selectedCategory
compact: false compact: false
@@ -88,14 +86,15 @@ Item {
Row { Row {
width: parent.width width: parent.width
spacing: Theme.spacingM spacing: Theme.spacingM
leftPadding: Theme.spacingS
DankTextField { DankTextField {
id: searchField id: searchField
width: parent.width - 80 - Theme.spacingM width: parent.width - 80 - Theme.spacingL
height: 56 height: 56
cornerRadius: Theme.cornerRadius cornerRadius: Theme.cornerRadius
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7) backgroundColor: Theme.surfaceContainerHigh
normalBorderColor: Theme.outlineMedium normalBorderColor: Theme.outlineMedium
focusedBorderColor: Theme.primary focusedBorderColor: Theme.primary
leftIconName: "search" leftIconName: "search"
@@ -141,8 +140,6 @@ Item {
height: 36 height: 36
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent" color: appLauncher.viewMode === "list" ? Theme.primaryHover : listViewArea.containsMouse ? Theme.surfaceHover : "transparent"
border.color: appLauncher.viewMode === "list" ? Theme.primarySelected : "transparent"
border.width: 1
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -168,8 +165,6 @@ Item {
height: 36 height: 36
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent" color: appLauncher.viewMode === "grid" ? Theme.primaryHover : gridViewArea.containsMouse ? Theme.surfaceHover : "transparent"
border.color: appLauncher.viewMode === "grid" ? Theme.primarySelected : "transparent"
border.width: 1
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent

View File

@@ -13,9 +13,7 @@ Rectangle {
width: parent.width width: parent.width
height: parent.height - y height: parent.height - y
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceLight color: "transparent"
border.color: Theme.outlineLight
border.width: 1
DankListView { DankListView {
id: resultsList id: resultsList
@@ -75,9 +73,7 @@ Rectangle {
width: ListView.view.width width: ListView.view.width
height: resultsList.itemHeight height: resultsList.itemHeight
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
border.width: ListView.isCurrentItem ? 2 : 1
Row { Row {
anchors.fill: parent anchors.fill: parent
@@ -238,9 +234,7 @@ Rectangle {
width: resultsGrid.cellWidth - resultsGrid.cellPadding width: resultsGrid.cellWidth - resultsGrid.cellPadding
height: resultsGrid.cellHeight - resultsGrid.cellPadding height: resultsGrid.cellHeight - resultsGrid.cellPadding
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: resultsGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
border.color: resultsGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
border.width: resultsGrid.currentIndex === index ? 2 : 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent

View File

@@ -33,7 +33,7 @@ DankPopout {
popupWidth: 520 popupWidth: 520
popupHeight: 600 popupHeight: 600
triggerX: Theme.spacingL triggerX: Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS triggerY: Math.max(26 + SettingsData.topBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.topBarInnerPadding)) + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance
triggerWidth: 40 triggerWidth: 40
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -95,7 +95,7 @@ DankPopout {
color: "transparent" color: "transparent"
radius: parent.radius + Math.abs(modelData.margin) radius: parent.radius + Math.abs(modelData.margin)
border.color: modelData.color border.color: modelData.color
border.width: 1 border.width: 0
z: modelData.z z: modelData.z
} }
} }
@@ -136,15 +136,16 @@ DankPopout {
} }
Column { Column {
width: parent.width - Theme.spacingL * 2 width: parent.width - Theme.spacingS * 2
height: parent.height - Theme.spacingL * 2 height: parent.height - Theme.spacingS * 2
x: Theme.spacingL x: Theme.spacingS
y: Theme.spacingL y: Theme.spacingS
spacing: Theme.spacingL spacing: Theme.spacingS
Row { Row {
width: parent.width width: parent.width
height: 40 height: 40
leftPadding: Theme.spacingS
StyledText { StyledText {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -170,7 +171,8 @@ DankPopout {
DankTextField { DankTextField {
id: searchField id: searchField
width: parent.width width: parent.width - Theme.spacingS * 2
anchors.horizontalCenter: parent.horizontalCenter
height: 52 height: 52
cornerRadius: Theme.cornerRadius cornerRadius: Theme.cornerRadius
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7) backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.7)
@@ -231,6 +233,8 @@ DankPopout {
height: 40 height: 40
spacing: Theme.spacingM spacing: Theme.spacingM
visible: searchField.text.length === 0 visible: searchField.text.length === 0
leftPadding: Theme.spacingS
topPadding: Theme.spacingXS
Item { Item {
width: 200 width: 200
@@ -238,6 +242,9 @@ DankPopout {
DankDropdown { DankDropdown {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
text: "" text: ""
currentValue: appLauncher.selectedCategory currentValue: appLauncher.selectedCategory
options: appLauncher.categories options: appLauncher.categories
@@ -249,7 +256,7 @@ DankPopout {
} }
Item { Item {
width: parent.width - 300 width: parent.width - 310
height: 1 height: 1
} }
@@ -286,15 +293,13 @@ DankPopout {
Rectangle { Rectangle {
width: parent.width width: parent.width
height: { height: {
let usedHeight = 40 + Theme.spacingL let usedHeight = 40 + Theme.spacingS
usedHeight += 52 + Theme.spacingL usedHeight += 52 + Theme.spacingS
usedHeight += (searchField.text.length === 0 ? 40 + Theme.spacingL : 0) usedHeight += (searchField.text.length === 0 ? 40 : 0)
return parent.height - usedHeight return parent.height - usedHeight
} }
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: 1
DankListView { DankListView {
id: appList id: appList
@@ -323,7 +328,9 @@ DankPopout {
} }
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
visible: appLauncher.viewMode === "list" visible: appLauncher.viewMode === "list"
model: appLauncher.model model: appLauncher.model
currentIndex: appLauncher.selectedIndex currentIndex: appLauncher.selectedIndex
@@ -353,9 +360,7 @@ DankPopout {
width: ListView.view.width width: ListView.view.width
height: appList.itemHeight height: appList.itemHeight
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: ListView.isCurrentItem ? Theme.primaryPressed : listMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
border.color: ListView.isCurrentItem ? Theme.primarySelected : Theme.outlineMedium
border.width: ListView.isCurrentItem ? 2 : 1
Row { Row {
anchors.fill: parent anchors.fill: parent
@@ -371,6 +376,7 @@ DankPopout {
id: listIconImg id: listIconImg
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingXS
source: Quickshell.iconPath(model.icon, true) source: Quickshell.iconPath(model.icon, true)
smooth: true smooth: true
asynchronous: true asynchronous: true
@@ -379,10 +385,13 @@ DankPopout {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingM
visible: !listIconImg.visible visible: !listIconImg.visible
color: Theme.surfaceLight color: Theme.surfaceLight
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.width: 1 border.width: 0
border.color: Theme.primarySelected border.color: Theme.primarySelected
StyledText { StyledText {
@@ -425,6 +434,9 @@ DankPopout {
id: listMouseArea id: listMouseArea
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingM
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
@@ -484,7 +496,9 @@ DankPopout {
} }
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
visible: appLauncher.viewMode === "grid" visible: appLauncher.viewMode === "grid"
model: appLauncher.model model: appLauncher.model
clip: true clip: true
@@ -516,9 +530,7 @@ DankPopout {
width: appGrid.cellWidth - appGrid.cellPadding width: appGrid.cellWidth - appGrid.cellPadding
height: appGrid.cellHeight - appGrid.cellPadding height: appGrid.cellHeight - appGrid.cellPadding
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.03) color: appGrid.currentIndex === index ? Theme.primaryPressed : gridMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
border.color: appGrid.currentIndex === index ? Theme.primarySelected : Theme.outlineMedium
border.width: appGrid.currentIndex === index ? 2 : 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -535,6 +547,9 @@ DankPopout {
id: gridIconImg id: gridIconImg
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
source: Quickshell.iconPath(model.icon, true) source: Quickshell.iconPath(model.icon, true)
smooth: true smooth: true
asynchronous: true asynchronous: true
@@ -543,10 +558,13 @@ DankPopout {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
visible: !gridIconImg.visible visible: !gridIconImg.visible
color: Theme.surfaceLight color: Theme.surfaceLight
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.width: 1 border.width: 0
border.color: Theme.primarySelected border.color: Theme.primarySelected
StyledText { StyledText {
@@ -577,6 +595,9 @@ DankPopout {
id: gridMouseArea id: gridMouseArea
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.bottomMargin: Theme.spacingS
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.RightButton
@@ -653,7 +674,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.popupBackground() color: Theme.popupBackground()
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
z: 1000 z: 1000
opacity: menuVisible ? 1 : 0 opacity: menuVisible ? 1 : 0
scale: menuVisible ? 1 : 0.85 scale: menuVisible ? 1 : 0.85

View File

@@ -15,7 +15,7 @@ Item {
readonly property int maxCompactItems: 8 readonly property int maxCompactItems: 8
readonly property int itemHeight: 36 readonly property int itemHeight: 36
readonly property color selectedBorderColor: "transparent" readonly property color selectedBorderColor: "transparent"
readonly property color unselectedBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) readonly property color unselectedBorderColor: "transparent"
function handleCategoryClick(category) { function handleCategoryClick(category) {
selectedCategory = category selectedCategory = category
@@ -42,8 +42,7 @@ Item {
height: root.itemHeight height: root.itemHeight
width: root.getButtonWidth(itemCount, parent.width) width: root.getButtonWidth(itemCount, parent.width)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: selectedCategory === modelData ? Theme.primary : "transparent" color: selectedCategory === modelData ? Theme.primary : Theme.surfaceContainerHigh
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -82,7 +81,7 @@ Item {
height: root.itemHeight height: root.itemHeight
width: root.getButtonWidth(itemCount, parent.width) width: root.getButtonWidth(itemCount, parent.width)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: selectedCategory === modelData ? Theme.primary : "transparent" color: selectedCategory === modelData ? Theme.primary : Theme.surfaceContainerHigh
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
StyledText { StyledText {
@@ -118,7 +117,7 @@ Item {
height: root.itemHeight height: root.itemHeight
width: root.getButtonWidth(itemCount, parent.width) width: root.getButtonWidth(itemCount, parent.width)
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: selectedCategory === modelData ? Theme.primary : "transparent" color: selectedCategory === modelData ? Theme.primary : Theme.surfaceContainerHigh
border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor border.color: selectedCategory === modelData ? selectedBorderColor : unselectedBorderColor
StyledText { StyledText {

View File

@@ -25,8 +25,7 @@ Rectangle {
readonly property color _tileBgActive: Theme.primary readonly property color _tileBgActive: Theme.primary
readonly property color _tileBgInactive: readonly property color _tileBgInactive:
Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.surfaceContainerHigh
Theme.getContentBackgroundAlpha() * 0.60)
readonly property color _tileRingActive: readonly property color _tileRingActive:
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22) Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)

View File

@@ -6,12 +6,14 @@ Item {
id: root id: root
property string expandedSection: "" property string expandedSection: ""
property var expandedWidgetData: null
Loader { Loader {
width: parent.width width: parent.width
height: 250 height: 250
y: Theme.spacingS y: Theme.spacingS
active: parent.height > 0 active: parent.height > 0
property string sectionKey: root.expandedSection
sourceComponent: { sourceComponent: {
switch (root.expandedSection) { switch (root.expandedSection) {
case "network": case "network":
@@ -20,9 +22,17 @@ Item {
case "audioOutput": return audioOutputDetailComponent case "audioOutput": return audioOutputDetailComponent
case "audioInput": return audioInputDetailComponent case "audioInput": return audioInputDetailComponent
case "battery": return batteryDetailComponent case "battery": return batteryDetailComponent
default: return null default:
if (root.expandedSection.startsWith("diskUsage_")) {
return diskUsageDetailComponent
}
return null
} }
} }
onSectionKeyChanged: {
active = false
active = true
}
} }
Component { Component {
@@ -49,4 +59,28 @@ Item {
id: batteryDetailComponent id: batteryDetailComponent
BatteryDetail {} BatteryDetail {}
} }
Component {
id: diskUsageDetailComponent
DiskUsageDetail {
currentMountPath: root.expandedWidgetData?.mountPath || "/"
instanceId: root.expandedWidgetData?.instanceId || ""
onMountPathChanged: (newMountPath) => {
if (root.expandedWidgetData && root.expandedWidgetData.id === "diskUsage") {
const widgets = SettingsData.controlCenterWidgets || []
const newWidgets = widgets.map(w => {
if (w.id === "diskUsage" && w.instanceId === root.expandedWidgetData.instanceId) {
const updatedWidget = Object.assign({}, w)
updatedWidget.mountPath = newMountPath
return updatedWidget
}
return w
})
SettingsData.setControlCenterWidgets(newWidgets)
}
}
}
}
} }

View File

@@ -0,0 +1,91 @@
import QtQuick
import qs.Common
import qs.Modules.ControlCenter.Details
Item {
id: root
property string expandedSection: ""
property var expandedWidgetData: null
height: active ? 250 : 0
visible: active
readonly property bool active: expandedSection !== ""
Behavior on height {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Easing.OutCubic
}
}
Loader {
anchors.fill: parent
anchors.topMargin: Theme.spacingS
sourceComponent: {
if (!root.active) return null
if (expandedSection.startsWith("diskUsage_")) {
return diskUsageDetailComponent
}
switch (expandedSection) {
case "wifi": return networkDetailComponent
case "bluetooth": return bluetoothDetailComponent
case "audioOutput": return audioOutputDetailComponent
case "audioInput": return audioInputDetailComponent
case "battery": return batteryDetailComponent
default: return null
}
}
}
Component {
id: networkDetailComponent
NetworkDetail {}
}
Component {
id: bluetoothDetailComponent
BluetoothDetail {}
}
Component {
id: audioOutputDetailComponent
AudioOutputDetail {}
}
Component {
id: audioInputDetailComponent
AudioInputDetail {}
}
Component {
id: batteryDetailComponent
BatteryDetail {}
}
Component {
id: diskUsageDetailComponent
DiskUsageDetail {
currentMountPath: root.expandedWidgetData?.mountPath || "/"
instanceId: root.expandedWidgetData?.instanceId || ""
onMountPathChanged: (newMountPath) => {
if (root.expandedWidgetData && root.expandedWidgetData.id === "diskUsage") {
const widgets = SettingsData.controlCenterWidgets || []
const newWidgets = widgets.map(w => {
if (w.id === "diskUsage" && w.instanceId === root.expandedWidgetData.instanceId) {
const updatedWidget = Object.assign({}, w)
updatedWidget.mountPath = newMountPath
return updatedWidget
}
return w
})
SettingsData.setControlCenterWidgets(newWidgets)
}
}
}
}
}

View File

@@ -12,6 +12,7 @@ Column {
property string expandedSection: "" property string expandedSection: ""
property int expandedWidgetIndex: -1 property int expandedWidgetIndex: -1
property var model: null property var model: null
property var expandedWidgetData: null
signal expandClicked(var widgetData, int globalIndex) signal expandClicked(var widgetData, int globalIndex)
signal removeWidget(int index) signal removeWidget(int index)
@@ -28,12 +29,28 @@ Column {
return LayoutUtils.calculateRowsAndWidgets(root, expandedSection, expandedWidgetIndex) return LayoutUtils.calculateRowsAndWidgets(root, expandedSection, expandedWidgetIndex)
} }
Repeater { property var layoutResult: {
model: { const dummy = [expandedSection, expandedWidgetIndex, model?.controlCenterWidgets]
const result = root.calculateRowsAndWidgets() return calculateRowsAndWidgets()
root.expandedRowIndex = result.expandedRowIndex }
return result.rows
onLayoutResultChanged: {
expandedRowIndex = layoutResult.expandedRowIndex
}
function moveToTop(item) {
const children = root.children
for (var i = 0; i < children.length; i++) {
if (children[i] === item)
continue
if (children[i].z)
children[i].z = Math.min(children[i].z, 999)
} }
item.z = 1000
}
Repeater {
model: root.layoutResult.rows
Column { Column {
width: root.width width: root.width
@@ -45,8 +62,8 @@ Column {
if (widgets.length === 0) return false if (widgets.length === 0) return false
return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider") return widgets.every(w => w.id === "volumeSlider" || w.id === "brightnessSlider" || w.id === "inputVolumeSlider")
} }
topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -12) : 0 topPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
bottomPadding: isSliderOnlyRow ? (root.editMode ? 4 : -12) : 0 bottomPadding: isSliderOnlyRow ? (root.editMode ? 4 : -6) : 0
Flow { Flow {
width: parent.width width: parent.width
@@ -55,13 +72,19 @@ Column {
Repeater { Repeater {
model: rowWidgets || [] model: rowWidgets || []
Item { DragDropWidgetWrapper {
property var widgetData: modelData widgetData: modelData
property int globalWidgetIndex: { property int globalWidgetIndex: {
const widgets = SettingsData.controlCenterWidgets || [] const widgets = SettingsData.controlCenterWidgets || []
for (var i = 0; i < widgets.length; i++) { for (var i = 0; i < widgets.length; i++) {
if (widgets[i].id === modelData.id) { if (widgets[i].id === modelData.id) {
return i if (modelData.id === "diskUsage") {
if (widgets[i].instanceId === modelData.instanceId) {
return i
}
} else {
return i
}
} }
} }
return -1 return -1
@@ -80,34 +103,41 @@ Column {
return baseWidth return baseWidth
} }
} }
height: 60 height: isSliderOnlyRow ? 48 : 60
Loader {
id: widgetLoader
anchors.fill: parent
property var widgetData: parent.widgetData
property int widgetIndex: parent.globalWidgetIndex
property int globalWidgetIndex: parent.globalWidgetIndex
property int widgetWidth: parent.widgetWidth
sourceComponent: {
const id = modelData.id || ""
if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
return compoundPillComponent
} else if (id === "volumeSlider") {
return audioSliderComponent
} else if (id === "brightnessSlider") {
return brightnessSliderComponent
} else if (id === "inputVolumeSlider") {
return inputAudioSliderComponent
} else if (id === "battery") {
return widgetWidth <= 25 ? smallBatteryComponent : batteryPillComponent
} else {
return widgetWidth <= 25 ? smallToggleComponent : toggleButtonComponent
}
}
editMode: root.editMode
widgetIndex: globalWidgetIndex
gridCellWidth: width
gridCellHeight: height
gridColumns: 4
gridLayout: root
isSlider: {
const id = modelData.id || ""
return id === "volumeSlider" || id === "brightnessSlider" || id === "inputVolumeSlider"
} }
widgetComponent: {
const id = modelData.id || ""
if (id === "wifi" || id === "bluetooth" || id === "audioOutput" || id === "audioInput") {
return compoundPillComponent
} else if (id === "volumeSlider") {
return audioSliderComponent
} else if (id === "brightnessSlider") {
return brightnessSliderComponent
} else if (id === "inputVolumeSlider") {
return inputAudioSliderComponent
} else if (id === "battery") {
return widgetWidth <= 25 ? smallBatteryComponent : batteryPillComponent
} else if (id === "diskUsage") {
return diskUsagePillComponent
} else {
return widgetWidth <= 25 ? smallToggleComponent : toggleButtonComponent
}
}
onWidgetMoved: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
onRemoveWidget: index => root.removeWidget(index)
onToggleWidgetSize: index => root.toggleWidgetSize(index)
} }
} }
} }
@@ -115,9 +145,19 @@ Column {
DetailHost { DetailHost {
width: parent.width width: parent.width
height: active ? (250 + Theme.spacingS) : 0 height: active ? (250 + Theme.spacingS) : 0
property bool active: root.expandedSection !== "" && rowIndex === root.expandedRowIndex property bool active: {
if (root.expandedSection === "") return false
if (root.expandedSection.startsWith("diskUsage_") && root.expandedWidgetData) {
const expandedInstanceId = root.expandedWidgetData.instanceId
return rowWidgets.some(w => w.id === "diskUsage" && w.instanceId === expandedInstanceId)
}
return rowIndex === root.expandedRowIndex
}
visible: active visible: active
expandedSection: root.expandedSection expandedSection: root.expandedSection
expandedWidgetData: root.expandedWidgetData
} }
} }
} }
@@ -132,201 +172,198 @@ Column {
height: 60 height: 60
iconName: { iconName: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "wifi": { case "wifi":
if (NetworkService.wifiToggling) { {
if (NetworkService.wifiToggling)
return "sync" return "sync"
} if (NetworkService.networkStatus === "ethernet")
if (NetworkService.networkStatus === "ethernet") {
return "settings_ethernet" return "settings_ethernet"
} if (NetworkService.networkStatus === "wifi")
if (NetworkService.networkStatus === "wifi") {
return NetworkService.wifiSignalIcon return NetworkService.wifiSignalIcon
} if (NetworkService.wifiEnabled)
if (NetworkService.wifiEnabled) {
return "wifi_off" return "wifi_off"
}
return "wifi_off" return "wifi_off"
} }
case "bluetooth": { case "bluetooth":
if (!BluetoothService.available) { {
if (!BluetoothService.available)
return "bluetooth_disabled" return "bluetooth_disabled"
} if (!BluetoothService.adapter || !BluetoothService.adapter.enabled)
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
return "bluetooth_disabled" return "bluetooth_disabled"
}
const primaryDevice = (() => { const primaryDevice = (() => {
if (!BluetoothService.adapter || !BluetoothService.adapter.devices) { if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
return null return null
} let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))] for (let device of devices) {
for (let device of devices) { if (device && device.connected)
if (device && device.connected) { return device
return device }
} return null
} })()
return null if (primaryDevice)
})()
if (primaryDevice) {
return BluetoothService.getDeviceIcon(primaryDevice) return BluetoothService.getDeviceIcon(primaryDevice)
}
return "bluetooth" return "bluetooth"
} }
case "audioOutput": { case "audioOutput":
if (!AudioService.sink) return "volume_off" {
if (!AudioService.sink)
return "volume_off"
let volume = AudioService.sink.audio.volume let volume = AudioService.sink.audio.volume
let muted = AudioService.sink.audio.muted let muted = AudioService.sink.audio.muted
if (muted || volume === 0.0) return "volume_off" if (muted || volume === 0.0)
if (volume <= 0.33) return "volume_down" return "volume_off"
if (volume <= 0.66) return "volume_up" if (volume <= 0.33)
return "volume_down"
if (volume <= 0.66)
return "volume_up"
return "volume_up" return "volume_up"
} }
case "audioInput": { case "audioInput":
if (!AudioService.source) return "mic_off" {
if (!AudioService.source)
return "mic_off"
let muted = AudioService.source.audio.muted let muted = AudioService.source.audio.muted
return muted ? "mic_off" : "mic" return muted ? "mic_off" : "mic"
} }
default: return widgetDef?.icon || "help" default:
return widgetDef?.icon || "help"
} }
} }
primaryText: { primaryText: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "wifi": { case "wifi":
if (NetworkService.wifiToggling) { {
if (NetworkService.wifiToggling)
return NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..." return NetworkService.wifiEnabled ? "Disabling WiFi..." : "Enabling WiFi..."
} if (NetworkService.networkStatus === "ethernet")
if (NetworkService.networkStatus === "ethernet") {
return "Ethernet" return "Ethernet"
} if (NetworkService.networkStatus === "wifi" && NetworkService.currentWifiSSID)
if (NetworkService.networkStatus === "wifi" && NetworkService.currentWifiSSID) {
return NetworkService.currentWifiSSID return NetworkService.currentWifiSSID
} if (NetworkService.wifiEnabled)
if (NetworkService.wifiEnabled) {
return "Not connected" return "Not connected"
}
return "WiFi off" return "WiFi off"
} }
case "bluetooth": { case "bluetooth":
if (!BluetoothService.available) { {
if (!BluetoothService.available)
return "Bluetooth" return "Bluetooth"
} if (!BluetoothService.adapter)
if (!BluetoothService.adapter) {
return "No adapter" return "No adapter"
} if (!BluetoothService.adapter.enabled)
if (!BluetoothService.adapter.enabled) {
return "Disabled" return "Disabled"
}
return "Enabled" return "Enabled"
} }
case "audioOutput": return AudioService.sink?.description || "No output device" case "audioOutput":
case "audioInput": return AudioService.source?.description || "No input device" return AudioService.sink?.description || "No output device"
default: return widgetDef?.text || "Unknown" case "audioInput":
return AudioService.source?.description || "No input device"
default:
return widgetDef?.text || "Unknown"
} }
} }
secondaryText: { secondaryText: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "wifi": { case "wifi":
if (NetworkService.wifiToggling) { {
if (NetworkService.wifiToggling)
return "Please wait..." return "Please wait..."
} if (NetworkService.networkStatus === "ethernet")
if (NetworkService.networkStatus === "ethernet") {
return "Connected" return "Connected"
} if (NetworkService.networkStatus === "wifi")
if (NetworkService.networkStatus === "wifi") {
return NetworkService.wifiSignalStrength > 0 ? NetworkService.wifiSignalStrength + "%" : "Connected" return NetworkService.wifiSignalStrength > 0 ? NetworkService.wifiSignalStrength + "%" : "Connected"
} if (NetworkService.wifiEnabled)
if (NetworkService.wifiEnabled) {
return "Select network" return "Select network"
}
return "" return ""
} }
case "bluetooth": { case "bluetooth":
if (!BluetoothService.available) { {
if (!BluetoothService.available)
return "No adapters" return "No adapters"
} if (!BluetoothService.adapter || !BluetoothService.adapter.enabled)
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
return "Off" return "Off"
}
const primaryDevice = (() => { const primaryDevice = (() => {
if (!BluetoothService.adapter || !BluetoothService.adapter.devices) { if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
return null return null
} let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))] for (let device of devices) {
for (let device of devices) { if (device && device.connected)
if (device && device.connected) { return device
return device }
} return null
} })()
return null if (primaryDevice)
})()
if (primaryDevice) {
return primaryDevice.name || primaryDevice.alias || primaryDevice.deviceName || "Connected Device" return primaryDevice.name || primaryDevice.alias || primaryDevice.deviceName || "Connected Device"
}
return "No devices" return "No devices"
} }
case "audioOutput": { case "audioOutput":
if (!AudioService.sink) { {
if (!AudioService.sink)
return "Select device" return "Select device"
} if (AudioService.sink.audio.muted)
if (AudioService.sink.audio.muted) {
return "Muted" return "Muted"
}
return Math.round(AudioService.sink.audio.volume * 100) + "%" return Math.round(AudioService.sink.audio.volume * 100) + "%"
} }
case "audioInput": { case "audioInput":
if (!AudioService.source) { {
if (!AudioService.source)
return "Select device" return "Select device"
} if (AudioService.source.audio.muted)
if (AudioService.source.audio.muted) {
return "Muted" return "Muted"
}
return Math.round(AudioService.source.audio.volume * 100) + "%" return Math.round(AudioService.source.audio.volume * 100) + "%"
} }
default: return widgetDef?.description || "" default:
return widgetDef?.description || ""
} }
} }
isActive: { isActive: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "wifi": { case "wifi":
if (NetworkService.wifiToggling) { {
if (NetworkService.wifiToggling)
return false return false
} if (NetworkService.networkStatus === "ethernet")
if (NetworkService.networkStatus === "ethernet") {
return true return true
} if (NetworkService.networkStatus === "wifi")
if (NetworkService.networkStatus === "wifi") {
return true return true
}
return NetworkService.wifiEnabled return NetworkService.wifiEnabled
} }
case "bluetooth": return !!(BluetoothService.available && BluetoothService.adapter && BluetoothService.adapter.enabled) case "bluetooth":
case "audioOutput": return !!(AudioService.sink && !AudioService.sink.audio.muted) return !!(BluetoothService.available && BluetoothService.adapter && BluetoothService.adapter.enabled)
case "audioInput": return !!(AudioService.source && !AudioService.source.audio.muted) case "audioOutput":
default: return false return !!(AudioService.sink && !AudioService.sink.audio.muted)
case "audioInput":
return !!(AudioService.source && !AudioService.source.audio.muted)
default:
return false
} }
} }
enabled: (widgetDef?.enabled ?? true) enabled: widgetDef?.enabled ?? true
onToggled: { onToggled: {
if (root.editMode) return if (root.editMode) return
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "wifi": { case "wifi":
{
if (NetworkService.networkStatus !== "ethernet" && !NetworkService.wifiToggling) { if (NetworkService.networkStatus !== "ethernet" && !NetworkService.wifiToggling) {
NetworkService.toggleWifiRadio() NetworkService.toggleWifiRadio()
} }
break break
} }
case "bluetooth": { case "bluetooth":
{
if (BluetoothService.available && BluetoothService.adapter) { if (BluetoothService.available && BluetoothService.adapter) {
BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled BluetoothService.adapter.enabled = !BluetoothService.adapter.enabled
} }
break break
} }
case "audioOutput": { case "audioOutput":
{
if (AudioService.sink && AudioService.sink.audio) { if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = !AudioService.sink.audio.muted AudioService.sink.audio.muted = !AudioService.sink.audio.muted
} }
break break
} }
case "audioInput": { case "audioInput":
{
if (AudioService.source && AudioService.source.audio) { if (AudioService.source && AudioService.source.audio) {
AudioService.source.audio.muted = !AudioService.source.audio.muted AudioService.source.audio.muted = !AudioService.source.audio.muted
} }
@@ -339,9 +376,11 @@ Column {
root.expandClicked(widgetData, widgetIndex) root.expandClicked(widgetData, widgetIndex)
} }
onWheelEvent: function (wheelEvent) { onWheelEvent: function (wheelEvent) {
if (root.editMode) return
const id = widgetData.id || "" const id = widgetData.id || ""
if (id === "audioOutput") { if (id === "audioOutput") {
if (!AudioService.sink || !AudioService.sink.audio) return if (!AudioService.sink || !AudioService.sink.audio)
return
let delta = wheelEvent.angleDelta.y let delta = wheelEvent.angleDelta.y
let currentVolume = AudioService.sink.audio.volume * 100 let currentVolume = AudioService.sink.audio.volume * 100
let newVolume let newVolume
@@ -353,7 +392,8 @@ Column {
AudioService.sink.audio.volume = newVolume / 100 AudioService.sink.audio.volume = newVolume / 100
wheelEvent.accepted = true wheelEvent.accepted = true
} else if (id === "audioInput") { } else if (id === "audioInput") {
if (!AudioService.source || !AudioService.source.audio) return if (!AudioService.source || !AudioService.source.audio)
return
let delta = wheelEvent.angleDelta.y let delta = wheelEvent.angleDelta.y
let currentVolume = AudioService.source.audio.volume * 100 let currentVolume = AudioService.source.audio.volume * 100
let newVolume let newVolume
@@ -366,18 +406,6 @@ Column {
wheelEvent.accepted = true wheelEvent.accepted = true
} }
} }
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: false
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
}
} }
} }
@@ -386,7 +414,6 @@ Column {
Item { Item {
property var widgetData: parent.widgetData || {} property var widgetData: parent.widgetData || {}
property int widgetIndex: parent.widgetIndex || 0 property int widgetIndex: parent.widgetIndex || 0
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
width: parent.width width: parent.width
height: 16 height: 16
@@ -394,19 +421,7 @@ Column {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width width: parent.width
height: 14 height: 14
property color sliderTrackColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) property color sliderTrackColor: Theme.surfaceContainerHigh
}
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: true
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
} }
} }
} }
@@ -423,19 +438,7 @@ Column {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width width: parent.width
height: 14 height: 14
property color sliderTrackColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) property color sliderTrackColor: Theme.surfaceContainerHigh
}
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: true
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
} }
} }
} }
@@ -452,19 +455,7 @@ Column {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width width: parent.width
height: 14 height: 14
property color sliderTrackColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) property color sliderTrackColor: Theme.surfaceContainerHigh
}
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: true
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
} }
} }
} }
@@ -482,18 +473,6 @@ Column {
root.expandClicked(widgetData, widgetIndex) root.expandClicked(widgetData, widgetIndex)
} }
} }
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: false
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
}
} }
} }
@@ -510,18 +489,6 @@ Column {
root.expandClicked(widgetData, widgetIndex) root.expandClicked(widgetData, widgetIndex)
} }
} }
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: false
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
}
} }
} }
@@ -530,80 +497,85 @@ Column {
ToggleButton { ToggleButton {
property var widgetData: parent.widgetData || {} property var widgetData: parent.widgetData || {}
property int widgetIndex: parent.widgetIndex || 0 property int widgetIndex: parent.widgetIndex || 0
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
width: parent.width width: parent.width
height: 60 height: 60
iconName: { iconName: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode" case "nightMode":
case "darkMode": return "contrast" return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode"
case "doNotDisturb": return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off" case "darkMode":
case "idleInhibitor": return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle" return "contrast"
default: return widgetDef?.icon || "help" case "doNotDisturb":
return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off"
case "idleInhibitor":
return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
default:
return "help"
} }
} }
text: { text: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": return "Night Mode" case "nightMode":
case "darkMode": return SessionData.isLightMode ? "Light Mode" : "Dark Mode" return "Night Mode"
case "doNotDisturb": return "Do Not Disturb" case "darkMode":
case "idleInhibitor": return SessionService.idleInhibited ? "Keeping Awake" : "Keep Awake" return SessionData.isLightMode ? "Light Mode" : "Dark Mode"
default: return widgetDef?.text || "Unknown" case "doNotDisturb":
return "Do Not Disturb"
case "idleInhibitor":
return SessionService.idleInhibited ? "Keeping Awake" : "Keep Awake"
default:
return "Unknown"
} }
} }
secondaryText: ""
iconRotation: widgetData.id === "darkMode" && SessionData.isLightMode ? 180 : 0 iconRotation: widgetData.id === "darkMode" && SessionData.isLightMode ? 180 : 0
isActive: { isActive: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": return DisplayService.nightModeEnabled || false case "nightMode":
case "darkMode": return !SessionData.isLightMode return DisplayService.nightModeEnabled || false
case "doNotDisturb": return SessionData.doNotDisturb || false case "darkMode":
case "idleInhibitor": return SessionService.idleInhibited || false return !SessionData.isLightMode
default: return false case "doNotDisturb":
return SessionData.doNotDisturb || false
case "idleInhibitor":
return SessionService.idleInhibited || false
default:
return false
} }
} }
enabled: (widgetDef?.enabled ?? true) && !root.editMode enabled: !root.editMode
onClicked: { onClicked: {
if (root.editMode)
return
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": { case "nightMode":
if (DisplayService.automationAvailable) { {
if (DisplayService.automationAvailable)
DisplayService.toggleNightMode() DisplayService.toggleNightMode()
}
break break
} }
case "darkMode": { case "darkMode":
{
Theme.toggleLightMode() Theme.toggleLightMode()
break break
} }
case "doNotDisturb": { case "doNotDisturb":
{
SessionData.setDoNotDisturb(!SessionData.doNotDisturb) SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
break break
} }
case "idleInhibitor": { case "idleInhibitor":
{
SessionService.toggleIdleInhibit() SessionService.toggleIdleInhibit()
break break
} }
} }
} }
EditModeOverlay {
anchors.fill: parent
editMode: root.editMode
widgetData: parent.widgetData
widgetIndex: parent.widgetIndex
showSizeControls: true
isSlider: false
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index)
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex)
}
} }
} }
@@ -612,17 +584,21 @@ Column {
SmallToggleButton { SmallToggleButton {
property var widgetData: parent.widgetData || {} property var widgetData: parent.widgetData || {}
property int widgetIndex: parent.widgetIndex || 0 property int widgetIndex: parent.widgetIndex || 0
property var widgetDef: root.model?.getWidgetForId(widgetData.id || "")
width: parent.width width: parent.width
height: 48 height: 48
iconName: { iconName: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode" case "nightMode":
case "darkMode": return "contrast" return DisplayService.nightModeEnabled ? "nightlight" : "dark_mode"
case "doNotDisturb": return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off" case "darkMode":
case "idleInhibitor": return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle" return "contrast"
default: return widgetDef?.icon || "help" case "doNotDisturb":
return SessionData.doNotDisturb ? "do_not_disturb_on" : "do_not_disturb_off"
case "idleInhibitor":
return SessionService.idleInhibited ? "motion_sensor_active" : "motion_sensor_idle"
default:
return "help"
} }
} }
@@ -630,49 +606,66 @@ Column {
isActive: { isActive: {
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": return DisplayService.nightModeEnabled || false case "nightMode":
case "darkMode": return !SessionData.isLightMode return DisplayService.nightModeEnabled || false
case "doNotDisturb": return SessionData.doNotDisturb || false case "darkMode":
case "idleInhibitor": return SessionService.idleInhibited || false return !SessionData.isLightMode
default: return false case "doNotDisturb":
return SessionData.doNotDisturb || false
case "idleInhibitor":
return SessionService.idleInhibited || false
default:
return false
} }
} }
enabled: (widgetDef?.enabled ?? true) && !root.editMode enabled: !root.editMode
onClicked: { onClicked: {
if (root.editMode)
return
switch (widgetData.id || "") { switch (widgetData.id || "") {
case "nightMode": { case "nightMode":
if (DisplayService.automationAvailable) { {
if (DisplayService.automationAvailable)
DisplayService.toggleNightMode() DisplayService.toggleNightMode()
}
break break
} }
case "darkMode": { case "darkMode":
{
Theme.toggleLightMode() Theme.toggleLightMode()
break break
} }
case "doNotDisturb": { case "doNotDisturb":
{
SessionData.setDoNotDisturb(!SessionData.doNotDisturb) SessionData.setDoNotDisturb(!SessionData.doNotDisturb)
break break
} }
case "idleInhibitor": { case "idleInhibitor":
{
SessionService.toggleIdleInhibit() SessionService.toggleIdleInhibit()
break break
} }
} }
} }
}
}
EditModeOverlay { Component {
anchors.fill: parent id: diskUsagePillComponent
editMode: root.editMode DiskUsagePill {
widgetData: parent.widgetData property var widgetData: parent.widgetData || {}
widgetIndex: parent.widgetIndex property int widgetIndex: parent.widgetIndex || 0
showSizeControls: true width: parent.width
isSlider: false height: 60
onRemoveWidget: (index) => root.removeWidget(index)
onToggleWidgetSize: (index) => root.toggleWidgetSize(index) mountPath: widgetData.mountPath || "/"
onMoveWidget: (fromIndex, toIndex) => root.moveWidget(fromIndex, toIndex) instanceId: widgetData.instanceId || ""
onExpandClicked: {
if (!root.editMode) {
root.expandClicked(widgetData, widgetIndex)
}
} }
} }
} }

View File

@@ -0,0 +1,289 @@
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: root
property bool editMode: false
property var widgetData: null
property int widgetIndex: -1
property bool isSlider: false
property Component widgetComponent: null
property real gridCellWidth: 100
property real gridCellHeight: 60
property int gridColumns: 4
property var gridLayout: null
z: dragArea.drag.active ? 10000 : 1
signal widgetMoved(int fromIndex, int toIndex)
signal removeWidget(int index)
signal toggleWidgetSize(int index)
width: {
const widgetWidth = widgetData?.width || 50
if (widgetWidth <= 25) return gridCellWidth
else if (widgetWidth <= 50) return gridCellWidth * 2
else if (widgetWidth <= 75) return gridCellWidth * 3
else return gridCellWidth * 4
}
height: isSlider ? 16 : gridCellHeight
Rectangle {
id: dragIndicator
anchors.fill: parent
color: "transparent"
border.color: Theme.primary
border.width: dragArea.drag.active ? 2 : 0
radius: Theme.cornerRadius
opacity: dragArea.drag.active ? 0.8 : 1.0
z: dragArea.drag.active ? 10000 : 1
Behavior on border.width {
NumberAnimation { duration: 150 }
}
Behavior on opacity {
NumberAnimation { duration: 150 }
}
}
Loader {
id: widgetLoader
anchors.fill: parent
sourceComponent: widgetComponent
property var widgetData: root.widgetData
property int widgetIndex: root.widgetIndex
property int globalWidgetIndex: root.widgetIndex
property int widgetWidth: root.widgetData?.width || 50
MouseArea {
id: editModeBlocker
anchors.fill: parent
enabled: root.editMode
acceptedButtons: Qt.AllButtons
onPressed: function(mouse) { mouse.accepted = true }
onWheel: function(wheel) { wheel.accepted = true }
z: 100
}
}
MouseArea {
id: dragArea
anchors.fill: parent
enabled: editMode
cursorShape: editMode ? Qt.OpenHandCursor : Qt.PointingHandCursor
drag.target: editMode ? root : null
drag.axis: Drag.XAndYAxis
drag.smoothed: true
onPressed: function(mouse) {
if (editMode) {
cursorShape = Qt.ClosedHandCursor
if (root.gridLayout && root.gridLayout.moveToTop) {
root.gridLayout.moveToTop(root)
}
}
}
onReleased: function(mouse) {
if (editMode) {
cursorShape = Qt.OpenHandCursor
root.snapToGrid()
}
}
}
Drag.active: dragArea.drag.active
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
function swapIndices(i, j) {
if (i === j) return;
const arr = SettingsData.controlCenterWidgets;
if (!arr || i < 0 || j < 0 || i >= arr.length || j >= arr.length) return;
const copy = arr.slice();
const tmp = copy[i];
copy[i] = copy[j];
copy[j] = tmp;
SettingsData.setControlCenterWidgets(copy);
}
function snapToGrid() {
if (!editMode || !gridLayout) return
const globalPos = root.mapToItem(gridLayout, 0, 0)
const cellWidth = gridLayout.width / gridColumns
const cellHeight = gridCellHeight + Theme.spacingS
const centerX = globalPos.x + (root.width / 2)
const centerY = globalPos.y + (root.height / 2)
let targetCol = Math.max(0, Math.floor(centerX / cellWidth))
let targetRow = Math.max(0, Math.floor(centerY / cellHeight))
targetCol = Math.min(targetCol, gridColumns - 1)
const newIndex = findBestInsertionIndex(targetRow, targetCol)
if (newIndex !== widgetIndex && newIndex >= 0 && newIndex < (SettingsData.controlCenterWidgets?.length || 0)) {
swapIndices(widgetIndex, newIndex)
}
}
function findBestInsertionIndex(targetRow, targetCol) {
const widgets = SettingsData.controlCenterWidgets || [];
const n = widgets.length;
if (!n || widgetIndex < 0 || widgetIndex >= n) return -1;
function spanFor(width) {
const w = width ?? 50;
if (w <= 25) return 1;
if (w <= 50) return 2;
if (w <= 75) return 3;
return 4;
}
const cols = gridColumns || 4;
let row = 0, col = 0;
let draggedOrigKey = null;
const pos = [];
for (let i = 0; i < n; i++) {
const span = Math.min(spanFor(widgets[i].width), cols);
if (col + span > cols) {
row++;
col = 0;
}
const startCol = col;
const centerKey = row * cols + (startCol + (span - 1) / 2);
if (i === widgetIndex) {
draggedOrigKey = centerKey;
} else {
pos.push({ index: i, row, startCol, span, centerKey });
}
col += span;
if (col >= cols) {
row++;
col = 0;
}
}
if (pos.length === 0) return -1;
const centerColCoord = targetCol + 0.5;
const targetKey = targetRow * cols + centerColCoord;
for (let k = 0; k < pos.length; k++) {
const p = pos[k];
if (p.row === targetRow && centerColCoord >= p.startCol && centerColCoord < (p.startCol + p.span)) {
return p.index;
}
}
let lo = 0, hi = pos.length - 1;
if (targetKey <= pos[0].centerKey) return pos[0].index;
if (targetKey >= pos[hi].centerKey) return pos[hi].index;
while (lo <= hi) {
const mid = (lo + hi) >> 1;
const mk = pos[mid].centerKey;
if (targetKey < mk) hi = mid - 1;
else if (targetKey > mk) lo = mid + 1;
else return pos[mid].index;
}
const movingUp = (draggedOrigKey != null) ? (targetKey < draggedOrigKey) : false;
return (movingUp ? pos[lo].index : pos[hi].index);
}
Rectangle {
width: 16
height: 16
radius: 8
color: Theme.error
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: -4
visible: editMode
z: 10
DankIcon {
anchors.centerIn: parent
name: "close"
size: 12
color: Theme.primaryText
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: removeWidget(widgetIndex)
}
}
PieChartSizeControl {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: -6
visible: editMode
z: 10
currentSize: root.widgetData?.width || 50
isSlider: root.isSlider
widgetIndex: root.widgetIndex
onSizeChanged: (newSize) => {
var widgets = SettingsData.controlCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets[widgetIndex].width = newSize
SettingsData.setControlCenterWidgets(widgets)
}
}
}
Rectangle {
id: dragHandle
width: 16
height: 12
radius: 2
color: Theme.primary
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 4
visible: editMode
z: 15
opacity: dragArea.drag.active ? 1.0 : 0.7
DankIcon {
anchors.centerIn: parent
name: "drag_indicator"
size: 10
color: Theme.primaryText
}
Behavior on opacity {
NumberAnimation { duration: 150 }
}
}
Rectangle {
anchors.fill: parent
color: editMode ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius
border.color: "transparent"
border.width: 0
z: -1
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
}
}

View File

@@ -29,7 +29,7 @@ Row {
background: Rectangle { background: Rectangle {
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.primarySelected border.color: Theme.primarySelected
border.width: 1 border.width: 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
} }
@@ -72,9 +72,9 @@ Row {
width: 400 - Theme.spacingL * 2 width: 400 - Theme.spacingL * 2
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: widgetMouseArea.containsMouse ? Theme.primaryHover : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: widgetMouseArea.containsMouse ? Theme.primaryHover : Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Row { Row {
anchors.fill: parent anchors.fill: parent
@@ -138,7 +138,7 @@ Row {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Theme.primary border.color: Theme.primary
border.width: 1 border.width: 0
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -172,7 +172,7 @@ Row {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12) color: Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12)
border.color: Theme.warning border.color: Theme.warning
border.width: 1 border.width: 0
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -206,7 +206,7 @@ Row {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
border.color: Theme.error border.color: Theme.error
border.width: 1 border.width: 0
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent

View File

@@ -1,241 +0,0 @@
import QtQuick
import qs.Common
import qs.Widgets
Item {
id: root
property bool editMode: false
property var widgetData: null
property int widgetIndex: -1
property bool showSizeControls: true
property bool isSlider: false
signal removeWidget(int index)
signal toggleWidgetSize(int index)
signal moveWidget(int fromIndex, int toIndex)
// Delete button in top-right
Rectangle {
width: 16
height: 16
radius: 8
color: Theme.error
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: -4
visible: editMode
z: 10
DankIcon {
anchors.centerIn: parent
name: "close"
size: 12
color: Theme.primaryText
}
MouseArea {
anchors.fill: parent
onClicked: root.removeWidget(widgetIndex)
}
}
// Size control buttons in bottom-right
Row {
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.margins: -8
spacing: 4
visible: editMode && showSizeControls
z: 10
Rectangle {
width: 24
height: 24
radius: 12
color: (widgetData?.width || 50) === 25 ? Theme.primary : Theme.primaryContainer
border.color: Theme.primary
border.width: 1
visible: !isSlider
StyledText {
anchors.centerIn: parent
text: "25"
font.pixelSize: 10
font.weight: Font.Medium
color: (widgetData?.width || 50) === 25 ? Theme.primaryText : Theme.primary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
var widgets = SettingsData.controlCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets[widgetIndex].width = 25
SettingsData.setControlCenterWidgets(widgets)
}
}
}
}
Rectangle {
width: 24
height: 24
radius: 12
color: (widgetData?.width || 50) === 50 ? Theme.primary : Theme.primaryContainer
border.color: Theme.primary
border.width: 1
StyledText {
anchors.centerIn: parent
text: "50"
font.pixelSize: 10
font.weight: Font.Medium
color: (widgetData?.width || 50) === 50 ? Theme.primaryText : Theme.primary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
var widgets = SettingsData.controlCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets[widgetIndex].width = 50
SettingsData.setControlCenterWidgets(widgets)
}
}
}
}
Rectangle {
width: 24
height: 24
radius: 12
color: (widgetData?.width || 50) === 75 ? Theme.primary : Theme.primaryContainer
border.color: Theme.primary
border.width: 1
visible: !isSlider
StyledText {
anchors.centerIn: parent
text: "75"
font.pixelSize: 10
font.weight: Font.Medium
color: (widgetData?.width || 50) === 75 ? Theme.primaryText : Theme.primary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
var widgets = SettingsData.controlCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets[widgetIndex].width = 75
SettingsData.setControlCenterWidgets(widgets)
}
}
}
}
Rectangle {
width: 24
height: 24
radius: 12
color: (widgetData?.width || 50) === 100 ? Theme.primary : Theme.primaryContainer
border.color: Theme.primary
border.width: 1
StyledText {
anchors.centerIn: parent
text: "100"
font.pixelSize: 9
font.weight: Font.Medium
color: (widgetData?.width || 50) === 100 ? Theme.primaryText : Theme.primary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
var widgets = SettingsData.controlCenterWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
widgets[widgetIndex].width = 100
SettingsData.setControlCenterWidgets(widgets)
}
}
}
}
}
// Arrow buttons for reordering in top-left
Row {
anchors.top: parent.top
anchors.left: parent.left
anchors.margins: 4
spacing: 2
visible: editMode
z: 20
Rectangle {
width: 16
height: 16
radius: 8
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
DankIcon {
anchors.centerIn: parent
name: "keyboard_arrow_left"
size: 12
color: Theme.surfaceText
}
MouseArea {
anchors.fill: parent
enabled: widgetIndex > 0
opacity: enabled ? 1.0 : 0.5
onClicked: root.moveWidget(widgetIndex, widgetIndex - 1)
}
}
Rectangle {
width: 16
height: 16
radius: 8
color: Theme.surfaceContainer
border.color: Theme.outline
border.width: 1
DankIcon {
anchors.centerIn: parent
name: "keyboard_arrow_right"
size: 12
color: Theme.surfaceText
}
MouseArea {
anchors.fill: parent
enabled: widgetIndex < ((SettingsData.controlCenterWidgets?.length ?? 0) - 1)
opacity: enabled ? 1.0 : 0.5
onClicked: root.moveWidget(widgetIndex, widgetIndex + 1)
}
}
}
// Border highlight
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
radius: Theme.cornerRadius
border.color: Theme.primary
border.width: editMode ? 1 : 0
visible: editMode
z: -1
Behavior on border.width {
NumberAnimation { duration: Theme.shortDuration }
}
}
}

View File

@@ -15,13 +15,10 @@ Rectangle {
implicitHeight: 70 implicitHeight: 70
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08) Theme.outline.b, 0.08)
border.width: 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left

View File

@@ -18,10 +18,7 @@ Item {
width: parent.width width: parent.width
height: 60 height: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.4)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08) Theme.outline.b, 0.08)
border.width: root.expanded ? 1 : 0 border.width: root.expanded ? 1 : 0

View File

@@ -26,11 +26,30 @@ DankPopout {
property var triggerScreen: null property var triggerScreen: null
property bool editMode: false property bool editMode: false
property int expandedWidgetIndex: -1 property int expandedWidgetIndex: -1
property var expandedWidgetData: null
signal powerActionRequested(string action, string title, string message) signal powerActionRequested(string action, string title, string message)
signal lockRequested signal lockRequested
readonly property color _containerBg: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) function collapseAll() {
expandedSection = ""
expandedWidgetIndex = -1
expandedWidgetData = null
}
onEditModeChanged: {
if (editMode) {
collapseAll()
}
}
onVisibleChanged: {
if (!visible) {
collapseAll()
}
}
readonly property color _containerBg: Theme.surfaceContainerHigh
function setTriggerPosition(x, y, width, section, screen) { function setTriggerPosition(x, y, width, section, screen) {
StateUtils.setTriggerPosition(root, x, y, width, section, screen) StateUtils.setTriggerPosition(root, x, y, width, section, screen)
@@ -47,7 +66,7 @@ DankPopout {
popupWidth: 550 popupWidth: 550
popupHeight: Math.min((triggerScreen?.height ?? 1080) - 100, contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400) popupHeight: Math.min((triggerScreen?.height ?? 1080) - 100, contentLoader.item && contentLoader.item.implicitHeight > 0 ? contentLoader.item.implicitHeight + 20 : 400)
triggerX: (triggerScreen?.width ?? 1920) - 600 - Theme.spacingL triggerX: (triggerScreen?.width ?? 1920) - 600 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.popupDistance
triggerWidth: 80 triggerWidth: 80
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -90,7 +109,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08) Theme.outline.b, 0.08)
border.width: 1 border.width: 0
antialiasing: true antialiasing: true
smooth: true smooth: true
@@ -126,16 +145,22 @@ DankPopout {
} }
} }
WidgetGrid { DragDropGrid {
id: widgetGrid id: widgetGrid
width: parent.width width: parent.width
editMode: root.editMode editMode: root.editMode
expandedSection: root.expandedSection expandedSection: root.expandedSection
expandedWidgetIndex: root.expandedWidgetIndex expandedWidgetIndex: root.expandedWidgetIndex
expandedWidgetData: root.expandedWidgetData
model: widgetModel model: widgetModel
onExpandClicked: (widgetData, globalIndex) => { onExpandClicked: (widgetData, globalIndex) => {
root.expandedWidgetIndex = globalIndex root.expandedWidgetIndex = globalIndex
root.toggleSection(widgetData.id) root.expandedWidgetData = widgetData
if (widgetData.id === "diskUsage") {
root.toggleSection("diskUsage_" + (widgetData.instanceId || "default"))
} else {
root.toggleSection(widgetData.id)
}
} }
onRemoveWidget: (index) => widgetModel.removeWidget(index) onRemoveWidget: (index) => widgetModel.removeWidget(index)
onMoveWidget: (fromIndex, toIndex) => widgetModel.moveWidget(fromIndex, toIndex) onMoveWidget: (fromIndex, toIndex) => widgetModel.moveWidget(fromIndex, toIndex)
@@ -147,7 +172,7 @@ DankPopout {
visible: editMode visible: editMode
availableWidgets: { availableWidgets: {
const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id) const existingIds = (SettingsData.controlCenterWidgets || []).map(w => w.id)
return widgetModel.baseWidgetDefinitions.filter(w => !existingIds.includes(w.id)) return widgetModel.baseWidgetDefinitions.filter(w => w.allowMultiple || !existingIds.includes(w.id))
} }
onAddWidget: (widgetId) => widgetModel.addWidget(widgetId) onAddWidget: (widgetId) => widgetModel.addWidget(widgetId)
onResetToDefault: () => widgetModel.resetToDefault() onResetToDefault: () => widgetModel.resetToDefault()

View File

@@ -14,9 +14,9 @@ Rectangle {
implicitHeight: headerRow.height + (hasInputVolumeSliderInCC ? 0 : volumeSlider.height) + audioContent.height + Theme.spacingM implicitHeight: headerRow.height + (hasInputVolumeSliderInCC ? 0 : volumeSlider.height) + audioContent.height + Theme.spacingM
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
Row { Row {
id: headerRow id: headerRow
@@ -57,10 +57,6 @@ Rectangle {
radius: (Theme.iconSize + Theme.spacingS * 2) / 2 radius: (Theme.iconSize + Theme.spacingS * 2) / 2
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
MouseArea { MouseArea {
id: iconArea id: iconArea
anchors.fill: parent anchors.fill: parent
@@ -138,9 +134,9 @@ Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2) color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: modelData === AudioService.source ? 2 : 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -198,14 +194,6 @@ Rectangle {
} }
} }
} }
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
Behavior on border.color {
ColorAnimation { duration: Theme.shortDuration }
}
} }
} }
} }

View File

@@ -14,9 +14,9 @@ Rectangle {
implicitHeight: headerRow.height + (!hasVolumeSliderInCC ? volumeSlider.height : 0) + audioContent.height + Theme.spacingM implicitHeight: headerRow.height + (!hasVolumeSliderInCC ? volumeSlider.height : 0) + audioContent.height + Theme.spacingM
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
Row { Row {
id: headerRow id: headerRow
@@ -57,10 +57,6 @@ Rectangle {
radius: (Theme.iconSize + Theme.spacingS * 2) / 2 radius: (Theme.iconSize + Theme.spacingS * 2) / 2
color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" color: iconArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
MouseArea { MouseArea {
id: iconArea id: iconArea
anchors.fill: parent anchors.fill: parent
@@ -143,9 +139,9 @@ Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2) color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: modelData === AudioService.sink ? 2 : 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -205,14 +201,6 @@ Rectangle {
} }
} }
} }
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
Behavior on border.color {
ColorAnimation { duration: Theme.shortDuration }
}
} }
} }
} }

View File

@@ -9,9 +9,9 @@ import qs.Widgets
Rectangle { Rectangle {
implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2 implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
function isActiveProfile(profile) { function isActiveProfile(profile) {
if (typeof PowerProfiles === "undefined") { if (typeof PowerProfiles === "undefined") {
@@ -125,9 +125,8 @@ Rectangle {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 64 height: 64
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) color: Theme.surfaceContainerHighest
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) border.width: 0
border.width: 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -161,9 +160,8 @@ Rectangle {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 64 height: 64
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) color: Theme.surfaceContainerHighest
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) border.width: 0
border.width: 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -211,7 +209,7 @@ Rectangle {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3) border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3)
border.width: 1 border.width: 0
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
Column { Column {

View File

@@ -124,7 +124,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
opacity: modalVisible ? 1 : 0 opacity: modalVisible ? 1 : 0
scale: modalVisible ? 1 : 0.9 scale: modalVisible ? 1 : 0.9
@@ -206,14 +206,14 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: { color: {
if (modelData.name === currentCodec) if (modelData.name === currentCodec)
return Theme.surfaceContainerHigh; return Theme.surfaceContainerHighest;
else if (codecMouseArea.containsMouse) else if (codecMouseArea.containsMouse)
return Theme.surfaceHover; return Theme.surfaceHover;
else else
return "transparent"; return "transparent";
} }
border.color: "transparent" border.color: "transparent"
border.width: 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -272,12 +272,6 @@ Item {
} }
} }
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
} }

View File

@@ -9,9 +9,9 @@ import qs.Widgets
Rectangle { Rectangle {
implicitHeight: BluetoothService.adapter && BluetoothService.adapter.enabled ? headerRow.height + bluetoothContent.height + Theme.spacingM : headerRow.height implicitHeight: BluetoothService.adapter && BluetoothService.adapter.enabled ? headerRow.height + bluetoothContent.height + Theme.spacingM : headerRow.height
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
property var bluetoothCodecModalRef: null property var bluetoothCodecModalRef: null
@@ -58,11 +58,11 @@ Rectangle {
radius: 18 radius: 18
color: { color: {
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) if (!BluetoothService.adapter || !BluetoothService.adapter.enabled)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) return Theme.surfaceContainerHigh
return scanMouseArea.containsMouse ? Theme.surfaceContainerHigh : "transparent" return scanMouseArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
} }
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 1 border.width: 0
visible: BluetoothService.adapter && BluetoothService.adapter.enabled visible: BluetoothService.adapter && BluetoothService.adapter.enabled
Row { Row {
@@ -96,13 +96,6 @@ Rectangle {
BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering
} }
} }
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
} }
} }
@@ -159,7 +152,7 @@ Rectangle {
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12) return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12)
if (deviceMouseArea.containsMouse) if (deviceMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2) return Theme.surfaceContainerHighest
} }
border.color: { border.color: {
if (modelData.state === BluetoothDeviceState.Connecting) if (modelData.state === BluetoothDeviceState.Connecting)
@@ -168,7 +161,7 @@ Rectangle {
return Theme.primary return Theme.primary
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
} }
border.width: (modelData.connected || modelData.state === BluetoothDeviceState.Connecting) ? 2 : 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -284,14 +277,6 @@ Rectangle {
} }
} }
} }
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
Behavior on border.color {
ColorAnimation { duration: Theme.shortDuration }
}
} }
} }
@@ -347,9 +332,9 @@ Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: availableMouseArea.containsMouse && !isBusy ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.15) color: availableMouseArea.containsMouse && !isBusy ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 1 border.width: 0
opacity: canConnect ? 1 : 0.6 opacity: canConnect ? 1 : 0.6
Row { Row {
@@ -427,9 +412,6 @@ Rectangle {
} }
} }
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
} }
} }
@@ -458,7 +440,7 @@ Rectangle {
background: Rectangle { background: Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.width: 1 border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
} }

View File

@@ -0,0 +1,166 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Rectangle {
id: root
property string currentMountPath: "/"
property string instanceId: ""
signal mountPathChanged(string newMountPath)
implicitHeight: diskContent.height + Theme.spacingM
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
Component.onCompleted: {
DgopService.addRef(["diskmounts"])
}
Component.onDestruction: {
DgopService.removeRef(["diskmounts"])
}
DankFlickable {
id: diskContent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: Theme.spacingM
anchors.topMargin: Theme.spacingM
contentHeight: diskColumn.height
clip: true
Column {
id: diskColumn
width: parent.width
spacing: Theme.spacingS
Item {
width: parent.width
height: 100
visible: !DgopService.dgopAvailable || !DgopService.diskMounts || DgopService.diskMounts.length === 0
Column {
anchors.centerIn: parent
spacing: Theme.spacingM
DankIcon {
anchors.horizontalCenter: parent.horizontalCenter
name: DgopService.dgopAvailable ? "storage" : "error"
size: 32
color: DgopService.dgopAvailable ? Theme.primary : Theme.error
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: DgopService.dgopAvailable ? "No disk data available" : "dgop not available"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
horizontalAlignment: Text.AlignHCenter
}
}
}
Repeater {
model: DgopService.diskMounts || []
delegate: Rectangle {
required property var modelData
required property int index
width: parent.width
height: 80
radius: Theme.cornerRadius
color: Theme.surfaceContainerHighest
border.color: modelData.mount === currentMountPath ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: modelData.mount === currentMountPath ? 2 : 0
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingM
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
DankIcon {
name: "storage"
size: Theme.iconSize
color: {
const percentStr = modelData.percent?.replace("%", "") || "0"
const percent = parseFloat(percentStr) || 0
if (percent > 90) return Theme.error
if (percent > 75) return Theme.warning
return modelData.mount === currentMountPath ? Theme.primary : Theme.surfaceText
}
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: {
const percentStr = modelData.percent?.replace("%", "") || "0"
const percent = parseFloat(percentStr) || 0
return percent.toFixed(0) + "%"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - 50 - Theme.spacingM
StyledText {
text: modelData.mount === "/" ? "Root Filesystem" : modelData.mount
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: modelData.mount === currentMountPath ? Font.Medium : Font.Normal
elide: Text.ElideRight
width: parent.width
}
StyledText {
text: modelData.mount
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
visible: modelData.mount !== "/"
}
StyledText {
text: `${modelData.used || "?"} / ${modelData.size || "?"}`
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
width: parent.width
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
currentMountPath = modelData.mount
mountPathChanged(modelData.mount)
}
}
}
}
}
}
}

View File

@@ -17,9 +17,9 @@ Rectangle {
return headerRow.height + wifiOffContent.height + Theme.spacingM return headerRow.height + wifiOffContent.height + Theme.spacingM
} }
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
Component.onCompleted: { Component.onCompleted: {
NetworkService.addRef() NetworkService.addRef()
@@ -32,15 +32,6 @@ Rectangle {
NetworkService.removeRef() NetworkService.removeRef()
} }
property var wifiPasswordModalRef: {
wifiPasswordModalLoader.active = true
return wifiPasswordModalLoader.item
}
property var networkInfoModalRef: {
networkInfoModalLoader.active = true
return networkInfoModalLoader.item
}
Row { Row {
id: headerRow id: headerRow
anchors.left: parent.left anchors.left: parent.left
@@ -158,7 +149,7 @@ Rectangle {
height: 36 height: 36
radius: 18 radius: 18
color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
border.width: 1 border.width: 0
border.color: Theme.primary border.color: Theme.primary
StyledText { StyledText {
@@ -177,12 +168,6 @@ Rectangle {
onClicked: NetworkService.toggleWifiRadio() onClicked: NetworkService.toggleWifiRadio()
} }
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
} }
} }
} }
@@ -242,9 +227,9 @@ Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2) color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: modelData.ssid === NetworkService.currentWifiSSID ? 2 : 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left
@@ -332,9 +317,7 @@ Rectangle {
onClicked: function(event) { onClicked: function(event) {
if (modelData.ssid !== NetworkService.currentWifiSSID) { if (modelData.ssid !== NetworkService.currentWifiSSID) {
if (modelData.secured && !modelData.saved) { if (modelData.secured && !modelData.saved) {
if (wifiPasswordModalRef) { wifiPasswordModal.show(modelData.ssid)
wifiPasswordModalRef.show(modelData.ssid)
}
} else { } else {
NetworkService.connectToWifi(modelData.ssid) NetworkService.connectToWifi(modelData.ssid)
} }
@@ -343,13 +326,6 @@ Rectangle {
} }
} }
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
Behavior on border.color {
ColorAnimation { duration: Theme.shortDuration }
}
} }
} }
} }
@@ -369,7 +345,7 @@ Rectangle {
background: Rectangle { background: Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.width: 1 border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
} }
@@ -395,9 +371,7 @@ Rectangle {
NetworkService.disconnectWifi() NetworkService.disconnectWifi()
} else { } else {
if (networkContextMenu.currentSecured && !networkContextMenu.currentSaved) { if (networkContextMenu.currentSecured && !networkContextMenu.currentSaved) {
if (wifiPasswordModalRef) { wifiPasswordModal.show(networkContextMenu.currentSSID)
wifiPasswordModalRef.show(networkContextMenu.currentSSID)
}
} else { } else {
NetworkService.connectToWifi(networkContextMenu.currentSSID) NetworkService.connectToWifi(networkContextMenu.currentSSID)
} }
@@ -423,10 +397,8 @@ Rectangle {
} }
onTriggered: { onTriggered: {
if (networkInfoModalRef) { let networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID)
let networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID) networkInfoModal.showNetworkInfo(networkContextMenu.currentSSID, networkData)
networkInfoModalRef.showNetworkInfo(networkContextMenu.currentSSID, networkData)
}
} }
} }
@@ -454,22 +426,12 @@ Rectangle {
} }
} }
LazyLoader { WifiPasswordModal {
id: wifiPasswordModalLoader id: wifiPasswordModal
active: false
WifiPasswordModal {
id: wifiPasswordModal
}
} }
LazyLoader { NetworkInfoModal {
id: networkInfoModalLoader id: networkInfoModal
active: false
NetworkInfoModal {
id: networkInfoModal
}
} }

View File

@@ -106,6 +106,16 @@ QtObject {
"icon": "battery_std", "icon": "battery_std",
"type": "action", "type": "action",
"enabled": true "enabled": true
},
{
"id": "diskUsage",
"text": "Disk Usage",
"description": "Filesystem usage monitoring",
"icon": "storage",
"type": "action",
"enabled": DgopService.dgopAvailable,
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined,
"allowMultiple": true
} }
] ]

View File

@@ -44,7 +44,7 @@ PanelWindow {
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08) Theme.outline.b, 0.08)
border.width: 1 border.width: 0
opacity: powerMenuVisible ? 1 : 0 opacity: powerMenuVisible ? 1 : 0
scale: powerMenuVisible ? 1 : 0.85 scale: powerMenuVisible ? 1 : 0.85

View File

@@ -70,7 +70,7 @@ Row {
unit: "%" unit: "%"
valueOverride: actualVolumePercent valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.surfaceContainerHigh
onSliderValueChanged: function(newValue) { onSliderValueChanged: function(newValue) {
if (defaultSink) { if (defaultSink) {
defaultSink.audio.volume = newValue / 100.0 defaultSink.audio.volume = newValue / 100.0

View File

@@ -30,9 +30,6 @@ CompoundPill {
if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) { if (!BluetoothService.adapter || !BluetoothService.adapter.enabled) {
return "bluetooth_disabled" return "bluetooth_disabled"
} }
if (primaryDevice) {
return BluetoothService.getDeviceIcon(primaryDevice)
}
return "bluetooth" return "bluetooth"
} }

View File

@@ -80,7 +80,7 @@ Row {
} }
} }
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
trackColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) trackColor: Theme.surfaceContainerHigh
} }
Menu { Menu {
@@ -91,7 +91,7 @@ Row {
background: Rectangle { background: Rectangle {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.width: 1 border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
} }

View File

@@ -20,9 +20,9 @@ Rectangle {
width: parent ? parent.width : 200 width: parent ? parent.width : 200
height: 60 height: 60
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.6) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
opacity: enabled ? 1.0 : 0.6 opacity: enabled ? 1.0 : 0.6
Row { Row {

View File

@@ -27,13 +27,14 @@ Rectangle {
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor) return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor)
} }
readonly property color _containerBg: readonly property color _containerBg: Theme.surfaceContainerHigh
Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.60)
color: _containerBg color: {
const baseColor = bodyMouse.containsMouse ? Theme.widgetBaseHoverColor : _containerBg
return baseColor
}
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10)
border.width: 1 border.width: 0
antialiasing: true antialiasing: true
readonly property color _labelPrimary: Theme.surfaceText readonly property color _labelPrimary: Theme.surfaceText

View File

@@ -0,0 +1,78 @@
import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.ControlCenter.Widgets
CompoundPill {
id: root
property string mountPath: "/"
property string instanceId: ""
iconName: "storage"
property var selectedMount: {
if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) {
return null
}
const targetMount = DgopService.diskMounts.find(mount => mount.mount === mountPath)
return targetMount || DgopService.diskMounts.find(mount => mount.mount === "/") || DgopService.diskMounts[0]
}
property real usagePercent: {
if (!selectedMount || !selectedMount.percent) {
return 0
}
const percentStr = selectedMount.percent.replace("%", "")
return parseFloat(percentStr) || 0
}
isActive: DgopService.dgopAvailable && selectedMount !== null
primaryText: {
if (!DgopService.dgopAvailable) {
return "Disk Usage"
}
if (!selectedMount) {
return "No disk data"
}
return selectedMount.mount
}
secondaryText: {
if (!DgopService.dgopAvailable) {
return "dgop not available"
}
if (!selectedMount) {
return "No disk data available"
}
return `${selectedMount.used} / ${selectedMount.size} (${usagePercent.toFixed(0)}%)`
}
iconColor: {
if (!DgopService.dgopAvailable || !selectedMount) {
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
}
if (usagePercent > 90) {
return Theme.error
}
if (usagePercent > 75) {
return Theme.warning
}
return Theme.surfaceText
}
Component.onCompleted: {
DgopService.addRef(["diskmounts"])
}
Component.onDestruction: {
DgopService.removeRef(["diskmounts"])
}
onToggled: {
expandClicked()
}
}

View File

@@ -68,7 +68,7 @@ Row {
unit: "%" unit: "%"
valueOverride: actualVolumePercent valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainer
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, Theme.getContentBackgroundAlpha() * 0.60) trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.surfaceContainerHigh
onSliderValueChanged: function(newValue) { onSliderValueChanged: function(newValue) {
if (defaultSource) { if (defaultSource) {
defaultSource.audio.volume = newValue / 100.0 defaultSource.audio.volume = newValue / 100.0

View File

@@ -25,15 +25,17 @@ Rectangle {
} }
readonly property color _tileBgActive: Theme.primary readonly property color _tileBgActive: Theme.primary
readonly property color _tileBgInactive: readonly property color _tileBgInactive: Theme.surfaceContainerHigh
Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.60)
readonly property color _tileRingActive: readonly property color _tileRingActive:
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22) Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
readonly property color _tileIconActive: Theme.primaryContainer readonly property color _tileIconActive: Theme.primaryContainer
readonly property color _tileIconInactive: Theme.primary readonly property color _tileIconInactive: Theme.primary
color: isActive ? _tileBgActive : _tileBgInactive color: {
if (isActive) return _tileBgActive
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : _tileBgInactive
return baseColor
}
border.color: isActive ? _tileRingActive : "transparent" border.color: isActive ? _tileRingActive : "transparent"
border.width: isActive ? 1 : 0 border.width: isActive ? 1 : 0
antialiasing: true antialiasing: true

View File

@@ -26,15 +26,17 @@ Rectangle {
} }
readonly property color _tileBgActive: Theme.primary readonly property color _tileBgActive: Theme.primary
readonly property color _tileBgInactive: readonly property color _tileBgInactive: Theme.surfaceContainerHigh
Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.60)
readonly property color _tileRingActive: readonly property color _tileRingActive:
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22) Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
readonly property color _tileIconActive: Theme.primaryContainer readonly property color _tileIconActive: Theme.primaryContainer
readonly property color _tileIconInactive: Theme.primary readonly property color _tileIconInactive: Theme.primary
color: isActive ? _tileBgActive : _tileBgInactive color: {
if (isActive) return _tileBgActive
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : _tileBgInactive
return baseColor
}
border.color: isActive ? _tileRingActive : "transparent" border.color: isActive ? _tileRingActive : "transparent"
border.width: isActive ? 1 : 0 border.width: isActive ? 1 : 0
antialiasing: true antialiasing: true

View File

@@ -23,15 +23,17 @@ Rectangle {
} }
readonly property color _tileBgActive: Theme.primary readonly property color _tileBgActive: Theme.primary
readonly property color _tileBgInactive: readonly property color _tileBgInactive: Theme.surfaceContainerHigh
Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.60)
readonly property color _tileRingActive: readonly property color _tileRingActive:
Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22) Qt.rgba(Theme.primaryText.r, Theme.primaryText.g, Theme.primaryText.b, 0.22)
color: isActive ? _tileBgActive : _tileBgInactive color: {
if (isActive) return _tileBgActive
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : _tileBgInactive
return baseColor
}
border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: isActive ? 1 : 1 border.width: 0
opacity: enabled ? 1.0 : 0.6 opacity: enabled ? 1.0 : 0.6
function hoverTint(base) { function hoverTint(base) {
@@ -39,9 +41,7 @@ Rectangle {
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor) return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor)
} }
readonly property color _containerBg: readonly property color _containerBg: Theme.surfaceContainerHigh
Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b,
Theme.getContentBackgroundAlpha() * 0.60)
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent

View File

@@ -32,7 +32,7 @@ function calculateRowsAndWidgets(controlCenterColumn, expandedSection, expandedW
currentWidth += (currentRow.length > 1 ? spacing : 0) + itemWidth currentWidth += (currentRow.length > 1 ? spacing : 0) + itemWidth
} }
if (widget.id === expandedSection && expandedWidgetIndex === i) { if (expandedWidgetIndex === i) {
expandedRow = rows.length expandedRow = rows.length
} }
} }

View File

@@ -9,10 +9,20 @@ function addWidget(widgetId) {
"enabled": true, "enabled": true,
"width": 50 "width": 50
} }
if (widgetId === "diskUsage") {
widget.instanceId = generateUniqueId()
widget.mountPath = "/"
}
widgets.push(widget) widgets.push(widget)
SettingsData.setControlCenterWidgets(widgets) SettingsData.setControlCenterWidgets(widgets)
} }
function generateUniqueId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2)
}
function removeWidget(index) { function removeWidget(index) {
var widgets = SettingsData.controlCenterWidgets.slice() var widgets = SettingsData.controlCenterWidgets.slice()
if (index >= 0 && index < widgets.length) { if (index >= 0 && index < widgets.length) {

View File

@@ -34,7 +34,7 @@ DankPopout {
popupWidth: 700 popupWidth: 700
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 500 popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 500
triggerX: Screen.width - 620 - Theme.spacingL triggerX: Screen.width - 620 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS triggerY: Math.max(26 + SettingsData.topBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.topBarInnerPadding)) + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance
triggerWidth: 80 triggerWidth: 80
positioning: "center" positioning: "center"
shouldBeVisible: dashVisible shouldBeVisible: dashVisible

View File

@@ -420,7 +420,7 @@ Item {
width: parent.width width: parent.width
height: 48 height: 48
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: deviceMouseAreaLeft.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2) color: deviceMouseAreaLeft.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.surfaceContainerHigh
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: modelData === AudioService.sink ? 2 : 1 border.width: modelData === AudioService.sink ? 2 : 1
@@ -563,7 +563,7 @@ Item {
width: parent.width width: parent.width
height: 48 height: 48
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: playerMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, index % 2 === 0 ? 0.3 : 0.2) color: playerMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.surfaceContainerHigh
border.color: modelData === activePlayer ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: modelData === activePlayer ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: modelData === activePlayer ? 2 : 1 border.width: modelData === activePlayer ? 2 : 1
@@ -837,7 +837,7 @@ Item {
width: 40 width: 40
height: 40 height: 40
radius: 20 radius: 20
color: prevBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent" color: prevBtnArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
DankIcon { DankIcon {
@@ -903,7 +903,7 @@ Item {
width: 40 width: 40
height: 40 height: 40
radius: 20 radius: 20
color: nextBtnArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent" color: nextBtnArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
DankIcon { DankIcon {
@@ -1115,7 +1115,7 @@ Item {
width: parent.width width: parent.width
height: parent.height height: parent.height
anchors.centerIn: parent anchors.centerIn: parent
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) color: Theme.surfaceContainerHigh
radius: Theme.cornerRadius radius: Theme.cornerRadius
} }

View File

@@ -84,7 +84,7 @@ Rectangle {
} }
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: 1 border.width: 1
@@ -345,7 +345,7 @@ Rectangle {
} else if (eventMouseArea.containsMouse) { } else if (eventMouseArea.containsMouse) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06) return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06)
} }
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) return Theme.surfaceContainerHigh
} }
border.color: { border.color: {
if (modelData.url && eventMouseArea.containsMouse) { if (modelData.url && eventMouseArea.containsMouse) {

View File

@@ -8,7 +8,7 @@ Rectangle {
property int pad: Theme.spacingM property int pad: Theme.spacingM
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 1

View File

@@ -131,7 +131,7 @@ Card {
height: 28 height: 28
radius: 14 radius: 14
anchors.verticalCenter: playPauseButton.verticalCenter anchors.verticalCenter: playPauseButton.verticalCenter
color: prevArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent" color: prevArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
@@ -183,7 +183,7 @@ Card {
height: 28 height: 28
radius: 14 radius: 14
anchors.verticalCenter: playPauseButton.verticalCenter anchors.verticalCenter: playPauseButton.verticalCenter
color: nextArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent" color: nextArea.containsMouse ? Theme.surfaceContainerHigh : "transparent"
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent

View File

@@ -231,7 +231,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -278,7 +278,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -325,7 +325,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -372,7 +372,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -419,7 +419,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -466,7 +466,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -554,7 +554,7 @@ Item {
return null return null
} }
color: isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) : Theme.surfaceContainerHigh
border.color: isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : "transparent" border.color: isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : "transparent"
border.width: isToday ? 1 : 0 border.width: isToday ? 1 : 0

View File

@@ -20,6 +20,7 @@ PanelWindow {
property var contextMenu property var contextMenu
property bool autoHide: SettingsData.dockAutoHide property bool autoHide: SettingsData.dockAutoHide
property real backgroundTransparency: SettingsData.dockTransparency property real backgroundTransparency: SettingsData.dockTransparency
property bool groupByApp: SettingsData.dockGroupByApp
property bool contextMenuOpen: (contextMenu && contextMenu.visible && contextMenu.screen === modelData) property bool contextMenuOpen: (contextMenu && contextMenu.visible && contextMenu.screen === modelData)
property bool windowIsFullscreen: { property bool windowIsFullscreen: {
@@ -135,6 +136,7 @@ PanelWindow {
anchors.bottomMargin: 4 anchors.bottomMargin: 4
contextMenu: dock.contextMenu contextMenu: dock.contextMenu
groupByApp: dock.groupByApp
} }
} }

View File

@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Wayland
import Quickshell.Widgets import Quickshell.Widgets
import qs.Common import qs.Common
import qs.Services import qs.Services
@@ -25,24 +26,39 @@ Item {
property bool isHovered: mouseArea.containsMouse && !dragging property bool isHovered: mouseArea.containsMouse && !dragging
property bool showTooltip: mouseArea.containsMouse && !dragging property bool showTooltip: mouseArea.containsMouse && !dragging
property bool isWindowFocused: { property bool isWindowFocused: {
if (!appData || appData.type !== "window") { if (!appData) {
return false return false
} }
const toplevel = getToplevelObject()
if (!toplevel) { if (appData.type === "window") {
return false const toplevel = getToplevelObject()
if (!toplevel) {
return false
}
return toplevel.activated
} else if (appData.type === "grouped") {
// For grouped apps, check if any window is focused
const allToplevels = ToplevelManager.toplevels.values
for (let i = 0; i < allToplevels.length; i++) {
const toplevel = allToplevels[i]
if (toplevel.appId === appData.appId && toplevel.activated) {
return true
}
}
} }
return toplevel.activated
return false
} }
property string tooltipText: { property string tooltipText: {
if (!appData) { if (!appData) {
return "" return ""
} }
if (appData.type === "window" && showWindowTitle) { if ((appData.type === "window" && showWindowTitle) || (appData.type === "grouped" && appData.windowTitle)) {
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId) const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
const appName = desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId const appName = desktopEntry && desktopEntry.name ? desktopEntry.name : appData.appId
return appName + (windowTitle ? "" + windowTitle : "") const title = appData.type === "window" ? windowTitle : appData.windowTitle
return appName + (title ? " • " + title : "")
} }
if (!appData.appId) { if (!appData.appId) {
@@ -57,7 +73,7 @@ Item {
height: 40 height: 40
function getToplevelObject() { function getToplevelObject() {
if (!appData || appData.type !== "window") { if (!appData) {
return null return null
} }
@@ -66,23 +82,47 @@ Item {
return null return null
} }
if (appData.uniqueId) { if (appData.type === "window") {
for (var i = 0; i < sortedToplevels.length; i++) { if (appData.uniqueId) {
const toplevel = sortedToplevels[i] for (var i = 0; i < sortedToplevels.length; i++) {
const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i const toplevel = sortedToplevels[i]
if (checkId === appData.uniqueId) { const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i
return toplevel if (checkId === appData.uniqueId) {
return toplevel
}
}
}
if (appData.windowId !== undefined && appData.windowId !== null && appData.windowId >= 0) {
if (appData.windowId < sortedToplevels.length) {
return sortedToplevels[appData.windowId]
}
}
} else if (appData.type === "grouped") {
if (appData.windowId !== undefined && appData.windowId !== null && appData.windowId >= 0) {
if (appData.windowId < sortedToplevels.length) {
return sortedToplevels[appData.windowId]
} }
} }
} }
if (appData.windowId !== undefined && appData.windowId !== null && appData.windowId >= 0) { return null
if (appData.windowId < sortedToplevels.length) { }
return sortedToplevels[appData.windowId]
} function getGroupedToplevels() {
if (!appData || appData.type !== "grouped") {
return []
} }
return null const toplevels = []
const allToplevels = ToplevelManager.toplevels.values
for (let i = 0; i < allToplevels.length; i++) {
const toplevel = allToplevels[i]
if (toplevel.appId === appData.appId) {
toplevels.push(toplevel)
}
}
return toplevels
} }
onIsHoveredChanged: { onIsHoveredChanged: {
if (isHovered) { if (isHovered) {
@@ -232,6 +272,36 @@ Item {
if (toplevel) { if (toplevel) {
toplevel.activate() toplevel.activate()
} }
} else if (appData.type === "grouped") {
if (appData.windowCount === 0) {
if (appData && appData.appId) {
const desktopEntry = DesktopEntries.heuristicLookup(appData.appId)
if (desktopEntry) {
AppUsageHistoryData.addAppUsage({
"id": appData.appId,
"name": desktopEntry.name || appData.appId,
"icon": desktopEntry.icon || "",
"exec": desktopEntry.exec || "",
"comment": desktopEntry.comment || ""
})
}
SessionService.launchDesktopEntry(desktopEntry)
}
} else if (appData.windowCount === 1) {
// For single window, activate directly
const toplevel = getToplevelObject()
if (toplevel) {
console.log("Activating grouped app window:", appData.windowTitle)
toplevel.activate()
} else {
console.warn("No toplevel found for grouped app")
}
} else {
// For multiple windows, show context menu (hide pin option for left-click)
if (contextMenu) {
contextMenu.showForButton(root, appData, 65, true)
}
}
} }
} else if (mouse.button === Qt.MiddleButton) { } else if (mouse.button === Qt.MiddleButton) {
if (appData && appData.appId) { if (appData && appData.appId) {
@@ -248,8 +318,11 @@ Item {
SessionService.launchDesktopEntry(desktopEntry) SessionService.launchDesktopEntry(desktopEntry)
} }
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
if (contextMenu) { if (contextMenu && appData) {
contextMenu.showForButton(root, appData, 40) console.log("Right-clicked on app:", appData.appId, "type:", appData.type, "windowCount:", appData.windowCount || 0)
contextMenu.showForButton(root, appData, 40, false)
} else {
console.warn("No context menu or appData available")
} }
} }
} }
@@ -322,31 +395,54 @@ Item {
} }
// Indicator for running/focused state // Indicator for running/focused state
Rectangle { Row {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: -2 anchors.bottomMargin: -2
width: 8 spacing: 2
height: 2 visible: appData && (appData.isRunning || appData.type === "window" || (appData.type === "grouped" && appData.windowCount > 0))
radius: 1
visible: appData && (appData.isRunning || appData.type === "window") Repeater {
color: { model: {
if (!appData) { if (!appData) return 0
return "transparent" if (appData.type === "grouped") {
return Math.min(appData.windowCount, 4)
} else if (appData.type === "window" || appData.isRunning) {
return 1
}
return 0
} }
if (isWindowFocused) { Rectangle {
return Theme.primary width: appData && appData.type === "grouped" && appData.windowCount > 1 ? 4 : 8
} height: 2
radius: 1
color: {
if (!appData) {
return "transparent"
}
if (appData.isRunning || appData.type === "window") { if (appData.type !== "grouped" || appData.windowCount === 1) {
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) if (isWindowFocused) {
} return Theme.primary
}
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
}
return "transparent" if (appData.type === "grouped" && appData.windowCount > 1) {
const groupToplevels = getGroupedToplevels()
if (index < groupToplevels.length && groupToplevels[index].activated) {
return Theme.primary
}
}
return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
}
}
} }
} }
transform: Translate { transform: Translate {
id: translateY id: translateY

View File

@@ -12,6 +12,7 @@ Item {
property var contextMenu: null property var contextMenu: null
property bool requestDockShow: false property bool requestDockShow: false
property int pinnedAppCount: 0 property int pinnedAppCount: 0
property bool groupByApp: false
implicitWidth: row.width implicitWidth: row.width
implicitHeight: row.height implicitHeight: row.height
@@ -50,53 +51,134 @@ Item {
const items = [] const items = []
const pinnedApps = [...(SessionData.pinnedApps || [])] const pinnedApps = [...(SessionData.pinnedApps || [])]
pinnedApps.forEach(appId => {
items.push({
"type": "pinned",
"appId": appId,
"windowId": -1,
"windowTitle": "",
"workspaceId": -1,
"isPinned": true,
"isRunning": false
})
})
root.pinnedAppCount = pinnedApps.length
const sortedToplevels = CompositorService.sortedToplevels const sortedToplevels = CompositorService.sortedToplevels
if (pinnedApps.length > 0 && sortedToplevels.length > 0) { if (root.groupByApp) {
items.push({ // Group windows by appId
"type": "separator", const appGroups = new Map()
"appId": "__SEPARATOR__",
"windowId": -1, // Add pinned apps first (even if they have no windows)
"windowTitle": "", pinnedApps.forEach(appId => {
"workspaceId": -1, appGroups.set(appId, {
"isPinned": false, appId: appId,
"isRunning": false, isPinned: true,
"isFocused": false windows: []
}) })
})
// Group all running windows by appId
sortedToplevels.forEach((toplevel, index) => {
const appId = toplevel.appId || "unknown"
if (!appGroups.has(appId)) {
appGroups.set(appId, {
appId: appId,
isPinned: false,
windows: []
})
}
const title = toplevel.title || "(Unnamed)"
const truncatedTitle = title.length > 50 ? title.substring(0, 47) + "..." : title
const uniqueId = toplevel.title + "|" + (toplevel.appId || "") + "|" + index
appGroups.get(appId).windows.push({
windowId: index,
windowTitle: truncatedTitle,
uniqueId: uniqueId
})
})
// Sort groups: pinned first, then unpinned
const pinnedGroups = []
const unpinnedGroups = []
Array.from(appGroups.entries()).forEach(([appId, group]) => {
// For grouped apps, just show the first window info but track all windows
const firstWindow = group.windows.length > 0 ? group.windows[0] : null
const item = {
"type": "grouped",
"appId": appId,
"windowId": firstWindow ? firstWindow.windowId : -1,
"windowTitle": firstWindow ? firstWindow.windowTitle : "",
"workspaceId": -1,
"isPinned": group.isPinned,
"isRunning": group.windows.length > 0,
"windowCount": group.windows.length,
"uniqueId": firstWindow ? firstWindow.uniqueId : "",
"allWindows": group.windows
}
if (group.isPinned) {
pinnedGroups.push(item)
} else {
unpinnedGroups.push(item)
}
})
// Add items in order
pinnedGroups.forEach(item => items.push(item))
// Add separator if needed
if (pinnedGroups.length > 0 && unpinnedGroups.length > 0) {
items.push({
"type": "separator",
"appId": "__SEPARATOR__",
"windowId": -1,
"windowTitle": "",
"workspaceId": -1,
"isPinned": false,
"isRunning": false
})
}
unpinnedGroups.forEach(item => items.push(item))
root.pinnedAppCount = pinnedGroups.length
} else {
pinnedApps.forEach(appId => {
items.push({
"type": "pinned",
"appId": appId,
"windowId": -1,
"windowTitle": "",
"workspaceId": -1,
"isPinned": true,
"isRunning": false
})
})
root.pinnedAppCount = pinnedApps.length
if (pinnedApps.length > 0 && sortedToplevels.length > 0) {
items.push({
"type": "separator",
"appId": "__SEPARATOR__",
"windowId": -1,
"windowTitle": "",
"workspaceId": -1,
"isPinned": false,
"isRunning": false,
"isFocused": false
})
}
sortedToplevels.forEach((toplevel, index) => {
const title = toplevel.title || "(Unnamed)"
const truncatedTitle = title.length > 50 ? title.substring(0, 47) + "..." : title
const uniqueId = toplevel.title + "|" + (toplevel.appId || "") + "|" + index
items.push({
"type": "window",
"appId": toplevel.appId,
"windowId": index,
"windowTitle": truncatedTitle,
"workspaceId": -1,
"isPinned": false,
"isRunning": true,
"uniqueId": uniqueId
})
})
} }
sortedToplevels.forEach((toplevel, index) => {
const title = toplevel.title || "(Unnamed)"
const truncatedTitle = title.length > 50 ? title.substring(0, 47) + "..." : title
const uniqueId = toplevel.title + "|" + (toplevel.appId || "") + "|" + index
items.push({
"type": "window",
"appId": toplevel.appId,
"windowId": index,
"windowTitle": truncatedTitle,
"workspaceId": -1,
"isPinned": false,
"isRunning": true,
"uniqueId": uniqueId
})
})
items.forEach(item => append(item)) items.forEach(item => append(item))
} }
} }
@@ -131,7 +213,7 @@ Item {
index: model.index index: model.index
// Override tooltip for windows to show window title // Override tooltip for windows to show window title
showWindowTitle: model.type === "window" showWindowTitle: model.type === "window" || model.type === "grouped"
windowTitle: model.windowTitle || "" windowTitle: model.windowTitle || ""
} }
} }
@@ -151,4 +233,8 @@ Item {
dockModel.updateModel() dockModel.updateModel()
} }
} }
onGroupByAppChanged: {
dockModel.updateModel()
}
} }

View File

@@ -15,11 +15,13 @@ PanelWindow {
property var anchorItem: null property var anchorItem: null
property real dockVisibleHeight: 40 property real dockVisibleHeight: 40
property int margin: 10 property int margin: 10
property bool hidePin: false
function showForButton(button, data, dockHeight) { function showForButton(button, data, dockHeight, hidePinOption) {
anchorItem = button anchorItem = button
appData = data appData = data
dockVisibleHeight = dockHeight || 40 dockVisibleHeight = dockHeight || 40
hidePin = hidePinOption || false
const dockWindow = button.Window.window const dockWindow = button.Window.window
if (dockWindow) { if (dockWindow) {
@@ -144,7 +146,102 @@ PanelWindow {
anchors.topMargin: Theme.spacingS anchors.topMargin: Theme.spacingS
spacing: 1 spacing: 1
// Window list for grouped apps
Repeater {
model: {
if (!root.appData || root.appData.type !== "grouped") return []
const toplevels = []
const allToplevels = ToplevelManager.toplevels.values
for (let i = 0; i < allToplevels.length; i++) {
const toplevel = allToplevels[i]
if (toplevel.appId === root.appData.appId) {
toplevels.push(toplevel)
}
}
return toplevels
}
Rectangle {
width: parent.width
height: 28
radius: Theme.cornerRadius
color: windowArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
StyledText {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingS
anchors.right: closeButton.left
anchors.rightMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
text: (modelData && modelData.title) ? modelData.title : "(Unnamed)"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
font.weight: Font.Normal
elide: Text.ElideRight
wrapMode: Text.NoWrap
}
Rectangle {
id: closeButton
anchors.right: parent.right
anchors.rightMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
width: 20
height: 20
radius: 10
color: closeMouseArea.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.2) : "transparent"
DankIcon {
anchors.centerIn: parent
name: "close"
size: 12
color: closeMouseArea.containsMouse ? Theme.error : Theme.surfaceText
}
MouseArea {
id: closeMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData && modelData.close) {
modelData.close()
}
root.close()
}
}
}
MouseArea {
id: windowArea
anchors.fill: parent
anchors.rightMargin: 24
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
if (modelData && modelData.activate) {
modelData.activate()
}
root.close()
}
}
}
}
Rectangle { Rectangle {
visible: {
if (!root.appData) return false
if (root.appData.type !== "grouped") return false
return root.appData.windowCount > 0
}
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
}
Rectangle {
visible: !root.hidePin
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadius radius: Theme.cornerRadius
@@ -198,7 +295,7 @@ PanelWindow {
} }
Rectangle { Rectangle {
visible: root.appData && root.appData.type === "window" visible: root.appData && (root.appData.type === "window" || (root.appData.type === "grouped" && root.appData.windowCount > 0))
width: parent.width width: parent.width
height: 28 height: 28
radius: Theme.cornerRadius radius: Theme.cornerRadius
@@ -210,7 +307,12 @@ PanelWindow {
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Theme.spacingS anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: "Close Window" text: {
if (root.appData && root.appData.type === "grouped") {
return "Close All Windows"
}
return "Close Window"
}
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
font.weight: Font.Normal font.weight: Font.Normal
@@ -224,8 +326,26 @@ PanelWindow {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (root.appData && root.appData.toplevelObject) { const sortedToplevels = CompositorService.sortedToplevels
root.appData.toplevelObject.close() if (root.appData && root.appData.type === "window") {
// Find and close the specific window
for (var i = 0; i < sortedToplevels.length; i++) {
const toplevel = sortedToplevels[i]
const checkId = toplevel.title + "|" + (toplevel.appId || "") + "|" + i
if (checkId === root.appData.uniqueId) {
toplevel.close()
break
}
}
} else if (root.appData && root.appData.type === "grouped") {
// Close all windows for this app
const allToplevels = ToplevelManager.toplevels.values
for (let i = 0; i < allToplevels.length; i++) {
const toplevel = allToplevels[i]
if (toplevel.appId === root.appData.appId) {
toplevel.close()
}
}
} }
root.close() root.close()
} }

View File

@@ -34,12 +34,6 @@ Rectangle {
} }
radius: Theme.cornerRadius radius: Theme.cornerRadius
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color { Behavior on border.color {
ColorAnimation { ColorAnimation {
@@ -50,12 +44,12 @@ Rectangle {
color: { color: {
if (isGroupSelected && keyboardNavigationActive) { if (isGroupSelected && keyboardNavigationActive) {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) return Theme.primaryPressed
} }
if (keyboardNavigationActive && expanded && selectedNotificationIndex >= 0) { if (keyboardNavigationActive && expanded && selectedNotificationIndex >= 0) {
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) return Theme.primaryHoverLight
} }
return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) return Theme.surfaceContainerHigh
} }
border.color: { border.color: {
if (isGroupSelected && keyboardNavigationActive) { if (isGroupSelected && keyboardNavigationActive) {
@@ -350,16 +344,10 @@ Rectangle {
return baseHeight return baseHeight
} }
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: isSelected ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.25) : "transparent" color: isSelected ? Theme.primaryPressed : Theme.surfaceContainerHigh
border.color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) border.color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: isSelected ? 1 : 1 border.width: isSelected ? 1 : 1
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color { Behavior on border.color {
ColorAnimation { ColorAnimation {

View File

@@ -36,7 +36,7 @@ DankPopout {
popupWidth: 400 popupWidth: 400
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 400 popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 400
triggerX: Screen.width - 400 - Theme.spacingL triggerX: Screen.width - 400 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.popupDistance
triggerWidth: 40 triggerWidth: 40
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -117,7 +117,7 @@ DankPopout {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
focus: true focus: true
Component.onCompleted: { Component.onCompleted: {

View File

@@ -106,9 +106,7 @@ Item {
height: 28 height: 28
radius: Theme.cornerRadius radius: Theme.cornerRadius
visible: NotificationService.notifications.length > 0 visible: NotificationService.notifications.length > 0
color: clearArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: clearArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceContainerHigh
border.color: clearArea.containsMouse ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -139,19 +137,6 @@ Item {
onClicked: NotificationService.clearAllNotifications() onClicked: NotificationService.clearAllNotifications()
} }
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
} }
} }
} }

View File

@@ -134,7 +134,7 @@ PanelWindow {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.popupBackground() color: Theme.popupBackground()
border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 1 border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
clip: true clip: true
Rectangle { Rectangle {

View File

@@ -40,7 +40,7 @@ Column {
width: parent.width width: parent.width
height: 200 height: 200
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1 border.width: 1
@@ -180,7 +180,7 @@ Column {
width: parent.width width: parent.width
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1 border.width: 1
@@ -350,7 +350,7 @@ Column {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1 border.width: 1
@@ -416,7 +416,7 @@ Column {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 80 height: 80
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
border.width: 1 border.width: 1

View File

@@ -40,7 +40,7 @@ DankPopout {
popupWidth: 600 popupWidth: 600
popupHeight: 600 popupHeight: 600
triggerX: Screen.width - 600 - Theme.spacingL triggerX: Screen.width - 600 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS triggerY: Math.max(26 + SettingsData.topBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.topBarInnerPadding)) + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance
triggerWidth: 55 triggerWidth: 55
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -62,7 +62,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.popupBackground() color: Theme.popupBackground()
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
clip: true clip: true
antialiasing: true antialiasing: true
smooth: true smooth: true
@@ -100,9 +100,9 @@ DankPopout {
Layout.fillWidth: true Layout.fillWidth: true
height: systemOverview.height + Theme.spacingM * 2 height: systemOverview.height + Theme.spacingM * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
SystemOverview { SystemOverview {
id: systemOverview id: systemOverview
@@ -117,9 +117,9 @@ DankPopout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: 1 border.width: 0
ProcessListView { ProcessListView {
anchors.fill: parent anchors.fill: parent

View File

@@ -24,7 +24,7 @@ DankFlickable {
width: parent.width width: parent.width
height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL height: systemInfoColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6) color: Theme.surfaceContainerHigh
border.width: 0 border.width: 0
Column { Column {
@@ -386,7 +386,7 @@ DankFlickable {
width: parent.width width: parent.width
height: storageColumn.implicitHeight + 2 * Theme.spacingL height: storageColumn.implicitHeight + 2 * Theme.spacingL
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.6) color: Theme.surfaceContainerHigh
border.width: 0 border.width: 0
Column { Column {

View File

@@ -28,11 +28,10 @@ Item {
width: parent.width width: parent.width
height: asciiSection.implicitHeight + Theme.spacingL * 2 height: asciiSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: asciiSection id: asciiSection
@@ -225,11 +224,10 @@ Item {
width: parent.width width: parent.width
height: projectSection.implicitHeight + Theme.spacingL * 2 height: projectSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: projectSection id: projectSection
@@ -285,11 +283,10 @@ Item {
width: parent.width width: parent.width
height: techSection.implicitHeight + Theme.spacingL * 2 height: techSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: techSection id: techSection
@@ -510,7 +507,7 @@ Item {
color: Theme.surfaceContainer color: Theme.surfaceContainer
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.width: 1 border.width: 0
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
x: hoveredButton ? hoveredButton.mapToItem(aboutTab, hoveredButton.width / 2, 0).x - width / 2 : 0 x: hoveredButton ? hoveredButton.mapToItem(aboutTab, hoveredButton.width / 2, 0).x - width / 2 : 0

View File

@@ -80,9 +80,9 @@ Item {
width: parent.width width: parent.width
height: screensInfoSection.implicitHeight + Theme.spacingL * 2 height: screensInfoSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: screensInfoSection id: screensInfoSection
@@ -146,7 +146,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.width: 1 border.width: 0
Row { Row {
id: screenRow id: screenRow
@@ -222,9 +222,9 @@ Item {
width: parent.width width: parent.width
height: componentSection.implicitHeight + Theme.spacingL * 2 height: componentSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: componentSection id: componentSection

View File

@@ -24,11 +24,10 @@ Item {
width: parent.width width: parent.width
height: enableDockSection.implicitHeight + Theme.spacingL * 2 height: enableDockSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: enableDockSection id: enableDockSection
@@ -88,11 +87,10 @@ Item {
width: parent.width width: parent.width
height: autoHideSection.implicitHeight + Theme.spacingL * 2 height: autoHideSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
visible: SettingsData.showDock visible: SettingsData.showDock
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
@@ -156,16 +154,87 @@ Item {
} }
} }
// Group by App
StyledRect {
width: parent.width
height: groupByAppSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2)
border.width: 0
visible: SettingsData.showDock
opacity: visible ? 1 : 0
Column {
id: groupByAppSection
anchors.fill: parent
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DankIcon {
name: "apps"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Column {
width: parent.width - Theme.iconSize - Theme.spacingM
- groupByAppToggle.width - Theme.spacingM
spacing: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: "Group by App"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Medium
color: Theme.surfaceText
}
StyledText {
text: "Group multiple windows of the same app together with a window count indicator"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
}
DankToggle {
id: groupByAppToggle
anchors.verticalCenter: parent.verticalCenter
checked: SettingsData.dockGroupByApp
onToggled: checked => {
SettingsData.setDockGroupByApp(checked)
}
}
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
// Dock Transparency Section // Dock Transparency Section
StyledRect { StyledRect {
width: parent.width width: parent.width
height: transparencySection.implicitHeight + Theme.spacingL * 2 height: transparencySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
visible: SettingsData.showDock visible: SettingsData.showDock
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
@@ -205,6 +274,7 @@ Item {
unit: "%" unit: "%"
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setDockTransparency( SettingsData.setDockTransparency(
newValue / 100) newValue / 100)

View File

@@ -23,11 +23,10 @@ Item {
width: parent.width width: parent.width
height: launchPrefixSection.implicitHeight + Theme.spacingL * 2 height: launchPrefixSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: launchPrefixSection id: launchPrefixSection
@@ -79,11 +78,10 @@ Item {
width: parent.width width: parent.width
height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2 height: recentlyUsedSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: recentlyUsedSection id: recentlyUsedSection
@@ -184,7 +182,7 @@ Item {
border.color: Qt.rgba(Theme.outline.r, border.color: Qt.rgba(Theme.outline.r,
Theme.outline.g, Theme.outline.g,
Theme.outline.b, 0.1) Theme.outline.b, 0.1)
border.width: 1 border.width: 0
Row { Row {
anchors.left: parent.left anchors.left: parent.left

View File

@@ -96,9 +96,9 @@ Item {
width: parent.width width: parent.width
height: wallpaperSection.implicitHeight + Theme.spacingL * 2 height: wallpaperSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: wallpaperSection id: wallpaperSection
@@ -137,7 +137,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceVariant color: Theme.surfaceVariant
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
CachingImage { CachingImage {
anchors.fill: parent anchors.fill: parent
@@ -377,7 +377,7 @@ Item {
var currentWallpaper = SessionData.perMonitorWallpaper ? SessionData.getMonitorWallpaper(selectedMonitorName) : SessionData.wallpaperPath var currentWallpaper = SessionData.perMonitorWallpaper ? SessionData.getMonitorWallpaper(selectedMonitorName) : SessionData.wallpaperPath
return (currentWallpaper && !currentWallpaper.startsWith("#") && !currentWallpaper.startsWith("we")) ? 1 : 0.5 return (currentWallpaper && !currentWallpaper.startsWith("#") && !currentWallpaper.startsWith("we")) ? 1 : 0.5
} }
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) backgroundColor: Theme.surfaceContainerHigh
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
onClicked: { onClicked: {
if (SessionData.perMonitorWallpaper) { if (SessionData.perMonitorWallpaper) {
@@ -400,7 +400,7 @@ Item {
var currentWallpaper = SessionData.perMonitorWallpaper ? SessionData.getMonitorWallpaper(selectedMonitorName) : SessionData.wallpaperPath var currentWallpaper = SessionData.perMonitorWallpaper ? SessionData.getMonitorWallpaper(selectedMonitorName) : SessionData.wallpaperPath
return (currentWallpaper && !currentWallpaper.startsWith("#") && !currentWallpaper.startsWith("we")) ? 1 : 0.5 return (currentWallpaper && !currentWallpaper.startsWith("#") && !currentWallpaper.startsWith("we")) ? 1 : 0.5
} }
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) backgroundColor: Theme.surfaceContainerHigh
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
onClicked: { onClicked: {
if (SessionData.perMonitorWallpaper) { if (SessionData.perMonitorWallpaper) {
@@ -805,24 +805,60 @@ Item {
text: "Transition Effect" text: "Transition Effect"
description: "Visual effect used when wallpaper changes" description: "Visual effect used when wallpaper changes"
currentValue: { currentValue: {
switch (SessionData.wallpaperTransition) { if (SessionData.wallpaperTransition === "random") return "Random"
case "none": return "None" return SessionData.wallpaperTransition.charAt(0).toUpperCase() + SessionData.wallpaperTransition.slice(1)
case "fade": return "Fade"
case "wipe": return "Wipe"
case "disc": return "Disc"
case "stripes": return "Stripes"
case "iris bloom": return "Iris Bloom"
case "pixelate": return "Pixelate"
case "portal": return "Portal"
default: return "Fade"
}
} }
options: ["None", "Fade", "Wipe", "Disc", "Stripes", "Iris Bloom", "Pixelate", "Portal"] options: ["Random"].concat(SessionData.availableWallpaperTransitions.map(t => t.charAt(0).toUpperCase() + t.slice(1)))
onValueChanged: value => { onValueChanged: value => {
var transition = value.toLowerCase() var transition = value.toLowerCase()
SessionData.setWallpaperTransition(transition) SessionData.setWallpaperTransition(transition)
} }
} }
Column {
width: parent.width
spacing: Theme.spacingS
visible: SessionData.wallpaperTransition === "random"
leftPadding: Theme.spacingM
rightPadding: Theme.spacingM
StyledText {
text: "Include Transitions"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
font.weight: Font.Medium
}
StyledText {
text: "Select which transitions to include in randomization"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width - parent.leftPadding - parent.rightPadding
}
DankButtonGroup {
id: transitionGroup
width: parent.width - parent.leftPadding - parent.rightPadding
selectionMode: "multi"
model: SessionData.availableWallpaperTransitions.filter(t => t !== "none")
initialSelection: SessionData.includedTransitions
currentSelection: SessionData.includedTransitions
onSelectionChanged: (index, selected) => {
const transition = model[index]
let newIncluded = [...SessionData.includedTransitions]
if (selected && !newIncluded.includes(transition)) {
newIncluded.push(transition)
} else if (!selected && newIncluded.includes(transition)) {
newIncluded = newIncluded.filter(t => t !== transition)
}
SessionData.includedTransitions = newIncluded
}
}
}
} }
} }
@@ -831,9 +867,9 @@ Item {
width: parent.width width: parent.width
height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2 height: dynamicThemeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: dynamicThemeSection id: dynamicThemeSection
@@ -889,6 +925,37 @@ Item {
} }
} }
DankDropdown {
id: personalizationMatugenPaletteDropdown
width: parent.width
text: "Matugen Palette"
description: "Select the palette algorithm used for wallpaper-based colors"
options: Theme.availableMatugenSchemes.map(function (option) { return option.label })
currentValue: Theme.getMatugenScheme(SettingsData.matugenScheme).label
enabled: Theme.matugenAvailable
opacity: enabled ? 1 : 0.4
onValueChanged: value => {
for (var i = 0; i < Theme.availableMatugenSchemes.length; i++) {
var option = Theme.availableMatugenSchemes[i]
if (option.label === value) {
SettingsData.setMatugenScheme(option.value)
break
}
}
}
}
StyledText {
text: {
var scheme = Theme.getMatugenScheme(SettingsData.matugenScheme)
return scheme.description + " (" + scheme.value + ")"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
StyledText { StyledText {
text: "matugen not detected - dynamic theming unavailable" text: "matugen not detected - dynamic theming unavailable"
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
@@ -905,9 +972,9 @@ Item {
width: parent.width width: parent.width
height: displaySection.implicitHeight + Theme.spacingL * 2 height: displaySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: displaySection id: displaySection
@@ -1292,9 +1359,9 @@ Item {
width: parent.width width: parent.width
height: lockScreenSection.implicitHeight + Theme.spacingL * 2 height: lockScreenSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: lockScreenSection id: lockScreenSection
@@ -1340,9 +1407,9 @@ Item {
width: parent.width width: parent.width
height: fontSection.implicitHeight + Theme.spacingL * 2 height: fontSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: fontSection id: fontSection
@@ -1526,7 +1593,7 @@ Item {
iconName: "remove" iconName: "remove"
iconSize: Theme.iconSizeSmall iconSize: Theme.iconSizeSmall
enabled: SettingsData.fontScale > 1.0 enabled: SettingsData.fontScale > 1.0
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) backgroundColor: Theme.surfaceContainerHigh
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
onClicked: { onClicked: {
var newScale = Math.max(1.0, SettingsData.fontScale - 0.05) var newScale = Math.max(1.0, SettingsData.fontScale - 0.05)
@@ -1538,9 +1605,9 @@ Item {
width: 60 width: 60
height: 32 height: 32
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 1 border.width: 0
StyledText { StyledText {
anchors.centerIn: parent anchors.centerIn: parent
@@ -1556,7 +1623,7 @@ Item {
iconName: "add" iconName: "add"
iconSize: Theme.iconSizeSmall iconSize: Theme.iconSizeSmall
enabled: SettingsData.fontScale < 2.0 enabled: SettingsData.fontScale < 2.0
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.5) backgroundColor: Theme.surfaceContainerHigh
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
onClicked: { onClicked: {
var newScale = Math.min(2.0, SettingsData.fontScale + 0.05) var newScale = Math.min(2.0, SettingsData.fontScale + 0.05)

View File

@@ -106,11 +106,10 @@ Item {
width: parent.width width: parent.width
height: themeSection.implicitHeight + Theme.spacingL * 2 height: themeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: themeSection id: themeSection
@@ -137,6 +136,40 @@ Item {
color: Theme.surfaceText color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
Item {
width: parent.width - parent.children[0].width - parent.children[1].width - surfaceBaseGroup.width - Theme.spacingM * 3
height: 1
}
DankButtonGroup {
id: surfaceBaseGroup
property int currentSurfaceIndex: {
switch (SettingsData.surfaceBase) {
case "sc": return 0
case "s": return 1
default: return 0
}
}
model: ["Container", "Surface"]
currentIndex: currentSurfaceIndex
selectionMode: "single"
anchors.verticalCenter: parent.verticalCenter
buttonHeight: 20
minButtonWidth: 48
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 2
spacing: 1
onSelectionChanged: (index, selected) => {
if (!selected) return
const surfaceOptions = ["sc", "s"]
SettingsData.setSurfaceBase(surfaceOptions[index])
}
}
} }
Column { Column {
@@ -181,6 +214,7 @@ Item {
} }
} }
Column { Column {
spacing: Theme.spacingM spacing: Theme.spacingM
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@@ -246,7 +280,7 @@ Item {
height: nameText.contentHeight + Theme.spacingXS * 2 height: nameText.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS anchors.bottomMargin: Theme.spacingXS
@@ -311,7 +345,7 @@ Item {
height: nameText2.contentHeight + Theme.spacingXS * 2 height: nameText2.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS anchors.bottomMargin: Theme.spacingXS
@@ -382,7 +416,7 @@ Item {
height: nameTextCat.contentHeight + Theme.spacingXS * 2 height: nameTextCat.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS anchors.bottomMargin: Theme.spacingXS
@@ -447,7 +481,7 @@ Item {
height: nameTextCat2.contentHeight + Theme.spacingXS * 2 height: nameTextCat2.contentHeight + Theme.spacingXS * 2
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
anchors.bottom: parent.top anchors.bottom: parent.top
anchors.bottomMargin: Theme.spacingXS anchors.bottomMargin: Theme.spacingXS
@@ -506,7 +540,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceVariant color: Theme.surfaceVariant
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
CachingImage { CachingImage {
anchors.fill: parent anchors.fill: parent
@@ -608,6 +642,37 @@ Item {
} }
} }
} }
DankDropdown {
id: matugenPaletteDropdown
width: parent.width
text: "Matugen Palette"
description: "Select the palette algorithm used for wallpaper-based colors"
options: Theme.availableMatugenSchemes.map(function (option) { return option.label })
currentValue: Theme.getMatugenScheme(SettingsData.matugenScheme).label
enabled: Theme.matugenAvailable
opacity: enabled ? 1 : 0.4
onValueChanged: value => {
for (var i = 0; i < Theme.availableMatugenSchemes.length; i++) {
var option = Theme.availableMatugenSchemes[i]
if (option.label === value) {
SettingsData.setMatugenScheme(option.value)
break
}
}
}
}
StyledText {
text: {
var scheme = Theme.getMatugenScheme(SettingsData.matugenScheme)
return scheme.description + " (" + scheme.value + ")"
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
}
} }
Column { Column {
@@ -662,11 +727,10 @@ Item {
width: parent.width width: parent.width
height: transparencySection.implicitHeight + Theme.spacingL * 2 height: transparencySection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: transparencySection id: transparencySection
@@ -716,6 +780,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setTopBarTransparency( SettingsData.setTopBarTransparency(
newValue / 100) newValue / 100)
@@ -784,6 +849,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setTopBarWidgetTransparency( SettingsData.setTopBarWidgetTransparency(
newValue / 100) newValue / 100)
@@ -812,6 +878,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setPopupTransparency( SettingsData.setPopupTransparency(
newValue / 100) newValue / 100)
@@ -819,6 +886,7 @@ Item {
} }
} }
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 1 height: 1
@@ -846,6 +914,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setCornerRadius( SettingsData.setCornerRadius(
newValue) newValue)
@@ -864,7 +933,7 @@ Item {
Theme.warning.b, 0.12) Theme.warning.b, 0.12)
border.color: Qt.rgba(Theme.warning.r, Theme.warning.g, border.color: Qt.rgba(Theme.warning.r, Theme.warning.g,
Theme.warning.b, 0.3) Theme.warning.b, 0.3)
border.width: 1 border.width: 0
Row { Row {
anchors.fill: parent anchors.fill: parent
@@ -894,11 +963,10 @@ Item {
width: parent.width width: parent.width
height: iconThemeSection.implicitHeight + Theme.spacingL * 2 height: iconThemeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: iconThemeSection id: iconThemeSection
@@ -949,11 +1017,10 @@ Item {
width: parent.width width: parent.width
height: systemThemingSection.implicitHeight + Theme.spacingL * 2 height: systemThemingSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
visible: Theme.matugenAvailable visible: Theme.matugenAvailable
Column { Column {
@@ -993,7 +1060,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Theme.primary border.color: Theme.primary
border.width: 1 border.width: 0
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
@@ -1029,7 +1096,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
border.color: Theme.primary border.color: Theme.primary
border.width: 1 border.width: 0
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent

View File

@@ -24,11 +24,10 @@ Item {
width: parent.width width: parent.width
height: timeSection.implicitHeight + Theme.spacingL * 2 height: timeSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: timeSection id: timeSection
@@ -89,11 +88,10 @@ Item {
width: parent.width width: parent.width
height: dateSection.implicitHeight + Theme.spacingL * 2 height: dateSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: dateSection id: dateSection
@@ -280,12 +278,10 @@ Item {
width: parent.width width: parent.width
height: formatHelp.implicitHeight + Theme.spacingM * 2 height: formatHelp.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.2)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.1) Theme.outline.b, 0.1)
border.width: 1 border.width: 0
Column { Column {
id: formatHelp id: formatHelp

View File

@@ -67,6 +67,13 @@ Item {
"id": "memUsage", "id": "memUsage",
"text": "Memory Usage", "text": "Memory Usage",
"description": "Memory usage indicator", "description": "Memory usage indicator",
"icon": "developer_board",
"enabled": DgopService.dgopAvailable,
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined
}, {
"id": "diskUsage",
"text": "Disk Usage",
"description": "Percentage",
"icon": "storage", "icon": "storage",
"enabled": DgopService.dgopAvailable, "enabled": DgopService.dgopAvailable,
"warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined "warning": !DgopService.dgopAvailable ? "Requires 'dgop' tool" : undefined
@@ -223,6 +230,9 @@ Item {
widgetObj.showBluetoothIcon = true widgetObj.showBluetoothIcon = true
widgetObj.showAudioIcon = true widgetObj.showAudioIcon = true
} }
if (widgetId === "diskUsage") {
widgetObj.mountPath = "/"
}
var widgets = [] var widgets = []
if (targetSection === "left") { if (targetSection === "left") {
@@ -412,6 +422,52 @@ Item {
SettingsData.setTopBarRightWidgets(widgets) SettingsData.setTopBarRightWidgets(widgets)
} }
function handleDiskMountSelectionChanged(sectionId, widgetIndex, mountPath) {
var widgets = []
if (sectionId === "left")
widgets = SettingsData.topBarLeftWidgets.slice()
else if (sectionId === "center")
widgets = SettingsData.topBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.topBarRightWidgets.slice()
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
var widget = widgets[widgetIndex]
if (typeof widget === "string") {
widgets[widgetIndex] = {
"id": widget,
"enabled": true,
"mountPath": mountPath
}
} else {
var newWidget = {
"id": widget.id,
"enabled": widget.enabled,
"mountPath": mountPath
}
if (widget.size !== undefined)
newWidget.size = widget.size
if (widget.selectedGpuIndex !== undefined)
newWidget.selectedGpuIndex = widget.selectedGpuIndex
if (widget.pciId !== undefined)
newWidget.pciId = widget.pciId
if (widget.id === "controlCenterButton") {
newWidget.showNetworkIcon = widget.showNetworkIcon !== undefined ? widget.showNetworkIcon : true
newWidget.showBluetoothIcon = widget.showBluetoothIcon !== undefined ? widget.showBluetoothIcon : true
newWidget.showAudioIcon = widget.showAudioIcon !== undefined ? widget.showAudioIcon : true
}
widgets[widgetIndex] = newWidget
}
}
if (sectionId === "left")
SettingsData.setTopBarLeftWidgets(widgets)
else if (sectionId === "center")
SettingsData.setTopBarCenterWidgets(widgets)
else if (sectionId === "right")
SettingsData.setTopBarRightWidgets(widgets)
}
function handleControlCenterSettingChanged(sectionId, widgetIndex, settingName, value) { function handleControlCenterSettingChanged(sectionId, widgetIndex, settingName, value) {
// Control Center settings are global, not per-widget instance // Control Center settings are global, not per-widget instance
if (settingName === "showNetworkIcon") { if (settingName === "showNetworkIcon") {
@@ -441,6 +497,8 @@ Item {
=== "string" ? undefined : widget.selectedGpuIndex === "string" ? undefined : widget.selectedGpuIndex
var widgetPciId = typeof widget var widgetPciId = typeof widget
=== "string" ? undefined : widget.pciId === "string" ? undefined : widget.pciId
var widgetMountPath = typeof widget
=== "string" ? undefined : widget.mountPath
var widgetShowNetworkIcon = typeof widget === "string" ? undefined : widget.showNetworkIcon var widgetShowNetworkIcon = typeof widget === "string" ? undefined : widget.showNetworkIcon
var widgetShowBluetoothIcon = typeof widget === "string" ? undefined : widget.showBluetoothIcon var widgetShowBluetoothIcon = typeof widget === "string" ? undefined : widget.showBluetoothIcon
var widgetShowAudioIcon = typeof widget === "string" ? undefined : widget.showAudioIcon var widgetShowAudioIcon = typeof widget === "string" ? undefined : widget.showAudioIcon
@@ -456,6 +514,8 @@ Item {
item.selectedGpuIndex = widgetSelectedGpuIndex item.selectedGpuIndex = widgetSelectedGpuIndex
if (widgetPciId !== undefined) if (widgetPciId !== undefined)
item.pciId = widgetPciId item.pciId = widgetPciId
if (widgetMountPath !== undefined)
item.mountPath = widgetMountPath
if (widgetShowNetworkIcon !== undefined) if (widgetShowNetworkIcon !== undefined)
item.showNetworkIcon = widgetShowNetworkIcon item.showNetworkIcon = widgetShowNetworkIcon
if (widgetShowBluetoothIcon !== undefined) if (widgetShowBluetoothIcon !== undefined)
@@ -529,11 +589,10 @@ Item {
width: parent.width width: parent.width
height: topBarAutoHideSection.implicitHeight + Theme.spacingL * 2 height: topBarAutoHideSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: topBarAutoHideSection id: topBarAutoHideSection
@@ -701,11 +760,10 @@ Item {
width: parent.width width: parent.width
height: topBarSpacingSection.implicitHeight + Theme.spacingL * 2 height: topBarSpacingSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: topBarSpacingSection id: topBarSpacingSection
@@ -754,7 +812,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setTopBarSpacing( SettingsData.setTopBarSpacing(
newValue) newValue)
@@ -782,7 +840,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setTopBarBottomGap( SettingsData.setTopBarBottomGap(
newValue) newValue)
@@ -810,7 +868,7 @@ Item {
unit: "" unit: ""
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainer thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setTopBarInnerPadding( SettingsData.setTopBarInnerPadding(
newValue) newValue)
@@ -859,11 +917,10 @@ Item {
width: parent.width width: parent.width
height: widgetManagementSection.implicitHeight + Theme.spacingL * 2 height: widgetManagementSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: widgetManagementSection id: widgetManagementSection
@@ -905,7 +962,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: resetArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariant color: resetArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariant
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
border.width: 1 border.width: 0
border.color: resetArea.containsMouse ? Theme.outline : Qt.rgba( border.color: resetArea.containsMouse ? Theme.outline : Qt.rgba(
Theme.outline.r, Theme.outline.r,
Theme.outline.g, Theme.outline.g,
@@ -983,12 +1040,10 @@ Item {
width: parent.width width: parent.width
height: leftSection.implicitHeight + Theme.spacingL * 2 height: leftSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
WidgetsTabSection { WidgetsTabSection {
id: leftSection id: leftSection
@@ -1045,6 +1100,10 @@ Item {
sectionId, widgetIndex, sectionId, widgetIndex,
selectedIndex) selectedIndex)
} }
onDiskMountSelectionChanged: (sectionId, widgetIndex, mountPath) => {
topBarTab.handleDiskMountSelectionChanged(
sectionId, widgetIndex, mountPath)
}
} }
} }
@@ -1053,12 +1112,10 @@ Item {
width: parent.width width: parent.width
height: centerSection.implicitHeight + Theme.spacingL * 2 height: centerSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
WidgetsTabSection { WidgetsTabSection {
id: centerSection id: centerSection
@@ -1115,6 +1172,10 @@ Item {
sectionId, widgetIndex, sectionId, widgetIndex,
selectedIndex) selectedIndex)
} }
onDiskMountSelectionChanged: (sectionId, widgetIndex, mountPath) => {
topBarTab.handleDiskMountSelectionChanged(
sectionId, widgetIndex, mountPath)
}
} }
} }
@@ -1123,12 +1184,10 @@ Item {
width: parent.width width: parent.width
height: rightSection.implicitHeight + Theme.spacingL * 2 height: rightSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.g,
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
WidgetsTabSection { WidgetsTabSection {
id: rightSection id: rightSection
@@ -1185,6 +1244,10 @@ Item {
sectionId, widgetIndex, sectionId, widgetIndex,
selectedIndex) selectedIndex)
} }
onDiskMountSelectionChanged: (sectionId, widgetIndex, mountPath) => {
topBarTab.handleDiskMountSelectionChanged(
sectionId, widgetIndex, mountPath)
}
} }
} }
} }

View File

@@ -24,11 +24,10 @@ Item {
width: parent.width width: parent.width
height: enableWeatherSection.implicitHeight + Theme.spacingL * 2 height: enableWeatherSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: enableWeatherSection id: enableWeatherSection
@@ -89,11 +88,10 @@ Item {
width: parent.width width: parent.width
height: temperatureSection.implicitHeight + Theme.spacingL * 2 height: temperatureSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
visible: SettingsData.weatherEnabled visible: SettingsData.weatherEnabled
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
@@ -163,11 +161,10 @@ Item {
width: parent.width width: parent.width
height: locationSection.implicitHeight + Theme.spacingL * 2 height: locationSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
visible: SettingsData.weatherEnabled visible: SettingsData.weatherEnabled
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0

View File

@@ -103,7 +103,7 @@ Popup {
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 1) Theme.surfaceContainer.b, 1)
border.color: Theme.primarySelected border.color: Theme.primarySelected
border.width: 1 border.width: 0
radius: Theme.cornerRadius radius: Theme.cornerRadius
} }
@@ -192,7 +192,7 @@ Popup {
width: parent.width width: parent.width
height: 48 height: 48
cornerRadius: Theme.cornerRadius cornerRadius: Theme.cornerRadius
backgroundColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3) backgroundColor: Theme.surfaceContainerHigh
normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2) normalBorderColor: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
focusedBorderColor: Theme.primary focusedBorderColor: Theme.primary
leftIconName: "search" leftIconName: "search"

View File

@@ -24,11 +24,10 @@ Item {
width: parent.width width: parent.width
height: launcherButtonSection.implicitHeight + Theme.spacingL * 2 height: launcherButtonSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: launcherButtonSection id: launcherButtonSection
@@ -128,6 +127,7 @@ Item {
unit: "%" unit: "%"
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setOSLogoBrightness( SettingsData.setOSLogoBrightness(
newValue / 100) newValue / 100)
@@ -156,6 +156,7 @@ Item {
unit: "%" unit: "%"
showValue: true showValue: true
wheelEnabled: false wheelEnabled: false
thumbOutlineColor: Theme.surfaceContainerHigh
onSliderValueChanged: newValue => { onSliderValueChanged: newValue => {
SettingsData.setOSLogoContrast( SettingsData.setOSLogoContrast(
newValue / 100) newValue / 100)
@@ -177,11 +178,10 @@ Item {
width: parent.width width: parent.width
height: workspaceSection.implicitHeight + Theme.spacingL * 2 height: workspaceSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: workspaceSection id: workspaceSection
@@ -301,11 +301,10 @@ Item {
width: parent.width width: parent.width
height: mediaSection.implicitHeight + Theme.spacingL * 2 height: mediaSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: mediaSection id: mediaSection
@@ -350,11 +349,10 @@ Item {
width: parent.width width: parent.width
height: runningAppsSection.implicitHeight + Theme.spacingL * 2 height: runningAppsSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
Column { Column {
id: runningAppsSection id: runningAppsSection
@@ -400,11 +398,10 @@ Item {
width: parent.width width: parent.width
height: workspaceIconsSection.implicitHeight + Theme.spacingL * 2 height: workspaceIconsSection.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, color: Theme.surfaceContainerHigh
Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
visible: SettingsData.hasNamedWorkspaces() visible: SettingsData.hasNamedWorkspaces()
Column { Column {
@@ -455,7 +452,7 @@ Item {
border.color: Qt.rgba(Theme.outline.r, border.color: Qt.rgba(Theme.outline.r,
Theme.outline.g, Theme.outline.g,
Theme.outline.b, 0.3) Theme.outline.b, 0.3)
border.width: 1 border.width: 0
Row { Row {
id: workspaceIconRow id: workspaceIconRow
@@ -522,7 +519,7 @@ Item {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: clearMouseArea.containsMouse ? Theme.errorHover : Theme.surfaceContainer color: clearMouseArea.containsMouse ? Theme.errorHover : Theme.surfaceContainer
border.color: clearMouseArea.containsMouse ? Theme.error : Theme.outline border.color: clearMouseArea.containsMouse ? Theme.error : Theme.outline
border.width: 1 border.width: 0
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
DankIcon { DankIcon {

View File

@@ -20,6 +20,7 @@ Column {
signal spacerSizeChanged(string sectionId, int widgetIndex, int newSize) signal spacerSizeChanged(string sectionId, int widgetIndex, int newSize)
signal compactModeChanged(string widgetId, var value) signal compactModeChanged(string widgetId, var value)
signal gpuSelectionChanged(string sectionId, int widgetIndex, int selectedIndex) signal gpuSelectionChanged(string sectionId, int widgetIndex, int selectedIndex)
signal diskMountSelectionChanged(string sectionId, int widgetIndex, string mountPath)
signal controlCenterSettingChanged(string sectionId, int widgetIndex, string settingName, bool value) signal controlCenterSettingChanged(string sectionId, int widgetIndex, string settingName, bool value)
width: parent.width width: parent.width
@@ -81,7 +82,7 @@ Column {
Theme.surfaceContainer.b, 0.8) Theme.surfaceContainer.b, 0.8)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
DankIcon { DankIcon {
name: "drag_indicator" name: "drag_indicator"
@@ -187,6 +188,38 @@ Column {
} }
} }
Item {
width: 120
height: 32
visible: modelData.id === "diskUsage"
DankDropdown {
id: diskMountDropdown
anchors.fill: parent
currentValue: {
const mountPath = modelData.mountPath || "/"
if (mountPath === "/") {
return "root (/)"
}
return mountPath
}
options: {
if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) {
return ["root (/)"]
}
return DgopService.diskMounts.map(mount => {
if (mount.mount === "/") {
return "root (/)"
}
return mount.mount
})
}
onValueChanged: value => {
const newPath = value === "root (/)" ? "/" : value
root.diskMountSelectionChanged(root.sectionId, index, newPath)
}
}
}
Item { Item {
width: 32 width: 32
height: 32 height: 32
@@ -226,7 +259,7 @@ Column {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
visible: warningArea.containsMouse visible: warningArea.containsMouse
&& warningText !== "" && warningText !== ""
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
@@ -349,7 +382,7 @@ Column {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.surfaceContainer color: Theme.surfaceContainer
border.color: Theme.outline border.color: Theme.outline
border.width: 1 border.width: 0
visible: false visible: false
opacity: visible ? 1 : 0 opacity: visible ? 1 : 0
x: -width - Theme.spacingS x: -width - Theme.spacingS
@@ -527,7 +560,7 @@ Column {
Theme.surfaceVariant.b, 0.3) Theme.surfaceVariant.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.2) Theme.outline.b, 0.2)
border.width: 1 border.width: 0
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
StyledText { StyledText {
@@ -585,7 +618,7 @@ Column {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1 border.width: 0
} }
contentItem: Item { contentItem: Item {

View File

@@ -26,7 +26,7 @@ DankPopout {
popupWidth: 400 popupWidth: 400
popupHeight: 500 popupHeight: 500
triggerX: Screen.width - 600 - Theme.spacingL triggerX: Screen.width - 600 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingXS triggerY: Math.max(26 + SettingsData.topBarInnerPadding + 4, Theme.barHeight - 4 - (8 - SettingsData.topBarInnerPadding)) + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance
triggerWidth: 55 triggerWidth: 55
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -70,7 +70,7 @@ DankPopout {
color: "transparent" color: "transparent"
radius: parent.radius + Math.abs(modelData.margin) radius: parent.radius + Math.abs(modelData.margin)
border.color: modelData.color border.color: modelData.color
border.width: 1 border.width: 0
z: modelData.z z: modelData.z
} }
} }
@@ -157,7 +157,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.1)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
border.width: 1 border.width: 0
Column { Column {
anchors.fill: parent anchors.fill: parent
@@ -208,7 +208,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: packageMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent" color: packageMouseArea.containsMouse ? Theme.primaryHoverLight : "transparent"
border.color: Theme.outlineLight border.color: Theme.outlineLight
border.width: 1 border.width: 0
Row { Row {
anchors.fill: parent anchors.fill: parent

View File

@@ -80,7 +80,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
toggleBatteryPopup(); toggleBatteryPopup();
} }

View File

@@ -45,7 +45,7 @@ DankPopout {
popupWidth: 400 popupWidth: 400
popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 400 popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 400
triggerX: Screen.width - 380 - Theme.spacingL triggerX: Screen.width - 380 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.popupDistance
triggerWidth: 70 triggerWidth: 70
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -60,7 +60,7 @@ DankPopout {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
border.width: 1 border.width: 0
antialiasing: true antialiasing: true
smooth: true smooth: true
focus: true focus: true
@@ -96,7 +96,7 @@ DankPopout {
color: "transparent" color: "transparent"
radius: parent.radius + 3 radius: parent.radius + 3
border.color: Qt.rgba(0, 0, 0, 0.05) border.color: Qt.rgba(0, 0, 0, 0.05)
border.width: 1 border.width: 0
z: -3 z: -3
} }
@@ -106,7 +106,7 @@ DankPopout {
color: "transparent" color: "transparent"
radius: parent.radius + 2 radius: parent.radius + 2
border.color: Theme.shadowMedium border.color: Theme.shadowMedium
border.width: 1 border.width: 0
z: -2 z: -2
} }
@@ -114,7 +114,7 @@ DankPopout {
anchors.fill: parent anchors.fill: parent
color: "transparent" color: "transparent"
border.color: Theme.outlineStrong border.color: Theme.outlineStrong
border.width: 1 border.width: 0
radius: parent.radius radius: parent.radius
z: -1 z: -1
} }
@@ -304,9 +304,8 @@ DankPopout {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 64 height: 64
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) border.width: 0
border.width: 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -340,9 +339,8 @@ DankPopout {
width: (parent.width - Theme.spacingM) / 2 width: (parent.width - Theme.spacingM) / 2
height: 64 height: 64
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) border.width: 0
border.width: 1
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -390,7 +388,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12) color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.12)
border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3) border.color: Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3)
border.width: 1 border.width: 0
visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None visible: (typeof PowerProfiles !== "undefined") && PowerProfiles.degradationReason !== PerformanceDegradationReason.None
Column { Column {

View File

@@ -84,7 +84,7 @@ Rectangle {
const currentScreen = parentScreen || Screen const currentScreen = parentScreen || Screen
const screenX = currentScreen.x || 0 const screenX = currentScreen.x || 0
const relativeX = globalPos.x - screenX const relativeX = globalPos.x - screenX
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen) popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen)
} }
root.clockClicked() root.clockClicked()
} }

View File

@@ -160,7 +160,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
root.clicked(); root.clicked();
} }

View File

@@ -47,7 +47,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
DgopService.setSortBy("cpu"); DgopService.setSortBy("cpu");
if (root.toggleProcessList) { if (root.toggleProcessList) {

View File

@@ -47,7 +47,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
DgopService.setSortBy("cpu"); DgopService.setSortBy("cpu");
if (root.toggleProcessList) { if (root.toggleProcessList) {

View File

@@ -0,0 +1,171 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Services
import qs.Widgets
Rectangle {
id: root
property var widgetData: null
property real widgetHeight: 30
property string mountPath: (widgetData && widgetData.mountPath !== undefined) ? widgetData.mountPath : "/"
readonly property real horizontalPadding: SettingsData.topBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetHeight / 30))
property var selectedMount: {
if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) {
return null
}
// Force re-evaluation when mountPath changes
const currentMountPath = root.mountPath || "/"
// First try to find exact match
for (let i = 0; i < DgopService.diskMounts.length; i++) {
if (DgopService.diskMounts[i].mount === currentMountPath) {
return DgopService.diskMounts[i]
}
}
// Fallback to root
for (let i = 0; i < DgopService.diskMounts.length; i++) {
if (DgopService.diskMounts[i].mount === "/") {
return DgopService.diskMounts[i]
}
}
// Last resort - first mount
return DgopService.diskMounts[0] || null
}
property real diskUsagePercent: {
if (!selectedMount || !selectedMount.percent) {
return 0
}
const percentStr = selectedMount.percent.replace("%", "")
return parseFloat(percentStr) || 0
}
width: diskContent.implicitWidth + horizontalPadding * 2
height: widgetHeight
radius: SettingsData.topBarNoBackground ? 0 : Theme.cornerRadius
color: {
if (SettingsData.topBarNoBackground) {
return "transparent"
}
const baseColor = Theme.widgetBaseBackgroundColor
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
}
Component.onCompleted: {
DgopService.addRef(["diskmounts"])
}
Component.onDestruction: {
DgopService.removeRef(["diskmounts"])
}
Connections {
function onWidgetDataChanged() {
// Force property re-evaluation by triggering change detection
root.mountPath = Qt.binding(() => {
return (root.widgetData && root.widgetData.mountPath !== undefined) ? root.widgetData.mountPath : "/"
})
root.selectedMount = Qt.binding(() => {
if (!DgopService.diskMounts || DgopService.diskMounts.length === 0) {
return null
}
const currentMountPath = root.mountPath || "/"
// First try to find exact match
for (let i = 0; i < DgopService.diskMounts.length; i++) {
if (DgopService.diskMounts[i].mount === currentMountPath) {
return DgopService.diskMounts[i]
}
}
// Fallback to root
for (let i = 0; i < DgopService.diskMounts.length; i++) {
if (DgopService.diskMounts[i].mount === "/") {
return DgopService.diskMounts[i]
}
}
// Last resort - first mount
return DgopService.diskMounts[0] || null
})
}
target: SettingsData
}
Row {
id: diskContent
anchors.centerIn: parent
spacing: 3
DankIcon {
name: "storage"
size: Theme.iconSize - 8
color: {
if (root.diskUsagePercent > 90) {
return Theme.tempDanger
}
if (root.diskUsagePercent > 75) {
return Theme.tempWarning
}
return Theme.surfaceText
}
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: {
if (!root.selectedMount) {
return "--"
}
return root.selectedMount.mount
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone
}
StyledText {
text: {
if (root.diskUsagePercent === undefined || root.diskUsagePercent === null || root.diskUsagePercent === 0) {
return "--%"
}
return root.diskUsagePercent.toFixed(0) + "%"
}
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideNone
StyledTextMetrics {
id: diskBaseline
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
text: "100%"
}
width: Math.max(diskBaseline.width, paintedWidth)
Behavior on width {
NumberAnimation {
duration: 120
easing.type: Easing.OutCubic
}
}
}
}
}

View File

@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Hyprland
import qs.Common import qs.Common
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
@@ -17,25 +18,40 @@ Rectangle {
readonly property int maxCompactWidth: 288 readonly property int maxCompactWidth: 288
readonly property Toplevel activeWindow: ToplevelManager.activeToplevel readonly property Toplevel activeWindow: ToplevelManager.activeToplevel
readonly property bool hasWindowsOnCurrentWorkspace: { readonly property bool hasWindowsOnCurrentWorkspace: {
if (!CompositorService.isNiri) { if (CompositorService.isNiri) {
return activeWindow && activeWindow.title let currentWorkspaceId = null
} for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
const ws = NiriService.allWorkspaces[i]
let currentWorkspaceId = null if (ws.is_focused) {
for (var i = 0; i < NiriService.allWorkspaces.length; i++) { currentWorkspaceId = ws.id
const ws = NiriService.allWorkspaces[i] break
if (ws.is_focused) { }
currentWorkspaceId = ws.id
break
} }
if (!currentWorkspaceId) {
return false
}
const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId)
return workspaceWindows.length > 0 && activeWindow && activeWindow.title
} }
if (!currentWorkspaceId) { if (CompositorService.isHyprland) {
return false if (!Hyprland.focusedWorkspace || !activeWindow || !activeWindow.title) {
return false
}
const hyprlandToplevels = Array.from(Hyprland.toplevels.values)
const activeHyprToplevel = hyprlandToplevels.find(t => t.wayland === activeWindow)
if (!activeHyprToplevel || !activeHyprToplevel.workspace) {
return false
}
return activeHyprToplevel.workspace.id === Hyprland.focusedWorkspace.id
} }
const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId) return activeWindow && activeWindow.title
return workspaceWindows.length > 0 && activeWindow && activeWindow.title
} }
width: !hasWindowsOnCurrentWorkspace ? 0 : (compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth)) width: !hasWindowsOnCurrentWorkspace ? 0 : (compactMode ? Math.min(baseWidth, maxCompactWidth) : Math.min(baseWidth, maxNormalWidth))

View File

@@ -121,7 +121,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
DgopService.setSortBy("cpu"); DgopService.setSortBy("cpu");
if (root.toggleProcessList) { if (root.toggleProcessList) {

View File

@@ -32,7 +32,7 @@ Item {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
root.clicked(); root.clicked();
} }

View File

@@ -212,7 +212,7 @@ Rectangle {
const currentScreen = root.parentScreen || Screen; const currentScreen = root.parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
root.popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, root.width, root.section, currentScreen); root.popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, root.width, root.section, currentScreen);
} }
root.clicked(); root.clicked();
} }

View File

@@ -61,7 +61,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
root.clicked(); root.clicked();
} }

View File

@@ -47,7 +47,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
DgopService.setSortBy("memory"); DgopService.setSortBy("memory");
if (root.toggleProcessList) { if (root.toggleProcessList) {

View File

@@ -95,7 +95,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
root.clicked(); root.clicked();
} }

View File

@@ -27,7 +27,6 @@ PanelWindow {
property real wingtipsRadius: Theme.cornerRadius property real wingtipsRadius: Theme.cornerRadius
readonly property real _wingR: Math.max(0, wingtipsRadius) readonly property real _wingR: Math.max(0, wingtipsRadius)
readonly property color _bgColor: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, topBarCore.backgroundTransparency) readonly property color _bgColor: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, topBarCore.backgroundTransparency)
readonly property color _tintColor: Qt.rgba(Theme.surfaceTint.r, Theme.surfaceTint.g, Theme.surfaceTint.b, 0.04 * topBarCore.backgroundTransparency)
signal colorPickerRequested() signal colorPickerRequested()
@@ -401,7 +400,7 @@ PanelWindow {
ctx.arcTo(0, 0, RT, 0, RT) ctx.arcTo(0, 0, RT, 0, RT)
ctx.closePath() ctx.closePath()
ctx.fillStyle = root._tintColor ctx.fillStyle = root._bgColor
ctx.fill() ctx.fill()
} }
} }
@@ -483,6 +482,7 @@ PanelWindow {
"clipboard": clipboardComponent, "clipboard": clipboardComponent,
"cpuUsage": cpuUsageComponent, "cpuUsage": cpuUsageComponent,
"memUsage": memUsageComponent, "memUsage": memUsageComponent,
"diskUsage": diskUsageComponent,
"cpuTemp": cpuTempComponent, "cpuTemp": cpuTempComponent,
"gpuTemp": gpuTempComponent, "gpuTemp": gpuTempComponent,
"notificationButton": notificationButtonComponent, "notificationButton": notificationButtonComponent,
@@ -1003,6 +1003,15 @@ PanelWindow {
} }
} }
Component {
id: diskUsageComponent
DiskUsage {
widgetHeight: root.widgetHeight
widgetData: parent.widgetData
}
}
Component { Component {
id: cpuTempComponent id: cpuTempComponent

View File

@@ -59,7 +59,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
root.toggleVpnPopup(); root.toggleVpnPopup();
} }

View File

@@ -27,7 +27,7 @@ DankPopout {
popupWidth: 360 popupWidth: 360
popupHeight: Math.min(Screen.height - 100, contentLoader.item ? contentLoader.item.implicitHeight : 260) popupHeight: Math.min(Screen.height - 100, contentLoader.item ? contentLoader.item.implicitHeight : 260)
triggerX: Screen.width - 380 - Theme.spacingL triggerX: Screen.width - 380 - Theme.spacingL
triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.spacingS triggerY: Theme.barHeight - 4 + SettingsData.topBarSpacing + Theme.popupDistance
triggerWidth: 70 triggerWidth: 70
positioning: "center" positioning: "center"
screen: triggerScreen screen: triggerScreen
@@ -42,7 +42,7 @@ DankPopout {
color: Theme.popupBackground() color: Theme.popupBackground()
radius: Theme.cornerRadius radius: Theme.cornerRadius
border.color: Theme.outlineMedium border.color: Theme.outlineMedium
border.width: 1 border.width: 0
antialiasing: true antialiasing: true
smooth: true smooth: true
focus: true focus: true
@@ -60,7 +60,7 @@ DankPopout {
color: "transparent" color: "transparent"
radius: parent.radius + 3 radius: parent.radius + 3
border.color: Qt.rgba(0, 0, 0, 0.05) border.color: Qt.rgba(0, 0, 0, 0.05)
border.width: 1 border.width: 0
z: -3 z: -3
} }
@@ -70,7 +70,7 @@ DankPopout {
color: "transparent" color: "transparent"
radius: parent.radius + 2 radius: parent.radius + 2
border.color: Theme.shadowMedium border.color: Theme.shadowMedium
border.width: 1 border.width: 0
z: -2 z: -2
} }
@@ -78,7 +78,7 @@ DankPopout {
anchors.fill: parent anchors.fill: parent
color: "transparent" color: "transparent"
border.color: Theme.outlineStrong border.color: Theme.outlineStrong
border.width: 1 border.width: 0
radius: parent.radius radius: parent.radius
z: -1 z: -1
} }
@@ -142,7 +142,7 @@ DankPopout {
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, Theme.getContentBackgroundAlpha() * 0.6) color: Qt.rgba(Theme.surfaceContainerHigh.r, Theme.surfaceContainerHigh.g, Theme.surfaceContainerHigh.b, Theme.getContentBackgroundAlpha() * 0.6)
border.color: Theme.outlineStrong border.color: Theme.outlineStrong
border.width: 1 border.width: 0
clip: true clip: true
Column { Column {
@@ -193,7 +193,7 @@ DankPopout {
visible: VpnService.connected visible: VpnService.connected
width: 130 width: 130
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
border.width: 1 border.width: 0
border.color: Theme.outlineLight border.color: Theme.outlineLight
Row { Row {

View File

@@ -73,7 +73,7 @@ Rectangle {
const currentScreen = parentScreen || Screen; const currentScreen = parentScreen || Screen;
const screenX = currentScreen.x || 0; const screenX = currentScreen.x || 0;
const relativeX = globalPos.x - screenX; const relativeX = globalPos.x - screenX;
popupTarget.setTriggerPosition(relativeX, barHeight + Theme.spacingXS, width, section, currentScreen); popupTarget.setTriggerPosition(relativeX, barHeight + SettingsData.topBarSpacing + SettingsData.topBarBottomGap - 2 + Theme.popupDistance, width, section, currentScreen);
} }
root.clicked(); root.clicked();
} }

View File

@@ -271,6 +271,8 @@ Rectangle {
model: root.workspaceList model: root.workspaceList
Rectangle { Rectangle {
id: delegateRoot
property bool isActive: { property bool isActive: {
if (CompositorService.isHyprland) { if (CompositorService.isHyprland) {
return modelData && modelData.id === root.currentWorkspace return modelData && modelData.id === root.currentWorkspace
@@ -284,34 +286,72 @@ Rectangle {
return modelData === -1 return modelData === -1
} }
property bool isHovered: mouseArea.containsMouse property bool isHovered: mouseArea.containsMouse
property var workspaceData: {
if (isPlaceholder) {
return null
}
if (CompositorService.isNiri) { property var loadedWorkspaceData: null
return NiriService.allWorkspaces.find(ws => ws.idx + 1 === modelData && ws.output === root.screenName) || null property var loadedIconData: null
} property bool loadedHasIcon: false
return CompositorService.isHyprland ? modelData : null property var loadedIcons: []
}
property var iconData: workspaceData?.name ? SettingsData.getWorkspaceNameIcon(workspaceData.name) : null
property bool hasIcon: iconData !== null
property var icons: SettingsData.showWorkspaceApps ? root.getWorkspaceIcons(CompositorService.isHyprland ? modelData : (modelData === -1 ? null : modelData)) : []
width: { Timer {
if (SettingsData.showWorkspaceApps) { id: dataUpdateTimer
if (icons.length > 0) { interval: 50 // Defer data calculation by 50ms
return isActive ? widgetHeight * 1.0 + Theme.spacingXS + contentRow.implicitWidth : widgetHeight * 0.8 + contentRow.implicitWidth onTriggered: {
if (isPlaceholder) {
delegateRoot.loadedWorkspaceData = null
delegateRoot.loadedIconData = null
delegateRoot.loadedHasIcon = false
delegateRoot.loadedIcons = []
return
}
var wsData = null;
if (CompositorService.isNiri) {
wsData = NiriService.allWorkspaces.find(ws => ws.idx + 1 === modelData && ws.output === root.screenName) || null;
} else if (CompositorService.isHyprland) {
wsData = modelData;
}
delegateRoot.loadedWorkspaceData = wsData;
var icData = null;
if (wsData?.name) {
icData = SettingsData.getWorkspaceNameIcon(wsData.name);
}
delegateRoot.loadedIconData = icData;
delegateRoot.loadedHasIcon = icData !== null;
if (SettingsData.showWorkspaceApps) {
delegateRoot.loadedIcons = root.getWorkspaceIcons(CompositorService.isHyprland ? modelData : (modelData === -1 ? null : modelData));
} else { } else {
return isActive ? widgetHeight * 1.0 + Theme.spacingXS : widgetHeight * 0.8 delegateRoot.loadedIcons = [];
} }
} }
return isActive ? widgetHeight * 1.2 + Theme.spacingXS : widgetHeight * 0.8 }
function updateAllData() {
dataUpdateTimer.restart()
}
width: {
if (SettingsData.showWorkspaceApps && loadedIcons.length > 0) {
const numIcons = Math.min(loadedIcons.length, SettingsData.maxWorkspaceIcons);
const iconsWidth = numIcons * 18 + (numIcons > 0 ? (numIcons - 1) * Theme.spacingXS : 0);
const baseWidth = isActive ? root.widgetHeight * 1.0 + Theme.spacingXS : root.widgetHeight * 0.8;
return baseWidth + iconsWidth;
}
return isActive ? root.widgetHeight * 1.2 : root.widgetHeight * 0.8;
} }
height: SettingsData.showWorkspaceApps ? widgetHeight * 0.8 : widgetHeight * 0.6 height: SettingsData.showWorkspaceApps ? widgetHeight * 0.8 : widgetHeight * 0.6
radius: height / 2 radius: height / 2
color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha color: isActive ? Theme.primary : isPlaceholder ? Theme.surfaceTextLight : isHovered ? Theme.outlineButton : Theme.surfaceTextAlpha
Behavior on width {
enabled: (!SettingsData.showWorkspaceApps || SettingsData.maxWorkspaceIcons <= 3)
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
MouseArea { MouseArea {
id: mouseArea id: mouseArea
@@ -332,118 +372,153 @@ Rectangle {
} }
} }
Row { // Loader for App Icons
id: contentRow Loader {
anchors.centerIn: parent id: appIconsLoader
spacing: 4 anchors.fill: parent
visible: SettingsData.showWorkspaceApps && icons.length > 0 active: SettingsData.showWorkspaceApps
sourceComponent: Item {
Row {
id: contentRow
anchors.centerIn: parent
spacing: 4
visible: loadedIcons.length > 0
Repeater { Repeater {
model: icons.slice(0, SettingsData.maxWorkspaceIcons) model: loadedIcons.slice(0, SettingsData.maxWorkspaceIcons)
delegate: Item { delegate: Item {
width: 18 width: 18
height: 18 height: 18
IconImage { IconImage {
id: appIcon id: appIcon
property var windowId: modelData.windowId property var windowId: modelData.windowId
anchors.fill: parent anchors.fill: parent
source: modelData.icon source: modelData.icon
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6 opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
visible: !modelData.isSteamApp visible: !modelData.isSteamApp
} }
DankIcon { DankIcon {
anchors.centerIn: parent anchors.centerIn: parent
size: 18 size: 18
name: "sports_esports" name: "sports_esports"
color: Theme.surfaceText color: Theme.surfaceText
opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6 opacity: modelData.active ? 1.0 : appMouseArea.containsMouse ? 0.8 : 0.6
visible: modelData.isSteamApp visible: modelData.isSteamApp
} }
MouseArea { MouseArea {
id: appMouseArea id: appMouseArea
hoverEnabled: true hoverEnabled: true
anchors.fill: parent anchors.fill: parent
enabled: isActive enabled: isActive
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
if (CompositorService.isHyprland) { if (CompositorService.isHyprland) {
Hyprland.dispatch(`focuswindow address:${appIcon.windowId}`) Hyprland.dispatch(`focuswindow address:${appIcon.windowId}`)
} else if (CompositorService.isNiri) { } else if (CompositorService.isNiri) {
NiriService.focusWindow(appIcon.windowId) NiriService.focusWindow(appIcon.windowId)
}
}
}
Rectangle {
visible: modelData.count > 1 && !isActive
width: 12
height: 12
radius: 6
color: "black"
border.color: "white"
border.width: 1
anchors.right: parent.right
anchors.bottom: parent.bottom
z: 2
Text {
anchors.centerIn: parent
text: modelData.count
font.pixelSize: 8
color: "white"
}
} }
} }
} }
}
}
}
Rectangle { // Loader for Custom Name Icon
visible: modelData.count > 1 && !isActive Loader {
width: 12 id: customIconLoader
height: 12 anchors.fill: parent
radius: 6 active: !isPlaceholder && loadedHasIcon && loadedIconData.type === "icon" && !SettingsData.showWorkspaceApps
color: "black" sourceComponent: Item {
border.color: "white" DankIcon {
border.width: 1 anchors.centerIn: parent
anchors.right: parent.right name: loadedIconData ? loadedIconData.value : "" // NULL CHECK
anchors.bottom: parent.bottom size: Theme.fontSizeSmall
z: 2 color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
weight: isActive && !isPlaceholder ? 500 : 400
}
}
}
Text { // Loader for Custom Name Text
anchors.centerIn: parent Loader {
text: modelData.count id: customTextLoader
font.pixelSize: 8 anchors.fill: parent
color: "white" active: !isPlaceholder && loadedHasIcon && loadedIconData.type === "text" && !SettingsData.showWorkspaceApps
sourceComponent: Item {
StyledText {
anchors.centerIn: parent
text: loadedIconData ? loadedIconData.value : "" // NULL CHECK
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
}
}
}
// Loader for Workspace Index
Loader {
id: indexLoader
anchors.fill: parent
active: !isPlaceholder && SettingsData.showWorkspaceIndex && !loadedHasIcon && !SettingsData.showWorkspaceApps
sourceComponent: Item {
StyledText {
anchors.centerIn: parent
text: {
const isPlaceholder = CompositorService.isHyprland ? (modelData?.id === -1) : (modelData === -1)
if (isPlaceholder) {
return index + 1
} }
return CompositorService.isHyprland ? (modelData?.id || "") : (modelData - 1);
} }
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
} }
} }
} }
DankIcon { // --- LOGIC / TRIGGERS ---
visible: hasIcon && iconData.type === "icon" && (!SettingsData.showWorkspaceApps || icons.length === 0) Component.onCompleted: updateAllData()
anchors.centerIn: parent
name: (hasIcon && iconData.type === "icon") ? iconData.value : "" Connections {
size: Theme.fontSizeSmall target: CompositorService
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium function onSortedToplevelsChanged() { delegateRoot.updateAllData() }
weight: isActive && !isPlaceholder ? 500 : 400
} }
Connections {
StyledText { target: NiriService
visible: hasIcon && iconData.type === "text" && (!SettingsData.showWorkspaceApps || icons.length === 0) enabled: CompositorService.isNiri
anchors.centerIn: parent function onAllWorkspacesChanged() { delegateRoot.updateAllData() }
text: (hasIcon && iconData.type === "text") ? iconData.value : ""
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
} }
Connections {
StyledText { target: SettingsData
visible: (SettingsData.showWorkspaceIndex && !hasIcon && (!SettingsData.showWorkspaceApps || icons.length === 0)) function onShowWorkspaceAppsChanged() { delegateRoot.updateAllData() }
anchors.centerIn: parent function onWorkspaceNameIconsChanged() { delegateRoot.updateAllData() }
text: {
const isPlaceholder = CompositorService.isHyprland ? (modelData?.id === -1) : (modelData === -1)
if (isPlaceholder) {
return index + 1
}
return CompositorService.isHyprland ? (modelData?.id || "") : (modelData - 1)
}
color: isActive ? Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95) : isPlaceholder ? Theme.surfaceTextAlpha : Theme.surfaceTextMedium
font.pixelSize: Theme.fontSizeSmall
font.weight: (isActive && !isPlaceholder) ? Font.DemiBold : Font.Normal
} }
Behavior on width {
// When having more icons, animation becomes clunky
enabled: (!SettingsData.showWorkspaceApps || SettingsData.maxWorkspaceIcons <= 3)
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
} }
} }
} }

View File

@@ -37,8 +37,24 @@ LazyLoader {
property string source: SessionData.getMonitorWallpaper(modelData.name) || "" property string source: SessionData.getMonitorWallpaper(modelData.name) || ""
property bool isColorSource: source.startsWith("#") property bool isColorSource: source.startsWith("#")
property string transitionType: SessionData.wallpaperTransition property string transitionType: SessionData.wallpaperTransition
property string actualTransitionType: transitionType
onTransitionTypeChanged: { onTransitionTypeChanged: {
currentWallpaper.visible = (transitionType === "none") if (transitionType === "random") {
if (SessionData.includedTransitions.length === 0) {
actualTransitionType = "none"
} else {
actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
}
} else {
actualTransitionType = transitionType
}
}
onActualTransitionTypeChanged: {
if (actualTransitionType === "none") {
currentWallpaper.visible = true
nextWallpaper.visible = false
}
} }
property real transitionProgress: 0 property real transitionProgress: 0
property real fillMode: 1.0 property real fillMode: 1.0
@@ -95,6 +111,8 @@ LazyLoader {
root.transitionProgress = 0.0 root.transitionProgress = 0.0
currentWallpaper.source = newSource currentWallpaper.source = newSource
nextWallpaper.source = "" nextWallpaper.source = ""
currentWallpaper.visible = true
nextWallpaper.visible = false
} }
function changeWallpaper(newPath, force) { function changeWallpaper(newPath, force) {
@@ -115,17 +133,25 @@ LazyLoader {
} }
// If transition is "none", set immediately // If transition is "none", set immediately
if (root.transitionType === "none") { if (root.transitionType === "random") {
if (SessionData.includedTransitions.length === 0) {
root.actualTransitionType = "none"
} else {
root.actualTransitionType = SessionData.includedTransitions[Math.floor(Math.random() * SessionData.includedTransitions.length)]
}
}
if (root.actualTransitionType === "none") {
setWallpaperImmediate(newPath) setWallpaperImmediate(newPath)
return return
} }
if (root.transitionType === "wipe") { if (root.actualTransitionType === "wipe") {
root.wipeDirection = Math.random() * 4 root.wipeDirection = Math.random() * 4
} else if (root.transitionType === "disc") { } else if (root.actualTransitionType === "disc") {
root.discCenterX = Math.random() root.discCenterX = Math.random()
root.discCenterY = Math.random() root.discCenterY = Math.random()
} else if (root.transitionType === "stripes") { } else if (root.actualTransitionType === "stripes") {
root.stripesCount = Math.round(Math.random() * 20 + 4) root.stripesCount = Math.round(Math.random() * 20 + 4)
root.stripesAngle = Math.random() * 360 root.stripesAngle = Math.random() * 360
} }
@@ -165,7 +191,7 @@ LazyLoader {
Image { Image {
id: currentWallpaper id: currentWallpaper
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "none" visible: root.actualTransitionType === "none"
opacity: 1 opacity: 1
layer.enabled: false layer.enabled: false
asynchronous: true asynchronous: true
@@ -188,7 +214,7 @@ LazyLoader {
onStatusChanged: { onStatusChanged: {
if (status !== Image.Ready) return if (status !== Image.Ready) return
if (root.transitionType === "none") { if (root.actualTransitionType === "none") {
currentWallpaper.source = source currentWallpaper.source = source
nextWallpaper.source = "" nextWallpaper.source = ""
root.transitionProgress = 0.0 root.transitionProgress = 0.0
@@ -206,7 +232,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: fadeShader id: fadeShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "fade" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "fade" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -226,7 +252,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: wipeShader id: wipeShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "wipe" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "wipe" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -248,7 +274,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: discShader id: discShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "disc" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "disc" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -272,7 +298,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: stripesShader id: stripesShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "stripes" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "stripes" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -296,7 +322,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: irisBloomShader id: irisBloomShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "iris bloom" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "iris bloom" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -320,7 +346,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: pixelateShader id: pixelateShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "pixelate" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "pixelate" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -344,7 +370,7 @@ LazyLoader {
ShaderEffect { ShaderEffect {
id: portalShader id: portalShader
anchors.fill: parent anchors.fill: parent
visible: root.transitionType === "portal" && (root.hasCurrent || root.booting) visible: root.actualTransitionType === "portal" && (root.hasCurrent || root.booting)
property variant source1: root.hasCurrent ? currentWallpaper : transparentSource property variant source1: root.hasCurrent ? currentWallpaper : transparentSource
property variant source2: nextWallpaper property variant source2: nextWallpaper
@@ -371,7 +397,7 @@ LazyLoader {
property: "transitionProgress" property: "transitionProgress"
from: 0.0 from: 0.0
to: 1.0 to: 1.0
duration: root.transitionType === "none" ? 0 : 1000 duration: root.actualTransitionType === "none" ? 0 : 1000
easing.type: Easing.InOutCubic easing.type: Easing.InOutCubic
onFinished: { onFinished: {
Qt.callLater(() => { Qt.callLater(() => {
@@ -380,7 +406,7 @@ LazyLoader {
} }
nextWallpaper.source = "" nextWallpaper.source = ""
nextWallpaper.visible = false nextWallpaper.visible = false
currentWallpaper.visible = root.transitionType === "none" currentWallpaper.visible = root.actualTransitionType === "none"
currentWallpaper.layer.enabled = false currentWallpaper.layer.enabled = false
nextWallpaper.layer.enabled = false nextWallpaper.layer.enabled = false
root.transitionProgress = 0.0 root.transitionProgress = 0.0

View File

@@ -310,6 +310,9 @@ binds {
Mod+X hotkey-overlay-title="Power Menu" { Mod+X hotkey-overlay-title="Power Menu" {
spawn "dms" "ipc" "call" "powermenu" "toggle"; spawn "dms" "ipc" "call" "powermenu" "toggle";
} }
Mod+C hotkey-overlay-title="Control Center" {
spawn "dms" "ipc" "call" "control-center" "toggle";
}
XF86AudioRaiseVolume allow-when-locked=true { XF86AudioRaiseVolume allow-when-locked=true {
spawn "dms" "ipc" "call" "audio" "increment" "3"; spawn "dms" "ipc" "call" "audio" "increment" "3";
} }
@@ -366,6 +369,7 @@ bind = SUPER, comma, exec, dms ipc call settings toggle
bind = SUPER, P, exec, dms ipc call notepad toggle bind = SUPER, P, exec, dms ipc call notepad toggle
bind = SUPERALT, L, exec, dms ipc call lock lock bind = SUPERALT, L, exec, dms ipc call lock lock
bind = SUPER, X, exec, dms ipc call powermenu toggle bind = SUPER, X, exec, dms ipc call powermenu toggle
bind = SUPER, C, exec, dms ipc call control-center toggle
# Audio controls (function keys) # Audio controls (function keys)
bindl = , XF86AudioRaiseVolume, exec, dms ipc call audio increment 3 bindl = , XF86AudioRaiseVolume, exec, dms ipc call audio increment 3
@@ -413,6 +417,8 @@ dms ipc call mpris next
## Theming ## Theming
dms will spawn a matugen process on theme changes to generate color palettes for installed and supported apps. If you do not want these files generated, you can set the env variable `DMS_DISABLE_MATUGEN=1` to disable it entirely.
### Custom Themes ### Custom Themes
DankMaterialShell supports custom color themes! You can create your own Material Design 3 color schemes or use pre-made themes like Cyberpunk Electric, Hotline Miami, and Miami Vice. DankMaterialShell supports custom color themes! You can create your own Material Design 3 color schemes or use pre-made themes like Cyberpunk Electric, Hotline Miami, and Miami Vice.
@@ -550,6 +556,13 @@ You can enable the dynamic color schemes in supported terminal apps by modifying
echo "config-file = ./config-dankcolors" >> ~/.config/ghostty/config echo "config-file = ./config-dankcolors" >> ~/.config/ghostty/config
``` ```
If you want to disable excessive config reloaded popup sin ghostty, you may wish to also add this:
```bash
# These are the default danklinux options, if you still want config reloaded and copied to clipboard popups you can skip it.
echo "app-notifications = no-clipboard-copy,no-config-reload" >> ~/.config/ghostty/config
```
**kitty**: **kitty**:
```bash ```bash

View File

@@ -71,55 +71,47 @@ Singleton {
} }
` `
if (monitorTimeout > 0) { monitorOffMonitor = Qt.createQmlObject(qmlString, root, "IdleService.MonitorOffMonitor")
monitorOffMonitor = Qt.createQmlObject(qmlString, root, "IdleService.MonitorOffMonitor") monitorOffMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.monitorTimeout > 0)
monitorOffMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.monitorTimeout > 0) monitorOffMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors)
monitorOffMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors) monitorOffMonitor.timeout = Qt.binding(() => root.monitorTimeout)
monitorOffMonitor.timeout = Qt.binding(() => root.monitorTimeout) monitorOffMonitor.isIdleChanged.connect(function() {
monitorOffMonitor.isIdleChanged.connect(function() { if (monitorOffMonitor.isIdle) {
if (monitorOffMonitor.isIdle) { root.requestMonitorOff()
root.requestMonitorOff() } else {
} else { root.requestMonitorOn()
root.requestMonitorOn() }
} })
})
}
if (lockTimeout > 0) { lockMonitor = Qt.createQmlObject(qmlString, root, "IdleService.LockMonitor")
lockMonitor = Qt.createQmlObject(qmlString, root, "IdleService.LockMonitor") lockMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.lockTimeout > 0)
lockMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.lockTimeout > 0) lockMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors)
lockMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors) lockMonitor.timeout = Qt.binding(() => root.lockTimeout)
lockMonitor.timeout = Qt.binding(() => root.lockTimeout) lockMonitor.isIdleChanged.connect(function() {
lockMonitor.isIdleChanged.connect(function() { if (lockMonitor.isIdle) {
if (lockMonitor.isIdle) { root.lockRequested()
root.lockRequested() }
} })
})
}
if (suspendTimeout > 0) { suspendMonitor = Qt.createQmlObject(qmlString, root, "IdleService.SuspendMonitor")
suspendMonitor = Qt.createQmlObject(qmlString, root, "IdleService.SuspendMonitor") suspendMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.suspendTimeout > 0)
suspendMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.suspendTimeout > 0) suspendMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors)
suspendMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors) suspendMonitor.timeout = Qt.binding(() => root.suspendTimeout)
suspendMonitor.timeout = Qt.binding(() => root.suspendTimeout) suspendMonitor.isIdleChanged.connect(function() {
suspendMonitor.isIdleChanged.connect(function() { if (suspendMonitor.isIdle) {
if (suspendMonitor.isIdle) { root.requestSuspend()
root.requestSuspend() }
} })
})
}
if (hibernateTimeout > 0 && SessionService.hibernateSupported) { hibernateMonitor = Qt.createQmlObject(qmlString, root, "IdleService.HibernateMonitor")
hibernateMonitor = Qt.createQmlObject(qmlString, root, "IdleService.HibernateMonitor") hibernateMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.hibernateTimeout > 0)
hibernateMonitor.enabled = Qt.binding(() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.hibernateTimeout > 0) hibernateMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors)
hibernateMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors) hibernateMonitor.timeout = Qt.binding(() => root.hibernateTimeout)
hibernateMonitor.timeout = Qt.binding(() => root.hibernateTimeout) hibernateMonitor.isIdleChanged.connect(function() {
hibernateMonitor.isIdleChanged.connect(function() { if (hibernateMonitor.isIdle) {
if (hibernateMonitor.isIdle) { root.requestHibernate()
root.requestHibernate() }
} })
})
}
} catch (e) { } catch (e) {
console.warn("IdleService: Error creating IdleMonitors:", e) console.warn("IdleService: Error creating IdleMonitors:", e)
} }

View File

@@ -2,13 +2,15 @@ import QtQuick
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
Row { Flow {
id: root id: root
property var model: [] property var model: []
property int currentIndex: -1 property int currentIndex: -1
property string selectionMode: "single" property string selectionMode: "single"
property bool multiSelect: selectionMode === "multi" property bool multiSelect: selectionMode === "multi"
property var initialSelection: []
property var currentSelection: initialSelection
property bool checkEnabled: true property bool checkEnabled: true
property int buttonHeight: 40 property int buttonHeight: 40
property int minButtonWidth: 64 property int minButtonWidth: 64
@@ -29,11 +31,18 @@ Row {
function selectItem(index) { function selectItem(index) {
if (multiSelect) { if (multiSelect) {
const item = repeater.itemAt(index) const modelValue = model[index]
if (item) { let newSelection = [...currentSelection]
item.selected = !item.selected const isCurrentlySelected = newSelection.includes(modelValue)
selectionChanged(index, item.selected)
if (isCurrentlySelected) {
newSelection = newSelection.filter(item => item !== modelValue)
} else {
newSelection.push(modelValue)
} }
currentSelection = newSelection
selectionChanged(index, !isCurrentlySelected)
} else { } else {
const oldIndex = currentIndex const oldIndex = currentIndex
currentIndex = index currentIndex = index
@@ -51,7 +60,7 @@ Row {
delegate: Rectangle { delegate: Rectangle {
id: segment id: segment
property bool selected: multiSelect ? false : (index === root.currentIndex) property bool selected: multiSelect ? root.currentSelection.includes(modelData) : (index === root.currentIndex)
property bool hovered: mouseArea.containsMouse property bool hovered: mouseArea.containsMouse
property bool pressed: mouseArea.pressed property bool pressed: mouseArea.pressed
property bool isFirst: index === 0 property bool isFirst: index === 0

View File

@@ -335,7 +335,7 @@ Rectangle {
onClicked: { onClicked: {
root.currentValue = modelData root.currentValue = modelData
root.valueChanged(modelData) root.valueChanged(modelData)
dropdownMenu.close() listView.popupRef.close()
} }
} }
} }

View File

@@ -36,7 +36,7 @@ Item {
id: background id: background
anchors.fill: parent anchors.fill: parent
radius: showText ? Theme.cornerRadius : 0 radius: showText ? Theme.cornerRadius : 0
color: showText ? Theme.surfaceHover : "transparent" color: "transparent"
visible: showText visible: showText
StateLayer { StateLayer {

View File

@@ -0,0 +1,51 @@
import QtQuick
import QtQuick.Controls
import qs.Common
Row {
id: root
property int currentSize: 50
property bool isSlider: false
property int widgetIndex: -1
signal sizeChanged(int newSize)
readonly property var availableSizes: isSlider ? [50, 100] : [25, 50, 75, 100]
spacing: 2
Repeater {
model: root.availableSizes
Rectangle {
width: 16
height: 16
radius: 3
color: modelData === root.currentSize ? Theme.primary : Theme.surfaceContainer
border.color: modelData === root.currentSize ? Theme.primary : Theme.outline
border.width: 1
StyledText {
anchors.centerIn: parent
text: modelData.toString()
font.pixelSize: 8
font.weight: Font.Medium
color: modelData === root.currentSize ? Theme.primaryContainer : Theme.surfaceText
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
root.currentSize = modelData
root.sizeChanged(modelData)
}
}
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
}
}
}

View File

@@ -28,6 +28,7 @@ These are the essential colors that define your theme's appearance:
"outline": "#80FF80", "outline": "#80FF80",
"surfaceContainer": "#1A2B1A", "surfaceContainer": "#1A2B1A",
"surfaceContainerHigh": "#264026", "surfaceContainerHigh": "#264026",
"surfaceContainerHighest": "#33553F",
"error": "#FF0066", "error": "#FF0066",
"warning": "#CCFF00", "warning": "#CCFF00",
"info": "#00FFCC", "info": "#00FFCC",
@@ -49,6 +50,7 @@ These are the essential colors that define your theme's appearance:
"outline": "#4DCC4D", "outline": "#4DCC4D",
"surfaceContainer": "#F5FFF5", "surfaceContainer": "#F5FFF5",
"surfaceContainerHigh": "#EBFFEB", "surfaceContainerHigh": "#EBFFEB",
"surfaceContainerHighest": "#E1FFE1",
"error": "#B3004D", "error": "#B3004D",
"warning": "#99CC00", "warning": "#99CC00",
"info": "#00B899", "info": "#00B899",
@@ -96,6 +98,7 @@ There are example themes you can start from:
- `surfaceVariantText` - Text color for surfaceVariant backgrounds - `surfaceVariantText` - Text color for surfaceVariant backgrounds
- `surfaceContainer` - Container surface color, slightly different from surface - `surfaceContainer` - Container surface color, slightly different from surface
- `surfaceContainerHigh` - Elevated container color for layered interfaces - `surfaceContainerHigh` - Elevated container color for layered interfaces
- `surfaceContainerHighest` - Highest elevation container color for top-level surfaces
**Background Colors** **Background Colors**
- `background` - Main background color for the entire interface - `background` - Main background color for the entire interface

Some files were not shown because too many files have changed in this diff Show More