diff --git a/Assets/Fonts/tabler/tabler-icons.ttf b/Assets/Fonts/tabler/tabler-icons.ttf index 2d936ba..8626fa1 100644 Binary files a/Assets/Fonts/tabler/tabler-icons.ttf and b/Assets/Fonts/tabler/tabler-icons.ttf differ diff --git a/Commons/Settings.qml b/Commons/Settings.qml index a6ecf64..7d3d885 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -121,12 +121,6 @@ Singleton { } } } - - // Upgrade the density of the bar so the look stay the same for people who upgrade. - if (adapter.settingsVersion == 2) { - adapter.bar.density = "comfortable" - adapter.settingsVersion++ - } } // ----------------------------------------------------- @@ -265,15 +259,13 @@ Singleton { JsonAdapter { id: adapter - property int settingsVersion: 3 + property int settingsVersion: 2 // bar property JsonObject bar: JsonObject { property string position: "top" // "top", "bottom", "left", or "right" property real backgroundOpacity: 1.0 property list monitors: [] - property string density: "default" // "compact", "default", "comfortable" - property bool showCapsule: true // Floating bar settings property bool floating: false @@ -328,7 +320,7 @@ Singleton { // general property JsonObject general: JsonObject { property string avatarImage: defaultAvatar - property bool dimDesktop: true + property bool dimDesktop: false property bool showScreenCorners: false property bool forceBlackScreenCorners: false property real radiusRatio: 1.0 diff --git a/Commons/Style.qml b/Commons/Style.qml index 2136e2e..99d88e6 100644 --- a/Commons/Style.qml +++ b/Commons/Style.qml @@ -65,36 +65,14 @@ Singleton { property int animationSlow: Math.round(450 / Settings.data.general.animationSpeed) property int animationSlowest: Math.round(750 / Settings.data.general.animationSpeed) + // Dimensions + property int barHeight: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 39 : 37 + property int capsuleHeight: (barHeight * 0.73) + property int baseWidgetSize: (barHeight * 0.9) + property int sliderWidth: 200 + // Delays property int tooltipDelay: 300 property int tooltipDelayLong: 1200 property int pillDelay: 500 - - // Settings widgets base size - property real baseWidgetSize: 33 - property real sliderWidth: 200 - - // Bar Dimensions - property real barHeight: { - if (Settings.data.bar.density === "compact") { - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 27 : 25 - } - if (Settings.data.bar.density === "default") { - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 33 : 31 - } - if (Settings.data.bar.density === "comfortable") { - return (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? 39 : 37 - } - } - property real capsuleHeight: { - if (Settings.data.bar.density === "compact") { - return barHeight * 0.85 - } - if (Settings.data.bar.density === "default") { - return barHeight * 0.82 - } - if (Settings.data.bar.density === "comfortable") { - return barHeight * 0.73 - } - } } diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index c98798f..11a618d 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -68,12 +68,23 @@ Variants { radius: Settings.data.bar.floating ? Style.radiusL : 0 } + // For vertical bars, use a single column layout Loader { + id: verticalBarLayout anchors.fill: parent - sourceComponent: (Settings.data.bar.position === "left" || Settings.data.bar.position === "right") ? verticalBarComponent : horizontalBarComponent + visible: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" + sourceComponent: verticalBarComponent } - // For vertical bars + // For horizontal bars, use the original three-section layout + Loader { + id: horizontalBarLayout + anchors.fill: parent + visible: Settings.data.bar.position === "top" || Settings.data.bar.position === "bottom" + sourceComponent: horizontalBarComponent + } + + // Main layout components Component { id: verticalBarComponent Item { @@ -152,7 +163,6 @@ Variants { } } - // For horizontal bars Component { id: horizontalBarComponent Item { diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index c190445..e9bb66d 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -37,18 +37,8 @@ Item { readonly property real maxWidth: minWidth * 2 readonly property string barPosition: Settings.data.bar.position - readonly property bool isVertical: barPosition === "left" || barPosition === "right" - readonly property bool compact: (Settings.data.bar.density === "compact") - implicitHeight: (barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling) - implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * 0.8 * scaling) : (horizontalLayout.implicitWidth + Style.marginM * 2 * scaling) - - readonly property real textSize: { - var base = isVertical ? width : height - return Math.max(1, compact ? base * 0.43 : base * 0.33) - } - - readonly property real iconSize: textSize * 1.25 + implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (horizontalLayout.implicitWidth + Style.marginM * 2 * scaling) function getTitle() { try { @@ -70,7 +60,7 @@ Item { let total = Style.marginM * 2 * scaling // internal padding if (showIcon) { - total += Style.capsuleHeight * 0.5 * scaling + 2 * scaling // icon + spacing + total += Style.baseWidgetSize * 0.5 * scaling + 2 * scaling // icon + spacing } // Calculate actual text width more accurately @@ -139,14 +129,12 @@ Item { Rectangle { id: windowTitleRect visible: root.visible - anchors.left: (barPosition === "top" || barPosition === "bottom") ? parent.left : undefined - anchors.top: (barPosition === "left" || barPosition === "right") ? parent.top : undefined + anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : (horizontalLayout.implicitWidth + Style.marginM * 2 * scaling) height: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : Math.round(Style.capsuleHeight * scaling) - radius: width / 2 - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + radius: Math.round(Style.radiusM * scaling) + color: Color.mSurfaceVariant Item { id: mainContainer @@ -164,8 +152,8 @@ Item { // Window icon Item { - Layout.preferredWidth: Style.capsuleHeight * 0.75 * scaling - Layout.preferredHeight: Style.capsuleHeight * 0.75 * scaling + Layout.preferredWidth: Style.baseWidgetSize * 0.5 * scaling + Layout.preferredHeight: Style.baseWidgetSize * 0.5 * scaling Layout.alignment: Qt.AlignVCenter visible: getTitle() !== "" && showIcon @@ -229,9 +217,10 @@ Item { // Window icon Item { - width: Style.capsuleHeight * 0.75 * scaling - height: Style.capsuleHeight * 0.75 * scaling + width: Style.baseWidgetSize * 0.5 * scaling + height: Style.baseWidgetSize * 0.5 * scaling anchors.centerIn: parent + visible: getTitle() !== "" && showIcon IconImage { id: windowIconVertical diff --git a/Modules/Bar/Widgets/Battery.qml b/Modules/Bar/Widgets/Battery.qml index 2b5ec67..fa2705b 100644 --- a/Modules/Bar/Widgets/Battery.qml +++ b/Modules/Bar/Widgets/Battery.qml @@ -5,7 +5,6 @@ import QtQuick.Layouts import qs.Commons import qs.Services import qs.Widgets -import qs.Modules.Bar.Extras Item { id: root @@ -82,11 +81,10 @@ Item { } } - BarPill { + NPill { id: pill - compact: (Settings.data.bar.density === "compact") - rightOpen: BarWidgetRegistry.getPillDirection(root) + rightOpen: BarWidgetRegistry.getNPillDirection(root) icon: testMode ? BatteryService.getIcon(testPercent, testCharging, true) : BatteryService.getIcon(percent, charging, isReady) text: (isReady || testMode) ? Math.round(percent) : "-" suffix: "%" diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml index 656794b..41588bf 100644 --- a/Modules/Bar/Widgets/Bluetooth.qml +++ b/Modules/Bar/Widgets/Bluetooth.qml @@ -13,9 +13,8 @@ NIconButton { property ShellScreen screen property real scaling: 1.0 - baseSize: Style.capsuleHeight - compact: (Settings.data.bar.density === "compact") - colorBg: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + sizeRatio: 0.8 + colorBg: Color.mSurfaceVariant colorFg: Color.mOnSurface colorBorder: Color.transparent colorBorderHover: Color.transparent diff --git a/Modules/Bar/Widgets/Brightness.qml b/Modules/Bar/Widgets/Brightness.qml index c588b1d..0ca072e 100644 --- a/Modules/Bar/Widgets/Brightness.qml +++ b/Modules/Bar/Widgets/Brightness.qml @@ -4,7 +4,6 @@ import qs.Commons import qs.Modules.SettingsPanel import qs.Services import qs.Widgets -import qs.Modules.Bar.Extras Item { id: root @@ -74,11 +73,10 @@ Item { onTriggered: pill.hide() } - BarPill { + NPill { id: pill - compact: (Settings.data.bar.density === "compact") - rightOpen: BarWidgetRegistry.getPillDirection(root) + rightOpen: BarWidgetRegistry.getNPillDirection(root) icon: getIcon() autoHide: false // Important to be false so we can hover as long as we want text: { diff --git a/Modules/Bar/Widgets/Clock.qml b/Modules/Bar/Widgets/Clock.qml index 3b2e4f7..45ebece 100644 --- a/Modules/Bar/Widgets/Clock.qml +++ b/Modules/Bar/Widgets/Clock.qml @@ -29,7 +29,6 @@ Rectangle { } readonly property string barPosition: Settings.data.bar.position - readonly property bool compact: (Settings.data.bar.density === "compact") // Resolve settings: try user settings or defaults from BarWidgetRegistry readonly property bool use12h: widgetSettings.use12HourClock !== undefined ? widgetSettings.use12HourClock : widgetMetadata.use12HourClock @@ -40,15 +39,15 @@ Rectangle { readonly property bool verticalMode: barPosition === "left" || barPosition === "right" implicitWidth: verticalMode ? Math.round(Style.capsuleHeight * scaling) : Math.round(layout.implicitWidth + Style.marginM * 2 * scaling) - implicitHeight: verticalMode ? Math.round(Style.capsuleHeight * 2.5 * scaling) : Math.round(Style.capsuleHeight * scaling) // Match BarPill + implicitHeight: verticalMode ? Math.round(Style.capsuleHeight * 2.5 * scaling) : Math.round(Style.baseWidgetSize * 0.8 * scaling) // Match NPill radius: Math.round(Style.radiusS * scaling) - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant Item { id: clockContainer anchors.fill: parent - anchors.margins: compact ? 0 : Style.marginXS * scaling + anchors.margins: Style.marginXS * scaling ColumnLayout { id: layout diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 496c670..9ab1b11 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -6,7 +6,6 @@ import qs.Commons import qs.Services import qs.Widgets import qs.Modules.SettingsPanel -import qs.Modules.Bar.Extras Item { id: root @@ -44,13 +43,12 @@ Item { implicitWidth: pill.width implicitHeight: pill.height - BarPill { + NPill { id: pill - rightOpen: BarWidgetRegistry.getPillDirection(root) + rightOpen: BarWidgetRegistry.getNPillDirection(root) icon: customIcon text: _dynamicText - compact: (Settings.data.bar.density === "compact") autoHide: false forceOpen: _dynamicText !== "" forceClose: false diff --git a/Modules/Bar/Widgets/DarkModeToggle.qml b/Modules/Bar/Widgets/DarkModeToggle.qml index a5ada46..cf68958 100644 --- a/Modules/Bar/Widgets/DarkModeToggle.qml +++ b/Modules/Bar/Widgets/DarkModeToggle.qml @@ -10,10 +10,10 @@ NIconButton { property real scaling: 1.0 icon: "dark-mode" - tooltipText: "Toggle light/dark mode." - compact: (Settings.data.bar.density === "compact") - baseSize: Style.capsuleHeight - colorBg: Settings.data.colorSchemes.darkMode ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary + tooltipText: "Toggle light/dark mode" + sizeRatio: 0.8 + + colorBg: Settings.data.colorSchemes.darkMode ? Color.mSurfaceVariant : Color.mPrimary colorFg: Settings.data.colorSchemes.darkMode ? Color.mOnSurface : Color.mOnPrimary colorBorder: Color.transparent colorBorderHover: Color.transparent diff --git a/Modules/Bar/Widgets/KeepAwake.qml b/Modules/Bar/Widgets/KeepAwake.qml index 9c4626f..10a55f2 100644 --- a/Modules/Bar/Widgets/KeepAwake.qml +++ b/Modules/Bar/Widgets/KeepAwake.qml @@ -11,12 +11,14 @@ NIconButton { property ShellScreen screen property real scaling: 1.0 - baseSize: Style.capsuleHeight - compact: (Settings.data.bar.density === "compact") + sizeRatio: 0.8 + icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" tooltipText: IdleInhibitorService.isInhibited ? "Disable keep awake" : "Enable keep awake" - colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) + colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : Color.mSurfaceVariant colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mOnSurface colorBorder: Color.transparent - onClicked: IdleInhibitorService.manualToggle() + onClicked: { + IdleInhibitorService.manualToggle() + } } diff --git a/Modules/Bar/Widgets/KeyboardLayout.qml b/Modules/Bar/Widgets/KeyboardLayout.qml index 13b4dac..87aef27 100644 --- a/Modules/Bar/Widgets/KeyboardLayout.qml +++ b/Modules/Bar/Widgets/KeyboardLayout.qml @@ -6,7 +6,6 @@ import Quickshell.Io import qs.Commons import qs.Services import qs.Widgets -import qs.Modules.Bar.Extras Item { id: root @@ -39,12 +38,11 @@ Item { implicitWidth: pill.width implicitHeight: pill.height - BarPill { + NPill { id: pill anchors.verticalCenter: parent.verticalCenter - compact: (Settings.data.bar.density === "compact") - rightOpen: BarWidgetRegistry.getPillDirection(root) + rightOpen: BarWidgetRegistry.getNPillDirection(root) icon: "keyboard" autoHide: false // Important to be false so we can hover as long as we want text: currentLayout.toUpperCase() diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 6d55d48..5cdf228 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -31,7 +31,6 @@ Item { } readonly property string barPosition: Settings.data.bar.position - readonly property bool compact: (Settings.data.bar.density === "compact") readonly property bool showAlbumArt: (widgetSettings.showAlbumArt !== undefined) ? widgetSettings.showAlbumArt : widgetMetadata.showAlbumArt readonly property bool showVisualizer: (widgetSettings.showVisualizer !== undefined) ? widgetSettings.showVisualizer : widgetMetadata.showVisualizer @@ -82,7 +81,7 @@ Item { width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (rowLayout.implicitWidth + Style.marginM * 2 * scaling) height: (barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : Math.round(Style.capsuleHeight * scaling) radius: (barPosition === "left" || barPosition === "right") ? width / 2 : Math.round(Style.radiusM * scaling) - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant // Used to anchor the tooltip, so the tooltip does not move when the content expands Item { diff --git a/Modules/Bar/Widgets/Microphone.qml b/Modules/Bar/Widgets/Microphone.qml index 7504414..3844260 100644 --- a/Modules/Bar/Widgets/Microphone.qml +++ b/Modules/Bar/Widgets/Microphone.qml @@ -6,7 +6,6 @@ import qs.Commons import qs.Modules.SettingsPanel import qs.Services import qs.Widgets -import qs.Modules.Bar.Extras Item { id: root @@ -87,11 +86,10 @@ Item { } } - BarPill { + NPill { id: pill - rightOpen: BarWidgetRegistry.getPillDirection(root) + rightOpen: BarWidgetRegistry.getNPillDirection(root) icon: getIcon() - compact: (Settings.data.bar.density === "compact") autoHide: false // Important to be false so we can hover as long as we want text: Math.floor(AudioService.inputVolume * 100) suffix: "%" diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml index d48097c..43028a1 100644 --- a/Modules/Bar/Widgets/NightLight.qml +++ b/Modules/Bar/Widgets/NightLight.qml @@ -14,9 +14,8 @@ NIconButton { property ShellScreen screen property real scaling: 1.0 - compact: (Settings.data.bar.density === "compact") - baseSize: Style.capsuleHeight - colorBg: Settings.data.nightLight.forced ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) + sizeRatio: 0.8 + colorBg: Settings.data.nightLight.forced ? Color.mPrimary : Color.mSurfaceVariant colorFg: Settings.data.nightLight.forced ? Color.mOnPrimary : Color.mOnSurface colorBorder: Color.transparent colorBorderHover: Color.transparent diff --git a/Modules/Bar/Widgets/NotificationHistory.qml b/Modules/Bar/Widgets/NotificationHistory.qml index 91faa68..3021b47 100644 --- a/Modules/Bar/Widgets/NotificationHistory.qml +++ b/Modules/Bar/Widgets/NotificationHistory.qml @@ -49,11 +49,10 @@ NIconButton { return count } - baseSize: Style.capsuleHeight - compact: (Settings.data.bar.density === "compact") + sizeRatio: 0.8 icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" tooltipText: Settings.data.notifications.doNotDisturb ? "Notification history.\nRight-click to disable 'Do Not Disturb'." : "Notification history.\nRight-click to enable 'Do Not Disturb'." - colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) + colorBg: Color.mSurfaceVariant colorFg: Color.mOnSurface colorBorder: Color.transparent colorBorderHover: Color.transparent @@ -69,20 +68,29 @@ NIconButton { Loader { anchors.right: parent.right anchors.top: parent.top - anchors.rightMargin: 2 * scaling - anchors.topMargin: 1 * scaling + anchors.rightMargin: -4 * scaling + anchors.topMargin: -4 * scaling z: 2 active: showUnreadBadge && (!hideWhenZero || computeUnreadCount() > 0) sourceComponent: Rectangle { id: badge readonly property int count: computeUnreadCount() - height: 8 * scaling - width: height + readonly property string label: count <= 99 ? String(count) : "99+" + readonly property real pad: 8 * scaling + height: 16 * scaling + width: Math.max(height, textNode.implicitWidth + pad) radius: height / 2 color: Color.mError border.color: Color.mSurface border.width: 1 visible: count > 0 || !hideWhenZero + NText { + id: textNode + anchors.centerIn: parent + text: badge.label + font.pointSize: Style.fontSizeXXS * scaling + color: Color.mOnError + } } } } diff --git a/Modules/Bar/Widgets/PowerProfile.qml b/Modules/Bar/Widgets/PowerProfile.qml index 2ddda3f..219e907 100644 --- a/Modules/Bar/Widgets/PowerProfile.qml +++ b/Modules/Bar/Widgets/PowerProfile.qml @@ -13,7 +13,7 @@ NIconButton { property real scaling: 1.0 readonly property bool hasPP: PowerProfileService.available - baseSize: Style.capsuleHeight + sizeRatio: 0.8 visible: hasPP function profileIcon() { @@ -46,8 +46,7 @@ NIconButton { icon: root.profileIcon() tooltipText: root.profileName() - compact: (Settings.data.bar.density === "compact") - colorBg: (PowerProfileService.profile === PowerProfile.Balanced) ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary + colorBg: (PowerProfileService.profile === PowerProfile.Balanced) ? Color.mSurfaceVariant : Color.mPrimary colorFg: (PowerProfileService.profile === PowerProfile.Balanced) ? Color.mOnSurface : Color.mOnPrimary colorBorder: Color.transparent colorBorderHover: Color.transparent diff --git a/Modules/Bar/Widgets/PowerToggle.qml b/Modules/Bar/Widgets/PowerToggle.qml index 9f33274..eccecf3 100644 --- a/Modules/Bar/Widgets/PowerToggle.qml +++ b/Modules/Bar/Widgets/PowerToggle.qml @@ -11,11 +11,11 @@ NIconButton { property ShellScreen screen property real scaling: 1.0 - compact: (Settings.data.bar.density === "compact") - baseSize: Style.capsuleHeight + sizeRatio: 0.8 + icon: "power" tooltipText: "Power Settings" - colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) + colorBg: Color.mSurfaceVariant colorFg: Color.mError colorBorder: Color.transparent colorBorderHover: Color.transparent diff --git a/Modules/Bar/Widgets/ScreenRecorderIndicator.qml b/Modules/Bar/Widgets/ScreenRecorderIndicator.qml index e8a36cb..efa8299 100644 --- a/Modules/Bar/Widgets/ScreenRecorderIndicator.qml +++ b/Modules/Bar/Widgets/ScreenRecorderIndicator.qml @@ -12,9 +12,8 @@ NIconButton { visible: ScreenRecorderService.isRecording icon: "camera-video" - tooltipText: "Screen recording is active.\nClick to stop recording." - compact: (Settings.data.bar.density === "compact") - baseSize: Style.capsuleHeight + tooltipText: "Screen recording is active\nClick to stop recording" + sizeRatio: 0.8 colorBg: Color.mPrimary colorFg: Color.mOnPrimary onClicked: ScreenRecorderService.toggleRecording() diff --git a/Modules/Bar/Widgets/SidePanelToggle.qml b/Modules/Bar/Widgets/SidePanelToggle.qml index b52e41f..c3347a8 100644 --- a/Modules/Bar/Widgets/SidePanelToggle.qml +++ b/Modules/Bar/Widgets/SidePanelToggle.qml @@ -33,9 +33,9 @@ NIconButton { icon: useDistroLogo ? "" : "noctalia" tooltipText: "Open side panel." - baseSize: Style.capsuleHeight - compact: (Settings.data.bar.density === "compact") - colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) + sizeRatio: 0.85 + + colorBg: Color.mSurfaceVariant colorFg: Color.mOnSurface colorBgHover: useDistroLogo ? Color.mSurfaceVariant : Color.mTertiary colorBorder: Color.transparent @@ -46,11 +46,10 @@ NIconButton { IconImage { id: logo anchors.centerIn: parent - width: root.width * 0.8 + width: root.width * 0.85 height: width source: useDistroLogo ? DistroLogoService.osLogo : "" visible: useDistroLogo && source !== "" smooth: true - asynchronous: true } } diff --git a/Modules/Bar/Widgets/SystemMonitor.qml b/Modules/Bar/Widgets/SystemMonitor.qml index 5bc5f86..37cdc42 100644 --- a/Modules/Bar/Widgets/SystemMonitor.qml +++ b/Modules/Bar/Widgets/SystemMonitor.qml @@ -29,8 +29,6 @@ Rectangle { } readonly property string barPosition: Settings.data.bar.position - readonly property bool isVertical: barPosition === "left" || barPosition === "right" - readonly property bool compact: (Settings.data.bar.density === "compact") readonly property bool showCpuUsage: (widgetSettings.showCpuUsage !== undefined) ? widgetSettings.showCpuUsage : widgetMetadata.showCpuUsage readonly property bool showCpuTemp: (widgetSettings.showCpuTemp !== undefined) ? widgetSettings.showCpuTemp : widgetMetadata.showCpuTemp @@ -39,267 +37,410 @@ Rectangle { readonly property bool showNetworkStats: (widgetSettings.showNetworkStats !== undefined) ? widgetSettings.showNetworkStats : widgetMetadata.showNetworkStats readonly property bool showDiskUsage: (widgetSettings.showDiskUsage !== undefined) ? widgetSettings.showDiskUsage : widgetMetadata.showDiskUsage - readonly property real textSize: { - var base = isVertical ? width * 0.82 : height - return Math.max(1, compact ? base * 0.43 : base * 0.33) + anchors.centerIn: parent + implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : Math.round(horizontalLayout.implicitWidth + Style.marginM * 2 * scaling) + implicitHeight: (barPosition === "left" || barPosition === "right") ? Math.round(verticalLayout.implicitHeight + Style.marginM * 2 * scaling) : Math.round(Style.capsuleHeight * scaling) + radius: Math.round(Style.radiusM * scaling) + color: Color.mSurfaceVariant + + // Compact speed formatter for vertical bar display + function formatCompactSpeed(bytesPerSecond) { + if (!bytesPerSecond || bytesPerSecond <= 0) + return "0" + const units = ["", "k", "M", "G"] + let value = bytesPerSecond + let unitIndex = 0 + while (value >= 1024 && unitIndex < units.length - 1) { + value = value / 1024.0 + unitIndex++ + } + // Promote at ~100 of current unit (e.g., 100k -> ~0.1M shown as 0.1M or 0M if rounded) + if (unitIndex < units.length - 1 && value >= 100) { + value = value / 1024.0 + unitIndex++ + } + const display = (value >= 10) ? Math.round(value).toString() : value.toFixed(1) + return display + units[unitIndex] } - readonly property real iconSize: textSize * 1.25 - - anchors.centerIn: parent - implicitWidth: isVertical ? Math.round(Style.capsuleHeight * scaling) : Math.round(mainGrid.implicitWidth + Style.marginM * 2 * scaling) - implicitHeight: isVertical ? Math.round(mainGrid.implicitHeight + Style.marginM * 2 * scaling) : Math.round(Style.capsuleHeight * scaling) - radius: Math.round(Style.radiusM * scaling) - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent - - GridLayout { - id: mainGrid + // Horizontal layout for top/bottom bars + RowLayout { + id: horizontalLayout anchors.centerIn: parent - - // Dynamic layout based on bar orientation - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? -1 : 1 - columns: isVertical ? 1 : -1 - - rowSpacing: isVertical ? (Style.marginS * scaling) : (Style.marginXS * scaling) - columnSpacing: isVertical ? (Style.marginXS * scaling) : (Style.marginXS * scaling) + anchors.leftMargin: Style.marginM * scaling + anchors.rightMargin: Style.marginM * scaling + spacing: Style.marginXS * scaling + visible: barPosition === "top" || barPosition === "bottom" // CPU Usage Component Item { - Layout.preferredWidth: cpuUsageContent.implicitWidth + Layout.preferredWidth: cpuUsageRow.implicitWidth Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) - Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: showCpuUsage - GridLayout { - id: cpuUsageContent + RowLayout { + id: cpuUsageRow anchors.centerIn: parent - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? 2 : 1 - columns: isVertical ? 1 : 2 - rowSpacing: Style.marginXXS * scaling - columnSpacing: Style.marginXXS * scaling - - NText { - text: isVertical ? `${Math.round(SystemStatService.cpuUsage)}%` : `${SystemStatService.cpuUsage}%` - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize - font.weight: Style.fontWeightMedium - Layout.alignment: Qt.AlignCenter - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: Color.mPrimary - Layout.row: isVertical ? 0 : 0 - Layout.column: isVertical ? 0 : 1 - } + spacing: Style.marginXXS * scaling NIcon { icon: "cpu-usage" - font.pointSize: iconSize - Layout.alignment: Qt.AlignCenter - Layout.row: isVertical ? 1 : 0 - Layout.column: 0 + font.pointSize: Style.fontSizeM * scaling + Layout.alignment: Qt.AlignVCenter + } + + NText { + text: `${SystemStatService.cpuUsage}%` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXS * scaling + font.weight: Style.fontWeightMedium + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + color: Color.mPrimary } } } // CPU Temperature Component Item { - Layout.preferredWidth: cpuTempContent.implicitWidth + Layout.preferredWidth: cpuTempRow.implicitWidth Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) - Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: showCpuTemp - GridLayout { - id: cpuTempContent + RowLayout { + id: cpuTempRow anchors.centerIn: parent - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? 2 : 1 - columns: isVertical ? 1 : 2 - rowSpacing: Style.marginXXS * scaling - columnSpacing: Style.marginXXS * scaling - - NText { - text: isVertical ? `${SystemStatService.cpuTemp}°` : `${SystemStatService.cpuTemp}°C` - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize - font.weight: Style.fontWeightMedium - Layout.alignment: Qt.AlignCenter - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: Color.mPrimary - Layout.row: isVertical ? 0 : 0 - Layout.column: isVertical ? 0 : 1 - } + spacing: Style.marginXXS * scaling NIcon { icon: "cpu-temperature" - font.pointSize: iconSize - Layout.alignment: Qt.AlignCenter - Layout.row: isVertical ? 1 : 0 - Layout.column: 0 + // Fire is so tall, we need to make it smaller + font.pointSize: Style.fontSizeS * scaling + Layout.alignment: Qt.AlignVCenter + } + + NText { + text: `${SystemStatService.cpuTemp}°C` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXS * scaling + font.weight: Style.fontWeightMedium + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + color: Color.mPrimary } } } // Memory Usage Component Item { - Layout.preferredWidth: memoryContent.implicitWidth + Layout.preferredWidth: memoryUsageRow.implicitWidth Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) - Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: showMemoryUsage - GridLayout { - id: memoryContent + RowLayout { + id: memoryUsageRow anchors.centerIn: parent - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? 2 : 1 - columns: isVertical ? 1 : 2 - rowSpacing: Style.marginXXS * scaling - columnSpacing: Style.marginXXS * scaling - - NText { - text: { - if (showMemoryAsPercent) { - return `${SystemStatService.memPercent}%` - } else { - return isVertical ? `${Math.round(SystemStatService.memGb)}G` : `${SystemStatService.memGb}G` - } - } - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize - font.weight: Style.fontWeightMedium - Layout.alignment: Qt.AlignCenter - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: Color.mPrimary - Layout.row: isVertical ? 0 : 0 - Layout.column: isVertical ? 0 : 1 - } + spacing: Style.marginXXS * scaling NIcon { icon: "memory" - font.pointSize: iconSize - Layout.alignment: Qt.AlignCenter - Layout.row: isVertical ? 1 : 0 - Layout.column: 0 + font.pointSize: Style.fontSizeM * scaling + Layout.alignment: Qt.AlignVCenter + } + + NText { + text: showMemoryAsPercent ? `${SystemStatService.memPercent}%` : `${SystemStatService.memGb}G` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXS * scaling + font.weight: Style.fontWeightMedium + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + color: Color.mPrimary } } } // Network Download Speed Component Item { - Layout.preferredWidth: downloadContent.implicitWidth + Layout.preferredWidth: networkDownloadRow.implicitWidth Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) - Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: showNetworkStats - GridLayout { - id: downloadContent + RowLayout { + id: networkDownloadRow anchors.centerIn: parent - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? 2 : 1 - columns: isVertical ? 1 : 2 - rowSpacing: Style.marginXXS * scaling - columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling) - - NText { - text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.rxSpeed) : SystemStatService.formatSpeed(SystemStatService.rxSpeed) - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize - font.weight: Style.fontWeightMedium - Layout.alignment: Qt.AlignCenter - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: Color.mPrimary - Layout.row: isVertical ? 0 : 0 - Layout.column: isVertical ? 0 : 1 - } + spacing: Style.marginXS * scaling NIcon { icon: "download-speed" - font.pointSize: iconSize - Layout.alignment: Qt.AlignCenter - Layout.row: isVertical ? 1 : 0 - Layout.column: 0 + font.pointSize: Style.fontSizeM * scaling + Layout.alignment: Qt.AlignVCenter + } + + NText { + text: SystemStatService.formatSpeed(SystemStatService.rxSpeed) + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXS * scaling + font.weight: Style.fontWeightMedium + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + color: Color.mPrimary } } } // Network Upload Speed Component Item { - Layout.preferredWidth: uploadContent.implicitWidth + Layout.preferredWidth: networkUploadRow.implicitWidth Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) - Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: showNetworkStats - GridLayout { - id: uploadContent + RowLayout { + id: networkUploadRow anchors.centerIn: parent - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? 2 : 1 - columns: isVertical ? 1 : 2 - rowSpacing: Style.marginXXS * scaling - columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling) - - NText { - text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.txSpeed) : SystemStatService.formatSpeed(SystemStatService.txSpeed) - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize - font.weight: Style.fontWeightMedium - Layout.alignment: Qt.AlignCenter - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: Color.mPrimary - Layout.row: isVertical ? 0 : 0 - Layout.column: isVertical ? 0 : 1 - } + spacing: Style.marginXS * scaling NIcon { icon: "upload-speed" - font.pointSize: iconSize - Layout.alignment: Qt.AlignCenter - Layout.row: isVertical ? 1 : 0 - Layout.column: 0 + font.pointSize: Style.fontSizeM * scaling + Layout.alignment: Qt.AlignVCenter + } + + NText { + text: SystemStatService.formatSpeed(SystemStatService.txSpeed) + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXS * scaling + font.weight: Style.fontWeightMedium + Layout.alignment: Qt.AlignVCenter + verticalAlignment: Text.AlignVCenter + color: Color.mPrimary } } } // Disk Usage Component (primary drive) Item { - Layout.preferredWidth: diskContent.implicitWidth + Layout.preferredWidth: diskUsageRow.implicitWidth Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) - Layout.alignment: isVertical ? Qt.AlignHCenter : Qt.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: showDiskUsage - GridLayout { - id: diskContent + RowLayout { + id: diskUsageRow anchors.centerIn: parent - flow: isVertical ? GridLayout.TopToBottom : GridLayout.LeftToRight - rows: isVertical ? 2 : 1 - columns: isVertical ? 1 : 2 - rowSpacing: Style.marginXXS * scaling - columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling) + spacing: Style.marginXS * scaling + + NIcon { + icon: "storage" + font.pointSize: Style.fontSizeM * scaling + Layout.alignment: Qt.AlignVCenter + } NText { text: `${SystemStatService.diskPercent}%` font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + font.pointSize: Style.fontSizeXS * scaling font.weight: Style.fontWeightMedium - Layout.alignment: Qt.AlignCenter - horizontalAlignment: Text.AlignHCenter + Layout.alignment: Qt.AlignVCenter verticalAlignment: Text.AlignVCenter color: Color.mPrimary - Layout.row: isVertical ? 0 : 0 - Layout.column: isVertical ? 0 : 1 + } + } + } + } + + // Vertical layout for left/right bars + ColumnLayout { + id: verticalLayout + anchors.centerIn: parent + anchors.topMargin: Style.marginS * scaling + anchors.bottomMargin: Style.marginS * scaling + width: Math.round(28 * scaling) + spacing: Style.marginS * scaling + visible: barPosition === "left" || barPosition === "right" + + // CPU Usage Component + Item { + Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) + Layout.preferredWidth: Math.round(28 * scaling) + Layout.alignment: Qt.AlignHCenter + visible: showCpuUsage + + Column { + id: cpuUsageRowVertical + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + + NText { + text: `${Math.round(SystemStatService.cpuUsage)}%` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXXS * scaling + font.weight: Style.fontWeightMedium + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + color: Color.mPrimary + } + + NIcon { + icon: "cpu-usage" + font.pointSize: Style.fontSizeS * scaling + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + + // CPU Temperature Component + Item { + Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) + Layout.preferredWidth: Math.round(28 * scaling) + Layout.alignment: Qt.AlignHCenter + visible: showCpuTemp + + Column { + id: cpuTempRowVertical + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + + NText { + text: `${SystemStatService.cpuTemp}°` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXXS * scaling + font.weight: Style.fontWeightMedium + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + color: Color.mPrimary + } + + NIcon { + icon: "cpu-temperature" + // Fire is so tall, we need to make it smaller + font.pointSize: Style.fontSizeXS * scaling + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + + // Memory Usage Component + Item { + Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) + Layout.preferredWidth: Math.round(28 * scaling) + Layout.alignment: Qt.AlignHCenter + visible: showMemoryUsage + + Column { + id: memoryUsageRowVertical + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + + NText { + text: showMemoryAsPercent ? `${SystemStatService.memPercent}%` : `${Math.round(SystemStatService.memGb)}G` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXXS * scaling + font.weight: Style.fontWeightMedium + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + color: Color.mPrimary + } + + NIcon { + icon: "memory" + font.pointSize: Style.fontSizeS * scaling + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + + // Network Download Speed Component + Item { + Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) + Layout.preferredWidth: Math.round(28 * scaling) + Layout.alignment: Qt.AlignHCenter + visible: showNetworkStats + + Column { + id: networkDownloadRowVertical + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + + NText { + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + text: formatCompactSpeed(SystemStatService.rxSpeed) + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXXS * scaling + font.weight: Style.fontWeightMedium + color: Color.mPrimary + } + + NIcon { + icon: "download-speed" + font.pointSize: Style.fontSizeS * scaling + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + + // Network Upload Speed Component + Item { + Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) + Layout.preferredWidth: Math.round(28 * scaling) + Layout.alignment: Qt.AlignHCenter + visible: showNetworkStats + + Column { + id: networkUploadRowVertical + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + + NText { + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + text: formatCompactSpeed(SystemStatService.txSpeed) + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXXS * scaling + font.weight: Style.fontWeightMedium + color: Color.mPrimary + } + + NIcon { + icon: "upload-speed" + font.pointSize: Style.fontSizeS * scaling + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + + // Disk Usage Component (primary drive) + Item { + Layout.preferredHeight: Math.round(Style.capsuleHeight * scaling) + Layout.preferredWidth: Math.round(28 * scaling) + Layout.alignment: Qt.AlignHCenter + visible: showDiskUsage + + ColumnLayout { + id: diskUsageRowVertical + anchors.centerIn: parent + spacing: Style.marginXXS * scaling + + NText { + text: `${SystemStatService.diskPercent}%` + font.family: Settings.data.ui.fontFixed + font.pointSize: Style.fontSizeXXS * scaling + font.weight: Style.fontWeightMedium + Layout.alignment: Qt.AlignHCenter + horizontalAlignment: Text.AlignHCenter + color: Color.mPrimary } NIcon { icon: "storage" - font.pointSize: iconSize - Layout.alignment: Qt.AlignCenter - Layout.row: isVertical ? 1 : 0 - Layout.column: 0 + font.pointSize: Style.fontSizeS * scaling + Layout.alignment: Qt.AlignHCenter } } } diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index d69007c..3c570ec 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -1,3 +1,5 @@ +pragma ComponentBehavior + import QtQuick import QtQuick.Controls import QtQuick.Layouts @@ -13,32 +15,18 @@ Rectangle { property ShellScreen screen property real scaling: 1.0 - readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" - readonly property bool compact: (Settings.data.bar.density === "compact") - readonly property real itemSize: compact ? Style.capsuleHeight * 0.9 * scaling : Style.capsuleHeight * 0.8 * scaling + readonly property real itemSize: Style.baseWidgetSize * 0.8 * scaling // Always visible when there are toplevels - implicitWidth: isVerticalBar ? Math.round(Style.capsuleHeight * scaling) : taskbarLayout.implicitWidth + Style.marginM * scaling * 2 - implicitHeight: isVerticalBar ? taskbarLayout.implicitHeight + Style.marginM * scaling * 2 : Math.round(Style.capsuleHeight * scaling) + implicitWidth: taskbarLayout.implicitWidth + Style.marginM * scaling * 2 + implicitHeight: Math.round(Style.capsuleHeight * scaling) radius: Math.round(Style.radiusM * scaling) - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant - GridLayout { + RowLayout { id: taskbarLayout - anchors.fill: parent - anchors { - leftMargin: isVerticalBar ? undefined : Style.marginM * scaling - rightMargin: isVerticalBar ? undefined : Style.marginM * scaling - topMargin: compact ? 0 : isVerticalBar ? Style.marginM * scaling : undefined - bottomMargin: compact ? 0 : isVerticalBar ? Style.marginM * scaling : undefined - } - - // Configure GridLayout to behave like RowLayout or ColumnLayout - rows: isVerticalBar ? -1 : 1 // -1 means unlimited - columns: isVerticalBar ? 1 : -1 // -1 means unlimited - - rowSpacing: isVerticalBar ? Style.marginXXS * root.scaling : 0 - columnSpacing: isVerticalBar ? 0 : Style.marginXXS * root.scaling + anchors.centerIn: parent + spacing: Style.marginXXS * root.scaling Repeater { model: ToplevelManager && ToplevelManager.toplevels ? ToplevelManager.toplevels : [] @@ -55,8 +43,8 @@ Rectangle { Rectangle { id: iconBackground anchors.centerIn: parent - width: parent.width - height: parent.height + width: root.itemSize * 0.75 + height: root.itemSize * 0.75 color: taskbarItem.isActive ? Color.mPrimary : root.color border.width: 0 radius: Math.round(Style.radiusXS * root.scaling) @@ -66,11 +54,10 @@ Rectangle { IconImage { id: appIcon anchors.centerIn: parent - width: parent.width - height: parent.height + width: Style.marginL * root.scaling + height: Style.marginL * root.scaling source: AppIcons.iconForAppId(taskbarItem.modelData.appId) smooth: true - asynchronous: true } } diff --git a/Modules/Bar/Widgets/Tray.qml b/Modules/Bar/Widgets/Tray.qml index 3904a9c..daa4c80 100644 --- a/Modules/Bar/Widgets/Tray.qml +++ b/Modules/Bar/Widgets/Tray.qml @@ -16,10 +16,9 @@ Rectangle { property ShellScreen screen property real scaling: 1.0 + readonly property real itemSize: 24 * scaling readonly property string barPosition: Settings.data.bar.position readonly property bool isVertical: barPosition === "left" || barPosition === "right" - readonly property bool compact: (Settings.data.bar.density === "compact") - readonly property real itemSize: isVertical ? width * 0.75 : height * 0.85 function onLoaded() { // When the widget is fully initialized with its props set the screen for the trayMenu @@ -32,7 +31,7 @@ Rectangle { implicitWidth: isVertical ? Math.round(Style.capsuleHeight * scaling) : (trayFlow.implicitWidth + Style.marginS * scaling * 2) implicitHeight: isVertical ? (trayFlow.implicitHeight + Style.marginS * scaling * 2) : Math.round(Style.capsuleHeight * scaling) radius: Math.round(Style.radiusM * scaling) - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant Layout.alignment: Qt.AlignVCenter diff --git a/Modules/Bar/Widgets/Volume.qml b/Modules/Bar/Widgets/Volume.qml index bcacd7f..15e1ddc 100644 --- a/Modules/Bar/Widgets/Volume.qml +++ b/Modules/Bar/Widgets/Volume.qml @@ -6,7 +6,6 @@ import qs.Commons import qs.Modules.SettingsPanel import qs.Services import qs.Widgets -import qs.Modules.Bar.Extras Item { id: root @@ -72,11 +71,10 @@ Item { } } - BarPill { + NPill { id: pill - compact: (Settings.data.bar.density === "compact") - rightOpen: BarWidgetRegistry.getPillDirection(root) + rightOpen: BarWidgetRegistry.getNPillDirection(root) icon: getIcon() autoHide: false // Important to be false so we can hover as long as we want text: Math.floor(AudioService.volume * 100) diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml index 9bc6058..74b3e73 100644 --- a/Modules/Bar/Widgets/WiFi.qml +++ b/Modules/Bar/Widgets/WiFi.qml @@ -13,9 +13,9 @@ NIconButton { property ShellScreen screen property real scaling: 1.0 - compact: (Settings.data.bar.density === "compact") - baseSize: Style.capsuleHeight - colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) + sizeRatio: 0.8 + + colorBg: Color.mSurfaceVariant colorFg: Color.mOnSurface colorBorder: Color.transparent colorBorderHover: Color.transparent diff --git a/Modules/Bar/Widgets/Workspace.qml b/Modules/Bar/Widgets/Workspace.qml index 1a4f30e..8d668a9 100644 --- a/Modules/Bar/Widgets/Workspace.qml +++ b/Modules/Bar/Widgets/Workspace.qml @@ -32,15 +32,6 @@ Item { } readonly property string barPosition: Settings.data.bar.position - readonly property bool isVertical: barPosition === "left" || barPosition === "right" - readonly property bool compact: (Settings.data.bar.density === "compact") - readonly property real baseDimensionRatio: { - const b = compact ? 0.85 : 0.65 - if (widgetSettings.labelMode === "none") { - return b * 0.75 - } - return b - } readonly property string labelMode: (widgetSettings.labelMode !== undefined) ? widgetSettings.labelMode : widgetMetadata.labelMode readonly property bool hideUnoccupied: (widgetSettings.hideUnoccupied !== undefined) ? widgetSettings.hideUnoccupied : widgetMetadata.hideUnoccupied @@ -58,45 +49,47 @@ Item { signal workspaceChanged(int workspaceId, color accentColor) - implicitWidth: isVertical ? Math.round(Style.barHeight * scaling) : computeWidth() - implicitHeight: isVertical ? computeHeight() : Math.round(Style.barHeight * scaling) + implicitHeight: (barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling) + implicitWidth: (barPosition === "left" || barPosition === "right") ? Math.round(Style.barHeight * scaling) : calculatedHorizontalWidth() - function getWorkspaceWidth(ws) { - const d = Style.capsuleHeight * root.baseDimensionRatio + function calculatedWsWidth(ws) { if (ws.isFocused) - return d * 2.5 + return Math.round(44 * scaling) + else if (ws.isActive) + return Math.round(28 * scaling) else - return d + return Math.round(20 * scaling) } - function getWorkspaceHeight(ws) { - const d = Style.capsuleHeight * root.baseDimensionRatio + function calculatedWsHeight(ws) { if (ws.isFocused) - return d * 3 + return Math.round(44 * scaling) + else if (ws.isActive) + return Math.round(28 * scaling) else - return d + return Math.round(20 * scaling) } - function computeWidth() { + function calculatedVerticalHeight() { let total = 0 for (var i = 0; i < localWorkspaces.count; i++) { const ws = localWorkspaces.get(i) - total += getWorkspaceWidth(ws) + total += calculatedWsHeight(ws) } total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills total += horizontalPadding * 2 - return Math.round(total) + return total } - function computeHeight() { + function calculatedHorizontalWidth() { let total = 0 for (var i = 0; i < localWorkspaces.count; i++) { const ws = localWorkspaces.get(i) - total += getWorkspaceHeight(ws) + total += calculatedWsWidth(ws) } total += Math.max(localWorkspaces.count - 1, 0) * spacingBetweenPills total += horizontalPadding * 2 - return Math.round(total) + return total } Component.onCompleted: { @@ -180,10 +173,10 @@ Item { Rectangle { id: workspaceBackground - width: isVertical ? Math.round(Style.capsuleHeight * scaling) : parent.width - height: isVertical ? parent.height : Math.round(Style.capsuleHeight * scaling) + width: (barPosition === "left" || barPosition === "right") ? Math.round(Style.capsuleHeight * scaling) : parent.width + height: (barPosition === "left" || barPosition === "right") ? parent.height : Math.round(Style.capsuleHeight * scaling) radius: Math.round(Style.radiusM * scaling) - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter @@ -194,16 +187,17 @@ Item { id: pillRow spacing: spacingBetweenPills anchors.verticalCenter: workspaceBackground.verticalCenter + width: root.width - horizontalPadding * 2 x: horizontalPadding - visible: !isVertical + visible: barPosition === "top" || barPosition === "bottom" Repeater { id: workspaceRepeaterHorizontal model: localWorkspaces Item { id: workspacePillContainer - width: root.getWorkspaceWidth(model) - height: Style.capsuleHeight * root.baseDimensionRatio + height: (labelMode !== "none") ? Math.round(18 * scaling) : Math.round(14 * scaling) + width: root.calculatedWsWidth(model) Rectangle { id: pill @@ -222,7 +216,7 @@ Item { return model.idx.toString() } } - font.pointSize: model.isFocused ? workspacePillContainer.height * 0.45 : workspacePillContainer.height * 0.42 + font.pointSize: model.isFocused ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling font.capitalization: Font.AllUppercase font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightBold @@ -338,16 +332,17 @@ Item { id: pillColumn spacing: spacingBetweenPills anchors.horizontalCenter: workspaceBackground.horizontalCenter + height: root.height - horizontalPadding * 2 y: horizontalPadding - visible: isVertical + visible: barPosition === "left" || barPosition === "right" Repeater { id: workspaceRepeaterVertical model: localWorkspaces Item { id: workspacePillContainerVertical - width: Style.capsuleHeight * root.baseDimensionRatio - height: root.getWorkspaceHeight(model) + width: (labelMode !== "none") ? Math.round(18 * scaling) : Math.round(14 * scaling) + height: root.calculatedWsHeight(model) Rectangle { id: pillVertical @@ -366,7 +361,7 @@ Item { return model.idx.toString() } } - font.pointSize: model.isFocused ? workspacePillContainerVertical.width * 0.45 : workspacePillContainerVertical.width * 0.42 + font.pointSize: model.isFocused ? Style.fontSizeXS * scaling : Style.fontSizeXXS * scaling font.capitalization: Font.AllUppercase font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightBold diff --git a/Modules/BluetoothPanel/BluetoothPanel.qml b/Modules/BluetoothPanel/BluetoothPanel.qml index aa743f0..12a5ce0 100644 --- a/Modules/BluetoothPanel/BluetoothPanel.qml +++ b/Modules/BluetoothPanel/BluetoothPanel.qml @@ -53,7 +53,7 @@ NPanel { enabled: Settings.data.network.bluetoothEnabled icon: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "refresh" tooltipText: "Refresh Devices" - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: { if (BluetoothService.adapter) { BluetoothService.adapter.discovering = !BluetoothService.adapter.discovering @@ -64,7 +64,7 @@ NPanel { NIconButton { icon: "close" tooltipText: "Close." - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: { root.close() } diff --git a/Modules/Calendar/Calendar.qml b/Modules/Calendar/Calendar.qml index 80b994a..80c6fd3 100644 --- a/Modules/Calendar/Calendar.qml +++ b/Modules/Calendar/Calendar.qml @@ -12,6 +12,7 @@ NPanel { preferredWidth: 340 preferredHeight: 320 + panelAnchorRight: Settings.data.bar.position === "right" // Main Column panelContent: ColumnLayout { diff --git a/Modules/Launcher/Plugins/ApplicationsPlugin.qml b/Modules/Launcher/Plugins/ApplicationsPlugin.qml index 2d21a5f..e6eced4 100644 --- a/Modules/Launcher/Plugins/ApplicationsPlugin.qml +++ b/Modules/Launcher/Plugins/ApplicationsPlugin.qml @@ -79,11 +79,8 @@ Item { "icon": app.icon || "application-x-executable", "isImage": false, "onActivate": function () { - // Close the launcher/NPanel immediately without any animations. - // Ensures we are not preventing the future focusing of the app - launcher.closeCompleted() - Logger.log("ApplicationsPlugin", `Launching: ${app.name}`) + if (Settings.data.appLauncher.useApp2Unit && app.id) { Logger.log("ApplicationsPlugin", `Using app2unit for: ${app.id}`) if (app.runInTerminal) @@ -92,9 +89,11 @@ Item { Quickshell.execDetached(["app2unit", "--"].concat(app.command)) } else if (app.execute) { app.execute() - } else { - Logger.log("ApplicationsPlugin", `Could not launch: ${app.name}`) + } else if (app.exec) { + // Fallback to manual execution + Process.execute(app.exec) } + launcher.close() } } } diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index 68d0906..940c6d6 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -326,7 +326,7 @@ Variants { NIconButton { icon: "close" tooltipText: "Close." - baseSize: Style.baseWidgetSize * 0.6 + sizeRatio: 0.6 anchors.top: parent.top anchors.topMargin: Style.marginM * scaling anchors.right: parent.right diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml index fd5be5f..0a9e852 100644 --- a/Modules/Notification/NotificationHistoryPanel.qml +++ b/Modules/Notification/NotificationHistoryPanel.qml @@ -14,6 +14,7 @@ NPanel { preferredWidth: 380 preferredHeight: 500 + panelAnchorRight: Settings.data.bar.position === "right" panelKeyboardFocus: true panelContent: Rectangle { @@ -47,15 +48,15 @@ NPanel { NIconButton { icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" tooltipText: Settings.data.notifications.doNotDisturb ? "'Do Not Disturb' is enabled." : "'Do Not Disturb' is disabled." - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb onRightClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb } NIconButton { icon: "trash" - tooltipText: "Clear history." - baseSize: Style.baseWidgetSize * 0.8 + tooltipText: "Clear history" + sizeRatio: 0.8 onClicked: { NotificationService.clearHistory() root.close() @@ -65,7 +66,7 @@ NPanel { NIconButton { icon: "close" tooltipText: "Close." - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: { root.close() } @@ -135,7 +136,7 @@ NPanel { width: notificationList.width height: notificationLayout.implicitHeight + (Style.marginM * scaling * 2) radius: Style.radiusM * scaling - color: Color.mSurfaceVariant + color: notificationMouseArea.containsMouse ? Color.mTertiary : Color.mSurfaceVariant border.color: Qt.alpha(Color.mOutline, Style.opacityMedium) border.width: Math.max(1, Style.borderS * scaling) @@ -168,7 +169,7 @@ NPanel { text: (summary || "No summary").substring(0, 100) font.pointSize: Style.fontSizeM * scaling font.weight: Font.Medium - color: Color.mPrimary + color: notificationMouseArea.containsMouse ? Color.mOnTertiary : Color.mPrimary wrapMode: Text.Wrap Layout.fillWidth: true maximumLineCount: 2 @@ -178,7 +179,7 @@ NPanel { NText { text: (body || "").substring(0, 150) font.pointSize: Style.fontSizeXS * scaling - color: Color.mOnSurface + color: notificationMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface wrapMode: Text.Wrap Layout.fillWidth: true maximumLineCount: 3 @@ -189,7 +190,7 @@ NPanel { NText { text: NotificationService.formatTimestamp(timestamp) font.pointSize: Style.fontSizeXS * scaling - color: Color.mOnSurface + color: notificationMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface Layout.fillWidth: true } } @@ -197,8 +198,8 @@ NPanel { // Delete button NIconButton { icon: "trash" - tooltipText: "Delete notification." - baseSize: Style.baseWidgetSize * 0.7 + tooltipText: "Delete notification" + sizeRatio: 0.7 Layout.alignment: Qt.AlignTop onClicked: { diff --git a/Modules/SettingsPanel/Bar/BarSectionEditor.qml b/Modules/SettingsPanel/Bar/BarSectionEditor.qml index 79ee7c1..0c1919b 100644 --- a/Modules/SettingsPanel/Bar/BarSectionEditor.qml +++ b/Modules/SettingsPanel/Bar/BarSectionEditor.qml @@ -14,8 +14,6 @@ NBox { property var widgetModel: [] property var availableWidgets: [] - readonly property real miniButtonSize: Style.baseWidgetSize * 0.65 - signal addWidget(string widgetId, string section) signal removeWidget(string section, int index) signal reorderWidget(string section, int fromIndex, int toIndex) @@ -180,7 +178,7 @@ NBox { active: BarWidgetRegistry.widgetHasUserSettings(modelData.id) sourceComponent: NIconButton { icon: "settings" - baseSize: miniButtonSize + sizeRatio: 0.6 colorBorder: Qt.alpha(Color.mOutline, Style.opacityLight) colorBg: Color.mOnSurface colorFg: Color.mOnPrimary @@ -220,7 +218,7 @@ NBox { NIconButton { icon: "close" - baseSize: miniButtonSize + sizeRatio: 0.6 colorBorder: Qt.alpha(Color.mOutline, Style.opacityLight) colorBg: Color.mOnSurface colorFg: Color.mOnPrimary diff --git a/Modules/SettingsPanel/Tabs/AudioTab.qml b/Modules/SettingsPanel/Tabs/AudioTab.qml index 463185c..b0d42ac 100644 --- a/Modules/SettingsPanel/Tabs/AudioTab.qml +++ b/Modules/SettingsPanel/Tabs/AudioTab.qml @@ -298,7 +298,7 @@ ColumnLayout { NIconButton { icon: "close" - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 Layout.alignment: Qt.AlignVCenter Layout.rightMargin: Style.marginXS * scaling onClicked: { diff --git a/Modules/SettingsPanel/Tabs/BarTab.qml b/Modules/SettingsPanel/Tabs/BarTab.qml index 8a005bc..1b4353c 100644 --- a/Modules/SettingsPanel/Tabs/BarTab.qml +++ b/Modules/SettingsPanel/Tabs/BarTab.qml @@ -45,52 +45,32 @@ ColumnLayout { description: "Configure bar appearance and positioning." } - NComboBox { - Layout.fillWidth: true - label: "Bar Position" - description: "Choose where to place the bar on the screen." - model: ListModel { - ListElement { - key: "top" - name: "Top" - } - ListElement { - key: "bottom" - name: "Bottom" - } - ListElement { - key: "left" - name: "Left" - } - ListElement { - key: "right" - name: "Right" + RowLayout { + NComboBox { + Layout.fillWidth: true + label: "Bar Position" + description: "Choose where to place the bar on the screen." + model: ListModel { + ListElement { + key: "top" + name: "Top" + } + ListElement { + key: "bottom" + name: "Bottom" + } + ListElement { + key: "left" + name: "Left" + } + ListElement { + key: "right" + name: "Right" + } } + currentKey: Settings.data.bar.position + onSelected: key => Settings.data.bar.position = key } - currentKey: Settings.data.bar.position - onSelected: key => Settings.data.bar.position = key - } - - NComboBox { - Layout.fillWidth: true - label: "Bar Density" - description: "Choose the density of the bar." - model: ListModel { - ListElement { - key: "compact" - name: "Compact" - } - ListElement { - key: "default" - name: "Default" - } - ListElement { - key: "comfortable" - name: "Comfortable" - } - } - currentKey: Settings.data.bar.density - onSelected: key => Settings.data.bar.density = key } ColumnLayout { @@ -112,15 +92,6 @@ ColumnLayout { text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%" } } - - NToggle { - Layout.fillWidth: true - label: "Show Capsule" - description: "Adds a capsule behind each widget to improve readability on transparent bars." - checked: Settings.data.bar.showCapsule - onToggled: checked => Settings.data.bar.showCapsule = checked - } - NToggle { Layout.fillWidth: true label: "Floating Bar" @@ -192,6 +163,40 @@ ColumnLayout { Layout.bottomMargin: Style.marginXL * scaling } + // Monitor Configuration + ColumnLayout { + spacing: Style.marginM * scaling + Layout.fillWidth: true + + NHeader { + label: "Monitors Configuration" + description: "Choose which monitors should display the bar." + } + + Repeater { + model: Quickshell.screens || [] + delegate: NCheckbox { + Layout.fillWidth: true + label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}` + description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})` + checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1 + onToggled: checked => { + if (checked) { + Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name) + } else { + Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name) + } + } + } + } + } + + NDivider { + Layout.fillWidth: true + Layout.topMargin: Style.marginXL * scaling + Layout.bottomMargin: Style.marginXL * scaling + } + // Widgets Management Section ColumnLayout { spacing: Style.marginXXS * scaling @@ -259,40 +264,6 @@ ColumnLayout { Layout.bottomMargin: Style.marginXL * scaling } - // Monitor Configuration - ColumnLayout { - spacing: Style.marginM * scaling - Layout.fillWidth: true - - NHeader { - label: "Monitors Configuration" - description: "Show bar on specific monitors. Defaults to all if none are chosen." - } - - Repeater { - model: Quickshell.screens || [] - delegate: NCheckbox { - Layout.fillWidth: true - label: modelData.name || "Unknown" - description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]` - checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1 - onToggled: checked => { - if (checked) { - Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name) - } else { - Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name) - } - } - } - } - } - - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } - // --------------------------------- // Signal functions // --------------------------------- diff --git a/Modules/SettingsPanel/Tabs/DisplayTab.qml b/Modules/SettingsPanel/Tabs/DisplayTab.qml index 65c14ef..b5e41f8 100644 --- a/Modules/SettingsPanel/Tabs/DisplayTab.qml +++ b/Modules/SettingsPanel/Tabs/DisplayTab.qml @@ -87,9 +87,19 @@ ColumnLayout { anchors.margins: Style.marginL * scaling spacing: Style.marginXXS * scaling - NLabel { - label: modelData.name || "Unknown" - description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]` + NText { + text: (`${modelData.name}: ${modelData.model}` || "Unknown") + font.pointSize: Style.fontSizeL * scaling + font.weight: Style.fontWeightBold + color: Color.mPrimary + } + + NText { + text: `Resolution: ${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})` + font.pointSize: Style.fontSizeXS * scaling + color: Color.mOnSurfaceVariant + wrapMode: Text.WordWrap + Layout.fillWidth: true } // Scale @@ -124,8 +134,8 @@ ColumnLayout { NIconButton { icon: "refresh" - baseSize: Style.baseWidgetSize * 0.9 - tooltipText: "Reset scaling." + sizeRatio: 0.8 + tooltipText: "Reset scaling" onClicked: ScalingService.setScreenScale(modelData, 1.0) anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter diff --git a/Modules/SettingsPanel/Tabs/DockTab.qml b/Modules/SettingsPanel/Tabs/DockTab.qml index b8a22ec..293378c 100644 --- a/Modules/SettingsPanel/Tabs/DockTab.qml +++ b/Modules/SettingsPanel/Tabs/DockTab.qml @@ -93,15 +93,15 @@ ColumnLayout { NHeader { label: "Monitors Configuration" - description: "Show dock on specific monitors." + description: "Choose which monitors should display the dock." } Repeater { model: Quickshell.screens || [] delegate: NCheckbox { Layout.fillWidth: true - label: modelData.name || "Unknown" - description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]` + label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}` + description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})` checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { diff --git a/Modules/SettingsPanel/Tabs/NotificationTab.qml b/Modules/SettingsPanel/Tabs/NotificationTab.qml index 7d7a7f2..fa6d268 100644 --- a/Modules/SettingsPanel/Tabs/NotificationTab.qml +++ b/Modules/SettingsPanel/Tabs/NotificationTab.qml @@ -46,6 +46,40 @@ ColumnLayout { Layout.bottomMargin: Style.marginXL * scaling } + // Monitor Configuration + ColumnLayout { + spacing: Style.marginM * scaling + Layout.fillWidth: true + + NHeader { + label: "Monitors Configuration" + description: "Choose which monitors should display notifications." + } + + Repeater { + model: Quickshell.screens || [] + delegate: NCheckbox { + Layout.fillWidth: true + label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}` + description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})` + checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1 + onToggled: checked => { + if (checked) { + Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name) + } else { + Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name) + } + } + } + } + } + + NDivider { + Layout.fillWidth: true + Layout.topMargin: Style.marginXL * scaling + Layout.bottomMargin: Style.marginXL * scaling + } + // Notification Duration Settings ColumnLayout { spacing: Style.marginL * scaling @@ -125,38 +159,4 @@ ColumnLayout { Layout.topMargin: Style.marginXL * scaling Layout.bottomMargin: Style.marginXL * scaling } - - // Monitor Configuration - ColumnLayout { - spacing: Style.marginM * scaling - Layout.fillWidth: true - - NHeader { - label: "Monitors Configuration" - description: "Show bar on specific monitors. Defaults to all if none are chosen." - } - - Repeater { - model: Quickshell.screens || [] - delegate: NCheckbox { - Layout.fillWidth: true - label: modelData.name || "Unknown" - description: `${modelData.model} - ${modelData.width}x${modelData.height} [x:${modelData.x} y:${modelData.y}]` - checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1 - onToggled: checked => { - if (checked) { - Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name) - } else { - Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name) - } - } - } - } - } - - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } } diff --git a/Modules/SettingsPanel/Tabs/ScreenRecorderTab.qml b/Modules/SettingsPanel/Tabs/ScreenRecorderTab.qml index 63f9f70..05cb66a 100644 --- a/Modules/SettingsPanel/Tabs/ScreenRecorderTab.qml +++ b/Modules/SettingsPanel/Tabs/ScreenRecorderTab.qml @@ -64,7 +64,7 @@ ColumnLayout { // Source NComboBox { label: "Video Source" - description: "Portal is recommended, if you get artifacts try Screen." + description: "Portal is recommend, if you get artifacts try Screen." model: ListModel { ListElement { key: "portal" diff --git a/Modules/Toast/SimpleToast.qml b/Modules/Toast/SimpleToast.qml index 90a8416..bc51858 100644 --- a/Modules/Toast/SimpleToast.qml +++ b/Modules/Toast/SimpleToast.qml @@ -136,7 +136,7 @@ Rectangle { colorBorder: Color.transparent colorBorderHover: Color.mOutline - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 Layout.alignment: Qt.AlignTop onClicked: root.hide() diff --git a/Modules/WiFiPanel/WiFiPanel.qml b/Modules/WiFiPanel/WiFiPanel.qml index 190110c..bfda627 100644 --- a/Modules/WiFiPanel/WiFiPanel.qml +++ b/Modules/WiFiPanel/WiFiPanel.qml @@ -57,7 +57,7 @@ NPanel { NIconButton { icon: "refresh" tooltipText: "Refresh" - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 enabled: Settings.data.network.wifiEnabled && !NetworkService.scanning onClicked: NetworkService.scan() } @@ -65,7 +65,7 @@ NPanel { NIconButton { icon: "close" tooltipText: "Close." - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: root.close() } } @@ -106,7 +106,7 @@ NPanel { NIconButton { icon: "close" - baseSize: Style.baseWidgetSize * 0.6 + sizeRatio: 0.6 onClicked: NetworkService.lastError = "" } } @@ -368,7 +368,7 @@ NPanel { visible: (modelData.existing || modelData.cached) && !modelData.connected && NetworkService.connectingTo !== modelData.ssid && NetworkService.forgettingNetwork !== modelData.ssid && NetworkService.disconnectingFrom !== modelData.ssid icon: "trash" tooltipText: "Forget network" - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.7 onClicked: expandedSsid = expandedSsid === modelData.ssid ? "" : modelData.ssid } @@ -478,7 +478,7 @@ NPanel { NIconButton { icon: "close" - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: { passwordSsid = "" passwordInput = "" @@ -532,7 +532,7 @@ NPanel { NIconButton { icon: "close" - baseSize: Style.baseWidgetSize * 0.8 + sizeRatio: 0.8 onClicked: expandedSsid = "" } } diff --git a/README.md b/README.md index d839edc..0429709 100644 --- a/README.md +++ b/README.md @@ -230,23 +230,6 @@ Start the Shell with: `qs -c noctalia-shell` Access settings through the side panel (top right button) to configure weather, wallpapers, screen recording, audio, network, and theme options. Configuration is usually stored in ~/.config/noctalia. -### Some of my app icons are missing! - -The issue is most likely that you did not set up your environment variables properly. -Example environment variables that you can use one of the following: - -If you already have an icon theme set for GTK then you can use this one: -- `QT_QPA_PLATFORMTHEME=gtk3` - -You can also use Qt6ct to set your icon theme, for that you can use: -- `QT_QPA_PLATFORMTHEME=qt6ct` - -If you don't have either of those set then you can just use: -- `QS_ICON_THEME="youricontheme"` - -**Any of these environment variables should go into `/etc/environment` (you need to reboot afterwards). For NixOS you can use `environment.variables` or `home.sessionVariables`.** - - ### Application Launcher The launcher supports special commands for enhanced functionality: @@ -295,6 +278,10 @@ window-rule { clip-to-geometry true } +layer-rule { + match namespace="^quickshell-wallpaper$" +} + layer-rule { match namespace="^quickshell-overview$" place-within-backdrop true diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index f12a94c..392b570 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -207,7 +207,7 @@ Singleton { return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true) } - function getPillDirection(widget) { + function getNPillDirection(widget) { try { if (widget.section === "left") { return true diff --git a/Services/PanelService.qml b/Services/PanelService.qml index f1df973..8922034 100644 --- a/Services/PanelService.qml +++ b/Services/PanelService.qml @@ -16,9 +16,6 @@ Singleton { property var registeredPanels: ({}) - signal willOpen - signal willClose - // Register this panel function registerPanel(panel) { registeredPanels[panel.objectName] = panel @@ -41,14 +38,6 @@ Singleton { openedPanel.close() } openedPanel = panel - - // emit signal - willOpen() - } - - function willClosePanel(panel) { - // emit signal - willClose() } function closedPanel(panel) { diff --git a/Services/SystemStatService.qml b/Services/SystemStatService.qml index 7a87e5c..a8d37d1 100644 --- a/Services/SystemStatService.qml +++ b/Services/SystemStatService.qml @@ -333,26 +333,6 @@ Singleton { } } - // Compact speed formatter for vertical bar display - function formatCompactSpeed(bytesPerSecond) { - if (!bytesPerSecond || bytesPerSecond <= 0) - return "0" - const units = ["", "K", "M", "G"] - let value = bytesPerSecond - let unitIndex = 0 - while (value >= 1024 && unitIndex < units.length - 1) { - value = value / 1024.0 - unitIndex++ - } - // Promote at ~100 of current unit (e.g., 100k -> ~0.1M shown as 0.1M or 0M if rounded) - if (unitIndex < units.length - 1 && value >= 100) { - value = value / 1024.0 - unitIndex++ - } - const display = Math.round(value).toString() - return display + units[unitIndex] - } - // ------------------------------------------------------- // Function to start fetching and computing the cpu temperature function updateCpuTemperature() { diff --git a/Services/UpdateService.qml b/Services/UpdateService.qml index 92bd577..c56a489 100644 --- a/Services/UpdateService.qml +++ b/Services/UpdateService.qml @@ -8,7 +8,7 @@ Singleton { id: root // Public properties - property string baseVersion: "2.11.0" + property string baseVersion: "2.9.2" property bool isDevelopment: false property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + "-dev"}` diff --git a/Widgets/NColorPicker.qml b/Widgets/NColorPicker.qml index 8eee16b..92525dd 100644 --- a/Widgets/NColorPicker.qml +++ b/Widgets/NColorPicker.qml @@ -13,7 +13,7 @@ Rectangle { signal colorSelected(color color) implicitWidth: 150 * scaling - implicitHeight: Math.round(Style.baseWidgetSize * 1.1 * scaling) + implicitHeight: 40 * scaling radius: Style.radiusM * scaling color: Color.mSurface @@ -40,16 +40,12 @@ Rectangle { RowLayout { anchors.fill: parent - anchors { - leftMargin: Style.marginL * scaling - rightMargin: Style.marginL * scaling - } + anchors.margins: Style.marginS * scaling spacing: Style.marginS * scaling - // Color preview circle Rectangle { - Layout.preferredWidth: root.height * 0.6 * scaling - Layout.preferredHeight: root.height * 0.6 * scaling + Layout.preferredWidth: 24 * scaling + Layout.preferredHeight: 24 * scaling radius: Layout.preferredWidth * 0.5 color: root.selectedColor border.color: Color.mOutline @@ -60,14 +56,11 @@ Rectangle { text: root.selectedColor.toString().toUpperCase() font.family: Settings.data.ui.fontFixed Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter } NIcon { icon: "color-picker" color: Color.mOnSurfaceVariant - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter } } } diff --git a/Widgets/NIconButton.qml b/Widgets/NIconButton.qml index 5989190..07f2798 100644 --- a/Widgets/NIconButton.qml +++ b/Widgets/NIconButton.qml @@ -7,14 +7,14 @@ import qs.Services Rectangle { id: root - property real baseSize: Style.baseWidgetSize + // Multiplier to control how large the button container is relative to Style.baseWidgetSize + property real sizeRatio: 1.0 property string icon property string tooltipText property bool enabled: true property bool allowClickWhenDisabled: false property bool hovering: false - property bool compact: false property color colorBg: Color.mSurfaceVariant property color colorFg: Color.mPrimary @@ -29,8 +29,8 @@ Rectangle { signal rightClicked signal middleClicked - implicitWidth: Math.round(baseSize * scaling) - implicitHeight: Math.round(baseSize * scaling) + implicitWidth: Math.round(Style.baseWidgetSize * scaling * sizeRatio) + implicitHeight: Math.round(Style.baseWidgetSize * scaling * sizeRatio) opacity: root.enabled ? Style.opacityFull : Style.opacityMedium color: root.enabled && root.hovering ? colorBgHover : colorBg @@ -47,7 +47,7 @@ Rectangle { NIcon { icon: root.icon - font.pointSize: Math.max(1, root.compact ? root.width * 0.65 : root.width * 0.48) + font.pointSize: Math.max(1, root.width * 0.47) color: root.enabled && root.hovering ? colorFgHover : colorFg // Center horizontally x: (root.width - width) / 2 diff --git a/Widgets/NPanel.qml b/Widgets/NPanel.qml index 5b4b898..ef286f1 100644 --- a/Widgets/NPanel.qml +++ b/Widgets/NPanel.qml @@ -38,9 +38,9 @@ Loader { readonly property real originalOpacity: 0.0 property real scaleValue: originalScale property real opacityValue: originalOpacity - property real dimmingOpacity: 0 property alias isClosing: hideTimer.running + readonly property string barPosition: Settings.data.bar.position signal opened signal closed @@ -109,11 +109,9 @@ Loader { // ----------------------------------------- function close() { - dimmingOpacity = 0 scaleValue = originalScale opacityValue = originalOpacity hideTimer.start() - PanelService.willClosePanel(root) } // ----------------------------------------- @@ -143,16 +141,10 @@ Loader { // PanelWindow has its own screen property inherited of QsWindow property real scaling: ScalingService.getScreenScale(screen) - - readonly property string barPosition: Settings.data.bar.position - readonly property bool isVertical: barPosition === "left" || barPosition === "right" + readonly property real barHeight: Math.round(Style.barHeight * scaling) + readonly property real barWidth: Math.round(Style.barHeight * scaling) + readonly property bool barAtBottom: Settings.data.bar.position === "bottom" readonly property bool barIsVisible: (screen !== null) && (Settings.data.bar.monitors.includes(screen.name) || (Settings.data.bar.monitors.length === 0)) - readonly property real verticalBarWidth: Math.round(Style.barHeight * scaling) - - Component.onCompleted: { - Logger.log("NPanel", "Opened", root.objectName) - dimmingOpacity = Style.opacityHeavy - } Connections { target: ScalingService @@ -177,14 +169,16 @@ Loader { visible: true - color: Settings.data.general.dimDesktop ? Qt.alpha(Color.mShadow, dimmingOpacity) : Color.transparent + // Dim desktop if required + color: (root.active && !root.isClosing && Settings.data.general.dimDesktop) ? Qt.alpha(Color.mShadow, Style.opacityHeavy) : Color.transparent + WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.namespace: "noctalia-panel" WlrLayershell.keyboardFocus: root.panelKeyboardFocus ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None Behavior on color { ColorAnimation { - duration: Style.animationSlow + duration: Style.animationNormal } } @@ -192,6 +186,29 @@ Loader { anchors.left: true anchors.right: true anchors.bottom: true + margins.top: { + if (!barIsVisible || barAtBottom) { + return 0 + } + switch (Settings.data.bar.position) { + case "top": + return (Style.barHeight + Style.marginM) * scaling + (Settings.data.bar.floating && !panelAnchorVerticalCenter ? Settings.data.bar.marginVertical * Style.marginXL * scaling : 0) + default: + return Style.marginM * scaling + } + } + + margins.bottom: { + if (!barIsVisible || !barAtBottom) { + return 0 + } + switch (Settings.data.bar.position) { + case "bottom": + return (Style.barHeight + Style.marginM) * scaling + (Settings.data.bar.floating && !panelAnchorVerticalCenter ? Settings.data.bar.marginVertical * Style.marginXL * scaling : 0) + default: + return 0 + } + } // Close any panel with Esc without requiring focus Shortcut { @@ -208,7 +225,6 @@ Loader { onClicked: root.close() } - // The actual panel's content Rectangle { id: panelBackground color: panelBackgroundColor @@ -239,131 +255,130 @@ Loader { scale: root.scaleValue opacity: root.opacityValue + x: calculatedX y: calculatedY - // --------------------------------------------- - // Does not account for corners are they are negligible and helps keep the code clean. - // --------------------------------------------- - property real marginTop: { - if (!barIsVisible) { - return 0 - } - switch (barPosition || panelAnchorVerticalCenter) { - case "top": - return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * 2 * Style.marginXL * scaling : 0) - default: - return Style.marginS * scaling - } - } - - property real marginBottom: { - if (!barIsVisible || panelAnchorVerticalCenter) { - return 0 - } - switch (barPosition) { - case "bottom": - return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginVertical * 2 * Style.marginXL * scaling : 0) - default: - return Style.marginS * scaling - } - } - - property real marginLeft: { - if (!barIsVisible || panelAnchorHorizontalCenter) { - return 0 - } - switch (barPosition) { - case "left": - return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginHorizontal * 2 * Style.marginXL * scaling : 0) - default: - return Style.marginS * scaling - } - } - - property real marginRight: { - if (!barIsVisible || panelAnchorHorizontalCenter) { - return 0 - } - switch (barPosition) { - case "right": - return (Style.barHeight + Style.marginS) * scaling + (Settings.data.bar.floating ? Settings.data.bar.marginHorizontal * 2 * Style.marginXL * scaling : 0) - default: - return Style.marginS * scaling - } - } - - // --------------------------------------------- property int calculatedX: { - // Priority to fixed anchoring - if (panelAnchorHorizontalCenter) { - return Math.round((panelWindow.width - panelBackground.width) / 2) - } else if (panelAnchorLeft) { - return marginLeft - } else if (panelAnchorRight) { - return Math.round(panelWindow.width - panelBackground.width - marginRight) - } + var barPosition = Settings.data.bar.position - // No fixed anchoring - if (isVertical) { - // Vertical bar + // Check anchor properties first, even when using button positioning + if (!panelAnchorHorizontalCenter && panelAnchorLeft) { + return Math.round(Style.marginS * scaling) + } else if (!panelAnchorHorizontalCenter && panelAnchorRight) { + // For right anchor, consider bar position if (barPosition === "right") { - // To the left of the right bar - return Math.round(panelWindow.width - panelBackground.width - marginRight) + // If bar is on right, position panel to the left of the bar + var maxX = panelWindow.width - barWidth - panelBackground.width - (Style.marginS * scaling) + + // If we have button position, position close to the button like working panels + if (root.useButtonPosition) { + // Use the same logic as working panels - position at edge of bar with spacing + var maxXWithSpacing = panelWindow.width - barWidth - panelBackground.width + // Add spacing - more if screen corners are disabled, less if enabled + if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) { + maxXWithSpacing -= Style.marginL * scaling + } else { + maxXWithSpacing -= Style.marginM * scaling + } + return Math.round(maxXWithSpacing) + } else { + return Math.round(maxX) + } } else { - // To the right of the left bar - return marginLeft + // Default right positioning + var rightX = panelWindow.width - panelBackground.width - (Style.marginS * scaling) + return Math.round(rightX) } + } else if (root.useButtonPosition) { + // Position panel relative to button (only if no explicit anchoring) + var targetX + + // For vertical bars, position panel close to the button + if (barPosition === "left") { + // Position panel to the right of the left bar, close to the button + var minX = barWidth + // Add spacing - more if screen corners are disabled, less if enabled + if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) { + minX += Style.marginL * scaling + } else { + minX += Style.marginM * scaling + } + targetX = minX + } else if (barPosition === "right") { + // Position panel to the left of the right bar, close to the button + var maxX = panelWindow.width - barWidth - panelBackground.width + // Add spacing - more if screen corners are disabled, less if enabled + if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) { + maxX -= Style.marginL * scaling + } else { + maxX -= Style.marginM * scaling + } + targetX = maxX + } else { + // For horizontal bars, center panel on button + targetX = root.buttonPosition.x + (root.buttonWidth / 2) - (panelBackground.width / 2) + } + + // Keep panel within screen bounds + var maxScreenX = panelWindow.width - panelBackground.width - (Style.marginS * scaling) + var minScreenX = Style.marginS * scaling + + return Math.round(Math.max(minScreenX, Math.min(targetX, maxScreenX))) } else { - // Horizontal bar - if (root.useButtonPosition) { - // Position panel relative to button - var targetX = buttonPosition.x + (buttonWidth / 2) - (panelBackground.width / 2) - // Keep panel within screen bounds - var maxX = panelWindow.width - panelBackground.width - marginRight - var minX = marginLeft - return Math.round(Math.max(minX, Math.min(targetX, maxX))) - } else { - // Fallback to center horizontally - return Math.round((panelWindow.width - panelBackground.width) / 2) + // For vertical bars, center but avoid bar overlap + var centerX = (panelWindow.width - panelBackground.width) / 2 + if (barPosition === "left") { + var minX = barWidth + // Add spacing - more if screen corners are disabled, less if enabled + if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) { + minX += Style.marginL * scaling + } else { + minX += Style.marginM * scaling + } + centerX = Math.max(centerX, minX) + } else if (barPosition === "right") { + // For right bar, center but ensure it doesn't overlap with the bar + var maxX = panelWindow.width - barWidth - panelBackground.width + // Add spacing - more if screen corners are disabled, less if enabled + if (!Settings.data.general.showScreenCorners || Settings.data.bar.floating) { + maxX -= Style.marginL * scaling + } else { + maxX -= Style.marginM * scaling + } + centerX = Math.min(centerX, maxX) } + return Math.round(centerX) } } - // --------------------------------------------- property int calculatedY: { - // Priority to fixed anchoring - if (panelAnchorVerticalCenter) { - return Math.round((panelWindow.height - panelBackground.height) / 2) - } else if (panelAnchorTop) { - return marginTop - } else if (panelAnchorBottom) { - return Math.round(panelWindow.height - panelBackground.height - marginBottom) - } + var barPosition = Settings.data.bar.position - // No fixed anchoring - if (isVertical) { - // Vertical bar - if (useButtonPosition) { - // Position panel relative to button - var targetY = buttonPosition.y + (buttonHeight / 2) - (panelBackground.height / 2) - // Keep panel within screen bounds - var maxY = panelWindow.height - panelBackground.height - marginBottom - var minY = marginTop - return Math.round(Math.max(minY, Math.min(targetY, maxY))) - } else { - // Fallback to center vertically - return Math.round((panelWindow.height - panelBackground.height) / 2) - } + if (root.useButtonPosition) { + // Position panel relative to button + var targetY = root.buttonPosition.y + (root.buttonHeight / 2) - (panelBackground.height / 2) + + // Keep panel within screen bounds + var maxY = panelWindow.height - panelBackground.height - (Style.marginS * scaling) + var minY = Style.marginS * scaling + + return Math.round(Math.max(minY, Math.min(targetY, maxY))) + } else if (panelAnchorVerticalCenter) { + return Math.round((panelWindow.height - panelBackground.height) / 2) + } else if (panelAnchorBottom) { + return Math.round(panelWindow.height - panelBackground.height - (Style.marginS * scaling)) + } else if (panelAnchorTop) { + return Math.round(Style.marginS * scaling) + } else if (barPosition === "left" || barPosition === "right") { + // For vertical bars, center vertically + return Math.round((panelWindow.height - panelBackground.height) / 2) + } else if (!barAtBottom) { + // Below the top bar + return Math.round(Style.marginS * scaling) } else { - // Horizontal bar - if (barPosition === "bottom") { - // Above the bottom bar - return Math.round(panelWindow.height - panelBackground.height - marginBottom) - } else { - // Below the top bar - return marginTop - } + // Above the bottom bar + return Math.round(panelWindow.height - panelBackground.height - (Style.marginS * scaling)) } } diff --git a/Modules/Bar/Extras/BarPill.qml b/Widgets/NPill.qml similarity index 94% rename from Modules/Bar/Extras/BarPill.qml rename to Widgets/NPill.qml index 6714d17..d6f0fac 100644 --- a/Modules/Bar/Extras/BarPill.qml +++ b/Widgets/NPill.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import qs.Commons import qs.Services -import qs.Widgets Item { id: root @@ -11,13 +10,13 @@ Item { property string text: "" property string suffix: "" property string tooltipText: "" + property real sizeRatio: 0.8 property bool autoHide: false property bool forceOpen: false property bool forceClose: false property bool disableOpen: false property bool rightOpen: false property bool hovered: false - property bool compact: false readonly property string barPosition: Settings.data.bar.position readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right" @@ -42,18 +41,18 @@ Item { Component { id: verticalPillComponent - BarPillVertical { + NPillVertical { icon: root.icon text: root.text suffix: root.suffix tooltipText: root.tooltipText + sizeRatio: root.sizeRatio autoHide: root.autoHide forceOpen: root.forceOpen forceClose: root.forceClose disableOpen: root.disableOpen rightOpen: root.rightOpen hovered: root.hovered - compact: root.compact onShown: root.shown() onHidden: root.hidden() onEntered: root.entered() @@ -67,18 +66,18 @@ Item { Component { id: horizontalPillComponent - BarPillHorizontal { + NPillHorizontal { icon: root.icon text: root.text suffix: root.suffix tooltipText: root.tooltipText + sizeRatio: root.sizeRatio autoHide: root.autoHide forceOpen: root.forceOpen forceClose: root.forceClose disableOpen: root.disableOpen rightOpen: root.rightOpen hovered: root.hovered - compact: root.compact onShown: root.shown() onHidden: root.hidden() onEntered: root.entered() diff --git a/Modules/Bar/Extras/BarPillHorizontal.qml b/Widgets/NPillHorizontal.qml similarity index 85% rename from Modules/Bar/Extras/BarPillHorizontal.qml rename to Widgets/NPillHorizontal.qml index 0e4b548..89888ba 100644 --- a/Modules/Bar/Extras/BarPillHorizontal.qml +++ b/Widgets/NPillHorizontal.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import qs.Commons import qs.Services -import qs.Widgets Item { id: root @@ -11,13 +10,13 @@ Item { property string text: "" property string suffix: "" property string tooltipText: "" + property real sizeRatio: 0.8 property bool autoHide: false property bool forceOpen: false property bool forceClose: false property bool disableOpen: false property bool rightOpen: false property bool hovered: false - property bool compact: false // Effective shown state (true if hovered/animated open or forced) readonly property bool revealed: forceOpen || showPill @@ -35,27 +34,26 @@ Item { property bool showPill: false property bool shouldAnimateHide: false - readonly property int pillHeight: Math.round(Style.capsuleHeight * scaling) - readonly property int pillPaddingHorizontal: Math.round(Style.capsuleHeight * 0.2 * scaling) - readonly property int pillOverlap: Math.round(Style.capsuleHeight * 0.5 * scaling) - readonly property int pillMaxWidth: Math.max(1, textItem.implicitWidth + pillPaddingHorizontal * 2 + pillOverlap) + // Exposed width logic + readonly property int iconSize: Math.round(Style.baseWidgetSize * sizeRatio * scaling) + readonly property int pillHeight: iconSize + readonly property int pillPaddingHorizontal: 3 * 2 * scaling // Very precise adjustment don't replace by Style.margin + readonly property int pillOverlap: iconSize * 0.5 + readonly property int maxPillWidth: Math.max(1, textItem.implicitWidth + pillPaddingHorizontal * 2 + pillOverlap) - readonly property real iconSize: Math.max(1, compact ? pillHeight * 0.65 : pillHeight * 0.48) - readonly property real textSize: Math.max(1, compact ? pillHeight * 0.45 : pillHeight * 0.33) - - width: pillHeight + Math.max(0, pill.width - pillOverlap) + width: iconSize + Math.max(0, pill.width - pillOverlap) height: pillHeight Rectangle { id: pill - width: revealed ? pillMaxWidth : 1 + width: revealed ? maxPillWidth : 1 height: pillHeight x: rightOpen ? (iconCircle.x + iconCircle.width / 2) : // Opens right (iconCircle.x + iconCircle.width / 2) - width // Opens left opacity: revealed ? Style.opacityFull : Style.opacityNone - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant topLeftRadius: rightOpen ? 0 : pillHeight * 0.5 bottomLeftRadius: rightOpen ? 0 : pillHeight * 0.5 @@ -78,7 +76,7 @@ Item { } text: root.text + root.suffix font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + font.pointSize: Style.fontSizeXS * scaling font.weight: Style.fontWeightBold color: forceOpen ? Color.mOnSurface : Color.mPrimary visible: revealed @@ -102,10 +100,10 @@ Item { Rectangle { id: iconCircle - width: pillHeight - height: pillHeight + width: iconSize + height: iconSize radius: width * 0.5 - color: hovered ? Color.mTertiary : Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: hovered ? Color.mTertiary : Color.mSurfaceVariant anchors.verticalCenter: parent.verticalCenter x: rightOpen ? 0 : (parent.width - width) @@ -119,7 +117,7 @@ Item { NIcon { icon: root.icon - font.pointSize: iconSize + font.pointSize: Style.fontSizeM * scaling color: hovered ? Color.mOnTertiary : Color.mOnSurface // Center horizontally x: (iconCircle.width - width) / 2 @@ -135,7 +133,7 @@ Item { target: pill property: "width" from: 1 - to: pillMaxWidth + to: maxPillWidth duration: Style.animationNormal easing.type: Easing.OutCubic } @@ -175,7 +173,7 @@ Item { NumberAnimation { target: pill property: "width" - from: pillMaxWidth + from: maxPillWidth to: 1 duration: Style.animationNormal easing.type: Easing.InCubic diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Widgets/NPillVertical.qml similarity index 87% rename from Modules/Bar/Extras/BarPillVertical.qml rename to Widgets/NPillVertical.qml index 494083e..fb5037a 100644 --- a/Modules/Bar/Extras/BarPillVertical.qml +++ b/Widgets/NPillVertical.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import qs.Commons import qs.Services -import qs.Widgets Item { id: root @@ -11,13 +10,13 @@ Item { property string text: "" property string suffix: "" property string tooltipText: "" + property real sizeRatio: 0.8 property bool autoHide: false property bool forceOpen: false property bool forceClose: false property bool disableOpen: false property bool rightOpen: false property bool hovered: false - property bool compact: false // Bar position detection for pill direction readonly property string barPosition: Settings.data.bar.position @@ -44,19 +43,16 @@ Item { property bool shouldAnimateHide: false // Sizing logic for vertical bars - readonly property int buttonSize: Math.round(Style.capsuleHeight * scaling) - readonly property int pillHeight: buttonSize + readonly property int iconSize: Math.round(Style.baseWidgetSize * sizeRatio * scaling) + readonly property int pillHeight: iconSize readonly property int pillPaddingVertical: 3 * 2 * scaling // Very precise adjustment don't replace by Style.margin - readonly property int pillOverlap: buttonSize * 0.5 - readonly property int maxPillWidth: buttonSize + readonly property int pillOverlap: iconSize * 0.5 + readonly property int maxPillWidth: iconSize readonly property int maxPillHeight: Math.max(1, textItem.implicitHeight + pillPaddingVertical * 4) - readonly property real iconSize: Math.max(1, compact ? pillHeight * 0.65 : pillHeight * 0.48) - readonly property real textSize: Math.max(1, compact ? pillHeight * 0.38 : pillHeight * 0.33) - // For vertical bars: width is just icon size, height includes pill space - width: buttonSize - height: revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize + width: iconSize + height: revealed ? (iconSize + maxPillHeight - pillOverlap) : iconSize Rectangle { id: pill @@ -68,13 +64,13 @@ Item { y: openUpward ? (iconCircle.y + iconCircle.height / 2 - height) : (iconCircle.y + iconCircle.height / 2) opacity: revealed ? Style.opacityFull : Style.opacityNone - color: Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: Color.mSurfaceVariant // Radius logic for vertical expansion - rounded on the side that connects to icon - topLeftRadius: openUpward ? buttonSize * 0.5 : 0 - bottomLeftRadius: openDownward ? buttonSize * 0.5 : 0 - topRightRadius: openUpward ? buttonSize * 0.5 : 0 - bottomRightRadius: openDownward ? buttonSize * 0.5 : 0 + topLeftRadius: openUpward ? iconSize * 0.5 : 0 + bottomLeftRadius: openDownward ? iconSize * 0.5 : 0 + topRightRadius: openUpward ? iconSize * 0.5 : 0 + bottomRightRadius: openDownward ? iconSize * 0.5 : 0 anchors.horizontalCenter: parent.horizontalCenter @@ -92,7 +88,7 @@ Item { } text: root.text + root.suffix font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + font.pointSize: Style.fontSizeXXS * scaling font.weight: Style.fontWeightMedium horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -125,10 +121,10 @@ Item { Rectangle { id: iconCircle - width: buttonSize - height: buttonSize + width: iconSize + height: iconSize radius: width * 0.5 - color: hovered ? Color.mTertiary : Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent + color: hovered ? Color.mTertiary : Color.mSurfaceVariant // Icon positioning based on direction x: 0 @@ -144,7 +140,7 @@ Item { NIcon { icon: root.icon - font.pointSize: iconSize + font.pointSize: Style.fontSizeM * scaling color: hovered ? Color.mOnTertiary : Color.mOnSurface // Center horizontally x: (iconCircle.width - width) / 2 diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index cd1d42c..4b6a7f5 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -173,7 +173,6 @@ RowLayout { NText { anchors.centerIn: parent text: root.prefix + spinBox.value + root.suffix - font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface diff --git a/Widgets/NWidgetLoader.qml b/Widgets/NWidgetLoader.qml index ac4c542..17bf887 100644 --- a/Widgets/NWidgetLoader.qml +++ b/Widgets/NWidgetLoader.qml @@ -49,7 +49,7 @@ Item { item.onLoaded() } - Logger.log("NWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name) + //Logger.log("NWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name) } }