1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 21:42:51 -05:00

replace qmlformat with a better tool

still not perfect, but well - what can ya do
This commit is contained in:
bbedward
2025-08-08 15:55:37 -04:00
parent 8dc6e2805d
commit 4d408c65f2
137 changed files with 30315 additions and 29625 deletions

View File

@@ -1,28 +1,26 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
Singleton {
id: root
id: root
readonly property int durShort: 200
readonly property int durMed: 450
readonly property int durLong: 600
readonly property int durShort: 200
readonly property int durMed: 450
readonly property int durLong: 600
readonly property int slidePx: 80
readonly property int slidePx: 80
readonly property var emphasized: [
0.05, 0.00, 0.133333, 0.06, 0.166667, 0.40,
0.208333, 0.82, 0.25, 1.00, 1.00, 1.00
]
readonly property var emphasized: [0.05, 0.00, 0.133333, 0.06, 0.166667, 0.40, 0.208333, 0.82, 0.25, 1.00, 1.00, 1.00]
readonly property var emphasizedDecel: [ 0.05, 0.70, 0.10, 1.00, 1.00, 1.00 ]
readonly property var emphasizedDecel: [0.05, 0.70, 0.10, 1.00, 1.00, 1.00]
readonly property var emphasizedAccel: [ 0.30, 0.00, 0.80, 0.15, 1.00, 1.00 ]
readonly property var emphasizedAccel: [0.30, 0.00, 0.80, 0.15, 1.00, 1.00]
readonly property var standard: [ 0.20, 0.00, 0.00, 1.00, 1.00, 1.00 ]
readonly property var standardDecel: [ 0.00, 0.00, 0.00, 1.00, 1.00, 1.00 ]
readonly property var standardAccel: [ 0.30, 0.00, 1.00, 1.00, 1.00, 1.00 ]
}
readonly property var standard: [0.20, 0.00, 0.00, 1.00, 1.00, 1.00]
readonly property var standardDecel: [0.00, 0.00, 0.00, 1.00, 1.00, 1.00]
readonly property var standardAccel: [0.30, 0.00, 1.00, 1.00, 1.00, 1.00]
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtCore
import QtQuick
@@ -8,118 +9,123 @@ import Quickshell.Io
Singleton {
id: root
id: root
property var appUsageRanking: {}
property var appUsageRanking: {
Component.onCompleted: {
loadSettings();
}
Component.onCompleted: {
loadSettings()
}
function loadSettings() {
parseSettings(settingsFile.text())
}
function parseSettings(content) {
try {
if (content && content.trim()) {
var settings = JSON.parse(content)
appUsageRanking = settings.appUsageRanking || {}
}
} catch (e) {
}
}
function saveSettings() {
settingsFile.setText(JSON.stringify({
"appUsageRanking": appUsageRanking
}, null, 2))
}
function addAppUsage(app) {
if (!app)
return
var appId = app.id || (app.execString || app.exec || "")
if (!appId)
return
var currentRanking = Object.assign({}, appUsageRanking)
if (currentRanking[appId]) {
currentRanking[appId].usageCount = (currentRanking[appId].usageCount
|| 1) + 1
currentRanking[appId].lastUsed = Date.now()
currentRanking[appId].icon = app.icon || currentRanking[appId].icon
|| "application-x-executable"
currentRanking[appId].name = app.name || currentRanking[appId].name || ""
} else {
currentRanking[appId] = {
"name": app.name || "",
"exec": app.execString || app.exec || "",
"icon": app.icon || "application-x-executable",
"comment": app.comment || "",
"usageCount": 1,
"lastUsed": Date.now()
}
}
function loadSettings() {
parseSettings(settingsFile.text());
appUsageRanking = currentRanking
saveSettings()
}
function getAppUsageRanking() {
return appUsageRanking
}
function getRankedApps() {
var apps = []
for (var appId in appUsageRanking) {
var appData = appUsageRanking[appId]
apps.push({
"id": appId,
"name": appData.name,
"exec": appData.exec,
"icon": appData.icon,
"comment": appData.comment,
"usageCount": appData.usageCount,
"lastUsed": appData.lastUsed
})
}
function parseSettings(content) {
try {
if (content && content.trim()) {
var settings = JSON.parse(content);
appUsageRanking = settings.appUsageRanking || {};
}
} catch (e) {
}
return apps.sort(function (a, b) {
if (a.usageCount !== b.usageCount)
return b.usageCount - a.usageCount
return a.name.localeCompare(b.name)
})
}
function cleanupAppUsageRanking(availableAppIds) {
var currentRanking = Object.assign({}, appUsageRanking)
var hasChanges = false
for (var appId in currentRanking) {
if (availableAppIds.indexOf(appId) === -1) {
delete currentRanking[appId]
hasChanges = true
}
}
function saveSettings() {
settingsFile.setText(JSON.stringify({
"appUsageRanking": appUsageRanking
}, null, 2));
if (hasChanges) {
appUsageRanking = currentRanking
saveSettings()
}
}
function addAppUsage(app) {
if (!app)
return;
FileView {
id: settingsFile
var appId = app.id || (app.execString || app.exec || "");
if (!appId)
return;
var currentRanking = Object.assign({}, appUsageRanking);
if (currentRanking[appId]) {
currentRanking[appId].usageCount = (currentRanking[appId].usageCount || 1) + 1;
currentRanking[appId].lastUsed = Date.now();
currentRanking[appId].icon = app.icon || currentRanking[appId].icon || "application-x-executable";
currentRanking[appId].name = app.name || currentRanking[appId].name || "";
} else {
currentRanking[appId] = {
"name": app.name || "",
"exec": app.execString || app.exec || "",
"icon": app.icon || "application-x-executable",
"comment": app.comment || "",
"usageCount": 1,
"lastUsed": Date.now()
};
}
appUsageRanking = currentRanking;
saveSettings();
path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/appusage.json"
blockLoading: true
blockWrites: true
watchChanges: true
onLoaded: {
parseSettings(settingsFile.text())
}
function getAppUsageRanking() {
return appUsageRanking;
}
function getRankedApps() {
var apps = [];
for (var appId in appUsageRanking) {
var appData = appUsageRanking[appId];
apps.push({
id: appId,
name: appData.name,
exec: appData.exec,
icon: appData.icon,
comment: appData.comment,
usageCount: appData.usageCount,
lastUsed: appData.lastUsed
});
}
return apps.sort(function(a, b) {
if (a.usageCount !== b.usageCount)
return b.usageCount - a.usageCount;
return a.name.localeCompare(b.name);
});
}
function cleanupAppUsageRanking(availableAppIds) {
var currentRanking = Object.assign({}, appUsageRanking);
var hasChanges = false;
for (var appId in currentRanking) {
if (availableAppIds.indexOf(appId) === -1) {
delete currentRanking[appId];
hasChanges = true;
}
}
if (hasChanges) {
appUsageRanking = currentRanking;
saveSettings();
}
}
FileView {
id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/appusage.json"
blockLoading: true
blockWrites: true
watchChanges: true
onLoaded: {
parseSettings(settingsFile.text());
}
onLoadFailed: (error) => {
}
}
}
onLoadFailed: error => {}
}
}

View File

@@ -1,65 +1,67 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtQuick
import Quickshell
Singleton {
id: root
id: root
readonly property Rounding rounding: Rounding {}
readonly property Spacing spacing: Spacing {}
readonly property FontSize fontSize: FontSize {}
readonly property Anim anim: Anim {}
readonly property Rounding rounding: Rounding {}
readonly property Spacing spacing: Spacing {}
readonly property FontSize fontSize: FontSize {}
readonly property Anim anim: Anim {}
component Rounding: QtObject {
readonly property int small: 8
readonly property int normal: 12
readonly property int large: 16
readonly property int extraLarge: 24
readonly property int full: 1000
}
component Rounding: QtObject {
readonly property int small: 8
readonly property int normal: 12
readonly property int large: 16
readonly property int extraLarge: 24
readonly property int full: 1000
}
component Spacing: QtObject {
readonly property int small: 4
readonly property int normal: 8
readonly property int large: 12
readonly property int extraLarge: 16
readonly property int huge: 24
}
component Spacing: QtObject {
readonly property int small: 4
readonly property int normal: 8
readonly property int large: 12
readonly property int extraLarge: 16
readonly property int huge: 24
}
component FontSize: QtObject {
readonly property int small: 12
readonly property int normal: 14
readonly property int large: 16
readonly property int extraLarge: 20
readonly property int huge: 24
}
component FontSize: QtObject {
readonly property int small: 12
readonly property int normal: 14
readonly property int large: 16
readonly property int extraLarge: 20
readonly property int huge: 24
}
component AnimCurves: QtObject {
readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1]
readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
readonly property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]
readonly property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1]
readonly property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1]
}
component AnimCurves: QtObject {
readonly property list<real> standard: [0.2, 0, 0, 1, 1, 1]
readonly property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
readonly property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
readonly property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1
/ 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
readonly property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
readonly property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
readonly property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]
readonly property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1]
readonly property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1]
}
component AnimDurations: QtObject {
readonly property int quick: 150
readonly property int normal: 300
readonly property int slow: 500
readonly property int extraSlow: 1000
readonly property int expressiveFastSpatial: 350
readonly property int expressiveDefaultSpatial: 500
readonly property int expressiveEffects: 200
}
component AnimDurations: QtObject {
readonly property int quick: 150
readonly property int normal: 300
readonly property int slow: 500
readonly property int extraSlow: 1000
readonly property int expressiveFastSpatial: 350
readonly property int expressiveDefaultSpatial: 500
readonly property int expressiveEffects: 200
}
component Anim: QtObject {
readonly property AnimCurves curves: AnimCurves {}
readonly property AnimDurations durations: AnimDurations {}
}
}
component Anim: QtObject {
readonly property AnimCurves curves: AnimCurves {}
readonly property AnimDurations durations: AnimDurations {}
}
}

