From 52fd1443a0beb7c6b732df0f44eb1fb1c5010cc2 Mon Sep 17 00:00:00 2001 From: Brainitech Date: Wed, 17 Jun 2026 02:21:32 +0530 Subject: [PATCH 1/3] fix(Scale): Attempt 1 on trying to fix scaling across different screen sizes This commit is currently on a different branch. In order to test it, pull this branch onto your existing setup and let me know how it looks on other screen sizes. I was only able to test it on one kind of monitor. There are some inconsistencies that I noticed on the right notch, they will be fixed soon. If anyone is testing this branch. Just let me know waht you find. --- src/components/DiskBar.qml | 25 +- src/components/IconBtn.qml | 9 +- src/components/ProfileButton.qml | 11 +- src/components/StatCard.qml | 5 +- src/components/StatRow.qml | 7 +- src/components/TabSwitcher.qml | 29 +-- src/components/TimeInput.qml | 44 ++-- src/modules/Center/CenterContent.qml | 123 +++++----- src/modules/Center/DashStats.qml | 44 +++- src/modules/Center/DiskPanel.qml | 26 +- src/modules/Center/FanPanel.qml | 8 +- src/modules/Center/NetStatsPanel.qml | 12 +- src/modules/Center/PowerPanel.qml | 26 +- src/modules/Center/TempPanel.qml | 3 +- src/modules/Left/LayoutDisplayer.qml | 10 +- src/modules/Left/LeftContent.qml | 19 +- src/modules/Left/Workspaces.qml | 15 +- src/modules/Right/Audio.qml | 11 +- src/modules/Right/Battery.qml | 2 + src/modules/Right/Clock.qml | 4 +- src/modules/Right/Network.qml | 14 +- src/modules/Right/Notifications.qml | 1 + src/modules/Right/RightContent.qml | 39 ++- src/modules/Right/SysTray.qml | 12 +- src/popups/ArchMenu.qml | 45 ++-- src/popups/AudioPopup.qml | 31 +-- src/popups/BluetoothTab.qml | 199 +++++++-------- src/popups/ClipboardPopup.qml | 23 +- src/popups/Dashboard.qml | 58 +++-- src/popups/HistoryTab.qml | 17 +- src/popups/HotspotTab.qml | 87 +++---- src/popups/NetworkPopup.qml | 43 ++-- src/popups/NotificationToast.qml | 97 ++++---- src/popups/NotificationsPopup.qml | 35 +-- src/popups/PopupLayer.qml | 4 +- src/popups/QuickControl.qml | 53 ++-- src/popups/ScreenRecOptionsPopup.qml | 27 +- src/popups/VPNTab.qml | 102 ++++---- src/popups/WallpaperPopup.qml | 139 ++++++----- src/popups/WifiTab.qml | 194 +++++++-------- src/services/AppLauncher.qml | 66 ++--- src/services/AudioControl.qml | 68 ++--- src/services/BatteryStatus.qml | 12 +- src/services/KanbanBoard.qml | 232 +++++++++--------- src/services/PowerMenu.qml | 13 +- src/services/config_tab/ShellConfig.qml | 29 ++- src/services/home/CalendarCard.qml | 24 +- src/services/home/ClockCard.qml | 133 +++++----- src/services/home/DashHome.qml | 15 +- src/services/home/PlayerCard.qml | 74 +++--- src/services/home/ProfileCard.qml | 27 +- src/services/home/QuickSettings.qml | 108 ++++---- .../notifications/NotificationList.qml | 64 ++--- src/services/system/EnvyControl.qml | 33 +-- src/theme/Metrics.qml | 2 +- src/windows/Border.qml | 13 +- src/windows/ConfirmDialog.qml | 69 +++--- src/windows/TopBar.qml | 57 +++-- src/windows/UpdatePopup.qml | 113 ++++----- 59 files changed, 1508 insertions(+), 1297 deletions(-) diff --git a/src/components/DiskBar.qml b/src/components/DiskBar.qml index 0619b7b..63b8a96 100644 --- a/src/components/DiskBar.qml +++ b/src/components/DiskBar.qml @@ -9,9 +9,10 @@ Item { property int usedPct: 0 property string usedStr: "—" property string totalStr: "—" + property real localScale: 1.0 - implicitWidth: 200 - implicitHeight: 40 + implicitWidth: Math.round(200 * localScale) + implicitHeight: Math.round(40 * localScale) readonly property color barColor: { if (usedPct >= 90) return "#f38ba8" @@ -25,9 +26,9 @@ Item { anchors.left: parent.left anchors.verticalCenter: barTrack.verticalCenter text: root.mount - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(1, 1, 1, 0.5) - width: 32 + width: Math.round(32 * localScale) elide: Text.ElideRight } @@ -37,10 +38,10 @@ Item { anchors.left: mountLabel.right anchors.right: pctLabel.left anchors.top: parent.top - anchors.topMargin: 12 - anchors.leftMargin: 6 - anchors.rightMargin: 6 - height: 6 + anchors.topMargin: Math.round(12 * localScale) + anchors.leftMargin: Math.round(6 * localScale) + anchors.rightMargin: Math.round(6 * localScale) + height: Math.round(6 * localScale) Rectangle { anchors.fill: parent @@ -69,10 +70,10 @@ Item { anchors.right: parent.right anchors.verticalCenter: barTrack.verticalCenter text: root.usedPct + "%" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) font.weight: Font.Medium color: root.barColor - width: 28 + width: Math.round(28 * localScale) horizontalAlignment: Text.AlignRight Behavior on color { ColorAnimation { duration: 300 } } } @@ -81,9 +82,9 @@ Item { Text { anchors.horizontalCenter: barTrack.horizontalCenter anchors.top: barTrack.bottom - anchors.topMargin: 4 + anchors.topMargin: Math.round(4 * localScale) text: root.usedStr + " / " + root.totalStr + " · " + root.source - font.pixelSize: 9 + font.pixelSize: Math.round(9 * localScale) color: Qt.rgba(1, 1, 1, 0.45) } } diff --git a/src/components/IconBtn.qml b/src/components/IconBtn.qml index b55b249..6d6ec5c 100644 --- a/src/components/IconBtn.qml +++ b/src/components/IconBtn.qml @@ -3,9 +3,10 @@ import "../" Rectangle { id: root - width: 24 - height: 24 - radius: 4 + property real localScale: 1.0 + width: Math.round(24 * localScale) + height: Math.round(24 * localScale) + radius: Math.round(4 * localScale) // 1. Correct: referencing the ID 'hover' directly works here color: hover.hovered ? Theme.active : "transparent" @@ -21,7 +22,7 @@ Rectangle { // 2. FIX: Changed 'root.hoverHandler.hovered' to 'hover.hovered' color: hover.hovered ? Theme.background : root.textColor - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) } HoverHandler { diff --git a/src/components/ProfileButton.qml b/src/components/ProfileButton.qml index 082d205..403a8ea 100644 --- a/src/components/ProfileButton.qml +++ b/src/components/ProfileButton.qml @@ -7,12 +7,13 @@ Item { property string label: "" property string icon: "" property bool active: false + property real localScale: 1.0 // `enabled` is inherited from Item — no redeclaration needed signal clicked() - implicitWidth: row.implicitWidth + 24 - implicitHeight: 28 + implicitWidth: row.implicitWidth + Math.round(24 * localScale) + implicitHeight: Math.round(28 * localScale) opacity: root.enabled ? 1 : 0.35 Behavior on opacity { NumberAnimation { duration: 120 } } @@ -36,12 +37,12 @@ Item { Row { id: row anchors.centerIn: parent - spacing: 5 + spacing: Math.round(5 * localScale) Text { visible: root.icon !== "" text: root.icon - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: root.active ? Theme.background : Qt.rgba(1, 1, 1, 0.7) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 120 } } @@ -49,7 +50,7 @@ Item { Text { text: root.label - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) font.weight: root.active ? Font.Medium : Font.Normal color: root.active ? Theme.background : Qt.rgba(1, 1, 1, 0.7) anchors.verticalCenter: parent.verticalCenter diff --git a/src/components/StatCard.qml b/src/components/StatCard.qml index 3aee99d..b89620a 100644 --- a/src/components/StatCard.qml +++ b/src/components/StatCard.qml @@ -14,11 +14,12 @@ Item { id: root default property alias content: inner.data - property int padding: 12 + property int padding: 12 + property real localScale: 1.0 Rectangle { anchors.fill: parent - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba(1, 1, 1, 0.04) border.color: Qt.rgba(1, 1, 1, 0.07) border.width: 1 diff --git a/src/components/StatRow.qml b/src/components/StatRow.qml index b73b2f5..9d2841a 100644 --- a/src/components/StatRow.qml +++ b/src/components/StatRow.qml @@ -11,14 +11,15 @@ Item { property string label: "" property string value: "" property color valueColor: Theme.text + property real localScale: 1.0 - implicitHeight: 20 + implicitHeight: Math.round(20 * localScale) Text { anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter text: root.label - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: Qt.rgba(1, 1, 1, 0.4) } @@ -26,7 +27,7 @@ Item { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter text: root.value - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: root.valueColor } } diff --git a/src/components/TabSwitcher.qml b/src/components/TabSwitcher.qml index 4d22b94..14e6528 100644 --- a/src/components/TabSwitcher.qml +++ b/src/components/TabSwitcher.qml @@ -22,6 +22,7 @@ Item { property var model: [] property string currentPage: "" property string orientation: "horizontal" // "horizontal" | "vertical" + property real localScale: 1.0 signal pageChanged(string key) @@ -34,8 +35,8 @@ Item { pageChanged(defaultPage) } - implicitWidth: orientation === "vertical" ? 40 : 0 - implicitHeight: orientation === "horizontal" ? 40 : 0 + implicitWidth: orientation === "vertical" ? Math.round(40 * localScale) : 0 + implicitHeight: orientation === "horizontal" ? Math.round(40 * localScale) : 0 // ── Scroll cooldown ─────────────────────────────────────────────────────── property bool scrollBusy: false @@ -83,8 +84,8 @@ Item { Rectangle { id: hBg anchors.centerIn: parent - width: hIcon.implicitWidth + hLabel.implicitWidth + 24 - height: parent.height - 8 + width: hIcon.implicitWidth + hLabel.implicitWidth + Math.round(24 * localScale) + height: parent.height - Math.round(8 * localScale) radius: height / 2 color: hTab.isActive @@ -97,12 +98,12 @@ Item { // Icon + label Row { anchors.centerIn: parent - spacing: 6 + spacing: Math.round(6 * localScale) Text { id: hIcon text: modelData.icon - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) anchors.verticalCenter: parent.verticalCenter color: hTab.isActive ? Theme.active @@ -114,7 +115,7 @@ Item { id: hLabel visible: modelData.label !== undefined text: modelData.label ?? "" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) font.weight: hTab.isActive ? Font.Medium : Font.Normal anchors.verticalCenter: parent.verticalCenter color: hTab.isActive @@ -150,7 +151,7 @@ Item { visible: root.orientation === "vertical" width: root.width - readonly property int tabH: 60 + readonly property int tabH: Math.round(60 * localScale) spacing: root.model.length > 1 ? (root.height - root.model.length * tabH) / (root.model.length - 1) : 0 @@ -169,7 +170,7 @@ Item { width: vCol.width height: vCol.tabH - radius: Theme.cornerRadius * 2 + radius: Math.round(Theme.cornerRadius * 2 * localScale) color: vTab.isActive ? Theme.active @@ -182,7 +183,7 @@ Item { visible: !vCol.hasLabels anchors.centerIn: parent text: modelData.icon - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: vTab.isActive ? Theme.background : Theme.text Behavior on color { ColorAnimation { duration: 120 } } } @@ -192,14 +193,14 @@ Item { visible: vCol.hasLabels anchors { left: parent.left - leftMargin: 16 + leftMargin: Math.round(16 * localScale) verticalCenter: parent.verticalCenter } - spacing: 12 + spacing: Math.round(12 * localScale) Text { text: modelData.icon - font.pixelSize: 15 + font.pixelSize: Math.round(15 * localScale) anchors.verticalCenter: parent.verticalCenter color: vTab.isActive ? Theme.background @@ -209,7 +210,7 @@ Item { Text { text: modelData.label ?? "" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) font.weight: vTab.isActive ? Font.Medium : Font.Normal anchors.verticalCenter: parent.verticalCenter color: vTab.isActive diff --git a/src/components/TimeInput.qml b/src/components/TimeInput.qml index 5b192d5..16171cf 100644 --- a/src/components/TimeInput.qml +++ b/src/components/TimeInput.qml @@ -7,6 +7,8 @@ import QtQuick Item { id: root + property real localScale: 1.0 + readonly property int hours: hVal readonly property int minutes: mVal @@ -27,37 +29,37 @@ Item { Row { id: _row - spacing: 8 + spacing: Math.round(8 * localScale) // ══ HOURS ═════════════════════════════════════════════════════════════ Column { - spacing: 2 - width: 36 + spacing: Math.round(2 * localScale) + width: Math.round(36 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter - text: "HH"; font.pixelSize: 9; font.weight: Font.Medium + text: "HH"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Medium font.family: "JetBrains Mono" color: Qt.rgba(1,1,1,0.3) } Rectangle { - width: parent.width; height: 22; radius: 6 + width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: hUpH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: 9; color: Qt.rgba(1,1,1,0.4) } + Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: hUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.incH() } } Item { - width: parent.width; height: 30 + width: parent.width; height: Math.round(30 * localScale) Text { anchors.centerIn: parent text: root.zp(root.hVal) - font.pixelSize: 20; font.weight: Font.Bold + font.pixelSize: Math.round(20 * localScale); font.weight: Font.Bold font.family: "JetBrains Mono" color: Qt.rgba(235/255, 240/255, 255/255, 0.9) } @@ -73,11 +75,11 @@ Item { } Rectangle { - width: parent.width; height: 22; radius: 6 + width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: hDnH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: 9; color: Qt.rgba(1,1,1,0.4) } + Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: hDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.decH() } } @@ -86,42 +88,42 @@ Item { // Colon Text { anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: 8 + anchors.verticalCenterOffset: Math.round(8 * localScale) text: ":" - font.pixelSize: 22; font.weight: Font.Bold + font.pixelSize: Math.round(22 * localScale); font.weight: Font.Bold font.family: "JetBrains Mono" color: Qt.rgba(1,1,1,0.3) } // ══ MINUTES ═══════════════════════════════════════════════════════════ Column { - spacing: 2 - width: 36 + spacing: Math.round(2 * localScale) + width: Math.round(36 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter - text: "MM"; font.pixelSize: 9; font.weight: Font.Medium + text: "MM"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Medium font.family: "JetBrains Mono" color: Qt.rgba(1,1,1,0.3) } Rectangle { - width: parent.width; height: 22; radius: 6 + width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: mUpH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: 9; color: Qt.rgba(1,1,1,0.4) } + Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: mUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.incM() } } Item { - width: parent.width; height: 30 + width: parent.width; height: Math.round(30 * localScale) Text { anchors.centerIn: parent text: root.zp(root.mVal) - font.pixelSize: 20; font.weight: Font.Bold + font.pixelSize: Math.round(20 * localScale); font.weight: Font.Bold font.family: "JetBrains Mono" color: Qt.rgba(235/255, 240/255, 255/255, 0.9) } @@ -137,11 +139,11 @@ Item { } Rectangle { - width: parent.width; height: 22; radius: 6 + width: parent.width; height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: mDnH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.08); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: 9; color: Qt.rgba(1,1,1,0.4) } + Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: mDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.decM() } } diff --git a/src/modules/Center/CenterContent.qml b/src/modules/Center/CenterContent.qml index a32875a..1ea5a26 100644 --- a/src/modules/Center/CenterContent.qml +++ b/src/modules/Center/CenterContent.qml @@ -25,14 +25,15 @@ import "../../services/home/." Item { id: root - width: Theme.cNotchMinWidth - height: 30 + property real localScale: 1.0 + width: Math.round(Theme.cNotchMinWidth * localScale) + height: Math.round(30 * localScale) // ── Required notch width for the current carousel item ──────────────────── // TopBar.cWidth reads this so the notch always matches what is visible, // even if the user scrolls away from record_active while recording. - readonly property int fw: Theme.notchRadius - readonly property int requiredWidth: Theme.cNotchMinWidth + readonly property int fw: Math.round(Theme.notchRadius * localScale) + readonly property int requiredWidth: Math.round(Theme.cNotchMinWidth * localScale) // ── MPRIS ───────────────────────────────────────────────────────────────── readonly property var player: Mpris.players.values.length > 0 ? Mpris.players.values[0] : null @@ -101,7 +102,7 @@ Item { // ── Dynamic item list ───────────────────────────────────────────────────── property var _items: ["title"] property int _carouselIndex: 0 - readonly property real _itemStride: 45 // 30px height + 15px spacing + readonly property real _itemStride: Math.round(45 * localScale) // 30px height + 15px spacing function _rebuildItems(autoScrollType) { var currentType = (_items.length > _carouselIndex) @@ -235,7 +236,7 @@ Item { id: statusList anchors.fill: parent orientation: ListView.Vertical - spacing: 15 + spacing: Math.round(15 * localScale) clip: true snapMode: ListView.SnapOneItem interactive: false @@ -250,8 +251,8 @@ Item { required property string modelData required property int index - width: Theme.cNotchMinWidth - height: 30 + width: Math.round(Theme.cNotchMinWidth * localScale) + height: statusList.height // ── Title ────────────────────────────────────────────────────── Text { @@ -259,7 +260,7 @@ Item { visible: modelData === "title" text: root.activeTitle color: Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter // leftPadding: 8u rightPadding: 8 @@ -273,8 +274,8 @@ Item { anchors.rightMargin: root.fw/2 visible: modelData === "music" - readonly property int artSize: 20 - readonly property int artPad: 7 + readonly property int artSize: Math.round(20 * localScale) + readonly property int artPad: Math.round(7 * localScale) Item { x: parent.artPad @@ -292,7 +293,7 @@ Item { Text { anchors.centerIn: parent text: "♪" - font.pixelSize: 9 + font.pixelSize: Math.round(9 * localScale) color: Theme.active } } @@ -326,14 +327,14 @@ Item { id: barsArea anchors { left: parent.left - leftMargin: parent.artPad + parent.artSize + 5 + leftMargin: parent.artPad + parent.artSize + Math.round(5 * localScale) right: parent.right - rightMargin: 5 + rightMargin: Math.round(5 * localScale) top: parent.top bottom: parent.bottom } - readonly property real _barW: 5 + readonly property real _barW: Math.round(5 * localScale) readonly property real _barSpacing: Math.max( 1, (width - _barW * root._cavaBars) / Math.max(1, root._cavaBars - 1)) @@ -381,7 +382,7 @@ Item { verticalCenter: parent.verticalCenter } text: "󰔟" - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: root.timerUrgent ? "#ff5555" : Theme.active Behavior on color { ColorAnimation { duration: 200 } } } @@ -391,13 +392,13 @@ Item { id: timerText anchors { left: parent.left - leftMargin: 8 + leftMargin: Math.round(8 * localScale) right: parent.right - rightMargin: 8 + rightMargin: Math.round(8 * localScale) verticalCenter: parent.verticalCenter } text: ClockState.timerDisplay - font.pixelSize: 15 + font.pixelSize: Math.round(15 * localScale) font.weight: Font.Bold font.family: "JetBrains Mono" horizontalAlignment: Text.AlignHCenter @@ -435,7 +436,7 @@ Item { verticalCenter: parent.verticalCenter } text: ClockState.timerRunning ? "󱫟" : "󱫡" - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: _timerPauseHov.hovered ? Theme.active : Theme.text HoverHandler { id: _timerPauseHov; } MouseArea { @@ -449,7 +450,7 @@ Item { verticalCenter: parent.verticalCenter } text: "󱫥" - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: _timerResetHov.hovered ? Theme.active : Theme.text HoverHandler { id: _timerResetHov; cursorShape: Qt.PointingHandCursor } MouseArea { @@ -475,7 +476,7 @@ Item { verticalCenter: parent.verticalCenter } text: "" - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: Theme.active } @@ -483,13 +484,13 @@ Item { Text { anchors { left: parent.left - leftMargin: 8 + leftMargin: Math.round(8 * localScale) right: parent.right - rightMargin: 8 + rightMargin: Math.round(8 * localScale) verticalCenter: parent.verticalCenter } text: ClockState.swDisplay - font.pixelSize: 15 + font.pixelSize: Math.round(15 * localScale) font.weight: Font.Bold font.family: "JetBrains Mono" horizontalAlignment: Text.AlignHCenter @@ -509,7 +510,7 @@ Item { verticalCenter: parent.verticalCenter } text: ClockState.swRunning ? "󱫟" : "󱫡" - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: _pauseHov.hovered ? Theme.active : Theme.text HoverHandler { id: _pauseHov; } MouseArea { @@ -525,7 +526,7 @@ Item { verticalCenter: parent.verticalCenter } text: "󱫥" - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: _notchResetHov.hovered ? Theme.active : Theme.text HoverHandler { id: _notchResetHov; cursorShape: Qt.PointingHandCursor } @@ -551,14 +552,14 @@ Item { visible: modelData === "record_setup" Row { - anchors { fill: parent; leftMargin: 8; rightMargin: 8 } - spacing: 6 + anchors { fill: parent; leftMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } + spacing: Math.round(6 * localScale) // ── Capture strip button ─────────────────────────────── Item { anchors.verticalCenter: parent.verticalCenter - width: csRow.implicitWidth + 14 - height: 22 + width: csRow.implicitWidth + Math.round(14 * localScale) + height: Math.round(22 * localScale) Rectangle { anchors.fill: parent @@ -576,10 +577,10 @@ Item { Row { id: csRow anchors.centerIn: parent - spacing: 5 + spacing: Math.round(5 * localScale) Text { text: ScreenRecService.captureIcon - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) color: ScreenRecService.openStrip === "capture" ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter @@ -587,14 +588,14 @@ Item { } Text { text: ScreenRecService.captureLabel - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: ScreenRecService.openStrip === "capture" ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } } Text { - text: "▾"; font.pixelSize: 8 + text: "▾"; font.pixelSize: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.35) anchors.verticalCenter: parent.verticalCenter } @@ -619,8 +620,8 @@ Item { // ── Audio strip button ───────────────────────────────── Item { anchors.verticalCenter: parent.verticalCenter - width: asRow.implicitWidth + 14 - height: 22 + width: asRow.implicitWidth + Math.round(14 * localScale) + height: Math.round(22 * localScale) Rectangle { anchors.fill: parent @@ -638,21 +639,21 @@ Item { Row { id: asRow anchors.centerIn: parent - spacing: 5 + spacing: Math.round(5 * localScale) Text { - text: "🎙"; font.pixelSize: 12 + text: "🎙"; font.pixelSize: Math.round(12 * localScale) anchors.verticalCenter: parent.verticalCenter } Text { text: ScreenRecService.audioLabel - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: ScreenRecService.openStrip === "audio" ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } } Text { - text: "▾"; font.pixelSize: 8 + text: "▾"; font.pixelSize: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.35) anchors.verticalCenter: parent.verticalCenter } @@ -679,17 +680,17 @@ Item { anchors.verticalCenter: parent.verticalCenter height: 1 width: parent.width - - csRow.implicitWidth - 14 - - asRow.implicitWidth - 14 - - recBtnLabel.implicitWidth - 24 + - csRow.implicitWidth - Math.round(14 * localScale) + - asRow.implicitWidth - Math.round(14 * localScale) + - recBtnLabel.implicitWidth - Math.round(24 * localScale) - parent.spacing * 3 } // ── Record button ────────────────────────────────────── Rectangle { anchors.verticalCenter: parent.verticalCenter - width: recBtnLabel.implicitWidth + 24 - height: 22 + width: recBtnLabel.implicitWidth + Math.round(24 * localScale) + height: Math.round(22 * localScale) radius: height / 2 color: recBtnH.hovered ? Qt.rgba(0.9, 0.2, 0.2, 0.85) @@ -697,16 +698,16 @@ Item { Behavior on color { ColorAnimation { duration: 100 } } Row { anchors.centerIn: parent - spacing: 5 + spacing: Math.round(5 * localScale) Rectangle { - width: 7; height: 7; radius: 4 + width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale) color: "#ffffff" anchors.verticalCenter: parent.verticalCenter } Text { id: recBtnLabel text: "Record" - font.pixelSize: 11; font.weight: Font.Medium + font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: "#ffffff" anchors.verticalCenter: parent.verticalCenter } @@ -730,14 +731,14 @@ Item { Row { anchors { left: parent.left - leftMargin: 10 + leftMargin: Math.round(10 * localScale) verticalCenter: parent.verticalCenter } - spacing: 7 + spacing: Math.round(7 * localScale) // Pulsing red dot Rectangle { - width: 8; height: 8; radius: 4 + width: Math.round(8 * localScale); height: Math.round(8 * localScale); radius: Math.round(4 * localScale) color: "#ff4444" anchors.verticalCenter: parent.verticalCenter SequentialAnimation on opacity { @@ -752,7 +753,7 @@ Item { Text { anchors.verticalCenter: parent.verticalCenter text: ScreenRecService.elapsedDisplay - font.pixelSize: 13; font.weight: Font.Bold + font.pixelSize: Math.round(13 * localScale); font.weight: Font.Bold font.family: "JetBrains Mono" color: Theme.text } @@ -762,10 +763,10 @@ Item { Item { id: recCava anchors.centerIn: parent - width: 44 - height: 20 + width: Math.round(44 * localScale) + height: Math.round(20 * localScale) - readonly property real _bw: 4 + readonly property real _bw: Math.round(4 * localScale) readonly property real _sp: Math.max(1, (width - _bw * 12) / 5) readonly property real _maxH: height / 2 @@ -801,7 +802,7 @@ Item { Row { anchors { right: parent.right - rightMargin: 10 + rightMargin: Math.round(10 * localScale) verticalCenter: parent.verticalCenter } spacing: root.fw/2 @@ -809,7 +810,7 @@ Item { // Discard button Rectangle { anchors.verticalCenter: parent.verticalCenter - width: 22; height: 22; radius: 5 + width: Math.round(22 * localScale); height: Math.round(22 * localScale); radius: Math.round(5 * localScale) color: recDiscardH.hovered ? Qt.rgba(1, 1, 1, 0.12) : Qt.rgba(1, 1, 1, 0.05) @@ -817,7 +818,7 @@ Item { Text { anchors.centerIn: parent text: "󰩺" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: recDiscardH.hovered ? Qt.rgba(1, 0.4, 0.4, 1.0) : Qt.rgba(1, 1, 1, 0.4) @@ -830,7 +831,7 @@ Item { // Stop button Rectangle { anchors.verticalCenter: parent.verticalCenter - width: 22; height: 22; radius: 5 + width: Math.round(22 * localScale); height: Math.round(22 * localScale); radius: Math.round(5 * localScale) color: recStopH.hovered ? Qt.rgba(0.9, 0.2, 0.2, 0.55) : Qt.rgba(0.8, 0.1, 0.1, 0.32) @@ -838,7 +839,7 @@ Item { Text { anchors.centerIn: parent text: "⏹" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: "#ff9999" } HoverHandler { id: recStopH } diff --git a/src/modules/Center/DashStats.qml b/src/modules/Center/DashStats.qml index b0ab96a..83f577a 100644 --- a/src/modules/Center/DashStats.qml +++ b/src/modules/Center/DashStats.qml @@ -6,6 +6,8 @@ import "../../services/" Item { id: root + property real localScale: 1.0 + CpuService { id: cpu; active: root.visible } MemService { id: mem; active: root.visible } NetService { id: net; active: root.visible } @@ -23,24 +25,26 @@ Item { Column { anchors { fill: parent - bottomMargin: 8 - topMargin: 8 + bottomMargin: Math.round(8 * localScale) + topMargin: Math.round(8 * localScale) } - spacing: 8 + spacing: Math.round(8 * localScale) // Speedometers Row { id: speedoRow width: parent.width - anchors.topMargin: 4 - height: 160 - spacing: 8 + anchors.topMargin: Math.round(4 * localScale) + height: Math.round(160 * localScale) + spacing: Math.round(8 * localScale) StatCard { + localScale: root.localScale width: (parent.width - parent.spacing * 3) / 4 height: parent.height Speedometer { anchors.centerIn: parent + size: localScale label: "CPU" percent: cpu.usagePercent centerText: cpu.usagePercent + "%" @@ -51,10 +55,12 @@ Item { } StatCard { + localScale: root.localScale width: (parent.width - parent.spacing * 3) / 4 height: parent.height Speedometer { anchors.centerIn: parent + size: localScale label: "RAM" percent: mem.usagePercent centerText: mem.usagePercent + "%" @@ -65,10 +71,12 @@ Item { } StatCard { + localScale: root.localScale width: (parent.width - parent.spacing * 3) / 4 height: parent.height Speedometer { anchors.centerIn: parent + size: localScale label: "iGPU" percent: gpu.igpu.freqPercent centerText: gpu.igpu.freqPercent + "%" @@ -79,10 +87,12 @@ Item { } StatCard { + localScale: root.localScale width: (parent.width - parent.spacing * 3) / 4 height: parent.height Speedometer { anchors.centerIn: parent + size: localScale label: "dGPU" percent: gpu.dgpu.active ? gpu.dgpu.usagePercent : 0 centerText: gpu.dgpu.active ? (gpu.dgpu.usagePercent + "%") : "0%" @@ -95,16 +105,18 @@ Item { Row{ width: parent.width - height: 100 - spacing: 8 + height: Math.round(100 * localScale) + spacing: Math.round(8 * localScale) // Thermal strip StatCard { + localScale: root.localScale width: (parent.width-parent.spacing)/2 height: parent.height - padding: 6 + padding: Math.round(6 * localScale) TempPanel { anchors.fill: parent + localScale: root.localScale service: thermal dgpuActive: gpu.dgpu.active } @@ -112,12 +124,14 @@ Item { // Fan control strip StatCard { + localScale: root.localScale width: (parent.width-parent.spacing)/2 height: parent.height - padding: 6 + padding: Math.round(6 * localScale) FanPanel { anchors.fill: parent + localScale: root.localScale service: fan } } @@ -125,35 +139,41 @@ Item { // Net | Disk | Power Row { width: parent.width - height: parent.height - speedoRow.height - 100 - parent.spacing - spacing: 8 + height: parent.height - speedoRow.height - Math.round(100 * localScale) - parent.spacing + spacing: Math.round(8 * localScale) // Network — narrow, only 3 rows StatCard { + localScale: root.localScale width: Math.round(parent.width * 0.20) height: parent.height NetStatsPanel { anchors.fill: parent + localScale: root.localScale service: net } } // Disks — moderate, horizontal bars stack vertically StatCard { + localScale: root.localScale width: Math.round(parent.width * 0.35) height: parent.height DiskPanel { anchors.fill: parent + localScale: root.localScale service: disk } } // Power — widest, two button rows need space StatCard { + localScale: root.localScale width: parent.width - Math.round(parent.width * 0.20) - Math.round(parent.width * 0.35) - parent.spacing * 2 height: parent.height PowerPanel { anchors.fill: parent + localScale: root.localScale cpuFreqService: cpuFreq envyService: envy } diff --git a/src/modules/Center/DiskPanel.qml b/src/modules/Center/DiskPanel.qml index 561bd9f..68ca6e5 100644 --- a/src/modules/Center/DiskPanel.qml +++ b/src/modules/Center/DiskPanel.qml @@ -6,6 +6,7 @@ import "../../components" Item { id: root + property real localScale: 1.0 required property var service readonly property bool _scrollable: flickable.contentHeight > flickable.height @@ -25,7 +26,7 @@ Item { id: headerLabel anchors.horizontalCenter: parent.horizontalCenter text: "Disks" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) font.weight: Font.Medium color: Qt.rgba(1, 1, 1, 0.4) } @@ -34,11 +35,11 @@ Item { visible: root.service.disks.length > 0 anchors { right: parent.right - rightMargin: 8 + rightMargin: Math.round(8 * localScale) verticalCenter: parent.verticalCenter } text: root.service.disks.length - font.pixelSize: 9 + font.pixelSize: Math.round(9 * localScale) font.weight: Font.Medium color: Qt.rgba(1, 1, 1, 0.25) } @@ -53,7 +54,7 @@ Item { top: flickable.top bottom: flickable.bottom right: parent.right - rightMargin: 3 + rightMargin: Math.round(3 * localScale) } // Manually bind to Flickable size: flickable.visibleArea.heightRatio @@ -61,8 +62,8 @@ Item { onPositionChanged: if (active) flickable.contentY = position * flickable.contentHeight contentItem: Rectangle { - implicitWidth: 2 - implicitHeight: 20 + implicitWidth: Math.round(2 * localScale) + implicitHeight: Math.round(20 * localScale) radius: width / 2 color: Qt.rgba(1, 1, 1, 0.5) opacity: vScroll.active ? 1.0 : 0.0 @@ -72,7 +73,7 @@ Item { } background: Rectangle { - implicitWidth: 2 + implicitWidth: Math.round(2 * localScale) radius: width / 2 color: Qt.rgba(1, 1, 1, 0.08) } @@ -83,13 +84,13 @@ Item { id: flickable anchors { top: headerRow.bottom - topMargin: 6 + topMargin: Math.round(6 * localScale) left: parent.left right: parent.right - rightMargin: root._scrollable ? 12 : 8 + rightMargin: root._scrollable ? Math.round(12 * localScale) : Math.round(8 * localScale) bottom: parent.bottom - bottomMargin: 4 - leftMargin: 8 + bottomMargin: Math.round(4 * localScale) + leftMargin: Math.round(8 * localScale) } clip: true contentHeight: diskColumn.implicitHeight @@ -102,12 +103,13 @@ Item { Column { id: diskColumn width: flickable.width - spacing: 10 + spacing: Math.round(10 * localScale) Repeater { model: root.service.disks delegate: DiskBar { + localScale: root.localScale width: parent.width source: modelData.source mount: modelData.mount diff --git a/src/modules/Center/FanPanel.qml b/src/modules/Center/FanPanel.qml index dc52183..d0337d2 100644 --- a/src/modules/Center/FanPanel.qml +++ b/src/modules/Center/FanPanel.qml @@ -5,17 +5,18 @@ import "../../components" Item { id: root + property real localScale: 1.0 required property var service Column { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - spacing: 10 + spacing: Math.round(10 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: "Fan Control" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) color: Qt.rgba(1, 1, 1, 0.35) } @@ -24,18 +25,21 @@ Item { spacing: parent.parent.width * 0.1 ProfileButton { + localScale: root.localScale icon: "󱗰" label: "Quiet" active: service.mode === "quiet" onClicked: service.setMode("quiet") } ProfileButton { + localScale: root.localScale icon: "󰁪" label: "Auto" active: service.mode === "auto" onClicked: service.setMode("auto") } ProfileButton { + localScale: root.localScale icon: "󱓞" label: "Max" active: service.mode === "max" diff --git a/src/modules/Center/NetStatsPanel.qml b/src/modules/Center/NetStatsPanel.qml index 748cea8..bd64bde 100644 --- a/src/modules/Center/NetStatsPanel.qml +++ b/src/modules/Center/NetStatsPanel.qml @@ -5,32 +5,35 @@ import "../../components" Item { id: root + property real localScale: 1.0 required property var service Column { anchors.centerIn: parent - width: parent.width - 16 - spacing: 10 + width: parent.width - Math.round(16 * localScale) + spacing: Math.round(10 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: "Network" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) font.weight: Font.Medium color: Qt.rgba(1, 1, 1, 0.4) } Column { width: parent.width - spacing: 6 + spacing: Math.round(6 * localScale) StatRow { + localScale: root.localScale width: parent.width label: "Interface" value: root.service.iface } StatRow { + localScale: root.localScale width: parent.width label: "↑ Upload" value: root.service.upSpeed @@ -38,6 +41,7 @@ Item { } StatRow { + localScale: root.localScale width: parent.width label: "↓ Download" value: root.service.downSpeed diff --git a/src/modules/Center/PowerPanel.qml b/src/modules/Center/PowerPanel.qml index a0a76d7..a0372d6 100644 --- a/src/modules/Center/PowerPanel.qml +++ b/src/modules/Center/PowerPanel.qml @@ -5,31 +5,32 @@ import "../../components" Item { id: root + property real localScale: 1.0 required property var cpuFreqService required property var envyService Column { anchors.centerIn: parent - spacing: 16 + spacing: Math.round(16 * localScale) Column { anchors.horizontalCenter: parent.horizontalCenter - spacing: 8 + spacing: Math.round(8 * localScale) // Label + lock icon hinting auto-cpufreq manages this Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 5 + spacing: Math.round(5 * localScale) Text { text: "󰌾" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: Qt.rgba(1, 1, 1, 0.25) anchors.verticalCenter: parent.verticalCenter } Text { text: "Power Profile" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) font.weight: Font.Medium color: Qt.rgba(1, 1, 1, 0.4) anchors.verticalCenter: parent.verticalCenter @@ -38,9 +39,10 @@ Item { Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 6 + spacing: Math.round(6 * localScale) ProfileButton { + localScale: root.localScale label: root.cpuFreqService.activeProfile === "performance" ? "Performance" : "Power Saver" active: true enabled: true @@ -50,34 +52,36 @@ Item { Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: 200 + width: Math.round(200 * localScale) height: 1 color: Qt.rgba(1, 1, 1, 0.07) } Column { anchors.horizontalCenter: parent.horizontalCenter - spacing: 8 + spacing: Math.round(8 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: "GPU Mode" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) font.weight: Font.Medium color: Qt.rgba(1, 1, 1, 0.4) } Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 6 + spacing: Math.round(6 * localScale) ProfileButton { + localScale: root.localScale label: "Integrated" active: root.envyService.currentMode === "integrated" enabled: !root.envyService.busy onClicked: root.envyService.switchMode("integrated") } ProfileButton { + localScale: root.localScale label: "Hybrid" active: root.envyService.currentMode === "hybrid" enabled: !root.envyService.busy @@ -88,7 +92,7 @@ Item { Text { anchors.horizontalCenter: parent.horizontalCenter text: "GPU mode switch requires a reboot" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(1, 1, 1, 0.25) } } diff --git a/src/modules/Center/TempPanel.qml b/src/modules/Center/TempPanel.qml index e6250f9..6269096 100644 --- a/src/modules/Center/TempPanel.qml +++ b/src/modules/Center/TempPanel.qml @@ -5,6 +5,7 @@ import "../../components" Item { id: root + property real localScale: 1.0 required property var service property bool dgpuActive: false property string fanMode: "quiet" @@ -17,7 +18,7 @@ Item { return Theme.active } - readonly property real s: 0.60 + readonly property real s: 0.60 * localScale // ── Speedometers — anchored left ────────────────────────────────────────── Row { diff --git a/src/modules/Left/LayoutDisplayer.qml b/src/modules/Left/LayoutDisplayer.qml index 2fc1345..8536265 100644 --- a/src/modules/Left/LayoutDisplayer.qml +++ b/src/modules/Left/LayoutDisplayer.qml @@ -24,8 +24,10 @@ import "../../" Item { id: root - implicitWidth: 26 - implicitHeight: 26 + property real localScale: 1.0 + + implicitWidth: Math.round(26 * localScale) + implicitHeight: Math.round(26 * localScale) // ── State ──────────────────────────────────────────────────────────────── @@ -130,7 +132,7 @@ Item { Rectangle { id: bg anchors.fill: parent - radius: 6 + radius: Math.round(6 * localScale) color: mouseArea.containsMouse ? Qt.rgba(1, 1, 1, 0.08) : "transparent" Behavior on color { @@ -157,7 +159,7 @@ Item { anchors.centerIn: parent text: root.currentLayout !== "" ? layoutSymbol(root.currentLayout) : "…" font.family: "JetBrainsMono Nerd Font" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) color: "#cdd6f4" // Brief scale-pop on symbol change diff --git a/src/modules/Left/LeftContent.qml b/src/modules/Left/LeftContent.qml index ba45b72..733943c 100644 --- a/src/modules/Left/LeftContent.qml +++ b/src/modules/Left/LeftContent.qml @@ -5,16 +5,27 @@ import "../../windows" import "../../" Row { - spacing: 5 + property real localScale: 1.0 + height: parent.height + spacing: Math.round(5 * localScale) // Note: Do NOT add anchors.centerIn: parent here. TopBar handles that. // 1. Arch Icon (Power Menu Trigger) - ControlPanel{} + ControlPanel{ + localScale: parent.localScale + anchors.verticalCenter: parent.verticalCenter + } // 2. Workspaces - Workspaces {} + Workspaces { + localScale: parent.localScale + anchors.verticalCenter: parent.verticalCenter + } //3. LayoutDisplay - LayoutDisplayer {} + LayoutDisplayer { + localScale: parent.localScale + anchors.verticalCenter: parent.verticalCenter + } } diff --git a/src/modules/Left/Workspaces.qml b/src/modules/Left/Workspaces.qml index f7da5e8..c403884 100644 --- a/src/modules/Left/Workspaces.qml +++ b/src/modules/Left/Workspaces.qml @@ -6,6 +6,7 @@ import "../../" Rectangle { id: root + property real localScale: 1.0 // ── Config Provider ──────────────────────────────────────────────── property string configProvider: ShellState.configProvider @@ -29,11 +30,11 @@ Rectangle { // --- 1. Capsule Container --- color: Theme.wsBackground - radius: Theme.wsRadius + radius: Math.round(Theme.wsRadius * localScale) // Auto-size - width: workspaceRow.width + (Theme.wsPadding * 2) - height: Theme.wsDotSize + (Theme.wsPadding * 2) + width: workspaceRow.width + Math.round(Theme.wsPadding * 2 * localScale) + height: Math.round(Theme.wsDotSize * localScale) + Math.round(Theme.wsPadding * 2 * localScale) // --- 2. LOGIC: Raw Event Listener --- property bool isScratchpad: false @@ -102,7 +103,7 @@ Rectangle { Row { id: workspaceRow anchors.centerIn: parent - spacing: Theme.wsSpacing + spacing: Math.round(Theme.wsSpacing * localScale) // Logic: Fade out dots when Scratchpad is active opacity: root.isScratchpad ? 0 : 1 @@ -123,9 +124,9 @@ Rectangle { property bool isUrgent: ws !== undefined && ws.urgent - height: Theme.wsDotSize + height: Math.round(Theme.wsDotSize * localScale) radius: height / 2 - width: isActive ? Theme.wsActiveWidth : Theme.wsDotSize + width: isActive ? Math.round(Theme.wsActiveWidth * localScale) : Math.round(Theme.wsDotSize * localScale) color: { if (isActive) return Theme.wsActive @@ -191,7 +192,7 @@ Rectangle { anchors.centerIn: parent text: "" color: "#FFFFFF" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) } MouseArea { diff --git a/src/modules/Right/Audio.qml b/src/modules/Right/Audio.qml index 00f3438..23a1efc 100644 --- a/src/modules/Right/Audio.qml +++ b/src/modules/Right/Audio.qml @@ -7,8 +7,9 @@ Item { id: root property bool showPercentage: false + property real localScale: 1.0 - implicitWidth: row.implicitWidth + 6 + implicitWidth: row.implicitWidth + Math.round(6 * localScale) implicitHeight: row.implicitHeight readonly property var sink: Pipewire.defaultAudioSink @@ -34,13 +35,13 @@ Item { Row { id: row anchors.centerIn: parent - spacing: 3 + spacing: Math.round(3 * localScale) Text { id: iconText text: root.icon color: hov.hovered ? Theme.active : Theme.text - font.pixelSize: 18 + font.pixelSize: Math.round(18 * localScale) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 120 } } } @@ -48,7 +49,7 @@ Item { Item { id: pctWrapper property bool show: root.showPercentage || hov.hovered - implicitWidth: show ? pctText.implicitWidth + 2 : 0 + implicitWidth: show ? pctText.implicitWidth + Math.round(2 * localScale) : 0 implicitHeight: pctText.implicitHeight clip: true anchors.verticalCenter: parent.verticalCenter @@ -58,7 +59,7 @@ Item { id: pctText text: root.pct + "%" color: hov.hovered ? Theme.active : Theme.text - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 120 } } } diff --git a/src/modules/Right/Battery.qml b/src/modules/Right/Battery.qml index 11bb3b8..30552b0 100644 --- a/src/modules/Right/Battery.qml +++ b/src/modules/Right/Battery.qml @@ -3,6 +3,7 @@ import "../../services" import "../../" Item { + property real localScale: 1.0 // Set to true to always show percentage beside the icon. // When false (default), percentage only shows on hover. property bool showPercentage: false @@ -14,6 +15,7 @@ Item { BatteryStatus { id: status + localScale: parent.localScale anchors.centerIn: parent showPercentage: parent.showPercentage } diff --git a/src/modules/Right/Clock.qml b/src/modules/Right/Clock.qml index f18cbe3..e5616be 100644 --- a/src/modules/Right/Clock.qml +++ b/src/modules/Right/Clock.qml @@ -3,12 +3,14 @@ import "../../" Text { id: clock + property real localScale: 1.0 + text: Qt.formatDateTime(new Date(), "hh:mm") color: clockHov.hovered ? Theme.active : Theme.text Behavior on color { ColorAnimation { duration: 120 } } font.bold: true anchors.verticalCenter: parent.verticalCenter - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) property int formatMode: 0 diff --git a/src/modules/Right/Network.qml b/src/modules/Right/Network.qml index 6a6bc0c..7c797be 100644 --- a/src/modules/Right/Network.qml +++ b/src/modules/Right/Network.qml @@ -6,7 +6,9 @@ import "../../" Item { id: root - implicitWidth: row.implicitWidth + 6 + property real localScale: 1.0 + + implicitWidth: row.implicitWidth + Math.round(6 * localScale) implicitHeight: row.implicitHeight property int _signal: 0 @@ -86,14 +88,14 @@ Item { Row { id: row anchors.centerIn: parent - spacing: 4 + spacing: Math.round(4 * localScale) // WiFi/ethernet icon — opens to wifi tab Text { id: netIcon text: root._netIcon color: root._netColor - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 200 } } MouseArea { @@ -111,7 +113,7 @@ Item { Text { visible: ShellState.vpnActive || ShellState.vpnConnecting text: ShellState.vpnConnecting ? "󱦚" : "󰦝" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) anchors.verticalCenter: parent.verticalCenter opacity: root._vpnOpacity color: ShellState.vpnActive ? Theme.active : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.70) @@ -132,7 +134,7 @@ Item { Text { visible: ShellState.btPowered text: ShellState.btConnected ? "󰂱" : "󰂯" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) anchors.verticalCenter: parent.verticalCenter color: ShellState.btConnected ? (hov.hovered ? Theme.active : Theme.text) : Qt.rgba(1,1,1,0.32) Behavior on color { ColorAnimation { duration: 200 } } @@ -151,7 +153,7 @@ Item { Text { visible: ShellState.hotspot text: "󰀂" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) anchors.verticalCenter: parent.verticalCenter color: Theme.active Behavior on color { ColorAnimation { duration: 200 } } diff --git a/src/modules/Right/Notifications.qml b/src/modules/Right/Notifications.qml index 31392b2..5a5157f 100644 --- a/src/modules/Right/Notifications.qml +++ b/src/modules/Right/Notifications.qml @@ -6,6 +6,7 @@ import "../../" import "../../services/" IconBtn { + property real localScale: 1.0 text: ShellState.dnd ? "󰂛" : NotificationService.count > 0 ? "󰂚" : "󰂜" diff --git a/src/modules/Right/RightContent.qml b/src/modules/Right/RightContent.qml index ed0330f..4ebda25 100644 --- a/src/modules/Right/RightContent.qml +++ b/src/modules/Right/RightContent.qml @@ -6,6 +6,8 @@ import "../../" Item { id: root + property real localScale: 1.0 + height: parent.height // The TopBar State handles expanding the notch for notifications/network/toasts implicitWidth: contentRow.implicitWidth @@ -13,7 +15,7 @@ Item { //Behavior on implicitWidth { // NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } //} - implicitHeight: contentRow.implicitHeight + implicitHeight: parent.height // ── Normal content — fades out when any right popup opens ───────────────── Row { @@ -21,18 +23,37 @@ Item { //anchors.centerIn: parent anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - spacing: 6 + height: parent.height + spacing: Math.round(6 * localScale) opacity: (Popups.notificationsOpen || Popups.networkOpen) ? 0 : 1 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: 150 } } - Network{} - Audio{} - Battery{} - Clock{} - SysTray{} - Notifications{} + Network{ + localScale: root.localScale + anchors.verticalCenter: parent.verticalCenter + } + Audio{ + localScale: root.localScale + anchors.verticalCenter: parent.verticalCenter + } + Battery{ + localScale: root.localScale + anchors.verticalCenter: parent.verticalCenter + } + Clock{ + localScale: root.localScale + anchors.verticalCenter: parent.verticalCenter + } + SysTray{ + localScale: root.localScale + anchors.verticalCenter: parent.verticalCenter + } + Notifications{ + localScale: root.localScale + anchors.verticalCenter: parent.verticalCenter + } } // ── Open indicator — fades in when any right popup opens ────────────────── @@ -40,7 +61,7 @@ Item { anchors.centerIn: parent text: "▾" color: Theme.active - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) opacity: (Popups.notificationsOpen || Popups.networkOpen) ? 1 : 0 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: 150 } } diff --git a/src/modules/Right/SysTray.qml b/src/modules/Right/SysTray.qml index 774ead4..3ccbca6 100644 --- a/src/modules/Right/SysTray.qml +++ b/src/modules/Right/SysTray.qml @@ -8,6 +8,7 @@ import "../../" RowLayout { id: root + property real localScale: 1.0 RowLayout { id: trayRow @@ -29,14 +30,14 @@ RowLayout { model: SystemTray.items delegate: Rectangle { // UX: Larger 28x28 hit-box makes it easier to click than a 16x16 icon - width: 26 - height: 26 - radius: 6 + width: Math.round(26 * localScale) + height: Math.round(26 * localScale) + radius: Math.round(6 * localScale) color: trayMouse.containsMouse ? Qt.rgba(1, 1, 1, 0.1) : "transparent" // Subtle hover effect Image { - width: 16 - height: 16 + width: Math.round(16 * localScale) + height: Math.round(16 * localScale) anchors.centerIn: parent source: modelData.icon smooth: true @@ -66,6 +67,7 @@ RowLayout { // Tray Toggle Button IconBtn { + localScale: root.localScale Layout.alignment: Qt.AlignVCenter text: trayRow.isOpen ? "" : "" onClicked: trayRow.isOpen = !trayRow.isOpen diff --git a/src/popups/ArchMenu.qml b/src/popups/ArchMenu.qml index b125384..4180bd3 100644 --- a/src/popups/ArchMenu.qml +++ b/src/popups/ArchMenu.qml @@ -11,22 +11,24 @@ PopupWindow { required property var anchorWindow - readonly property int fw: Theme.cornerRadius - readonly property int fh: Theme.cornerRadius + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int fw: Math.round(Theme.cornerRadius * root.localScale) + readonly property int fh: Math.round(Theme.cornerRadius * root.localScale) readonly property var pageHeights: ({ - "power": 270, - "performance": 190, - "stats": 250 + "power": Math.round(270 * root.localScale), + "performance": Math.round(190 * root.localScale), + "stats": Math.round(250 * root.localScale) }) readonly property var pageWidths: ({ - "power": 220, - "performance": 260, - "stats": 390 + "power": Math.round(220 * root.localScale), + "performance": Math.round(260 * root.localScale), + "stats": Math.round(390 * root.localScale) }) - readonly property int contentWidth: pageWidths[page] ?? 220 - readonly property int contentHeight: pageHeights[page] ?? 220 + readonly property int contentWidth: pageWidths[page] ?? Math.round(220 * root.localScale) + readonly property int contentHeight: pageHeights[page] ?? Math.round(220 * root.localScale) property string page: "power" @@ -34,8 +36,8 @@ PopupWindow { visible: slide.windowVisible mask: Region { item: maskProxy } - implicitWidth: (pageWidths["stats"] ?? 220) + fw - implicitHeight: (pageHeights["stats"] ?? 220) + fh * 2 + implicitWidth: (pageWidths["stats"] ?? Math.round(220 * root.localScale)) + fw + implicitHeight: (pageHeights["stats"] ?? Math.round(220 * root.localScale)) + fh * 2 anchor.window: anchorWindow anchor.gravity: Edges.Right @@ -43,9 +45,9 @@ PopupWindow { 0, anchorWindow.height / 2, anchorWindow.width, - implicitHeight + anchorWindow.height ) - + Item { id: maskProxy x: 0 @@ -53,7 +55,7 @@ PopupWindow { width: sizer.width height: sizer.height } - + PopupSlide { id: slide anchors.fill: parent @@ -80,7 +82,7 @@ PopupWindow { anchors.fill: parent attachedEdge: "left" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } @@ -88,10 +90,10 @@ PopupWindow { Item { anchors { fill: parent - leftMargin: root.fw - 4 - rightMargin: 8 - topMargin: root.fh + 6 - bottomMargin: root.fh + 6 + leftMargin: root.fw - Math.round(4 * root.localScale) + rightMargin: Math.round(8 * root.localScale) + topMargin: root.fh + Math.round(6 * root.localScale) + bottomMargin: root.fh + Math.round(6 * root.localScale) } //── Page content ────────────────────────────────────────── Item { @@ -104,6 +106,7 @@ PopupWindow { visible: root.page === "power" PowerMenu { + localScale: root.localScale width: parent.width } } @@ -111,4 +114,4 @@ PopupWindow { } } } -} \ No newline at end of file +} diff --git a/src/popups/AudioPopup.qml b/src/popups/AudioPopup.qml index c647370..28e39bf 100644 --- a/src/popups/AudioPopup.qml +++ b/src/popups/AudioPopup.qml @@ -11,18 +11,20 @@ PopupWindow { required property var anchorWindow - readonly property int fw: Theme.cornerRadius - readonly property int fh: Theme.cornerRadius + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int fw: Math.round(Theme.cornerRadius * root.localScale) + readonly property int fh: Math.round(Theme.cornerRadius * root.localScale) readonly property var pageWidths: ({ - "output": 200, - "input": 200, - "mixer": 300 + "output": Math.round(200 * root.localScale), + "input": Math.round(200 * root.localScale), + "mixer": Math.round(300 * root.localScale) }) - readonly property int popupHeight: 340 + readonly property int popupHeight: Math.round(340 * root.localScale) - readonly property int maxWidth: 300 + readonly property int maxWidth: Math.round(300 * root.localScale) color: "transparent" visible: slide.windowVisible @@ -30,8 +32,8 @@ PopupWindow { anchor.window: anchorWindow anchor.rect: Qt.rect( - Theme.cornerRadius, - anchorWindow.height / 2, + Math.round(Theme.cornerRadius * root.localScale), + anchorWindow.height/2, 0, popupHeight ) @@ -91,19 +93,20 @@ PopupWindow { anchors.fill: parent attachedEdge: "right" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } AudioControl { id: audioControl + localScale: root.localScale anchors { fill: parent - topMargin: root.fh + 6 - bottomMargin: root.fh + 6 - leftMargin: 10 - rightMargin: root.fw - 4 + topMargin: root.fh + Math.round(6 * root.localScale) + bottomMargin: root.fh + Math.round(6 * root.localScale) + leftMargin: Math.round(10 * root.localScale) + rightMargin: root.fw - Math.round(4 * root.localScale) } } } diff --git a/src/popups/BluetoothTab.qml b/src/popups/BluetoothTab.qml index e17706c..7b47a50 100644 --- a/src/popups/BluetoothTab.qml +++ b/src/popups/BluetoothTab.qml @@ -11,6 +11,7 @@ import "../components" Item { id: root + property real localScale: 1.0 property var _allDevices: [] property bool _scanning: false property bool _btPowered: true @@ -256,7 +257,7 @@ Item { component ScanRings: Item { id: ringsRoot property string centerGlyph: "󰂯" - property int glyphSize: 18 + property int glyphSize: Math.round(18 * localScale) Repeater { model: 4 delegate: Rectangle { @@ -265,7 +266,7 @@ Item { width: ringsRoot.width; height: ringsRoot.width; radius: ringsRoot.width / 2 color: "transparent" border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.80) - border.width: 1.5; opacity: 0; scale: 0.08 + border.width: Math.max(1, Math.round(1.5 * localScale)); opacity: 0; scale: 0.08 SequentialAnimation { running: root._scanning; loops: Animation.Infinite PauseAnimation { duration: index * 650 } @@ -303,14 +304,14 @@ Item { height: baseRow.height + expandArea.height Rectangle { - anchors.fill: parent; radius: Theme.cornerRadius + anchors.fill: parent; radius: Math.round(Theme.cornerRadius * localScale) color: dRow.isConnected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.07) : rowHov.hovered && !dRow.isPaired ? Qt.rgba(1,1,1,0.04) : "transparent" border.color: dRow.isConnected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : dRow.isRemovePending ? Qt.rgba(248/255,113/255,113/255,0.22) : Qt.rgba(1,1,1,0.06) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 130 } } Behavior on border.color { ColorAnimation { duration: 130 } } } @@ -318,41 +319,41 @@ Item { Item { id: baseRow anchors { top: parent.top; left: parent.left; right: parent.right } - height: 50 + height: Math.round(50 * localScale) Text { - anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter } - text: root._glyph(dRow.device.iconType); font.pixelSize: 18 + anchors { left: parent.left; leftMargin: Math.round(12 * localScale); verticalCenter: parent.verticalCenter } + text: root._glyph(dRow.device.iconType); font.pixelSize: Math.round(18 * localScale) color: dRow.isConnected ? Theme.active : (dRow.inAction || dRow.inRemove) ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) : Qt.rgba(1,1,1,0.32) Behavior on color { ColorAnimation { duration: 150 } } } Column { - anchors { left: parent.left; leftMargin: 44; verticalCenter: parent.verticalCenter } - spacing: 3 + anchors { left: parent.left; leftMargin: Math.round(44 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(3 * localScale) Text { - text: dRow.device.name; font.pixelSize: 13 + text: dRow.device.name; font.pixelSize: Math.round(13 * localScale) font.weight: dRow.isConnected ? Font.Medium : Font.Normal color: dRow.isConnected ? Theme.text : Qt.rgba(1,1,1,0.68) - width: 160; elide: Text.ElideRight + width: Math.round(160 * localScale); elide: Text.ElideRight } Text { visible: dRow.isConnected || dRow.inAction || dRow.inRemove text: dRow.inRemove ? "Removing…" : dRow.inAction ? "Working…" : "Connected" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: (dRow.inAction || dRow.inRemove) ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) : Theme.active } } Row { - anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter } - spacing: 6 + anchors { right: parent.right; rightMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(6 * localScale) // Spinner Text { visible: dRow.inAction || dRow.inRemove - text: "○"; font.pixelSize: 15; color: Theme.active + text: "○"; font.pixelSize: Math.round(15 * localScale); color: Theme.active anchors.verticalCenter: parent.verticalCenter SequentialAnimation on opacity { running: dRow.inAction || dRow.inRemove; loops: Animation.Infinite @@ -365,15 +366,15 @@ Item { Rectangle { visible: dRow.isPaired && !dRow.inAction && !dRow.inRemove anchors.verticalCenter: parent.verticalCenter - width: togContent.implicitWidth + 20; height: 28; radius: 14 + width: togContent.implicitWidth + Math.round(20 * localScale); height: Math.round(28 * localScale); radius: Math.round(14 * localScale) color: dRow.isConnected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : togH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04) border.color: dRow.isConnected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.36) : Qt.rgba(1,1,1,0.11) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } Row { - id: togContent; anchors.centerIn: parent; spacing: 7 - Rectangle { width: 7; height: 7; radius: 4; anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: 150 } } } - Text { text: dRow.isConnected ? "Connected" : "Connect"; font.pixelSize: 11; font.weight: Font.Medium; anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.48); Behavior on color { ColorAnimation { duration: 120 } } } + id: togContent; anchors.centerIn: parent; spacing: Math.round(7 * localScale) + Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: 150 } } } + Text { text: dRow.isConnected ? "Connected" : "Connect"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; anchors.verticalCenter: parent.verticalCenter; color: dRow.isConnected ? Theme.active : Qt.rgba(1,1,1,0.48); Behavior on color { ColorAnimation { duration: 120 } } } } HoverHandler { id: togH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: dRow.isConnected ? root._disconnect(dRow.device.mac) : root._connect(dRow.device.mac) } @@ -382,9 +383,9 @@ Item { // Paired: remove button Item { visible: dRow.isPaired && !dRow.inAction && !dRow.inRemove - width: 28; height: 28; anchors.verticalCenter: parent.verticalCenter - Rectangle { anchors.fill: parent; radius: 7; color: rmH.hovered ? Qt.rgba(248/255,113/255,113/255,0.20) : dRow.isRemovePending ? Qt.rgba(248/255,113/255,113/255,0.12) : "transparent"; Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: 13; color: (rmH.hovered || dRow.isRemovePending) ? "#f87171" : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: 100 } } } + width: Math.round(28 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent.verticalCenter + Rectangle { anchors.fill: parent; radius: Math.round(7 * localScale); color: rmH.hovered ? Qt.rgba(248/255,113/255,113/255,0.20) : dRow.isRemovePending ? Qt.rgba(248/255,113/255,113/255,0.12) : "transparent"; Behavior on color { ColorAnimation { duration: 100 } } } + Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: Math.round(13 * localScale); color: (rmH.hovered || dRow.isRemovePending) ? "#f87171" : Qt.rgba(1,1,1,0.25); Behavior on color { ColorAnimation { duration: 100 } } } HoverHandler { id: rmH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { root._pairingMac = ""; root._removeMac = dRow.isRemovePending ? "" : dRow.device.mac } } } @@ -393,22 +394,22 @@ Item { Row { visible: !dRow.isPaired && !dRow.inAction anchors.verticalCenter: parent.verticalCenter - spacing: 6 + spacing: Math.round(6 * localScale) Rectangle { - width: pairLbl.implicitWidth + 20; height: 28; radius: 8 + width: pairLbl.implicitWidth + Math.round(20 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: pairH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.09) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 100 } } - Text { id: pairLbl; anchors.centerIn: parent; text: "Pair"; font.pixelSize: 11; font.weight: Font.Medium; color: Theme.active } + Text { id: pairLbl; anchors.centerIn: parent; text: "Pair"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: pairH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { root._removeMac = ""; root._pairingMac = ""; root._pair(dRow.device.mac, "") } } } Item { - width: 24; height: 28; anchors.verticalCenter: parent?.verticalCenter - Rectangle { anchors.fill: parent; radius: 6; color: pinH.hovered ? Qt.rgba(1,1,1,0.10) : dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : Qt.rgba(1,1,1,0.04); border.color: dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(1,1,1,0.09); border.width: 1; Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰌾"; font.pixelSize: 12; color: dRow.isPairingOpen ? Theme.active : pinH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.28); Behavior on color { ColorAnimation { duration: 100 } } } + width: Math.round(24 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent?.verticalCenter + Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: pinH.hovered ? Qt.rgba(1,1,1,0.10) : dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : Qt.rgba(1,1,1,0.04); border.color: dRow.isPairingOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(1,1,1,0.09); border.width: Math.max(1, Math.round(1 * localScale)); Behavior on color { ColorAnimation { duration: 100 } } } + Text { anchors.centerIn: parent; text: "󰌾"; font.pixelSize: Math.round(12 * localScale); color: dRow.isPairingOpen ? Theme.active : pinH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.28); Behavior on color { ColorAnimation { duration: 100 } } } HoverHandler { id: pinH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -429,29 +430,29 @@ Item { id: expandArea anchors { top: baseRow.bottom; left: parent.left; right: parent.right } clip: true - height: dRow.isRemovePending ? removeRow.implicitHeight + 16 : dRow.isPairingOpen ? pinRow.implicitHeight + 16 : 0 + height: dRow.isRemovePending ? removeRow.implicitHeight + Math.round(16 * localScale) : dRow.isPairingOpen ? pinRow.implicitHeight + Math.round(16 * localScale) : 0 Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } // Remove confirmation Item { id: removeRow - anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 8 } - implicitHeight: 32 + anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(8 * localScale) } + implicitHeight: Math.round(32 * localScale) opacity: dRow.isRemovePending ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 140 } } Rectangle { - anchors { fill: parent; leftMargin: 8; rightMargin: 8 } - radius: 8; color: Qt.rgba(248/255,113/255,113/255,0.06); border.color: Qt.rgba(248/255,113/255,113/255,0.22); border.width: 1 + anchors { fill: parent; leftMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } + radius: Math.round(8 * localScale); color: Qt.rgba(248/255,113/255,113/255,0.06); border.color: Qt.rgba(248/255,113/255,113/255,0.22); border.width: Math.max(1, Math.round(1 * localScale)) Row { - anchors.centerIn: parent; spacing: 12 - Text { anchors.verticalCenter: parent.verticalCenter; text: "Remove this device?"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.5) } - Rectangle { width: 58; height: 24; radius: 6; color: cxH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04); Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: 10; color: Qt.rgba(1,1,1,0.42) } + anchors.centerIn: parent; spacing: Math.round(12 * localScale) + Text { anchors.verticalCenter: parent.verticalCenter; text: "Remove this device?"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.5) } + Rectangle { width: Math.round(58 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: cxH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04); Behavior on color { ColorAnimation { duration: 80 } } + Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.42) } HoverHandler { id: cxH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._removeMac = "" } } - Rectangle { width: 64; height: 24; radius: 6; color: rxH.hovered ? Qt.rgba(248/255,113/255,113/255,0.40) : Qt.rgba(248/255,113/255,113/255,0.18); Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Remove"; font.pixelSize: 10; font.weight: Font.Medium; color: "#f87171" } + Rectangle { width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: rxH.hovered ? Qt.rgba(248/255,113/255,113/255,0.40) : Qt.rgba(248/255,113/255,113/255,0.18); Behavior on color { ColorAnimation { duration: 80 } } + Text { anchors.centerIn: parent; text: "Remove"; font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium; color: "#f87171" } HoverHandler { id: rxH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._remove(dRow.device.mac) } } @@ -462,40 +463,40 @@ Item { // PIN row Item { id: pinRow - anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 8 } + anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(8 * localScale) } implicitHeight: pinCol.implicitHeight opacity: dRow.isPairingOpen ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 140 } } Column { id: pinCol - anchors { left: parent.left; right: parent.right; leftMargin: 8; rightMargin: 8 } - spacing: 6 - Text { width: parent.width; text: "Legacy PIN pairing — enter the PIN shown on your device"; font.pixelSize: 10; color: Qt.rgba(1,1,1,0.30); wrapMode: Text.WordWrap } + anchors { left: parent.left; right: parent.right; leftMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } + spacing: Math.round(6 * localScale) + Text { width: parent.width; text: "Legacy PIN pairing — enter the PIN shown on your device"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.30); wrapMode: Text.WordWrap } Row { - width: parent.width; spacing: 8 + width: parent.width; spacing: Math.round(8 * localScale) Rectangle { - width: parent.width - pairConfBtn.width - parent.spacing; height: 32; radius: 8 + width: parent.width - pairConfBtn.width - parent.spacing; height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.06) border.color: pinInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) : Qt.rgba(1,1,1,0.12) - border.width: 1; Behavior on border.color { ColorAnimation { duration: 120 } } - Text { anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } - text: "PIN (optional)…"; font.pixelSize: 12; color: Qt.rgba(1,1,1,0.22); visible: pinInput.text === "" } + border.width: Math.max(1, Math.round(1 * localScale)); Behavior on border.color { ColorAnimation { duration: 120 } } + Text { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + text: "PIN (optional)…"; font.pixelSize: Math.round(12 * localScale); color: Qt.rgba(1,1,1,0.22); visible: pinInput.text === "" } TextInput { id: pinInput - anchors { fill: parent; leftMargin: 10; rightMargin: 10 } + anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } verticalAlignment: TextInput.AlignVCenter; color: Theme.text - font.pixelSize: 12; font.family: "JetBrains Mono" + font.pixelSize: Math.round(12 * localScale); font.family: "JetBrains Mono" inputMethodHints: Qt.ImhDigitsOnly; maximumLength: 8 selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); clip: true Keys.onReturnPressed: root._pair(dRow.device.mac, text) } } Rectangle { - id: pairConfBtn; width: 64; height: 32; radius: 8 + id: pairConfBtn; width: Math.round(64 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: pcH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.42); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.42); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "Pair"; font.pixelSize: 11; font.weight: Font.Medium; color: Theme.active } + Text { anchors.centerIn: parent; text: "Pair"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: pcH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._pair(dRow.device.mac, pinInput.text) } } @@ -514,50 +515,50 @@ Item { // Header Item { - width: parent.width; height: 40 + width: parent.width; height: Math.round(40 * localScale) - Text { anchors { left: parent.left; leftMargin: 2; verticalCenter: parent.verticalCenter } - text: "Bluetooth"; font.pixelSize: 15; font.weight: Font.Bold; color: Theme.text } + Text { anchors { left: parent.left; leftMargin: Math.round(2 * localScale); verticalCenter: parent.verticalCenter } + text: "Bluetooth"; font.pixelSize: Math.round(15 * localScale); font.weight: Font.Bold; color: Theme.text } Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - spacing: 8 + spacing: Math.round(8 * localScale) // Power toggle Rectangle { - width: 32; height: 32; radius: 8 + width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: pwrH.hovered ? (root._btPowered ? Qt.rgba(248/255,113/255,113/255,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18)) : Qt.rgba(1,1,1,0.04) - border.color: root._btPowered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30); border.width: 1 + border.color: root._btPowered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } Behavior on border.color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: 14; color: root._btPowered ? (pwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: 120 } } } + Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: Math.round(14 * localScale); color: root._btPowered ? (pwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: 120 } } } HoverHandler { id: pwrH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._setPower(!root._btPowered) } } // Settings — blueman-manager Rectangle { - width: 32; height: 32; radius: 8 + width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: settH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.03) - border.color: Qt.rgba(1,1,1,0.10); border.width: 1 + border.color: Qt.rgba(1,1,1,0.10); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: 14; color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: 100 } } } + Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: Math.round(14 * localScale); color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: 100 } } } HoverHandler { id: settH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { bluemanProc.running = false; bluemanProc.running = true } } } // Scan / Stop pill — disabled when adapter is off Rectangle { - width: scanRow.implicitWidth + 20; height: 30; radius: 15 + width: scanRow.implicitWidth + Math.round(20 * localScale); height: Math.round(30 * localScale); radius: Math.round(15 * localScale) opacity: root._btPowered ? 1.0 : 0.35 Behavior on opacity { NumberAnimation { duration: 200 } } color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : scanH.hovered && root._btPowered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : Qt.rgba(1,1,1,0.05) - border.color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.48) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28); border.width: 1 + border.color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.48) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 130 } } Row { - id: scanRow; anchors.centerIn: parent; spacing: 7 + id: scanRow; anchors.centerIn: parent; spacing: Math.round(7 * localScale) Rectangle { - width: 7; height: 7; radius: 4; anchors.verticalCenter: parent.verticalCenter + width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter color: root._scanning ? Theme.active : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) Behavior on color { ColorAnimation { duration: 120 } } SequentialAnimation on opacity { @@ -565,7 +566,7 @@ Item { NumberAnimation { to: 1.0; duration: 450 } } } - Text { anchors.verticalCenter: parent.verticalCenter; text: root._scanning ? "Stop" : "Scan"; font.pixelSize: 12; font.weight: Font.Medium; color: root._scanning ? Theme.active : Qt.rgba(1,1,1,0.6); Behavior on color { ColorAnimation { duration: 130 } } } + Text { anchors.verticalCenter: parent.verticalCenter; text: root._scanning ? "Stop" : "Scan"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: root._scanning ? Theme.active : Qt.rgba(1,1,1,0.6); Behavior on color { ColorAnimation { duration: 130 } } } } HoverHandler { id: scanH; cursorShape: root._btPowered ? Qt.PointingHandCursor : Qt.ArrowCursor } MouseArea { anchors.fill: parent; onClicked: if (root._btPowered) root._startScan() } @@ -574,82 +575,82 @@ Item { } Rectangle { width: parent.width; height: 1; color: Qt.rgba(1,1,1,0.07) } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } // Scan animation strip Item { - width: parent.width; height: root._scanning ? 90 : 0; clip: true + width: parent.width; height: root._scanning ? Math.round(90 * localScale) : 0; clip: true Behavior on height { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } - ScanRings { anchors.centerIn: parent; width: 52; height: 52; centerGlyph: "󰂯"; glyphSize: 14 } - Text { anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 6 } - text: "Scanning for devices…"; font.pixelSize: 10; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.50) } + ScanRings { anchors.centerIn: parent; width: Math.round(52 * localScale); height: Math.round(52 * localScale); centerGlyph: "󰂯"; glyphSize: Math.round(14 * localScale) } + Text { anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: Math.round(6 * localScale) } + text: "Scanning for devices…"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.50) } } Flickable { width: parent.width - height: parent.height - 49 - (root._scanning ? 90 : 0) + height: parent.height - Math.round(49 * localScale) - (root._scanning ? Math.round(90 * localScale) : 0) contentWidth: width; contentHeight: devCol.height clip: true; boundsBehavior: Flickable.StopAtBounds Behavior on height { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } } Column { - id: devCol; width: parent.width; height: implicitHeight; spacing: 4 + id: devCol; width: parent.width; height: implicitHeight; spacing: Math.round(4 * localScale) - Item { width: parent.width; height: visible ? pLbl.implicitHeight + 4 : 0; visible: root._paired.length > 0 - Text { id: pLbl; text: "PAIRED"; font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } + Item { width: parent.width; height: visible ? pLbl.implicitHeight + Math.round(4 * localScale) : 0; visible: root._paired.length > 0 + Text { id: pLbl; text: "PAIRED"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } Repeater { model: root._paired - delegate: DeviceRow { required property var modelData; width: devCol.width - 2; x: 1; device: modelData; isPaired: true } + delegate: DeviceRow { required property var modelData; width: devCol.width - Math.round(2 * localScale); x: Math.round(1 * localScale); device: modelData; isPaired: true } } - Item { width: parent.width; height: 10; visible: root._paired.length > 0 && root._available.length > 0 } + Item { width: parent.width; height: Math.round(10 * localScale); visible: root._paired.length > 0 && root._available.length > 0 } - Item { width: parent.width; height: visible ? aLbl.implicitHeight + 4 : 0; visible: root._available.length > 0 - Text { id: aLbl; text: root._scanning ? "DISCOVERED" : "AVAILABLE"; font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(1,1,1,0.25) } } + Item { width: parent.width; height: visible ? aLbl.implicitHeight + Math.round(4 * localScale) : 0; visible: root._available.length > 0 + Text { id: aLbl; text: root._scanning ? "DISCOVERED" : "AVAILABLE"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(1,1,1,0.25) } } Repeater { model: root._available - delegate: DeviceRow { required property var modelData; width: devCol.width - 2; x: 1; device: modelData; isPaired: false } + delegate: DeviceRow { required property var modelData; width: devCol.width - Math.round(2 * localScale); x: Math.round(1 * localScale); device: modelData; isPaired: false } } // Empty state Item { - width: parent.width; height: 120 + width: parent.width; height: Math.round(120 * localScale) visible: !root._scanning && root._allDevices.length === 0 && root._btPowered - Column { anchors.centerIn: parent; spacing: 10 - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰂯"; font.pixelSize: 32; color: Qt.rgba(1,1,1,0.08) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "No devices found"; font.pixelSize: 12; color: Qt.rgba(1,1,1,0.2) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Tap Scan to discover nearby devices"; font.pixelSize: 10; color: Qt.rgba(1,1,1,0.14) } + Column { anchors.centerIn: parent; spacing: Math.round(10 * localScale) + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰂯"; font.pixelSize: Math.round(32 * localScale); color: Qt.rgba(1,1,1,0.08) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "No devices found"; font.pixelSize: Math.round(12 * localScale); color: Qt.rgba(1,1,1,0.2) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Tap Scan to discover nearby devices"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.14) } } } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } } } } // ── Bluetooth off overlay — anchors.fill + topMargin, no overflow ───────── Item { - anchors { fill: parent; topMargin: 49 } + anchors { fill: parent; topMargin: Math.round(49 * localScale) } visible: !root._btPowered z: 2 Rectangle { anchors.fill: parent; color: Qt.rgba(Theme.background.r, Theme.background.g, Theme.background.b, 0.95) } Column { - anchors.centerIn: parent; spacing: 16 - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰂲"; font.pixelSize: 42; color: Qt.rgba(1,1,1,0.12) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Bluetooth is off"; font.pixelSize: 14; font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.30) } + anchors.centerIn: parent; spacing: Math.round(16 * localScale) + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰂲"; font.pixelSize: Math.round(42 * localScale); color: Qt.rgba(1,1,1,0.12) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Bluetooth is off"; font.pixelSize: Math.round(14 * localScale); font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.30) } Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: enableRow.implicitWidth + 24; height: 34; radius: 17 + width: enableRow.implicitWidth + Math.round(24 * localScale); height: Math.round(34 * localScale); radius: Math.round(17 * localScale) color: enableH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } - Row { id: enableRow; anchors.centerIn: parent; spacing: 8 - Text { anchors.verticalCenter: parent.verticalCenter; text: "󰂯"; font.pixelSize: 14; color: Theme.active } - Text { anchors.verticalCenter: parent.verticalCenter; text: "Turn On"; font.pixelSize: 12; font.weight: Font.Medium; color: Theme.active } + Row { id: enableRow; anchors.centerIn: parent; spacing: Math.round(8 * localScale) + Text { anchors.verticalCenter: parent.verticalCenter; text: "󰂯"; font.pixelSize: Math.round(14 * localScale); color: Theme.active } + Text { anchors.verticalCenter: parent.verticalCenter; text: "Turn On"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: Theme.active } } HoverHandler { id: enableH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._setPower(true) } diff --git a/src/popups/ClipboardPopup.qml b/src/popups/ClipboardPopup.qml index 07f5503..27d6bfd 100644 --- a/src/popups/ClipboardPopup.qml +++ b/src/popups/ClipboardPopup.qml @@ -9,10 +9,12 @@ import "../" PanelWindow { id: root - readonly property int popupWidth: 420 - readonly property int popupHeight: 560 - readonly property int fw: Theme.cornerRadius - readonly property int fh: Theme.cornerRadius + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int popupWidth: Math.round(420 * root.localScale) + readonly property int popupHeight: Math.round(560 * root.localScale) + readonly property int fw: Math.round(Theme.cornerRadius * root.localScale) + readonly property int fh: Math.round(Theme.cornerRadius * root.localScale) anchors.top: true anchors.left: true @@ -87,7 +89,7 @@ PanelWindow { anchors.fill: parent attachedEdge: "bottom-right" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } @@ -96,9 +98,9 @@ PanelWindow { id: content anchors { fill: parent - topMargin: root.fh + 8 - leftMargin: root.fw + 10 - bottomMargin: 8 + topMargin: root.fh + Math.round(8 * root.localScale) + leftMargin: root.fw + Math.round(10 * root.localScale) + bottomMargin: Math.round(8 * root.localScale) } opacity: Popups.clipboardOpen ? 1 : 0 @@ -108,7 +110,10 @@ PanelWindow { } } - HistoryTab { anchors.fill: parent } + HistoryTab { + anchors.fill: parent + localScale: root.localScale + } } } } diff --git a/src/popups/Dashboard.qml b/src/popups/Dashboard.qml index 2ca570c..8735729 100644 --- a/src/popups/Dashboard.qml +++ b/src/popups/Dashboard.qml @@ -21,8 +21,13 @@ PanelWindow { // Kept so existing instantiation sites that pass anchorWindow: … still compile. required property var anchorWindow - readonly property int fw: Theme.notchRadius - readonly property int fh: Theme.notchRadius + // ── Context-Aware Scaling ───────────────────────────────────────────────── + // Multiplier based on screen height relative to 1080p, clamped to prevent + // extreme scaling on ultra-high or ultra-low resolution displays. + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int fw: Math.round(Theme.notchRadius * localScale) + readonly property int fh: Math.round(Theme.notchRadius * localScale) readonly property int animDuration: Theme.animDuration property string page: Popups.dashboardPage @@ -37,12 +42,13 @@ PanelWindow { }) function _applyPageWidth(p) { - var w = _pageWidths[p] - Popups.dashboardPageWidth = (w !== undefined) ? w : 900 + Popups.dashboardPageWidth = _pageWidths[p] ?? 900 } onPageChanged: _applyPageWidth(page) + readonly property real scaledPageWidth: Math.min(Popups.dashboardPageWidth * localScale, (screen ? screen.width : 1920) * 0.95) + color: "transparent" visible: windowVisible @@ -107,8 +113,10 @@ PanelWindow { anchors.horizontalCenter: parent.horizontalCenter clip: true - width: Popups.dashboardOpen ? Popups.dashboardPageWidth + 2 * root.fw : Theme.cNotchMinWidth + 2 * root.fw - height: Popups.dashboardOpen ? Theme.dashboardHeight : Theme.notchHeight / 2 + width: Popups.dashboardOpen ? root.scaledPageWidth + 2 * root.fw : Theme.cNotchMinWidth + 2 * root.fw + height: Popups.dashboardOpen + ? Math.min(Theme.dashboardHeight * localScale, (screen ? screen.height : 1080) * 0.90) + : Theme.notchHeight / 2 Behavior on width { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } Behavior on height { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } @@ -123,7 +131,7 @@ PanelWindow { anchors.fill: parent attachedEdge: "top" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * localScale) flareWidth: root.fw flareHeight: root.fh } @@ -133,10 +141,10 @@ PanelWindow { id: content anchors { fill: parent - topMargin: root.fh + 8 - leftMargin: root.fw + 8 - rightMargin: root.fw + 8 - bottomMargin: 8 + topMargin: root.fh + Math.round(8 * localScale) + leftMargin: root.fw + Math.round(8 * localScale) + rightMargin: root.fw + Math.round(8 * localScale) + bottomMargin: Math.round(8 * localScale) } opacity: Popups.dashboardOpen ? 1 : 0 @@ -155,6 +163,7 @@ PanelWindow { // ── Tab bar ─────────────────────────────────────────────────── TabSwitcher { id: tabBar + localScale: root.localScale orientation: "horizontal" width: parent.width currentPage: root.page @@ -179,34 +188,45 @@ PanelWindow { Item { anchors.fill: parent visible: root.page === "home" - DashHome { anchors.fill: parent } + DashHome { + anchors.fill: parent + localScale: root.localScale + } } Item { anchors.fill: parent visible: root.page === "stats" - DashStats { anchors.fill: parent } + DashStats { + anchors.fill: parent + localScale: root.localScale + } } Item { anchors.fill: parent visible: root.page === "kanban" - KanbanBoard { anchors.fill: parent } + KanbanBoard { + anchors.fill: parent + localScale: root.localScale + } } Item { anchors.fill: parent visible: root.page === "launcher" - AppLauncher { anchors.fill: parent } + AppLauncher { + anchors.fill: parent + localScale: root.localScale + } } Item { anchors.fill: parent visible: root.page === "config" - Item { - anchors.fill: parent - visible: root.page === "config" - ShellConfig { anchors.fill: parent } + ShellConfig { + anchors.fill: parent + localScale: root.localScale } } diff --git a/src/popups/HistoryTab.qml b/src/popups/HistoryTab.qml index f862ebc..8537663 100644 --- a/src/popups/HistoryTab.qml +++ b/src/popups/HistoryTab.qml @@ -5,6 +5,7 @@ import "../" Item { id: root + property real localScale: 1.0 readonly property var pinned: ClipboardService.pinned ?? [] readonly property var history: ClipboardService.entries ?? [] @@ -56,21 +57,21 @@ Item { // ── Header ───────────────────────────────────────────────────────────── Item { width: parent.width - height: 44 + height: Math.round(44 * localScale) Text { anchors.centerIn: parent text: "Clipboard" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) font.weight: Font.DemiBold color: Theme.text } // Clear unpinned history button Rectangle { - anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 4 } - width: clearRow.implicitWidth + 14 - height: 26; radius: 8 + anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: Math.round(4 * localScale) } + width: clearRow.implicitWidth + Math.round(14 * localScale) + height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: clearH.hovered ? Qt.rgba(248/255, 113/255, 113/255, 0.18) : Qt.rgba(1, 1, 1, 0.04) @@ -82,14 +83,14 @@ Item { Row { id: clearRow anchors.centerIn: parent - spacing: 5 + spacing: Math.round(5 * localScale) Text { - text: "󰩺"; font.pixelSize: 12 + text: "󰩺"; font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(248/255, 113/255, 113/255, 0.80) anchors.verticalCenter: parent.verticalCenter } Text { - text: "Clear"; font.pixelSize: 10 + text: "Clear"; font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(248/255, 113/255, 113/255, 0.80) anchors.verticalCenter: parent.verticalCenter } diff --git a/src/popups/HotspotTab.qml b/src/popups/HotspotTab.qml index a8d5720..1b210e6 100644 --- a/src/popups/HotspotTab.qml +++ b/src/popups/HotspotTab.qml @@ -11,6 +11,7 @@ import "../components" Item { id: root + property real localScale: 1.0 property string _ssid: "BrainShell" property string _password: "changeme1" property bool _showPass: false @@ -76,73 +77,73 @@ Item { // Header Item { - width: parent.width; height: 40 - Text { anchors { left: parent.left; leftMargin: 2 + width: parent.width; height: Math.round(40 * localScale) + Text { anchors { left: parent.left; leftMargin: Math.round(2 * localScale) verticalCenter: parent.verticalCenter } text: "Hotspot" - font.pixelSize: 15; font.weight: Font.Bold; color: Theme.text } + font.pixelSize: Math.round(15 * localScale); font.weight: Font.Bold; color: Theme.text } // Active indicator Row { - anchors { left: parent.left; leftMargin: 76; + anchors { left: parent.left; leftMargin: Math.round(76 * localScale); verticalCenter: parent.verticalCenter } - spacing: 6 - Rectangle { width: 7; height: 7; radius: 4; anchors.verticalCenter: parent.verticalCenter; color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.22); Behavior on color { ColorAnimation { duration: 200 } } } - Text { anchors.verticalCenter: parent.verticalCenter; text: ShellState.hotspot ? "Active" : "Inactive"; font.pixelSize: 11; color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.32) } + spacing: Math.round(6 * localScale) + Rectangle { width: Math.round(7 * localScale); height: Math.round(7 * localScale); radius: Math.round(4 * localScale); anchors.verticalCenter: parent.verticalCenter; color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.22); Behavior on color { ColorAnimation { duration: 200 } } } + Text { anchors.verticalCenter: parent.verticalCenter; text: ShellState.hotspot ? "Active" : "Inactive"; font.pixelSize: Math.round(11 * localScale); color: ShellState.hotspot ? Theme.active : Qt.rgba(1,1,1,0.32) } } } Rectangle { width: parent.width; height: 1; color: Qt.rgba(1,1,1,0.07) } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } Flickable { - width: parent.width; height: parent.height - 49 - contentWidth: width; contentHeight: mainCol.implicitHeight + 8 + width: parent.width; height: parent.height - Math.round(49 * localScale) + contentWidth: width; contentHeight: mainCol.implicitHeight + Math.round(8 * localScale) clip: true; boundsBehavior: Flickable.StopAtBounds Column { - id: mainCol; width: parent.width; spacing: 14 + id: mainCol; width: parent.width; spacing: Math.round(14 * localScale) // Info banner Rectangle { - width: parent.width; height: infoCol.implicitHeight + 16; radius: Theme.cornerRadius + width: parent.width; height: infoCol.implicitHeight + Math.round(16 * localScale); radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.06) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18); border.width: Math.max(1, Math.round(1 * localScale)) Column { id: infoCol; - anchors { left: parent.left; right: parent.right; top: parent.top; margins: 12 } - spacing: 4 - Text { width: parent.width; text: "󰀃 Toggle hotspot from the Quick Settings panel."; font.pixelSize: 11; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7); wrapMode: Text.WordWrap } - Text { width: parent.width; text: "Requires an ethernet connection. Shares the same WiFi channel as your current connection."; font.pixelSize: 10; color: Qt.rgba(1,1,1,0.30); wrapMode: Text.WordWrap; lineHeight: 1.4 } + anchors { left: parent.left; right: parent.right; top: parent.top; margins: Math.round(12 * localScale) } + spacing: Math.round(4 * localScale) + Text { width: parent.width; text: "󰀃 Toggle hotspot from the Quick Settings panel."; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7); wrapMode: Text.WordWrap } + Text { width: parent.width; text: "Requires an ethernet connection. Shares the same WiFi channel as your current connection."; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.30); wrapMode: Text.WordWrap; lineHeight: 1.4 } } } // Config card Rectangle { - width: parent.width; height: cfgCol.implicitHeight + 20; radius: Theme.cornerRadius - color: Qt.rgba(1,1,1,0.04); border.color: Qt.rgba(1,1,1,0.07); border.width: 1 + width: parent.width; height: cfgCol.implicitHeight + Math.round(20 * localScale); radius: Math.round(Theme.cornerRadius * localScale) + color: Qt.rgba(1,1,1,0.04); border.color: Qt.rgba(1,1,1,0.07); border.width: Math.max(1, Math.round(1 * localScale)) Column { - id: cfgCol; anchors { left: parent.left; right: parent.right; top: parent.top; margins: 12 } - spacing: 12 + id: cfgCol; anchors { left: parent.left; right: parent.right; top: parent.top; margins: Math.round(12 * localScale) } + spacing: Math.round(12 * localScale) - Text { text: "CREDENTIALS"; font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } + Text { text: "CREDENTIALS"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } // SSID Item { - width: parent.width; height: 32 + width: parent.width; height: Math.round(32 * localScale) Text { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - text: "SSID"; font.pixelSize: 11; font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.45); width: 72 } + text: "SSID"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.45); width: Math.round(72 * localScale) } Rectangle { - anchors { left: parent.left; leftMargin: 76; right: parent.right; verticalCenter: parent.verticalCenter } - height: 28; radius: 7 + anchors { left: parent.left; leftMargin: Math.round(76 * localScale); right: parent.right; verticalCenter: parent.verticalCenter } + height: Math.round(28 * localScale); radius: Math.round(7 * localScale) color: ssidInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08) : Qt.rgba(1,1,1,0.05) - border.color: ssidInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.11); border.width: 1 + border.color: ssidInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.11); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on border.color { ColorAnimation { duration: 120 } } TextInput { - id: ssidInput; anchors { fill: parent; leftMargin: 10; rightMargin: 10 } - verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: 12 + id: ssidInput; anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } + verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: Math.round(12 * localScale) selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) clip: true; maximumLength: 32 text: root._ssid @@ -153,18 +154,18 @@ Item { // Password Item { - width: parent.width; height: 32 + width: parent.width; height: Math.round(32 * localScale) Text { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - text: "Password"; font.pixelSize: 11; font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.45); width: 72 } + text: "Password"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.45); width: Math.round(72 * localScale) } Rectangle { - anchors { left: parent.left; leftMargin: 76; right: eyeBtn.left; rightMargin: 6; verticalCenter: parent.verticalCenter } - height: 28; radius: 7 + anchors { left: parent.left; leftMargin: Math.round(76 * localScale); right: eyeBtn.left; rightMargin: Math.round(6 * localScale); verticalCenter: parent.verticalCenter } + height: Math.round(28 * localScale); radius: Math.round(7 * localScale) color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08) : Qt.rgba(1,1,1,0.05) - border.color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.11); border.width: 1 + border.color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.11); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on border.color { ColorAnimation { duration: 120 } } TextInput { - id: passInput; anchors { fill: parent; leftMargin: 10; rightMargin: 10 } - verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: 12 + id: passInput; anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } + verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: Math.round(12 * localScale) selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) echoMode: root._showPass ? TextInput.Normal : TextInput.Password clip: true; maximumLength: 63 @@ -175,9 +176,9 @@ Item { Item { id: eyeBtn; anchors { right: parent.right; verticalCenter: parent.verticalCenter } - width: 28; height: 28 - Rectangle { anchors.fill: parent; radius: 6; color: eyeH.hovered ? Qt.rgba(1,1,1,0.08) : "transparent" } - Text { anchors.centerIn: parent; text: root._showPass ? "" : ""; font.pixelSize: 13; color: root._showPass ? Theme.active : Qt.rgba(1,1,1,0.28) } + width: Math.round(28 * localScale); height: Math.round(28 * localScale) + Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: eyeH.hovered ? Qt.rgba(1,1,1,0.08) : "transparent" } + Text { anchors.centerIn: parent; text: root._showPass ? "" : ""; font.pixelSize: Math.round(13 * localScale); color: root._showPass ? Theme.active : Qt.rgba(1,1,1,0.28) } HoverHandler { id: eyeH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._showPass = !root._showPass } } @@ -187,20 +188,20 @@ Item { Rectangle { visible: root._dirty anchors.horizontalCenter: parent.horizontalCenter - width: 90; height: 28; radius: 8 + width: Math.round(90 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: saveH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "Save"; font.pixelSize: 12; font.weight: Font.Medium; color: Theme.active } + Text { anchors.centerIn: parent; text: "Save"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: saveH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._save() } } } } - Item { width: parent.width; height: 4 } + Item { width: parent.width; height: Math.round(4 * localScale) } } } } diff --git a/src/popups/NetworkPopup.qml b/src/popups/NetworkPopup.qml index a26d640..d2ac2a4 100644 --- a/src/popups/NetworkPopup.qml +++ b/src/popups/NetworkPopup.qml @@ -9,10 +9,12 @@ import "../" PanelWindow { id: root - readonly property int popupWidth: Theme.networkPopupWidth // 480 - readonly property int popupHeight: 648 - readonly property int fw: Theme.notchRadius - readonly property int fh: Theme.notchRadius + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int popupWidth: Math.round(Theme.networkPopupWidth * root.localScale) + readonly property int popupHeight: Math.round(648 * root.localScale) + readonly property int fw: Math.round(Theme.notchRadius * root.localScale) + readonly property int fh: Math.round(Theme.notchRadius * root.localScale) property string page: Popups.networkPage @@ -20,8 +22,8 @@ PanelWindow { anchors.top: true // Window height = popup content only — sizer starts at y:0 - implicitWidth: popupWidth + fw - implicitHeight: popupHeight + implicitWidth: popupWidth + fw + 8 + implicitHeight: popupHeight + 8 exclusionMode: ExclusionMode.Ignore color: "transparent" @@ -73,13 +75,13 @@ PanelWindow { Item { id: sizer anchors.right: parent.right - anchors.rightMargin: Theme.borderWidth + anchors.rightMargin: Math.round(Theme.borderWidth * root.localScale) y: 0 clip: true width: Popups.networkOpen - ? root.popupWidth + 9 - : Theme.rNotchMinWidth + root.fw + ? root.popupWidth + Math.round(9 * root.localScale) + : Math.round(Theme.rNotchMinWidth * root.localScale) + root.fw height: Popups.networkOpen ? root.popupHeight : 0 @@ -90,21 +92,21 @@ PanelWindow { anchors.fill: parent attachedEdge: "right" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } - + Keys.onEscapePressed: Popups.networkOpen = false Item { id: contentArea anchors { fill: parent - topMargin: Theme.notchHeight + topMargin: Math.round(Theme.notchHeight * root.localScale) leftMargin: root.fw rightMargin: root.fw/2 - bottomMargin: root.fh + Theme.cornerRadius + bottomMargin: root.fh + Math.round(Theme.cornerRadius * root.localScale) } opacity: Popups.networkOpen ? 1 : 0 @@ -130,12 +132,14 @@ PanelWindow { anchors.fill: parent active: root.page === "wifi" source: "WifiTab.qml" + onLoaded: item.localScale = root.localScale } Loader { anchors.fill: parent active: root.page === "bluetooth" source: "BluetoothTab.qml" + onLoaded: item.localScale = root.localScale } // VPN — WireGuard connections @@ -143,6 +147,7 @@ PanelWindow { anchors.fill: parent active: root.page === "vpn" source: "VPNTab.qml" + onLoaded: item.localScale = root.localScale } // Hotspot — virtual AP interface @@ -150,18 +155,20 @@ PanelWindow { anchors.fill: parent active: root.page === "hotspot" source: "HotspotTab.qml" + onLoaded: item.localScale = root.localScale } } // ── Tab bar — lifted by cornerRadius from the popup bottom ──────── TabSwitcher { id: tabBar + localScale: root.localScale || 1.0 anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - bottomMargin: -16 - } + left: parent.left + right: parent.right + bottom: parent.bottom + bottomMargin: Math.round(-16 * root.localScale) + } orientation: "horizontal" width: parent.width currentPage: root.page diff --git a/src/popups/NotificationToast.qml b/src/popups/NotificationToast.qml index 0038ccd..68036ee 100644 --- a/src/popups/NotificationToast.qml +++ b/src/popups/NotificationToast.qml @@ -10,21 +10,22 @@ PopupWindow { id: root required property var anchorWindow - - readonly property int toastWidth: Theme.notificationToastWidth+(fw/2) - readonly property int fw: Theme.notchRadius - readonly property int fh: Theme.notchRadius - - implicitWidth: toastWidth + fw - implicitHeight: 180 - - anchor.window: root.anchorWindow - anchor.rect: Qt.rect( - root.anchorWindow.width - toastWidth/2-fw+1, - -Theme.notchHeight-20, - toastWidth, - Theme.notchHeight - ) + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int toastWidth: Math.round(Theme.notificationToastWidth * localScale) + fw/1.5 + readonly property int fw: Math.round(Theme.notchRadius * localScale) + readonly property int fh: Math.round(Theme.notchRadius * localScale) + + implicitWidth: toastWidth + Math.round(fw/2) + Math.round(10 * localScale) + implicitHeight: Math.round(180 * localScale) + + anchor.window: root.anchorWindow + anchor.rect: Qt.rect( + root.anchorWindow.width - Math.round(toastWidth/2) - Math.round(fw), + Math.round((-Theme.notchHeight / 2) * localScale), + toastWidth, + Math.round(Theme.notchHeight * localScale) + ) anchor.gravity: Edges.Bottom anchor.adjustment: PopupAdjustment.None @@ -109,7 +110,7 @@ PopupWindow { : root.fw height: root.showing - ? (cardCol.y + cardCol.implicitHeight + 24 + root.fh) + ? (cardCol.y + cardCol.implicitHeight + Math.round(24 * root.localScale) + root.fh) : root.fh Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } @@ -119,7 +120,7 @@ PopupWindow { anchors.fill: parent attachedEdge: "right" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } @@ -133,8 +134,8 @@ PopupWindow { bottomMargin: fh*1.2 rightMargin: root.fw } - width: 3 - radius: 2 + width: Math.round(3 * root.localScale) + radius: Math.round(2 * root.localScale) color: { if (!root.current) return "#ABB2BF" switch (root.current.urgency) { @@ -155,17 +156,17 @@ PopupWindow { right: parent.right rightMargin: root.fw bottom: cardCol.bottom - bottomMargin: -10 + bottomMargin: Math.round(-10 * root.localScale) } - height: 2 - radius: 1 + height: Math.round(2 * root.localScale) + radius: Math.round(1 * root.localScale) color: Theme.active opacity: 0.5 property bool running: false // Use toastWidth so the bar stays within the visible body, not the flare - width: running ? 0 : root.toastWidth - 10 + width: running ? 0 : root.toastWidth - Math.round(10 * root.localScale) Behavior on width { enabled: progressBar.running NumberAnimation { duration: 5000; easing.type: Easing.Linear } @@ -193,24 +194,24 @@ PopupWindow { Column { id: cardCol anchors { - left: parent.left; leftMargin: 14 - right: parent.right; rightMargin: root.fw + 6 + left: parent.left; leftMargin: Math.round(14 * root.localScale) + right: parent.right; rightMargin: root.fw + Math.round(6 * root.localScale) } - spacing: 2 - bottomPadding: 10 - y: root.fh + 6 + spacing: Math.round(2 * root.localScale) + bottomPadding: Math.round(10 * root.localScale) + y: root.fh + Math.round(6 * root.localScale) // No fixed height — sizes to content Row { id: headerRow width: parent.width - height: 40 - spacing: 8 + height: Math.round(40 * root.localScale) + spacing: Math.round(8 * root.localScale) Item { - width: 16 - height: 16 + width: Math.round(16 * root.localScale) + height: Math.round(16 * root.localScale) anchors.verticalCenter: parent.verticalCenter Image { @@ -225,8 +226,8 @@ PopupWindow { fillMode: Image.PreserveAspectFit smooth: true visible: status === Image.Ready - sourceSize.width: 16 - sourceSize.height: 16 + sourceSize.width: Math.round(16 * root.localScale) | 0 + sourceSize.height: Math.round(16 * root.localScale) | 0 } Rectangle { anchors.fill: parent @@ -237,24 +238,24 @@ PopupWindow { anchors.centerIn: parent text: (root.current?.appName ?? "?").charAt(0).toUpperCase() color: Theme.text - font.pixelSize: 9 + font.pixelSize: Math.round(9 * root.localScale) | 0 font.bold: true } } } Text { - width: parent.width - 16 - 24 - parent.spacing * 2 + width: parent.width - Math.round(16 * root.localScale) - Math.round(24 * root.localScale) - parent.spacing * 2 anchors.verticalCenter: parent.verticalCenter text: root.current?.appName ?? "" color: Theme.subtext - font.pixelSize: 11 + font.pixelSize: Math.round(11 * root.localScale) | 0 elide: Text.ElideRight } Item { - width: 20 - height: 20 + width: Math.round(20 * root.localScale) + height: Math.round(20 * root.localScale) anchors.verticalCenter: parent.verticalCenter Rectangle { anchors.fill: parent @@ -266,7 +267,7 @@ PopupWindow { anchors.centerIn: parent text: "✕" color: Theme.subtext - font.pixelSize: 9 + font.pixelSize: Math.round(9 * root.localScale) | 0 } HoverHandler { id: xHover } TapHandler { onTapped: root.startDismiss() } @@ -277,7 +278,7 @@ PopupWindow { width: parent.width text: root.current?.summary ?? "" color: Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * root.localScale) | 0 font.bold: true wrapMode: Text.WordWrap maximumLineCount: 2 @@ -289,7 +290,7 @@ PopupWindow { width: parent.width text: root.current?.body ?? "" color: Theme.subtext - font.pixelSize: 12 + font.pixelSize: Math.round(12 * root.localScale) | 0 wrapMode: Text.WordWrap maximumLineCount: 2 elide: Text.ElideRight @@ -298,19 +299,19 @@ PopupWindow { } Row { - spacing: 6 - topPadding: 2 + spacing: Math.round(6 * root.localScale) + topPadding: Math.round(2 * root.localScale) visible: (root.current?.actions?.length ?? 0) > 0 Repeater { model: root.current?.actions ?? [] delegate: Item { required property var modelData - width: actionLbl.width + 20 - height: 24 + width: actionLbl.width + Math.round(20 * root.localScale) + height: Math.round(24 * root.localScale) Rectangle { anchors.fill: parent - radius: 4 + radius: Math.round(4 * root.localScale) color: actHover.containsMouse ? Qt.rgba(1,1,1,0.18) : Qt.rgba(1,1,1,0.08) @@ -321,7 +322,7 @@ PopupWindow { anchors.centerIn: parent text: modelData?.text ?? "" color: Theme.text - font.pixelSize: 11 + font.pixelSize: Math.round(11 * root.localScale) | 0 } HoverHandler { id: actHover } TapHandler { diff --git a/src/popups/NotificationsPopup.qml b/src/popups/NotificationsPopup.qml index 0a8c053..a411f8d 100644 --- a/src/popups/NotificationsPopup.qml +++ b/src/popups/NotificationsPopup.qml @@ -12,22 +12,24 @@ PopupWindow { required property var anchorWindow - readonly property int popupWidth: Theme.notificationsWidth - readonly property int maxHeight: 700 - readonly property int fw: Theme.notchRadius - readonly property int fh: Theme.notchRadius + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + + readonly property int popupWidth: Math.round(Theme.notificationsWidth * root.localScale) + readonly property int maxHeight: Math.round(700 * root.localScale) + readonly property int fw: Math.round(Theme.notchRadius * root.localScale) + readonly property int fh: Math.round(Theme.notchRadius * root.localScale) readonly property int animDuration: Theme.animDuration // Fixed — never zero, never dynamic - implicitWidth: popupWidth +fw + implicitWidth: popupWidth + fw implicitHeight: maxHeight anchor.window: root.anchorWindow anchor.rect: Qt.rect( - (anchorWindow.width - Theme.notificationsWidth / 2)-(fw/2), + Math.round(anchorWindow.width - (popupWidth / 2) - fw + 1), 0, - Theme.notificationsWidth, - Theme.notchHeight + Math.round(Theme.notificationsWidth * root.localScale), + Math.round(Theme.notchHeight * root.localScale) ) anchor.gravity: Edges.Bottom anchor.adjustment: PopupAdjustment.None @@ -76,12 +78,12 @@ PopupWindow { // Width: rNotchMinWidth → notificationsWidth (+ fw for flare region) width: Popups.notificationsOpen - ? Theme.notificationsWidth + root.fw - : Theme.rNotchMinWidth + root.fw + ? Math.round(Theme.notificationsWidth * root.localScale) + root.fw + : Math.round(Theme.rNotchMinWidth * root.localScale) + root.fw // Height: fh (invisible sliver) → full content height height: Popups.notificationsOpen - ? notifList.height + Theme.popupPadding * 2 + root.fh + ? notifList.height + Math.round(Theme.popupPadding * 2 * root.localScale) + root.fh : root.fh Behavior on width { NumberAnimation { duration: root.animDuration; easing.type: Easing.InOutCubic } } @@ -92,7 +94,7 @@ PopupWindow { anchors.fill: parent attachedEdge: "right" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } @@ -103,10 +105,10 @@ PopupWindow { Item { anchors { fill: parent - topMargin: root.fh + 4 - leftMargin: root.fw + 4 - rightMargin: 4 - bottomMargin: 4 + topMargin: root.fh + Math.round(4 * root.localScale) + leftMargin: root.fw + Math.round(4 * root.localScale) + rightMargin: Math.round(4 * root.localScale) + bottomMargin: Math.round(4 * root.localScale) } opacity: Popups.notificationsOpen ? 1 : 0 @@ -120,6 +122,7 @@ PopupWindow { NotificationList { id: notifList + localScale: root.localScale width: parent.width } } diff --git a/src/popups/PopupLayer.qml b/src/popups/PopupLayer.qml index 740585d..822ee69 100644 --- a/src/popups/PopupLayer.qml +++ b/src/popups/PopupLayer.qml @@ -41,7 +41,7 @@ Item { anchorWindow: root.rightBorder } QuickControl { - anchorWindow: root.topBar + anchorWindow: root.rightBorder } // Center notch — dashboard (expands below the center notch) @@ -55,7 +55,7 @@ Item { } NotificationToast { - anchorWindow: root.rightBorder + anchorWindow: root.topBar } // Screen recorder strip options — appears below center notch on hover diff --git a/src/popups/QuickControl.qml b/src/popups/QuickControl.qml index e05be83..9b1fae0 100644 --- a/src/popups/QuickControl.qml +++ b/src/popups/QuickControl.qml @@ -12,11 +12,14 @@ PopupWindow { required property var anchorWindow + // ── Context-Aware Scaling ───────────────────────────────────────────────── + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + // ── Config ──────────────────────────────────────────────────────────────── - readonly property int fw: Theme.cornerRadius - readonly property int fh: Theme.cornerRadius - readonly property int popupHeight: 340 - readonly property int popupWidth: 180 // Thinner than the 300px AudioPopup + readonly property int fw: Math.round(Theme.cornerRadius * root.localScale) + readonly property int fh: Math.round(Theme.cornerRadius * root.localScale) + readonly property int popupHeight: Math.round(340 * root.localScale) + readonly property int popupWidth: Math.round(180 * root.localScale) // Thinner than the 300px AudioPopup color: "transparent" visible: slide.windowVisible @@ -26,12 +29,12 @@ PopupWindow { anchor.window: anchorWindow anchor.rect: Qt.rect( anchorWindow.width - root.fw, - (root.screen.height + root.fh + 5)/2, + anchorWindow.height/2, 0, 0 ) anchor.gravity: Edges.Right - + Item { id: maskProxy x: root.popupWidth - sizer.width @@ -103,9 +106,9 @@ PopupWindow { id: slide anchors.fill: parent edge: "right" - open: Popups.quickOpen + open: Popups.quickOpen hoverEnabled: true - triggerHovered: Popups.quickTriggerHovered + triggerHovered: Popups.quickTriggerHovered onCloseRequested: Popups.quickOpen = false Item { @@ -137,7 +140,7 @@ PopupWindow { leftMargin: 8 rightMargin: 8 } - spacing: 8 + spacing: 8 anchors.horizontalCenter: parent.horizontalCenter // Audio Slider @@ -152,7 +155,7 @@ PopupWindow { value: root.sink?.ready ? root.sink.audio.volume : 0 muted: root.sink?.audio.muted ?? false active: root.sink?.ready ?? false - + onVolumeChanged: function(v) { if (root.sink?.ready) root.sink.audio.volume = v } @@ -163,11 +166,12 @@ PopupWindow { // Brightness Slider ChannelColumn { + localScale: root.localScale icon: "󰃠" - value: root._bVal + value: root._bVal muted: false active: true - + onVolumeChanged: function(v) { root.setBrightness(v) } @@ -180,15 +184,16 @@ PopupWindow { component ChannelColumn: Item { id: col + property real localScale: 1.0 property string label: "" property string icon: "" property real value: 0.0 property bool muted: false property bool active: false - readonly property int trackHeight: 180 - readonly property int barW: 22 - readonly property int thumbD: barW - 6 + readonly property int trackHeight: Math.round(180 * root.localScale) + readonly property int barW: Math.round(22 * root.localScale) + readonly property int thumbD: barW - Math.round(6 * root.localScale) signal volumeChanged(real value) signal muteToggled() @@ -201,13 +206,13 @@ PopupWindow { Column { id: inner anchors.horizontalCenter: parent.horizontalCenter - spacing: 12 + spacing: Math.round(12 * root.localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: col.pctText color: col.muted ? Qt.rgba(1,1,1,0.25) : Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * root.localScale) font.bold: true Behavior on color { ColorAnimation { duration: 150 } } } @@ -275,9 +280,9 @@ PopupWindow { // Icon & Mute Toggle Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: col.barW + 16 - height: 28 - radius: Theme.cornerRadius + width: col.barW + Math.round(16 * root.localScale) + height: Math.round(28 * root.localScale) + radius: Math.round(Theme.cornerRadius * root.localScale) color: col.muted ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.2) : Qt.rgba(1,1,1,0.06) @@ -286,7 +291,7 @@ PopupWindow { Text { anchors.centerIn: parent text: col.icon - font.pixelSize: 14 + font.pixelSize: Math.round(14 * root.localScale) color: col.muted ? Theme.active : Qt.rgba(1,1,1,0.55) Behavior on color { ColorAnimation { duration: 150 } } } @@ -305,13 +310,13 @@ PopupWindow { anchors.horizontalCenter: parent.horizontalCenter text: col.label color: Qt.rgba(1,1,1,0.3) - font.pixelSize: 10 + font.pixelSize: Math.round(10 * root.localScale) font.capitalization: Font.AllUppercase font.letterSpacing: 1 elide: Text.ElideRight - width: col.barW + 50 + width: col.barW + Math.round(50 * root.localScale) horizontalAlignment: Text.AlignHCenter } } } -} \ No newline at end of file +} diff --git a/src/popups/ScreenRecOptionsPopup.qml b/src/popups/ScreenRecOptionsPopup.qml index 4c9ba81..3226916 100644 --- a/src/popups/ScreenRecOptionsPopup.qml +++ b/src/popups/ScreenRecOptionsPopup.qml @@ -13,9 +13,10 @@ PopupWindow { id: root required property var anchorWindow + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) - readonly property int _padH: 5 - readonly property int _padV: 5 + readonly property int _padH: Math.round(5 * root.localScale) + readonly property int _padV: Math.round(5 * root.localScale) implicitWidth: optCol.implicitWidth + _padH * 2 implicitHeight: optCol.implicitHeight + _padV * 2 @@ -25,9 +26,9 @@ PopupWindow { anchor.adjustment: PopupAdjustment.None anchor.rect: Qt.rect( ScreenRecService.popupTargetX + (ScreenRecService.popupTargetWidth / 2), - 25, + Math.round(25 * root.localScale), root.implicitWidth, - Theme.notchHeight + Math.round(Theme.notchHeight * root.localScale) ) color: "transparent" @@ -42,7 +43,7 @@ PopupWindow { Rectangle { anchors.fill: parent - radius: Theme.cornerRadius - 6 + radius: Math.round((Theme.cornerRadius - 6) * root.localScale) color: Theme.background border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) border.width: 1 @@ -52,7 +53,7 @@ PopupWindow { id: optCol x: _padH y: _padV - spacing: 2 + spacing: Math.round(2 * root.localScale) // Capture — radio (one active at a time) Repeater { @@ -111,12 +112,12 @@ PopupWindow { signal clicked() - implicitWidth: 8 + 14 + 6 + _lbl.implicitWidth + 12 - implicitHeight: 26 + implicitWidth: Math.round((8 + 14 + 6 + 12) * root.localScale) + _lbl.implicitWidth + implicitHeight: Math.round(26 * root.localScale) Rectangle { anchors.fill: parent - radius: 5 + radius: Math.round(5 * root.localScale) color: row._selected ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : rH.hovered ? Qt.rgba(1, 1, 1, 0.07) : "transparent" @@ -124,12 +125,12 @@ PopupWindow { } Row { - anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter } - spacing: 6 + anchors { left: parent.left; leftMargin: Math.round(8 * root.localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(6 * root.localScale) Text { text: row._icon - font.pixelSize: 13 + font.pixelSize: Math.round(13 * root.localScale) color: row._selected ? Theme.active : Qt.rgba(1, 1, 1, 0.45) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } @@ -137,7 +138,7 @@ PopupWindow { Text { id: _lbl text: row._label - font.pixelSize: 12 + font.pixelSize: Math.round(12 * root.localScale) color: row._selected ? Theme.active : Qt.rgba(1, 1, 1, 0.70) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } diff --git a/src/popups/VPNTab.qml b/src/popups/VPNTab.qml index 364d560..218f0bf 100644 --- a/src/popups/VPNTab.qml +++ b/src/popups/VPNTab.qml @@ -19,6 +19,8 @@ import "../components" Item { id: root + property real localScale: 1.0 + // ── State ───────────────────────────────────────────────────────────────── property var _connections: [] // [{name, active, busy}] property var _buf: [] @@ -351,43 +353,43 @@ Item { // Header Item { - width: parent.width; height: 40 + width: parent.width; height: Math.round(40 * localScale) Text { - anchors { left: parent.left; leftMargin: 2; verticalCenter: parent.verticalCenter } - text: "VPN"; font.pixelSize: 15; font.weight: Font.Bold; color: Theme.text + anchors { left: parent.left; leftMargin: Math.round(2 * localScale); verticalCenter: parent.verticalCenter } + text: "VPN"; font.pixelSize: Math.round(15 * localScale); font.weight: Font.Bold; color: Theme.text } Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - spacing: 8 + spacing: Math.round(8 * localScale) // Kill switch toggle Rectangle { - height: 28; radius: 14 - width: ksRow.implicitWidth + 18 + height: Math.round(28 * localScale); radius: Math.round(14 * localScale) + width: ksRow.implicitWidth + Math.round(18 * localScale) color: root._killSwitch ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : ksH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: root._killSwitch ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40) : Qt.rgba(1,1,1,0.10) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 130 } } Behavior on border.color { ColorAnimation { duration: 130 } } Row { - id: ksRow; anchors.centerIn: parent; spacing: 6 + id: ksRow; anchors.centerIn: parent; spacing: Math.round(6 * localScale) Text { anchors.verticalCenter: parent.verticalCenter - text: "󰒃"; font.pixelSize: 13 + text: "󰒃"; font.pixelSize: Math.round(13 * localScale) color: root._killSwitch ? Theme.active : Qt.rgba(1,1,1,0.40) Behavior on color { ColorAnimation { duration: 130 } } } Text { anchors.verticalCenter: parent.verticalCenter - text: "Kill Switch"; font.pixelSize: 11; font.weight: Font.Medium + text: "Kill Switch"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: root._killSwitch ? Theme.active : Qt.rgba(1,1,1,0.45) Behavior on color { ColorAnimation { duration: 130 } } } @@ -399,14 +401,14 @@ Item { // Refresh Rectangle { - width: 32; height: 32; radius: 8 + width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: rfH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } Text { - id: rfIcon; anchors.centerIn: parent; text: "󰑐"; font.pixelSize: 15 + id: rfIcon; anchors.centerIn: parent; text: "󰑐"; font.pixelSize: Math.round(15 * localScale) color: root._loading ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) : Theme.active @@ -424,24 +426,24 @@ Item { } Rectangle { width: parent.width; height: 1; color: Qt.rgba(1,1,1,0.07) } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } // Connection list Flickable { - width: parent.width; height: parent.height - 49 + width: parent.width; height: parent.height - Math.round(49 * localScale) contentWidth: width; contentHeight: conCol.height clip: true; boundsBehavior: Flickable.StopAtBounds Column { - id: conCol; width: parent.width; height: implicitHeight; spacing: 6 + id: conCol; width: parent.width; height: implicitHeight; spacing: Math.round(6 * localScale) // Active section Item { - width: parent.width; height: visible ? aLbl.implicitHeight + 4 : 0 + width: parent.width; height: visible ? aLbl.implicitHeight + Math.round(4 * localScale) : 0 visible: root._connections.some(function(c) { return c.active }) Text { id: aLbl; text: "ACTIVE" - font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2 + font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2 color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } @@ -450,23 +452,23 @@ Item { model: root._connections.filter(function(c) { return c.active }) delegate: VPNRow { required property var modelData - width: conCol.width - 2; x: 1; con: modelData + width: conCol.width - Math.round(2 * localScale); x: Math.round(1 * localScale); con: modelData } } Item { - width: parent.width; height: 6 + width: parent.width; height: Math.round(6 * localScale) visible: root._connections.some(function(c) { return c.active }) && root._connections.some(function(c) { return !c.active }) } // Available section Item { - width: parent.width; height: visible ? iLbl.implicitHeight + 4 : 0 + width: parent.width; height: visible ? iLbl.implicitHeight + Math.round(4 * localScale) : 0 visible: root._connections.some(function(c) { return !c.active }) Text { id: iLbl; text: "AVAILABLE" - font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2 + font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2 color: Qt.rgba(1,1,1,0.25) } } @@ -475,27 +477,27 @@ Item { model: root._connections.filter(function(c) { return !c.active }) delegate: VPNRow { required property var modelData - width: conCol.width - 2; x: 1; con: modelData + width: conCol.width - Math.round(2 * localScale); x: Math.round(1 * localScale); con: modelData } } // Empty state Item { - width: parent.width; height: 180 + width: parent.width; height: Math.round(180 * localScale) visible: !root._loading && root._connections.length === 0 Column { - anchors.centerIn: parent; spacing: 12 - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰦝"; font.pixelSize: 36; color: Qt.rgba(1,1,1,0.08) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "No WireGuard connections"; font.pixelSize: 13; color: Qt.rgba(1,1,1,0.2) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Import a config to get started:"; font.pixelSize: 10; color: Qt.rgba(1,1,1,0.14); horizontalAlignment: Text.AlignHCenter } + anchors.centerIn: parent; spacing: Math.round(12 * localScale) + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰦝"; font.pixelSize: Math.round(36 * localScale); color: Qt.rgba(1,1,1,0.08) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "No WireGuard connections"; font.pixelSize: Math.round(13 * localScale); color: Qt.rgba(1,1,1,0.2) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Import a config to get started:"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.14); horizontalAlignment: Text.AlignHCenter } Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: codeText.implicitWidth + 24; height: 26; radius: 6 - color: Qt.rgba(1,1,1,0.05); border.color: Qt.rgba(1,1,1,0.10); border.width: 1 + width: codeText.implicitWidth + Math.round(24 * localScale); height: Math.round(26 * localScale); radius: Math.round(6 * localScale) + color: Qt.rgba(1,1,1,0.05); border.color: Qt.rgba(1,1,1,0.10); border.width: Math.max(1, Math.round(1 * localScale)) Text { id: codeText; anchors.centerIn: parent text: "nmcli con import type wireguard file " - font.pixelSize: 9; font.family: "JetBrains Mono" + font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono" color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } @@ -504,13 +506,13 @@ Item { // Loading state Item { - width: parent.width; height: 80 + width: parent.width; height: Math.round(80 * localScale) visible: root._loading && root._connections.length === 0 Column { - anchors.centerIn: parent; spacing: 8 + anchors.centerIn: parent; spacing: Math.round(8 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter - text: "○"; font.pixelSize: 20; color: Theme.active + text: "○"; font.pixelSize: Math.round(20 * localScale); color: Theme.active SequentialAnimation on opacity { running: root._loading && root._connections.length === 0 loops: Animation.Infinite @@ -518,11 +520,11 @@ Item { NumberAnimation { to: 1.0; duration: 550 } } } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Loading…"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.25) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Loading…"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.25) } } } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } } } } @@ -531,7 +533,7 @@ Item { component VPNRow: Item { id: vRow required property var con // { name, active, busy } - height: 54 + height: Math.round(54 * localScale) property bool _wasActive: false onConChanged: { @@ -541,14 +543,14 @@ Item { // Card background Rectangle { - id: card; anchors.fill: parent; radius: Theme.cornerRadius + id: card; anchors.fill: parent; radius: Math.round(Theme.cornerRadius * localScale) color: vRow.con.active ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.08) : vHov.hovered ? Qt.rgba(1,1,1,0.04) : "transparent" border.color: vRow.con.active ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(1,1,1,0.07) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 200 } } Behavior on border.color { ColorAnimation { duration: 200 } } @@ -560,13 +562,13 @@ Item { } Row { - anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter } - spacing: 12 + anchors { left: parent.left; leftMargin: Math.round(12 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(12 * localScale) // Shield glyph Text { anchors.verticalCenter: parent.verticalCenter - text: "󰦝"; font.pixelSize: 20 + text: "󰦝"; font.pixelSize: Math.round(20 * localScale) color: vRow.con.active ? Theme.active : vRow.con.busy @@ -576,16 +578,16 @@ Item { } Column { - anchors.verticalCenter: parent.verticalCenter; spacing: 4 + anchors.verticalCenter: parent.verticalCenter; spacing: Math.round(4 * localScale) Text { - text: vRow.con.name; font.pixelSize: 13 + text: vRow.con.name; font.pixelSize: Math.round(13 * localScale) font.weight: vRow.con.active ? Font.Medium : Font.Normal color: vRow.con.active ? Theme.text : Qt.rgba(1,1,1,0.65) - width: 160; elide: Text.ElideRight + width: Math.round(160 * localScale); elide: Text.ElideRight } Text { - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) text: vRow.con.busy ? (vRow.con.active ? "Disconnecting…" : "Connecting…") : vRow.con.active ? "Connected" : "Disconnected" @@ -599,12 +601,12 @@ Item { // Right: spinner or status dot Item { - anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter } - width: 28; height: 28 + anchors { right: parent.right; rightMargin: Math.round(12 * localScale); verticalCenter: parent.verticalCenter } + width: Math.round(28 * localScale); height: Math.round(28 * localScale) Text { anchors.centerIn: parent; visible: vRow.con.busy - text: "○"; font.pixelSize: 16; color: Theme.active + text: "○"; font.pixelSize: Math.round(16 * localScale); color: Theme.active SequentialAnimation on opacity { running: vRow.con.busy; loops: Animation.Infinite NumberAnimation { to: 0.15; duration: 450 } @@ -614,7 +616,7 @@ Item { Rectangle { anchors.centerIn: parent; visible: !vRow.con.busy - width: 10; height: 10; radius: 5 + width: Math.round(10 * localScale); height: Math.round(10 * localScale); radius: Math.round(5 * localScale) color: vRow.con.active ? Theme.active : vHov.hovered ? Qt.rgba(1,1,1,0.35) : Qt.rgba(1,1,1,0.18) diff --git a/src/popups/WallpaperPopup.qml b/src/popups/WallpaperPopup.qml index da2b364..d98243a 100644 --- a/src/popups/WallpaperPopup.qml +++ b/src/popups/WallpaperPopup.qml @@ -13,6 +13,8 @@ import "../" PanelWindow { id: root + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + anchors.top: true anchors.left: true anchors.right: true @@ -34,10 +36,10 @@ PanelWindow { } } - readonly property int panelWidth: 980 - readonly property int panelHeight: 420 - readonly property int fw: Theme.notchRadius - readonly property int fh: Theme.notchRadius + readonly property int panelWidth: Math.round(980 * root.localScale) + readonly property int panelHeight: Math.round(420 * root.localScale) + readonly property int fw: Math.round(Theme.notchRadius * root.localScale) + readonly property int fh: Math.round(Theme.notchRadius * root.localScale) property bool windowVisible: false visible: windowVisible @@ -160,10 +162,10 @@ PanelWindow { id: sizer anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom - anchors.bottomMargin: Theme.borderWidth + anchors.bottomMargin: Math.round(Theme.borderWidth * root.localScale) clip: true - width: Popups.wallpaperOpen ? root.panelWidth + 2 * root.fw : Theme.cNotchMinWidth + 2 * root.fw + width: Popups.wallpaperOpen ? root.panelWidth + 2 * root.fw : Math.round(Theme.cNotchMinWidth * root.localScale) + 2 * root.fw height: Popups.wallpaperOpen ? root.panelHeight : 0 Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } @@ -182,7 +184,7 @@ PanelWindow { anchors.fill: parent attachedEdge: "bottom" color: Theme.background - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * root.localScale) flareWidth: root.fw flareHeight: root.fh } @@ -192,10 +194,10 @@ PanelWindow { focus: true anchors { fill: parent - topMargin: 16 - bottomMargin: root.fh + 8 - leftMargin: root.fw + 16 - rightMargin: root.fw + 16 + topMargin: Math.round(16 * root.localScale) + bottomMargin: root.fh + Math.round(8 * root.localScale) + leftMargin: root.fw + Math.round(16 * root.localScale) + rightMargin: root.fw + Math.round(16 * root.localScale) } property string searchQuery: "" @@ -218,7 +220,7 @@ PanelWindow { opacity: Popups.wallpaperOpen ? 1 : 0 transform: Translate { - y: Popups.wallpaperOpen ? 0 : 40 + y: Popups.wallpaperOpen ? 0 : Math.round(40 * root.localScale) Behavior on y { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.OutExpo } } } Behavior on opacity { @@ -239,16 +241,16 @@ PanelWindow { anchors.left: parent.left anchors.right: parent.right anchors.bottom: divider.top - anchors.bottomMargin: 8 + anchors.bottomMargin: Math.round(8 * localScale) orientation: ListView.Horizontal - spacing: 14 + spacing: Math.round(14 * localScale) clip: true boundsBehavior: Flickable.StopAtBounds interactive: false ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AsNeeded - height: 6 + height: Math.round(6 * localScale) } model: content.filteredWallpapers @@ -257,7 +259,7 @@ PanelWindow { visible: wallGrid.count === 0 text: "No wallpapers found in " + WallpaperService.wallpaperDir color: Qt.rgba(1,1,1,0.25) - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) } delegate: Item { @@ -266,10 +268,10 @@ PanelWindow { required property int index property bool isPreview: WallpaperService.previewWall === modelData property bool isCurrent: WallpaperService.currentWall === modelData - readonly property int labelH: 30 + readonly property int labelH: Math.round(30 * localScale) - width: isPreview ? (130 * 1.2) : 130 - height: isPreview ? wallGrid.height : wallGrid.height - 14 + width: isPreview ? Math.round(130 * 1.2 * localScale) : Math.round(130 * localScale) + height: isPreview ? wallGrid.height : wallGrid.height - Math.round(14 * localScale) Behavior on width { NumberAnimation { duration: 120; easing.type: Easing.InOutCubic } } Item { @@ -299,10 +301,10 @@ PanelWindow { Text { anchors.centerIn: parent - width: parent.width - 10 + width: parent.width - Math.round(10 * localScale) text: modelData.split("/").pop().replace(/\.[^/.]+$/, "") color: isPreview ? Theme.active : Qt.rgba(1,1,1,0.65) - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) font.weight: isPreview ? Font.Medium : Font.Normal elide: Text.ElideRight horizontalAlignment: Text.AlignHCenter @@ -313,7 +315,7 @@ PanelWindow { Rectangle { id: cardMask anchors.fill: parent - radius: 10 + radius: Math.round(10 * localScale) visible: false layer.enabled: true } @@ -329,9 +331,9 @@ PanelWindow { Rectangle { anchors.fill: parent - radius: 10 + radius: Math.round(10 * localScale) color: "transparent" - border.width: isPreview ? 2 : 1 + border.width: isPreview ? Math.round(2 * localScale) : Math.round(1 * localScale) border.color: isPreview ? Theme.active : isCurrent ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.45) : Qt.rgba(1,1,1,0.15) @@ -361,7 +363,7 @@ PanelWindow { anchors.left: parent.left anchors.right: parent.right anchors.bottom: divider.top - anchors.bottomMargin: 8 + anchors.bottomMargin: Math.round(8 * root.localScale) z: wallGrid.z + 1 acceptedButtons: Qt.NoButton onWheel: function(wheel) { @@ -374,7 +376,7 @@ PanelWindow { Rectangle { id: divider anchors.bottom: utilBar.top - anchors.bottomMargin: 8 + anchors.bottomMargin: Math.round(8 * root.localScale) anchors.left: parent.left anchors.right: parent.right height: 1 @@ -384,20 +386,21 @@ PanelWindow { Item { id: utilBar anchors.bottom: parent.bottom - anchors.bottomMargin: -20 + anchors.bottomMargin: Math.round((Theme.notchRadius - 12) * root.localScale) anchors.left: parent.left anchors.right: parent.right - height: 32 + height: Math.round(32 * localScale) Row { - anchors.centerIn: parent - spacing: 8 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + spacing: Math.round(8 * localScale) Rectangle { id: folderBtn - width: 32 - height: 32 - radius: 8 + width: Math.round(32 * root.localScale) + height: Math.round(32 * root.localScale) + radius: Math.round(8 * root.localScale) color: folderBtnMA.containsMouse ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : (content.folderMode ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : Qt.rgba(1,1,1,0.04)) @@ -408,7 +411,7 @@ PanelWindow { Behavior on color { ColorAnimation { duration: 100 } } Behavior on border.color { ColorAnimation { duration: 100 } } Text { - anchors.centerIn: parent; text: "󰉋"; font.pixelSize: 15 + anchors.centerIn: parent; text: "󰉋"; font.pixelSize: Math.round(15 * root.localScale) color: (content.folderMode || folderBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.5) Behavior on color { ColorAnimation { duration: 100 } } } @@ -433,9 +436,9 @@ PanelWindow { Rectangle { id: filterBox - width: 300 - height: 32 - radius: 8 + width: Math.round(300 * root.localScale) + height: Math.round(32 * root.localScale) + radius: Math.round(8 * root.localScale) color: filterBoxMA.containsMouse ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.06) border.color: (searchInput.activeFocus || dirInput.activeFocus) ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) @@ -453,15 +456,15 @@ PanelWindow { Item { anchors.fill: parent - anchors.leftMargin: 10 - anchors.rightMargin: 10 + anchors.leftMargin: Math.round(10 * root.localScale) + anchors.rightMargin: Math.round(10 * root.localScale) visible: !content.folderMode Text { anchors.verticalCenter: parent.verticalCenter text: "Search wallpapers…" color: (searchInput.activeFocus || filterBoxMA.containsMouse) ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7) : Qt.rgba(1,1,1,0.28) - font.pixelSize: 12; visible: searchInput.text === "" + font.pixelSize: Math.round(12 * root.localScale); visible: searchInput.text === "" } TextInput { @@ -469,7 +472,7 @@ PanelWindow { anchors.fill: parent verticalAlignment: TextInput.AlignVCenter color: Theme.text - font.pixelSize: 12 + font.pixelSize: Math.round(12 * root.localScale) selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) clip: true onTextChanged: content.searchQuery = text @@ -520,8 +523,8 @@ PanelWindow { Item { anchors.fill: parent - anchors.leftMargin: 10 - anchors.rightMargin: 10 + anchors.leftMargin: Math.round(10 * root.localScale) + anchors.rightMargin: Math.round(10 * root.localScale) visible: content.folderMode Text { @@ -530,7 +533,7 @@ PanelWindow { anchors.verticalCenter: parent.verticalCenter text: "Path: " color: (dirInput.activeFocus || filterBoxMA.containsMouse) ? Theme.active : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7) - font.pixelSize: 11 + font.pixelSize: Math.round(11 * root.localScale) } TextInput { @@ -541,7 +544,7 @@ PanelWindow { anchors.bottom: parent.bottom verticalAlignment: TextInput.AlignVCenter color: Theme.text - font.pixelSize: 12 + font.pixelSize: Math.round(12 * root.localScale) font.family: "JetBrains Mono" selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) clip: true @@ -562,8 +565,8 @@ PanelWindow { Rectangle { id: schemeBtn width: schemeBtnRow.implicitWidth + 20 - height: 32 - radius: 8 + height: Math.round(32 * root.localScale) + radius: Math.round(8 * root.localScale) color: schemeBtnMA.containsMouse ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : (content.schemePopupOpen ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : Qt.rgba(1,1,1,0.04)) @@ -575,24 +578,24 @@ PanelWindow { Behavior on border.color { ColorAnimation { duration: 100 } } Row { - id: schemeBtnRow; anchors.centerIn: parent; spacing: 7 + id: schemeBtnRow; anchors.centerIn: parent; spacing: Math.round(7 * localScale) Text { text: "󰏘" - font.pixelSize: 14 + font.pixelSize: Math.round(14 * localScale) color: (content.schemePopupOpen || schemeBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.55) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } } Text { text: WallpaperService.scheme - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: (content.schemePopupOpen || schemeBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.7) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } } Text { text: content.schemePopupOpen ? "▴" : "▾" - font.pixelSize: 8 + font.pixelSize: Math.round(8 * localScale) color: (content.schemePopupOpen || schemeBtnMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.35) anchors.verticalCenter: parent.verticalCenter } @@ -613,9 +616,9 @@ PanelWindow { anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter property bool active: content.applyActive - width: active ? 90 : 0 - height: 32 - radius: 8 + width: active ? Math.round(90 * localScale) : 0 + height: Math.round(32 * localScale) + radius: Math.round(8 * localScale) opacity: active ? 1 : 0 clip: true color: applyBtnMA.containsMouse @@ -632,7 +635,7 @@ PanelWindow { Text { anchors.centerIn: parent text: WallpaperService.applying ? "…" : "Apply" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) font.weight: Font.Medium color: Theme.active opacity: applyBtn.active ? 1 : 0 @@ -667,9 +670,9 @@ PanelWindow { visible: content.schemePopupOpen clip: false - width: schemeDropdownCol.implicitWidth + 32 - height: schemeDropdownCol.implicitHeight + 16 - radius: Theme.cornerRadius + width: schemeDropdownCol.implicitWidth + Math.round(32 * root.localScale) + height: schemeDropdownCol.implicitHeight + Math.round(16 * root.localScale) + radius: Math.round(Theme.cornerRadius * root.localScale) color: Theme.background border.color: Theme.active @@ -681,8 +684,8 @@ PanelWindow { onVisibleChanged: { if (visible) { var pos = schemeBtn.mapToItem(sizer, 0, 0) - x = Math.min(pos.x, sizer.width - width - 4) - y = pos.y - height - 6 + x = Math.min(pos.x, sizer.width - width - Math.round(4 * root.localScale)) + y = pos.y - height - Math.round(6 * root.localScale) } } @@ -694,7 +697,7 @@ PanelWindow { ColumnLayout { id: schemeDropdownCol anchors.centerIn: parent - spacing: 4 + spacing: Math.round(4 * root.localScale) Repeater { model: WallpaperService.schemes @@ -705,10 +708,10 @@ PanelWindow { Layout.fillWidth: true // Pad minimumWidth to ensure space between text and rectangle edges - Layout.minimumWidth: schemeItemText.implicitWidth + 40 - Layout.preferredHeight: 32 + Layout.minimumWidth: schemeItemText.implicitWidth + Math.round(40 * root.localScale) + Layout.preferredHeight: Math.round(32 * root.localScale) - radius: 8 + radius: Math.round(8 * root.localScale) color: schemeItemMA.containsMouse ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : (sel ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : "transparent") @@ -724,19 +727,19 @@ PanelWindow { Row { anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: 12 - spacing: 10 + anchors.leftMargin: Math.round(12 * root.localScale) + spacing: Math.round(10 * root.localScale) Text { text: sel ? "●" : "○" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * root.localScale) color: (sel || schemeItemMA.containsMouse) ? Theme.active : Qt.rgba(1,1,1,0.3) anchors.verticalCenter: parent.verticalCenter } Text { id: schemeItemText text: modelData - font.pixelSize: 13 + font.pixelSize: Math.round(13 * root.localScale) color: (sel || schemeItemMA.containsMouse) ? Theme.text : Qt.rgba(1,1,1,0.65) anchors.verticalCenter: parent.verticalCenter } diff --git a/src/popups/WifiTab.qml b/src/popups/WifiTab.qml index bde08cd..a98b527 100644 --- a/src/popups/WifiTab.qml +++ b/src/popups/WifiTab.qml @@ -10,6 +10,7 @@ import "../components" Item { id: root + property real localScale: 1.0 property var _networks: [] property var _needsPassword: ({}) property bool _scanning: false @@ -221,7 +222,7 @@ Item { component ScanRings: Item { id: ringsRoot property string centerGlyph: "󰤨" - property int glyphSize: 18 + property int glyphSize: Math.round(18 * localScale) Repeater { model: 4 delegate: Rectangle { @@ -230,7 +231,7 @@ Item { width: ringsRoot.width; height: ringsRoot.width; radius: ringsRoot.width / 2 color: "transparent" border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.80) - border.width: 1.5; opacity: 0; scale: 0.08 + border.width: Math.max(1, Math.round(1.5 * localScale)); opacity: 0; scale: 0.08 SequentialAnimation { running: root._scanning; loops: Animation.Infinite PauseAnimation { duration: index * 650 } @@ -255,14 +256,14 @@ Item { component SignalBars: Item { id: barsRoot required property int signal - width: 18; height: 14 + width: Math.round(18 * localScale); height: Math.round(14 * localScale) Row { - anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; spacing: 2 + anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; spacing: Math.round(2 * localScale) Repeater { model: 4 delegate: Rectangle { required property int index - width: 3; height: 4 + index * 3; radius: 1; anchors.bottom: parent?.bottom + width: Math.round(3 * localScale); height: Math.round((4 + index * 3) * localScale); radius: Math.max(1, Math.round(1 * localScale)); anchors.bottom: parent?.bottom readonly property bool lit: { switch (index) { case 0: return barsRoot.signal > 0 @@ -291,7 +292,7 @@ Item { height: baseRow.height + expandArea.height Rectangle { - anchors.fill: parent; radius: Theme.cornerRadius + anchors.fill: parent; radius: Math.round(Theme.cornerRadius * localScale) color: netRow.isCurrent ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.07) : rHov.hovered ? Qt.rgba(1,1,1,0.04) : "transparent" @@ -300,7 +301,7 @@ Item { : netRow.needsPassword ? Qt.rgba(245/255,196/255,122/255,0.30) : Qt.rgba(1,1,1,0.06) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 130 } } Behavior on border.color { ColorAnimation { duration: 130 } } } @@ -308,42 +309,42 @@ Item { Item { id: baseRow anchors { top: parent.top; left: parent.left; right: parent.right } - height: 48 + height: Math.round(48 * localScale) Column { - anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter } - spacing: 3 + anchors { left: parent.left; leftMargin: Math.round(12 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(3 * localScale) Text { - text: netRow.net.ssid; font.pixelSize: 13 + text: netRow.net.ssid; font.pixelSize: Math.round(13 * localScale) font.weight: netRow.isCurrent ? Font.Medium : Font.Normal color: netRow.isCurrent ? Theme.text : Qt.rgba(1,1,1,0.7) - width: 170; elide: Text.ElideRight + width: Math.round(170 * localScale); elide: Text.ElideRight } Text { visible: netRow.needsPassword && !netRow.isCurrent - text: "Password required"; font.pixelSize: 10 + text: "Password required"; font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(245/255,196/255,122/255,0.80) } - Text { visible: netRow.isCurrent; text: "Connected"; font.pixelSize: 10; color: Theme.active } + Text { visible: netRow.isCurrent; text: "Connected"; font.pixelSize: Math.round(10 * localScale); color: Theme.active } } Row { - anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter } - spacing: 6 + anchors { right: parent.right; rightMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(6 * localScale) Text { visible: netRow.net.secured && !netRow.isCurrent - text: "󰌾"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.28) + text: "󰌾"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.28) anchors.verticalCenter: parent.verticalCenter } Item { - width: 22; height: 16; anchors.verticalCenter: parent.verticalCenter + width: Math.round(22 * localScale); height: Math.round(16 * localScale); anchors.verticalCenter: parent.verticalCenter SignalBars { anchors.centerIn: parent; signal: netRow.net.signal } } Item { - visible: netRow.isConnecting; width: 20; height: 20; anchors.verticalCenter: parent.verticalCenter + visible: netRow.isConnecting; width: Math.round(20 * localScale); height: Math.round(20 * localScale); anchors.verticalCenter: parent.verticalCenter Text { - anchors.centerIn: parent; text: "○"; font.pixelSize: 14; color: Theme.active + anchors.centerIn: parent; text: "○"; font.pixelSize: Math.round(14 * localScale); color: Theme.active SequentialAnimation on opacity { running: netRow.isConnecting; loops: Animation.Infinite NumberAnimation { to: 0.2; duration: 500 } @@ -353,21 +354,21 @@ Item { } // Disconnect Item { - visible: netRow.isCurrent; width: 28; height: 28; anchors.verticalCenter: parent.verticalCenter - Rectangle { anchors.fill: parent; radius: 6; color: dH.hovered ? Qt.rgba(1,1,1,0.10) : "transparent"; Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰖪"; font.pixelSize: 14; color: dH.hovered ? Qt.rgba(1,1,1,0.65) : Qt.rgba(1,1,1,0.35); Behavior on color { ColorAnimation { duration: 100 } } } + visible: netRow.isCurrent; width: Math.round(28 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent.verticalCenter + Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: dH.hovered ? Qt.rgba(1,1,1,0.10) : "transparent"; Behavior on color { ColorAnimation { duration: 100 } } } + Text { anchors.centerIn: parent; text: "󰖪"; font.pixelSize: Math.round(14 * localScale); color: dH.hovered ? Qt.rgba(1,1,1,0.65) : Qt.rgba(1,1,1,0.35); Behavior on color { ColorAnimation { duration: 100 } } } HoverHandler { id: dH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._disconnect() } } // Forget Item { - visible: netRow.isCurrent; width: 28; height: 28; anchors.verticalCenter: parent.verticalCenter + visible: netRow.isCurrent; width: Math.round(28 * localScale); height: Math.round(28 * localScale); anchors.verticalCenter: parent.verticalCenter Rectangle { - anchors.fill: parent; radius: 6 + anchors.fill: parent; radius: Math.round(6 * localScale) color: fH.hovered ? Qt.rgba(248/255,113/255,113/255,0.15) : netRow.isForgetPending ? Qt.rgba(248/255,113/255,113/255,0.10) : "transparent" Behavior on color { ColorAnimation { duration: 100 } } } - Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: 13; color: (fH.hovered || netRow.isForgetPending) ? "#f87171" : Qt.rgba(1,1,1,0.3); Behavior on color { ColorAnimation { duration: 100 } } } + Text { anchors.centerIn: parent; text: "󰗼"; font.pixelSize: Math.round(13 * localScale); color: (fH.hovered || netRow.isForgetPending) ? "#f87171" : Qt.rgba(1,1,1,0.3); Behavior on color { ColorAnimation { duration: 100 } } } HoverHandler { id: fH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._forgetSsid = netRow.isForgetPending ? "" : netRow.net.ssid } } @@ -375,11 +376,11 @@ Item { Rectangle { visible: !netRow.isCurrent && !netRow.isConnecting anchors.verticalCenter: parent.verticalCenter - width: connectLbl.implicitWidth + 20; height: 28; radius: 8 + width: connectLbl.implicitWidth + Math.round(20 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: conH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.09) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 100 } } - Text { id: connectLbl; anchors.centerIn: parent; text: netRow.isExpanded ? "Retry" : "Connect"; font.pixelSize: 11; font.weight: Font.Medium; color: Theme.active } + Text { id: connectLbl; anchors.centerIn: parent; text: netRow.isExpanded ? "Retry" : "Connect"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: conH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -399,35 +400,35 @@ Item { id: expandArea anchors { top: baseRow.bottom; left: parent.left; right: parent.right } clip: true - height: netRow.isForgetPending ? forgetRow.implicitHeight + 16 : netRow.isExpanded ? passRow.implicitHeight + 16 : 0 + height: netRow.isForgetPending ? forgetRow.implicitHeight + Math.round(16 * localScale) : netRow.isExpanded ? passRow.implicitHeight + Math.round(16 * localScale) : 0 Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } } Item { id: forgetRow - anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 8 } - implicitHeight: 32 + anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(8 * localScale) } + implicitHeight: Math.round(32 * localScale) opacity: netRow.isForgetPending ? 1 : 0 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: 150 } } Rectangle { - anchors { fill: parent; leftMargin: 10; rightMargin: 10 } - radius: 8; color: Qt.rgba(248/255,113/255,113/255,0.07) - border.color: Qt.rgba(248/255,113/255,113/255,0.22); border.width: 1 + anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } + radius: Math.round(8 * localScale); color: Qt.rgba(248/255,113/255,113/255,0.07) + border.color: Qt.rgba(248/255,113/255,113/255,0.22); border.width: Math.max(1, Math.round(1 * localScale)) Row { - anchors.centerIn: parent; spacing: 12 - Text { anchors.verticalCenter: parent.verticalCenter; text: "Forget this network?"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.55) } + anchors.centerIn: parent; spacing: Math.round(12 * localScale) + Text { anchors.verticalCenter: parent.verticalCenter; text: "Forget this network?"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.55) } Rectangle { - width: 54; height: 24; radius: 6; color: cfH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04) + width: Math.round(54 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale); color: cfH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.04) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: 10; color: Qt.rgba(1,1,1,0.45) } + Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1,0.45) } HoverHandler { id: cfH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._forgetSsid = "" } } Rectangle { - width: 54; height: 24; radius: 6 + width: Math.round(54 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale) color: ffH.hovered ? Qt.rgba(248/255,113/255,113/255,0.35) : Qt.rgba(248/255,113/255,113/255,0.18) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Forget"; font.pixelSize: 10; font.weight: Font.Medium; color: "#f87171" } + Text { anchors.centerIn: parent; text: "Forget"; font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium; color: "#f87171" } HoverHandler { id: ffH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._forget(netRow.net.ssid) } } @@ -437,26 +438,26 @@ Item { Item { id: passRow - anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 8 } - implicitHeight: 40 + anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(8 * localScale) } + implicitHeight: Math.round(40 * localScale) opacity: netRow.isExpanded ? 1 : 0 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: 150 } } Row { - anchors { fill: parent; leftMargin: 10; rightMargin: 10 } - spacing: 8 + anchors { fill: parent; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale) } + spacing: Math.round(8 * localScale) Rectangle { - width: parent.width - parent.spacing; height: 32; radius: 8 + width: parent.width - parent.spacing; height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.06) border.color: passInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) : Qt.rgba(1,1,1,0.12) - border.width: 1; Behavior on border.color { ColorAnimation { duration: 120 } } - Text { anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } - text: "Password…"; font.pixelSize: 12; color: Qt.rgba(1,1,1,0.22); visible: passInput.text === "" } + border.width: Math.max(1, Math.round(1 * localScale)); Behavior on border.color { ColorAnimation { duration: 120 } } + Text { anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + text: "Password…"; font.pixelSize: Math.round(12 * localScale); color: Qt.rgba(1,1,1,0.22); visible: passInput.text === "" } TextInput { id: passInput // Updated anchors to make room for the eye button - anchors { left: parent.left; leftMargin: 10; right: eyeBtn.left; rightMargin: 6; top: parent.top; bottom: parent.bottom } - verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: 12 + anchors { left: parent.left; leftMargin: Math.round(10 * localScale); right: eyeBtn.left; rightMargin: Math.round(6 * localScale); top: parent.top; bottom: parent.bottom } + verticalAlignment: TextInput.AlignVCenter; color: Theme.text; font.pixelSize: Math.round(12 * localScale) // Toggle echoMode based on state echoMode: netRow._showPass ? TextInput.Normal : TextInput.Password selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35); clip: true @@ -467,12 +468,12 @@ Item { Item { id: eyeBtn anchors { right: parent.right; verticalCenter: parent.verticalCenter } - width: 28; height: 28 - Rectangle { anchors.fill: parent; radius: 6; color: eyeH.hovered ? Qt.rgba(1,1,1,0.08) : "transparent" } + width: Math.round(28 * localScale); height: Math.round(28 * localScale) + Rectangle { anchors.fill: parent; radius: Math.round(6 * localScale); color: eyeH.hovered ? Qt.rgba(1,1,1,0.08) : "transparent" } Text { anchors.centerIn: parent text: netRow._showPass ? "" : "" - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) color: netRow._showPass ? Theme.active : Qt.rgba(1,1,1,0.28) } HoverHandler { id: eyeH; cursorShape: Qt.PointingHandCursor } @@ -498,41 +499,41 @@ Item { anchors.fill: parent; spacing: 0 Item { - width: parent.width; height: 40 - Text { anchors { left: parent.left; leftMargin: 2; verticalCenter: parent.verticalCenter } - text: "Wi-Fi"; font.pixelSize: 15; font.weight: Font.Bold; color: Theme.text } + width: parent.width; height: Math.round(40 * localScale) + Text { anchors { left: parent.left; leftMargin: Math.round(2 * localScale); verticalCenter: parent.verticalCenter } + text: "Wi-Fi"; font.pixelSize: Math.round(15 * localScale); font.weight: Font.Bold; color: Theme.text } Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - spacing: 8 + spacing: Math.round(8 * localScale) Rectangle { - width: 32; height: 32; radius: 8 + width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: wfPwrH.hovered ? (root._wifiEnabled ? Qt.rgba(248/255,113/255,113/255,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18)) : Qt.rgba(1,1,1,0.04) border.color: root._wifiEnabled ? Qt.rgba(1,1,1,0.10) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) - border.width: 1 + border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } Behavior on border.color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: 14; color: root._wifiEnabled ? (wfPwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: 120 } } } + Text { anchors.centerIn: parent; text: "⏻"; font.pixelSize: Math.round(14 * localScale); color: root._wifiEnabled ? (wfPwrH.hovered ? "#f87171" : Qt.rgba(1,1,1,0.32)) : Theme.active; Behavior on color { ColorAnimation { duration: 120 } } } HoverHandler { id: wfPwrH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._setWifiEnabled(!root._wifiEnabled) } } Rectangle { - width: 32; height: 32; radius: 8 + width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: settH.hovered ? Qt.rgba(1,1,1,0.09) : Qt.rgba(1,1,1,0.03) - border.color: Qt.rgba(1,1,1,0.10); border.width: 1; Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: 14; color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: 100 } } } + border.color: Qt.rgba(1,1,1,0.10); border.width: Math.max(1, Math.round(1 * localScale)); Behavior on color { ColorAnimation { duration: 100 } } + Text { anchors.centerIn: parent; text: "󰒓"; font.pixelSize: Math.round(14 * localScale); color: settH.hovered ? Qt.rgba(1,1,1,0.75) : Qt.rgba(1,1,1,0.30); Behavior on color { ColorAnimation { duration: 100 } } } HoverHandler { id: settH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: { nmtuiProc.running = false; nmtuiProc.running = true } } } Rectangle { - width: 32; height: 32; radius: 8 + width: Math.round(32 * localScale); height: Math.round(32 * localScale); radius: Math.round(8 * localScale) color: rfH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.05) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.28); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } Text { - id: rfIcon; anchors.centerIn: parent; text: "󰑐"; font.pixelSize: 15 + id: rfIcon; anchors.centerIn: parent; text: "󰑐"; font.pixelSize: Math.round(15 * localScale) color: root._scanning ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.4) : (root._wifiEnabled ? Theme.active : Qt.rgba(1,1,1,0.18)) Behavior on color { ColorAnimation { duration: 150 } } RotationAnimator { target: rfIcon; from: 0; to: 360; duration: 900; loops: Animation.Infinite; running: root._scanning; easing.type: Easing.Linear } @@ -544,47 +545,48 @@ Item { } Rectangle { width: parent.width; height: 1; color: Qt.rgba(1,1,1,0.07) } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } Flickable { - id: flick; width: parent.width; height: parent.height - 49 + id: flick; width: parent.width; height: parent.height - Math.round(49 * localScale) contentWidth: width; contentHeight: contentCol.height; clip: true; boundsBehavior: Flickable.StopAtBounds Column { - id: contentCol; width: flick.width; height: implicitHeight; spacing: 4 + id: contentCol; width: flick.width; height: implicitHeight; spacing: Math.round(4 * localScale) - Item { width: parent.width; height: visible ? sLbl1.implicitHeight + 4 : 0; visible: root._current !== null - Text { id: sLbl1; text: "CONNECTED"; font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } + Item { width: parent.width; height: visible ? sLbl1.implicitHeight + Math.round(4 * localScale) : 0; visible: root._current !== null + Text { id: sLbl1; text: "CONNECTED"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } - NetworkRow { visible: root._current !== null; width: parent.width - 2; x: 1; net: root._current ?? { ssid: "", signal: 0, secured: false, inUse: true }; isCurrent: true } + NetworkRow { visible: root._current !== null; width: parent.width - Math.round(2 * localScale); x: Math.round(1 * localScale); net: root._current ?? { ssid: "", signal: 0, secured: false, inUse: true }; isCurrent: true } - Item { width: parent.width; height: 10; visible: root._current !== null && root._available.length > 0 } + Item { width: parent.width; height: Math.round(10 * localScale); visible: root._current !== null && root._available.length > 0 } - Item { width: parent.width; height: visible ? sLbl2.implicitHeight + 4 : 0; visible: root._available.length > 0 - Text { id: sLbl2; text: "AVAILABLE"; font.pixelSize: 9; font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(1,1,1,0.25) } } + Item { width: parent.width; height: visible ? sLbl2.implicitHeight + Math.round(4 * localScale) : 0; visible: root._available.length > 0 + Text { id: sLbl2; text: "AVAILABLE"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; font.letterSpacing: 1.2; color: Qt.rgba(1,1,1,0.25) } } Repeater { model: root._available - delegate: NetworkRow { required property var modelData; width: contentCol.width - 2; x: 1; net: modelData; isCurrent: false } + delegate: NetworkRow { required property var modelData; width: contentCol.width - Math.round(2 * localScale); x: Math.round(1 * localScale); net: modelData; isCurrent: false } } + // Empty state Item { - width: parent.width; height: 160 + width: parent.width; height: Math.round(160 * localScale) visible: !root._scanning && root._networks.length === 0 && root._wifiEnabled - Column { anchors.centerIn: parent; spacing: 10 - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰤭"; font.pixelSize: 34; color: Qt.rgba(1,1,1,0.08) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "No networks found"; font.pixelSize: 12; color: Qt.rgba(1,1,1,0.2) } } + Column { anchors.centerIn: parent; spacing: Math.round(10 * localScale) + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰤭"; font.pixelSize: Math.round(34 * localScale); color: Qt.rgba(1,1,1,0.08) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "No networks found"; font.pixelSize: Math.round(12 * localScale); color: Qt.rgba(1,1,1,0.2) } } } Item { - width: parent.width; height: 160 + width: parent.width; height: Math.round(160 * localScale) visible: root._scanning && root._networks.length === 0 - ScanRings { anchors { horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: 12 } - width: 96; height: 96; centerGlyph: "󰤨"; glyphSize: 18 } - Text { anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: 8 } - text: "Scanning…"; font.pixelSize: 11; color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } + ScanRings { anchors { horizontalCenter: parent.horizontalCenter; top: parent.top; topMargin: Math.round(12 * localScale) } + width: Math.round(96 * localScale); height: Math.round(96 * localScale); centerGlyph: "󰤨"; glyphSize: Math.round(18 * localScale) } + Text { anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom; bottomMargin: Math.round(8 * localScale) } + text: "Scanning…"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.5) } } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } } } } @@ -593,7 +595,7 @@ Item { Item { anchors { fill: parent - topMargin: 49 // below header 40 + divider 1 + gap 8 + topMargin: Math.round(49 * localScale) // below header 40 + divider 1 + gap 8 } visible: !root._wifiEnabled z: 2 @@ -601,18 +603,18 @@ Item { Rectangle { anchors.fill: parent; color: Qt.rgba(Theme.background.r, Theme.background.g, Theme.background.b, 0.95) } Column { - anchors.centerIn: parent; spacing: 16 - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰤭"; font.pixelSize: 42; color: Qt.rgba(1,1,1,0.12) } - Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Wi-Fi is off"; font.pixelSize: 14; font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.30) } + anchors.centerIn: parent; spacing: Math.round(16 * localScale) + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "󰤭"; font.pixelSize: Math.round(42 * localScale); color: Qt.rgba(1,1,1,0.12) } + Text { anchors.horizontalCenter: parent.horizontalCenter; text: "Wi-Fi is off"; font.pixelSize: Math.round(14 * localScale); font.weight: Font.Medium; color: Qt.rgba(1,1,1,0.30) } Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: wfEnRow.implicitWidth + 24; height: 34; radius: 17 + width: wfEnRow.implicitWidth + Math.round(24 * localScale); height: Math.round(34 * localScale); radius: Math.round(17 * localScale) color: wfEnH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) - border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: 1 + border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40); border.width: Math.max(1, Math.round(1 * localScale)) Behavior on color { ColorAnimation { duration: 120 } } - Row { id: wfEnRow; anchors.centerIn: parent; spacing: 8 - Text { anchors.verticalCenter: parent.verticalCenter; text: "󰤨"; font.pixelSize: 14; color: Theme.active } - Text { anchors.verticalCenter: parent.verticalCenter; text: "Turn On"; font.pixelSize: 12; font.weight: Font.Medium; color: Theme.active } + Row { id: wfEnRow; anchors.centerIn: parent; spacing: Math.round(8 * localScale) + Text { anchors.verticalCenter: parent.verticalCenter; text: "󰤨"; font.pixelSize: Math.round(14 * localScale); color: Theme.active } + Text { anchors.verticalCenter: parent.verticalCenter; text: "Turn On"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium; color: Theme.active } } HoverHandler { id: wfEnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._setWifiEnabled(true) } diff --git a/src/services/AppLauncher.qml b/src/services/AppLauncher.qml index 9918ea3..d930a8f 100644 --- a/src/services/AppLauncher.qml +++ b/src/services/AppLauncher.qml @@ -6,6 +6,8 @@ import "../" Item { id: root + property real localScale: 1.0 + // ── State ───────────────────────────────────────────────────────────────── property bool loading: true property int selIndex: -1 @@ -57,7 +59,7 @@ Item { // ── Layout ──────────────────────────────────────────────────────────────── Column { anchors.fill: parent - spacing: 8 + spacing: Math.round(8 * localScale) // App list container Item { @@ -67,12 +69,12 @@ Item { // Loading state Column { anchors.centerIn: parent - spacing: 12 + spacing: Math.round(12 * localScale) visible: root.loading Text { anchors.horizontalCenter: parent.horizontalCenter - text: "󰣪"; font.pixelSize: 32 + text: "󰣪"; font.pixelSize: Math.round(32 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.3) RotationAnimation on rotation { @@ -86,27 +88,27 @@ Item { anchors.horizontalCenter: parent.horizontalCenter text: "Initializing..." color: Qt.rgba(1,1,1,0.25) - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) } } // Empty / no results state Column { anchors.centerIn: parent - spacing: 10 + spacing: Math.round(10 * localScale) visible: !root.loading && root.filtered.length === 0 Text { anchors.horizontalCenter: parent.horizontalCenter text: root.query !== "" ? "󰩄" : "󱗃" - font.pixelSize: 28 + font.pixelSize: Math.round(28 * localScale) color: Qt.rgba(1,1,1,0.18) } Text { anchors.horizontalCenter: parent.horizontalCenter text: root.query !== "" ? "No results" : "No apps found" color: Qt.rgba(1,1,1,0.25) - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) } } @@ -120,15 +122,15 @@ Item { model: root.filtered clip: true - spacing: 3 + spacing: Math.round(3 * localScale) boundsBehavior: Flickable.StopAtBounds ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded contentItem: Rectangle { - implicitWidth: 3 - implicitHeight: 40 - radius: 1.5 + implicitWidth: Math.round(3 * localScale) + implicitHeight: Math.round(40 * localScale) + radius: width / 2 color: Qt.rgba(1, 1, 1, 0.22) } background: Item {} @@ -138,9 +140,9 @@ Item { required property var modelData required property int index - width: appList.width - 8 - height: 46 - radius: 9 + width: appList.width - Math.round(8 * localScale) + height: Math.round(46 * localScale) + radius: Math.round(9 * localScale) readonly property bool isSel: root.selIndex === index @@ -157,15 +159,15 @@ Item { Row { anchors { - left: parent.left; leftMargin: 12 - right: parent.right; rightMargin: 12 + left: parent.left; leftMargin: Math.round(12 * localScale) + right: parent.right; rightMargin: Math.round(12 * localScale) verticalCenter: parent.verticalCenter } - spacing: 12 + spacing: Math.round(12 * localScale) // App icon Item { - width: 28; height: 28 + width: Math.round(28 * localScale); height: Math.round(28 * localScale) anchors.verticalCenter: parent.verticalCenter Loader { @@ -184,8 +186,8 @@ Item { } fillMode: Image.PreserveAspectFit smooth: true - sourceSize.width: 28 - sourceSize.height: 28 + sourceSize.width: Math.round(28 * localScale) + sourceSize.height: Math.round(28 * localScale) onStatusChanged: { if (status === Image.Error || status === Image.Null) { @@ -198,14 +200,14 @@ Item { // Tier 2 Fallback: Nerd Font Icon Rectangle { anchors.fill: parent - radius: 7 + radius: Math.round(7 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) visible: !iconLoader.active || (iconLoader.item && iconLoader.item.status !== Image.Ready) Text { anchors.centerIn: parent text: "󰀻" // Generic Nerd Font App Grid Icon - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: Theme.active } } @@ -213,10 +215,10 @@ Item { // App name Text { - width: parent.width - 28 - parent.spacing + width: parent.width - Math.round(28 * localScale) - parent.spacing anchors.verticalCenter: parent.verticalCenter text: modelData.name - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) color: isSel ? Theme.active : Theme.text elide: Text.ElideRight Behavior on color { ColorAnimation { duration: 100 } } @@ -238,7 +240,7 @@ Item { // Search bar Rectangle { id: searchBar - width: parent.width; height: 44; radius: 12 + width: parent.width; height: Math.round(44 * localScale); radius: Math.round(12 * localScale) color: Qt.rgba(1,1,1,0.06) border.color: searchInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.50) @@ -247,12 +249,12 @@ Item { Behavior on border.color { ColorAnimation { duration: 120 } } Row { - anchors { fill: parent; leftMargin: 14; rightMargin: 14 } - spacing: 10 + anchors { fill: parent; leftMargin: Math.round(14 * localScale); rightMargin: Math.round(14 * localScale) } + spacing: Math.round(10 * localScale) Text { anchors.verticalCenter: parent.verticalCenter - text: "󰍉"; font.pixelSize: 16 + text: "󰍉"; font.pixelSize: Math.round(16 * localScale) color: searchInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7) : Qt.rgba(1,1,1,0.35) @@ -260,7 +262,7 @@ Item { } Item { - width: parent.width - 26 - parent.spacing + width: parent.width - Math.round(26 * localScale) - parent.spacing height: parent.height anchors.verticalCenter: parent.verticalCenter @@ -268,16 +270,16 @@ Item { anchors.verticalCenter: parent.verticalCenter text: "Search apps…" color: Qt.rgba(1,1,1,0.22) - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) visible: searchInput.text === "" } TextInput { id: searchInput - anchors { fill: parent; topMargin: 2; bottomMargin: 2 } + anchors { fill: parent; topMargin: Math.round(2 * localScale); bottomMargin: Math.round(2 * localScale) } verticalAlignment: TextInput.AlignVCenter color: Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) clip: true diff --git a/src/services/AudioControl.qml b/src/services/AudioControl.qml index a65bf19..6d310ad 100644 --- a/src/services/AudioControl.qml +++ b/src/services/AudioControl.qml @@ -6,6 +6,8 @@ import "../" Item { id: root + property real localScale: 1.0 + readonly property var sink: Pipewire.defaultAudioSink readonly property var source: Pipewire.defaultAudioSource @@ -67,6 +69,7 @@ Item { visible: root.page === "output" ChannelColumn { + localScale: root.localScale width: parent.width label: (root.sink && root.sink.ready) ? root.deviceName(root.sink) : "Output" icon: { @@ -95,6 +98,7 @@ Item { visible: root.page === "input" ChannelColumn { + localScale: root.localScale width: parent.width label: (root.source && root.source.ready) ? root.deviceName(root.source) : "Input" icon: (root.source && root.source.audio && root.source.audio.muted) ? "󰍭" : "󰍬" @@ -121,6 +125,7 @@ Item { Repeater { model: root.sinkNodes delegate: DeviceRow { + localScale: root.localScale width: parent.width label: root.deviceName(modelData) isDefault: (root.sink && root.sink.ready && modelData.name === root.sink.name) || false @@ -132,8 +137,8 @@ Item { visible: root.sinkNodes.length === 0 text: "No output devices" color: Qt.rgba(1,1,1,0.2) - font.pixelSize: 11 - leftPadding: 10 + font.pixelSize: Math.round(11 * localScale) + leftPadding: Math.round(10 * localScale) } Rectangle { @@ -141,11 +146,12 @@ Item { color: Qt.rgba(1, 1, 1, 0.06) } - SectionLabel { text: "Input Devices" } + SectionLabel { localScale: root.localScale; text: "Input Devices" } Repeater { model: root.sourceNodes delegate: DeviceRow { + localScale: root.localScale width: parent.width label: root.deviceName(modelData) isDefault: (root.source && root.source.ready && modelData.name === root.source.name) || false @@ -157,8 +163,8 @@ Item { visible: root.sourceNodes.length === 0 text: "No input devices" color: Qt.rgba(1,1,1,0.2) - font.pixelSize: 11 - leftPadding: 10 + font.pixelSize: Math.round(11 * localScale) + leftPadding: Math.round(10 * localScale) } } } @@ -172,8 +178,9 @@ Item { // Tab switcher — right side TabSwitcher { id: switcher + localScale: root.localScale orientation: "vertical" - height: (parent.height - 17) + height: (parent.height - Math.round(17 * localScale)) anchors.verticalCenter: parent.verticalCenter model: [ { key: "output", icon: "󰕾" }, @@ -189,15 +196,16 @@ Item { component ChannelColumn: Item { id: col + property real localScale: 1.0 property string label: "" property string icon: "" property real value: 0.0 property bool muted: false property bool active: false - readonly property int trackHeight: 160 - readonly property int barW: 22 - readonly property int thumbD: barW - 6 + readonly property int trackHeight: Math.round(160 * localScale) + readonly property int barW: Math.round(22 * localScale) + readonly property int thumbD: barW - Math.round(6 * localScale) signal volumeChanged(real value) signal muteToggled() @@ -212,13 +220,13 @@ Item { Column { id: inner anchors.horizontalCenter: parent.horizontalCenter - spacing: 8 + spacing: Math.round(8 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: col.pctText color: col.muted ? Qt.rgba(1,1,1,0.25) : Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) font.bold: true Behavior on color { ColorAnimation { duration: 150 } } } @@ -287,9 +295,9 @@ Item { // Mute button Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: col.barW + 32 - height: 28 - radius: Theme.cornerRadius + width: col.barW + Math.round(32 * localScale) + height: Math.round(28 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: col.muted ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.2) : Qt.rgba(1,1,1,0.06) @@ -297,17 +305,17 @@ Item { Row { anchors.centerIn: parent - spacing: 5 + spacing: Math.round(5 * localScale) Text { text: col.icon - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) color: col.muted ? Theme.active : Qt.rgba(1,1,1,0.55) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 150 } } } Text { text: col.muted ? "Muted" : "Mute" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: col.muted ? Theme.active : Qt.rgba(1,1,1,0.4) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 150 } } @@ -327,11 +335,11 @@ Item { anchors.horizontalCenter: parent.horizontalCenter text: col.label color: Qt.rgba(1,1,1,0.3) - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) font.capitalization: Font.AllUppercase font.letterSpacing: 1 elide: Text.ElideRight - width: col.barW + 60 + width: col.barW + Math.round(60 * localScale) horizontalAlignment: Text.AlignHCenter } } @@ -339,18 +347,20 @@ Item { // ── SectionLabel ────────────────────────────────────────────────────────── component SectionLabel: Text { + property real localScale: 1.0 color: Qt.rgba(1, 1, 1, 0.35) - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) font.capitalization: Font.AllUppercase font.letterSpacing: 0.8 - leftPadding: 4 - topPadding: 2 + leftPadding: Math.round(4 * localScale) + topPadding: Math.round(2 * localScale) } // ── DeviceRow ───────────────────────────────────────────────────────────── component DeviceRow: Item { id: row - implicitHeight: 28 + property real localScale: 1.0 + implicitHeight: Math.round(28 * localScale) property string label: "" property bool isDefault: false @@ -358,7 +368,7 @@ Item { Rectangle { anchors.fill: parent - radius: Theme.cornerRadius - 4 + radius: Math.round((Theme.cornerRadius - 4) * localScale) color: row.isDefault ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) : (rowHov.hovered ? Qt.rgba(1,1,1,0.05) : "transparent") @@ -366,11 +376,11 @@ Item { } Row { - anchors { left: parent.left; leftMargin: 8; right: parent.right; rightMargin: 8; verticalCenter: parent.verticalCenter } - spacing: 6 + anchors { left: parent.left; leftMargin: Math.round(8 * localScale); right: parent.right; rightMargin: Math.round(8 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(6 * localScale) Rectangle { - width: 6; height: 6; radius: 3 + width: Math.round(6 * localScale); height: Math.round(6 * localScale); radius: width / 2 anchors.verticalCenter: parent.verticalCenter color: row.isDefault ? Theme.active : Qt.rgba(1,1,1,0.2) Behavior on color { ColorAnimation { duration: 150 } } @@ -379,9 +389,9 @@ Item { Text { text: row.label color: row.isDefault ? Theme.text : Qt.rgba(1,1,1,0.5) - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) elide: Text.ElideRight - width: parent.width - 14 - parent.spacing + width: parent.width - Math.round(14 * localScale) - parent.spacing anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 150 } } } diff --git a/src/services/BatteryStatus.qml b/src/services/BatteryStatus.qml index 8c747af..f1416c7 100644 --- a/src/services/BatteryStatus.qml +++ b/src/services/BatteryStatus.qml @@ -8,6 +8,7 @@ import "../" Item { id: root + property real localScale: 1.0 property bool showPercentage: false // ── UPower data ────────────────────────────────────────────────────────── @@ -23,7 +24,7 @@ Item { ? bat.state === UPowerDeviceState.FullyCharged : false - implicitWidth: statusRow.implicitWidth + 6 + implicitWidth: statusRow.implicitWidth + Math.round(6 * localScale) implicitHeight: statusRow.implicitHeight // ── Warning tracker ────────────────────────────────────────────────────── @@ -99,14 +100,14 @@ Item { // ── Display ─────────────────────────────────────────────────────────────── Row { id: statusRow - spacing: 4 + spacing: Math.round(4 * localScale) anchors.centerIn: parent Text { id: iconText text: root.icon color: root.iconColor - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) anchors.verticalCenter: parent.verticalCenter // Pulse when critically low and discharging @@ -130,7 +131,7 @@ Item { Item { id: pctWrapper property bool show: root.showPercentage || hov.hovered - implicitWidth: show ? pctText.implicitWidth + 2 : 0 + implicitWidth: show ? pctText.implicitWidth + Math.round(2 * localScale) : 0 implicitHeight: pctText.implicitHeight clip: true anchors.verticalCenter: parent.verticalCenter @@ -140,7 +141,7 @@ Item { id: pctText text: root.pct + "%" color: hov.hovered ? Theme.active : Theme.text - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 120 } } } @@ -152,6 +153,7 @@ Item { // ── Warning window ──────────────────────────────────────────────────────── BatteryWarning { id: warningWindow + // localScale: root.localScale visible: false } } diff --git a/src/services/KanbanBoard.qml b/src/services/KanbanBoard.qml index fb35ecd..0ab5cc8 100644 --- a/src/services/KanbanBoard.qml +++ b/src/services/KanbanBoard.qml @@ -18,6 +18,8 @@ Item { id: root focus: true + property real localScale: 1.0 + // ── Persistent state ────────────────────────────────────────────────────── property var _tasks: [] property int _nextId: 0 @@ -300,8 +302,8 @@ Item { Row { id: mainRow anchors.fill: parent - anchors.topMargin: 8 - spacing: 8 + anchors.topMargin: Math.round(8 * localScale) + spacing: Math.round(8 * localScale) Repeater { model: root.colDefs @@ -323,35 +325,35 @@ Item { height: parent.height Rectangle { - anchors.fill: parent; radius: Theme.cornerRadius + anchors.fill: parent; radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba(1, 1, 1, 0.03) border.color: Qt.rgba(1, 1, 1, 0.07); border.width: 1 } Column { - anchors { fill: parent; margins: 10 } - spacing: 8 + anchors { fill: parent; margins: Math.round(10 * localScale) } + spacing: Math.round(8 * localScale) // Header Item { - width: parent.width; height: 26 + width: parent.width; height: Math.round(26 * localScale) Row { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - spacing: 7 + spacing: Math.round(7 * localScale) Text { anchors.verticalCenter: parent.verticalCenter text: colItem.cLabel; color: Theme.active - font.pixelSize: 12; font.weight: Font.DemiBold + font.pixelSize: Math.round(12 * localScale); font.weight: Font.DemiBold } Rectangle { anchors.verticalCenter: parent.verticalCenter - width: cntT.implicitWidth + 10; height: 16; radius: 8 + width: cntT.implicitWidth + Math.round(10 * localScale); height: Math.round(16 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.12) Text { id: cntT; anchors.centerIn: parent text: colItem.cTasks.length - color: Theme.active; font.pixelSize: 9; font.weight: Font.Bold + color: Theme.active; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold } } } @@ -359,14 +361,14 @@ Item { // Add (+) button Rectangle { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - width: 22; height: 22; radius: 6 + width: Math.round(22 * localScale); height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: addH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) : Qt.rgba(1, 1, 1, 0.05) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.20) border.width: 1 Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "+"; color: Theme.active; font.pixelSize: 15 } + Text { anchors.centerIn: parent; text: "+"; color: Theme.active; font.pixelSize: Math.round(15 * localScale) } HoverHandler { id: addH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -385,37 +387,37 @@ Item { // Content area Item { width: parent.width - height: parent.height - 26 - 1 - parent.spacing * 2 + height: parent.height - Math.round(26 * localScale) - 1 - parent.spacing * 2 // Draft card — slides in from top Item { id: draftWrap; z: 2; width: parent.width - height: colItem.draftOpen ? draftRect.implicitHeight + 6 : 0 + height: colItem.draftOpen ? draftRect.implicitHeight + Math.round(6 * localScale) : 0 clip: true Behavior on height { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } Rectangle { id: draftRect - anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: 3 } - radius: 8 + anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: Math.round(3 * localScale) } + radius: Math.round(8 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.06) border.color: draftInput.activeFocus ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.50) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) border.width: 1 - implicitHeight: draftInput.contentHeight + 24 + implicitHeight: draftInput.contentHeight + Math.round(24 * localScale) Behavior on border.color { ColorAnimation { duration: 100 } } Text { - anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } + anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } visible: draftInput.text === "" - text: "Task title…"; color: Qt.rgba(1,1,1,0.25); font.pixelSize: 12 + text: "Task title…"; color: Qt.rgba(1,1,1,0.25); font.pixelSize: Math.round(12 * localScale) } TextInput { id: draftInput - anchors { left: parent.left; right: parent.right; leftMargin: 10; rightMargin: 10; verticalCenter: parent.verticalCenter } - color: Theme.text; font.pixelSize: 12 + anchors { left: parent.left; right: parent.right; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + color: Theme.text; font.pixelSize: Math.round(12 * localScale) wrapMode: TextInput.WordWrap selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) @@ -438,21 +440,22 @@ Item { anchors.top: draftWrap.bottom anchors.left: parent.left anchors.right: parent.right - anchors.topMargin: colItem.draftOpen ? 4 : 0 - height: parent.height - draftWrap.height - (colItem.draftOpen ? 4 : 0) + anchors.topMargin: colItem.draftOpen ? Math.round(4 * localScale) : 0 + height: parent.height - draftWrap.height - (colItem.draftOpen ? Math.round(4 * localScale) : 0) contentWidth: width - contentHeight: taskCol.implicitHeight + 4 + contentHeight: taskCol.implicitHeight + Math.round(4 * localScale) clip: true boundsBehavior: Flickable.StopAtBounds Column { id: taskCol - width: parent.width; spacing: 6 + width: parent.width; spacing: Math.round(6 * localScale) Repeater { model: colItem.cTasks delegate: TaskCard { required property var modelData + localScale: root.localScale width: parent.width taskData: modelData colIdx: colItem.cIdx @@ -481,9 +484,9 @@ Item { anchors.centerIn: parent visible: root.pickerTaskId >= 0 - width: 230 - height: pickerCol.implicitHeight + 24 - radius: Theme.cornerRadius + width: Math.round(230 * localScale) + height: pickerCol.implicitHeight + Math.round(24 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba( Math.min(1, Theme.background.r + 0.06), Math.min(1, Theme.background.g + 0.06), @@ -495,15 +498,15 @@ Item { Column { id: pickerCol - anchors { left: parent.left; right: parent.right; top: parent.top; margins: 12 } - spacing: 8 + anchors { left: parent.left; right: parent.right; top: parent.top; margins: Math.round(12 * localScale) } + spacing: Math.round(8 * localScale) // ── Month nav ────────────────────────────────────────────────────── Item { - width: parent.width; height: 22 + width: parent.width; height: Math.round(22 * localScale) Text { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - text: "‹"; font.pixelSize: 17 + text: "‹"; font.pixelSize: Math.round(17 * localScale) color: pmH.hovered ? Qt.rgba(1,1,1,0.85) : Qt.rgba(1,1,1,0.30) Behavior on color { ColorAnimation { duration: 80 } } HoverHandler { id: pmH; cursorShape: Qt.PointingHandCursor } @@ -518,11 +521,11 @@ Item { Text { anchors.centerIn: parent text: root._monthNames[root.pickerMonth].substring(0,3) + " " + root.pickerYear - color: Theme.text; font.pixelSize: 11; font.weight: Font.DemiBold + color: Theme.text; font.pixelSize: Math.round(11 * localScale); font.weight: Font.DemiBold } Text { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - text: "›"; font.pixelSize: 17 + text: "›"; font.pixelSize: Math.round(17 * localScale) color: nmH.hovered ? Qt.rgba(1,1,1,0.85) : Qt.rgba(1,1,1,0.30) Behavior on color { ColorAnimation { duration: 80 } } HoverHandler { id: nmH; cursorShape: Qt.PointingHandCursor } @@ -538,7 +541,7 @@ Item { // ── Day-of-week headers ──────────────────────────────────────────── Item { - width: parent.width; height: 14 + width: parent.width; height: Math.round(14 * localScale) Row { anchors.fill: parent Repeater { @@ -546,7 +549,7 @@ Item { delegate: Text { width: Math.floor(parent.parent.width / 7) horizontalAlignment: Text.AlignHCenter - text: modelData; font.pixelSize: 8; font.weight: Font.Bold + text: modelData; font.pixelSize: Math.round(8 * localScale); font.weight: Font.Bold color: Qt.rgba(1,1,1,0.18) } } @@ -558,7 +561,7 @@ Item { id: dayGrid width: parent.width; columns: 7; rows: 6 readonly property real cW: width / 7 - readonly property real cH: 24 + readonly property real cH: Math.round(24 * localScale) Repeater { model: root.pickerDays @@ -590,7 +593,7 @@ Item { Text { anchors.centerIn: parent text: modelData.n - font.pixelSize: 9; font.weight: isSel ? Font.Bold : Font.Normal + font.pixelSize: Math.round(9 * localScale); font.weight: isSel ? Font.Bold : Font.Normal color: isSel ? Theme.background : modelData.cur ? Qt.rgba(1,1,1,0.78) : Qt.rgba(1,1,1,0.14) } @@ -610,81 +613,81 @@ Item { Row { id: timeInner anchors.horizontalCenter: parent.horizontalCenter - spacing: 10 + spacing: Math.round(10 * localScale) Text { anchors.verticalCenter: parent.verticalCenter - text: "⏰"; font.pixelSize: 13 + text: "⏰"; font.pixelSize: Math.round(13 * localScale) } // Controls when time is set Row { - spacing: 4; visible: root.pickerHasTime + spacing: Math.round(4 * localScale); visible: root.pickerHasTime anchors.verticalCenter: parent.verticalCenter // ── Hour col ────────────────────────────────────────── Column { - spacing: 2; anchors.verticalCenter: parent.verticalCenter + spacing: Math.round(2 * localScale); anchors.verticalCenter: parent.verticalCenter Rectangle { - width: 26; height: 18; radius: 4 + width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: hUpH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: 7; color: Qt.rgba(1,1,1,0.50) } + Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: hUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeH = (root.pickerTimeH + 1) % 24 } } Rectangle { - width: 26; height: 24; radius: 4 + width: Math.round(26 * localScale); height: Math.round(24 * localScale); radius: Math.round(4 * localScale) color: Qt.rgba(1,1,1,0.07); border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Text { anchors.centerIn: parent text: root._zp2(root.pickerTimeH) - font.pixelSize: 13; font.family: "JetBrains Mono"; font.weight: Font.Bold + font.pixelSize: Math.round(13 * localScale); font.family: "JetBrains Mono"; font.weight: Font.Bold color: Theme.active } } Rectangle { - width: 26; height: 18; radius: 4 + width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: hDnH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: 7; color: Qt.rgba(1,1,1,0.50) } + Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: hDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeH = (root.pickerTimeH + 23) % 24 } } } - Text { anchors.verticalCenter: parent.verticalCenter; text: ":"; font.pixelSize: 15; font.weight: Font.Bold; color: Theme.text } + Text { anchors.verticalCenter: parent.verticalCenter; text: ":"; font.pixelSize: Math.round(15 * localScale); font.weight: Font.Bold; color: Theme.text } // ── Minute col ──────────────────────────────────────── Column { - spacing: 2; anchors.verticalCenter: parent.verticalCenter + spacing: Math.round(2 * localScale); anchors.verticalCenter: parent.verticalCenter Rectangle { - width: 26; height: 18; radius: 4 + width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: mUpH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: 7; color: Qt.rgba(1,1,1,0.50) } + Text { anchors.centerIn: parent; text: "▲"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: mUpH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeM = (root.pickerTimeM + 5) % 60 } } Rectangle { - width: 26; height: 24; radius: 4 + width: Math.round(26 * localScale); height: Math.round(24 * localScale); radius: Math.round(4 * localScale) color: Qt.rgba(1,1,1,0.07); border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Text { anchors.centerIn: parent text: root._zp2(root.pickerTimeM) - font.pixelSize: 13; font.family: "JetBrains Mono"; font.weight: Font.Bold + font.pixelSize: Math.round(13 * localScale); font.family: "JetBrains Mono"; font.weight: Font.Bold color: Theme.active } } Rectangle { - width: 26; height: 18; radius: 4 + width: Math.round(26 * localScale); height: Math.round(18 * localScale); radius: Math.round(4 * localScale) color: mDnH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: 7; color: Qt.rgba(1,1,1,0.50) } + Text { anchors.centerIn: parent; text: "▼"; font.pixelSize: Math.round(7 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: mDnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerTimeM = (root.pickerTimeM + 55) % 60 } } @@ -693,10 +696,10 @@ Item { // Clear time ✕ Rectangle { anchors.verticalCenter: parent.verticalCenter - width: 18; height: 18; radius: 9 + width: Math.round(18 * localScale); height: Math.round(18 * localScale); radius: width / 2 color: clrTH.hovered ? Qt.rgba(1,1,1,0.14) : Qt.rgba(1,1,1,0.05) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: 8; color: Qt.rgba(1,1,1,0.40) } + Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(8 * localScale); color: Qt.rgba(1,1,1,0.40) } HoverHandler { id: clrTH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.pickerHasTime = false } } @@ -706,7 +709,7 @@ Item { Rectangle { visible: !root.pickerHasTime anchors.verticalCenter: parent.verticalCenter - width: addTL.implicitWidth + 18; height: 24; radius: 12 + width: addTL.implicitWidth + Math.round(18 * localScale); height: Math.round(24 * localScale); radius: height / 2 color: addTH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.06) @@ -714,7 +717,7 @@ Item { Behavior on color { ColorAnimation { duration: 80 } } Text { id: addTL; anchors.centerIn: parent - text: "Add time"; font.pixelSize: 10 + text: "Add time"; font.pixelSize: Math.round(10 * localScale) color: addTH.hovered ? Theme.active : Qt.rgba(1,1,1,0.45) Behavior on color { ColorAnimation { duration: 80 } } } @@ -732,14 +735,14 @@ Item { // ── Clear / Done ─────────────────────────────────────────────────── Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 10; bottomPadding: 0 + spacing: Math.round(10 * localScale); bottomPadding: 0 Rectangle { - width: 86; height: 28; radius: 8 + width: Math.round(86 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: clrH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Clear"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.50) } + Text { anchors.centerIn: parent; text: "Clear"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.50) } HoverHandler { id: clrH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent @@ -748,13 +751,13 @@ Item { } Rectangle { - width: 86; height: 28; radius: 8 + width: Math.round(86 * localScale); height: Math.round(28 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, doneH.hovered ? 0.28 : 0.16) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.38); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } Text { anchors.centerIn: parent; text: "Done" - font.pixelSize: 11; font.weight: Font.Medium; color: Theme.active + font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium; color: Theme.active } HoverHandler { id: doneH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._commitPicker() } @@ -769,6 +772,7 @@ Item { property var taskData property int colIdx + property real localScale: 1.0 property bool showExtra: false property real xEntry: 0 @@ -776,7 +780,7 @@ Item { readonly property bool isDelConfirm: root.delConfirmId === taskData.id - height: cardBg.implicitHeight + 2 + height: cardBg.implicitHeight + Math.round(2 * localScale) transform: [ Translate { x: card.dragX + card.xEntry }, @@ -784,7 +788,7 @@ Item { Rotation { origin.x: card.width / 2; origin.y: card.height / 2 axis { x: 0; y: 1; z: 0 } - angle: (card.dragX / 65.0) * -12 + angle: (card.dragX / (65.0 * localScale)) * -12 Behavior on angle { SpringAnimation { spring: 2.5; damping: 0.3 } } } ] @@ -810,7 +814,7 @@ Item { delete root._entryDirections[id] // dir=1 (moved right) → xEntry=+36 (card overshoots right, bounces left to 0) // dir=-1 (moved left) → xEntry=-36 (card overshoots left, bounces right to 0) - card.xEntry = dir * 36 + card.xEntry = dir * Math.round(36 * localScale) xSpringAnim.restart() } } @@ -828,18 +832,18 @@ Item { DragHandler { id: dragHandler target: null - xAxis.enabled: true; yAxis.enabled: false; dragThreshold: 12 + xAxis.enabled: true; yAxis.enabled: false; dragThreshold: Math.round(12 * localScale) onActiveChanged: { if (!active) { var d = card.dragX; snapAnim.start() var dir = d > 0 ? 1 : -1 - if (Math.abs(d) > 50 && card.colIdx + dir >= 0 && card.colIdx + dir <= 2) + if (Math.abs(d) > Math.round(50 * localScale) && card.colIdx + dir >= 0 && card.colIdx + dir <= 2) root._moveTask(card.taskData.id, dir) } } onTranslationChanged: { - if (active) card.dragX = Math.max(-65, Math.min(65, translation.x)) + if (active) card.dragX = Math.max(Math.round(-65 * localScale), Math.min(Math.round(65 * localScale), translation.x)) } } @@ -853,17 +857,17 @@ Item { } // Dynamic Glow: stronger, smoother color tinting - readonly property real dragAmt: Math.abs(dragX) / 65.0 + readonly property real dragAmt: Math.abs(dragX) / (65.0 * localScale) readonly property color dragTint: { - if (dragX > 2) return Qt.rgba(166/255, 227/255, 161/255, dragAmt * 0.35) - if (dragX < -2) return Qt.rgba(243/255, 139/255, 168/255, dragAmt * 0.35) + if (dragX > Math.round(2 * localScale)) return Qt.rgba(166/255, 227/255, 161/255, dragAmt * 0.35) + if (dragX < Math.round(-2 * localScale)) return Qt.rgba(243/255, 139/255, 168/255, dragAmt * 0.35) return "transparent" } // ── Card body ───────────────────────────────────────────────────────── Rectangle { id: cardBg - width: parent.width; radius: 8 + width: parent.width; radius: Math.round(8 * localScale) color: Qt.rgba(1, 1, 1, 0.05) border.color: { var u = card.taskData.urgency @@ -874,7 +878,7 @@ Item { } border.width: 1 Behavior on border.color { ColorAnimation { duration: 150 } } - implicitHeight: body.implicitHeight + 18 + implicitHeight: body.implicitHeight + Math.round(18 * localScale) // Drag direction tint Rectangle { @@ -884,14 +888,14 @@ Item { Column { id: body - anchors { left: parent.left; right: parent.right; leftMargin: 10; rightMargin: 10; top: parent.top; topMargin: 9 } - spacing: 6 + anchors { left: parent.left; right: parent.right; leftMargin: Math.round(10 * localScale); rightMargin: Math.round(10 * localScale); top: parent.top; topMargin: Math.round(9 * localScale) } + spacing: Math.round(6 * localScale) // Title (inline edit) TextInput { width: parent.width text: card.taskData.title - color: Theme.text; font.pixelSize: 12; font.weight: Font.Medium + color: Theme.text; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium wrapMode: TextInput.WordWrap selectionColor: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.35) onEditingFinished: { var t = text.trim(); if (t !== "") root._patchTask(card.taskData.id, "title", t) } @@ -900,42 +904,42 @@ Item { // Badges row Row { visible: card.taskData.urgency !== "" || (card.taskData.dueDate || "") !== "" - spacing: 6 + spacing: Math.round(6 * localScale) Rectangle { visible: card.taskData.urgency !== "" anchors.verticalCenter: parent.verticalCenter - width: urgL.implicitWidth + 12; height: 16; radius: 8 + width: urgL.implicitWidth + Math.round(12 * localScale); height: Math.round(16 * localScale); radius: Math.round(8 * localScale) color: root._urgColor(card.taskData.urgency); opacity: 0.85 - Text { id: urgL; anchors.centerIn: parent; text: root._urgLabel(card.taskData.urgency); font.pixelSize: 9; font.weight: Font.Bold; color: "#1e1e2e" } + Text { id: urgL; anchors.centerIn: parent; text: root._urgLabel(card.taskData.urgency); font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold; color: "#1e1e2e" } } Row { visible: (card.taskData.dueDate || "") !== "" - anchors.verticalCenter: parent.verticalCenter; spacing: 3 - Text { text: "📅"; font.pixelSize: 9 } - Text { text: root._formatDue(card.taskData.dueDate || ""); font.pixelSize: 9; color: Qt.rgba(1,1,1,0.50) } + anchors.verticalCenter: parent.verticalCenter; spacing: Math.round(3 * localScale) + Text { text: "📅"; font.pixelSize: Math.round(9 * localScale) } + Text { text: root._formatDue(card.taskData.dueDate || ""); font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.50) } } } // Expandable extra fields Column { - visible: card.showExtra; width: parent.width; spacing: 6 + visible: card.showExtra; width: parent.width; spacing: Math.round(6 * localScale) // Urgency picker Row { - spacing: 5 - Text { anchors.verticalCenter: parent.verticalCenter; text: "Urgency"; font.pixelSize: 9; color: Qt.rgba(1,1,1,0.35) } + spacing: Math.round(5 * localScale) + Text { anchors.verticalCenter: parent.verticalCenter; text: "Urgency"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.35) } Repeater { model: ["", "low", "medium", "high"] delegate: Rectangle { required property string modelData property bool sel: card.taskData.urgency === modelData - width: uT.implicitWidth + 12; height: 17; radius: 9 + width: uT.implicitWidth + Math.round(12 * localScale); height: Math.round(17 * localScale); radius: Math.round(9 * localScale) color: sel ? (modelData === "" ? Qt.rgba(1,1,1,0.15) : root._urgColor(modelData)) : (uH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.05)) border.color: Qt.rgba(1,1,1, sel ? 0.20 : 0.08); border.width: 1 Behavior on color { ColorAnimation { duration: 100 } } Text { - id: uT; anchors.centerIn: parent; font.pixelSize: 9 + id: uT; anchors.centerIn: parent; font.pixelSize: Math.round(9 * localScale) text: modelData === "" ? "None" : modelData.charAt(0).toUpperCase() + modelData.slice(1) color: (sel && modelData !== "") ? "#1e1e2e" : Qt.rgba(1,1,1,0.65) } @@ -947,19 +951,19 @@ Item { // Due date button row Row { - spacing: 6 - Text { anchors.verticalCenter: parent.verticalCenter; text: "Due"; font.pixelSize: 9; color: Qt.rgba(1,1,1,0.35) } + spacing: Math.round(6 * localScale) + Text { anchors.verticalCenter: parent.verticalCenter; text: "Due"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1,0.35) } Rectangle { anchors.verticalCenter: parent.verticalCenter - width: dueLbl.implicitWidth + 20; height: 20; radius: 10 + width: dueLbl.implicitWidth + Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(10 * localScale) color: dueBH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.07) border.color: Qt.rgba(1,1,1,0.12); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } Text { - id: dueLbl; anchors.centerIn: parent; font.pixelSize: 9 + id: dueLbl; anchors.centerIn: parent; font.pixelSize: Math.round(9 * localScale) text: (card.taskData.dueDate || "") !== "" ? root._formatDue(card.taskData.dueDate) : "Set due date" color: (card.taskData.dueDate || "") !== "" ? Theme.active : Qt.rgba(1,1,1,0.40) Behavior on color { ColorAnimation { duration: 80 } } @@ -972,10 +976,10 @@ Item { Rectangle { visible: (card.taskData.dueDate || "") !== "" anchors.verticalCenter: parent.verticalCenter - width: 16; height: 16; radius: 8 + width: Math.round(16 * localScale); height: Math.round(16 * localScale); radius: width / 2 color: clrDH.hovered ? Qt.rgba(1,1,1,0.12) : Qt.rgba(1,1,1,0.05) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: 8; color: Qt.rgba(1,1,1,0.35) } + Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(8 * localScale); color: Qt.rgba(1,1,1,0.35) } HoverHandler { id: clrDH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._patchTask(card.taskData.id, "dueDate", "") } } @@ -984,30 +988,30 @@ Item { // Action bar Item { - width: parent.width; height: 22 + width: parent.width; height: Math.round(22 * localScale) // ▾/▴ extra fields Rectangle { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - width: 20; height: 20; radius: 5 + width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: optH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.04) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: card.showExtra ? "▴" : "▾"; font.pixelSize: 9; color: Qt.rgba(1,1,1, optH.hovered ? 0.70 : 0.30) } + Text { anchors.centerIn: parent; text: card.showExtra ? "▴" : "▾"; font.pixelSize: Math.round(9 * localScale); color: Qt.rgba(1,1,1, optH.hovered ? 0.70 : 0.30) } HoverHandler { id: optH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: card.showExtra = !card.showExtra } } Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - spacing: 4 + spacing: Math.round(4 * localScale) // ← left Rectangle { visible: card.colIdx > 0 - width: 20; height: 20; radius: 5 + width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: lH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.04) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "←"; font.pixelSize: 10; color: Qt.rgba(1,1,1, lH.hovered ? 0.80 : 0.40) } + Text { anchors.centerIn: parent; text: "←"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1, lH.hovered ? 0.80 : 0.40) } HoverHandler { id: lH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._moveTask(card.taskData.id, -1) } } @@ -1015,21 +1019,21 @@ Item { // → right Rectangle { visible: card.colIdx < 2 - width: 20; height: 20; radius: 5 + width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: rH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.04) Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "→"; font.pixelSize: 10; color: Qt.rgba(1,1,1, rH.hovered ? 0.80 : 0.40) } + Text { anchors.centerIn: parent; text: "→"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(1,1,1, rH.hovered ? 0.80 : 0.40) } HoverHandler { id: rH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._moveTask(card.taskData.id, 1) } } // ✕ delete Rectangle { - width: 20; height: 20; radius: 5 + width: Math.round(20 * localScale); height: Math.round(20 * localScale); radius: Math.round(5 * localScale) color: dH.hovered ? Qt.rgba(248/255,113/255,113/255,0.20) : Qt.rgba(1,1,1,0.04) Behavior on color { ColorAnimation { duration: 80 } } Text { - anchors.centerIn: parent; text: "✕"; font.pixelSize: 10 + anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(248/255,113/255,113/255, dH.hovered ? 1.0 : 0.60) Behavior on color { ColorAnimation { duration: 80 } } } @@ -1050,34 +1054,34 @@ Item { Math.min(1, Theme.background.b + 0.05), 0.96) Column { - anchors.centerIn: parent; spacing: 10 + anchors.centerIn: parent; spacing: Math.round(10 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter - text: "Delete task?"; color: Theme.text; font.pixelSize: 12; font.weight: Font.Medium + text: "Delete task?"; color: Theme.text; font.pixelSize: Math.round(12 * localScale); font.weight: Font.Medium } Row { - anchors.horizontalCenter: parent.horizontalCenter; spacing: 8 + anchors.horizontalCenter: parent.horizontalCenter; spacing: Math.round(8 * localScale) Rectangle { - width: 64; height: 24; radius: 6 + width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale) color: cnH.hovered ? Qt.rgba(1,1,1,0.10) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.10); border.width: 1 Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.60) } + Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.60) } HoverHandler { id: cnH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root.delConfirmId = -1 } } Rectangle { - width: 64; height: 24; radius: 6 + width: Math.round(64 * localScale); height: Math.round(24 * localScale); radius: Math.round(6 * localScale) color: cfH.hovered ? "#cc3a3a" : "#993030" Behavior on color { ColorAnimation { duration: 80 } } - Text { anchors.centerIn: parent; text: "Delete"; font.pixelSize: 11; font.weight: Font.Bold; color: "white" } + Text { anchors.centerIn: parent; text: "Delete"; font.pixelSize: Math.round(11 * localScale); font.weight: Font.Bold; color: "white" } HoverHandler { id: cfH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._removeTask(card.taskData.id) } } } Text { anchors.horizontalCenter: parent.horizontalCenter - text: "↵ confirm · ⎋ cancel"; font.pixelSize: 9 + text: "↵ confirm · ⎋ cancel"; font.pixelSize: Math.round(9 * localScale) color: Qt.rgba(1,1,1,0.20) } } diff --git a/src/services/PowerMenu.qml b/src/services/PowerMenu.qml index fc326ec..2e7994e 100644 --- a/src/services/PowerMenu.qml +++ b/src/services/PowerMenu.qml @@ -6,8 +6,9 @@ import "../" Column { id: root - spacing: 4 + spacing: Math.round(4 * localScale) width: parent.width + property real localScale: 1.0 readonly property var actions: [ { @@ -78,8 +79,8 @@ Column { delegate: Rectangle { width: root.width - height: 44 - radius: Theme.cornerRadius + height: Math.round(44 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: hov.hovered ? (modelData.danger ? "#4d2020" : Theme.active) : "transparent" @@ -88,18 +89,18 @@ Column { Row { anchors.centerIn: parent - spacing: 10 + spacing: Math.round(10 * localScale) Text { text: modelData.icon - font.pixelSize: 16 + font.pixelSize: Math.round(16 * localScale) color: modelData.danger && hov.hovered ? "#ff6b6b" : hov.hovered?"#000000":Theme.text anchors.verticalCenter: parent.verticalCenter } Text { text: modelData.label - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) color: modelData.danger && hov.hovered ? "#ff6b6b" : hov.hovered?"#000000":Theme.text anchors.verticalCenter: parent.verticalCenter } diff --git a/src/services/config_tab/ShellConfig.qml b/src/services/config_tab/ShellConfig.qml index 7896663..6a31729 100644 --- a/src/services/config_tab/ShellConfig.qml +++ b/src/services/config_tab/ShellConfig.qml @@ -6,6 +6,7 @@ import "../../components" Item { id: root + property real localScale: 1.0 property string _page: "appearance" readonly property var _tabs: [ @@ -19,30 +20,31 @@ Item { Row { anchors { fill: parent - margins: 8 + margins: Math.round(8 * localScale) } - spacing: 12 + spacing: Math.round(12 * localScale) // ── Left: tab column (30%) ──────────────────────────────────────────── Rectangle { width: Math.floor((parent.width - parent.spacing) * 0.30) height: parent.height - radius: Theme.cornerRadius + radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba(1, 1, 1, 0.04) border.color: Qt.rgba(1, 1, 1, 0.07) border.width: 1 TabSwitcher { + localScale: root.localScale orientation: "vertical" anchors { top: parent.top bottom: parent.bottom left: parent.left right: parent.right - topMargin: 8 - bottomMargin: 8 - leftMargin: 6 - rightMargin: 6 + topMargin: Math.round(8 * localScale) + bottomMargin: Math.round(8 * localScale) + leftMargin: Math.round(6 * localScale) + rightMargin: Math.round(6 * localScale) } currentPage: root._page model: root._tabs @@ -58,27 +60,30 @@ Item { Item { anchors.fill: parent visible: root._page === "appearance" - Text { anchors.centerIn: parent; text: "Appearance Coming Soon!"; font.pixelSize: 13; color: Qt.rgba(1,1,1,0.12) } + Text { anchors.centerIn: parent; text: "Appearance Coming Soon!"; font.pixelSize: Math.round(13 * localScale); color: Qt.rgba(1,1,1,0.12) } } Item { anchors.fill: parent visible: root._page === "layout" - Text { anchors.centerIn: parent; text: "Layout & Behavior Coming Soon!"; font.pixelSize: 13; color: Qt.rgba(1,1,1,0.12) } + Text { anchors.centerIn: parent; text: "Layout & Behavior Coming Soon!"; font.pixelSize: Math.round(13 * localScale); color: Qt.rgba(1,1,1,0.12) } } Item { anchors.fill: parent visible: root._page === "data" - Text { anchors.centerIn: parent; text: "Data & Storage Coming Soon! "; font.pixelSize: 13; color: Qt.rgba(1,1,1,0.12) } + Text { anchors.centerIn: parent; text: "Data & Storage Coming Soon! "; font.pixelSize: Math.round(13 * localScale); color: Qt.rgba(1,1,1,0.12) } } Item { anchors.fill: parent visible: root._page === "keybinds" - KeybindsPage { anchors.fill: parent } + KeybindsPage { + anchors.fill: parent + // localScale: root.localScale // If KeybindsPage is updated later + } } Item { anchors.fill: parent visible: root._page === "misc" - Text { anchors.centerIn: parent; text: "Misc Coming Soon!"; font.pixelSize: 13; color: Qt.rgba(1,1,1,0.12) } + Text { anchors.centerIn: parent; text: "Misc Coming Soon!"; font.pixelSize: Math.round(13 * localScale); color: Qt.rgba(1,1,1,0.12) } } } } diff --git a/src/services/home/CalendarCard.qml b/src/services/home/CalendarCard.qml index 0034ac0..c6ded00 100644 --- a/src/services/home/CalendarCard.qml +++ b/src/services/home/CalendarCard.qml @@ -9,6 +9,8 @@ StatCard { id: root padding: 0 + property real localScale: 1.0 + // ── State ───────────────────────────────────────────────────────────────── property int _year: 0 property int _month: 0 @@ -76,17 +78,17 @@ StatCard { // ── UI ──────────────────────────────────────────────────────────────────── Item { - anchors { fill: parent; margins: 12 } + anchors { fill: parent; margins: Math.round(12 * localScale) } // Header Item { id: hdr anchors { left: parent.left; right: parent.right; top: parent.top } - height: 22 + height: Math.round(22 * localScale) Text { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - text: "‹"; font.pixelSize: 15 + text: "‹"; font.pixelSize: Math.round(15 * localScale) color: pH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.25) Behavior on color { ColorAnimation { duration: 100 } } HoverHandler { id: pH; cursorShape: Qt.PointingHandCursor } @@ -94,12 +96,12 @@ StatCard { } Text { anchors.centerIn: parent - text: root._label; font.pixelSize: 10; font.weight: Font.Bold + text: root._label; font.pixelSize: Math.round(10 * localScale); font.weight: Font.Bold color: Theme.text } Text { anchors { right: parent.right; verticalCenter: parent.verticalCenter } - text: "›"; font.pixelSize: 15 + text: "›"; font.pixelSize: Math.round(15 * localScale) color: nH.hovered ? Qt.rgba(1,1,1,0.7) : Qt.rgba(1,1,1,0.25) Behavior on color { ColorAnimation { duration: 100 } } HoverHandler { id: nH; cursorShape: Qt.PointingHandCursor } @@ -110,8 +112,8 @@ StatCard { // DOW row Item { id: dow - anchors { left: parent.left; right: parent.right; top: hdr.bottom; topMargin: 3 } - height: 16 + anchors { left: parent.left; right: parent.right; top: hdr.bottom; topMargin: Math.round(3 * localScale) } + height: Math.round(16 * localScale) Row { anchors.fill: parent Repeater { @@ -119,7 +121,7 @@ StatCard { delegate: Text { width: Math.floor(dow.width / 7) horizontalAlignment: Text.AlignHCenter - text: modelData; font.pixelSize: 8; font.weight: Font.Bold + text: modelData; font.pixelSize: Math.round(8 * localScale); font.weight: Font.Bold color: Qt.rgba(1,1,1,0.2) } } @@ -129,7 +131,7 @@ StatCard { // Day grid Grid { id: grid - anchors { left: parent.left; right: parent.right; top: dow.bottom; topMargin: 2; bottom: parent.bottom } + anchors { left: parent.left; right: parent.right; top: dow.bottom; topMargin: Math.round(2 * localScale); bottom: parent.bottom } columns: 7; rows: 6 readonly property real cW: width / 7 @@ -149,7 +151,7 @@ StatCard { Rectangle { anchors.centerIn: parent - width: Math.min(parent.width, parent.height) - 4 + width: Math.min(parent.width, parent.height) - Math.round(4 * localScale) height: width; radius: width / 2 color: isToday ? Qt.rgba(166/255,208/255,247/255,0.15) : dH.hovered && modelData.cur ? Qt.rgba(1,1,1,0.07) : "transparent" @@ -158,7 +160,7 @@ StatCard { Behavior on color { ColorAnimation { duration: 80 } } Text { anchors.centerIn: parent; text: modelData.n - font.pixelSize: 9; font.family: "JetBrains Mono" + font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono" font.weight: isToday ? Font.Bold : Font.Normal color: isToday ? Theme.active : modelData.cur ? Qt.rgba(205/255,214/255,244/255,0.55) diff --git a/src/services/home/ClockCard.qml b/src/services/home/ClockCard.qml index c5e2e27..35f8430 100644 --- a/src/services/home/ClockCard.qml +++ b/src/services/home/ClockCard.qml @@ -9,6 +9,8 @@ StatCard { id: root padding: 0 + property real localScale: 1.0 + // ── Mode ────────────────────────────────────────────────────────────────── property string _mode: "clock" @@ -233,23 +235,23 @@ StatCard { Row { anchors.centerIn: parent - spacing: 10 + spacing: Math.round(10 * localScale) // HH stacked above MM with diagonal offset Item { anchors.verticalCenter: parent.verticalCenter // Width fits both texts plus the one-char offset - readonly property int charOffset: 40 + readonly property int charOffset: Math.round(40 * localScale) width: hhText.implicitWidth + charOffset - height: hhText.implicitHeight + mmText.implicitHeight - 8 + height: hhText.implicitHeight + mmText.implicitHeight - Math.round(8 * localScale) Text { id: hhText anchors.left: parent.left anchors.top: parent.top text: root._hStr - font.pixelSize: 72; font.weight: Font.Bold - font.family: "JetBrains Mono"; font.letterSpacing: -4 + font.pixelSize: Math.round(72 * localScale); font.weight: Font.Bold + font.family: "JetBrains Mono"; font.letterSpacing: Math.round(-4 * localScale) color: Theme.text } Text { @@ -257,10 +259,10 @@ StatCard { anchors.left: parent.left anchors.leftMargin: parent.charOffset anchors.top: hhText.bottom - anchors.topMargin: -8 + anchors.topMargin: Math.round(-8 * localScale) text: root._mStr - font.pixelSize: 72; font.weight: Font.Bold - font.family: "JetBrains Mono"; font.letterSpacing: -4 + font.pixelSize: Math.round(72 * localScale); font.weight: Font.Bold + font.family: "JetBrains Mono"; font.letterSpacing: Math.round(-4 * localScale) color: Theme.active } } @@ -269,7 +271,7 @@ StatCard { Text { anchors.verticalCenter: parent.verticalCenter text: root._sec - font.pixelSize: 22; font.weight: Font.Medium + font.pixelSize: Math.round(22 * localScale); font.weight: Font.Medium font.family: "JetBrains Mono" color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.45) } @@ -284,11 +286,11 @@ StatCard { // "+" / "x" toggle — top-right corner Item { id: addTimerBtn - anchors { top: parent.top; right: parent.right; topMargin: 8; rightMargin: 8 } - width: 24; height: 24 + anchors { top: parent.top; right: parent.right; topMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } + width: Math.round(24 * localScale); height: Math.round(24 * localScale) Rectangle { - anchors.fill: parent; radius: 7 + anchors.fill: parent; radius: Math.round(7 * localScale) color: _addTimerHov.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.15) : Qt.rgba(1,1,1,0.06) @@ -297,7 +299,7 @@ StatCard { Text { anchors.centerIn: parent text: root._addTimerOpen ? "x" : "+" - font.pixelSize: 14; color: Theme.active + font.pixelSize: Math.round(14 * localScale); color: Theme.active } } HoverHandler { id: _addTimerHov; cursorShape: Qt.PointingHandCursor } @@ -308,12 +310,12 @@ StatCard { } Column { - anchors.centerIn: parent; spacing: 10 + anchors.centerIn: parent; spacing: Math.round(10 * localScale) // ── Ring — hidden while add-timer panel is open ──────────────── Item { anchors.horizontalCenter: parent.horizontalCenter - width: 100; height: 100 + width: Math.round(100 * localScale); height: Math.round(100 * localScale) visible: !root._addTimerOpen Canvas { @@ -322,16 +324,16 @@ StatCard { onPaint: { var ctx = getContext("2d") ctx.clearRect(0, 0, width, height) - var cx = width/2, cy = height/2, r = 44 + var cx = width/2, cy = height/2, r = Math.round(44 * localScale) ctx.beginPath(); ctx.arc(cx, cy, r, 0, Math.PI*2) ctx.strokeStyle = Qt.rgba(1,1,1,0.08) - ctx.lineWidth = 5; ctx.stroke() + ctx.lineWidth = Math.round(5 * localScale); ctx.stroke() var p = root._timerProgress() if (p > 0) { ctx.beginPath() ctx.arc(cx, cy, r, -Math.PI/2, -Math.PI/2 + Math.PI*2*p) ctx.strokeStyle = Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.85) - ctx.lineWidth = 5; ctx.lineCap = "round"; ctx.stroke() + ctx.lineWidth = Math.round(5 * localScale); ctx.lineCap = "round"; ctx.stroke() } } Connections { @@ -345,13 +347,13 @@ StatCard { Text { anchors.horizontalCenter: parent.horizontalCenter text: root._timerDisplay() - font.pixelSize: root._timerLeft >= 3600 ? 16 : 22 + font.pixelSize: root._timerLeft >= 3600 ? Math.round(16 * localScale) : Math.round(22 * localScale) font.weight: Font.Bold; font.family: "JetBrains Mono" color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.9) } Text { anchors.horizontalCenter: parent.horizontalCenter - text: "remaining"; font.pixelSize: 8 + text: "remaining"; font.pixelSize: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.25) } } @@ -360,21 +362,21 @@ StatCard { // ── Presets — hidden while add-timer panel is open ───────────── Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 5 + spacing: Math.round(5 * localScale) visible: !root._addTimerOpen && !root._timerRunning Repeater { model: [5, 10, 15, 30] delegate: Rectangle { required property int modelData required property int index - width: 36; height: 22; radius: 6 + width: Math.round(36 * localScale); height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: _pH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1) : Qt.rgba(1,1,1,0.05) border.color: Qt.rgba(1,1,1,0.1); border.width: 1 Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent text: modelData < 60 ? modelData+"m" : "1h" - font.pixelSize: 9; font.family: "JetBrains Mono"; font.weight: Font.Bold + font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono"; font.weight: Font.Bold color: Qt.rgba(1,1,1,0.45) } HoverHandler { id: _pH; cursorShape: Qt.PointingHandCursor } @@ -403,17 +405,18 @@ StatCard { Column { id: _timerInputCol anchors.centerIn: parent - spacing: 10 + spacing: Math.round(10 * localScale) TimeInput { id: timerTimeInput + localScale: root.localScale anchors.horizontalCenter: parent.horizontalCenter minuteStep: 1 } Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: 58; height: 26; radius: 8 + width: Math.round(58 * localScale); height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: _setTimerHov.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1) @@ -421,7 +424,7 @@ StatCard { Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent; text: "Set Timer" - font.pixelSize: 11; font.weight: Font.Medium + font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: Theme.active } HoverHandler { id: _setTimerHov; cursorShape: Qt.PointingHandCursor } @@ -448,12 +451,12 @@ StatCard { // ── Start / Pause + Reset ───────────────────── Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 6 + spacing: Math.round(6 * localScale) visible: !root._addTimerOpen // Start / Pause Rectangle { - width: 58; height: 26; radius: 8 + width: Math.round(58 * localScale); height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: _startHov.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.2) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.12) @@ -462,7 +465,7 @@ StatCard { Text { anchors.centerIn: parent text: root._timerRunning ? "Pause" : "Start" - font.pixelSize: 10; font.weight: Font.Medium + font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium color: Theme.active } HoverHandler { id: _startHov; cursorShape: Qt.PointingHandCursor } @@ -479,7 +482,7 @@ StatCard { // Reset Rectangle { - width: 58; height: 26; radius: 8 + width: Math.round(58 * localScale); height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: _resetHov.hovered ? Qt.rgba(1,1,1,0.1) : Qt.rgba(1,1,1,0.05) @@ -487,7 +490,7 @@ StatCard { Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent; text: "Reset" - font.pixelSize: 10; font.weight: Font.Medium + font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: _resetHov; cursorShape: Qt.PointingHandCursor } @@ -514,27 +517,27 @@ StatCard { clip: true Item { - anchors { fill: parent; margins: 10 } + anchors { fill: parent; margins: Math.round(10 * localScale) } // ── Header — Item, not Row, so right-anchor on + button works ── Item { id: alarmHeader anchors { left: parent.left; right: parent.right; top: parent.top } - height: 28 + height: Math.round(28 * localScale) Text { anchors { left: parent.left; verticalCenter: parent.verticalCenter } - text: "Alarms"; font.pixelSize: 12; font.weight: Font.DemiBold + text: "Alarms"; font.pixelSize: Math.round(12 * localScale); font.weight: Font.DemiBold color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.7) } Item { id: addAlarmBtn anchors { right: parent.right; verticalCenter: parent.verticalCenter } - width: 24; height: 24 + width: Math.round(24 * localScale); height: Math.round(24 * localScale) Rectangle { - anchors.fill: parent; radius: 7 + anchors.fill: parent; radius: Math.round(7 * localScale) color: _addHov.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.15) : Qt.rgba(1,1,1,0.06) @@ -543,7 +546,7 @@ StatCard { Text { anchors.centerIn: parent text: root._addOpen ? "✕" : "+" - font.pixelSize: 14; color: Theme.active + font.pixelSize: Math.round(14 * localScale); color: Theme.active } } HoverHandler { id: _addHov; cursorShape: Qt.PointingHandCursor } @@ -571,11 +574,11 @@ StatCard { // ── Add alarm panel ──────────────────────────────────────────── Rectangle { id: addPanel - anchors { left: parent.left; right: parent.right; top: alarmHeader.bottom; topMargin: 6 } - height: root._addOpen ? 140 : 0 + anchors { left: parent.left; right: parent.right; top: alarmHeader.bottom; topMargin: Math.round(6 * localScale) } + height: root._addOpen ? Math.round(140 * localScale) : 0 clip: true color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.05) - radius: 8 + radius: Math.round(8 * localScale) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1); border.width: 1 opacity: root._addOpen ? 1 : 0 Behavior on height { NumberAnimation { duration: 180; easing.type: Easing.OutCubic } } @@ -583,17 +586,18 @@ StatCard { Column { anchors.centerIn: parent - spacing: 10 + spacing: Math.round(10 * localScale) TimeInput { id: alarmTimeInput + localScale: root.localScale anchors.horizontalCenter: parent.horizontalCenter minuteStep: 1 } Rectangle { anchors.horizontalCenter: parent.horizontalCenter - width: 58; height: 26; radius: 8 + width: Math.round(58 * localScale); height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: _setAlarmHov.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.18) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.1) @@ -601,7 +605,7 @@ StatCard { Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent; text: "Set Alarm" - font.pixelSize: 11; font.weight: Font.Medium + font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: Theme.active } HoverHandler { id: _setAlarmHov; cursorShape: Qt.PointingHandCursor } @@ -622,17 +626,17 @@ StatCard { id: alarmList anchors { left: parent.left; right: parent.right - top: addPanel.bottom; topMargin: 6 + top: addPanel.bottom; topMargin: Math.round(6 * localScale) bottom: parent.bottom } model: root._alarms - clip: true; spacing: 4 + clip: true; spacing: Math.round(4 * localScale) boundsBehavior: Flickable.StopAtBounds delegate: Rectangle { required property var modelData required property int index - width: alarmList.width; height: 36; radius: 8 + width: alarmList.width; height: Math.round(36 * localScale); radius: Math.round(8 * localScale) color: Qt.rgba(1,1,1,0.04) border.color: modelData.enabled ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.15) @@ -641,9 +645,9 @@ StatCard { // Time label Text { - anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } + anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } text: root._zp(modelData.hour) + ":" + root._zp(modelData.minute) - font.pixelSize: 15; font.weight: Font.Bold; font.family: "JetBrains Mono" + font.pixelSize: Math.round(15 * localScale); font.weight: Font.Bold; font.family: "JetBrains Mono" color: modelData.enabled ? Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.9) : Qt.rgba(1,1,1,0.3) @@ -652,16 +656,16 @@ StatCard { // Toggle Rectangle { id: toggleBtn - anchors { right: deleteBtn.left; rightMargin: 6; verticalCenter: parent.verticalCenter } - width: 28; height: 18; radius: 9 + anchors { right: deleteBtn.left; rightMargin: Math.round(6 * localScale); verticalCenter: parent.verticalCenter } + width: Math.round(28 * localScale); height: Math.round(18 * localScale); radius: Math.round(9 * localScale) color: modelData.enabled ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.25) : Qt.rgba(1,1,1,0.1) Behavior on color { ColorAnimation { duration: 130 } } Rectangle { - width: 12; height: 12; radius: 6 + width: Math.round(12 * localScale); height: Math.round(12 * localScale); radius: Math.round(6 * localScale) anchors.verticalCenter: parent.verticalCenter - x: modelData.enabled ? parent.width - width - 3 : 3 + x: modelData.enabled ? parent.width - width - Math.round(3 * localScale) : Math.round(3 * localScale) color: modelData.enabled ? Theme.active : Qt.rgba(1,1,1,0.3) Behavior on x { NumberAnimation { duration: 130; easing.type: Easing.OutCubic } } Behavior on color { ColorAnimation { duration: 130 } } @@ -675,11 +679,11 @@ StatCard { // Delete Rectangle { id: deleteBtn - anchors { right: parent.right; rightMargin: 10; verticalCenter: parent.verticalCenter } - width: 22; height: 22; radius: 6 + anchors { right: parent.right; rightMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + width: Math.round(22 * localScale); height: Math.round(22 * localScale); radius: Math.round(6 * localScale) color: _delH.hovered ? Qt.rgba(248/255,113/255,113/255,0.18) : "transparent" Behavior on color { ColorAnimation { duration: 100 } } - Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: 10; color: Qt.rgba(248/255,113/255,113/255,0.6) } + Text { anchors.centerIn: parent; text: "✕"; font.pixelSize: Math.round(10 * localScale); color: Qt.rgba(248/255,113/255,113/255,0.6) } HoverHandler { id: _delH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: root._deleteAlarm(modelData.id) } } @@ -690,7 +694,7 @@ StatCard { visible: root._alarms.length === 0 && !root._addOpen text: "No alarms set\nTap + to add one" horizontalAlignment: Text.AlignHCenter - font.pixelSize: 11; color: Qt.rgba(1,1,1,0.2) + font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.2) lineHeight: 1.5 } } @@ -703,23 +707,23 @@ StatCard { visible: root._mode === "stopwatch" Column { - anchors.centerIn: parent; spacing: 12 + anchors.centerIn: parent; spacing: Math.round(12 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: root._swDisplay() - font.pixelSize: 52; font.weight: Font.Bold - font.family: "JetBrains Mono"; font.letterSpacing: -1 + font.pixelSize: Math.round(52 * localScale); font.weight: Font.Bold + font.family: "JetBrains Mono"; font.letterSpacing: Math.round(-1 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.9) } Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 6 + spacing: Math.round(6 * localScale) // Start / Stop Rectangle { - width: 58; height: 26; radius: 8 + width: Math.round(58 * localScale); height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: _swStartHov.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.2) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b,0.12) @@ -728,7 +732,7 @@ StatCard { Text { anchors.centerIn: parent text: root._swRunning ? "Stop" : "Start" - font.pixelSize: 10; font.weight: Font.Medium + font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium color: Theme.active } HoverHandler { id: _swStartHov; cursorShape: Qt.PointingHandCursor } @@ -740,7 +744,7 @@ StatCard { } // Reset Rectangle { - width: 58; height: 26; radius: 8 + width: Math.round(58 * localScale); height: Math.round(26 * localScale); radius: Math.round(8 * localScale) color: _swResetHov.hovered ? Qt.rgba(1,1,1,0.1) : Qt.rgba(1,1,1,0.05) @@ -748,7 +752,7 @@ StatCard { Behavior on color { ColorAnimation { duration: 100 } } Text { anchors.centerIn: parent; text: "Reset" - font.pixelSize: 10; font.weight: Font.Medium + font.pixelSize: Math.round(10 * localScale); font.weight: Font.Medium color: Qt.rgba(1,1,1,0.4) } HoverHandler { id: _swResetHov; cursorShape: Qt.PointingHandCursor } @@ -764,6 +768,7 @@ StatCard { // ── Tab bar ─────────────────────────────────────────────────────────── TabSwitcher { id: tabs + localScale: root.localScale anchors { left: parent.left; right: parent.right; bottom: parent.bottom } orientation: "horizontal"; width: parent.width currentPage: root._mode diff --git a/src/services/home/DashHome.qml b/src/services/home/DashHome.qml index 4244642..95f2989 100644 --- a/src/services/home/DashHome.qml +++ b/src/services/home/DashHome.qml @@ -15,10 +15,12 @@ import "../../components" Item { id: root - readonly property int colW: 210 - readonly property int gap: 8 - readonly property int profileH: 160 - readonly property int clockH: 220 + property real localScale: 1.0 + + readonly property int colW: Math.round(210 * localScale) + readonly property int gap: Math.round(8 * localScale) + readonly property int profileH: Math.round(160 * localScale) + readonly property int clockH: Math.round(220 * localScale) // ── Avatar path ─────────────────────────────────────────────────────────── property string _avatarPath: "" @@ -67,12 +69,14 @@ Item { ProfileCard { id: profileCard + localScale: root.localScale anchors { left: parent.left; right: parent.right; top: parent.top } height: root.profileH avatarPath: root._avatarPath } CalendarCard { + localScale: root.localScale anchors { left: parent.left; right: parent.right top: profileCard.bottom; topMargin: root.gap @@ -84,6 +88,7 @@ Item { // ── Right column — QuickSettings fills full height ──────────────────────── QuickSettings { id: rightCard + localScale: root.localScale anchors { right: parent.right; top: parent.top; bottom: parent.bottom; topMargin: root.gap } width: root.colW } @@ -100,11 +105,13 @@ Item { ClockCard { id: clockCard + localScale: root.localScale anchors { left: parent.left; right: parent.right; top: parent.top } height: root.clockH } PlayerCard { + localScale: root.localScale anchors { left: parent.left; right: parent.right top: clockCard.bottom; topMargin: root.gap diff --git a/src/services/home/PlayerCard.qml b/src/services/home/PlayerCard.qml index 004fcc1..c82387b 100644 --- a/src/services/home/PlayerCard.qml +++ b/src/services/home/PlayerCard.qml @@ -8,6 +8,8 @@ import "../../components" Item { id: root + property real localScale: 1.0 + // ── Source blocklist ────────────────────────────────────────────────────── readonly property var _blocked: [ "kdeconnect", @@ -197,16 +199,16 @@ Item { // ── Track name + artist ─────────────────────────────────────────────────── Column { anchors { - left: parent.left; leftMargin: 120 - right: parent.right; rightMargin: 120 - top: parent.top; topMargin: 16 + left: parent.left; leftMargin: Math.round(120 * localScale) + right: parent.right; rightMargin: Math.round(120 * localScale) + top: parent.top; topMargin: Math.round(16 * localScale) } - spacing: 4 + spacing: Math.round(4 * localScale) clip: true // Ensure nothing bleeds outside the column boundaries // ── Title with Marquee Scroll ── Item { width: parent.width - height: 22 + height: Math.round(22 * localScale) clip: true TextMetrics { id: titleMetrics @@ -216,7 +218,7 @@ Item { Text { id: titleText text: root.title - font.pixelSize: 18; font.weight: Font.Bold + font.pixelSize: Math.round(18 * localScale); font.weight: Font.Bold color: "#ffffff" anchors.horizontalCenter: titleMetrics.width <= parent.width ? parent.horizontalCenter : undefined NumberAnimation on x { @@ -234,7 +236,7 @@ Item { width: parent.width text: root.artist visible: root.artist !== "" - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) color: Qt.rgba(1,1,1,0.55) maximumLineCount: 1 @@ -247,16 +249,16 @@ Item { // ── Bottom stack: controls + progress (raised to give room for picker) ────── Column { anchors { - left: parent.left; leftMargin: 14 - right: parent.right; rightMargin: 14 - bottom: parent.bottom; bottomMargin: 54 + left: parent.left; leftMargin: Math.round(14 * localScale) + right: parent.right; rightMargin: Math.round(14 * localScale) + bottom: parent.bottom; bottomMargin: Math.round(54 * localScale) } - spacing: 6 + spacing: Math.round(6 * localScale) // Controls Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 28 + spacing: Math.round(28 * localScale) Repeater { model: [ { key: "prev" }, { key: "play" }, { key: "next" } ] delegate: Rectangle { @@ -268,7 +270,7 @@ Item { if (modelData.key === "next") return "󰒬" return !root.isPlaying ? "󰐊" : "󰏤" } - width: 36; height: 36 + width: Math.round(36 * localScale); height: Math.round(36 * localScale) radius: height / 2 color: isPlay ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.18) @@ -279,7 +281,7 @@ Item { Text { anchors.centerIn: parent text: parent.dispIcon - font.pixelSize: isPlay ? 18 : 14 + font.pixelSize: isPlay ? Math.round(18 * localScale) : Math.round(14 * localScale) color: isPlay ? Theme.active : Qt.rgba(1,1,1,0.7) } HoverHandler { id: cH; cursorShape: Qt.PointingHandCursor } @@ -307,9 +309,9 @@ Item { // Progress bar + timestamps Column { - width: parent.width; spacing: 3 + width: parent.width; spacing: Math.round(3 * localScale) Item { - width: parent.width; height: 6 + width: parent.width; height: Math.round(6 * localScale) Rectangle { anchors.fill: parent; radius: height / 2 color: Qt.rgba(1,1,1,0.2) @@ -332,19 +334,19 @@ Item { } } Item { - width: parent.width; height: 14 + width: parent.width; height: Math.round(14 * localScale) Text { anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: root._fmt(root._pos) - font.pixelSize: 9; font.family: "JetBrains Mono" + font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono" color: Qt.rgba(1,1,1,0.4) } Text { anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: root._fmt(root.length) - font.pixelSize: 9; font.family: "JetBrains Mono" + font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono" color: Qt.rgba(1,1,1,0.4) } } @@ -358,8 +360,8 @@ Item { anchors { top: parent.top right: parent.right - topMargin: 12 - rightMargin: 12 + topMargin: Math.round(12 * localScale) + rightMargin: Math.round(12 * localScale) } visible: root.filteredPlayers.length > 1 z: 30 @@ -373,9 +375,9 @@ Item { anchors.right: parent.right // Width tracks the active row + padding - width: activeRow.implicitWidth + 24 + width: activeRow.implicitWidth + Math.round(24 * localScale) - readonly property int _rowH: 26 + readonly property int _rowH: Math.round(26 * localScale) height: root._dropdownOpen ? (_rowH * root.filteredPlayers.length) : _rowH @@ -405,22 +407,22 @@ Item { Row { id: activeRow anchors.centerIn: parent - spacing: 6 + spacing: Math.round(6 * localScale) Text { anchors.verticalCenter: parent.verticalCenter text: root.player ? root._playerIcon(root.player) : "♪" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: Theme.active } Text { anchors.verticalCenter: parent.verticalCenter text: root.player ? root._playerLabel(root.player) : "Player" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) font.weight: Font.Medium color: Qt.rgba(1,1,1,0.92) // Cap width so crazy browser identities don't stretch the pill - width: Math.min(implicitWidth, 120) + width: Math.min(implicitWidth, Math.round(120 * localScale)) elide: Text.ElideRight } } @@ -450,21 +452,21 @@ Item { Row { anchors.centerIn: parent - spacing: 6 + spacing: Math.round(6 * localScale) Text { anchors.verticalCenter: parent.verticalCenter text: root._playerIcon(modelData) - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: rowH.hovered ? Qt.rgba(1,1,1,0.90) : Qt.rgba(1,1,1,0.55) Behavior on color { ColorAnimation { duration: 100 } } } Text { anchors.verticalCenter: parent.verticalCenter text: root._playerLabel(modelData) - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: rowH.hovered ? Qt.rgba(1,1,1,0.90) : Qt.rgba(1,1,1,0.55) - width: Math.min(implicitWidth, 120) + width: Math.min(implicitWidth, Math.round(120 * localScale)) elide: Text.ElideRight Behavior on color { ColorAnimation { duration: 100 } } } @@ -486,23 +488,23 @@ Item { // ── Cava bars — independent, always flush with the card bottom ──────────── Item { - anchors { left: parent.left; right: parent.right; bottom: parent.bottom; leftMargin: 7; rightMargin: 7; bottomMargin: 4 } - height: 32 + anchors { left: parent.left; right: parent.right; bottom: parent.bottom; leftMargin: Math.round(7 * localScale); rightMargin: Math.round(7 * localScale); bottomMargin: Math.round(4 * localScale) } + height: Math.round(32 * localScale) Row { anchors { left: parent.left; right: parent.right; bottom: parent.bottom } - spacing: 2 + spacing: Math.round(2 * localScale) readonly property real barW: Math.max(1, (parent.width - spacing * (root._cavaBars - 1)) / root._cavaBars) Repeater { model: root._bars delegate: Item { required property int modelData required property int index - width: parent.barW; height: 32 + width: parent.barW; height: Math.round(32 * localScale) Rectangle { anchors.bottom: parent.bottom width: parent.width readonly property real _amp: root.isPlaying ? (modelData / 100) : 0 - height: Math.max(2, _amp * 32) + height: Math.max(2, _amp * Math.round(32 * localScale)) radius: width / 2 color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.25 + _amp * 0.65) Behavior on height { NumberAnimation { duration: 50; easing.type: Easing.OutCubic } } diff --git a/src/services/home/ProfileCard.qml b/src/services/home/ProfileCard.qml index f788aad..6fb3b67 100644 --- a/src/services/home/ProfileCard.qml +++ b/src/services/home/ProfileCard.qml @@ -10,6 +10,7 @@ StatCard { id: root padding: 0 + property real localScale: 1.0 property string avatarPath: "" property string _user: "" @@ -58,15 +59,15 @@ StatCard { Row { anchors { - left: parent.left; leftMargin: 16 - right: parent.right; rightMargin: 16 + left: parent.left; leftMargin: Math.round(16 * localScale) + right: parent.right; rightMargin: Math.round(16 * localScale) verticalCenter: parent.verticalCenter } - spacing: 18 + spacing: Math.round(18 * localScale) // Circular avatar Item { - width: 72; height: 72 + width: Math.round(72 * localScale); height: Math.round(72 * localScale) anchors.verticalCenter: parent.verticalCenter Rectangle { @@ -106,7 +107,7 @@ StatCard { Text { anchors.centerIn: parent text: "󰀄" - font.pixelSize: 28 + font.pixelSize: Math.round(28 * localScale) color: Theme.active visible: root.avatarPath === "" } @@ -115,35 +116,35 @@ StatCard { // Text stats Column { anchors.verticalCenter: parent.verticalCenter - spacing: 10 + spacing: Math.round(10 * localScale) Text { text: root._user - font.pixelSize: 17; font.weight: Font.DemiBold + font.pixelSize: Math.round(17 * localScale); font.weight: Font.DemiBold color: Theme.active } Row { - spacing: 8 + spacing: Math.round(8 * localScale) Text { - text: "󰣇"; font.pixelSize: 12; color: Theme.active + text: "󰣇"; font.pixelSize: Math.round(12 * localScale); color: Theme.active anchors.verticalCenter: parent.verticalCenter } Text { - text: root._wm; font.pixelSize: 12 + text: root._wm; font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(205/255,214/255,244/255,0.55) anchors.verticalCenter: parent.verticalCenter } } Row { - spacing: 8 + spacing: Math.round(8 * localScale) Text { - text: "󰔚"; font.pixelSize: 12; color: Theme.active + text: "󰔚"; font.pixelSize: Math.round(12 * localScale); color: Theme.active anchors.verticalCenter: parent.verticalCenter } Text { - text: root._uptime; font.pixelSize: 12 + text: root._uptime; font.pixelSize: Math.round(12 * localScale) font.family: "JetBrains Mono" color: Qt.rgba(205/255,214/255,244/255,0.55) anchors.verticalCenter: parent.verticalCenter diff --git a/src/services/home/QuickSettings.qml b/src/services/home/QuickSettings.qml index 1afdf37..88a4add 100644 --- a/src/services/home/QuickSettings.qml +++ b/src/services/home/QuickSettings.qml @@ -13,6 +13,8 @@ StatCard { padding: 0 focus: true + property real localScale: 1.0 + // ───────────────────────────────────────────────────────────────────────── // Brightness // ───────────────────────────────────────────────────────────────────────── @@ -609,48 +611,48 @@ StatCard { // UI // ───────────────────────────────────────────────────────────────────────── Column { - anchors { fill: parent; margins: 12 } + anchors { fill: parent; margins: Math.round(12 * localScale) } spacing: 0 // ── Brightness ──────────────────────────────────────────────────────── Item { width: parent.width - height: 52 + height: Math.round(52 * localScale) Text { id: brightLbl anchors { left: parent.left; top: parent.top } - text: "BRIGHTNESS"; font.pixelSize: 9; font.weight: Font.Bold + text: "BRIGHTNESS"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) } Text { anchors { right: parent.right; top: parent.top } text: Math.round(root._brightVal * 100) + "%" - font.pixelSize: 9; font.family: "JetBrains Mono"; font.weight: Font.Bold + font.pixelSize: Math.round(9 * localScale); font.family: "JetBrains Mono"; font.weight: Font.Bold color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.7) } Row { - anchors { left: parent.left; right: parent.right; top: brightLbl.bottom; topMargin: 8 } - spacing: 8 + anchors { left: parent.left; right: parent.right; top: brightLbl.bottom; topMargin: Math.round(8 * localScale) } + spacing: Math.round(8 * localScale) Text { anchors.verticalCenter: parent.verticalCenter - text: "󰃞"; font.pixelSize: 13 + text: "󰃞"; font.pixelSize: Math.round(13 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.35) } Item { id: btw - width: parent.width - 13 - 13 - parent.spacing * 2 - height: 30; anchors.verticalCenter: parent.verticalCenter - anchors.bottomMargin: 30 - readonly property int thumbD: 14 + width: parent.width - Math.round(13 * localScale) - Math.round(13 * localScale) - parent.spacing * 2 + height: Math.round(30 * localScale); anchors.verticalCenter: parent.verticalCenter + anchors.bottomMargin: Math.round(30 * localScale) + readonly property int thumbD: Math.round(14 * localScale) Rectangle { id: btrack anchors.verticalCenter: parent.verticalCenter - width: parent.width; height: 5; radius: height / 2 + width: parent.width; height: Math.round(5 * localScale); radius: height / 2 color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.12) Rectangle { anchors { left: parent.left; top: parent.top; bottom: parent.bottom } @@ -685,7 +687,7 @@ StatCard { Text { anchors.verticalCenter: parent.verticalCenter - text: "󰃠"; font.pixelSize: 13 + text: "󰃠"; font.pixelSize: Math.round(13 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.75) } } @@ -695,25 +697,25 @@ StatCard { width: parent.width; height: 1 color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.08) } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } Text { id: qsLbl; width: parent.width - text: "QUICK SETTINGS"; font.pixelSize: 9; font.weight: Font.Bold + text: "QUICK SETTINGS"; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) } - Item { width: parent.width; height: 8 } + Item { width: parent.width; height: Math.round(8 * localScale) } // ── Tile grid ───────────────────────────────────────────────────────── Item { width: parent.width - height: root.height - 12 - 52 - 1 - 8 - qsLbl.height - 8 + height: root.height - Math.round(12 * localScale) - Math.round(52 * localScale) - 1 - Math.round(8 * localScale) - qsLbl.height - Math.round(8 * localScale) Flickable { id: flick anchors.fill: parent contentWidth: width - contentHeight: tileGrid.implicitHeight + 8 + contentHeight: tileGrid.implicitHeight + Math.round(8 * localScale) clip: true boundsBehavior: Flickable.StopAtBounds @@ -725,7 +727,7 @@ StatCard { property string sublabel: "" signal toggled() - radius: 10 + radius: Math.round(10 * localScale) color: on ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : bH.hovered @@ -739,31 +741,31 @@ StatCard { Behavior on border.color { ColorAnimation { duration: 130 } } Rectangle { - anchors { top: parent.top; right: parent.right; margins: 8 } - width: 6; height: 6; radius: 3 + anchors { top: parent.top; right: parent.right; margins: Math.round(8 * localScale) } + width: Math.round(6 * localScale); height: Math.round(6 * localScale); radius: width / 2 color: btn.on ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.18) Behavior on color { ColorAnimation { duration: 130 } } } Column { - anchors { left: parent.left; bottom: parent.bottom; margins: 9 } - spacing: 2 + anchors { left: parent.left; bottom: parent.bottom; margins: Math.round(9 * localScale) } + spacing: Math.round(2 * localScale) Text { - text: btn.icon; font.pixelSize: 17 + text: btn.icon; font.pixelSize: Math.round(17 * localScale) color: btn.on ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.40) Behavior on color { ColorAnimation { duration: 130 } } } Text { - text: btn.label; font.pixelSize: 9; font.weight: Font.Medium + text: btn.label; font.pixelSize: Math.round(9 * localScale); font.weight: Font.Medium color: btn.on ? Theme.text : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.45) Behavior on color { ColorAnimation { duration: 130 } } } Text { visible: btn.sublabel !== "" text: btn.sublabel - font.pixelSize: 8; font.family: "JetBrains Mono" + font.pixelSize: Math.round(8 * localScale); font.family: "JetBrains Mono" color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.65) - width: btn.width - 18; elide: Text.ElideRight + width: btn.width - Math.round(18 * localScale); elide: Text.ElideRight } } HoverHandler { id: bH; cursorShape: Qt.PointingHandCursor } @@ -773,7 +775,7 @@ StatCard { Grid { id: tileGrid width: flick.width - columns: 2; spacing: 6 + columns: 2; spacing: Math.round(6 * localScale) readonly property real btnW: (width - spacing) / 2 readonly property real btnH: btnW * 0.85 @@ -880,14 +882,14 @@ StatCard { anchors { right: parent.right bottom: parent.bottom - rightMargin: 12 - bottomMargin: 12 + rightMargin: Math.round(12 * localScale) + bottomMargin: Math.round(12 * localScale) } - width: 180 + width: Math.round(180 * localScale) // Height fits "Off" row + all shader rows, capped at 280 - height: Math.min(280, pickerCol.implicitHeight + 16) - radius: Theme.cornerRadius + height: Math.min(Math.round(280 * localScale), pickerCol.implicitHeight + Math.round(16 * localScale)) + radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba( Math.min(1, Theme.background.r + 0.05), @@ -912,7 +914,7 @@ StatCard { } Flickable { - anchors { fill: parent; margins: 8 } + anchors { fill: parent; margins: Math.round(8 * localScale) } contentWidth: width contentHeight: pickerCol.implicitHeight clip: true @@ -921,23 +923,23 @@ StatCard { Column { id: pickerCol width: parent.width - spacing: 2 + spacing: Math.round(2 * localScale) // Header label Text { width: parent.width text: "SHADER" - font.pixelSize: 9; font.weight: Font.Bold + font.pixelSize: Math.round(9 * localScale); font.weight: Font.Bold color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.55) - leftPadding: 4 - bottomPadding: 4 + leftPadding: Math.round(4 * localScale) + bottomPadding: Math.round(4 * localScale) } // "Off" row — always first Rectangle { width: parent.width - height: 28 - radius: 6 + height: Math.round(28 * localScale) + radius: Math.round(6 * localScale) property bool isActive: root.currentFilter === "" color: isActive ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) @@ -945,18 +947,18 @@ StatCard { Behavior on color { ColorAnimation { duration: 100 } } Row { - anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } - spacing: 8 + anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(8 * localScale) Text { text: parent.parent.isActive ? "●" : "○" - font.pixelSize: 9 + font.pixelSize: Math.round(9 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.30) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } } Text { text: "Off" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.65) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } @@ -980,30 +982,30 @@ StatCard { property bool isActive: root.currentFilter === modelData width: pickerCol.width - height: 28 - radius: 6 + height: Math.round(28 * localScale) + radius: Math.round(6 * localScale) color: isActive ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.14) : itemH.hovered ? Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.07) : "transparent" Behavior on color { ColorAnimation { duration: 100 } } Row { - anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } - spacing: 8 + anchors { left: parent.left; leftMargin: Math.round(10 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(8 * localScale) Text { text: parent.parent.isActive ? "●" : "○" - font.pixelSize: 9 + font.pixelSize: Math.round(9 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.30) anchors.verticalCenter: parent.verticalCenter Behavior on color { ColorAnimation { duration: 100 } } } Text { text: modelData - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: parent.parent.isActive ? Theme.active : Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.65) anchors.verticalCenter: parent.verticalCenter elide: Text.ElideRight - width: pickerCol.width - 38 + width: pickerCol.width - Math.round(38 * localScale) Behavior on color { ColorAnimation { duration: 100 } } } } @@ -1017,10 +1019,10 @@ StatCard { width: parent.width visible: root.filterList.length === 0 text: "Loading…" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.25) horizontalAlignment: Text.AlignHCenter - topPadding: 4 + topPadding: Math.round(4 * localScale) } } } diff --git a/src/services/notifications/NotificationList.qml b/src/services/notifications/NotificationList.qml index 8b7ac89..48ddbf1 100644 --- a/src/services/notifications/NotificationList.qml +++ b/src/services/notifications/NotificationList.qml @@ -9,7 +9,9 @@ import "../../" Item { id: root - width: 360 + property real localScale: 1.0 + + width: Math.round(360 * root.localScale) // Total height: header + list area (or empty state) height: header.height @@ -71,14 +73,14 @@ Item { height: Math.min(contentList.contentHeight, maxListHeight) visible: NotificationService.count > 0 - readonly property int maxListHeight: 440 + readonly property int maxListHeight: Math.round(440 * root.localScale) ListView { id: contentList anchors.fill: parent model: NotificationService.list clip: true - spacing: 1 + spacing: Math.round(1 * root.localScale) boundsBehavior: Flickable.StopAtBounds delegate: NotificationCard { @@ -91,7 +93,7 @@ Item { // Fade overlay when clipped Rectangle { anchors { left: parent.left; right: parent.right; bottom: parent.bottom } - height: 28 + height: Math.round(28 * root.localScale) visible: contentList.contentHeight > listArea.maxListHeight gradient: Gradient { orientation: Gradient.Vertical @@ -105,25 +107,25 @@ Item { Item { id: emptyState anchors { top: header.bottom; left: parent.left; right: parent.right } - height: 80 + height: Math.round(80 * root.localScale) visible: NotificationService.count === 0 Column { anchors.centerIn: parent - spacing: 6 + spacing: Math.round(6 * root.localScale) Text { anchors.horizontalCenter: parent.horizontalCenter text: "󰂚" color: Qt.rgba(1, 1, 1, 0.15) - font.pixelSize: 28 + font.pixelSize: Math.round(28 * root.localScale) font.family: Theme.iconFont } Text { anchors.horizontalCenter: parent.horizontalCenter text: "No notifications" color: Theme.subtext - font.pixelSize: 12 + font.pixelSize: Math.round(12 * root.localScale) } } } @@ -145,7 +147,7 @@ Item { } } - height: cardRow.height + 20 + height: cardRow.height + Math.round(20 * root.localScale) // Hover background Rectangle { @@ -157,7 +159,7 @@ Item { // Left urgency accent bar Rectangle { anchors { left: parent.left; top: parent.top; bottom: parent.bottom } - width: 3 + width: Math.round(3 * root.localScale) color: card.urgencyColor opacity: 0.85 } @@ -166,18 +168,18 @@ Item { Row { id: cardRow anchors { - left: parent.left; leftMargin: 12 - right: parent.right; rightMargin: 8 - top: parent.top; topMargin: 10 + left: parent.left; leftMargin: Math.round(12 * root.localScale) + right: parent.right; rightMargin: Math.round(8 * root.localScale) + top: parent.top; topMargin: Math.round(10 * root.localScale) } - spacing: 10 + spacing: Math.round(10 * root.localScale) height: Math.max(iconArea.height, textCol.implicitHeight) // App icon Item { id: iconArea - width: 32 - height: 32 + width: Math.round(32 * root.localScale) + height: Math.round(32 * root.localScale) Image { id: iconImg @@ -191,8 +193,8 @@ Item { fillMode: Image.PreserveAspectFit smooth: true visible: status === Image.Ready - sourceSize.width: 32 - sourceSize.height: 32 + sourceSize.width: Math.round(32 * root.localScale) + sourceSize.height: Math.round(32 * root.localScale) } // Letter fallback @@ -206,7 +208,7 @@ Item { anchors.centerIn: parent text: (card.notification?.appName ?? "?").charAt(0).toUpperCase() color: Theme.text - font.pixelSize: 14 + font.pixelSize: Math.round(14 * root.localScale) font.bold: true } } @@ -217,14 +219,14 @@ Item { id: textCol // Leave room for dismiss button width: cardRow.width - iconArea.width - dismissBtn.width - (cardRow.spacing * 2) - spacing: 3 + spacing: Math.round(3 * root.localScale) // App name Text { width: parent.width text: card.notification?.appName ?? "" color: Theme.subtext - font.pixelSize: 11 + font.pixelSize: Math.round(11 * root.localScale) elide: Text.ElideRight visible: text !== "" } @@ -234,7 +236,7 @@ Item { width: parent.width text: card.notification?.summary ?? "" color: Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * root.localScale) font.bold: true wrapMode: Text.WordWrap maximumLineCount: 2 @@ -247,7 +249,7 @@ Item { width: parent.width text: card.notification?.body ?? "" color: Theme.subtext - font.pixelSize: 12 + font.pixelSize: Math.round(12 * root.localScale) wrapMode: Text.WordWrap maximumLineCount: 3 elide: Text.ElideRight @@ -257,19 +259,19 @@ Item { // Action buttons Row { - spacing: 6 + spacing: Math.round(6 * root.localScale) visible: (card.notification?.actions?.length ?? 0) > 0 Repeater { model: card.notification?.actions ?? [] delegate: Item { required property var modelData - width: actionLbl.width + 20 - height: 22 + width: actionLbl.width + Math.round(20 * root.localScale) + height: Math.round(22 * root.localScale) Rectangle { anchors.fill: parent - radius: 3 + radius: Math.round(3 * root.localScale) color: actHover.containsMouse ? Qt.rgba(1,1,1,0.15) : Qt.rgba(1,1,1,0.07) @@ -280,7 +282,7 @@ Item { anchors.centerIn: parent text: modelData?.text ?? "" color: Theme.text - font.pixelSize: 11 + font.pixelSize: Math.round(11 * root.localScale) } HoverHandler { id: actHover } TapHandler { onTapped: modelData?.invoke() } @@ -292,8 +294,8 @@ Item { // Dismiss ✕ Item { id: dismissBtn - width: 24 - height: 24 + width: Math.round(24 * root.localScale) + height: Math.round(24 * root.localScale) Rectangle { anchors.fill: parent @@ -305,7 +307,7 @@ Item { anchors.centerIn: parent text: "✕" color: Theme.subtext - font.pixelSize: 10 + font.pixelSize: Math.round(10 * root.localScale) } HoverHandler { id: xHover } TapHandler { onTapped: card.notification?.dismiss() } diff --git a/src/services/system/EnvyControl.qml b/src/services/system/EnvyControl.qml index 62a3041..e4a93b4 100644 --- a/src/services/system/EnvyControl.qml +++ b/src/services/system/EnvyControl.qml @@ -7,7 +7,8 @@ import "../" Column { id: root - spacing: 12 + property real localScale: 1.0 + spacing: Math.round(12 * localScale) width: parent.width readonly property var bat: UPower.displayDevice @@ -44,36 +45,36 @@ Column { Text { text: "Power Profile" color: Qt.rgba(1, 1, 1, 0.4) - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) font.capitalization: Font.AllUppercase - leftPadding: 2 + leftPadding: Math.round(2 * localScale) } Rectangle { width: parent.width - height: 40 - radius: Theme.cornerRadius + height: Math.round(40 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba(1, 1, 1, 0.05) Row { - anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter } - spacing: 8 + anchors { left: parent.left; leftMargin: Math.round(12 * localScale); verticalCenter: parent.verticalCenter } + spacing: Math.round(8 * localScale) - Text { text: "⚙️"; font.pixelSize: 14; anchors.verticalCenter: parent.verticalCenter } + Text { text: "⚙️"; font.pixelSize: Math.round(14 * localScale); anchors.verticalCenter: parent.verticalCenter } Text { text: root.powerProfile.charAt(0).toUpperCase() + root.powerProfile.slice(1) color: Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) anchors.verticalCenter: parent.verticalCenter } } Text { - anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter } + anchors { right: parent.right; rightMargin: Math.round(12 * localScale); verticalCenter: parent.verticalCenter } text: "🔒" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) opacity: 0.4 } } @@ -84,20 +85,20 @@ Column { // ── dGPU toggle row ─────────────────────────────────────────────────────── Column { width: parent.width - spacing: 4 + spacing: Math.round(4 * localScale) Text { text: "Graphics" color: Qt.rgba(1, 1, 1, 0.4) - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) font.capitalization: Font.AllUppercase - leftPadding: 2 + leftPadding: Math.round(2 * localScale) } Rectangle { width: parent.width - height: 48 - radius: Theme.cornerRadius + height: Math.round(48 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: Qt.rgba(1, 1, 1, 0.05) Row { diff --git a/src/theme/Metrics.qml b/src/theme/Metrics.qml index 7d3c424..70d1970 100644 --- a/src/theme/Metrics.qml +++ b/src/theme/Metrics.qml @@ -38,7 +38,7 @@ QtObject { // -- Notifications Popup Width -- property int notificationsWidth: 400 - property int notificationToastWidth: notificationsWidth / 1.2 + property int notificationToastWidth: notificationsWidth /1.2 property int networkPopupWidth: 480 // -- Popup Size Constraints -- diff --git a/src/windows/Border.qml b/src/windows/Border.qml index 5f52d81..a3b4086 100644 --- a/src/windows/Border.qml +++ b/src/windows/Border.qml @@ -6,10 +6,12 @@ import "../services/" PanelWindow { id: root + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + property string edge: "bottom" property bool isBarEnabled: Theme.barEnabled - property int thickness: Theme.borderWidth - property int radius: Theme.cornerRadius + property int thickness: Math.round(Theme.borderWidth * root.localScale) + property int radius: Math.round(Theme.cornerRadius * root.localScale) property color fillColor: Theme.background implicitWidth: (edge === "left" || edge === "right") ? radius : 0 @@ -26,9 +28,8 @@ PanelWindow { } margins { - top: (edge !== "bottom") ? ShellState.focusMode ? Theme.borderWidth : Theme.notchHeight: 0 + top: (edge !== "bottom") ? ShellState.focusMode ? Math.round(Theme.borderWidth * root.localScale) : Math.round((Theme.notchHeight-1) * root.localScale) : 0 Behavior on top { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic }} - bottom: (edge !== "bottom") ? radius : 0 } @@ -109,14 +110,14 @@ PanelWindow { ctx.lineTo(w, 0); // 2. Inner Right Corner (ROUNDED) - ctx.lineTo(w - t, 0); + ctx.lineTo(w - t + 1, 0); ctx.arcTo(w - t, h - t, w - t - r, h - t, r); // 3. Inner Bottom Line ctx.lineTo(t + r, h - t); // 4. Inner Left Corner (ROUNDED) - ctx.arcTo(t, h - t, t, 0, r); + ctx.arcTo(t + 4, h - t, t, 0, r); // 5. Close Loop ctx.lineTo(t, 0); diff --git a/src/windows/ConfirmDialog.qml b/src/windows/ConfirmDialog.qml index b4044d2..acdc741 100644 --- a/src/windows/ConfirmDialog.qml +++ b/src/windows/ConfirmDialog.qml @@ -21,6 +21,7 @@ import "../services/" PanelWindow { id: root + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) color: "transparent" @@ -124,9 +125,9 @@ PanelWindow { // ── Confirm dialog ──────────────────────────────────────────────────────── Rectangle { anchors.centerIn: parent - width: 360 - height: col.implicitHeight + 48 - radius: Theme.notchRadius + width: Math.round(360 * localScale) + height: col.implicitHeight + Math.round(48 * localScale) + radius: Math.round(Theme.notchRadius * localScale) color: Theme.background visible: Popups.confirmOpen && !Popups.confirmRunning @@ -138,11 +139,11 @@ PanelWindow { top: parent.top left: parent.left right: parent.right - topMargin: 24 - leftMargin: 24 - rightMargin: 24 + topMargin: Math.round(24 * localScale) + leftMargin: Math.round(24 * localScale) + rightMargin: Math.round(24 * localScale) } - spacing: 16 + spacing: Math.round(16 * localScale) Text { anchors.horizontalCenter: parent.horizontalCenter @@ -155,14 +156,14 @@ PanelWindow { default: return "⚠️" } } - font.pixelSize: 32 + font.pixelSize: Math.round(32 * localScale) } Text { anchors.horizontalCenter: parent.horizontalCenter text: Popups.confirmTitle color: Theme.text - font.pixelSize: 15 + font.pixelSize: Math.round(15 * localScale) font.bold: true } @@ -170,7 +171,7 @@ PanelWindow { width: parent.width text: Popups.confirmMessage color: Qt.rgba(1, 1, 1, 0.65) - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) wrapMode: Text.WordWrap textFormat: Text.RichText lineHeight: 1.4 @@ -178,12 +179,12 @@ PanelWindow { Row { anchors.horizontalCenter: parent.horizontalCenter - spacing: 10 + spacing: Math.round(10 * localScale) Rectangle { - width: 130 - height: 38 - radius: Theme.cornerRadius + width: Math.round(130 * localScale) + height: Math.round(38 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: cancelHov.hovered ? Qt.rgba(1, 1, 1, 0.1) : Qt.rgba(1, 1, 1, 0.05) Behavior on color { ColorAnimation { duration: 120 } } @@ -191,7 +192,7 @@ PanelWindow { anchors.centerIn: parent text: "Cancel" color: Theme.text - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) } HoverHandler { id: cancelHov; cursorShape: Qt.PointingHandCursor } @@ -199,9 +200,9 @@ PanelWindow { } Rectangle { - width: 130 - height: 38 - radius: Theme.cornerRadius + width: Math.round(130 * localScale) + height: Math.round(38 * localScale) + radius: Math.round(Theme.cornerRadius * localScale) color: confirmHov.hovered ? "#cc3a3a" : "#993030" Behavior on color { ColorAnimation { duration: 120 } } @@ -209,7 +210,7 @@ PanelWindow { anchors.centerIn: parent text: Popups.confirmLabel color: "white" - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) font.bold: true } @@ -223,9 +224,9 @@ PanelWindow { // ── Processing card ─────────────────────────────────────────────────────── Rectangle { anchors.centerIn: parent - width: 300 - height: processingCol.implicitHeight + 56 - radius: Theme.notchRadius + width: Math.round(300 * localScale) + height: processingCol.implicitHeight + Math.round(56 * localScale) + radius: Math.round(Theme.notchRadius * localScale) color: Theme.background visible: Popups.confirmRunning @@ -237,17 +238,17 @@ PanelWindow { top: parent.top left: parent.left right: parent.right - topMargin: 28 - leftMargin: 24 - rightMargin: 24 + topMargin: Math.round(28 * localScale) + leftMargin: Math.round(24 * localScale) + rightMargin: Math.round(24 * localScale) } - spacing: 18 + spacing: Math.round(18 * localScale) Canvas { id: spinnerCanvas anchors.horizontalCenter: parent.horizontalCenter - width: 40 - height: 40 + width: Math.round(40 * localScale) + height: Math.round(40 * localScale) transformOrigin: Item.Center RotationAnimator { @@ -263,16 +264,16 @@ PanelWindow { onPaint: { var ctx = getContext("2d") ctx.clearRect(0, 0, width, height) - var cx = width / 2, cy = height / 2, r = 16 + var cx = width / 2, cy = height / 2, r = Math.round(16 * localScale) ctx.beginPath() ctx.arc(cx, cy, r, 0, 2 * Math.PI) ctx.strokeStyle = "rgba(255,255,255,0.1)" - ctx.lineWidth = 3 + ctx.lineWidth = Math.round(3 * localScale) ctx.stroke() ctx.beginPath() ctx.arc(cx, cy, r, -Math.PI / 2, Math.PI) ctx.strokeStyle = "white" - ctx.lineWidth = 3 + ctx.lineWidth = Math.round(3 * localScale) ctx.lineCap = "round" ctx.stroke() } @@ -284,7 +285,7 @@ PanelWindow { anchors.horizontalCenter: parent.horizontalCenter text: "Applying Changes" color: Theme.text - font.pixelSize: 15 + font.pixelSize: Math.round(15 * localScale) font.bold: true } @@ -294,7 +295,7 @@ PanelWindow { text: "Switching to " + Popups.confirmGfxMode + " graphics mode.
" + "Your system will reboot when finished." color: Qt.rgba(1, 1, 1, 0.55) - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) wrapMode: Text.WordWrap textFormat: Text.RichText lineHeight: 1.5 @@ -312,7 +313,7 @@ PanelWindow { anchors.horizontalCenter: parent.horizontalCenter text: "Do not turn off your computer." color: Qt.rgba(1, 1, 1, 0.3) - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) horizontalAlignment: Text.AlignHCenter } } diff --git a/src/windows/TopBar.qml b/src/windows/TopBar.qml index f177532..d5c9633 100644 --- a/src/windows/TopBar.qml +++ b/src/windows/TopBar.qml @@ -12,6 +12,9 @@ PanelWindow { property string screenName: screen ? screen.name : "" + // ── Context-Aware Scaling ───────────────────────────────────────────────── + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) + color: "transparent" anchors { @@ -27,30 +30,30 @@ PanelWindow { // ── Height shrinks to a border strip in focus mode ─────────────────────── // Safe to animate on PanelWindow (anchored, no position jank). // PopupWindow is the one that must never have animated implicitHeight. - implicitHeight: ShellState.focusMode ? Theme.borderWidth : Theme.notchHeight + implicitHeight: (ShellState.focusMode ? Math.round(Theme.borderWidth * root.localScale) : Math.round(Theme.notchHeight * root.localScale)) + 1 Behavior on implicitHeight { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - exclusiveZone: ShellState.focusMode ? 0 : Theme.exclusionGap + exclusiveZone: ShellState.focusMode ? 0 : Math.round(Theme.exclusionGap * root.localScale) Behavior on exclusiveZone { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } readonly property int lWidth: Math.max( - Theme.lNotchMinWidth, - Math.min(Theme.lNotchMaxWidth, - leftContent.implicitWidth + Theme.notchPadding * 2) + Math.round(Theme.lNotchMinWidth * root.localScale), + Math.min(Math.round(Theme.lNotchMaxWidth * root.localScale), + leftContent.implicitWidth + Math.round(Theme.notchPadding * 2 * root.localScale)) ) // cWidth uses Popups.dashboardPageWidth when the dashboard is open, // so the center notch tracks the active tab's declared width. property int cWidth: Popups.dashboardOpen - ? Popups.dashboardPageWidth + ? Math.min(Popups.dashboardPageWidth * root.localScale, (screen ? screen.width : 1920) * 0.95) : Math.max( - Theme.cNotchMinWidth, - Math.min(Theme.cNotchMaxWidth, - centerContent.implicitWidth + Theme.notchPadding * 2) + Math.round(Theme.cNotchMinWidth * root.localScale), + Math.min(Math.round(Theme.cNotchMaxWidth * root.localScale), + centerContent.implicitWidth + Math.round(Theme.notchPadding * 2 * root.localScale)) ) Behavior on cWidth { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } @@ -58,8 +61,8 @@ PanelWindow { // Width matches sizer open width: popupWidth + notchRadius (fw) in both popups property int rWidth: Math.max( - Theme.rNotchMinWidth, - Math.min(Theme.rNotchMaxWidth, rightContent.implicitWidth + Theme.notchPadding * 2) + Math.round(Theme.rNotchMinWidth * root.localScale), + Math.min(Math.round(Theme.rNotchMaxWidth * root.localScale), rightContent.implicitWidth + Math.round(Theme.notchPadding * 2 * root.localScale)) ) // ── Border strip (focus mode) ──────────────────────────────────────────── @@ -82,22 +85,22 @@ PanelWindow { Behavior on opacity { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } - + states: [ State { name: "notifications" when: Popups.notificationsOpen - PropertyChanges { target: root; rWidth: Theme.notificationsWidth + Theme.notchRadius } + PropertyChanges { target: root; rWidth: Math.round(((Theme.notificationsWidth * root.localScale) + (Theme.notchRadius * root.localScale)*1.5 -2)) } }, State { name: "network" when: Popups.networkOpen && !Popups.notificationsOpen - PropertyChanges { target: root; rWidth: Theme.networkPopupWidth + Theme.notchRadius } + PropertyChanges { target: root; rWidth: Math.round((Theme.networkPopupWidth * root.localScale) + (Theme.notchRadius * root.localScale)) } }, State { name: "toast" when: Popups.notificationToastOpen && !Popups.notificationsOpen && !Popups.networkOpen - PropertyChanges { target: root; rWidth: Theme.notificationToastWidth + Theme.notchRadius + Theme.notchPadding -3 } + PropertyChanges { target: root; rWidth: Math.round((Theme.notificationToastWidth * root.localScale) + (Theme.notchRadius * root.localScale) + (Theme.notchPadding * root.localScale)) } } ] @@ -114,16 +117,22 @@ PanelWindow { leftWidth: root.lWidth centerWidth: root.cWidth rightWidth: root.rWidth + notchHeight: Math.round(Theme.notchHeight * root.localScale) + radius: Math.round(Theme.notchRadius * root.localScale) + topBorderWidth: Math.round(Theme.borderWidth * root.localScale) } Item { id: leftNotch width: root.lWidth - height: Theme.notchHeight + height: Math.round((Theme.notchHeight - Theme.borderWidth) * root.localScale) anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: Math.round(Theme.borderWidth * root.localScale) LeftContent { id: leftContent + localScale: root.localScale anchors.centerIn: parent } } @@ -131,11 +140,14 @@ PanelWindow { Item { id: centerNotch width: root.cWidth - height: Theme.notchHeight + height: Math.round((Theme.notchHeight - Theme.borderWidth) * root.localScale) anchors.centerIn: parent + anchors.top: parent.top + anchors.topMargin: Math.round(Theme.borderWidth * root.localScale) CenterContent { id: centerContent + localScale: root.localScale anchors.centerIn: parent } } @@ -143,17 +155,20 @@ PanelWindow { Item { id: rightNotch width: root.rWidth - height: Theme.notchHeight + height: Math.round((Theme.notchHeight - Theme.borderWidth) * root.localScale) anchors.right: parent.right - + anchors.top: parent.top + anchors.topMargin: Math.round(Theme.borderWidth * root.localScale) + clip: true RightContent { id: rightContent + localScale: root.localScale anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - anchors.rightMargin: Theme.notchPadding + anchors.rightMargin: Math.round(Theme.notchPadding * root.localScale) } } } -} \ No newline at end of file +} diff --git a/src/windows/UpdatePopup.qml b/src/windows/UpdatePopup.qml index 3a86d24..18b7309 100644 --- a/src/windows/UpdatePopup.qml +++ b/src/windows/UpdatePopup.qml @@ -17,6 +17,7 @@ import "../" PanelWindow { id: root + readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) color: "transparent" anchors { top: true; left: true; right: true; bottom: true } @@ -67,14 +68,14 @@ PanelWindow { Rectangle { id: card anchors.centerIn: parent - width: 380 - radius: Theme.notchRadius + width: Math.round(380 * localScale) + radius: Math.round(Theme.notchRadius * localScale) color: Theme.background border.color: Qt.rgba(1, 1, 1, 0.08) border.width: 1 // Size to content - height: cardCol.implicitHeight + 48 + height: cardCol.implicitHeight + Math.round(48 * localScale) // Prevent clicks from hitting the dim MouseArea MouseArea { anchors.fill: parent } @@ -83,11 +84,11 @@ PanelWindow { Rectangle { anchors { left: parent.left - top: parent.top; topMargin: 10 - bottom: parent.bottom; bottomMargin: 10 + top: parent.top; topMargin: Math.round(10 * localScale) + bottom: parent.bottom; bottomMargin: Math.round(10 * localScale) } - width: 3 - radius: 2 + width: Math.round(3 * localScale) + radius: Math.round(2 * localScale) color: UpdateService.updateSuccess ? "#a6e3a1" : UpdateService.hasConflict ? "#f5c47a" : (UpdateService.lastError !== "" && @@ -97,17 +98,17 @@ PanelWindow { } Item { visible: !UpdateService.updating - anchors { top: parent.top; right: parent.right; topMargin: 8; rightMargin: 8 } - width: 24; height: 24 + anchors { top: parent.top; right: parent.right; topMargin: Math.round(8 * localScale); rightMargin: Math.round(8 * localScale) } + width: Math.round(24 * localScale); height: Math.round(24 * localScale) Rectangle { - anchors.fill: parent; radius: 6 + anchors.fill: parent; radius: Math.round(6 * localScale) color: xHov.hovered ? Qt.rgba(1,1,1,0.10) : "transparent" Behavior on color { ColorAnimation { duration: 100 } } } Text { anchors.centerIn: parent - text: "✕"; font.pixelSize: 11 + text: "✕"; font.pixelSize: Math.round(11 * localScale) color: Qt.rgba(1,1,1,0.35) } HoverHandler { id: xHov; cursorShape: Qt.PointingHandCursor } @@ -117,21 +118,21 @@ PanelWindow { Column { id: cardCol anchors { - top: parent.top; topMargin: 24 - left: parent.left; leftMargin: 22 - right: parent.right; rightMargin: 18 + top: parent.top; topMargin: Math.round(24 * localScale) + left: parent.left; leftMargin: Math.round(22 * localScale) + right: parent.right; rightMargin: Math.round(18 * localScale) } - spacing: 12 + spacing: Math.round(12 * localScale) // ── Header row ──────────────────────────────────────────────────── Row { width: parent.width - spacing: 10 + spacing: Math.round(10 * localScale) Text { id: headerIcon anchors.verticalCenter: parent.verticalCenter - font.pixelSize: 18 + font.pixelSize: Math.round(18 * localScale) text: UpdateService.updating || UpdateService.checking ? "󰑐" : UpdateService.updateSuccess ? "󰄬" : UpdateService.hasConflict ? "󰙨" @@ -156,7 +157,7 @@ PanelWindow { Text { anchors.verticalCenter: parent.verticalCenter - font.pixelSize: 13 + font.pixelSize: Math.round(13 * localScale) font.weight: Font.DemiBold color: Theme.text text: UpdateService.updating ? "Updating…" @@ -181,32 +182,32 @@ PanelWindow { !UpdateService.updateSuccess && UpdateService.lastError === "" width: parent.width - spacing: 10 + spacing: Math.round(10 * localScale) Text { text: UpdateService.commitsBehind + " new commit" + (UpdateService.commitsBehind === 1 ? "" : "s") + " on main" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.55) } Column { width: parent.width - spacing: 4 + spacing: Math.round(4 * localScale) Repeater { model: Math.min(3, UpdateService.commitMessages.length) delegate: Row { - spacing: 8 + spacing: Math.round(8 * localScale) Text { text: "·" - font.pixelSize: 11 + font.pixelSize: Math.round(11 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.60) anchors.verticalCenter: parent.verticalCenter } Text { - width: parent.parent.width - 18 - font.pixelSize: 11 + width: parent.parent.width - Math.round(18 * localScale) + font.pixelSize: Math.round(11 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.55) elide: Text.ElideRight // Strip the short hash prefix from the commit line @@ -222,18 +223,18 @@ PanelWindow { Text { visible: UpdateService.commitMessages.length > 3 text: "+ " + (UpdateService.commitMessages.length - 3) + " more" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.40) - leftPadding: 16 + leftPadding: Math.round(16 * localScale) } } Row { - spacing: 8 + spacing: Math.round(8 * localScale) // Update Now Rectangle { - width: 108; height: 30; radius: 8 + width: Math.round(108 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: uH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.26) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.13) @@ -243,7 +244,7 @@ PanelWindow { Text { anchors.centerIn: parent text: "Update Now" - font.pixelSize: 11; font.weight: Font.Medium + font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: Theme.active } HoverHandler { id: uH; cursorShape: Qt.PointingHandCursor } @@ -252,22 +253,22 @@ PanelWindow { // Skip (dismiss this check) Rectangle { - width: 58; height: 30; radius: 8 + width: Math.round(58 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: skH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "Skip"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.52) } + Text { anchors.centerIn: parent; text: "Skip"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: skH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } } // Disable auto-update Rectangle { - width: 82; height: 30; radius: 8 + width: Math.round(82 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: disH.hovered ? Qt.rgba(1,1,1,0.06) : "transparent" border.color: Qt.rgba(1,1,1,0.07); border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "Disable"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.28) } + Text { anchors.centerIn: parent; text: "Disable"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.28) } HoverHandler { id: disH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.disableAutoUpdate() } } @@ -278,18 +279,18 @@ PanelWindow { Column { visible: UpdateService.updating width: parent.width - spacing: 6 + spacing: Math.round(6 * localScale) Text { text: "Pulling latest changes from origin/main…" - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.55) wrapMode: Text.WordWrap width: parent.width } Text { text: "Do not close the shell." - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(1, 1, 1, 0.25) } } @@ -298,12 +299,12 @@ PanelWindow { Column { visible: UpdateService.hasConflict && !UpdateService.updating width: parent.width - spacing: 12 + spacing: Math.round(12 * localScale) Text { text: "Local uncommitted changes conflict with the update.\n" + "Stash them aside to proceed, or cancel." - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.55) wrapMode: Text.WordWrap width: parent.width @@ -311,11 +312,11 @@ PanelWindow { } Row { - spacing: 8 + spacing: Math.round(8 * localScale) // Stash & Update Rectangle { - width: 128; height: 30; radius: 8 + width: Math.round(128 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: saH.hovered ? Qt.rgba(245/255, 196/255, 122/255, 0.22) : Qt.rgba(245/255, 196/255, 122/255, 0.10) @@ -324,7 +325,7 @@ PanelWindow { Text { anchors.centerIn: parent text: "Stash & Update" - font.pixelSize: 11; font.weight: Font.Medium + font.pixelSize: Math.round(11 * localScale); font.weight: Font.Medium color: "#f5c47a" } HoverHandler { id: saH; cursorShape: Qt.PointingHandCursor } @@ -333,11 +334,11 @@ PanelWindow { // Cancel Rectangle { - width: 72; height: 30; radius: 8 + width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: cxH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.52) } + Text { anchors.centerIn: parent; text: "Cancel"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: cxH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } } @@ -348,11 +349,11 @@ PanelWindow { Column { visible: UpdateService.updateSuccess width: parent.width - spacing: 12 + spacing: Math.round(12 * localScale) Text { text: "Shell updated successfully.\nReload to apply the changes." - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.55) wrapMode: Text.WordWrap width: parent.width @@ -361,11 +362,11 @@ PanelWindow { // Dismiss Rectangle { - width: 72; height: 30; radius: 8 + width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: dmH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "Dismiss"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.52) } + Text { anchors.centerIn: parent; text: "Dismiss"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: dmH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } } @@ -373,7 +374,7 @@ PanelWindow { Text { text: "Auto-dismissing in a few seconds…" - font.pixelSize: 10 + font.pixelSize: Math.round(10 * localScale) color: Qt.rgba(1, 1, 1, 0.22) } } @@ -384,40 +385,40 @@ PanelWindow { !UpdateService.updating && !UpdateService.hasConflict width: parent.width - spacing: 12 + spacing: Math.round(12 * localScale) Text { text: UpdateService.lastError - font.pixelSize: 12 + font.pixelSize: Math.round(12 * localScale) color: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.55) wrapMode: Text.WordWrap width: parent.width } Row { - spacing: 8 + spacing: Math.round(8 * localScale) // Retry Rectangle { - width: 72; height: 30; radius: 8 + width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: rtH.hovered ? Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.22) : Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.09) border.color: Qt.rgba(Theme.active.r, Theme.active.g, Theme.active.b, 0.30) border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "Retry"; font.pixelSize: 11; color: Theme.active } + Text { anchors.centerIn: parent; text: "Retry"; font.pixelSize: Math.round(11 * localScale); color: Theme.active } HoverHandler { id: rtH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.check() } } // Close Rectangle { - width: 72; height: 30; radius: 8 + width: Math.round(72 * localScale); height: Math.round(30 * localScale); radius: Math.round(8 * localScale) color: clH.hovered ? Qt.rgba(1,1,1,0.08) : Qt.rgba(1,1,1,0.04) border.color: Qt.rgba(1,1,1,0.09); border.width: 1 Behavior on color { ColorAnimation { duration: 120 } } - Text { anchors.centerIn: parent; text: "Close"; font.pixelSize: 11; color: Qt.rgba(1,1,1,0.52) } + Text { anchors.centerIn: parent; text: "Close"; font.pixelSize: Math.round(11 * localScale); color: Qt.rgba(1,1,1,0.52) } HoverHandler { id: clH; cursorShape: Qt.PointingHandCursor } MouseArea { anchors.fill: parent; onClicked: UpdateService.dismiss() } } From 8c86dcbf522f85edbdc45b89182ad8367f880dd7 Mon Sep 17 00:00:00 2001 From: Brainitech Date: Thu, 18 Jun 2026 01:22:24 +0530 Subject: [PATCH 2/3] fix: Notification Toast alignment --- src/popups/NotificationToast.qml | 23 ++++++++++++----------- src/windows/TopBar.qml | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/popups/NotificationToast.qml b/src/popups/NotificationToast.qml index 68036ee..4ea583a 100644 --- a/src/popups/NotificationToast.qml +++ b/src/popups/NotificationToast.qml @@ -12,22 +12,23 @@ PopupWindow { required property var anchorWindow readonly property real localScale: Math.max(0.75, Math.min(1.5, (screen ? screen.height : 1080.0) / 1080.0)) - readonly property int toastWidth: Math.round(Theme.notificationToastWidth * localScale) + fw/1.5 readonly property int fw: Math.round(Theme.notchRadius * localScale) readonly property int fh: Math.round(Theme.notchRadius * localScale) - implicitWidth: toastWidth + Math.round(fw/2) + Math.round(10 * localScale) + readonly property int toastWidth: Math.round(Theme.notificationToastWidth * localScale) + Math.round(10 * localScale) + + implicitWidth: toastWidth + fw + Math.round(10 * localScale) implicitHeight: Math.round(180 * localScale) anchor.window: root.anchorWindow anchor.rect: Qt.rect( - root.anchorWindow.width - Math.round(toastWidth/2) - Math.round(fw), + Math.round(root.anchorWindow.width - ((toastWidth + (fw*2)+ Theme.borderWidth)/2)), Math.round((-Theme.notchHeight / 2) * localScale), - toastWidth, - Math.round(Theme.notchHeight * localScale) + 0, + 0 ) - anchor.gravity: Edges.Bottom - anchor.adjustment: PopupAdjustment.None + anchor.gravity: Edges.Bottom + anchor.adjustment: PopupAdjustment.None color: "transparent" visible: windowVisible @@ -105,12 +106,12 @@ PopupWindow { clip: true - width: root.showing - ? root.toastWidth + root.fw + width: root.showing + ? root.toastWidth + root.fw : root.fw - height: root.showing - ? (cardCol.y + cardCol.implicitHeight + Math.round(24 * root.localScale) + root.fh) + height: root.showing + ? (cardCol.y + cardCol.implicitHeight + Math.round(24 * root.localScale) + root.fh) : root.fh Behavior on width { NumberAnimation { duration: Theme.animDuration; easing.type: Easing.InOutCubic } } diff --git a/src/windows/TopBar.qml b/src/windows/TopBar.qml index d5c9633..fd586bd 100644 --- a/src/windows/TopBar.qml +++ b/src/windows/TopBar.qml @@ -100,7 +100,7 @@ PanelWindow { State { name: "toast" when: Popups.notificationToastOpen && !Popups.notificationsOpen && !Popups.networkOpen - PropertyChanges { target: root; rWidth: Math.round((Theme.notificationToastWidth * root.localScale) + (Theme.notchRadius * root.localScale) + (Theme.notchPadding * root.localScale)) } + PropertyChanges { target: root; rWidth: Math.round(Theme.notificationToastWidth * root.localScale) + Math.round(Theme.notchRadius * 2 * root.localScale) } } ] From 5f61d61e21af9f4722749f15fe3234942bc16e93 Mon Sep 17 00:00:00 2001 From: Brainitech Date: Fri, 19 Jun 2026 17:00:12 +0530 Subject: [PATCH 3/3] fix: Network Popup positional scaling --- src/popups/NetworkPopup.qml | 4 ++-- src/windows/TopBar.qml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/popups/NetworkPopup.qml b/src/popups/NetworkPopup.qml index d2ac2a4..f9eedad 100644 --- a/src/popups/NetworkPopup.qml +++ b/src/popups/NetworkPopup.qml @@ -80,8 +80,8 @@ PanelWindow { clip: true width: Popups.networkOpen - ? root.popupWidth + Math.round(9 * root.localScale) - : Math.round(Theme.rNotchMinWidth * root.localScale) + root.fw + ? root.popupWidth + root.fw + : Math.round(Theme.rNotchMinWidth * root.localScale) + root.fw height: Popups.networkOpen ? root.popupHeight : 0 diff --git a/src/windows/TopBar.qml b/src/windows/TopBar.qml index fd586bd..a873808 100644 --- a/src/windows/TopBar.qml +++ b/src/windows/TopBar.qml @@ -95,7 +95,7 @@ PanelWindow { State { name: "network" when: Popups.networkOpen && !Popups.notificationsOpen - PropertyChanges { target: root; rWidth: Math.round((Theme.networkPopupWidth * root.localScale) + (Theme.notchRadius * root.localScale)) } + PropertyChanges { target: root; rWidth: Math.round(Theme.networkPopupWidth * root.localScale) + Math.round(Theme.notchRadius * root.localScale) + Math.round(Theme.borderWidth * root.localScale) } }, State { name: "toast"