diff --git a/Commons/Settings.qml b/Commons/Settings.qml index afac08c..243ddee 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -122,6 +122,7 @@ Singleton { property bool alwaysShowBatteryPercentage: false property bool showNetworkStats: false property real backgroundOpacity: 1.0 + property bool useDistroLogo: false property string showWorkspaceLabel: "none" property list monitors: [] @@ -142,8 +143,6 @@ Singleton { property real radiusRatio: 1.0 // Animation speed multiplier (0.1x - 2.0x) property real animationSpeed: 1.0 - // Replace sidepanel toggle with distro logo (shown in bar and/or side panel) - property bool useDistroLogoForSidepanel: false } // location diff --git a/Modules/Bar/Widgets/SidePanelToggle.qml b/Modules/Bar/Widgets/SidePanelToggle.qml index f37ff12..2febfa4 100644 --- a/Modules/Bar/Widgets/SidePanelToggle.qml +++ b/Modules/Bar/Widgets/SidePanelToggle.qml @@ -1,4 +1,6 @@ import Quickshell +import Quickshell.Widgets +import QtQuick.Effects import qs.Commons import qs.Widgets import qs.Services @@ -9,7 +11,7 @@ NIconButton { property ShellScreen screen property real scaling: 1.0 - icon: "widgets" + icon: Settings.data.bar.useDistroLogo ? "" : "widgets" tooltipText: "Open side panel" sizeRatio: 0.8 @@ -20,4 +22,25 @@ NIconButton { anchors.verticalCenter: parent.verticalCenter onClicked: PanelService.getPanel("sidePanel")?.toggle(screen) + + // When enabled, draw the distro logo instead of the icon glyph + IconImage { + id: logo + anchors.centerIn: parent + width: root.width * 0.6 + height: width + source: Settings.data.bar.useDistroLogo ? DistroLogoService.osLogo : "" + visible: false //Settings.data.bar.useDistroLogo && source !== "" + smooth: true + } + + MultiEffect { + anchors.fill: logo + source: logo + //visible: logo.visible + colorization: 1 + brightness: 1 + saturation: 1 + colorizationColor: root.hovering ? Color.mSurfaceVariant : Color.mOnSurface + } } diff --git a/Modules/SettingsPanel/Tabs/BarTab.qml b/Modules/SettingsPanel/Tabs/BarTab.qml index b1d064d..de13288 100644 --- a/Modules/SettingsPanel/Tabs/BarTab.qml +++ b/Modules/SettingsPanel/Tabs/BarTab.qml @@ -97,6 +97,15 @@ ColumnLayout { } } + NToggle { + label: "Replace SidePanel toggle with distro logo" + description: "Show distro logo instead of the SidePanel toggle button in the bar." + checked: Settings.data.bar.useDistroLogo + onToggled: checked => { + Settings.data.bar.useDistroLogo = checked + } + } + NComboBox { label: "Show Workspaces Labels" description: "Display the workspace name or index in the workspace indicator" diff --git a/Services/DistroLogoService.qml b/Services/DistroLogoService.qml new file mode 100644 index 0000000..3a04d6e --- /dev/null +++ b/Services/DistroLogoService.qml @@ -0,0 +1,94 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Commons + +Singleton { + id: root + + // Public properties + property string osPretty: "" + property string osLogo: "" + + // Internal helpers + function buildCandidates(name) { + const n = (name || "").trim() + if (!n) + return [] + + const sizes = ["512x512", "256x256", "128x128", "64x64", "48x48", "32x32", "24x24", "22x22", "16x16"] + const exts = ["svg", "png"] + const candidates = [] + + // pixmaps + for (const ext of exts) { + candidates.push(`/usr/share/pixmaps/${n}.${ext}`) + } + + // hicolor scalable and raster sizes + candidates.push(`/usr/share/icons/hicolor/scalable/apps/${n}.svg`) + for (const s of sizes) { + for (const ext of exts) { + candidates.push(`/usr/share/icons/hicolor/${s}/apps/${n}.${ext}`) + } + } + + // Generic icon themes under /usr/share/icons (common cases) + for (const ext of exts) { + candidates.push(`/usr/share/icons/${n}.${ext}`) + candidates.push(`/usr/share/icons/${n}/${n}.${ext}`) + candidates.push(`/usr/share/icons/${n}/apps/${n}.${ext}`) + } + + return candidates + } + + function resolveLogo(name) { + const all = buildCandidates(name) + if (all.length === 0) + return + + const script = all.map(p => `if [ -f "${p}" ]; then echo "${p}"; exit 0; fi`).join("; ") + "; exit 1" + probe.command = ["sh", "-c", script] + probe.running = true + } + + // Read /etc/os-release and trigger resolution + FileView { + id: osInfo + path: "/etc/os-release" + onLoaded: { + try { + const lines = text().split("\n") + const val = k => { + const l = lines.find(x => x.startsWith(k + "=")) + return l ? l.split("=")[1].replace(/"/g, "") : "" + } + root.osPretty = val("PRETTY_NAME") || val("NAME") + const logoName = val("LOGO") + if (logoName) + resolveLogo(logoName) + } catch (e) { + Logger.warn("DistroLogoService", "failed to read os-release", e) + } + } + } + + Process { + id: probe + onExited: code => { + const p = String(stdout.text || "").trim() + if (code === 0 && p) { + root.osLogo = `file://${p}` + Logger.log("DistroLogoService", "found", root.osLogo) + } else { + root.osLogo = "" + Logger.warn("DistroLogoService", "none found") + } + } + stdout: StdioCollector {} + stderr: StdioCollector {} + } +} diff --git a/Widgets/NWidgetLoader.qml b/Widgets/NWidgetLoader.qml index 6e8c64b..1f4046c 100644 --- a/Widgets/NWidgetLoader.qml +++ b/Widgets/NWidgetLoader.qml @@ -13,7 +13,7 @@ Item { Connections { target: ScalingService function onScaleChanged(screenName, scale) { - if ((loader.item.screen !== null) && (screenName === loader.item.screen.name)) { + if (loader.item && loader.item.screen && screenName === loader.item.screen.name) { loader.item['scaling'] = scale } }