From bff195309ac4fbb1ca6ece6ddcbe47a88675f466 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 8 Oct 2025 23:05:52 -0400 Subject: [PATCH 01/16] QuickSettings: editable widgets/button section in the ControlCenter --- Commons/Settings.qml | 10 + Modules/Bar/Extras/BarWidgetLoader.qml | 2 +- Modules/ControlCenter/Cards/TopCard.qml | 220 ++---------------- Modules/ControlCenter/Cards/WeatherCard.qml | 130 ----------- Modules/ControlCenter/ControlCenterPanel.qml | 18 +- .../Extras/ControlCenterWidgetLoader.qml | 74 ++++++ Modules/ControlCenter/Widgets/Bluetooth.qml | 17 ++ Modules/ControlCenter/Widgets/KeepAwake.qml | 17 ++ Modules/ControlCenter/Widgets/NightLight.qml | 33 +++ .../ControlCenter/Widgets/PowerProfile.qml | 23 ++ .../ControlCenter/Widgets/ScreenRecorder.qml | 24 ++ .../Widgets/WallpaperSelector.qml | 20 ++ Modules/ControlCenter/Widgets/WiFi.qml | 42 ++++ .../SectionEditor.qml} | 21 +- Modules/Settings/SettingsPanel.qml | 10 + Modules/Settings/Tabs/BarTab.qml | 14 +- Modules/Settings/Tabs/ControlCenterTab.qml | 140 +++++++++++ Services/ControlCenterWidgetRegistry.qml | 71 ++++++ Widgets/NButton.qml | 13 +- 19 files changed, 542 insertions(+), 357 deletions(-) delete mode 100644 Modules/ControlCenter/Cards/WeatherCard.qml create mode 100644 Modules/ControlCenter/Extras/ControlCenterWidgetLoader.qml create mode 100644 Modules/ControlCenter/Widgets/Bluetooth.qml create mode 100644 Modules/ControlCenter/Widgets/KeepAwake.qml create mode 100644 Modules/ControlCenter/Widgets/NightLight.qml create mode 100644 Modules/ControlCenter/Widgets/PowerProfile.qml create mode 100644 Modules/ControlCenter/Widgets/ScreenRecorder.qml create mode 100644 Modules/ControlCenter/Widgets/WallpaperSelector.qml create mode 100644 Modules/ControlCenter/Widgets/WiFi.qml rename Modules/Settings/{Bar/BarSectionEditor.qml => Extras/SectionEditor.qml} (96%) create mode 100644 Modules/Settings/Tabs/ControlCenterTab.qml create mode 100644 Services/ControlCenterWidgetRegistry.qml diff --git a/Commons/Settings.qml b/Commons/Settings.qml index c0939caf..61b4d184 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -246,6 +246,16 @@ Singleton { property JsonObject controlCenter: JsonObject { // Position: close_to_bar_button, center, top_left, top_right, bottom_left, bottom_right, bottom_center, top_center property string position: "close_to_bar_button" + property JsonObject widgets + widgets: JsonObject { + property list quickSettings: [{ + "id": "Bluetooth" + }, { + "id": "WiFi" + }, { + "id": "PowerProfile" + }] + } } // dock diff --git a/Modules/Bar/Extras/BarWidgetLoader.qml b/Modules/Bar/Extras/BarWidgetLoader.qml index 8697db5b..69b08623 100644 --- a/Modules/Bar/Extras/BarWidgetLoader.qml +++ b/Modules/Bar/Extras/BarWidgetLoader.qml @@ -77,7 +77,7 @@ Item { // Error handling onWidgetIdChanged: { if (widgetId && !BarWidgetRegistry.hasWidget(widgetId)) { - Logger.warn("BarWidgetLoader", "Widget not found in bar registry:", widgetId) + Logger.warn("BarWidgetLoader", "Widget not found in registry:", widgetId) } } } diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index d68d84be..1bb36148 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -4,9 +4,9 @@ import QtQuick.Layouts import Quickshell import Quickshell.Io import Quickshell.Widgets -import Quickshell.Services.UPower import qs.Modules.Settings import qs.Modules.ControlCenter +import qs.Modules.ControlCenter.Extras import qs.Commons import qs.Services import qs.Widgets @@ -17,7 +17,6 @@ NBox { property string uptimeText: "--" property real spacing: Style.marginS * scaling - readonly property bool hasPP: PowerProfileService.available ColumnLayout { anchors.fill: parent @@ -97,205 +96,34 @@ NBox { } } - RowLayout { - id: utilitiesRow - Layout.alignment: Qt.AlignVCenter + NDivider { + Layout.fillWidth: true Layout.topMargin: Style.marginM * scaling Layout.bottomMargin: Style.marginM * scaling + } + + GridLayout { + id: grid Layout.fillWidth: true + columns: 2 + columnSpacing: Style.marginL * scaling + rowSpacing: Style.marginM * scaling - // Left group - Media & Display - Rectangle { - color: Color.mSurface - radius: Style.radiusM * scaling - Layout.preferredHeight: Style.baseWidgetSize * 1.2 * scaling - Layout.preferredWidth: childrenRect.width + (Style.marginS * scaling * 2) - - RowLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - // Screen Recorder - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - icon: "camera-video" - visible: ProgramCheckerService.gpuScreenRecorderAvailable - tooltipText: ScreenRecorderService.isRecording ? I18n.tr("tooltips.stop-screen-recording") : I18n.tr("tooltips.start-screen-recording") - colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : Color.mSurfaceVariant - colorFg: ScreenRecorderService.isRecording ? Color.mOnPrimary : Color.mPrimary - onClicked: { - ScreenRecorderService.toggleRecording() - if (!ScreenRecorderService.isRecording) { - var panel = PanelService.getPanel("controlCenterPanel") - panel?.close() - } - } - } - - // Wallpaper - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - visible: Settings.data.wallpaper.enabled - icon: "wallpaper-selector" - tooltipText: I18n.tr("tooltips.wallpaper-selector") - onClicked: PanelService.getPanel("wallpaperPanel")?.toggle(this) - onRightClicked: WallpaperService.setRandomWallpaper() - } - - // Night Light - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - visible: ProgramCheckerService.wlsunsetAvailable - colorBg: Settings.data.nightLight.forced ? Color.mPrimary : Color.transparent - colorFg: Settings.data.nightLight.forced ? Color.mOnPrimary : Color.mPrimary - icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" - tooltipText: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? I18n.tr("tooltips.night-light-forced") : I18n.tr("tooltips.night-light-enabled")) : I18n.tr("tooltips.night-light-disabled") - onClicked: { - if (!Settings.data.nightLight.enabled) { - Settings.data.nightLight.enabled = true - Settings.data.nightLight.forced = false - } else if (Settings.data.nightLight.enabled && !Settings.data.nightLight.forced) { - Settings.data.nightLight.forced = true - } else { - Settings.data.nightLight.enabled = false - Settings.data.nightLight.forced = false - } - } - - onRightClicked: { - var settingsPanel = PanelService.getPanel("settingsPanel") - settingsPanel.requestedTab = SettingsPanel.Tab.Display - settingsPanel.open() - } - } - } - } - - // Spacer - Item { - Layout.fillWidth: true - } - - // Center group - Network & Caffeine - Rectangle { - color: Color.mSurface - radius: Style.radiusM * scaling - Layout.preferredHeight: Style.baseWidgetSize * 1.2 * scaling - Layout.preferredWidth: childrenRect.width + (Style.marginS * scaling * 2) - - RowLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - // Wifi - NIconButton { - id: wifiButton - baseSize: Style.baseWidgetSize * 0.9 - tooltipText: I18n.tr("tooltips.manage-wifi") - icon: { - try { - if (NetworkService.ethernetConnected) { - return "ethernet" - } - let connected = false - let signalStrength = 0 - for (const net in NetworkService.networks) { - if (NetworkService.networks[net].connected) { - connected = true - signalStrength = NetworkService.networks[net].signal - break - } - } - return connected ? NetworkService.signalIcon(signalStrength) : "wifi-off" - } catch (error) { - Logger.error("Wi-Fi", "Error getting icon:", error) - return "signal_wifi_bad" - } - } - onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) - onRightClicked: PanelService.getPanel("wifiPanel")?.toggle(this) - } - - // Bluetooth - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - tooltipText: I18n.tr("tooltips.bluetooth-devices") - icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" - onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) - onRightClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) - } - - // Caffeine (Keep Awake) - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" - tooltipText: IdleInhibitorService.isInhibited ? I18n.tr("tooltips.disable-keep-awake") : I18n.tr("tooltips.enable-keep-awake") - colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : Color.mSurfaceVariant - colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mPrimary - onClicked: { - IdleInhibitorService.manualToggle() - } - } - } - } - - // Spacer - Item { - Layout.fillWidth: true - } - - // Right group - Power Profiles - Rectangle { - color: Color.mSurface - radius: Style.radiusM * scaling - Layout.preferredHeight: Style.baseWidgetSize * 1.2 * scaling - Layout.preferredWidth: childrenRect.width + (Style.marginS * scaling * 2) - - RowLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - // Performance - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - icon: PowerProfileService.getIcon(PowerProfile.Performance) - tooltipText: I18n.tr("tooltips.set-power-profile", { - "profile": PowerProfileService.getName(PowerProfile.Performance) - }) - enabled: hasPP - opacity: enabled ? Style.opacityFull : Style.opacityMedium - colorBg: (enabled && PowerProfileService.profile === PowerProfile.Performance) ? Color.mPrimary : Color.mSurfaceVariant - colorFg: (enabled && PowerProfileService.profile === PowerProfile.Performance) ? Color.mOnPrimary : Color.mPrimary - onClicked: PowerProfileService.setProfile(PowerProfile.Performance) - } - - // Balanced - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - icon: PowerProfileService.getIcon(PowerProfile.Balanced) - tooltipText: I18n.tr("tooltips.set-power-profile", { - "profile": PowerProfileService.getName(PowerProfile.Balanced) - }) - enabled: hasPP - opacity: enabled ? Style.opacityFull : Style.opacityMedium - colorBg: (enabled && PowerProfileService.profile === PowerProfile.Balanced) ? Color.mPrimary : Color.mSurfaceVariant - colorFg: (enabled && PowerProfileService.profile === PowerProfile.Balanced) ? Color.mOnPrimary : Color.mPrimary - onClicked: PowerProfileService.setProfile(PowerProfile.Balanced) - } - - // Eco - NIconButton { - baseSize: Style.baseWidgetSize * 0.9 - icon: PowerProfileService.getIcon(PowerProfile.PowerSaver) - tooltipText: I18n.tr("tooltips.set-power-profile", { - "profile": PowerProfileService.getName(PowerProfile.PowerSaver) - }) - enabled: hasPP - opacity: enabled ? Style.opacityFull : Style.opacityMedium - colorBg: (enabled && PowerProfileService.profile === PowerProfile.PowerSaver) ? Color.mPrimary : Color.mSurfaceVariant - colorFg: (enabled && PowerProfileService.profile === PowerProfile.PowerSaver) ? Color.mOnPrimary : Color.mPrimary - onClicked: PowerProfileService.setProfile(PowerProfile.PowerSaver) + Repeater { + model: Settings.data.controlCenter.widgets.quickSettings + delegate: ControlCenterWidgetLoader { + Layout.fillWidth: true + Layout.preferredWidth: (grid.width - grid.columnSpacing) / 2 + widgetId: (modelData.id !== undefined ? modelData.id : "") + widgetProps: { + "screen": root.modelData || null, + "scaling": ScalingService.getScreenScale(screen), + "widgetId": modelData.id, + "section": "quickSettings", + "sectionWidgetIndex": index, + "sectionWidgetsCount": Settings.data.controlCenter.widgets.quickSettings.length } + Layout.alignment: Qt.AlignVCenter } } } diff --git a/Modules/ControlCenter/Cards/WeatherCard.qml b/Modules/ControlCenter/Cards/WeatherCard.qml deleted file mode 100644 index d9e8510a..00000000 --- a/Modules/ControlCenter/Cards/WeatherCard.qml +++ /dev/null @@ -1,130 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import Quickshell -import qs.Commons -import qs.Services -import qs.Widgets - -// Weather overview card (placeholder data) -NBox { - id: root - - readonly property bool weatherReady: (LocationService.data.weather !== null) - - ColumnLayout { - id: content - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Style.marginM * scaling - spacing: Style.marginM * scaling - clip: true - - RowLayout { - spacing: Style.marginS * scaling - NIcon { - Layout.alignment: Qt.AlignVCenter - icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode) : "" - pointSize: Style.fontSizeXXXL * 1.75 * scaling - color: Color.mPrimary - } - - ColumnLayout { - spacing: Style.marginXXS * scaling - NText { - text: { - // Ensure the name is not too long if one had to specify the country - const chunks = Settings.data.location.name.split(",") - return chunks[0] - } - pointSize: Style.fontSizeL * scaling - font.weight: Style.fontWeightBold - } - - RowLayout { - NText { - visible: weatherReady - text: { - if (!weatherReady) { - return "" - } - var temp = LocationService.data.weather.current_weather.temperature - var suffix = "C" - if (Settings.data.location.useFahrenheit) { - temp = LocationService.celsiusToFahrenheit(temp) - var suffix = "F" - } - temp = Math.round(temp) - return `${temp}°${suffix}` - } - pointSize: Style.fontSizeXL * scaling - font.weight: Style.fontWeightBold - } - - NText { - text: weatherReady ? `(${LocationService.data.weather.timezone_abbreviation})` : "" - pointSize: Style.fontSizeXS * scaling - color: Color.mOnSurfaceVariant - visible: LocationService.data.weather - } - } - } - } - - NDivider { - visible: weatherReady - Layout.fillWidth: true - } - - RowLayout { - visible: weatherReady - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - spacing: Style.marginL * scaling - Repeater { - model: weatherReady ? LocationService.data.weather.daily.time : [] - delegate: ColumnLayout { - Layout.alignment: Qt.AlignHCenter - spacing: Style.marginS * scaling - NText { - text: { - var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")) - return Qt.locale().toString(weatherDate, "ddd") - } - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - NIcon { - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - icon: LocationService.weatherSymbolFromCode(LocationService.data.weather.daily.weathercode[index]) - pointSize: Style.fontSizeXXL * 1.6 * scaling - color: Color.mPrimary - } - NText { - Layout.alignment: Qt.AlignHCenter - text: { - var max = LocationService.data.weather.daily.temperature_2m_max[index] - var min = LocationService.data.weather.daily.temperature_2m_min[index] - if (Settings.data.location.useFahrenheit) { - max = LocationService.celsiusToFahrenheit(max) - min = LocationService.celsiusToFahrenheit(min) - } - max = Math.round(max) - min = Math.round(min) - return `${max}°/${min}°` - } - pointSize: Style.fontSizeXS * scaling - color: Color.mOnSurfaceVariant - } - } - } - } - - RowLayout { - visible: !weatherReady - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - NBusyIndicator {} - } - } -} diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index c2290cc0..e47c593c 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -10,8 +10,8 @@ import qs.Widgets NPanel { id: root - preferredWidth: 480 - preferredHeight: 580 + preferredWidth: 440 + preferredHeight: 540 panelKeyboardFocus: true // Positioning @@ -38,13 +38,7 @@ NPanel { // Top Card: profile + utilities TopCard { Layout.fillWidth: true - Layout.preferredHeight: Math.max(124 * scaling) - } - - // Weather - WeatherCard { - Layout.fillWidth: true - Layout.preferredHeight: Math.max(196 * scaling) + Layout.preferredHeight: Math.max(280 * scaling) } // Media + stats column @@ -55,13 +49,13 @@ NPanel { // Media card MediaCard { - Layout.preferredWidth: Math.max(270 * scaling) - Layout.fillHeight: true + Layout.preferredWidth: Math.max(250 * scaling) + Layout.preferredHeight: Math.max(196 * scaling) } // System monitors combined in one card SystemMonitorCard { - Layout.preferredWidth: Math.max(160 * scaling) + Layout.preferredWidth: Math.max(140 * scaling) Layout.preferredHeight: Math.max(196 * scaling) } } diff --git a/Modules/ControlCenter/Extras/ControlCenterWidgetLoader.qml b/Modules/ControlCenter/Extras/ControlCenterWidgetLoader.qml new file mode 100644 index 00000000..4e7577ee --- /dev/null +++ b/Modules/ControlCenter/Extras/ControlCenterWidgetLoader.qml @@ -0,0 +1,74 @@ +import QtQuick +import Quickshell +import qs.Services +import qs.Commons + +Item { + id: root + + property string widgetId: "" + property var widgetProps: ({}) + property string screenName: widgetProps && widgetProps.screen ? widgetProps.screen.name : "" + property string section: widgetProps && widgetProps.section || "" + property int sectionIndex: widgetProps && widgetProps.sectionWidgetIndex || 0 + + // Don't reserve space unless the loaded widget is really visible + implicitWidth: getImplicitSize(loader.item, "implicitWidth") + implicitHeight: getImplicitSize(loader.item, "implicitHeight") + + Connections { + target: ScalingService + enabled: loader.item && (loader.item.screen !== undefined) + function onScaleChanged(aScreenName, scale) { + if (loader.item && loader.item.screen && aScreenName === screenName) { + loader.item['scaling'] = scale + } + } + } + + function getImplicitSize(item, prop) { + return (item && item.visible) ? item[prop] : 0 + } + + Loader { + id: loader + anchors.fill: parent + active: widgetId !== "" + asynchronous: false + sourceComponent: { + if (!active) { + return null + } + return ControlCenterWidgetRegistry.getWidget(widgetId) + } + + onLoaded: { + if (item && widgetProps) { + // Apply properties to loaded widget + for (var prop in widgetProps) { + if (item.hasOwnProperty(prop)) { + item[prop] = widgetProps[prop] + } + } + } + + if (item.hasOwnProperty("onLoaded")) { + item.onLoaded() + } + + //Logger.log("ControlCenterWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name) + } + + Component.onDestruction: { + // Explicitly clear references + widgetProps = null + } + } + + // Error handling + onWidgetIdChanged: { + if (widgetId && !ControlCenterWidgetRegistry.hasWidget(widgetId)) { + Logger.warn("ControlCenterWidgetLoader", "Widget not found in registry:", widgetId) + } + } +} diff --git a/Modules/ControlCenter/Widgets/Bluetooth.qml b/Modules/ControlCenter/Widgets/Bluetooth.qml new file mode 100644 index 00000000..7129ba64 --- /dev/null +++ b/Modules/ControlCenter/Widgets/Bluetooth.qml @@ -0,0 +1,17 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + property ShellScreen screen + property real scaling: 1.0 + + outlined: true + text: "Bluetooth" + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" + onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) +} diff --git a/Modules/ControlCenter/Widgets/KeepAwake.qml b/Modules/ControlCenter/Widgets/KeepAwake.qml new file mode 100644 index 00000000..9840c5b3 --- /dev/null +++ b/Modules/ControlCenter/Widgets/KeepAwake.qml @@ -0,0 +1,17 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + property ShellScreen screen + property real scaling: 1.0 + + outlined: true + text: IdleInhibitorService.isInhibited ? "Keep-awake" : "Keep-awake" + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" + onClicked: IdleInhibitorService.manualToggle() +} diff --git a/Modules/ControlCenter/Widgets/NightLight.qml b/Modules/ControlCenter/Widgets/NightLight.qml new file mode 100644 index 00000000..841cc560 --- /dev/null +++ b/Modules/ControlCenter/Widgets/NightLight.qml @@ -0,0 +1,33 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + property ShellScreen screen + property real scaling: 1.0 + + outlined: true + enabled: ProgramCheckerService.wlsunsetAvailable + text: "Night Light" + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" + onClicked: { + if (!Settings.data.nightLight.enabled) { + Settings.data.nightLight.enabled = true + Settings.data.nightLight.forced = false + } else if (Settings.data.nightLight.enabled && !Settings.data.nightLight.forced) { + Settings.data.nightLight.forced = true + } else { + Settings.data.nightLight.enabled = false + Settings.data.nightLight.forced = false + } + } + onRightClicked: { + var settingsPanel = PanelService.getPanel("settingsPanel") + settingsPanel.requestedTab = SettingsPanel.Tab.Display + settingsPanel.open() + } +} diff --git a/Modules/ControlCenter/Widgets/PowerProfile.qml b/Modules/ControlCenter/Widgets/PowerProfile.qml new file mode 100644 index 00000000..b5b0df8d --- /dev/null +++ b/Modules/ControlCenter/Widgets/PowerProfile.qml @@ -0,0 +1,23 @@ +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.UPower +import qs.Commons +import qs.Services +import qs.Widgets + +// Performance +NButton { + property ShellScreen screen + property real scaling: 1.0 + readonly property bool hasPP: PowerProfileService.available + + enabled: hasPP + outlined: true + text: PowerProfileService.getName() + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + icon: PowerProfileService.getIcon() + onClicked: { + PowerProfileService.cycleProfile() + } +} diff --git a/Modules/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/ControlCenter/Widgets/ScreenRecorder.qml new file mode 100644 index 00000000..fb4b0825 --- /dev/null +++ b/Modules/ControlCenter/Widgets/ScreenRecorder.qml @@ -0,0 +1,24 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + + property ShellScreen screen + property real scaling: 1.0 + + enabled: ProgramCheckerService.gpuScreenRecorderAvailable + outlined: true + icon: "camera-video" + text: "Screen Recorder" + fontWeight: Style.fontWeightRegular + onClicked: { + ScreenRecorderService.toggleRecording() + if (!ScreenRecorderService.isRecording) { + var panel = PanelService.getPanel("controlCenterPanel") + panel?.close() + } + } +} diff --git a/Modules/ControlCenter/Widgets/WallpaperSelector.qml b/Modules/ControlCenter/Widgets/WallpaperSelector.qml new file mode 100644 index 00000000..fd5a7b81 --- /dev/null +++ b/Modules/ControlCenter/Widgets/WallpaperSelector.qml @@ -0,0 +1,20 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + property ShellScreen screen + property real scaling: 1.0 + + + enabled: Settings.data.wallpaper.enabled + outlined: true + icon: "wallpaper-selector" + text: "Wallpaper" + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + onClicked: PanelService.getPanel("wallpaperPanel")?.toggle(this) + onRightClicked: WallpaperService.setRandomWallpaper() +} diff --git a/Modules/ControlCenter/Widgets/WiFi.qml b/Modules/ControlCenter/Widgets/WiFi.qml new file mode 100644 index 00000000..28d4e047 --- /dev/null +++ b/Modules/ControlCenter/Widgets/WiFi.qml @@ -0,0 +1,42 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + property ShellScreen screen + property real scaling: 1.0 + + + outlined: true + icon: { + try { + if (NetworkService.ethernetConnected) { + return "ethernet" + } + let connected = false + let signalStrength = 0 + for (const net in NetworkService.networks) { + if (NetworkService.networks[net].connected) { + connected = true + signalStrength = NetworkService.networks[net].signal + break + } + } + return connected ? NetworkService.signalIcon(signalStrength) : "wifi-off" + } catch (error) { + Logger.error("Wi-Fi", "Error getting icon:", error) + return "signal_wifi_bad" + } + } + text: { + if (NetworkService.ethernetConnected) { + return "Network" + } + return "Wi-Fi" + } + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) +} diff --git a/Modules/Settings/Bar/BarSectionEditor.qml b/Modules/Settings/Extras/SectionEditor.qml similarity index 96% rename from Modules/Settings/Bar/BarSectionEditor.qml rename to Modules/Settings/Extras/SectionEditor.qml index a36a1b17..af5a8380 100644 --- a/Modules/Settings/Bar/BarSectionEditor.qml +++ b/Modules/Settings/Extras/SectionEditor.qml @@ -13,6 +13,10 @@ NBox { property string sectionId: "" property var widgetModel: [] property var availableWidgets: [] + property bool enableMoveBetweenSections: true + + property var widgetRegistry: null + property string settingsDialogComponent: "BarWidgetSettingsDialog.qml" readonly property real miniButtonSize: Style.baseWidgetSize * 0.65 @@ -154,7 +158,7 @@ NBox { // Store the widget index for drag operations property int widgetIndex: index readonly property int buttonsWidth: Math.round(20 * scaling) - readonly property int buttonsCount: 1 + BarWidgetRegistry.widgetHasUserSettings(modelData.id) + readonly property int buttonsCount: 1 + (root.widgetRegistry ? root.widgetRegistry.widgetHasUserSettings(modelData.id) : 0) // Visual feedback during drag opacity: flowDragArea.draggedIndex === index ? 0.5 : 1.0 @@ -197,9 +201,10 @@ NBox { onTriggered: action => root.moveWidget(root.sectionId, index, action) } - // Update the MouseArea to use the new context menu + // MouseArea for the context menu MouseArea { id: contextMouseArea + enabled: enableMoveBetweenSections anchors.fill: parent acceptedButtons: Qt.RightButton z: -1 // Below the buttons but above background @@ -209,9 +214,7 @@ NBox { // Check if click is not on the buttons area const localX = mouse.x const buttonsStartX = parent.width - (parent.buttonsCount * parent.buttonsWidth) - if (localX < buttonsStartX) { - // Use the helper function to open at mouse position contextMenu.openAtItem(widgetItem, mouse.x, mouse.y) } } @@ -236,7 +239,7 @@ NBox { Layout.preferredWidth: buttonsCount * buttonsWidth Loader { - active: BarWidgetRegistry.widgetHasUserSettings(modelData.id) + active: root.widgetRegistry && root.widgetRegistry.widgetHasUserSettings(modelData.id) sourceComponent: NIconButton { icon: "settings" tooltipText: I18n.tr("tooltips.widget-settings") @@ -247,7 +250,7 @@ NBox { colorBgHover: Qt.alpha(Color.mOnPrimary, Style.opacityLight) colorFgHover: Color.mOnPrimary onClicked: { - var component = Qt.createComponent(Qt.resolvedUrl("BarWidgetSettingsDialog.qml")) + var component = Qt.createComponent(Qt.resolvedUrl(root.settingsDialogComponent)) function instantiateAndOpen() { var dialog = component.createObject(root, { "widgetIndex": index, @@ -258,19 +261,19 @@ NBox { if (dialog) { dialog.open() } else { - Logger.error("BarSectionEditor", "Failed to create settings dialog instance") + Logger.error("WidgetSectionEditor", "Failed to create settings dialog instance") } } if (component.status === Component.Ready) { instantiateAndOpen() } else if (component.status === Component.Error) { - Logger.error("BarSectionEditor", component.errorString()) + Logger.error("WidgetSectionEditor", component.errorString()) } else { component.statusChanged.connect(function () { if (component.status === Component.Ready) { instantiateAndOpen() } else if (component.status === Component.Error) { - Logger.error("BarSectionEditor", component.errorString()) + Logger.error("WidgetSectionEditor", component.errorString()) } }) } diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index d13f5e9e..cb76dff4 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -29,6 +29,7 @@ NPanel { Audio, Bar, ColorScheme, + ControlCenter, OSD, Display, Dock, @@ -111,6 +112,10 @@ NPanel { id: notificationsTab NotificationsTab {} } + Component { + id: controlCenterTab + ControlCenterTab {} + } // Order *DOES* matter function updateTabsModel() { @@ -124,6 +129,11 @@ NPanel { "label": "settings.bar.title", "icon": "settings-bar", "source": barTab + }, { + "id": SettingsPanel.Tab.ControlCenter, + "label": "settings.control-center.title", + "icon": "settings-bar", + "source": controlCenterTab }, { "id": SettingsPanel.Tab.Dock, "label": "settings.dock.title", diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index 31405f5c..fff686ca 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -5,7 +5,7 @@ import Quickshell import qs.Commons import qs.Services import qs.Widgets -import qs.Modules.Settings.Bar +import qs.Modules.Settings.Extras ColumnLayout { id: root @@ -201,9 +201,11 @@ ColumnLayout { spacing: Style.marginM * scaling // Left Section - BarSectionEditor { + SectionEditor { sectionName: "Left" sectionId: "left" + settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Settings/Bar/BarWidgetSettingsDialog.qml") + widgetRegistry: BarWidgetRegistry widgetModel: Settings.data.bar.widgets.left availableWidgets: availableWidgets onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section) @@ -216,9 +218,11 @@ ColumnLayout { } // Center Section - BarSectionEditor { + SectionEditor { sectionName: "Center" sectionId: "center" + settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Settings/Bar/BarWidgetSettingsDialog.qml") + widgetRegistry: BarWidgetRegistry widgetModel: Settings.data.bar.widgets.center availableWidgets: availableWidgets onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section) @@ -231,9 +235,11 @@ ColumnLayout { } // Right Section - BarSectionEditor { + SectionEditor { sectionName: "Right" sectionId: "right" + settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Settings/Bar/BarWidgetSettingsDialog.qml") + widgetRegistry: BarWidgetRegistry widgetModel: Settings.data.bar.widgets.right availableWidgets: availableWidgets onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section) diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml new file mode 100644 index 00000000..9f432137 --- /dev/null +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -0,0 +1,140 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets +import qs.Modules.Settings.Extras + +ColumnLayout { + id: root + spacing: Style.marginL * scaling + + // Handler for drag start - disables panel background clicks + function handleDragStart() { + var panel = PanelService.getPanel("settingsPanel") + if (panel && panel.disableBackgroundClick) { + panel.disableBackgroundClick() + } + } + + // Handler for drag end - re-enables panel background clicks + function handleDragEnd() { + var panel = PanelService.getPanel("settingsPanel") + if (panel && panel.enableBackgroundClick) { + panel.enableBackgroundClick() + } + } + + // Widgets Management Section + ColumnLayout { + spacing: Style.marginXXS * scaling + Layout.fillWidth: true + + NHeader { + label: I18n.tr("settings.controlCenter.widgets.section.label") + description: I18n.tr("settings.controlCenter.widgets.section.description") + } + + // Bar Sections + ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.topMargin: Style.marginM * scaling + spacing: Style.marginM * scaling + + // Quick Settings + SectionEditor { + sectionName: "Quick Settings" + sectionId: "quickSettings" + settingsDialogComponent: "" + widgetRegistry: ControlCenterWidgetRegistry + widgetModel: Settings.data.controlCenter.widgets["quickSettings"] + availableWidgets: availableWidgets + enableMoveBetweenSections: false + onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section) + onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index) + onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex) + onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings) + onDragPotentialStarted: root.handleDragStart() + onDragPotentialEnded: root.handleDragEnd() + } + } + } + + NDivider { + Layout.fillWidth: true + Layout.topMargin: Style.marginXL * scaling + Layout.bottomMargin: Style.marginXL * scaling + } + + // --------------------------------- + // Signal functions + // --------------------------------- + function _addWidgetToSection(widgetId, section) { + var newWidget = { + "id": widgetId + } + if (ControlCenterWidgetRegistry.widgetHasUserSettings(widgetId)) { + var metadata = ControlCenterWidgetRegistry.widgetMetadata[widgetId] + if (metadata) { + Object.keys(metadata).forEach(function (key) { + if (key !== "allowUserSettings") { + newWidget[key] = metadata[key] + } + }) + } + } + Settings.data.controlCenter.widgets[section].push(newWidget) + } + + function _removeWidgetFromSection(section, index) { + if (index >= 0 && index < Settings.data.controlCenter.widgets[section].length) { + var newArray = Settings.data.controlCenter.widgets[section].slice() + var removedWidgets = newArray.splice(index, 1) + Settings.data.controlCenter.widgets[section] = newArray + + // Check that we still have a control center + if (removedWidgets[0].id === "ControlCenter" && BarService.lookupWidget("ControlCenter") === undefined) { + ToastService.showWarning(I18n.tr("toast.missing-control-center.label"), I18n.tr("toast.missing-control-center.description"), 12000) + } + } + } + + function _reorderWidgetInSection(section, fromIndex, toIndex) { + if (fromIndex >= 0 && fromIndex < Settings.data.controlCenter.widgets[section].length && toIndex >= 0 && toIndex < Settings.data.controlCenter.widgets[section].length) { + + // Create a new array to avoid modifying the original + var newArray = Settings.data.controlCenter.widgets[section].slice() + var item = newArray[fromIndex] + newArray.splice(fromIndex, 1) + newArray.splice(toIndex, 0, item) + + Settings.data.controlCenter.widgets[section] = newArray + //Logger.log("BarTab", "Widget reordered. New array:", JSON.stringify(newArray)) + } + } + + function _updateWidgetSettingsInSection(section, index, settings) { + // Update the widget settings in the Settings data + Settings.data.controlCenter.widgets[section][index] = settings + //Logger.log("BarTab", `Updated widget settings for ${settings.id} in ${section} section`) + } + + // Base list model for all combo boxes + ListModel { + id: availableWidgets + } + + Component.onCompleted: { + // Fill out availableWidgets ListModel + availableWidgets.clear() + ControlCenterWidgetRegistry.getAvailableWidgets().forEach(entry => { + availableWidgets.append({ + "key": entry, + "name": entry + }) + }) + } +} diff --git a/Services/ControlCenterWidgetRegistry.qml b/Services/ControlCenterWidgetRegistry.qml new file mode 100644 index 00000000..5fac8e00 --- /dev/null +++ b/Services/ControlCenterWidgetRegistry.qml @@ -0,0 +1,71 @@ +pragma Singleton + +import QtQuick +import Quickshell +import qs.Commons +import qs.Modules.ControlCenter.Widgets + +Singleton { + id: root + + // Widget registry object mapping widget names to components + property var widgets: ({ + "Bluetooth": bluetoothComponent, + "KeepAwake": keepAwakeComponent, + "NightLight": nightLightComponent, + "PowerProfile": powerProfileComponent, + "ScreenRecorder": screenRecorderComponent, + "WiFi": wiFiComponent, + "WallpaperSelector": wallpaperSelectorComponent + }) + + property var widgetMetadata: ({}) + + // Component definitions - these are loaded once at startup + property Component bluetoothComponent: Component { + Bluetooth {} + } + property Component keepAwakeComponent: Component { + KeepAwake {} + } + property Component nightLightComponent: Component { + NightLight {} + } + property Component powerProfileComponent: Component { + PowerProfile {} + } + property Component screenRecorderComponent: Component { + ScreenRecorder {} + } + property Component wiFiComponent: Component { + WiFi {} + } + property Component wallpaperSelectorComponent: Component { + WallpaperSelector {} + } + + function init() { + Logger.log("ControlCenterWidgetRegistry", "Service started") + } + + // ------------------------------ + // Helper function to get widget component by name + function getWidget(id) { + return widgets[id] || null + } + + // Helper function to check if widget exists + function hasWidget(id) { + return id in widgets + } + + // Get list of available widget id + function getAvailableWidgets() { + return Object.keys(widgets) + } + + // Helper function to check if widget has user settings + function widgetHasUserSettings(id) { + return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true) + } +} diff --git a/Widgets/NButton.qml b/Widgets/NButton.qml index 6ce1c75b..2f4f5daf 100644 --- a/Widgets/NButton.qml +++ b/Widgets/NButton.qml @@ -19,6 +19,7 @@ Rectangle { property int fontWeight: Style.fontWeightBold property real iconSize: Style.fontSizeL * scaling property bool outlined: false + property int horizontalAlignment: Qt.AlignHCenter // Signals signal clicked @@ -27,7 +28,6 @@ Rectangle { // Internal properties property bool hovered: false - property bool pressed: false // Dimensions implicitWidth: contentRow.implicitWidth + (Style.marginL * 2 * scaling) @@ -47,7 +47,7 @@ Rectangle { border.color: { if (!enabled) return Color.mOutline - if (pressed || hovered) + if (hovered) return backgroundColor return outlined ? backgroundColor : Color.transparent } @@ -71,7 +71,10 @@ Rectangle { // Content RowLayout { id: contentRow - anchors.centerIn: parent + anchors.verticalCenter: parent.verticalCenter + anchors.left: root.horizontalAlignment === Qt.AlignLeft ? parent.left : undefined + anchors.horizontalCenter: root.horizontalAlignment === Qt.AlignHCenter ? parent.horizontalCenter : undefined + anchors.leftMargin: root.horizontalAlignment === Qt.AlignLeft ? Style.marginL * scaling : 0 spacing: Style.marginXS * scaling // Icon (optional) @@ -84,8 +87,8 @@ Rectangle { if (!root.enabled) return Color.mOnSurfaceVariant if (root.outlined) { - if (root.pressed || root.hovered) - return root.backgroundColor + if (root.hovered) + return root.textColor return root.backgroundColor } return root.textColor From a90bca23aa5c277f5c73015eb45bba1b23fa3ab2 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 8 Oct 2025 23:24:22 -0400 Subject: [PATCH 02/16] QuickSettings: 3 columns + added Do not disturb --- Modules/ControlCenter/Cards/TopCard.qml | 7 +++---- Modules/ControlCenter/ControlCenterPanel.qml | 2 +- Modules/ControlCenter/Widgets/DoNotDisturb.qml | 17 +++++++++++++++++ .../ControlCenter/Widgets/ScreenRecorder.qml | 3 ++- Services/ControlCenterWidgetRegistry.qml | 4 ++++ 5 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 Modules/ControlCenter/Widgets/DoNotDisturb.qml diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index 1bb36148..a7123bfb 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -98,14 +98,14 @@ NBox { NDivider { Layout.fillWidth: true - Layout.topMargin: Style.marginM * scaling - Layout.bottomMargin: Style.marginM * scaling + Layout.topMargin: Style.marginS * scaling + Layout.bottomMargin: Style.marginS * scaling } GridLayout { id: grid Layout.fillWidth: true - columns: 2 + columns: 3 columnSpacing: Style.marginL * scaling rowSpacing: Style.marginM * scaling @@ -113,7 +113,6 @@ NBox { model: Settings.data.controlCenter.widgets.quickSettings delegate: ControlCenterWidgetLoader { Layout.fillWidth: true - Layout.preferredWidth: (grid.width - grid.columnSpacing) / 2 widgetId: (modelData.id !== undefined ? modelData.id : "") widgetProps: { "screen": root.modelData || null, diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index e47c593c..999f0071 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -38,7 +38,7 @@ NPanel { // Top Card: profile + utilities TopCard { Layout.fillWidth: true - Layout.preferredHeight: Math.max(280 * scaling) + Layout.preferredHeight: Math.max(230 * scaling) } // Media + stats column diff --git a/Modules/ControlCenter/Widgets/DoNotDisturb.qml b/Modules/ControlCenter/Widgets/DoNotDisturb.qml new file mode 100644 index 00000000..fed665d6 --- /dev/null +++ b/Modules/ControlCenter/Widgets/DoNotDisturb.qml @@ -0,0 +1,17 @@ +import QtQuick.Layouts +import Quickshell +import qs.Commons +import qs.Services +import qs.Widgets + +NButton { + property ShellScreen screen + property real scaling: 1.0 + + outlined: true + text: "Do not Disturb" + fontSize: Style.fontSizeS * scaling + fontWeight: Style.fontWeightRegular + icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" + onClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb +} diff --git a/Modules/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/ControlCenter/Widgets/ScreenRecorder.qml index fb4b0825..fbcb9bd9 100644 --- a/Modules/ControlCenter/Widgets/ScreenRecorder.qml +++ b/Modules/ControlCenter/Widgets/ScreenRecorder.qml @@ -12,7 +12,8 @@ NButton { enabled: ProgramCheckerService.gpuScreenRecorderAvailable outlined: true icon: "camera-video" - text: "Screen Recorder" + text: "Screen Rec." + fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightRegular onClicked: { ScreenRecorderService.toggleRecording() diff --git a/Services/ControlCenterWidgetRegistry.qml b/Services/ControlCenterWidgetRegistry.qml index 5fac8e00..4ed3d2ae 100644 --- a/Services/ControlCenterWidgetRegistry.qml +++ b/Services/ControlCenterWidgetRegistry.qml @@ -11,6 +11,7 @@ Singleton { // Widget registry object mapping widget names to components property var widgets: ({ "Bluetooth": bluetoothComponent, + "DoNotDisturb": doNotDisturbComponent, "KeepAwake": keepAwakeComponent, "NightLight": nightLightComponent, "PowerProfile": powerProfileComponent, @@ -25,6 +26,9 @@ Singleton { property Component bluetoothComponent: Component { Bluetooth {} } + property Component doNotDisturbComponent: Component { + DoNotDisturb {} + } property Component keepAwakeComponent: Component { KeepAwake {} } From f77efc409b34a23dc9f45fcdf3fd7fef62011fe1 Mon Sep 17 00:00:00 2001 From: lysec Date: Thu, 9 Oct 2025 13:56:35 +0200 Subject: [PATCH 03/16] QuickSettings: customization!? --- Assets/Translations/en.json | 22 ++ Assets/settings-default.json | 31 +- Commons/Settings.qml | 1 + Modules/ControlCenter/Cards/TopCard.qml | 4 +- Modules/ControlCenter/Widgets/Bluetooth.qml | 9 +- .../ControlCenter/Widgets/DoNotDisturb.qml | 11 +- Modules/ControlCenter/Widgets/KeepAwake.qml | 11 +- Modules/ControlCenter/Widgets/NightLight.qml | 18 +- .../ControlCenter/Widgets/PowerProfile.qml | 9 +- .../ControlCenter/Widgets/ScreenRecorder.qml | 10 +- .../Widgets/WallpaperSelector.qml | 10 +- Modules/ControlCenter/Widgets/WiFi.qml | 40 ++- Modules/Settings/Tabs/ControlCenterTab.qml | 35 ++ Widgets/NButton.qml | 2 +- Widgets/NQuickSetting.qml | 327 ++++++++++++++++++ 15 files changed, 507 insertions(+), 33 deletions(-) create mode 100644 Widgets/NQuickSetting.qml diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index ff91166a..62d3e9c7 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -95,6 +95,24 @@ "label": "Position", "description": "Choose where the Control Center panel appears when opened." } + }, + "controlCenter": { + "quickSettingsStyle": { + "section": { + "label": "Quick Settings Style", + "description": "Choose the visual style for quick settings buttons." + }, + "style": { + "label": "Display Style", + "description": "Select between modern card-style buttons or classic icon buttons." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Manage and configure Control Center widgets." + } + } } }, "audio": { @@ -1241,6 +1259,10 @@ "bottom_right": "Bottom right", "bottom_center": "Bottom center", "top_center": "Top center" + }, + "quickSettingsStyle": { + "modern": "Modern Cards", + "classic": "Classic Icons" } }, "osd": { diff --git a/Assets/settings-default.json b/Assets/settings-default.json index a80e2bb4..05675bd4 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -112,7 +112,36 @@ "terminalCommand": "xterm -e" }, "controlCenter": { - "position": "close_to_bar_button" + "position": "close_to_bar_button", + "quickSettingsStyle": "modern", + "widgets": { + "quickSettings": [ + { + "id": "WiFi" + }, + { + "id": "Bluetooth" + }, + { + "id": "DoNotDisturb" + }, + { + "id": "NightLight" + }, + { + "id": "KeepAwake" + }, + { + "id": "PowerProfile" + }, + { + "id": "ScreenRecorder" + }, + { + "id": "WallpaperSelector" + } + ] + } }, "dock": { "displayMode": "always_visible", diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 61b4d184..8ab90c93 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -246,6 +246,7 @@ Singleton { property JsonObject controlCenter: JsonObject { // Position: close_to_bar_button, center, top_left, top_right, bottom_left, bottom_right, bottom_center, top_center property string position: "close_to_bar_button" + property string quickSettingsStyle: "modern" // "modern" or "classic" property JsonObject widgets widgets: JsonObject { property list quickSettings: [{ diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index a7123bfb..51aeb619 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -106,8 +106,8 @@ NBox { id: grid Layout.fillWidth: true columns: 3 - columnSpacing: Style.marginL * scaling - rowSpacing: Style.marginM * scaling + columnSpacing: Style.marginM * scaling + rowSpacing: Style.marginS * scaling Repeater { model: Settings.data.controlCenter.widgets.quickSettings diff --git a/Modules/ControlCenter/Widgets/Bluetooth.qml b/Modules/ControlCenter/Widgets/Bluetooth.qml index 7129ba64..9b1cd17d 100644 --- a/Modules/ControlCenter/Widgets/Bluetooth.qml +++ b/Modules/ControlCenter/Widgets/Bluetooth.qml @@ -4,14 +4,17 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 - outlined: true text: "Bluetooth" fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" + active: BluetoothService.enabled + tooltipText: BluetoothService.enabled ? "Bluetooth enabled" : "Bluetooth disabled" + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) } diff --git a/Modules/ControlCenter/Widgets/DoNotDisturb.qml b/Modules/ControlCenter/Widgets/DoNotDisturb.qml index fed665d6..cc2a1d1a 100644 --- a/Modules/ControlCenter/Widgets/DoNotDisturb.qml +++ b/Modules/ControlCenter/Widgets/DoNotDisturb.qml @@ -4,14 +4,17 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 - outlined: true text: "Do not Disturb" fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular - icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" + fontWeight: Style.fontWeightMedium + icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" + active: Settings.data.notifications.doNotDisturb + tooltipText: Settings.data.notifications.doNotDisturb ? "Turn off Do Not Disturb" : "Turn on Do Not Disturb" + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + onClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb } diff --git a/Modules/ControlCenter/Widgets/KeepAwake.qml b/Modules/ControlCenter/Widgets/KeepAwake.qml index 9840c5b3..a254f8df 100644 --- a/Modules/ControlCenter/Widgets/KeepAwake.qml +++ b/Modules/ControlCenter/Widgets/KeepAwake.qml @@ -4,14 +4,17 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 - outlined: true - text: IdleInhibitorService.isInhibited ? "Keep-awake" : "Keep-awake" + text: "Keep-awake" fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" + active: IdleInhibitorService.isInhibited + tooltipText: IdleInhibitorService.isInhibited ? "Disable keep-awake" : "Enable keep-awake" + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + onClicked: IdleInhibitorService.manualToggle() } diff --git a/Modules/ControlCenter/Widgets/NightLight.qml b/Modules/ControlCenter/Widgets/NightLight.qml index 841cc560..21077f37 100644 --- a/Modules/ControlCenter/Widgets/NightLight.qml +++ b/Modules/ControlCenter/Widgets/NightLight.qml @@ -4,16 +4,27 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 - outlined: true enabled: ProgramCheckerService.wlsunsetAvailable text: "Night Light" fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" + active: Settings.data.nightLight.enabled + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + tooltipText: { + if (!Settings.data.nightLight.enabled) { + return "Turn on Night Light" + } else if (Settings.data.nightLight.forced) { + return "Night Light forced on" + } else { + return "Turn off Night Light" + } + } + onClicked: { if (!Settings.data.nightLight.enabled) { Settings.data.nightLight.enabled = true @@ -25,6 +36,7 @@ NButton { Settings.data.nightLight.forced = false } } + onRightClicked: { var settingsPanel = PanelService.getPanel("settingsPanel") settingsPanel.requestedTab = SettingsPanel.Tab.Display diff --git a/Modules/ControlCenter/Widgets/PowerProfile.qml b/Modules/ControlCenter/Widgets/PowerProfile.qml index b5b0df8d..2636d40e 100644 --- a/Modules/ControlCenter/Widgets/PowerProfile.qml +++ b/Modules/ControlCenter/Widgets/PowerProfile.qml @@ -6,17 +6,20 @@ import qs.Services import qs.Widgets // Performance -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 readonly property bool hasPP: PowerProfileService.available enabled: hasPP - outlined: true text: PowerProfileService.getName() fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium icon: PowerProfileService.getIcon() + active: hasPP + tooltipText: hasPP ? "Current: " + PowerProfileService.getName() : "Power profiles not available" + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + onClicked: { PowerProfileService.cycleProfile() } diff --git a/Modules/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/ControlCenter/Widgets/ScreenRecorder.qml index fbcb9bd9..0523bf7e 100644 --- a/Modules/ControlCenter/Widgets/ScreenRecorder.qml +++ b/Modules/ControlCenter/Widgets/ScreenRecorder.qml @@ -4,17 +4,19 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { - +NQuickSetting { property ShellScreen screen property real scaling: 1.0 enabled: ProgramCheckerService.gpuScreenRecorderAvailable - outlined: true icon: "camera-video" text: "Screen Rec." fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium + active: ScreenRecorderService.isRecording + tooltipText: ScreenRecorderService.isRecording ? "Stop recording" : "Start screen recording" + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + onClicked: { ScreenRecorderService.toggleRecording() if (!ScreenRecorderService.isRecording) { diff --git a/Modules/ControlCenter/Widgets/WallpaperSelector.qml b/Modules/ControlCenter/Widgets/WallpaperSelector.qml index fd5a7b81..9ec4db51 100644 --- a/Modules/ControlCenter/Widgets/WallpaperSelector.qml +++ b/Modules/ControlCenter/Widgets/WallpaperSelector.qml @@ -4,17 +4,19 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 - enabled: Settings.data.wallpaper.enabled - outlined: true icon: "wallpaper-selector" text: "Wallpaper" fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium + active: Settings.data.wallpaper.enabled + tooltipText: "Open wallpaper selector" + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + onClicked: PanelService.getPanel("wallpaperPanel")?.toggle(this) onRightClicked: WallpaperService.setRandomWallpaper() } diff --git a/Modules/ControlCenter/Widgets/WiFi.qml b/Modules/ControlCenter/Widgets/WiFi.qml index 28d4e047..30a4f635 100644 --- a/Modules/ControlCenter/Widgets/WiFi.qml +++ b/Modules/ControlCenter/Widgets/WiFi.qml @@ -4,12 +4,10 @@ import qs.Commons import qs.Services import qs.Widgets -NButton { +NQuickSetting { property ShellScreen screen property real scaling: 1.0 - - outlined: true icon: { try { if (NetworkService.ethernetConnected) { @@ -30,13 +28,47 @@ NButton { return "signal_wifi_bad" } } + text: { if (NetworkService.ethernetConnected) { return "Network" } return "Wi-Fi" } + fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightRegular + fontWeight: Style.fontWeightMedium + style: Settings.data.controlCenter.quickSettingsStyle || "modern" + + active: { + if (NetworkService.ethernetConnected) { + return true + } + try { + for (const net in NetworkService.networks) { + if (NetworkService.networks[net].connected) { + return true + } + } + return false + } catch (error) { + return false + } + } + + tooltipText: { + if (NetworkService.ethernetConnected) { + return "Ethernet connected" + } + let connected = false + for (const net in NetworkService.networks) { + if (NetworkService.networks[net].connected) { + connected = true + break + } + } + return connected ? "Wi-Fi connected" : "Wi-Fi disconnected" + } + onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) } diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml index 9f432137..6a6a3b16 100644 --- a/Modules/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -27,6 +27,41 @@ ColumnLayout { } } + // Quick Settings Style Section + ColumnLayout { + spacing: Style.marginL * scaling + Layout.fillWidth: true + + NHeader { + label: I18n.tr("settings.controlCenter.quickSettingsStyle.section.label") + description: I18n.tr("settings.controlCenter.quickSettingsStyle.section.description") + } + + NComboBox { + id: quickSettingsStyle + label: I18n.tr("settings.controlCenter.quickSettingsStyle.style.label") + description: I18n.tr("settings.controlCenter.quickSettingsStyle.style.description") + Layout.fillWidth: true + model: [{ + "key": "modern", + "name": I18n.tr("options.controlCenter.quickSettingsStyle.modern") + }, { + "key": "classic", + "name": I18n.tr("options.controlCenter.quickSettingsStyle.classic") + }] + currentKey: Settings.data.controlCenter.quickSettingsStyle || "modern" + onSelected: function (key) { + Settings.data.controlCenter.quickSettingsStyle = key + } + } + } + + NDivider { + Layout.fillWidth: true + Layout.topMargin: Style.marginXL * scaling + Layout.bottomMargin: Style.marginXL * scaling + } + // Widgets Management Section ColumnLayout { spacing: Style.marginXXS * scaling diff --git a/Widgets/NButton.qml b/Widgets/NButton.qml index 2f4f5daf..3d1b05a3 100644 --- a/Widgets/NButton.qml +++ b/Widgets/NButton.qml @@ -19,7 +19,7 @@ Rectangle { property int fontWeight: Style.fontWeightBold property real iconSize: Style.fontSizeL * scaling property bool outlined: false - property int horizontalAlignment: Qt.AlignHCenter + property int horizontalAlignment: Qt.AlignHCenter // Signals signal clicked diff --git a/Widgets/NQuickSetting.qml b/Widgets/NQuickSetting.qml new file mode 100644 index 00000000..3c199c16 --- /dev/null +++ b/Widgets/NQuickSetting.qml @@ -0,0 +1,327 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Effects +import qs.Commons +import qs.Services + +Rectangle { + id: root + + // Public properties + property string text: "" + property string icon: "" + property string tooltipText: "" + property bool enabled: true + property bool active: false + property bool compact: false + property string style: "modern" // "modern" or "classic" + + // Styling properties + property real fontSize: Style.fontSizeS * scaling + property int fontWeight: Style.fontWeightMedium + property real iconSize: Style.fontSizeL * scaling + property real cornerRadius: Style.radiusM * scaling + + // Colors - Style-dependent colors + property color backgroundColor: style === "classic" ? Color.mSurfaceVariant : Color.mSurface + property color textColor: Color.mOnSurface + property color iconColor: style === "classic" ? Color.mPrimary : (active ? Color.mPrimary : Color.mOnSurface) + property color borderColor: Color.mOutline + property color hoverColor: style === "classic" ? Color.mTertiary : Color.mPrimary + property color pressedColor: style === "classic" ? Color.mTertiary : Qt.darker(Color.mPrimary, 1.1) + property color hoverTextColor: Color.mOnPrimary + property color hoverIconColor: style === "classic" ? Color.mOnTertiary : Color.mOnPrimary + + // Signals + signal clicked + signal rightClicked + signal middleClicked + + // Internal properties + property bool hovered: false + property bool pressed: false + property real scaling: 1.0 + + // Dimensions - Style-dependent sizing + implicitWidth: { + if (style === "classic") { + return Style.baseWidgetSize * scaling + } + return compact ? Math.max(100 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) : Math.max(120 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) + } + implicitHeight: { + if (style === "classic") { + return Style.baseWidgetSize * scaling + } + return compact ? Math.max(48 * scaling, contentRow.implicitHeight + (Style.marginM * scaling)) : Math.max(56 * scaling, contentRow.implicitHeight + (Style.marginL * scaling)) + } + + // Appearance - Style-dependent styling + radius: style === "classic" ? width * 0.5 : cornerRadius + color: { + if (!enabled) + return Qt.lighter(Color.mSurface, 1.1) + if (pressed) + return pressedColor + if (hovered) + return hoverColor + return backgroundColor + } + + border.width: style === "classic" ? Math.max(1, Style.borderS * scaling) : 0 + border.color: style === "classic" ? borderColor : "transparent" + + opacity: enabled ? (style === "classic" ? Style.opacityFull : 1.0) : (style === "classic" ? Style.opacityMedium : 0.6) + + // Smooth animations + Behavior on color { + ColorAnimation { + duration: style === "classic" ? Style.animationNormal : Style.animationFast + easing.type: style === "classic" ? Easing.InOutQuad : Easing.OutCubic + } + } + + Behavior on border.color { + ColorAnimation { + duration: style === "classic" ? Style.animationNormal : Style.animationFast + easing.type: style === "classic" ? Easing.InOutQuad : Easing.OutCubic + } + } + + Behavior on scale { + NumberAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + + // Hover scale effect + scale: hovered ? 1.02 : 1.0 + + // Subtle shadow/elevation effect + Rectangle { + anchors.fill: parent + radius: parent.radius + color: Qt.rgba(0, 0, 0, 0.1) + visible: active + z: -1 + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + + // Modern style - icon above text + ColumnLayout { + id: contentRow + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + visible: root.style !== "classic" + + // Icon + NIcon { + Layout.alignment: Qt.AlignHCenter + visible: root.icon !== "" + icon: root.icon + pointSize: root.iconSize + color: { + if (!root.enabled) + return Color.mOnSurfaceVariant + if (root.hovered) + return root.hoverIconColor + return root.iconColor + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + + // Text content + NText { + Layout.alignment: Qt.AlignHCenter + visible: root.text !== "" && !compact + text: root.text + pointSize: root.fontSize + font.weight: root.fontWeight + color: { + if (!root.enabled) + return Color.mOnSurfaceVariant + if (root.hovered) + return root.hoverTextColor + return root.textColor + } + elide: Text.ElideRight + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + } + + // Classic style - EXACTLY like NIconButton (icon + text) + RowLayout { + anchors.centerIn: parent + visible: root.style === "classic" + spacing: Style.marginXS * scaling + + NIcon { + visible: root.icon !== "" + icon: root.icon + pointSize: Style.fontSizeM * scaling + color: { + if (!root.enabled) + return Color.mOnSurfaceVariant + if (root.hovered) + return root.hoverIconColor + return root.iconColor + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + + NText { + visible: root.text !== "" + text: root.text + pointSize: root.fontSize + font.weight: root.fontWeight + color: { + if (!root.enabled) + return Color.mOnSurfaceVariant + if (root.hovered) + return root.hoverTextColor + return root.textColor + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + } + + // Mouse interaction with enhanced feedback + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: root.enabled + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + + onEntered: { + root.hovered = true + if (tooltipText) { + TooltipService.show(Screen, root, root.tooltipText) + } + } + + onExited: { + root.hovered = false + if (tooltipText) { + TooltipService.hide() + } + } + + onPressed: mouse => { + root.pressed = true + root.scale = 0.95 + if (tooltipText) { + TooltipService.hide() + } + } + + onReleased: mouse => { + root.pressed = false + root.scale = 1.0 + + if (mouse.button === Qt.LeftButton) { + root.clicked() + } else if (mouse.button === Qt.RightButton) { + root.rightClicked() + } else if (mouse.button === Qt.MiddleButton) { + root.middleClicked() + } + } + + onCanceled: { + root.hovered = false + root.pressed = false + root.scale = 1.0 + if (tooltipText) { + TooltipService.hide() + } + } + } + + // Ripple effect for M3-style interaction feedback + Rectangle { + id: ripple + anchors.fill: parent + radius: parent.radius + color: Qt.rgba(1, 1, 1, 0.2) + scale: 0 + opacity: 0 + visible: false + + SequentialAnimation { + id: rippleAnimation + running: false + + ParallelAnimation { + NumberAnimation { + target: ripple + property: "scale" + from: 0 + to: 1.2 + duration: Style.animationNormal + easing.type: Easing.OutCubic + } + NumberAnimation { + target: ripple + property: "opacity" + from: 0.6 + to: 0 + duration: Style.animationNormal + easing.type: Easing.OutCubic + } + } + } + } + + // Trigger ripple effect on click + Connections { + target: root + function onClicked() { + ripple.visible = true + rippleAnimation.start() + } + } + + // Clean up ripple after animation + Connections { + target: rippleAnimation + function onFinished() { + ripple.visible = false + ripple.scale = 0 + ripple.opacity = 0 + } + } +} From a5ff7cfe6b26f197c5da70e0e5a0bd042b4caea6 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 08:59:26 -0400 Subject: [PATCH 04/16] ControlCenter: improved height computation --- Modules/ControlCenter/ControlCenterPanel.qml | 27 ++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 999f0071..2e8d5375 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -11,9 +11,24 @@ NPanel { id: root preferredWidth: 440 - preferredHeight: 540 + preferredHeight: topHeight + bottomHeight + Math.round(Style.marginL * scaling * 3) panelKeyboardFocus: true + readonly property int bottomHeight: Math.round(Math.max(196 * scaling)) + readonly property int topHeight: { + const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / 3) + + var buttonHeight; + if (Settings.data.controlCenter.quickSettingsStyle === "classic") { + buttonHeight = Style.baseWidgetSize + } + else { + buttonHeight = 56 + } + + return (rowsCount * buttonHeight) + (120 * scaling) + } + // Positioning readonly property string controlCenterPosition: Settings.data.controlCenter.position panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_center") @@ -37,26 +52,28 @@ NPanel { // Top Card: profile + utilities TopCard { + id: topCard Layout.fillWidth: true - Layout.preferredHeight: Math.max(230 * scaling) + Layout.preferredHeight: topHeight } // Media + stats column RowLayout { + id: bottomCard Layout.fillWidth: true - Layout.preferredHeight: Math.max(196 * scaling) + Layout.preferredHeight: bottomHeight spacing: content.cardSpacing // Media card MediaCard { Layout.preferredWidth: Math.max(250 * scaling) - Layout.preferredHeight: Math.max(196 * scaling) + Layout.preferredHeight: bottomHeight } // System monitors combined in one card SystemMonitorCard { Layout.preferredWidth: Math.max(140 * scaling) - Layout.preferredHeight: Math.max(196 * scaling) + Layout.preferredHeight: bottomHeight } } } From 95dcded6b7540fe975cdc2448f10c87ddd990ce6 Mon Sep 17 00:00:00 2001 From: lysec Date: Thu, 9 Oct 2025 15:17:23 +0200 Subject: [PATCH 05/16] QuickSettings: add compact version i18n: add translations --- Assets/Translations/de.json | 41 +++++++++ Assets/Translations/en.json | 37 ++++++-- Assets/Translations/es.json | 41 +++++++++ Assets/Translations/fr.json | 41 +++++++++ Assets/Translations/pt.json | 41 +++++++++ Assets/Translations/zh-CN.json | 41 +++++++++ Modules/Settings/Tabs/ControlCenterTab.qml | 19 ++-- Widgets/NQuickSetting.qml | 100 +++++++++++++++++---- 8 files changed, 329 insertions(+), 32 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 021a823f..eb2f15ce 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -85,6 +85,7 @@ "reset-scaling": "Skalierung zurücksetzen" }, "control-center": { + "title": "Kontrollzentrum", "section": { "label": "Kontrollzentrum", "description": "Konfigurieren Sie die Positionierung und das Verhalten des Kontrollzentrum-Panels." @@ -92,6 +93,22 @@ "position": { "label": "Position", "description": "Wählen Sie, wo das Kontrollzentrum-Panel beim Öffnen erscheint." + }, + "quickSettingsStyle": { + "section": { + "label": "Schnelleinstellungen-Stil", + "description": "Passen Sie das Aussehen und Verhalten der Schnelleinstellungen im Kontrollzentrum an." + }, + "style": { + "label": "Schnelleinstellungen-Stil", + "description": "Wählen Sie den visuellen Stil für Schnelleinstellungs-Schalter und -Steuerungen." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Konfigurieren und verwalten Sie Kontrollzentrum-Widgets und deren Anzeigeoptionen." + } } } }, @@ -709,6 +726,25 @@ } } }, + "control-center": { + "title": "Kontrollzentrum", + "quickSettingsStyle": { + "section": { + "label": "Schnelleinstellungen-Stil", + "description": "Passen Sie das Aussehen und Verhalten der Schnelleinstellungen im Kontrollzentrum an." + }, + "style": { + "label": "Schnelleinstellungen-Stil", + "description": "Wählen Sie den visuellen Stil für Schnelleinstellungs-Schalter und -Steuerungen." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Konfigurieren und verwalten Sie Kontrollzentrum-Widgets und deren Anzeigeoptionen." + } + } + }, "hooks": { "title": "Hooks", "system-hooks": { @@ -1259,6 +1295,11 @@ "bottom_right": "Unten rechts", "bottom_center": "Unten mittig", "top_center": "Oben mittig" + }, + "quickSettingsStyle": { + "modern": "Modern", + "classic": "Klassisch", + "compact": "Kompakt" } }, "osd": { diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 62d3e9c7..4d7e9b13 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -87,6 +87,7 @@ } }, "control-center": { + "title": "Control Center", "section": { "label": "Control Center", "description": "Configure the Control Center panel positioning and behavior." @@ -94,23 +95,21 @@ "position": { "label": "Position", "description": "Choose where the Control Center panel appears when opened." - } - }, - "controlCenter": { + }, "quickSettingsStyle": { "section": { "label": "Quick Settings Style", - "description": "Choose the visual style for quick settings buttons." + "description": "Customize the appearance and behavior of quick settings in the Control Center." }, "style": { - "label": "Display Style", - "description": "Select between modern card-style buttons or classic icon buttons." + "label": "Quick Settings Style", + "description": "Choose the visual style for quick settings toggles and controls." } }, "widgets": { "section": { "label": "Widgets", - "description": "Manage and configure Control Center widgets." + "description": "Configure and manage Control Center widgets and their display options." } } } @@ -725,6 +724,25 @@ } } }, + "control-center": { + "title": "Control Center", + "quickSettingsStyle": { + "section": { + "label": "Quick Settings Style", + "description": "Customize the appearance and behavior of quick settings in the Control Center." + }, + "style": { + "label": "Quick Settings Style", + "description": "Choose the visual style for quick settings toggles and controls." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configure and manage Control Center widgets and their display options." + } + } + }, "hooks": { "title": "Hooks", "system-hooks": { @@ -1261,8 +1279,9 @@ "top_center": "Top center" }, "quickSettingsStyle": { - "modern": "Modern Cards", - "classic": "Classic Icons" + "modern": "Modern", + "classic": "Classic", + "compact": "Compact" } }, "osd": { diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index f33d2e0c..5b904ade 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -85,6 +85,7 @@ "reset-scaling": "Restablecer la escala" }, "control-center": { + "title": "Centro de control", "section": { "label": "Centro de control", "description": "Configurar el posicionamiento y comportamiento del panel del centro de control." @@ -92,6 +93,22 @@ "position": { "label": "Posición", "description": "Elige dónde aparece el panel del centro de control cuando se abre." + }, + "quickSettingsStyle": { + "section": { + "label": "Estilo de configuración rápida", + "description": "Personaliza la apariencia y el comportamiento de las configuraciones rápidas en el centro de control." + }, + "style": { + "label": "Estilo de configuración rápida", + "description": "Elige el estilo visual para los interruptores y controles de configuración rápida." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configura y gestiona los widgets del centro de control y sus opciones de visualización." + } } } }, @@ -705,6 +722,25 @@ } } }, + "control-center": { + "title": "Centro de control", + "quickSettingsStyle": { + "section": { + "label": "Estilo de configuración rápida", + "description": "Personaliza la apariencia y el comportamiento de las configuraciones rápidas en el centro de control." + }, + "style": { + "label": "Estilo de configuración rápida", + "description": "Elige el estilo visual para los interruptores y controles de configuración rápida." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configura y gestiona los widgets del centro de control y sus opciones de visualización." + } + } + }, "hooks": { "title": "Hooks", "system-hooks": { @@ -1238,6 +1274,11 @@ "bottom_right": "Inferior derecha", "bottom_center": "Inferior central", "top_center": "Superior central" + }, + "quickSettingsStyle": { + "modern": "Moderno", + "classic": "Clásico", + "compact": "Compacto" } }, "osd": { diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index a087896a..aab3dd41 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -85,6 +85,7 @@ "reset-scaling": "Réinitialiser l'échelle" }, "control-center": { + "title": "Centre de contrôle", "section": { "label": "Centre de contrôle", "description": "Configurer le positionnement et le comportement du panneau du centre de contrôle." @@ -92,6 +93,22 @@ "position": { "label": "Position", "description": "Choisissez où apparaît le panneau du centre de contrôle lors de l'ouverture." + }, + "quickSettingsStyle": { + "section": { + "label": "Style des paramètres rapides", + "description": "Personnalisez l'apparence et le comportement des paramètres rapides dans le centre de contrôle." + }, + "style": { + "label": "Style des paramètres rapides", + "description": "Choisissez le style visuel pour les commutateurs et contrôles des paramètres rapides." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configurez et gérez les widgets du centre de contrôle et leurs options d'affichage." + } } } }, @@ -705,6 +722,25 @@ } } }, + "control-center": { + "title": "Centre de contrôle", + "quickSettingsStyle": { + "section": { + "label": "Style des paramètres rapides", + "description": "Personnalisez l'apparence et le comportement des paramètres rapides dans le centre de contrôle." + }, + "style": { + "label": "Style des paramètres rapides", + "description": "Choisissez le style visuel pour les commutateurs et contrôles des paramètres rapides." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configurez et gérez les widgets du centre de contrôle et leurs options d'affichage." + } + } + }, "hooks": { "title": "Hooks", "system-hooks": { @@ -1238,6 +1274,11 @@ "bottom_right": "En bas à droite", "bottom_center": "En bas au centre", "top_center": "En haut au centre" + }, + "quickSettingsStyle": { + "modern": "Moderne", + "classic": "Classique", + "compact": "Compact" } }, "osd": { diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index d9b1d538..ca66a0b4 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -85,6 +85,7 @@ "reset-scaling": "Redefinir escala" }, "control-center": { + "title": "Centro de controle", "section": { "label": "Centro de controle", "description": "Configurar o posicionamento e comportamento do painel do centro de controle." @@ -92,6 +93,22 @@ "position": { "label": "Posição", "description": "Escolha onde o painel do centro de controle aparece quando aberto." + }, + "quickSettingsStyle": { + "section": { + "label": "Estilo de configurações rápidas", + "description": "Personalize a aparência e o comportamento das configurações rápidas no centro de controle." + }, + "style": { + "label": "Estilo de configurações rápidas", + "description": "Escolha o estilo visual para os interruptores e controles de configurações rápidas." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configure e gerencie os widgets do centro de controle e suas opções de exibição." + } } } }, @@ -671,6 +688,25 @@ } } }, + "control-center": { + "title": "Centro de controle", + "quickSettingsStyle": { + "section": { + "label": "Estilo de configurações rápidas", + "description": "Personalize a aparência e o comportamento das configurações rápidas no centro de controle." + }, + "style": { + "label": "Estilo de configurações rápidas", + "description": "Escolha o estilo visual para os interruptores e controles de configurações rápidas." + } + }, + "widgets": { + "section": { + "label": "Widgets", + "description": "Configure e gerencie os widgets do centro de controle e suas opções de exibição." + } + } + }, "hooks": { "title": "Hooks", "system-hooks": { @@ -1237,6 +1273,11 @@ "bottom_right": "Inferior direito", "bottom_center": "Centro inferior", "top_center": "Centro superior" + }, + "quickSettingsStyle": { + "modern": "Moderno", + "classic": "Clássico", + "compact": "Compacto" } }, "bar": { diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 8bdfbce4..f5ee975e 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -85,6 +85,7 @@ } }, "control-center": { + "title": "控制中心", "section": { "label": "控制中心", "description": "配置控制中心面板的定位和行为。" @@ -92,6 +93,22 @@ "position": { "label": "位置", "description": "选择控制中心面板打开时出现的位置。" + }, + "quickSettingsStyle": { + "section": { + "label": "快速设置样式", + "description": "自定义控制中心中快速设置的外观和行为。" + }, + "style": { + "label": "快速设置样式", + "description": "选择快速设置开关和控件的视觉样式。" + } + }, + "widgets": { + "section": { + "label": "小部件", + "description": "配置和管理控制中心小部件及其显示选项。" + } } } }, @@ -705,6 +722,25 @@ } } }, + "control-center": { + "title": "控制中心", + "quickSettingsStyle": { + "section": { + "label": "快速设置样式", + "description": "自定义控制中心中快速设置的外观和行为。" + }, + "style": { + "label": "快速设置样式", + "description": "选择快速设置开关和控件的视觉样式。" + } + }, + "widgets": { + "section": { + "label": "小部件", + "description": "配置和管理控制中心小部件及其显示选项。" + } + } + }, "hooks": { "title": "钩子", "system-hooks": { @@ -1238,6 +1274,11 @@ "bottom_right": "右下角", "bottom_center": "底部居中", "top_center": "顶部居中" + }, + "quickSettingsStyle": { + "modern": "现代", + "classic": "经典", + "compact": "紧凑" } }, "osd": { diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml index 6a6a3b16..044f13c8 100644 --- a/Modules/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -33,21 +33,24 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: I18n.tr("settings.controlCenter.quickSettingsStyle.section.label") - description: I18n.tr("settings.controlCenter.quickSettingsStyle.section.description") + label: I18n.tr("settings.control-center.quickSettingsStyle.section.label") + description: I18n.tr("settings.control-center.quickSettingsStyle.section.description") } NComboBox { id: quickSettingsStyle - label: I18n.tr("settings.controlCenter.quickSettingsStyle.style.label") - description: I18n.tr("settings.controlCenter.quickSettingsStyle.style.description") + label: I18n.tr("settings.control-center.quickSettingsStyle.style.label") + description: I18n.tr("settings.control-center.quickSettingsStyle.style.description") Layout.fillWidth: true model: [{ "key": "modern", - "name": I18n.tr("options.controlCenter.quickSettingsStyle.modern") + "name": I18n.tr("options.control-center.quickSettingsStyle.modern") }, { "key": "classic", - "name": I18n.tr("options.controlCenter.quickSettingsStyle.classic") + "name": I18n.tr("options.control-center.quickSettingsStyle.classic") + }, { + "key": "compact", + "name": I18n.tr("options.control-center.quickSettingsStyle.compact") }] currentKey: Settings.data.controlCenter.quickSettingsStyle || "modern" onSelected: function (key) { @@ -68,8 +71,8 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: I18n.tr("settings.controlCenter.widgets.section.label") - description: I18n.tr("settings.controlCenter.widgets.section.description") + label: I18n.tr("settings.control-center.widgets.section.label") + description: I18n.tr("settings.control-center.widgets.section.description") } // Bar Sections diff --git a/Widgets/NQuickSetting.qml b/Widgets/NQuickSetting.qml index 3c199c16..75517718 100644 --- a/Widgets/NQuickSetting.qml +++ b/Widgets/NQuickSetting.qml @@ -15,7 +15,7 @@ Rectangle { property bool enabled: true property bool active: false property bool compact: false - property string style: "modern" // "modern" or "classic" + property string style: "modern" // "modern", "classic", or "compact" // Styling properties property real fontSize: Style.fontSizeS * scaling @@ -24,14 +24,44 @@ Rectangle { property real cornerRadius: Style.radiusM * scaling // Colors - Style-dependent colors - property color backgroundColor: style === "classic" ? Color.mSurfaceVariant : Color.mSurface + property color backgroundColor: { + if (style === "classic") + return Color.mSurfaceVariant + if (style === "compact") + return Color.mSurface + return Color.mSurface + } property color textColor: Color.mOnSurface - property color iconColor: style === "classic" ? Color.mPrimary : (active ? Color.mPrimary : Color.mOnSurface) + property color iconColor: { + if (style === "classic") + return Color.mPrimary + if (style === "compact") + return active ? Color.mPrimary : Color.mOnSurface + return active ? Color.mPrimary : Color.mOnSurface + } property color borderColor: Color.mOutline - property color hoverColor: style === "classic" ? Color.mTertiary : Color.mPrimary - property color pressedColor: style === "classic" ? Color.mTertiary : Qt.darker(Color.mPrimary, 1.1) + property color hoverColor: { + if (style === "classic") + return Color.mTertiary + if (style === "compact") + return Color.mPrimary + return Color.mPrimary + } + property color pressedColor: { + if (style === "classic") + return Color.mTertiary + if (style === "compact") + return Qt.darker(Color.mPrimary, 1.1) + return Qt.darker(Color.mPrimary, 1.1) + } property color hoverTextColor: Color.mOnPrimary - property color hoverIconColor: style === "classic" ? Color.mOnTertiary : Color.mOnPrimary + property color hoverIconColor: { + if (style === "classic") + return Color.mOnTertiary + if (style === "compact") + return Color.mOnPrimary + return Color.mOnPrimary + } // Signals signal clicked @@ -48,17 +78,29 @@ Rectangle { if (style === "classic") { return Style.baseWidgetSize * scaling } + if (style === "compact") { + return Style.baseWidgetSize * 0.8 * scaling + } return compact ? Math.max(100 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) : Math.max(120 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) } implicitHeight: { if (style === "classic") { return Style.baseWidgetSize * scaling } + if (style === "compact") { + return Style.baseWidgetSize * 0.8 * scaling + } return compact ? Math.max(48 * scaling, contentRow.implicitHeight + (Style.marginM * scaling)) : Math.max(56 * scaling, contentRow.implicitHeight + (Style.marginL * scaling)) } // Appearance - Style-dependent styling - radius: style === "classic" ? width * 0.5 : cornerRadius + radius: { + if (style === "classic") + return width * 0.5 + if (style === "compact") + return Style.radiusS * scaling // Smaller radius for compact + return cornerRadius + } color: { if (!enabled) return Qt.lighter(Color.mSurface, 1.1) @@ -69,12 +111,21 @@ Rectangle { return backgroundColor } - border.width: style === "classic" ? Math.max(1, Style.borderS * scaling) : 0 - border.color: style === "classic" ? borderColor : "transparent" + border.width: { + if (style === "classic") + return Math.max(1, Style.borderS * scaling) + if (style === "compact") + return 0 + return 0 + } + border.color: { + if (style === "classic") + return borderColor + return "transparent" + } opacity: enabled ? (style === "classic" ? Style.opacityFull : 1.0) : (style === "classic" ? Style.opacityMedium : 0.6) - // Smooth animations Behavior on color { ColorAnimation { duration: style === "classic" ? Style.animationNormal : Style.animationFast @@ -120,7 +171,7 @@ Rectangle { id: contentRow anchors.centerIn: parent spacing: Style.marginXXS * scaling - visible: root.style !== "classic" + visible: root.style !== "classic" && root.style !== "compact" // Icon NIcon { @@ -169,6 +220,29 @@ Rectangle { } } + // Compact style - icon only, small square button + NIcon { + id: compactIcon + anchors.centerIn: parent + visible: root.style === "compact" && root.icon !== "" + icon: root.icon + pointSize: Style.fontSizeM * scaling // Smaller icon for compact + color: { + if (!root.enabled) + return Color.mOnSurfaceVariant + if (root.hovered) + return root.hoverIconColor + return root.iconColor + } + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + easing.type: Easing.OutCubic + } + } + } + // Classic style - EXACTLY like NIconButton (icon + text) RowLayout { anchors.centerIn: parent @@ -217,7 +291,6 @@ Rectangle { } } - // Mouse interaction with enhanced feedback MouseArea { id: mouseArea anchors.fill: parent @@ -271,7 +344,6 @@ Rectangle { } } - // Ripple effect for M3-style interaction feedback Rectangle { id: ripple anchors.fill: parent @@ -306,7 +378,6 @@ Rectangle { } } - // Trigger ripple effect on click Connections { target: root function onClicked() { @@ -315,7 +386,6 @@ Rectangle { } } - // Clean up ripple after animation Connections { target: rippleAnimation function onFinished() { From 7dbb3deeeaeb11fc1f3794ffdf4fb015fe9cdf11 Mon Sep 17 00:00:00 2001 From: lysec Date: Thu, 9 Oct 2025 15:48:23 +0200 Subject: [PATCH 06/16] QuickSettings: compact version uses 4 per row --- Modules/ControlCenter/Cards/TopCard.qml | 2 +- Modules/ControlCenter/ControlCenterPanel.qml | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index 51aeb619..643200e2 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -105,7 +105,7 @@ NBox { GridLayout { id: grid Layout.fillWidth: true - columns: 3 + columns: (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 columnSpacing: Style.marginM * scaling rowSpacing: Style.marginS * scaling diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 2e8d5375..014c9a88 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -16,12 +16,16 @@ NPanel { readonly property int bottomHeight: Math.round(Math.max(196 * scaling)) readonly property int topHeight: { - const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / 3) + const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 + const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / columns) var buttonHeight; if (Settings.data.controlCenter.quickSettingsStyle === "classic") { buttonHeight = Style.baseWidgetSize } + else if (Settings.data.controlCenter.quickSettingsStyle === "compact") { + buttonHeight = Style.baseWidgetSize * 0.8 // Smaller for compact + } else { buttonHeight = 56 } From bfb57f13c60ad615e09fb288411ee1fa3515c8a8 Mon Sep 17 00:00:00 2001 From: lysec Date: Thu, 9 Oct 2025 15:59:33 +0200 Subject: [PATCH 07/16] Settings: edit default bar & quick access Autoformat --- Commons/Settings.qml | 12 ++++++------ Modules/ControlCenter/ControlCenterPanel.qml | 10 ++++------ Modules/Settings/Tabs/ControlCenterTab.qml | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 8ab90c93..ae0a17cb 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -162,10 +162,6 @@ Singleton { "id": "Tray" }, { "id": "NotificationHistory" - }, { - "id": "WiFi" - }, { - "id": "Bluetooth" }, { "id": "Battery" }, { @@ -246,13 +242,17 @@ Singleton { property JsonObject controlCenter: JsonObject { // Position: close_to_bar_button, center, top_left, top_right, bottom_left, bottom_right, bottom_center, top_center property string position: "close_to_bar_button" - property string quickSettingsStyle: "modern" // "modern" or "classic" + property string quickSettingsStyle: "compact" // "modern", "classic", or "compact" property JsonObject widgets widgets: JsonObject { property list quickSettings: [{ + "id": "WiFi" + }, { "id": "Bluetooth" }, { - "id": "WiFi" + "id": "DoNotDisturb" + }, { + "id": "ScreenRecorder" }, { "id": "PowerProfile" }] diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 014c9a88..4f76e029 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -11,7 +11,7 @@ NPanel { id: root preferredWidth: 440 - preferredHeight: topHeight + bottomHeight + Math.round(Style.marginL * scaling * 3) + preferredHeight: topHeight + bottomHeight + Math.round(Style.marginL * scaling * 3) panelKeyboardFocus: true readonly property int bottomHeight: Math.round(Math.max(196 * scaling)) @@ -19,14 +19,12 @@ NPanel { const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / columns) - var buttonHeight; + var buttonHeight if (Settings.data.controlCenter.quickSettingsStyle === "classic") { buttonHeight = Style.baseWidgetSize - } - else if (Settings.data.controlCenter.quickSettingsStyle === "compact") { + } else if (Settings.data.controlCenter.quickSettingsStyle === "compact") { buttonHeight = Style.baseWidgetSize * 0.8 // Smaller for compact - } - else { + } else { buttonHeight = 56 } diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml index 044f13c8..fbc968f9 100644 --- a/Modules/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -52,7 +52,7 @@ ColumnLayout { "key": "compact", "name": I18n.tr("options.control-center.quickSettingsStyle.compact") }] - currentKey: Settings.data.controlCenter.quickSettingsStyle || "modern" + currentKey: Settings.data.controlCenter.quickSettingsStyle || "compact" onSelected: function (key) { Settings.data.controlCenter.quickSettingsStyle = key } From 075c8f08f6eeccf4b8ea602ac6a7cc4a5e407870 Mon Sep 17 00:00:00 2001 From: lysec Date: Thu, 9 Oct 2025 17:56:49 +0200 Subject: [PATCH 08/16] quicksettings: replace hardcoded text with i18n, edit label & tooltip, force hover when recording --- Assets/Translations/de.json | 118 ++++++++++++- Assets/Translations/en.json | 75 ++++++++ Assets/Translations/es.json | 118 ++++++++++++- Assets/Translations/fr.json | 162 +++++++++++++++++- Assets/Translations/pt.json | 118 ++++++++++++- Assets/Translations/zh-CN.json | 118 ++++++++++++- Assets/settings-default.json | 2 +- Commons/I18n.qml | 18 +- Commons/Settings.qml | 2 +- Modules/ControlCenter/Widgets/Bluetooth.qml | 4 +- Modules/ControlCenter/Widgets/KeepAwake.qml | 4 +- Modules/ControlCenter/Widgets/NightLight.qml | 12 +- .../{DoNotDisturb.qml => Notifications.qml} | 7 +- .../ControlCenter/Widgets/PowerProfile.qml | 4 +- .../ControlCenter/Widgets/ScreenRecorder.qml | 8 +- .../Widgets/WallpaperSelector.qml | 4 +- Modules/ControlCenter/Widgets/WiFi.qml | 25 ++- Modules/Settings/Tabs/ControlCenterTab.qml | 2 +- Services/ControlCenterWidgetRegistry.qml | 6 +- 19 files changed, 754 insertions(+), 53 deletions(-) rename Modules/ControlCenter/Widgets/{DoNotDisturb.qml => Notifications.qml} (51%) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index eb2f15ce..6f530c47 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -744,8 +744,52 @@ "description": "Konfigurieren und verwalten Sie Kontrollzentrum-Widgets und deren Anzeigeoptionen." } } + }, + "quickSettings": { + "notifications": { + "label": "Benachrichtigungen", + "tooltip": { + "enable": "Nicht stören aktivieren", + "disable": "Nicht stören deaktivieren" + } }, - "hooks": { + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Netzwerk" + }, + "tooltip": { + "wifi": { + "connected": "Wi-Fi verbunden", + "disconnected": "Wi-Fi getrennt" + }, + "ethernet": { + "connected": "Ethernet verbunden" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth aktiviert", + "disabled": "Bluetooth deaktiviert" + } + }, + "screenRecorder": { + "label": "Bildschirm", + "tooltip": { + "start": "Bildschirmaufnahme starten", + "stop": "Aufnahme beenden" + } + }, + "powerProfile": { + "tooltip": { + "current": "Aktuell: {profile}", + "unavailable": "Energieprofile nicht verfügbar" + } + } + }, + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1432,6 +1476,78 @@ "restart": "Neu starten", "suspend": "Ruhezustand" }, + "quickSettings": { + "notifications": { + "label": { + "enabled": "Benachrichtigungen", + "disabled": "Nicht stören" + }, + "tooltip": { + "action": "Linksklick: Benachrichtigungsverlauf öffnen\nRechtsklick: Nicht stören umschalten" + } + }, + "screenRecorder": { + "label": { + "recording": "Stopp", + "stopped": "Aufnehmen" + }, + "tooltip": { + "action": "Klicken zum Starten/Stoppen der Bildschirmaufnahme" + } + }, + "powerProfile": { + "label": { + "unavailable": "Energieprofil" + }, + "tooltip": { + "action": "Klicken zum Wechseln des Energieprofils" + } + }, + "wifi": { + "label": { + "ethernet": "Ethernet", + "wifi": "Wi-Fi", + "disconnected": "Wi-Fi getrennt" + }, + "tooltip": { + "action": "Klicken zum Verwalten der Wi-Fi-Verbindungen" + } + }, + "bluetooth": { + "label": { + "enabled": "Bluetooth", + "disabled": "Bluetooth" + }, + "tooltip": { + "action": "Klicken zum Verwalten der Bluetooth-Geräte" + } + }, + "nightLight": { + "label": { + "enabled": "Nachtlicht", + "forced": "Nachtlicht", + "disabled": "Nachtlicht" + }, + "tooltip": { + "action": "Klicken zum Wechseln des Nachtlicht-Modus\nRechtsklick: Einstellungen öffnen" + } + }, + "wallpaperSelector": { + "label": "Hintergrundbild", + "tooltip": { + "action": "Linksklick: Hintergrundbildauswahl öffnen\nRechtsklick: Zufälliges Hintergrundbild setzen" + } + }, + "keepAwake": { + "label": { + "enabled": "Wach halten", + "disabled": "Wach halten" + }, + "tooltip": { + "action": "Klicken zum Umschalten des Wach-halten-Modus" + } + } + }, "toast": { "night-light": { "enabled": "Aktiviert", diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 4d7e9b13..b9dd76b7 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -741,6 +741,9 @@ "label": "Widgets", "description": "Configure and manage Control Center widgets and their display options." } + }, + "quickSettings": { + "sectionName": "Quick Settings" } }, "hooks": { @@ -1403,6 +1406,78 @@ "restart": "Restart", "suspend": "Suspend" }, + "quickSettings": { + "notifications": { + "label": { + "enabled": "Notifications", + "disabled": "Do Not Disturb" + }, + "tooltip": { + "action": "Left click: Open notification history\nRight click: Toggle Do Not Disturb" + } + }, + "screenRecorder": { + "label": { + "recording": "Stop", + "stopped": "Record" + }, + "tooltip": { + "action": "Click to start/stop screen recording" + } + }, + "powerProfile": { + "label": { + "unavailable": "Power Profile" + }, + "tooltip": { + "action": "Click to cycle power profile" + } + }, + "wifi": { + "label": { + "ethernet": "Ethernet", + "wifi": "Wi-Fi", + "disconnected": "Wi-Fi Disconnected" + }, + "tooltip": { + "action": "Click to manage Wi-Fi connections" + } + }, + "bluetooth": { + "label": { + "enabled": "Bluetooth", + "disabled": "Bluetooth" + }, + "tooltip": { + "action": "Click to manage Bluetooth devices" + } + }, + "nightLight": { + "label": { + "enabled": "Night Light", + "forced": "Night Light", + "disabled": "Night Light" + }, + "tooltip": { + "action": "Click to cycle Night Light mode\nRight click: Open settings" + } + }, + "wallpaperSelector": { + "label": "Wallpaper", + "tooltip": { + "action": "Left click: Open wallpaper selector\nRight click: Set random wallpaper" + } + }, + "keepAwake": { + "label": { + "enabled": "Keep Awake", + "disabled": "Keep Awake" + }, + "tooltip": { + "action": "Click to toggle keep awake mode" + } + } + }, "toast": { "night-light": { "enabled": "Enabled", diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 5b904ade..c7e094ca 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -740,8 +740,52 @@ "description": "Configura y gestiona los widgets del centro de control y sus opciones de visualización." } } + }, + "quickSettings": { + "notifications": { + "label": "Notificaciones", + "tooltip": { + "enable": "Activar No molestar", + "disable": "Desactivar No molestar" + } }, - "hooks": { + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Red" + }, + "tooltip": { + "wifi": { + "connected": "Wi-Fi conectado", + "disconnected": "Wi-Fi desconectado" + }, + "ethernet": { + "connected": "Ethernet conectado" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth habilitado", + "disabled": "Bluetooth deshabilitado" + } + }, + "screenRecorder": { + "label": "Pantalla", + "tooltip": { + "start": "Iniciar grabación de pantalla", + "stop": "Detener grabación" + } + }, + "powerProfile": { + "tooltip": { + "current": "Actual: {profile}", + "unavailable": "Perfiles de energía no disponibles" + } + } + }, + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1400,6 +1444,78 @@ "restart": "Reiniciar", "suspend": "Suspender" }, + "quickSettings": { + "notifications": { + "label": { + "enabled": "Notificaciones", + "disabled": "No molestar" + }, + "tooltip": { + "action": "Clic izquierdo: Abrir historial de notificaciones\nClic derecho: Alternar No molestar" + } + }, + "screenRecorder": { + "label": { + "recording": "Detener", + "stopped": "Grabar" + }, + "tooltip": { + "action": "Hacer clic para iniciar/detener la grabación de pantalla" + } + }, + "powerProfile": { + "label": { + "unavailable": "Perfil de energía" + }, + "tooltip": { + "action": "Hacer clic para cambiar el perfil de energía" + } + }, + "wifi": { + "label": { + "ethernet": "Ethernet", + "wifi": "Wi-Fi", + "disconnected": "Wi-Fi desconectado" + }, + "tooltip": { + "action": "Hacer clic para gestionar las conexiones Wi-Fi" + } + }, + "bluetooth": { + "label": { + "enabled": "Bluetooth", + "disabled": "Bluetooth" + }, + "tooltip": { + "action": "Hacer clic para gestionar los dispositivos Bluetooth" + } + }, + "nightLight": { + "label": { + "enabled": "Luz nocturna", + "forced": "Luz nocturna", + "disabled": "Luz nocturna" + }, + "tooltip": { + "action": "Hacer clic para alternar el modo Luz nocturna\nClic derecho: Abrir configuración" + } + }, + "wallpaperSelector": { + "label": "Fondo de pantalla", + "tooltip": { + "action": "Clic izquierdo: Abrir selector de fondo de pantalla\nClic derecho: Establecer fondo de pantalla aleatorio" + } + }, + "keepAwake": { + "label": { + "enabled": "Mantener despierto", + "disabled": "Mantener despierto" + }, + "tooltip": { + "action": "Hacer clic para alternar el modo Mantener despierto" + } + } + }, "toast": { "night-light": { "enabled": "Activada", diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index aab3dd41..1a659cb7 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -741,7 +741,95 @@ } } }, - "hooks": { + "quickSettings": { + "notifications": { + "label": "Notifications", + "tooltip": { + "enable": "Activer Ne pas déranger", + "disable": "Désactiver Ne pas déranger" + } + }, + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Réseau" + }, + "tooltip": { + "wifi": { + "connected": "Wi-Fi connecté", + "disconnected": "Wi-Fi déconnecté" + }, + "ethernet": { + "connected": "Ethernet connecté" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth activé", + "disabled": "Bluetooth désactivé" + } + }, + "screenRecorder": { + "label": "Écran", + "tooltip": { + "start": "Démarrer l'enregistrement d'écran", + "stop": "Arrêter l'enregistrement" + } + }, + "powerProfile": { + "tooltip": { + "current": "Actuel : {profile}", + "unavailable": "Profils d'alimentation non disponibles" + } + } + }, + "quickSettings": { + "notifications": { + "label": "Notifications", + "tooltip": { + "enable": "Activer Ne pas déranger", + "disable": "Désactiver Ne pas déranger" + } + }, + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Réseau" + }, + "tooltip": { + "wifi": { + "connected": "Wi-Fi connecté", + "disconnected": "Wi-Fi déconnecté" + }, + "ethernet": { + "connected": "Ethernet connecté" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth activé", + "disabled": "Bluetooth désactivé" + } + }, + "screenRecorder": { + "label": "Écran", + "tooltip": { + "start": "Démarrer l'enregistrement d'écran", + "stop": "Arrêter l'enregistrement" + } + }, + "powerProfile": { + "tooltip": { + "current": "Actuel : {profile}", + "unavailable": "Profils d'alimentation non disponibles" + } + } + }, + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1400,6 +1488,78 @@ "restart": "Redémarrer", "suspend": "Mettre en veille" }, + "quickSettings": { + "notifications": { + "label": { + "enabled": "Notifications", + "disabled": "Ne pas déranger" + }, + "tooltip": { + "action": "Clic gauche : Ouvrir l'historique des notifications\nClic droit : Basculer Ne pas déranger" + } + }, + "screenRecorder": { + "label": { + "recording": "Arrêter", + "stopped": "Enregistrer" + }, + "tooltip": { + "action": "Cliquer pour démarrer/arrêter l'enregistrement d'écran" + } + }, + "powerProfile": { + "label": { + "unavailable": "Profil d'alimentation" + }, + "tooltip": { + "action": "Cliquer pour changer de profil d'alimentation" + } + }, + "wifi": { + "label": { + "ethernet": "Ethernet", + "wifi": "Wi-Fi", + "disconnected": "Wi-Fi déconnecté" + }, + "tooltip": { + "action": "Cliquer pour gérer les connexions Wi-Fi" + } + }, + "bluetooth": { + "label": { + "enabled": "Bluetooth", + "disabled": "Bluetooth" + }, + "tooltip": { + "action": "Cliquer pour gérer les appareils Bluetooth" + } + }, + "nightLight": { + "label": { + "enabled": "Lumière nocturne", + "forced": "Lumière nocturne", + "disabled": "Lumière nocturne" + }, + "tooltip": { + "action": "Cliquer pour basculer le mode Lumière nocturne\nClic droit : Ouvrir les paramètres" + } + }, + "wallpaperSelector": { + "label": "Fond d'écran", + "tooltip": { + "action": "Clic gauche : Ouvrir le sélecteur de fond d'écran\nClic droit : Définir un fond d'écran aléatoire" + } + }, + "keepAwake": { + "label": { + "enabled": "Rester éveillé", + "disabled": "Rester éveillé" + }, + "tooltip": { + "action": "Cliquer pour basculer le mode Rester éveillé" + } + } + }, "toast": { "night-light": { "enabled": "Activé", diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index ca66a0b4..4dcb10c7 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -706,8 +706,52 @@ "description": "Configure e gerencie os widgets do centro de controle e suas opções de exibição." } } + }, + "quickSettings": { + "notifications": { + "label": "Notificações", + "tooltip": { + "enable": "Ativar Não perturbe", + "disable": "Desativar Não perturbe" + } }, - "hooks": { + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Rede" + }, + "tooltip": { + "wifi": { + "connected": "Wi-Fi conectado", + "disconnected": "Wi-Fi desconectado" + }, + "ethernet": { + "connected": "Ethernet conectado" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth habilitado", + "disabled": "Bluetooth desabilitado" + } + }, + "screenRecorder": { + "label": "Tela", + "tooltip": { + "start": "Iniciar gravação de tela", + "stop": "Parar gravação" + } + }, + "powerProfile": { + "tooltip": { + "current": "Atual: {profile}", + "unavailable": "Perfis de energia não disponíveis" + } + } + }, + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1400,6 +1444,78 @@ "restart": "Reiniciar", "suspend": "Suspender" }, + "quickSettings": { + "notifications": { + "label": { + "enabled": "Notificações", + "disabled": "Não perturbar" + }, + "tooltip": { + "action": "Clique esquerdo: Abrir histórico de notificações\nClique direito: Alternar Não perturbar" + } + }, + "screenRecorder": { + "label": { + "recording": "Parar", + "stopped": "Gravar" + }, + "tooltip": { + "action": "Clique para iniciar/parar a gravação da tela" + } + }, + "powerProfile": { + "label": { + "unavailable": "Perfil de energia" + }, + "tooltip": { + "action": "Clique para alternar o perfil de energia" + } + }, + "wifi": { + "label": { + "ethernet": "Ethernet", + "wifi": "Wi-Fi", + "disconnected": "Wi-Fi desconectado" + }, + "tooltip": { + "action": "Clique para gerenciar conexões Wi-Fi" + } + }, + "bluetooth": { + "label": { + "enabled": "Bluetooth", + "disabled": "Bluetooth" + }, + "tooltip": { + "action": "Clique para gerenciar dispositivos Bluetooth" + } + }, + "nightLight": { + "label": { + "enabled": "Luz noturna", + "forced": "Luz noturna", + "disabled": "Luz noturna" + }, + "tooltip": { + "action": "Clique para alternar o modo Luz noturna\nClique direito: Abrir configurações" + } + }, + "wallpaperSelector": { + "label": "Papel de parede", + "tooltip": { + "action": "Clique esquerdo: Abrir seletor de papel de parede\nClique direito: Definir papel de parede aleatório" + } + }, + "keepAwake": { + "label": { + "enabled": "Manter acordado", + "disabled": "Manter acordado" + }, + "tooltip": { + "action": "Clique para alternar o modo Manter acordado" + } + } + }, "toast": { "night-light": { "enabled": "Ativada", diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index f5ee975e..6b21676c 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -740,8 +740,52 @@ "description": "配置和管理控制中心小部件及其显示选项。" } } + }, + "quickSettings": { + "notifications": { + "label": "通知", + "tooltip": { + "enable": "开启勿扰模式", + "disable": "关闭勿扰模式" + } }, - "hooks": { + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "网络" + }, + "tooltip": { + "wifi": { + "connected": "Wi-Fi 已连接", + "disconnected": "Wi-Fi 已断开" + }, + "ethernet": { + "connected": "以太网已连接" + } + } + }, + "bluetooth": { + "label": "蓝牙", + "tooltip": { + "enabled": "蓝牙已启用", + "disabled": "蓝牙已禁用" + } + }, + "screenRecorder": { + "label": "屏幕录制", + "tooltip": { + "start": "开始屏幕录制", + "stop": "停止录制" + } + }, + "powerProfile": { + "tooltip": { + "current": "当前:{profile}", + "unavailable": "电源配置文件不可用" + } + } + }, + "hooks": { "title": "钩子", "system-hooks": { "section": { @@ -1400,6 +1444,78 @@ "restart": "重启", "suspend": "挂起" }, + "quickSettings": { + "notifications": { + "label": { + "enabled": "通知", + "disabled": "勿扰模式" + }, + "tooltip": { + "action": "左键:打开通知历史\n右键:切换勿扰模式" + } + }, + "screenRecorder": { + "label": { + "recording": "停止", + "stopped": "录制" + }, + "tooltip": { + "action": "点击开始/停止屏幕录制" + } + }, + "powerProfile": { + "label": { + "unavailable": "电源模式" + }, + "tooltip": { + "action": "点击切换电源模式" + } + }, + "wifi": { + "label": { + "ethernet": "以太网", + "wifi": "Wi-Fi", + "disconnected": "Wi-Fi 已断开" + }, + "tooltip": { + "action": "点击管理 Wi-Fi 连接" + } + }, + "bluetooth": { + "label": { + "enabled": "蓝牙", + "disabled": "蓝牙" + }, + "tooltip": { + "action": "点击管理蓝牙设备" + } + }, + "nightLight": { + "label": { + "enabled": "夜间模式", + "forced": "夜间模式", + "disabled": "夜间模式" + }, + "tooltip": { + "action": "点击切换夜间模式\n右键:打开设置" + } + }, + "wallpaperSelector": { + "label": "壁纸", + "tooltip": { + "action": "左键:打开壁纸选择器\n右键:设置随机壁纸" + } + }, + "keepAwake": { + "label": { + "enabled": "保持唤醒", + "disabled": "保持唤醒" + }, + "tooltip": { + "action": "点击切换保持唤醒模式" + } + } + }, "toast": { "night-light": { "enabled": "已启用", diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 05675bd4..fd3707c4 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -123,7 +123,7 @@ "id": "Bluetooth" }, { - "id": "DoNotDisturb" + "id": "Notifications" }, { "id": "NightLight" diff --git a/Commons/I18n.qml b/Commons/I18n.qml index 3a013c57..11180047 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -54,6 +54,9 @@ Singleton { var data = JSON.parse(text()) root.translations = data Logger.log("I18n", `Loaded translations for "${root.langCode}"`) + if (debug) { + Logger.log("I18n", `Available root keys: ${Object.keys(data).join(", ")}`) + } root.isLoaded = true root.translationsLoaded() @@ -279,9 +282,9 @@ Singleton { interpolations = {} if (!isLoaded) { - // if (debug) { - // Logger.warn("I18n", "Translations not loaded yet") - // } + if (debug) { + Logger.warn("I18n", "Translations not loaded yet") + } return key } @@ -291,12 +294,19 @@ Singleton { // Look-up translation in the active language var value = translations var notFound = false + if (debug) { + Logger.log("I18n", `Looking up key: "${key}"`) + } for (var i = 0; i < keys.length; i++) { if (value && typeof value === "object" && keys[i] in value) { value = value[keys[i]] + if (debug) { + Logger.log("I18n", `Found key part "${keys[i]}"`) + } } else { if (debug) { - Logger.warn("I18n", `Translation key "${key}" not found`) + Logger.warn("I18n", `Translation key "${key}" not found at part "${keys[i]}"`) + Logger.warn("I18n", `Available keys: ${Object.keys(value || {}).join(", ")}`) } notFound = true break diff --git a/Commons/Settings.qml b/Commons/Settings.qml index ae0a17cb..ffe9039a 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -250,7 +250,7 @@ Singleton { }, { "id": "Bluetooth" }, { - "id": "DoNotDisturb" + "id": "Notifications" }, { "id": "ScreenRecorder" }, { diff --git a/Modules/ControlCenter/Widgets/Bluetooth.qml b/Modules/ControlCenter/Widgets/Bluetooth.qml index 9b1cd17d..e44d9844 100644 --- a/Modules/ControlCenter/Widgets/Bluetooth.qml +++ b/Modules/ControlCenter/Widgets/Bluetooth.qml @@ -8,12 +8,12 @@ NQuickSetting { property ShellScreen screen property real scaling: 1.0 - text: "Bluetooth" + text: I18n.tr("quickSettings.bluetooth.label.enabled") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" active: BluetoothService.enabled - tooltipText: BluetoothService.enabled ? "Bluetooth enabled" : "Bluetooth disabled" + tooltipText: I18n.tr("quickSettings.bluetooth.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) diff --git a/Modules/ControlCenter/Widgets/KeepAwake.qml b/Modules/ControlCenter/Widgets/KeepAwake.qml index a254f8df..e384272a 100644 --- a/Modules/ControlCenter/Widgets/KeepAwake.qml +++ b/Modules/ControlCenter/Widgets/KeepAwake.qml @@ -8,12 +8,12 @@ NQuickSetting { property ShellScreen screen property real scaling: 1.0 - text: "Keep-awake" + text: I18n.tr("quickSettings.keepAwake.label.enabled") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" active: IdleInhibitorService.isInhibited - tooltipText: IdleInhibitorService.isInhibited ? "Disable keep-awake" : "Enable keep-awake" + tooltipText: I18n.tr("quickSettings.keepAwake.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" onClicked: IdleInhibitorService.manualToggle() diff --git a/Modules/ControlCenter/Widgets/NightLight.qml b/Modules/ControlCenter/Widgets/NightLight.qml index 21077f37..a2d6bfc1 100644 --- a/Modules/ControlCenter/Widgets/NightLight.qml +++ b/Modules/ControlCenter/Widgets/NightLight.qml @@ -9,21 +9,13 @@ NQuickSetting { property real scaling: 1.0 enabled: ProgramCheckerService.wlsunsetAvailable - text: "Night Light" + text: I18n.tr("quickSettings.nightLight.label.enabled") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" active: Settings.data.nightLight.enabled style: Settings.data.controlCenter.quickSettingsStyle || "modern" - tooltipText: { - if (!Settings.data.nightLight.enabled) { - return "Turn on Night Light" - } else if (Settings.data.nightLight.forced) { - return "Night Light forced on" - } else { - return "Turn off Night Light" - } - } + tooltipText: I18n.tr("quickSettings.nightLight.tooltip.action") onClicked: { if (!Settings.data.nightLight.enabled) { diff --git a/Modules/ControlCenter/Widgets/DoNotDisturb.qml b/Modules/ControlCenter/Widgets/Notifications.qml similarity index 51% rename from Modules/ControlCenter/Widgets/DoNotDisturb.qml rename to Modules/ControlCenter/Widgets/Notifications.qml index cc2a1d1a..131db7f9 100644 --- a/Modules/ControlCenter/Widgets/DoNotDisturb.qml +++ b/Modules/ControlCenter/Widgets/Notifications.qml @@ -8,13 +8,14 @@ NQuickSetting { property ShellScreen screen property real scaling: 1.0 - text: "Do not Disturb" + text: Settings.data.notifications.doNotDisturb ? I18n.tr("quickSettings.notifications.label.disabled") : I18n.tr("quickSettings.notifications.label.enabled") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" active: Settings.data.notifications.doNotDisturb - tooltipText: Settings.data.notifications.doNotDisturb ? "Turn off Do Not Disturb" : "Turn on Do Not Disturb" + tooltipText: I18n.tr("quickSettings.notifications.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" - onClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb + onClicked: PanelService.getPanel("notificationHistoryPanel")?.toggle(this) + onRightClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb } diff --git a/Modules/ControlCenter/Widgets/PowerProfile.qml b/Modules/ControlCenter/Widgets/PowerProfile.qml index 2636d40e..1c57f9fa 100644 --- a/Modules/ControlCenter/Widgets/PowerProfile.qml +++ b/Modules/ControlCenter/Widgets/PowerProfile.qml @@ -12,12 +12,12 @@ NQuickSetting { readonly property bool hasPP: PowerProfileService.available enabled: hasPP - text: PowerProfileService.getName() + text: hasPP ? PowerProfileService.getName() : I18n.tr("quickSettings.powerProfile.label.unavailable") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: PowerProfileService.getIcon() active: hasPP - tooltipText: hasPP ? "Current: " + PowerProfileService.getName() : "Power profiles not available" + tooltipText: I18n.tr("quickSettings.powerProfile.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" onClicked: { diff --git a/Modules/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/ControlCenter/Widgets/ScreenRecorder.qml index 0523bf7e..a9560bdf 100644 --- a/Modules/ControlCenter/Widgets/ScreenRecorder.qml +++ b/Modules/ControlCenter/Widgets/ScreenRecorder.qml @@ -10,13 +10,17 @@ NQuickSetting { enabled: ProgramCheckerService.gpuScreenRecorderAvailable icon: "camera-video" - text: "Screen Rec." + text: ScreenRecorderService.isRecording ? I18n.tr("quickSettings.screenRecorder.label.recording") : I18n.tr("quickSettings.screenRecorder.label.stopped") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium active: ScreenRecorderService.isRecording - tooltipText: ScreenRecorderService.isRecording ? "Stop recording" : "Start screen recording" + tooltipText: I18n.tr("quickSettings.screenRecorder.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" + // Force hover state when recording to get hover colors + property bool originalHovered: hovered + hovered: ScreenRecorderService.isRecording || originalHovered + onClicked: { ScreenRecorderService.toggleRecording() if (!ScreenRecorderService.isRecording) { diff --git a/Modules/ControlCenter/Widgets/WallpaperSelector.qml b/Modules/ControlCenter/Widgets/WallpaperSelector.qml index 9ec4db51..a4639383 100644 --- a/Modules/ControlCenter/Widgets/WallpaperSelector.qml +++ b/Modules/ControlCenter/Widgets/WallpaperSelector.qml @@ -10,11 +10,11 @@ NQuickSetting { enabled: Settings.data.wallpaper.enabled icon: "wallpaper-selector" - text: "Wallpaper" + text: I18n.tr("quickSettings.wallpaperSelector.label") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium active: Settings.data.wallpaper.enabled - tooltipText: "Open wallpaper selector" + tooltipText: I18n.tr("quickSettings.wallpaperSelector.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" onClicked: PanelService.getPanel("wallpaperPanel")?.toggle(this) diff --git a/Modules/ControlCenter/Widgets/WiFi.qml b/Modules/ControlCenter/Widgets/WiFi.qml index 30a4f635..9d896a5c 100644 --- a/Modules/ControlCenter/Widgets/WiFi.qml +++ b/Modules/ControlCenter/Widgets/WiFi.qml @@ -31,9 +31,16 @@ NQuickSetting { text: { if (NetworkService.ethernetConnected) { - return "Network" + return I18n.tr("quickSettings.wifi.label.ethernet") } - return "Wi-Fi" + let connected = false + for (const net in NetworkService.networks) { + if (NetworkService.networks[net].connected) { + connected = true + break + } + } + return connected ? I18n.tr("quickSettings.wifi.label.wifi") : I18n.tr("quickSettings.wifi.label.disconnected") } fontSize: Style.fontSizeS * scaling @@ -56,19 +63,7 @@ NQuickSetting { } } - tooltipText: { - if (NetworkService.ethernetConnected) { - return "Ethernet connected" - } - let connected = false - for (const net in NetworkService.networks) { - if (NetworkService.networks[net].connected) { - connected = true - break - } - } - return connected ? "Wi-Fi connected" : "Wi-Fi disconnected" - } + tooltipText: I18n.tr("quickSettings.wifi.tooltip.action") onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) } diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml index fbc968f9..8b7fe265 100644 --- a/Modules/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -84,7 +84,7 @@ ColumnLayout { // Quick Settings SectionEditor { - sectionName: "Quick Settings" + sectionName: I18n.tr("settings.control-center.quickSettings.sectionName") sectionId: "quickSettings" settingsDialogComponent: "" widgetRegistry: ControlCenterWidgetRegistry diff --git a/Services/ControlCenterWidgetRegistry.qml b/Services/ControlCenterWidgetRegistry.qml index 4ed3d2ae..ce2fcbf1 100644 --- a/Services/ControlCenterWidgetRegistry.qml +++ b/Services/ControlCenterWidgetRegistry.qml @@ -11,7 +11,7 @@ Singleton { // Widget registry object mapping widget names to components property var widgets: ({ "Bluetooth": bluetoothComponent, - "DoNotDisturb": doNotDisturbComponent, + "Notifications": notificationsComponent, "KeepAwake": keepAwakeComponent, "NightLight": nightLightComponent, "PowerProfile": powerProfileComponent, @@ -26,8 +26,8 @@ Singleton { property Component bluetoothComponent: Component { Bluetooth {} } - property Component doNotDisturbComponent: Component { - DoNotDisturb {} + property Component notificationsComponent: Component { + Notifications {} } property Component keepAwakeComponent: Component { KeepAwake {} From 0989601dbcdf79e3ead3256af9b9d727045f103b Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 17:31:42 -0400 Subject: [PATCH 09/16] Fixed a bunch of scaling issue in bar NIconButtons --- Modules/Bar/Widgets/Bluetooth.qml | 3 ++- Modules/Bar/Widgets/ControlCenter.qml | 3 ++- Modules/Bar/Widgets/CustomButton.qml | 2 +- Modules/Bar/Widgets/DarkMode.qml | 3 ++- Modules/Bar/Widgets/KeepAwake.qml | 3 ++- Modules/Bar/Widgets/NightLight.qml | 3 ++- Modules/Bar/Widgets/NotificationHistory.qml | 3 ++- Modules/Bar/Widgets/PowerProfile.qml | 3 ++- Modules/Bar/Widgets/ScreenRecorder.qml | 3 ++- Modules/Bar/Widgets/SessionMenu.qml | 1 + Modules/Bar/Widgets/Spacer.qml | 2 +- Modules/Bar/Widgets/WallpaperSelector.qml | 3 ++- Modules/Bar/Widgets/WiFi.qml | 3 ++- Widgets/NIconButton.qml | 1 + 14 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml index 21fe96c7..520455e4 100644 --- a/Modules/Bar/Widgets/Bluetooth.qml +++ b/Modules/Bar/Widgets/Bluetooth.qml @@ -10,7 +10,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/ControlCenter.qml b/Modules/Bar/Widgets/ControlCenter.qml index 5fbe7282..993e2f0b 100644 --- a/Modules/Bar/Widgets/ControlCenter.qml +++ b/Modules/Bar/Widgets/ControlCenter.qml @@ -9,7 +9,8 @@ import qs.Services NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen // Widget properties passed from Bar.qml for per-instance settings property string widgetId: "" diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 3973b4cd..11a1b7d6 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -12,7 +12,7 @@ Item { id: root // Widget properties passed from Bar.qml - property var screen + property ShellScreen screen property real scaling: 1.0 // Widget properties passed from Bar.qml for per-instance settings diff --git a/Modules/Bar/Widgets/DarkMode.qml b/Modules/Bar/Widgets/DarkMode.qml index 1333da05..13998414 100644 --- a/Modules/Bar/Widgets/DarkMode.qml +++ b/Modules/Bar/Widgets/DarkMode.qml @@ -6,7 +6,8 @@ import qs.Services NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen icon: "dark-mode" tooltipText: Settings.data.colorSchemes.darkMode ? I18n.tr("tooltips.switch-to-light-mode") : I18n.tr("tooltips.switch-to-dark-mode") diff --git a/Modules/Bar/Widgets/KeepAwake.qml b/Modules/Bar/Widgets/KeepAwake.qml index 692466a4..058a512d 100644 --- a/Modules/Bar/Widgets/KeepAwake.qml +++ b/Modules/Bar/Widgets/KeepAwake.qml @@ -8,7 +8,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml index f5ac5770..065f6799 100644 --- a/Modules/Bar/Widgets/NightLight.qml +++ b/Modules/Bar/Widgets/NightLight.qml @@ -11,7 +11,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight diff --git a/Modules/Bar/Widgets/NotificationHistory.qml b/Modules/Bar/Widgets/NotificationHistory.qml index ad9bb86b..a5448ae1 100644 --- a/Modules/Bar/Widgets/NotificationHistory.qml +++ b/Modules/Bar/Widgets/NotificationHistory.qml @@ -10,7 +10,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen // Widget properties passed from Bar.qml for per-instance settings property string widgetId: "" diff --git a/Modules/Bar/Widgets/PowerProfile.qml b/Modules/Bar/Widgets/PowerProfile.qml index a89c4e7a..ad1dc21d 100644 --- a/Modules/Bar/Widgets/PowerProfile.qml +++ b/Modules/Bar/Widgets/PowerProfile.qml @@ -9,7 +9,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen baseSize: Style.capsuleHeight visible: PowerProfileService.available diff --git a/Modules/Bar/Widgets/ScreenRecorder.qml b/Modules/Bar/Widgets/ScreenRecorder.qml index 0f2dd5fa..06869689 100644 --- a/Modules/Bar/Widgets/ScreenRecorder.qml +++ b/Modules/Bar/Widgets/ScreenRecorder.qml @@ -7,7 +7,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen icon: "camera-video" tooltipText: ScreenRecorderService.isRecording ? I18n.tr("tooltips.click-to-stop-recording") : I18n.tr("tooltips.click-to-start-recording") diff --git a/Modules/Bar/Widgets/SessionMenu.qml b/Modules/Bar/Widgets/SessionMenu.qml index cb506ad3..f8f09929 100644 --- a/Modules/Bar/Widgets/SessionMenu.qml +++ b/Modules/Bar/Widgets/SessionMenu.qml @@ -8,6 +8,7 @@ import qs.Widgets NIconButton { id: root + property ShellScreen screen property real scaling: 1.0 compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/Spacer.qml b/Modules/Bar/Widgets/Spacer.qml index 8f1378e3..811bcb53 100644 --- a/Modules/Bar/Widgets/Spacer.qml +++ b/Modules/Bar/Widgets/Spacer.qml @@ -9,7 +9,7 @@ Item { id: root // Widget properties passed from Bar.qml - property var screen + property ShellScreen screen property real scaling: 1.0 // Widget properties passed from Bar.qml for per-instance settings diff --git a/Modules/Bar/Widgets/WallpaperSelector.qml b/Modules/Bar/Widgets/WallpaperSelector.qml index 51188450..cbed457f 100644 --- a/Modules/Bar/Widgets/WallpaperSelector.qml +++ b/Modules/Bar/Widgets/WallpaperSelector.qml @@ -8,7 +8,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml index 58a0e885..55b2ebb8 100644 --- a/Modules/Bar/Widgets/WiFi.qml +++ b/Modules/Bar/Widgets/WiFi.qml @@ -10,7 +10,8 @@ import qs.Widgets NIconButton { id: root - property real scaling: 1.0 + // NIconButton must only define screen, not scaling + property ShellScreen screen compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight diff --git a/Widgets/NIconButton.qml b/Widgets/NIconButton.qml index e2d0d0fa..57df95a2 100644 --- a/Widgets/NIconButton.qml +++ b/Widgets/NIconButton.qml @@ -8,6 +8,7 @@ Rectangle { id: root property real baseSize: Style.baseWidgetSize + property real scaling: 1.0 property string icon property string tooltipText From 4d0041abeeb7f71724560134d20aff5b9788c0df Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 19:57:12 -0400 Subject: [PATCH 10/16] Quicksettings: polishing, fixed all scaling issues. --- Assets/settings-default.json | 19 +- Commons/Settings.qml | 2 +- Modules/Bar/Widgets/ActiveWindow.qml | 1 + Modules/Bar/Widgets/Bluetooth.qml | 2 +- Modules/Bar/Widgets/ControlCenter.qml | 2 +- Modules/Bar/Widgets/CustomButton.qml | 1 - Modules/Bar/Widgets/DarkMode.qml | 2 +- Modules/Bar/Widgets/KeepAwake.qml | 2 +- Modules/Bar/Widgets/NightLight.qml | 2 +- Modules/Bar/Widgets/NotificationHistory.qml | 2 +- Modules/Bar/Widgets/PowerProfile.qml | 2 +- Modules/Bar/Widgets/ScreenRecorder.qml | 2 +- Modules/Bar/Widgets/Spacer.qml | 1 - Modules/Bar/Widgets/WallpaperSelector.qml | 2 +- Modules/Bar/Widgets/WiFi.qml | 2 +- Modules/ControlCenter/Cards/TopCard.qml | 4 +- Modules/ControlCenter/ControlCenterPanel.qml | 16 +- Modules/ControlCenter/Widgets/Bluetooth.qml | 2 - Modules/ControlCenter/Widgets/KeepAwake.qml | 2 +- Modules/ControlCenter/Widgets/NightLight.qml | 2 +- .../ControlCenter/Widgets/Notifications.qml | 2 +- .../ControlCenter/Widgets/PowerProfile.qml | 2 +- .../ControlCenter/Widgets/ScreenRecorder.qml | 2 +- .../Widgets/WallpaperSelector.qml | 1 - Modules/ControlCenter/Widgets/WiFi.qml | 18 -- .../Bar/WidgetSettings/TaskbarSettings.qml | 1 - Modules/Settings/Tabs/ControlCenterTab.qml | 8 +- Services/PowerProfileService.qml | 6 + Widgets/NCircleStat.qml | 2 +- Widgets/NIconButton.qml | 1 - Widgets/NQuickSetting.qml | 166 +++++------------- 31 files changed, 87 insertions(+), 192 deletions(-) diff --git a/Assets/settings-default.json b/Assets/settings-default.json index fd3707c4..05ccde05 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -36,12 +36,6 @@ { "id": "NotificationHistory" }, - { - "id": "WiFi" - }, - { - "id": "Bluetooth" - }, { "id": "Battery" }, @@ -113,7 +107,7 @@ }, "controlCenter": { "position": "close_to_bar_button", - "quickSettingsStyle": "modern", + "quickSettingsStyle": "compact", "widgets": { "quickSettings": [ { @@ -125,20 +119,11 @@ { "id": "Notifications" }, - { - "id": "NightLight" - }, - { - "id": "KeepAwake" - }, - { - "id": "PowerProfile" - }, { "id": "ScreenRecorder" }, { - "id": "WallpaperSelector" + "id": "PowerProfile" } ] } diff --git a/Commons/Settings.qml b/Commons/Settings.qml index ffe9039a..960edd67 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -242,7 +242,7 @@ Singleton { property JsonObject controlCenter: JsonObject { // Position: close_to_bar_button, center, top_left, top_right, bottom_left, bottom_right, bottom_center, top_center property string position: "close_to_bar_button" - property string quickSettingsStyle: "compact" // "modern", "classic", or "compact" + property string quickSettingsStyle: "compact" // "compact", "classic", or "modern" property JsonObject widgets widgets: JsonObject { property list quickSettings: [{ diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index 91c05f1d..de10760d 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -10,6 +10,7 @@ import qs.Widgets Item { id: root + property ShellScreen screen property real scaling: 1.0 diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml index 520455e4..e76fa234 100644 --- a/Modules/Bar/Widgets/Bluetooth.qml +++ b/Modules/Bar/Widgets/Bluetooth.qml @@ -10,8 +10,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/ControlCenter.qml b/Modules/Bar/Widgets/ControlCenter.qml index 993e2f0b..65eb3b8c 100644 --- a/Modules/Bar/Widgets/ControlCenter.qml +++ b/Modules/Bar/Widgets/ControlCenter.qml @@ -9,8 +9,8 @@ import qs.Services NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 // Widget properties passed from Bar.qml for per-instance settings property string widgetId: "" diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 11a1b7d6..50310b24 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -11,7 +11,6 @@ import qs.Modules.Bar.Extras Item { id: root - // Widget properties passed from Bar.qml property ShellScreen screen property real scaling: 1.0 diff --git a/Modules/Bar/Widgets/DarkMode.qml b/Modules/Bar/Widgets/DarkMode.qml index 13998414..b35dd236 100644 --- a/Modules/Bar/Widgets/DarkMode.qml +++ b/Modules/Bar/Widgets/DarkMode.qml @@ -6,8 +6,8 @@ import qs.Services NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 icon: "dark-mode" tooltipText: Settings.data.colorSchemes.darkMode ? I18n.tr("tooltips.switch-to-light-mode") : I18n.tr("tooltips.switch-to-dark-mode") diff --git a/Modules/Bar/Widgets/KeepAwake.qml b/Modules/Bar/Widgets/KeepAwake.qml index 058a512d..ba09d92a 100644 --- a/Modules/Bar/Widgets/KeepAwake.qml +++ b/Modules/Bar/Widgets/KeepAwake.qml @@ -8,8 +8,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml index 065f6799..b972d37d 100644 --- a/Modules/Bar/Widgets/NightLight.qml +++ b/Modules/Bar/Widgets/NightLight.qml @@ -11,8 +11,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight diff --git a/Modules/Bar/Widgets/NotificationHistory.qml b/Modules/Bar/Widgets/NotificationHistory.qml index a5448ae1..aee73598 100644 --- a/Modules/Bar/Widgets/NotificationHistory.qml +++ b/Modules/Bar/Widgets/NotificationHistory.qml @@ -10,8 +10,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 // Widget properties passed from Bar.qml for per-instance settings property string widgetId: "" diff --git a/Modules/Bar/Widgets/PowerProfile.qml b/Modules/Bar/Widgets/PowerProfile.qml index ad1dc21d..fbd2a719 100644 --- a/Modules/Bar/Widgets/PowerProfile.qml +++ b/Modules/Bar/Widgets/PowerProfile.qml @@ -9,8 +9,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 baseSize: Style.capsuleHeight visible: PowerProfileService.available diff --git a/Modules/Bar/Widgets/ScreenRecorder.qml b/Modules/Bar/Widgets/ScreenRecorder.qml index 06869689..16b57804 100644 --- a/Modules/Bar/Widgets/ScreenRecorder.qml +++ b/Modules/Bar/Widgets/ScreenRecorder.qml @@ -7,8 +7,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 icon: "camera-video" tooltipText: ScreenRecorderService.isRecording ? I18n.tr("tooltips.click-to-stop-recording") : I18n.tr("tooltips.click-to-start-recording") diff --git a/Modules/Bar/Widgets/Spacer.qml b/Modules/Bar/Widgets/Spacer.qml index 811bcb53..d8e4abcb 100644 --- a/Modules/Bar/Widgets/Spacer.qml +++ b/Modules/Bar/Widgets/Spacer.qml @@ -8,7 +8,6 @@ import qs.Widgets Item { id: root - // Widget properties passed from Bar.qml property ShellScreen screen property real scaling: 1.0 diff --git a/Modules/Bar/Widgets/WallpaperSelector.qml b/Modules/Bar/Widgets/WallpaperSelector.qml index cbed457f..4be3e9a1 100644 --- a/Modules/Bar/Widgets/WallpaperSelector.qml +++ b/Modules/Bar/Widgets/WallpaperSelector.qml @@ -8,8 +8,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml index 55b2ebb8..00fefab6 100644 --- a/Modules/Bar/Widgets/WiFi.qml +++ b/Modules/Bar/Widgets/WiFi.qml @@ -10,8 +10,8 @@ import qs.Widgets NIconButton { id: root - // NIconButton must only define screen, not scaling property ShellScreen screen + property real scaling: 1.0 compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index 643200e2..16336beb 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -31,7 +31,7 @@ NBox { NImageCircled { width: Style.baseWidgetSize * 1.25 * scaling - height: Style.baseWidgetSize * 1.25 * scaling + height: width imagePath: Settings.data.general.avatarImage fallbackIcon: "person" borderColor: Color.mPrimary @@ -105,7 +105,7 @@ NBox { GridLayout { id: grid Layout.fillWidth: true - columns: (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 + columns: (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 5 : 3 columnSpacing: Style.marginM * scaling rowSpacing: Style.marginS * scaling diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 4f76e029..25458401 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -11,12 +11,12 @@ NPanel { id: root preferredWidth: 440 - preferredHeight: topHeight + bottomHeight + Math.round(Style.marginL * scaling * 3) + preferredHeight: topHeight + bottomHeight + Math.round(Style.marginL * 3) panelKeyboardFocus: true - readonly property int bottomHeight: Math.round(Math.max(196 * scaling)) + readonly property int bottomHeight: 196 readonly property int topHeight: { - const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 + const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 5 : 3 const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / columns) var buttonHeight @@ -28,7 +28,7 @@ NPanel { buttonHeight = 56 } - return (rowsCount * buttonHeight) + (120 * scaling) + return (rowsCount * buttonHeight) + 120 } // Positioning @@ -56,26 +56,26 @@ NPanel { TopCard { id: topCard Layout.fillWidth: true - Layout.preferredHeight: topHeight + Layout.preferredHeight: topHeight * scaling } // Media + stats column RowLayout { id: bottomCard Layout.fillWidth: true - Layout.preferredHeight: bottomHeight + Layout.preferredHeight: bottomHeight * scaling spacing: content.cardSpacing // Media card MediaCard { Layout.preferredWidth: Math.max(250 * scaling) - Layout.preferredHeight: bottomHeight + Layout.preferredHeight: bottomHeight * scaling } // System monitors combined in one card SystemMonitorCard { Layout.preferredWidth: Math.max(140 * scaling) - Layout.preferredHeight: bottomHeight + Layout.preferredHeight: bottomHeight * scaling } } } diff --git a/Modules/ControlCenter/Widgets/Bluetooth.qml b/Modules/ControlCenter/Widgets/Bluetooth.qml index e44d9844..9150004d 100644 --- a/Modules/ControlCenter/Widgets/Bluetooth.qml +++ b/Modules/ControlCenter/Widgets/Bluetooth.qml @@ -12,9 +12,7 @@ NQuickSetting { fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" - active: BluetoothService.enabled tooltipText: I18n.tr("quickSettings.bluetooth.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" - onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) } diff --git a/Modules/ControlCenter/Widgets/KeepAwake.qml b/Modules/ControlCenter/Widgets/KeepAwake.qml index e384272a..fff72489 100644 --- a/Modules/ControlCenter/Widgets/KeepAwake.qml +++ b/Modules/ControlCenter/Widgets/KeepAwake.qml @@ -12,7 +12,7 @@ NQuickSetting { fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" - active: IdleInhibitorService.isInhibited + hot: IdleInhibitorService.isInhibited tooltipText: I18n.tr("quickSettings.keepAwake.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/NightLight.qml b/Modules/ControlCenter/Widgets/NightLight.qml index a2d6bfc1..dac6dd98 100644 --- a/Modules/ControlCenter/Widgets/NightLight.qml +++ b/Modules/ControlCenter/Widgets/NightLight.qml @@ -13,7 +13,7 @@ NQuickSetting { fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" - active: Settings.data.nightLight.enabled + hot: !Settings.data.nightLight.enabled || Settings.data.nightLight.forced style: Settings.data.controlCenter.quickSettingsStyle || "modern" tooltipText: I18n.tr("quickSettings.nightLight.tooltip.action") diff --git a/Modules/ControlCenter/Widgets/Notifications.qml b/Modules/ControlCenter/Widgets/Notifications.qml index 131db7f9..7d8085e4 100644 --- a/Modules/ControlCenter/Widgets/Notifications.qml +++ b/Modules/ControlCenter/Widgets/Notifications.qml @@ -12,7 +12,7 @@ NQuickSetting { fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" - active: Settings.data.notifications.doNotDisturb + hot: Settings.data.notifications.doNotDisturb tooltipText: I18n.tr("quickSettings.notifications.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/PowerProfile.qml b/Modules/ControlCenter/Widgets/PowerProfile.qml index 1c57f9fa..442cc9c5 100644 --- a/Modules/ControlCenter/Widgets/PowerProfile.qml +++ b/Modules/ControlCenter/Widgets/PowerProfile.qml @@ -16,7 +16,7 @@ NQuickSetting { fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium icon: PowerProfileService.getIcon() - active: hasPP + hot: !PowerProfileService.isDefault() tooltipText: I18n.tr("quickSettings.powerProfile.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/ControlCenter/Widgets/ScreenRecorder.qml index a9560bdf..a53e3950 100644 --- a/Modules/ControlCenter/Widgets/ScreenRecorder.qml +++ b/Modules/ControlCenter/Widgets/ScreenRecorder.qml @@ -13,7 +13,7 @@ NQuickSetting { text: ScreenRecorderService.isRecording ? I18n.tr("quickSettings.screenRecorder.label.recording") : I18n.tr("quickSettings.screenRecorder.label.stopped") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium - active: ScreenRecorderService.isRecording + hot: ScreenRecorderService.isRecording tooltipText: I18n.tr("quickSettings.screenRecorder.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/WallpaperSelector.qml b/Modules/ControlCenter/Widgets/WallpaperSelector.qml index a4639383..e4531ecd 100644 --- a/Modules/ControlCenter/Widgets/WallpaperSelector.qml +++ b/Modules/ControlCenter/Widgets/WallpaperSelector.qml @@ -13,7 +13,6 @@ NQuickSetting { text: I18n.tr("quickSettings.wallpaperSelector.label") fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium - active: Settings.data.wallpaper.enabled tooltipText: I18n.tr("quickSettings.wallpaperSelector.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/WiFi.qml b/Modules/ControlCenter/Widgets/WiFi.qml index 9d896a5c..29c89a8a 100644 --- a/Modules/ControlCenter/Widgets/WiFi.qml +++ b/Modules/ControlCenter/Widgets/WiFi.qml @@ -46,24 +46,6 @@ NQuickSetting { fontSize: Style.fontSizeS * scaling fontWeight: Style.fontWeightMedium style: Settings.data.controlCenter.quickSettingsStyle || "modern" - - active: { - if (NetworkService.ethernetConnected) { - return true - } - try { - for (const net in NetworkService.networks) { - if (NetworkService.networks[net].connected) { - return true - } - } - return false - } catch (error) { - return false - } - } - tooltipText: I18n.tr("quickSettings.wifi.tooltip.action") - onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) } diff --git a/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml b/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml index 98df4c3f..c80dd09f 100644 --- a/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml @@ -21,7 +21,6 @@ ColumnLayout { var settings = Object.assign({}, widgetData || {}) settings.onlySameOutput = valueOnlySameOutput settings.onlyActiveWorkspaces = valueOnlyActiveWorkspaces - console.log(JSON.stringify(settings)) return settings } diff --git a/Modules/Settings/Tabs/ControlCenterTab.qml b/Modules/Settings/Tabs/ControlCenterTab.qml index 8b7fe265..a880334c 100644 --- a/Modules/Settings/Tabs/ControlCenterTab.qml +++ b/Modules/Settings/Tabs/ControlCenterTab.qml @@ -43,14 +43,14 @@ ColumnLayout { description: I18n.tr("settings.control-center.quickSettingsStyle.style.description") Layout.fillWidth: true model: [{ - "key": "modern", - "name": I18n.tr("options.control-center.quickSettingsStyle.modern") + "key": "compact", + "name": I18n.tr("options.control-center.quickSettingsStyle.compact") }, { "key": "classic", "name": I18n.tr("options.control-center.quickSettingsStyle.classic") }, { - "key": "compact", - "name": I18n.tr("options.control-center.quickSettingsStyle.compact") + "key": "modern", + "name": I18n.tr("options.control-center.quickSettingsStyle.modern") }] currentKey: Settings.data.controlCenter.quickSettingsStyle || "compact" onSelected: function (key) { diff --git a/Services/PowerProfileService.qml b/Services/PowerProfileService.qml index 98acfb71..9a43217e 100644 --- a/Services/PowerProfileService.qml +++ b/Services/PowerProfileService.qml @@ -71,6 +71,12 @@ Singleton { setProfile(PowerProfile.Balanced) } + function isDefault() { + if (!available) + return true + return (profile === PowerProfile.Balanced) + } + Connections { target: powerProfiles function onProfileChanged() { diff --git a/Widgets/NCircleStat.qml b/Widgets/NCircleStat.qml index 53177d07..9c924883 100644 --- a/Widgets/NCircleStat.qml +++ b/Widgets/NCircleStat.qml @@ -84,7 +84,7 @@ Rectangle { anchors.centerIn: parent anchors.verticalCenterOffset: -4 * scaling * contentScale text: `${root.value}${root.suffix}` - pointSize: Style.fontSizeM * scaling * contentScale + pointSize: Style.fontSizeM * scaling * contentScale * 0.9 font.weight: Style.fontWeightBold color: Color.mOnSurface horizontalAlignment: Text.AlignHCenter diff --git a/Widgets/NIconButton.qml b/Widgets/NIconButton.qml index 57df95a2..e2d0d0fa 100644 --- a/Widgets/NIconButton.qml +++ b/Widgets/NIconButton.qml @@ -8,7 +8,6 @@ Rectangle { id: root property real baseSize: Style.baseWidgetSize - property real scaling: 1.0 property string icon property string tooltipText diff --git a/Widgets/NQuickSetting.qml b/Widgets/NQuickSetting.qml index 75517718..c5706cf9 100644 --- a/Widgets/NQuickSetting.qml +++ b/Widgets/NQuickSetting.qml @@ -13,8 +13,7 @@ Rectangle { property string icon: "" property string tooltipText: "" property bool enabled: true - property bool active: false - property bool compact: false + property bool hot: false property string style: "modern" // "modern", "classic", or "compact" // Styling properties @@ -23,56 +22,54 @@ Rectangle { property real iconSize: Style.fontSizeL * scaling property real cornerRadius: Style.radiusM * scaling + // Internal properties + property bool hovered: false + property bool pressed: false + // Colors - Style-dependent colors property color backgroundColor: { + if (pressed) { + return Color.mTertiary + } + if (hot) { + return Color.mPrimary + } if (style === "classic") return Color.mSurfaceVariant if (style === "compact") return Color.mSurface return Color.mSurface } - property color textColor: Color.mOnSurface + property color textColor: { + if (pressed) { + return Color.mOnTertiary + } + if (hot) { + return Color.mOnPrimary + } + return Color.mOnSurface + } property color iconColor: { - if (style === "classic") + if (pressed) { + return Color.mOnTertiary + } + if (hot) { + return Color.mOnPrimary + } + if (style !== "compact") return Color.mPrimary - if (style === "compact") - return active ? Color.mPrimary : Color.mOnSurface - return active ? Color.mPrimary : Color.mOnSurface + return Color.mOnSurface } property color borderColor: Color.mOutline - property color hoverColor: { - if (style === "classic") - return Color.mTertiary - if (style === "compact") - return Color.mPrimary - return Color.mPrimary - } - property color pressedColor: { - if (style === "classic") - return Color.mTertiary - if (style === "compact") - return Qt.darker(Color.mPrimary, 1.1) - return Qt.darker(Color.mPrimary, 1.1) - } - property color hoverTextColor: Color.mOnPrimary - property color hoverIconColor: { - if (style === "classic") - return Color.mOnTertiary - if (style === "compact") - return Color.mOnPrimary - return Color.mOnPrimary - } + property color hoverColor: Color.mTertiary + property color hoverTextColor: Color.mOnTertiary + property color hoverIconColor: Color.mOnTertiary // Signals signal clicked signal rightClicked signal middleClicked - // Internal properties - property bool hovered: false - property bool pressed: false - property real scaling: 1.0 - // Dimensions - Style-dependent sizing implicitWidth: { if (style === "classic") { @@ -81,7 +78,7 @@ Rectangle { if (style === "compact") { return Style.baseWidgetSize * 0.8 * scaling } - return compact ? Math.max(100 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) : Math.max(120 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) + return Math.max(120 * scaling, contentRow.implicitWidth + (Style.marginL * scaling)) } implicitHeight: { if (style === "classic") { @@ -90,7 +87,7 @@ Rectangle { if (style === "compact") { return Style.baseWidgetSize * 0.8 * scaling } - return compact ? Math.max(48 * scaling, contentRow.implicitHeight + (Style.marginM * scaling)) : Math.max(56 * scaling, contentRow.implicitHeight + (Style.marginL * scaling)) + return Math.max(48 * scaling, contentRow.implicitHeight + (Style.marginL * scaling)) } // Appearance - Style-dependent styling @@ -104,8 +101,6 @@ Rectangle { color: { if (!enabled) return Qt.lighter(Color.mSurface, 1.1) - if (pressed) - return pressedColor if (hovered) return hoverColor return backgroundColor @@ -128,14 +123,14 @@ Rectangle { Behavior on color { ColorAnimation { - duration: style === "classic" ? Style.animationNormal : Style.animationFast + duration: Style.animationFast easing.type: style === "classic" ? Easing.InOutQuad : Easing.OutCubic } } Behavior on border.color { ColorAnimation { - duration: style === "classic" ? Style.animationNormal : Style.animationFast + duration: Style.animationFast easing.type: style === "classic" ? Easing.InOutQuad : Easing.OutCubic } } @@ -147,25 +142,6 @@ Rectangle { } } - // Hover scale effect - scale: hovered ? 1.02 : 1.0 - - // Subtle shadow/elevation effect - Rectangle { - anchors.fill: parent - radius: parent.radius - color: Qt.rgba(0, 0, 0, 0.1) - visible: active - z: -1 - - Behavior on color { - ColorAnimation { - duration: Style.animationFast - easing.type: Easing.OutCubic - } - } - } - // Modern style - icon above text ColumnLayout { id: contentRow @@ -198,7 +174,7 @@ Rectangle { // Text content NText { Layout.alignment: Qt.AlignHCenter - visible: root.text !== "" && !compact + visible: root.text !== "" text: root.text pointSize: root.fontSize font.weight: root.fontWeight @@ -315,22 +291,25 @@ Rectangle { onPressed: mouse => { root.pressed = true - root.scale = 0.95 + root.scale = 0.92 if (tooltipText) { TooltipService.hide() } } onReleased: mouse => { - root.pressed = false root.scale = 1.0 + root.pressed = false - if (mouse.button === Qt.LeftButton) { - root.clicked() - } else if (mouse.button === Qt.RightButton) { - root.rightClicked() - } else if (mouse.button === Qt.MiddleButton) { - root.middleClicked() + // Only trigger actions if released while hovering + if (root.hovered) { + if (mouse.button === Qt.LeftButton) { + root.clicked() + } else if (mouse.button === Qt.RightButton) { + root.rightClicked() + } else if (mouse.button === Qt.MiddleButton) { + root.middleClicked() + } } } @@ -343,55 +322,4 @@ Rectangle { } } } - - Rectangle { - id: ripple - anchors.fill: parent - radius: parent.radius - color: Qt.rgba(1, 1, 1, 0.2) - scale: 0 - opacity: 0 - visible: false - - SequentialAnimation { - id: rippleAnimation - running: false - - ParallelAnimation { - NumberAnimation { - target: ripple - property: "scale" - from: 0 - to: 1.2 - duration: Style.animationNormal - easing.type: Easing.OutCubic - } - NumberAnimation { - target: ripple - property: "opacity" - from: 0.6 - to: 0 - duration: Style.animationNormal - easing.type: Easing.OutCubic - } - } - } - } - - Connections { - target: root - function onClicked() { - ripple.visible = true - rippleAnimation.start() - } - } - - Connections { - target: rippleAnimation - function onFinished() { - ripple.visible = false - ripple.scale = 0 - ripple.opacity = 0 - } - } } From 3fe63f463e7ab75cac9cf39b36ba8a88bfdf6421 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 20:20:26 -0400 Subject: [PATCH 11/16] ControlCenter: Looks better when it's taller and less wide. --- .../ControlCenter/Cards/SystemMonitorCard.qml | 7 ++-- Modules/ControlCenter/Cards/TopCard.qml | 2 +- Modules/ControlCenter/ControlCenterPanel.qml | 35 ++++++++----------- Widgets/NQuickSetting.qml | 4 +-- 4 files changed, 20 insertions(+), 28 deletions(-) diff --git a/Modules/ControlCenter/Cards/SystemMonitorCard.qml b/Modules/ControlCenter/Cards/SystemMonitorCard.qml index 351d4c68..b0572f8a 100644 --- a/Modules/ControlCenter/Cards/SystemMonitorCard.qml +++ b/Modules/ControlCenter/Cards/SystemMonitorCard.qml @@ -9,14 +9,11 @@ import qs.Widgets NBox { id: root - GridLayout { + RowLayout { id: content anchors.fill: parent anchors.margins: Style.marginXS * scaling - columns: 2 - rows: 2 - columnSpacing: Style.marginS * scaling - rowSpacing: Style.marginS * scaling + spacing: Style.marginS * scaling NCircleStat { value: SystemStatService.cpuUsage diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index 16336beb..2c9616c2 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -105,7 +105,7 @@ NBox { GridLayout { id: grid Layout.fillWidth: true - columns: (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 5 : 3 + columns: (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 columnSpacing: Style.marginM * scaling rowSpacing: Style.marginS * scaling diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 25458401..94e36dbd 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -10,13 +10,13 @@ import qs.Widgets NPanel { id: root - preferredWidth: 440 - preferredHeight: topHeight + bottomHeight + Math.round(Style.marginL * 3) + preferredWidth: 400 + preferredHeight: topHeight + midHeight + bottomHeight + Math.round(Style.marginL * 4) panelKeyboardFocus: true - readonly property int bottomHeight: 196 + readonly property int topHeight: { - const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 5 : 3 + const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / columns) var buttonHeight @@ -30,6 +30,9 @@ NPanel { return (rowsCount * buttonHeight) + 120 } + readonly property int midHeight: 220 + readonly property int bottomHeight: 80 + // Positioning readonly property string controlCenterPosition: Settings.data.controlCenter.position @@ -59,24 +62,16 @@ NPanel { Layout.preferredHeight: topHeight * scaling } - // Media + stats column - RowLayout { - id: bottomCard + // Media card + MediaCard { + Layout.fillWidth: true + Layout.preferredHeight: midHeight * scaling + } + + // System monitors combined in one card + SystemMonitorCard { Layout.fillWidth: true Layout.preferredHeight: bottomHeight * scaling - spacing: content.cardSpacing - - // Media card - MediaCard { - Layout.preferredWidth: Math.max(250 * scaling) - Layout.preferredHeight: bottomHeight * scaling - } - - // System monitors combined in one card - SystemMonitorCard { - Layout.preferredWidth: Math.max(140 * scaling) - Layout.preferredHeight: bottomHeight * scaling - } } } } diff --git a/Widgets/NQuickSetting.qml b/Widgets/NQuickSetting.qml index c5706cf9..2e708e7c 100644 --- a/Widgets/NQuickSetting.qml +++ b/Widgets/NQuickSetting.qml @@ -300,7 +300,7 @@ Rectangle { onReleased: mouse => { root.scale = 1.0 root.pressed = false - + // Only trigger actions if released while hovering if (root.hovered) { if (mouse.button === Qt.LeftButton) { @@ -322,4 +322,4 @@ Rectangle { } } } -} +} \ No newline at end of file From 6b444cea07b1565302bc04fb1ae52bb78eb478d3 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 20:26:07 -0400 Subject: [PATCH 12/16] Translations --- Assets/Translations/de.json | 85 ++++++++++---------- Assets/Translations/en.json | 2 +- Assets/Translations/es.json | 85 ++++++++++---------- Assets/Translations/fr.json | 53 ++---------- Assets/Translations/pt.json | 85 ++++++++++---------- Assets/Translations/zh-CN.json | 83 ++++++++++--------- Modules/ControlCenter/Cards/TopCard.qml | 2 +- Modules/ControlCenter/ControlCenterPanel.qml | 4 +- Widgets/NQuickSetting.qml | 4 +- 9 files changed, 186 insertions(+), 217 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 6f530c47..b9c10d0d 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -743,53 +743,56 @@ "label": "Widgets", "description": "Konfigurieren und verwalten Sie Kontrollzentrum-Widgets und deren Anzeigeoptionen." } - } - }, - "quickSettings": { - "notifications": { - "label": "Benachrichtigungen", - "tooltip": { - "enable": "Nicht stören aktivieren", - "disable": "Nicht stören deaktivieren" + }, + "quickSettings": { + "sectionName": "Schnelleinstellungen" } }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Netzwerk" + "quickSettings": { + "notifications": { + "label": "Benachrichtigungen", + "tooltip": { + "enable": "Nicht stören aktivieren", + "disable": "Nicht stören deaktivieren" + } }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi verbunden", - "disconnected": "Wi-Fi getrennt" + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Netzwerk" }, - "ethernet": { - "connected": "Ethernet verbunden" + "tooltip": { + "wifi": { + "connected": "Wi-Fi verbunden", + "disconnected": "Wi-Fi getrennt" + }, + "ethernet": { + "connected": "Ethernet verbunden" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth aktiviert", + "disabled": "Bluetooth deaktiviert" + } + }, + "screenRecorder": { + "label": "Bildschirm", + "tooltip": { + "start": "Bildschirmaufnahme starten", + "stop": "Aufnahme beenden" + } + }, + "powerProfile": { + "tooltip": { + "current": "Aktuell: {profile}", + "unavailable": "Energieprofile nicht verfügbar" } } }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth aktiviert", - "disabled": "Bluetooth deaktiviert" - } - }, - "screenRecorder": { - "label": "Bildschirm", - "tooltip": { - "start": "Bildschirmaufnahme starten", - "stop": "Aufnahme beenden" - } - }, - "powerProfile": { - "tooltip": { - "current": "Aktuell: {profile}", - "unavailable": "Energieprofile nicht verfügbar" - } - } - }, - "hooks": { + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1440,7 +1443,7 @@ "calculator-error": "Fehler" }, "system": { - "uptime": "System-Laufzeit: {uptime}", + "uptime": "Laufzeit: {uptime}", "welcome-back": "Willkommen zurück,", "monitor-description": "{model} ({width}x{height})", "scaling-percentage": "{percentage}%", diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index b9dd76b7..4401d058 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1381,7 +1381,7 @@ "calculator-error": "Error" }, "system": { - "uptime": "System uptime: {uptime}", + "uptime": "Uptime: {uptime}", "welcome-back": "Welcome back,", "monitor-description": "{model} ({width}x{height})", "scaling-percentage": "{percentage}%", diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index c7e094ca..455e93fa 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -739,53 +739,56 @@ "label": "Widgets", "description": "Configura y gestiona los widgets del centro de control y sus opciones de visualización." } - } - }, - "quickSettings": { - "notifications": { - "label": "Notificaciones", - "tooltip": { - "enable": "Activar No molestar", - "disable": "Desactivar No molestar" + }, + "quickSettings": { + "sectionName": "Ajustes rápidos" } }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Red" + "quickSettings": { + "notifications": { + "label": "Notificaciones", + "tooltip": { + "enable": "Activar No molestar", + "disable": "Desactivar No molestar" + } }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi conectado", - "disconnected": "Wi-Fi desconectado" + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Red" }, - "ethernet": { - "connected": "Ethernet conectado" + "tooltip": { + "wifi": { + "connected": "Wi-Fi conectado", + "disconnected": "Wi-Fi desconectado" + }, + "ethernet": { + "connected": "Ethernet conectado" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth habilitado", + "disabled": "Bluetooth deshabilitado" + } + }, + "screenRecorder": { + "label": "Pantalla", + "tooltip": { + "start": "Iniciar grabación de pantalla", + "stop": "Detener grabación" + } + }, + "powerProfile": { + "tooltip": { + "current": "Actual: {profile}", + "unavailable": "Perfiles de energía no disponibles" } } }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth habilitado", - "disabled": "Bluetooth deshabilitado" - } - }, - "screenRecorder": { - "label": "Pantalla", - "tooltip": { - "start": "Iniciar grabación de pantalla", - "stop": "Detener grabación" - } - }, - "powerProfile": { - "tooltip": { - "current": "Actual: {profile}", - "unavailable": "Perfiles de energía no disponibles" - } - } - }, - "hooks": { + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1419,7 +1422,7 @@ "calculator-error": "Error" }, "system": { - "uptime": "Tiempo de actividad: {uptime}", + "uptime": "Actividad: {uptime}", "welcome-back": "¡Bienvenido de nuevo,", "monitor-description": "{model} ({width}x{height})", "scaling-percentage": "{percentage}%", diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 1a659cb7..c09015c6 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -739,6 +739,9 @@ "label": "Widgets", "description": "Configurez et gérez les widgets du centre de contrôle et leurs options d'affichage." } + }, + "quickSettings": { + "sectionName": "Paramètres rapides" } }, "quickSettings": { @@ -784,52 +787,8 @@ "unavailable": "Profils d'alimentation non disponibles" } } - }, - "quickSettings": { - "notifications": { - "label": "Notifications", - "tooltip": { - "enable": "Activer Ne pas déranger", - "disable": "Désactiver Ne pas déranger" - } }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Réseau" - }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi connecté", - "disconnected": "Wi-Fi déconnecté" - }, - "ethernet": { - "connected": "Ethernet connecté" - } - } - }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth activé", - "disabled": "Bluetooth désactivé" - } - }, - "screenRecorder": { - "label": "Écran", - "tooltip": { - "start": "Démarrer l'enregistrement d'écran", - "stop": "Arrêter l'enregistrement" - } - }, - "powerProfile": { - "tooltip": { - "current": "Actuel : {profile}", - "unavailable": "Profils d'alimentation non disponibles" - } - } - }, - "hooks": { + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1463,7 +1422,6 @@ "calculator-error": "Erreur" }, "system": { - "uptime": "Temps d'activité : {uptime}", "welcome-back": "Bon retour,", "monitor-description": "{model} ({width}x{height})", "scaling-percentage": "{percentage}%", @@ -1477,7 +1435,8 @@ "user-requested": "Demandé par l'utilisateur", "unknown": "Inconnu", "unknown-version": "Inconnue", - "unknown-layout": "Inconnue" + "unknown-layout": "Inconnue", + "uptime": "Activité : {uptime}" }, "lock-screen": { "password": "Entrez votre mot de passe...", diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 4dcb10c7..0c098e50 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -705,53 +705,56 @@ "label": "Widgets", "description": "Configure e gerencie os widgets do centro de controle e suas opções de exibição." } - } - }, - "quickSettings": { - "notifications": { - "label": "Notificações", - "tooltip": { - "enable": "Ativar Não perturbe", - "disable": "Desativar Não perturbe" + }, + "quickSettings": { + "sectionName": "Configurações rápidas" } }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Rede" + "quickSettings": { + "notifications": { + "label": "Notificações", + "tooltip": { + "enable": "Ativar Não perturbe", + "disable": "Desativar Não perturbe" + } }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi conectado", - "disconnected": "Wi-Fi desconectado" + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "Rede" }, - "ethernet": { - "connected": "Ethernet conectado" + "tooltip": { + "wifi": { + "connected": "Wi-Fi conectado", + "disconnected": "Wi-Fi desconectado" + }, + "ethernet": { + "connected": "Ethernet conectado" + } + } + }, + "bluetooth": { + "label": "Bluetooth", + "tooltip": { + "enabled": "Bluetooth habilitado", + "disabled": "Bluetooth desabilitado" + } + }, + "screenRecorder": { + "label": "Tela", + "tooltip": { + "start": "Iniciar gravação de tela", + "stop": "Parar gravação" + } + }, + "powerProfile": { + "tooltip": { + "current": "Atual: {profile}", + "unavailable": "Perfis de energia não disponíveis" } } }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth habilitado", - "disabled": "Bluetooth desabilitado" - } - }, - "screenRecorder": { - "label": "Tela", - "tooltip": { - "start": "Iniciar gravação de tela", - "stop": "Parar gravação" - } - }, - "powerProfile": { - "tooltip": { - "current": "Atual: {profile}", - "unavailable": "Perfis de energia não disponíveis" - } - } - }, - "hooks": { + "hooks": { "title": "Hooks", "system-hooks": { "section": { @@ -1419,7 +1422,7 @@ "calculator-error": "Erro" }, "system": { - "uptime": "Sistema ativo há: {uptime}", + "uptime": "Atividade: {uptime}", "welcome-back": "Bem-vindo(a) de volta, {user}!", "monitor-description": "{model} ({width}x{height})", "scaling-percentage": "{percentage}%", diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 6b21676c..e70ccd30 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -739,53 +739,56 @@ "label": "小部件", "description": "配置和管理控制中心小部件及其显示选项。" } - } - }, - "quickSettings": { - "notifications": { - "label": "通知", - "tooltip": { - "enable": "开启勿扰模式", - "disable": "关闭勿扰模式" + }, + "quickSettings": { + "sectionName": "快速设置" } }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "网络" + "quickSettings": { + "notifications": { + "label": "通知", + "tooltip": { + "enable": "开启勿扰模式", + "disable": "关闭勿扰模式" + } }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi 已连接", - "disconnected": "Wi-Fi 已断开" + "wifi": { + "label": { + "wifi": "Wi-Fi", + "ethernet": "网络" }, - "ethernet": { - "connected": "以太网已连接" + "tooltip": { + "wifi": { + "connected": "Wi-Fi 已连接", + "disconnected": "Wi-Fi 已断开" + }, + "ethernet": { + "connected": "以太网已连接" + } + } + }, + "bluetooth": { + "label": "蓝牙", + "tooltip": { + "enabled": "蓝牙已启用", + "disabled": "蓝牙已禁用" + } + }, + "screenRecorder": { + "label": "屏幕录制", + "tooltip": { + "start": "开始屏幕录制", + "stop": "停止录制" + } + }, + "powerProfile": { + "tooltip": { + "current": "当前:{profile}", + "unavailable": "电源配置文件不可用" } } }, - "bluetooth": { - "label": "蓝牙", - "tooltip": { - "enabled": "蓝牙已启用", - "disabled": "蓝牙已禁用" - } - }, - "screenRecorder": { - "label": "屏幕录制", - "tooltip": { - "start": "开始屏幕录制", - "stop": "停止录制" - } - }, - "powerProfile": { - "tooltip": { - "current": "当前:{profile}", - "unavailable": "电源配置文件不可用" - } - } - }, - "hooks": { + "hooks": { "title": "钩子", "system-hooks": { "section": { diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index 2c9616c2..69f1bf5a 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -52,7 +52,7 @@ NBox { text: I18n.tr("system.uptime", { "uptime": uptimeText }) - pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant } } diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 94e36dbd..756dc1d6 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -10,11 +10,10 @@ import qs.Widgets NPanel { id: root - preferredWidth: 400 + preferredWidth: 360 preferredHeight: topHeight + midHeight + bottomHeight + Math.round(Style.marginL * 4) panelKeyboardFocus: true - readonly property int topHeight: { const columns = (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 const rowsCount = Math.ceil(Settings.data.controlCenter.widgets.quickSettings.length / columns) @@ -33,7 +32,6 @@ NPanel { readonly property int midHeight: 220 readonly property int bottomHeight: 80 - // Positioning readonly property string controlCenterPosition: Settings.data.controlCenter.position panelAnchorHorizontalCenter: controlCenterPosition !== "close_to_bar_button" && controlCenterPosition.endsWith("_center") diff --git a/Widgets/NQuickSetting.qml b/Widgets/NQuickSetting.qml index 2e708e7c..c5706cf9 100644 --- a/Widgets/NQuickSetting.qml +++ b/Widgets/NQuickSetting.qml @@ -300,7 +300,7 @@ Rectangle { onReleased: mouse => { root.scale = 1.0 root.pressed = false - + // Only trigger actions if released while hovering if (root.hovered) { if (mouse.button === Qt.LeftButton) { @@ -322,4 +322,4 @@ Rectangle { } } } -} \ No newline at end of file +} From c96eecedb3f6e1c7f0d2aa9208f32669102cf001 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 20:39:28 -0400 Subject: [PATCH 13/16] i18n-json-check: removed empty nested structure. --- Assets/Translations/de.json | 48 -------- Assets/Translations/es.json | 44 ------- Assets/Translations/fr.json | 44 ------- Assets/Translations/pt.json | 44 ------- Assets/Translations/zh-CN.json | 44 ------- Bin/i18n-json-check.sh | 205 ++++++++++++++++++++++++++++++++- 6 files changed, 200 insertions(+), 229 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index b9c10d0d..21a946a4 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -283,10 +283,6 @@ "section": { "label": "Monitor-Anzeige", "description": "Statusleiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind." - }, - "only-same-output": { - "label": "Nur Apps vom gleichen Bildschirm", - "description": "Zeige nur Apps vom dem Bildschirm an, wo sich das Dock befindet." } } }, @@ -748,50 +744,6 @@ "sectionName": "Schnelleinstellungen" } }, - "quickSettings": { - "notifications": { - "label": "Benachrichtigungen", - "tooltip": { - "enable": "Nicht stören aktivieren", - "disable": "Nicht stören deaktivieren" - } - }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Netzwerk" - }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi verbunden", - "disconnected": "Wi-Fi getrennt" - }, - "ethernet": { - "connected": "Ethernet verbunden" - } - } - }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth aktiviert", - "disabled": "Bluetooth deaktiviert" - } - }, - "screenRecorder": { - "label": "Bildschirm", - "tooltip": { - "start": "Bildschirmaufnahme starten", - "stop": "Aufnahme beenden" - } - }, - "powerProfile": { - "tooltip": { - "current": "Aktuell: {profile}", - "unavailable": "Energieprofile nicht verfügbar" - } - } - }, "hooks": { "title": "Hooks", "system-hooks": { diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 455e93fa..68474d06 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -744,50 +744,6 @@ "sectionName": "Ajustes rápidos" } }, - "quickSettings": { - "notifications": { - "label": "Notificaciones", - "tooltip": { - "enable": "Activar No molestar", - "disable": "Desactivar No molestar" - } - }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Red" - }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi conectado", - "disconnected": "Wi-Fi desconectado" - }, - "ethernet": { - "connected": "Ethernet conectado" - } - } - }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth habilitado", - "disabled": "Bluetooth deshabilitado" - } - }, - "screenRecorder": { - "label": "Pantalla", - "tooltip": { - "start": "Iniciar grabación de pantalla", - "stop": "Detener grabación" - } - }, - "powerProfile": { - "tooltip": { - "current": "Actual: {profile}", - "unavailable": "Perfiles de energía no disponibles" - } - } - }, "hooks": { "title": "Hooks", "system-hooks": { diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index c09015c6..478abc24 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -744,50 +744,6 @@ "sectionName": "Paramètres rapides" } }, - "quickSettings": { - "notifications": { - "label": "Notifications", - "tooltip": { - "enable": "Activer Ne pas déranger", - "disable": "Désactiver Ne pas déranger" - } - }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Réseau" - }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi connecté", - "disconnected": "Wi-Fi déconnecté" - }, - "ethernet": { - "connected": "Ethernet connecté" - } - } - }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth activé", - "disabled": "Bluetooth désactivé" - } - }, - "screenRecorder": { - "label": "Écran", - "tooltip": { - "start": "Démarrer l'enregistrement d'écran", - "stop": "Arrêter l'enregistrement" - } - }, - "powerProfile": { - "tooltip": { - "current": "Actuel : {profile}", - "unavailable": "Profils d'alimentation non disponibles" - } - } - }, "hooks": { "title": "Hooks", "system-hooks": { diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 0c098e50..e614733e 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -710,50 +710,6 @@ "sectionName": "Configurações rápidas" } }, - "quickSettings": { - "notifications": { - "label": "Notificações", - "tooltip": { - "enable": "Ativar Não perturbe", - "disable": "Desativar Não perturbe" - } - }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "Rede" - }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi conectado", - "disconnected": "Wi-Fi desconectado" - }, - "ethernet": { - "connected": "Ethernet conectado" - } - } - }, - "bluetooth": { - "label": "Bluetooth", - "tooltip": { - "enabled": "Bluetooth habilitado", - "disabled": "Bluetooth desabilitado" - } - }, - "screenRecorder": { - "label": "Tela", - "tooltip": { - "start": "Iniciar gravação de tela", - "stop": "Parar gravação" - } - }, - "powerProfile": { - "tooltip": { - "current": "Atual: {profile}", - "unavailable": "Perfis de energia não disponíveis" - } - } - }, "hooks": { "title": "Hooks", "system-hooks": { diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index e70ccd30..d0c913a0 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -744,50 +744,6 @@ "sectionName": "快速设置" } }, - "quickSettings": { - "notifications": { - "label": "通知", - "tooltip": { - "enable": "开启勿扰模式", - "disable": "关闭勿扰模式" - } - }, - "wifi": { - "label": { - "wifi": "Wi-Fi", - "ethernet": "网络" - }, - "tooltip": { - "wifi": { - "connected": "Wi-Fi 已连接", - "disconnected": "Wi-Fi 已断开" - }, - "ethernet": { - "connected": "以太网已连接" - } - } - }, - "bluetooth": { - "label": "蓝牙", - "tooltip": { - "enabled": "蓝牙已启用", - "disabled": "蓝牙已禁用" - } - }, - "screenRecorder": { - "label": "屏幕录制", - "tooltip": { - "start": "开始屏幕录制", - "stop": "停止录制" - } - }, - "powerProfile": { - "tooltip": { - "current": "当前:{profile}", - "unavailable": "电源配置文件不可用" - } - } - }, "hooks": { "title": "钩子", "system-hooks": { diff --git a/Bin/i18n-json-check.sh b/Bin/i18n-json-check.sh index 408677b2..a847d66c 100755 --- a/Bin/i18n-json-check.sh +++ b/Bin/i18n-json-check.sh @@ -181,6 +181,40 @@ inject_translation() { fi } +# Function to remove a key from JSON file using jq +remove_json_key() { + local json_file=$1 + local key_path=$2 + + # Split key path into array + local -a path_parts + IFS='.' read -ra path_parts <<< "$key_path" + + # Build jq path array + local jq_path="[" + for i in "${!path_parts[@]}"; do + if [[ $i -gt 0 ]]; then + jq_path+="," + fi + jq_path+="\"${path_parts[$i]}\"" + done + jq_path+="]" + + # Create a temporary file + local temp_file=$(mktemp) + + # Use jq to delete the path + jq --argjson path "$jq_path" 'delpaths([$path])' "$json_file" > "$temp_file" + + if [[ $? -eq 0 ]]; then + mv "$temp_file" "$json_file" + return 0 + else + rm -f "$temp_file" + return 1 + fi +} + # Function to extract all keys from a JSON file recursively extract_keys() { local json_file=$1 @@ -207,6 +241,78 @@ extract_keys() { ' "$json_file" 2>/dev/null | sort } +# Function to extract empty keys from a JSON file recursively +extract_empty_keys() { + local json_file=$1 + + if [[ ! -f "$json_file" ]]; then + echo "Error: File $json_file not found" >&2 + return 1 + fi + + # Extract all keys with empty string or null values recursively using jq + jq -r ' + def empty_keys_recursive: + if type == "object" then + keys[] as $k | + if (.[$k] | type) == "object" then + ($k + "." + (.[$k] | empty_keys_recursive)) + elif (.[$k] == "" or .[$k] == null) then + $k + else + empty + end + else + empty + end; + empty_keys_recursive + ' "$json_file" 2>/dev/null | sort +} + +# Function to remove empty objects recursively from JSON file +remove_empty_objects() { + local json_file=$1 + + # Create a temporary file + local temp_file=$(mktemp) + + # Use jq to recursively remove empty objects + # This function walks the entire JSON tree and removes any object that contains no leaf values + jq ' + def remove_empty: + if type == "object" then + to_entries | + map( + .value |= remove_empty + ) | + map( + select( + .value != {} and + .value != [] and + .value != null and + .value != "" + ) + ) | + from_entries | + if length == 0 then empty else . end + elif type == "array" then + map(remove_empty) | + map(select(. != null and . != {} and . != [] and . != "")) + else + . + end; + remove_empty + ' "$json_file" > "$temp_file" 2>/dev/null + + if [[ $? -eq 0 ]]; then + mv "$temp_file" "$json_file" + return 0 + else + rm -f "$temp_file" + return 1 + fi +} + # Function to get language files get_language_files() { find "$FOLDER_PATH" -maxdepth 1 -name "*.json" -type f | sort @@ -223,15 +329,20 @@ generate_header() { echo "Reference file: $REFERENCE_FILE" echo "Folder: $(realpath "$FOLDER_PATH")" if $TRANSLATE_MODE; then - echo "Mode: TRANSLATION ENABLED" + echo "Mode: TRANSLATION ENABLED (translates missing keys, removes extra/empty keys and empty objects)" fi echo "" echo "Notes:" echo "- Keys are compared recursively through all nested JSON objects" echo "- Missing keys indicate incomplete translations" echo "- Extra keys might indicate deprecated keys or translation-specific additions" + echo "- Empty keys are keys with empty string (\"\") or null values" + echo "- Empty objects are nested objects containing no actual values (only other empty objects)" echo "- Translation completion percentage is calculated based on English reference" echo "- Results are sorted by descending line numbers for easier editing" + if $TRANSLATE_MODE; then + echo "- In translation mode, extra keys, empty keys, and empty objects are automatically removed" + fi echo "" echo "This report compares all language JSON files against the English reference file" echo "and identifies missing keys and extra keys in each language." @@ -427,11 +538,92 @@ compare_language() { done rm -f "$temp_extra" echo "" + + # Remove extra keys if in translate mode + if $TRANSLATE_MODE; then + print_color $BLUE "Removing extra keys from $lang_name..." >&2 + local removed_count=0 + local failed_removal_count=0 + + while IFS= read -r key; do + if [[ -n "$key" ]]; then + print_color $YELLOW " Removing: $key" >&2 + + if remove_json_key "$lang_file" "$key"; then + print_color $GREEN " ✓ Removed: $key" >&2 + removed_count=$((removed_count + 1)) + else + print_color $RED " ✗ Failed to remove: $key" >&2 + failed_removal_count=$((failed_removal_count + 1)) + fi + fi + done <<< "$extra_keys" + + echo "" + print_color $GREEN "Removal complete: $removed_count removed, $failed_removal_count failed" >&2 + echo "" + fi else echo "✅ No extra keys in $lang_name" echo "" fi + # Handle empty keys in translate mode + if $TRANSLATE_MODE; then + local empty_keys=$(extract_empty_keys "$lang_file") + local empty_count=$(count_non_empty_lines "$empty_keys") + + if [[ $empty_count -gt 0 && -n "$empty_keys" ]]; then + echo "EMPTY KEYS IN $lang_name:" + + # Display empty keys + local counter=1 + while IFS= read -r key; do + if [[ -n "$key" ]]; then + local lang_line=$(find_key_line_number "$lang_file" "$key") + printf " %3d. %s (%s:%s)\n" "$counter" "$key" "$(basename "$lang_file")" "$lang_line" + counter=$((counter + 1)) + fi + done <<< "$empty_keys" + echo "" + + print_color $BLUE "Removing empty keys from $lang_name..." >&2 + local removed_empty_count=0 + local failed_empty_removal_count=0 + + while IFS= read -r key; do + if [[ -n "$key" ]]; then + print_color $YELLOW " Removing empty key: $key" >&2 + + if remove_json_key "$lang_file" "$key"; then + print_color $GREEN " ✓ Removed: $key" >&2 + removed_empty_count=$((removed_empty_count + 1)) + else + print_color $RED " ✗ Failed to remove: $key" >&2 + failed_empty_removal_count=$((failed_empty_removal_count + 1)) + fi + fi + done <<< "$empty_keys" + + echo "" + print_color $GREEN "Empty key removal complete: $removed_empty_count removed, $failed_empty_removal_count failed" >&2 + echo "" + else + echo "✅ No empty keys in $lang_name" + echo "" + fi + + # Remove empty objects (nested objects with no actual values) + print_color $BLUE "Cleaning up empty objects in $lang_name..." >&2 + if remove_empty_objects "$lang_file"; then + print_color $GREEN "✓ Successfully removed all empty objects" >&2 + echo "" + else + print_color $RED "✗ Failed to clean up empty objects" >&2 + echo "" + fi + fi + # Clean up rm -f "$lang_keys_file" } @@ -545,7 +737,7 @@ main() { echo "Target language: $target_language" fi if $TRANSLATE_MODE; then - echo "Translation mode: ENABLED" + echo "Translation mode: ENABLED (translated missing keys, removed extra keys, removed empty keys and objects)" fi echo "Report generated: $(date '+%Y-%m-%d %H:%M:%S')" echo "" @@ -568,7 +760,9 @@ show_usage() { echo "This script compares JSON language files in '$FOLDER_PATH' against the English reference." >&2 echo "" >&2 echo "Arguments:" >&2 - echo " --translate Enable automatic translation of missing keys using Gemini API" >&2 + echo " --translate Enable automatic translation of missing keys, removal of extra keys," >&2 + echo " removal of empty keys (empty strings or null values), and removal of" >&2 + echo " empty objects (nested objects containing no actual values)" >&2 echo " --list-models List all available Gemini models and exit" >&2 echo " language_code Optional. Compare only the specified language (e.g., 'fr', 'es', 'de')" >&2 echo " If not provided, all language files will be compared" >&2 @@ -581,8 +775,8 @@ show_usage() { echo " $0 # Compare all languages" >&2 echo " $0 fr # Compare only French (fr.json)" >&2 echo " $0 --list-models # List available Gemini models" >&2 - echo " $0 --translate # Compare all and translate missing keys" >&2 - echo " $0 --translate fr # Translate missing keys for French only" >&2 + echo " $0 --translate # Compare all, translate missing, remove extra/empty keys and objects" >&2 + echo " $0 --translate fr # Translate and clean French only" >&2 echo "" >&2 echo "Requirements:" >&2 echo " - jq must be installed" >&2 @@ -595,6 +789,7 @@ show_usage() { echo " - Comparison report is printed to stdout" >&2 echo " - Progress messages are printed to stderr" >&2 echo " - Results are sorted by descending line numbers for easier editing" >&2 + echo " - In translate mode, extra keys, empty keys, and empty objects are removed" >&2 } # Handle command line arguments From b2c5c71116902e18e2cf1dec4b11da86c147da82 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 20:48:30 -0400 Subject: [PATCH 14/16] NFilePicker: added missing translations --- Assets/Translations/de.json | 6 +++++- Assets/Translations/en.json | 6 +++++- Assets/Translations/es.json | 6 +++++- Assets/Translations/fr.json | 6 +++++- Assets/Translations/pt.json | 6 +++++- Assets/Translations/zh-CN.json | 6 +++++- .../Settings/Bar/BarWidgetSettingsDialog.qml | 2 +- Widgets/NFilePicker.qml | 18 +++++++++--------- 8 files changed, 40 insertions(+), 16 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 21a946a4..79211cbb 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -801,7 +801,11 @@ }, "file-picker": { "select-folder": "Ordner auswählen", - "select-file": "Datei auswählen" + "select-file": "Datei auswählen", + "cancel": "Abbrechen", + "search-placeholder": "Dateien und Ordner suchen...", + "select-current": "Aktuelle auswählen", + "title": "Dateiauswahl" }, "datetime-tokens": { "common": { diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 4401d058..b2c0df34 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -785,8 +785,12 @@ "placeholder": "Placeholder" }, "file-picker": { + "title": "File Picker", "select-folder": "Select Folder", - "select-file": "Select File" + "select-file": "Select File", + "search-placeholder": "Search files and folders...", + "select-current": "Select Current", + "cancel": "Cancel" }, "datetime-tokens": { "common": { diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 68474d06..53a69f7a 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -784,7 +784,11 @@ }, "file-picker": { "select-folder": "Seleccionar carpeta", - "select-file": "Seleccionar archivo" + "select-file": "Seleccionar archivo", + "cancel": "Cancelar", + "search-placeholder": "Buscar archivos y carpetas...", + "select-current": "Seleccionar actual", + "title": "Selector de archivos" }, "datetime-tokens": { "common": { diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 478abc24..2a5b07f9 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -784,7 +784,11 @@ }, "file-picker": { "select-folder": "Sélectionner un dossier", - "select-file": "Sélectionner un fichier" + "select-file": "Sélectionner un fichier", + "cancel": "Annuler", + "search-placeholder": "Rechercher des fichiers et des dossiers...", + "select-current": "Sélectionner Actuel", + "title": "Sélecteur de fichiers" }, "datetime-tokens": { "common": { diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index e614733e..528ff799 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -784,7 +784,11 @@ }, "file-picker": { "select-folder": "Selecionar Pasta", - "select-file": "Selecionar Arquivo" + "select-file": "Selecionar Arquivo", + "cancel": "Cancelar", + "search-placeholder": "Pesquisar arquivos e pastas...", + "select-current": "Selecionar Atual", + "title": "Seletor de Arquivos" }, "datetime-tokens": { "common": { diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index d0c913a0..23af1975 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -784,7 +784,11 @@ }, "file-picker": { "select-folder": "选择文件夹", - "select-file": "选择文件" + "select-file": "选择文件", + "cancel": "取消", + "search-placeholder": "搜索文件和文件夹...", + "select-current": "选择当前", + "title": "文件选择器" }, "datetime-tokens": { "common": { diff --git a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml index 1c2a1aaf..4eac93d3 100644 --- a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml @@ -69,7 +69,7 @@ Popup { NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") onClicked: widgetSettings.close() } } diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index 2eed6c9a..4013c59c 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -13,7 +13,7 @@ Popup { id: root // Properties - property string title: "File Picker" + property string title: I18n.tr("widget.file-picker.title") property string initialPath: Quickshell.env("HOME") || "/home" property string selectionMode: "files" // "files" or "folders" property var nameFilters: ["*"] @@ -203,7 +203,7 @@ Popup { // "Select Current" button only visible in folder selection mode NButton { - text: "Select Current" + text: I18n.tr("widgets.file-picker.select-current") icon: "filepicker-folder-current" visible: root.selectionMode === "folders" onClicked: { @@ -214,7 +214,7 @@ Popup { NIconButton { icon: "filepicker-refresh" - tooltipText: "Refresh" + tooltipText: I18n.tr("tooltips.refresh") onClicked: { // Force a proper refresh by resetting the folder const currentFolder = folderModel.folder @@ -225,7 +225,7 @@ Popup { } NIconButton { icon: "filepicker-close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") onClicked: { root.cancelled() root.close() @@ -256,7 +256,7 @@ Popup { NIconButton { icon: "filepicker-arrow-up" - tooltipText: "Up" + tooltipText: I18n.tr("tooltips.up") baseSize: Style.baseWidgetSize * 0.8 enabled: folderModel.folder.toString() !== "file:///" onClicked: { @@ -268,7 +268,7 @@ Popup { NIconButton { icon: "filepicker-home" - tooltipText: "Home" + tooltipText: I18n.tr("tooltips.home") baseSize: Style.baseWidgetSize * 0.8 onClicked: { const homePath = Quickshell.env("HOME") || "/home" @@ -361,7 +361,7 @@ Popup { } NTextInput { id: searchInput - placeholderText: "Search files and folders..." + placeholderText: I18n.tr("widget.file-picker.search-placeholder") Layout.fillWidth: true text: filePickerPanel.searchText onTextChanged: { @@ -378,7 +378,7 @@ Popup { } NIconButton { icon: "filepicker-x" - tooltipText: "Clear" + tooltipText: I18n.tr("tooltips.clear") baseSize: Style.baseWidgetSize * 0.6 visible: filePickerPanel.searchText.length > 0 onClicked: { @@ -814,7 +814,7 @@ Popup { } NButton { - text: "Cancel" + text: I18n.tr("widgets.file-picker.cancel") outlined: true onClicked: { root.cancelled() From 789354464de479fa953f2d5a236a1f6d969ca15b Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Thu, 9 Oct 2025 21:29:07 -0400 Subject: [PATCH 15/16] QuickSettings: minor layout tweaks --- Modules/ControlCenter/Cards/MediaCard.qml | 6 +++--- Modules/ControlCenter/Cards/TopCard.qml | 2 +- Modules/ControlCenter/ControlCenterPanel.qml | 2 +- Modules/ControlCenter/Widgets/Bluetooth.qml | 2 -- Modules/ControlCenter/Widgets/KeepAwake.qml | 2 -- Modules/ControlCenter/Widgets/NightLight.qml | 2 -- Modules/ControlCenter/Widgets/Notifications.qml | 2 -- Modules/ControlCenter/Widgets/PowerProfile.qml | 2 -- Modules/ControlCenter/Widgets/ScreenRecorder.qml | 2 -- Modules/ControlCenter/Widgets/WallpaperSelector.qml | 2 -- Modules/ControlCenter/Widgets/WiFi.qml | 2 -- Widgets/NQuickSetting.qml | 5 +++-- 12 files changed, 8 insertions(+), 23 deletions(-) diff --git a/Modules/ControlCenter/Cards/MediaCard.qml b/Modules/ControlCenter/Cards/MediaCard.qml index 0781b984..4484e27f 100644 --- a/Modules/ControlCenter/Cards/MediaCard.qml +++ b/Modules/ControlCenter/Cards/MediaCard.qml @@ -84,7 +84,7 @@ NBox { anchors.fill: parent values: CavaService.values fillColor: Color.mPrimary - opacity: MediaService.trackArtUrl !== "" ? 0.4 : 0.8 + opacity: MediaService.trackArtUrl !== "" ? 0.5 : 0.8 } } @@ -94,7 +94,7 @@ NBox { anchors.fill: parent values: CavaService.values fillColor: Color.mPrimary - opacity: MediaService.trackArtUrl !== "" ? 0.4 : 0.8 + opacity: MediaService.trackArtUrl !== "" ? 0.5 : 0.8 } } @@ -104,7 +104,7 @@ NBox { anchors.fill: parent values: CavaService.values fillColor: Color.mPrimary - opacity: MediaService.trackArtUrl !== "" ? 0.4 : 0.8 + opacity: MediaService.trackArtUrl !== "" ? 0.5 : 0.8 } } } diff --git a/Modules/ControlCenter/Cards/TopCard.qml b/Modules/ControlCenter/Cards/TopCard.qml index 69f1bf5a..21b68eca 100644 --- a/Modules/ControlCenter/Cards/TopCard.qml +++ b/Modules/ControlCenter/Cards/TopCard.qml @@ -106,7 +106,7 @@ NBox { id: grid Layout.fillWidth: true columns: (Settings.data.controlCenter.quickSettingsStyle === "compact") ? 4 : 3 - columnSpacing: Style.marginM * scaling + columnSpacing: Style.marginS * scaling rowSpacing: Style.marginS * scaling Repeater { diff --git a/Modules/ControlCenter/ControlCenterPanel.qml b/Modules/ControlCenter/ControlCenterPanel.qml index 756dc1d6..e5b2145d 100644 --- a/Modules/ControlCenter/ControlCenterPanel.qml +++ b/Modules/ControlCenter/ControlCenterPanel.qml @@ -10,7 +10,7 @@ import qs.Widgets NPanel { id: root - preferredWidth: 360 + preferredWidth: 400 preferredHeight: topHeight + midHeight + bottomHeight + Math.round(Style.marginL * 4) panelKeyboardFocus: true diff --git a/Modules/ControlCenter/Widgets/Bluetooth.qml b/Modules/ControlCenter/Widgets/Bluetooth.qml index 9150004d..e9886a4f 100644 --- a/Modules/ControlCenter/Widgets/Bluetooth.qml +++ b/Modules/ControlCenter/Widgets/Bluetooth.qml @@ -9,8 +9,6 @@ NQuickSetting { property real scaling: 1.0 text: I18n.tr("quickSettings.bluetooth.label.enabled") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off" tooltipText: I18n.tr("quickSettings.bluetooth.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/KeepAwake.qml b/Modules/ControlCenter/Widgets/KeepAwake.qml index fff72489..044734e4 100644 --- a/Modules/ControlCenter/Widgets/KeepAwake.qml +++ b/Modules/ControlCenter/Widgets/KeepAwake.qml @@ -9,8 +9,6 @@ NQuickSetting { property real scaling: 1.0 text: I18n.tr("quickSettings.keepAwake.label.enabled") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" hot: IdleInhibitorService.isInhibited tooltipText: I18n.tr("quickSettings.keepAwake.tooltip.action") diff --git a/Modules/ControlCenter/Widgets/NightLight.qml b/Modules/ControlCenter/Widgets/NightLight.qml index dac6dd98..19cdd669 100644 --- a/Modules/ControlCenter/Widgets/NightLight.qml +++ b/Modules/ControlCenter/Widgets/NightLight.qml @@ -10,8 +10,6 @@ NQuickSetting { enabled: ProgramCheckerService.wlsunsetAvailable text: I18n.tr("quickSettings.nightLight.label.enabled") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" hot: !Settings.data.nightLight.enabled || Settings.data.nightLight.forced style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/Notifications.qml b/Modules/ControlCenter/Widgets/Notifications.qml index 7d8085e4..19c22a82 100644 --- a/Modules/ControlCenter/Widgets/Notifications.qml +++ b/Modules/ControlCenter/Widgets/Notifications.qml @@ -9,8 +9,6 @@ NQuickSetting { property real scaling: 1.0 text: Settings.data.notifications.doNotDisturb ? I18n.tr("quickSettings.notifications.label.disabled") : I18n.tr("quickSettings.notifications.label.enabled") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" hot: Settings.data.notifications.doNotDisturb tooltipText: I18n.tr("quickSettings.notifications.tooltip.action") diff --git a/Modules/ControlCenter/Widgets/PowerProfile.qml b/Modules/ControlCenter/Widgets/PowerProfile.qml index 442cc9c5..1a504963 100644 --- a/Modules/ControlCenter/Widgets/PowerProfile.qml +++ b/Modules/ControlCenter/Widgets/PowerProfile.qml @@ -13,8 +13,6 @@ NQuickSetting { enabled: hasPP text: hasPP ? PowerProfileService.getName() : I18n.tr("quickSettings.powerProfile.label.unavailable") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium icon: PowerProfileService.getIcon() hot: !PowerProfileService.isDefault() tooltipText: I18n.tr("quickSettings.powerProfile.tooltip.action") diff --git a/Modules/ControlCenter/Widgets/ScreenRecorder.qml b/Modules/ControlCenter/Widgets/ScreenRecorder.qml index a53e3950..f9ad8786 100644 --- a/Modules/ControlCenter/Widgets/ScreenRecorder.qml +++ b/Modules/ControlCenter/Widgets/ScreenRecorder.qml @@ -11,8 +11,6 @@ NQuickSetting { enabled: ProgramCheckerService.gpuScreenRecorderAvailable icon: "camera-video" text: ScreenRecorderService.isRecording ? I18n.tr("quickSettings.screenRecorder.label.recording") : I18n.tr("quickSettings.screenRecorder.label.stopped") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium hot: ScreenRecorderService.isRecording tooltipText: I18n.tr("quickSettings.screenRecorder.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/WallpaperSelector.qml b/Modules/ControlCenter/Widgets/WallpaperSelector.qml index e4531ecd..95a50af3 100644 --- a/Modules/ControlCenter/Widgets/WallpaperSelector.qml +++ b/Modules/ControlCenter/Widgets/WallpaperSelector.qml @@ -11,8 +11,6 @@ NQuickSetting { enabled: Settings.data.wallpaper.enabled icon: "wallpaper-selector" text: I18n.tr("quickSettings.wallpaperSelector.label") - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium tooltipText: I18n.tr("quickSettings.wallpaperSelector.tooltip.action") style: Settings.data.controlCenter.quickSettingsStyle || "modern" diff --git a/Modules/ControlCenter/Widgets/WiFi.qml b/Modules/ControlCenter/Widgets/WiFi.qml index 29c89a8a..7f739866 100644 --- a/Modules/ControlCenter/Widgets/WiFi.qml +++ b/Modules/ControlCenter/Widgets/WiFi.qml @@ -43,8 +43,6 @@ NQuickSetting { return connected ? I18n.tr("quickSettings.wifi.label.wifi") : I18n.tr("quickSettings.wifi.label.disconnected") } - fontSize: Style.fontSizeS * scaling - fontWeight: Style.fontWeightMedium style: Settings.data.controlCenter.quickSettingsStyle || "modern" tooltipText: I18n.tr("quickSettings.wifi.tooltip.action") onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) diff --git a/Widgets/NQuickSetting.qml b/Widgets/NQuickSetting.qml index c5706cf9..7b559019 100644 --- a/Widgets/NQuickSetting.qml +++ b/Widgets/NQuickSetting.qml @@ -17,7 +17,7 @@ Rectangle { property string style: "modern" // "modern", "classic", or "compact" // Styling properties - property real fontSize: Style.fontSizeS * scaling + property real fontSize: (style === "classic") ? Style.fontSizeXS * scaling : Style.fontSizeS * scaling property int fontWeight: Style.fontWeightMedium property real iconSize: Style.fontSizeL * scaling property real cornerRadius: Style.radiusM * scaling @@ -171,7 +171,7 @@ Rectangle { } } - // Text content + // Modern - Text content NText { Layout.alignment: Qt.AlignHCenter visible: root.text !== "" @@ -245,6 +245,7 @@ Rectangle { } } + // Classic - Text content NText { visible: root.text !== "" text: root.text From 8f614194df94fc3f7f928bdeb5c7888bf888b314 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Fri, 10 Oct 2025 07:42:28 -0400 Subject: [PATCH 16/16] QuickSettings: added wallpaper selector to the defaults --- Assets/settings-default.json | 3 +++ Commons/Settings.qml | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 05ccde05..34e4eb59 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -124,6 +124,9 @@ }, { "id": "PowerProfile" + }, + { + "id": "WallpaperSelector" } ] } diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 960edd67..2f686558 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -255,6 +255,8 @@ Singleton { "id": "ScreenRecorder" }, { "id": "PowerProfile" + }, { + "id": "WallpaperSelector" }] } }