diff --git a/Modules/Panels/Settings/Tabs/ColorScheme/SchemeDownloader.qml b/Modules/Panels/Settings/Tabs/ColorScheme/SchemeDownloader.qml index 0bd650a1..1c7b4016 100644 --- a/Modules/Panels/Settings/Tabs/ColorScheme/SchemeDownloader.qml +++ b/Modules/Panels/Settings/Tabs/ColorScheme/SchemeDownloader.qml @@ -521,7 +521,7 @@ Popup { return; } - var targetDir = ColorSchemeService.schemesDirectory + "/" + schemeName; + var targetDir = ColorSchemeService.downloadedSchemesDirectory + "/" + schemeName; var downloadScript = "mkdir -p '" + targetDir + "'\n"; // Build download script for all files @@ -612,6 +612,17 @@ Popup { return false; } + function isSchemeDownloaded(schemeName) { + // Check if scheme is in the downloaded directory (not preinstalled) + for (var i = 0; i < ColorSchemeService.schemes.length; i++) { + var path = ColorSchemeService.schemes[i]; + if ((path.indexOf("/" + schemeName + "/") !== -1 || path.indexOf("/" + schemeName + ".json") !== -1) && path.indexOf(ColorSchemeService.downloadedSchemesDirectory) !== -1) { + return true; + } + } + return false; + } + function deleteScheme(schemeName) { if (downloading) { return; @@ -624,7 +635,8 @@ Popup { var deletedSchemeDisplayName = ColorSchemeService.getBasename(schemeName); var needsReset = (currentScheme === deletedSchemeDisplayName); - var targetDir = ColorSchemeService.schemesDirectory + "/" + schemeName; + // Only allow deleting downloaded schemes, not preinstalled ones + var targetDir = ColorSchemeService.downloadedSchemesDirectory + "/" + schemeName; var deleteScript = "rm -rf '" + targetDir + "'"; var deleteProcess = Qt.createQmlObject(` @@ -897,12 +909,14 @@ Popup { NIconButton { property bool isDownloading: downloading && downloadingScheme === schemeRow.schemeName property bool isInstalled: root.isSchemeInstalled(schemeRow.schemeName) + property bool isDownloaded: root.isSchemeDownloaded(schemeRow.schemeName) - icon: isDownloading ? "" : (isInstalled ? "trash" : "download") - tooltipText: isDownloading ? I18n.tr("settings.color-scheme.download.downloading") : (isInstalled ? I18n.tr("settings.color-scheme.download.delete") : I18n.tr("settings.color-scheme.download.download")) + icon: isDownloading ? "" : (isDownloaded ? "trash" : "download") + tooltipText: isDownloading ? I18n.tr("settings.color-scheme.download.downloading") : (isDownloaded ? I18n.tr("settings.color-scheme.download.delete") : I18n.tr("settings.color-scheme.download.download")) enabled: !downloading Layout.alignment: Qt.AlignVCenter - onClicked: isInstalled ? root.deleteScheme(schemeRow.schemeName) : root.downloadScheme(modelData) + visible: !isInstalled || isDownloaded // Show button only if not installed (can download) or if downloaded (can delete) + onClicked: isDownloaded ? root.deleteScheme(schemeRow.schemeName) : root.downloadScheme(modelData) NBusyIndicator { anchors.centerIn: parent diff --git a/Services/Theming/ColorSchemeService.qml b/Services/Theming/ColorSchemeService.qml index ddc1be9e..4e7d7879 100644 --- a/Services/Theming/ColorSchemeService.qml +++ b/Services/Theming/ColorSchemeService.qml @@ -13,6 +13,7 @@ Singleton { property var schemes: [] property bool scanning: false property string schemesDirectory: Quickshell.shellDir + "/Assets/ColorScheme" + property string downloadedSchemesDirectory: Settings.configDir + "colorschemes" property string colorsJsonFilePath: Settings.configDir + "colors.json" Connections { @@ -43,8 +44,11 @@ Singleton { Logger.d("ColorScheme", "Load colorScheme"); scanning = true; schemes = []; - // Use find command to locate all scheme.json files - findProcess.command = ["find", schemesDirectory, "-name", "*.json", "-type", "f"]; + // Use find command to locate all scheme.json files in both directories + // First ensure the downloaded schemes directory exists + Quickshell.execDetached(["mkdir", "-p", downloadedSchemesDirectory]); + // Find in both preinstalled and downloaded directories + findProcess.command = ["find", schemesDirectory, downloadedSchemesDirectory, "-name", "*.json", "-type", "f"]; findProcess.running = true; } @@ -81,7 +85,17 @@ Singleton { } else if (schemeName === "Tokyo Night") { schemeName = "Tokyo-Night"; } - return schemesDirectory + "/" + schemeName + "/" + schemeName + ".json"; + // Check preinstalled directory first, then downloaded directory + var preinstalledPath = schemesDirectory + "/" + schemeName + "/" + schemeName + ".json"; + var downloadedPath = downloadedSchemesDirectory + "/" + schemeName + "/" + schemeName + ".json"; + // Try to find the scheme in the loaded schemes list to determine which directory it's in + for (var i = 0; i < schemes.length; i++) { + if (schemes[i].indexOf("/" + schemeName + "/") !== -1 || schemes[i].indexOf("/" + schemeName + ".json") !== -1) { + return schemes[i]; + } + } + // Fallback: prefer preinstalled, then downloaded + return preinstalledPath; } function applyScheme(nameOrPath) { diff --git a/Services/Theming/TemplateProcessor.qml b/Services/Theming/TemplateProcessor.qml index f74f536d..e7f93cfd 100644 --- a/Services/Theming/TemplateProcessor.qml +++ b/Services/Theming/TemplateProcessor.qml @@ -5,6 +5,7 @@ import Quickshell import Quickshell.Io import qs.Commons import qs.Services.System +import qs.Services.Theming import qs.Services.UI Singleton { @@ -329,7 +330,26 @@ Singleton { extension = ".toml"; } - return `${Quickshell.shellDir}/Assets/ColorScheme/${colorScheme}/terminal/${terminal}/${colorScheme}-${mode}${extension}`; + const fileName = `${colorScheme}-${mode}${extension}`; + const relativePath = `terminal/${terminal}/${fileName}`; + + // Try to find the scheme in the loaded schemes list to determine which directory it's in + for (let i = 0; i < ColorSchemeService.schemes.length; i++) { + const schemeJsonPath = ColorSchemeService.schemes[i]; + // Check if this is the scheme we're looking for + if (schemeJsonPath.indexOf(`/${colorScheme}/`) !== -1 || schemeJsonPath.indexOf(`/${colorScheme}.json`) !== -1) { + // Extract the scheme directory from the JSON path + // JSON path is like: /path/to/scheme/SchemeName/SchemeName.json + // We need: /path/to/scheme/SchemeName/terminal/... + const schemeDir = schemeJsonPath.substring(0, schemeJsonPath.lastIndexOf('/')); + return `${schemeDir}/${relativePath}`; + } + } + + // Fallback: try downloaded first, then preinstalled + const downloadedPath = `${ColorSchemeService.downloadedSchemesDirectory}/${colorScheme}/${relativePath}`; + const preinstalledPath = `${ColorSchemeService.schemesDirectory}/${colorScheme}/${relativePath}`; + return preinstalledPath; } // ================================================================================