View File

@@ -3,39 +3,43 @@ import qs.Common
pragma Singleton
Singleton {
id: root
id: root
// Clear all image cache
function clearImageCache() {
Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)]);
Paths.mkdir(Paths.imagecache);
}
// Clear all image cache
function clearImageCache() {
Quickshell.execDetached(["rm", "-rf", Paths.stringify(Paths.imagecache)])
Paths.mkdir(Paths.imagecache)
}
// Clear cache older than specified minutes
function clearOldCache(ageInMinutes) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"]);
}
// Clear cache older than specified minutes
function clearOldCache(ageInMinutes) {
Quickshell.execDetached(
["find", Paths.stringify(
Paths.imagecache), "-name", "*.png", "-mmin", `+${ageInMinutes}`, "-delete"])
}
// Clear cache for specific size
function clearCacheForSize(size) {
Quickshell.execDetached(["find", Paths.stringify(Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"]);
}
// Get cache size in MB
function getCacheSize(callback) {
var process = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["du", "-sm", "${Paths.stringify(Paths.imagecache)}"]
running: true
stdout: StdioCollector {
onStreamFinished: {
var sizeMB = parseInt(text.split("\\t")[0]) || 0
callback(sizeMB)
}
}
}
`, root);
}
// Clear cache for specific size
function clearCacheForSize(size) {
Quickshell.execDetached(
["find", Paths.stringify(
Paths.imagecache), "-name", `*@${size}x${size}.png`, "-delete"])
}
// Get cache size in MB
function getCacheSize(callback) {
var process = Qt.createQmlObject(`
import Quickshell.Io
Process {
command: ["du", "-sm", "${Paths.stringify(
Paths.imagecache)}"]
running: true
stdout: StdioCollector {
onStreamFinished: {
var sizeMB = parseInt(text.split("\\t")[0]) || 0
callback(sizeMB)
}
}
}
`, root)
}
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import Qt.labs.platform
import QtQuick
@@ -9,347 +10,376 @@ import qs.Services
import qs.Common
Singleton {
id: root
id: root
readonly property string _homeUrl: StandardPaths.writableLocation(StandardPaths.HomeLocation)
readonly property string homeDir: _homeUrl.startsWith("file://") ? _homeUrl.substring(7) : _homeUrl
readonly property string _configUrl: StandardPaths.writableLocation(StandardPaths.ConfigLocation)
readonly property string configDir: _configUrl.startsWith("file://") ? _configUrl.substring(7) : _configUrl
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace("file://", "").replace("/Common/", "")
readonly property string wallpaperPath: SessionData.wallpaperPath
property bool matugenAvailable: false
property bool gtkThemingEnabled: false
property bool qtThemingEnabled: false
property bool systemThemeGenerationInProgress: false
property string matugenJson: ""
property var matugenColors: ({})
property bool extractionRequested: false
property int colorUpdateTrigger: 0
property string lastWallpaperTimestamp: ""
property color primary: getMatugenColor("primary", "#42a5f5")
property color secondary: getMatugenColor("secondary", "#8ab4f8")
property color tertiary: getMatugenColor("tertiary", "#bb86fc")
property color tertiaryContainer: getMatugenColor("tertiary_container", "#3700b3")
property color error: getMatugenColor("error", "#cf6679")
property color inversePrimary: getMatugenColor("inverse_primary", "#6200ea")
property color bg: getMatugenColor("background", "#1a1c1e")
property color surface: getMatugenColor("surface", "#1a1c1e")
property color surfaceContainer: getMatugenColor("surface_container", "#1e2023")
property color surfaceContainerHigh: getMatugenColor("surface_container_high", "#292b2f")
property color surfaceVariant: getMatugenColor("surface_variant", "#44464f")
property color surfaceText: getMatugenColor("on_background", "#e3e8ef")
property color primaryText: getMatugenColor("on_primary", "#ffffff")
property color surfaceVariantText: getMatugenColor("on_surface_variant", "#c4c7c5")
property color primaryContainer: getMatugenColor("primary_container", "#1976d2")
property color surfaceTint: getMatugenColor("surface_tint", "#8ab4f8")
property color outline: getMatugenColor("outline", "#8e918f")
property color accentHi: primary
property color accentLo: secondary
readonly property string _homeUrl: StandardPaths.writableLocation(
StandardPaths.HomeLocation)
readonly property string homeDir: _homeUrl.startsWith(
"file://") ? _homeUrl.substring(
7) : _homeUrl
readonly property string _configUrl: StandardPaths.writableLocation(
StandardPaths.ConfigLocation)
readonly property string configDir: _configUrl.startsWith(
"file://") ? _configUrl.substring(
7) : _configUrl
readonly property string shellDir: Qt.resolvedUrl(".").toString().replace(
"file://", "").replace("/Common/", "")
readonly property string wallpaperPath: SessionData.wallpaperPath
property bool matugenAvailable: false
property bool gtkThemingEnabled: false
property bool qtThemingEnabled: false
property bool systemThemeGenerationInProgress: false
property string matugenJson: ""
property var matugenColors: ({})
property bool extractionRequested: false
property int colorUpdateTrigger: 0
property string lastWallpaperTimestamp: ""
property color primary: getMatugenColor("primary", "#42a5f5")
property color secondary: getMatugenColor("secondary", "#8ab4f8")
property color tertiary: getMatugenColor("tertiary", "#bb86fc")
property color tertiaryContainer: getMatugenColor("tertiary_container",
"#3700b3")
property color error: getMatugenColor("error", "#cf6679")
property color inversePrimary: getMatugenColor("inverse_primary", "#6200ea")
property color bg: getMatugenColor("background", "#1a1c1e")
property color surface: getMatugenColor("surface", "#1a1c1e")
property color surfaceContainer: getMatugenColor("surface_container",
"#1e2023")
property color surfaceContainerHigh: getMatugenColor(
"surface_container_high", "#292b2f")
property color surfaceVariant: getMatugenColor("surface_variant", "#44464f")
property color surfaceText: getMatugenColor("on_background", "#e3e8ef")
property color primaryText: getMatugenColor("on_primary", "#ffffff")
property color surfaceVariantText: getMatugenColor("on_surface_variant",
"#c4c7c5")
property color primaryContainer: getMatugenColor("primary_container",
"#1976d2")
property color surfaceTint: getMatugenColor("surface_tint", "#8ab4f8")
property color outline: getMatugenColor("outline", "#8e918f")
property color accentHi: primary
property color accentLo: secondary
signal colorsUpdated
signal colorsUpdated
function onLightModeChanged() {
if (matugenColors && Object.keys(matugenColors).length > 0) {
colorUpdateTrigger++;
colorsUpdated();
function onLightModeChanged() {
if (matugenColors && Object.keys(matugenColors).length > 0) {
colorUpdateTrigger++
colorsUpdated()
if (typeof Theme !== "undefined" && Theme.isDynamicTheme) {
generateSystemThemes();
}
if (typeof Theme !== "undefined" && Theme.isDynamicTheme) {
generateSystemThemes()
}
}
}
function extractColors() {
extractionRequested = true
if (matugenAvailable)
fileChecker.running = true
else
matugenCheck.running = true
}
function getMatugenColor(path, fallback) {
colorUpdateTrigger
const colorMode = (typeof SessionData !== "undefined"
&& SessionData.isLightMode) ? "light" : "dark"
let cur = matugenColors && matugenColors.colors
&& matugenColors.colors[colorMode]
for (const part of path.split(".")) {
if (!cur || typeof cur !== "object" || !(part in cur))
return fallback
cur = cur[part]
}
return cur || fallback
}
function isColorDark(c) {
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5
}
Component.onCompleted: {
matugenCheck.running = true
checkGtkThemingAvailability()
checkQtThemingAvailability()
if (typeof SessionData !== "undefined")
SessionData.isLightModeChanged.connect(root.onLightModeChanged)
}
Process {
id: matugenCheck
command: ["which", "matugen"]
onExited: code => {
matugenAvailable = (code === 0)
if (!matugenAvailable) {
ToastService.wallpaperErrorStatus = "matugen_missing"
ToastService.showWarning("matugen not found - dynamic theming disabled")
return
}
if (extractionRequested) {
fileChecker.running = true
}
}
}
Process {
id: fileChecker
command: ["test", "-r", wallpaperPath]
onExited: code => {
if (code === 0) {
matugenProcess.running = true
} else {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper processing failed")
}
}
}
Process {
id: matugenProcess
command: ["matugen", "-v", "image", wallpaperPath, "--json", "hex"]
stdout: StdioCollector {
id: matugenCollector
onStreamFinished: {
const out = matugenCollector.text
if (!out.length) {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed")
return
}
}
function extractColors() {
extractionRequested = true;
if (matugenAvailable)
fileChecker.running = true;
else
matugenCheck.running = true;
}
function getMatugenColor(path, fallback) {
colorUpdateTrigger;
const colorMode = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "light" : "dark";
let cur = matugenColors && matugenColors.colors && matugenColors.colors[colorMode];
for (const part of path.split(".")) {
if (!cur || typeof cur !== "object" || !(part in cur))
return fallback;
cur = cur[part];
try {
root.matugenJson = out
root.matugenColors = JSON.parse(out)
root.colorsUpdated()
generateAppConfigs()
ToastService.clearWallpaperError()
} catch (e) {
ToastService.wallpaperErrorStatus = "error"
ToastService.showError("Wallpaper Processing Failed")
}
return cur || fallback;
}
}
function isColorDark(c) {
return (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) < 0.5;
stderr: StdioCollector {
id: matugenErr
}
}
function generateAppConfigs() {
if (!matugenColors || !matugenColors.colors) {
return
}
Component.onCompleted: {
matugenCheck.running = true;
checkGtkThemingAvailability();
checkQtThemingAvailability();
if (typeof SessionData !== "undefined")
SessionData.isLightModeChanged.connect(root.onLightModeChanged);
generateNiriConfig()
generateGhosttyConfig()
if (gtkThemingEnabled && typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) {
generateSystemThemes()
} else if (qtThemingEnabled && typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) {
generateSystemThemes()
}
}
Process {
id: matugenCheck
function generateNiriConfig() {
var dark = matugenColors.colors.dark
if (!dark)
return
command: ["which", "matugen"]
onExited: code => {
matugenAvailable = (code === 0);
if (!matugenAvailable) {
ToastService.wallpaperErrorStatus = "matugen_missing";
ToastService.showWarning("matugen not found - dynamic theming disabled");
return;
}
if (extractionRequested) {
fileChecker.running = true;
}
}
}
var bg = dark.background || "#1a1c1e"
var primary = dark.primary || "#42a5f5"
var secondary = dark.secondary || "#8ab4f8"
var inverse = dark.inverse_primary || "#6200ea"
Process {
id: fileChecker
command: ["test", "-r", wallpaperPath]
onExited: code => {
if (code === 0) {
matugenProcess.running = true;
} else {
ToastService.wallpaperErrorStatus = "error";
ToastService.showError("Wallpaper processing failed");
}
}
}
Process {
id: matugenProcess
command: ["matugen", "-v", "image", wallpaperPath, "--json", "hex"]
stdout: StdioCollector {
id: matugenCollector
onStreamFinished: {
const out = matugenCollector.text;
if (!out.length) {
ToastService.wallpaperErrorStatus = "error";
ToastService.showError("Wallpaper Processing Failed");
return;
}
try {
root.matugenJson = out;
root.matugenColors = JSON.parse(out);
root.colorsUpdated();
generateAppConfigs();
ToastService.clearWallpaperError();
} catch (e) {
ToastService.wallpaperErrorStatus = "error";
ToastService.showError("Wallpaper Processing Failed");
}
}
}
stderr: StdioCollector {
id: matugenErr
}
}
function generateAppConfigs() {
if (!matugenColors || !matugenColors.colors) {
return;
}
generateNiriConfig();
generateGhosttyConfig();
if (gtkThemingEnabled && typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) {
generateSystemThemes();
} else if (qtThemingEnabled && typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) {
generateSystemThemes();
}
}
function generateNiriConfig() {
var dark = matugenColors.colors.dark;
if (!dark)
return;
var bg = dark.background || "#1a1c1e";
var primary = dark.primary || "#42a5f5";
var secondary = dark.secondary || "#8ab4f8";
var inverse = dark.inverse_primary || "#6200ea";
var content = `layout {
var content = `layout {
border {
active-color "${primary}"
inactive-color "${secondary}"
active-color "${primary}"
inactive-color "${secondary}"
}
focus-ring {
active-color "${inverse}"
active-color "${inverse}"
}
background-color "${bg}"
}`;
}`
Quickshell.execDetached(["bash", "-c", `echo '${content}' > niri-colors.generated.kdl`]);
Quickshell.execDetached(
["bash", "-c", `echo '${content}' > niri-colors.generated.kdl`])
}
function generateGhosttyConfig() {
var dark = matugenColors.colors.dark
var light = matugenColors.colors.light
if (!dark || !light)
return
var bg = dark.background || "#1a1c1e"
var fg = dark.on_background || "#e3e8ef"
var primary = dark.primary || "#42a5f5"
var secondary = dark.secondary || "#8ab4f8"
var tertiary = dark.tertiary || "#bb86fc"
var tertiary_ctr = dark.tertiary_container || "#3700b3"
var error = dark.error || "#cf6679"
var inverse = dark.inverse_primary || "#6200ea"
var bg_b = light.background || "#fef7ff"
var fg_b = light.on_background || "#1d1b20"
var primary_b = light.primary || "#1976d2"
var secondary_b = light.secondary || "#1565c0"
var tertiary_b = light.tertiary || "#7b1fa2"
var tertiary_ctr_b = light.tertiary_container || "#e1bee7"
var error_b = light.error || "#b00020"
var inverse_b = light.inverse_primary || "#bb86fc"
var content = `background = ${bg}
foreground = ${fg}
cursor-color = ${inverse}
selection-background = ${secondary}
selection-foreground = #ffffff
palette = 0=${bg}
palette = 1=${error}
palette = 2=${tertiary}
palette = 3=${secondary}
palette = 4=${primary}
palette = 5=${tertiary_ctr}
palette = 6=${inverse}
palette = 7=${fg}
palette = 8=${bg_b}
palette = 9=${error_b}
palette = 10=${tertiary_b}
palette = 11=${secondary_b}
palette = 12=${primary_b}
palette = 13=${tertiary_ctr_b}
palette = 14=${inverse_b}
palette = 15=${fg_b}`
var ghosttyConfigDir = configDir + "/ghostty"
var ghosttyConfigPath = ghosttyConfigDir + "/config-dankcolors"
Quickshell.execDetached(
["bash", "-c", `mkdir -p '${ghosttyConfigDir}' && echo '${content}' > '${ghosttyConfigPath}'`])
}
function checkGtkThemingAvailability() {
gtkAvailabilityChecker.running = true
}
function checkQtThemingAvailability() {
qtAvailabilityChecker.running = true
}
function generateSystemThemes() {
if (systemThemeGenerationInProgress) {
return
}
function generateGhosttyConfig() {
var dark = matugenColors.colors.dark;
var light = matugenColors.colors.light;
if (!dark || !light)
return;
var bg = dark.background || "#1a1c1e";
var fg = dark.on_background || "#e3e8ef";
var primary = dark.primary || "#42a5f5";
var secondary = dark.secondary || "#8ab4f8";
var tertiary = dark.tertiary || "#bb86fc";
var tertiary_ctr = dark.tertiary_container || "#3700b3";
var error = dark.error || "#cf6679";
var inverse = dark.inverse_primary || "#6200ea";
var bg_b = light.background || "#fef7ff";
var fg_b = light.on_background || "#1d1b20";
var primary_b = light.primary || "#1976d2";
var secondary_b = light.secondary || "#1565c0";
var tertiary_b = light.tertiary || "#7b1fa2";
var tertiary_ctr_b = light.tertiary_container || "#e1bee7";
var error_b = light.error || "#b00020";
var inverse_b = light.inverse_primary || "#bb86fc";
var content = `background = ${bg}
foreground = ${fg}
cursor-color = ${inverse}
selection-background = ${secondary}
selection-foreground = #ffffff
palette = 0=${bg}
palette = 1=${error}
palette = 2=${tertiary}
palette = 3=${secondary}
palette = 4=${primary}
palette = 5=${tertiary_ctr}
palette = 6=${inverse}
palette = 7=${fg}
palette = 8=${bg_b}
palette = 9=${error_b}
palette = 10=${tertiary_b}
palette = 11=${secondary_b}
palette = 12=${primary_b}
palette = 13=${tertiary_ctr_b}
palette = 14=${inverse_b}
palette = 15=${fg_b}`;
var ghosttyConfigDir = configDir + "/ghostty";
var ghosttyConfigPath = ghosttyConfigDir + "/config-dankcolors";
Quickshell.execDetached(["bash", "-c", `mkdir -p '${ghosttyConfigDir}' && echo '${content}' > '${ghosttyConfigPath}'`]);
if (!matugenAvailable) {
return
}
function checkGtkThemingAvailability() {
gtkAvailabilityChecker.running = true;
if (!wallpaperPath || wallpaperPath === "") {
return
}
function checkQtThemingAvailability() {
qtAvailabilityChecker.running = true;
const isLight = (typeof SessionData !== "undefined"
&& SessionData.isLightMode) ? "true" : "false"
const iconTheme = (typeof SettingsData !== "undefined"
&& SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
const gtkTheming = (typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) ? "true" : "false"
const qtTheming = (typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) ? "true" : "false"
systemThemeGenerationInProgress = true
systemThemeGenerator.command = [shellDir + "/generate-themes.sh", wallpaperPath, shellDir, configDir, "generate", isLight, iconTheme, gtkTheming, qtTheming]
systemThemeGenerator.running = true
}
function restoreSystemThemes() {
const shellDir = root.shellDir
if (!shellDir) {
return
}
function generateSystemThemes() {
if (systemThemeGenerationInProgress) {
return;
}
const isLight = (typeof SessionData !== "undefined"
&& SessionData.isLightMode) ? "true" : "false"
const iconTheme = (typeof SettingsData !== "undefined"
&& SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"
const gtkTheming = (typeof SettingsData !== "undefined"
&& SettingsData.gtkThemingEnabled) ? "true" : "false"
const qtTheming = (typeof SettingsData !== "undefined"
&& SettingsData.qtThemingEnabled) ? "true" : "false"
if (!matugenAvailable) {
return;
}
systemThemeRestoreProcess.command = [shellDir + "/generate-themes.sh", "", shellDir, configDir, "restore", isLight, iconTheme, gtkTheming, qtTheming]
systemThemeRestoreProcess.running = true
}
if (!wallpaperPath || wallpaperPath === "") {
return;
}
Process {
id: gtkAvailabilityChecker
command: ["bash", "-c", "command -v gsettings >/dev/null && [ -d "
+ configDir + "/gtk-3.0 -o -d " + configDir + "/gtk-4.0 ]"]
running: false
onExited: exitCode => {
gtkThemingEnabled = (exitCode === 0)
}
}
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false";
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default";
const gtkTheming = (typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) ? "true" : "false";
const qtTheming = (typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) ? "true" : "false";
Process {
id: qtAvailabilityChecker
command: ["bash", "-c", "command -v qt5ct >/dev/null || command -v qt6ct >/dev/null"]
running: false
onExited: exitCode => {
qtThemingEnabled = (exitCode === 0)
}
}
systemThemeGenerationInProgress = true;
systemThemeGenerator.command = [shellDir + "/generate-themes.sh", wallpaperPath, shellDir, configDir, "generate", isLight, iconTheme, gtkTheming, qtTheming];
systemThemeGenerator.running = true;
Process {
id: systemThemeGenerator
running: false
stdout: StdioCollector {
id: systemThemeStdout
}
function restoreSystemThemes() {
const shellDir = root.shellDir;
if (!shellDir) {
return;
}
const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode) ? "true" : "false";
const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default";
const gtkTheming = (typeof SettingsData !== "undefined" && SettingsData.gtkThemingEnabled) ? "true" : "false";
const qtTheming = (typeof SettingsData !== "undefined" && SettingsData.qtThemingEnabled) ? "true" : "false";
systemThemeRestoreProcess.command = [shellDir + "/generate-themes.sh", "", shellDir, configDir, "restore", isLight, iconTheme, gtkTheming, qtTheming];
systemThemeRestoreProcess.running = true;
stderr: StdioCollector {
id: systemThemeStderr
}
Process {
id: gtkAvailabilityChecker
command: ["bash", "-c", "command -v gsettings >/dev/null && [ -d " + configDir + "/gtk-3.0 -o -d " + configDir + "/gtk-4.0 ]"]
running: false
onExited: exitCode => {
gtkThemingEnabled = (exitCode === 0);
}
onExited: exitCode => {
systemThemeGenerationInProgress = false
if (exitCode !== 0) {
ToastService.showError(
"Failed to generate system themes: " + systemThemeStderr.text)
}
}
}
Process {
id: systemThemeRestoreProcess
running: false
stdout: StdioCollector {
id: restoreThemeStdout
}
Process {
id: qtAvailabilityChecker
command: ["bash", "-c", "command -v qt5ct >/dev/null || command -v qt6ct >/dev/null"]
running: false
onExited: exitCode => {
qtThemingEnabled = (exitCode === 0);
}
stderr: StdioCollector {
id: restoreThemeStderr
}
Process {
id: systemThemeGenerator
running: false
stdout: StdioCollector {
id: systemThemeStdout
}
stderr: StdioCollector {
id: systemThemeStderr
}
onExited: exitCode => {
systemThemeGenerationInProgress = false;
if (exitCode !== 0) {
ToastService.showError("Failed to generate system themes: " + systemThemeStderr.text);
}
}
}
Process {
id: systemThemeRestoreProcess
running: false
stdout: StdioCollector {
id: restoreThemeStdout
}
stderr: StdioCollector {
id: restoreThemeStderr
}
onExited: exitCode => {
if (exitCode === 0) {
ToastService.showInfo("System themes restored to default");
} else {
ToastService.showWarning("Failed to restore system themes: " + restoreThemeStderr.text);
}
}
onExited: exitCode => {
if (exitCode === 0) {
ToastService.showInfo("System themes restored to default")
} else {
ToastService.showWarning(
"Failed to restore system themes: " + restoreThemeStderr.text)
}
}
}
}

View File

@@ -4,39 +4,45 @@ import Quickshell
import QtCore
Singleton {
id: root
id: root
readonly property url home: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
readonly property url home: StandardPaths.standardLocations(
StandardPaths.HomeLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(
StandardPaths.PicturesLocation)[0]
readonly property url data: `${StandardPaths.standardLocations(StandardPaths.GenericDataLocation)[0]}/DankMaterialShell`
readonly property url state: `${StandardPaths.standardLocations(StandardPaths.GenericStateLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
readonly property url config: `${StandardPaths.standardLocations(StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url data: `${StandardPaths.standardLocations(
StandardPaths.GenericDataLocation)[0]}/DankMaterialShell`
readonly property url state: `${StandardPaths.standardLocations(
StandardPaths.GenericStateLocation)[0]}/DankMaterialShell`
readonly property url cache: `${StandardPaths.standardLocations(
StandardPaths.GenericCacheLocation)[0]}/DankMaterialShell`
readonly property url config: `${StandardPaths.standardLocations(
StandardPaths.GenericConfigLocation)[0]}/DankMaterialShell`
readonly property url imagecache: `${cache}/imagecache`
readonly property url imagecache: `${cache}/imagecache`
function stringify(path: url): string {
return path.toString().replace(/%20/g, " ");
}
function stringify(path: url): string {
return path.toString().replace(/%20/g, " ")
}
function expandTilde(path: string): string {
return strip(path.replace("~", stringify(root.home)));
}
function expandTilde(path: string): string {
return strip(path.replace("~", stringify(root.home)))
}
function shortenHome(path: string): string {
return path.replace(strip(root.home), "~");
}
function shortenHome(path: string): string {
return path.replace(strip(root.home), "~")
}
function strip(path: url): string {
return stringify(path).replace("file://", "");
}
function strip(path: url): string {
return stringify(path).replace("file://", "")
}
function mkdir(path: url): void {
Quickshell.execDetached(["mkdir", "-p", strip(path)]);
}
function mkdir(path: url): void {
Quickshell.execDetached(["mkdir", "-p", strip(path)])
}
function copy(from: url, to: url): void {
Quickshell.execDetached(["cp", strip(from), strip(to)]);
}
}
function copy(from: url, to: url): void {
Quickshell.execDetached(["cp", strip(from), strip(to)])
}
}

View File

@@ -2,8 +2,8 @@ import QtQuick
import Quickshell
QtObject {
required property Singleton service
required property Singleton service
Component.onCompleted: service.refCount++
Component.onDestruction: service.refCount--
Component.onCompleted: service.refCount++
Component.onDestruction: service.refCount--
}

View File

@@ -1,5 +1,6 @@
pragma Singleton
pragma ComponentBehavior: Bound
pragma ComponentBehavior
import QtCore
import QtQuick
@@ -8,169 +9,176 @@ import Quickshell.Io
Singleton {
id: root
id: root
property bool isLightMode: false
property string wallpaperPath: ""
property string wallpaperLastPath: ""
property string profileLastPath: ""
property bool doNotDisturb: false
property var pinnedApps: []
property bool isLightMode: false
property string wallpaperPath: ""
property string wallpaperLastPath: ""
property string profileLastPath: ""
property bool doNotDisturb: false
property var pinnedApps: []
Component.onCompleted: {
loadSettings();
Component.onCompleted: {
loadSettings()
}
function loadSettings() {
parseSettings(settingsFile.text())
}
function parseSettings(content) {
try {
if (content && content.trim()) {
var settings = JSON.parse(content)
isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false
wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : ""
wallpaperLastPath = settings.wallpaperLastPath
!== undefined ? settings.wallpaperLastPath : ""
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : ""
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : []
}
} catch (e) {
}
}
function saveSettings() {
settingsFile.setText(JSON.stringify({
"isLightMode": isLightMode,
"wallpaperPath": wallpaperPath,
"wallpaperLastPath": wallpaperLastPath,
"profileLastPath": profileLastPath,
"doNotDisturb": doNotDisturb,
"pinnedApps": pinnedApps
}, null, 2))
}
function setLightMode(lightMode) {
isLightMode = lightMode
saveSettings()
}
function setDoNotDisturb(enabled) {
doNotDisturb = enabled
saveSettings()
}
function setWallpaperPath(path) {
wallpaperPath = path
saveSettings()
}
function setWallpaper(imagePath) {
wallpaperPath = imagePath
saveSettings()
if (typeof Colors !== "undefined" && typeof SettingsData !== "undefined"
&& SettingsData.wallpaperDynamicTheming) {
Colors.extractColors()
}
}
function setWallpaperLastPath(path) {
wallpaperLastPath = path
saveSettings()
}
function setProfileLastPath(path) {
profileLastPath = path
saveSettings()
}
function setPinnedApps(apps) {
pinnedApps = apps
saveSettings()
}
function addPinnedApp(appId) {
if (!appId)
return
var currentPinned = [...pinnedApps]
if (currentPinned.indexOf(appId) === -1) {
currentPinned.push(appId)
setPinnedApps(currentPinned)
}
}
function removePinnedApp(appId) {
if (!appId)
return
var currentPinned = pinnedApps.filter(id => id !== appId)
setPinnedApps(currentPinned)
}
function isPinnedApp(appId) {
return appId && pinnedApps.indexOf(appId) !== -1
}
FileView {
id: settingsFile
path: StandardPaths.writableLocation(
StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: true
blockWrites: true
watchChanges: true
onLoaded: {
parseSettings(settingsFile.text())
}
onLoadFailed: error => {}
}
IpcHandler {
target: "wallpaper"
function get(): string {
return root.wallpaperPath || ""
}
function loadSettings() {
parseSettings(settingsFile.text());
function set(path: string): string {
if (!path) {
return "ERROR: No path provided"
}
var absolutePath = path.startsWith(
"/") ? path : StandardPaths.writableLocation(
StandardPaths.HomeLocation) + "/" + path
try {
root.setWallpaper(absolutePath)
return "SUCCESS: Wallpaper set to " + absolutePath
} catch (e) {
return "ERROR: Failed to set wallpaper: " + e.toString()
}
}
function parseSettings(content) {
try {
if (content && content.trim()) {
var settings = JSON.parse(content);
isLightMode = settings.isLightMode !== undefined ? settings.isLightMode : false;
wallpaperPath = settings.wallpaperPath !== undefined ? settings.wallpaperPath : "";
wallpaperLastPath = settings.wallpaperLastPath !== undefined ? settings.wallpaperLastPath : "";
profileLastPath = settings.profileLastPath !== undefined ? settings.profileLastPath : "";
doNotDisturb = settings.doNotDisturb !== undefined ? settings.doNotDisturb : false;
pinnedApps = settings.pinnedApps !== undefined ? settings.pinnedApps : [];
}
} catch (e) {
}
function clear(): string {
root.setWallpaper("")
return "SUCCESS: Wallpaper cleared"
}
}
IpcHandler {
target: "theme"
function toggle(): string {
root.setLightMode(!root.isLightMode)
return root.isLightMode ? "light" : "dark"
}
function saveSettings() {
settingsFile.setText(JSON.stringify({
"isLightMode": isLightMode,
"wallpaperPath": wallpaperPath,
"wallpaperLastPath": wallpaperLastPath,
"profileLastPath": profileLastPath,
"doNotDisturb": doNotDisturb,
"pinnedApps": pinnedApps
}, null, 2));
function light(): string {
root.setLightMode(true)
return "light"
}
function setLightMode(lightMode) {
isLightMode = lightMode;
saveSettings();
function dark(): string {
root.setLightMode(false)
return "dark"
}
function setDoNotDisturb(enabled) {
doNotDisturb = enabled;
saveSettings();
function getMode(): string {
return root.isLightMode ? "light" : "dark"
}
function setWallpaperPath(path) {
wallpaperPath = path;
saveSettings();
}
function setWallpaper(imagePath) {
wallpaperPath = imagePath;
saveSettings();
if (typeof Colors !== "undefined" && typeof SettingsData !== "undefined" && SettingsData.wallpaperDynamicTheming) {
Colors.extractColors();
}
}
function setWallpaperLastPath(path) {
wallpaperLastPath = path;
saveSettings();
}
function setProfileLastPath(path) {
profileLastPath = path;
saveSettings();
}
function setPinnedApps(apps) {
pinnedApps = apps;
saveSettings();
}
function addPinnedApp(appId) {
if (!appId) return;
var currentPinned = [...pinnedApps];
if (currentPinned.indexOf(appId) === -1) {
currentPinned.push(appId);
setPinnedApps(currentPinned);
}
}
function removePinnedApp(appId) {
if (!appId) return;
var currentPinned = pinnedApps.filter(id => id !== appId);
setPinnedApps(currentPinned);
}
function isPinnedApp(appId) {
return appId && pinnedApps.indexOf(appId) !== -1;
}
FileView {
id: settingsFile
path: StandardPaths.writableLocation(StandardPaths.GenericStateLocation) + "/DankMaterialShell/session.json"
blockLoading: true
blockWrites: true
watchChanges: true
onLoaded: {
parseSettings(settingsFile.text());
}
onLoadFailed: (error) => {
}
}
IpcHandler {
target: "wallpaper"
function get(): string {
return root.wallpaperPath || ""
}
function set(path: string): string {
if (!path) {
return "ERROR: No path provided"
}
var absolutePath = path.startsWith("/") ? path : StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/" + path
try {
root.setWallpaper(absolutePath)
return "SUCCESS: Wallpaper set to " + absolutePath
} catch (e) {
return "ERROR: Failed to set wallpaper: " + e.toString()
}
}
function clear(): string {
root.setWallpaper("")
return "SUCCESS: Wallpaper cleared"
}
}
IpcHandler {
target: "theme"
function toggle(): string {
root.setLightMode(!root.isLightMode)
return root.isLightMode ? "light" : "dark"
}
function light(): string {
root.setLightMode(true)
return "light"
}
function dark(): string {
root.setLightMode(false)
return "dark"
}
function getMode(): string {
return root.isLightMode ? "light" : "dark"
}
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff