diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 58a4870ab..c2e4795d4 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Bluetooth aktivieren", "enable-dnd": "'Nicht stören' aktivieren", "enable-wifi": "WLAN aktivieren", + "lower-to-bottom": "Senken bis zum Anschlag / Ganz nach unten senken", "next": "Nächste/r/s", "open-calendar": "Kalender öffnen", "open-display-settings": "Anzeigeeinstellungen", @@ -582,7 +583,9 @@ "pause": "Pause", "play": "Spielen", "previous": "Vorherige", + "raise-to-top": "Nach oben verschieben", "random-wallpaper": "Zufälliges Hintergrundbild", + "reset-scale": "Waage zurücksetzen", "toggle-mute": "Stummschaltung umschalten", "widget-settings": "Widget-Einstellungen" }, diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index dc372cffb..290b3ac69 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Enable Bluetooth", "enable-dnd": "Enable Do Not Disturb", "enable-wifi": "Enable Wi-Fi", + "lower-to-bottom": "Lower to bottom", "next": "Next", "open-calendar": "Open calendar", "open-display-settings": "Display settings", @@ -582,7 +583,9 @@ "pause": "Pause", "play": "Play", "previous": "Previous", + "raise-to-top": "Raise to top", "random-wallpaper": "Random wallpaper", + "reset-scale": "Reset scale", "toggle-mute": "Toggle mute", "widget-settings": "Widget settings" }, diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 722b37978..b92fef175 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Activar Bluetooth", "enable-dnd": "Activar No molestar", "enable-wifi": "Activar Wi-Fi", + "lower-to-bottom": "Bajar hasta el fondo", "next": "Siguiente", "open-calendar": "Abrir calendario", "open-display-settings": "Configuración de pantalla", @@ -582,7 +583,9 @@ "pause": "Pausa", "play": "Reproducir", "previous": "Anterior", + "raise-to-top": "Subir al principio", "random-wallpaper": "Fondo de pantalla aleatorio", + "reset-scale": "Restablecer escala", "toggle-mute": "Activar/desactivar silencio", "widget-settings": "Configuración del widget" }, diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 6ffdbc18f..fcf54768b 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Activer le Bluetooth", "enable-dnd": "Activer le mode Ne pas déranger", "enable-wifi": "Activer le Wi-Fi", + "lower-to-bottom": "Abaisser au plus bas / Descendre au plus bas", "next": "Suivant", "open-calendar": "Ouvrir le calendrier", "open-display-settings": "Paramètres d'affichage", @@ -582,7 +583,9 @@ "pause": "Pause", "play": "Jouer", "previous": "Précédent", + "raise-to-top": "Remonter en haut", "random-wallpaper": "Fond d'écran aléatoire", + "reset-scale": "Réinitialiser l'échelle", "toggle-mute": "Activer/désactiver le mode muet", "widget-settings": "Paramètres du widget" }, diff --git a/Assets/Translations/hu.json b/Assets/Translations/hu.json index 15636c938..25ddb7ac5 100644 --- a/Assets/Translations/hu.json +++ b/Assets/Translations/hu.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Bluetooth bekapcsolása", "enable-dnd": "Ne zavarjanak bekapcsolása", "enable-wifi": "Wi-Fi bekapcsolása", + "lower-to-bottom": "Engedd le a legaljára / Engedd le az aljára", "next": "Következő", "open-calendar": "Naptár megnyitása", "open-display-settings": "Kijelzőbeállítások", @@ -582,7 +583,9 @@ "pause": "Szünet", "play": "Lejátszás", "previous": "Előző", + "raise-to-top": "Felülre emelés", "random-wallpaper": "Véletlenszerű háttérkép", + "reset-scale": "Mérleg nullázása", "toggle-mute": "Némítás kapcsolása", "widget-settings": "Widget beállítások" }, diff --git a/Assets/Translations/ja.json b/Assets/Translations/ja.json index de8e72dba..cd54c3346 100644 --- a/Assets/Translations/ja.json +++ b/Assets/Translations/ja.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Bluetooth を有効化", "enable-dnd": "おやすみモードを有効化", "enable-wifi": "Wi-Fi を有効化", + "lower-to-bottom": "一番下まで下げてください。", "next": "次へ", "open-calendar": "カレンダーを開く", "open-display-settings": "ディスプレイ設定", @@ -582,7 +583,9 @@ "pause": "一時停止", "play": "再生", "previous": "前へ", + "raise-to-top": "一番上に移動", "random-wallpaper": "壁紙をランダムに変更", + "reset-scale": "スケールをリセット", "toggle-mute": "ミュート切り替え", "widget-settings": "ウィジェット設定" }, diff --git a/Assets/Translations/nl.json b/Assets/Translations/nl.json index 6ce7f987e..d4962dd17 100644 --- a/Assets/Translations/nl.json +++ b/Assets/Translations/nl.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Bluetooth inschakelen", "enable-dnd": "Niet Storen inschakelen", "enable-wifi": "Wi-Fi inschakelen", + "lower-to-bottom": "Laagste naar beneden", "next": "Volgende", "open-calendar": "Open agenda", "open-display-settings": "Beeldscherminstellingen", @@ -582,7 +583,9 @@ "pause": "Pauze", "play": "Spelen", "previous": "Vorige", + "raise-to-top": "Naar boven halen", "random-wallpaper": "Willekeurige achtergrond", + "reset-scale": "Schaal resetten", "toggle-mute": "Dempen aan/uit", "widget-settings": "Widgetinstellingen" }, diff --git a/Assets/Translations/pl.json b/Assets/Translations/pl.json index 4ba07a795..a1ec933a5 100644 --- a/Assets/Translations/pl.json +++ b/Assets/Translations/pl.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Włącz Bluetooth", "enable-dnd": "Włącz Nie przeszkadzać", "enable-wifi": "Włącz Wi-Fi", + "lower-to-bottom": "Opuść na dół.", "next": "Następny", "open-calendar": "Otwórz kalendarz", "open-display-settings": "Ustawienia ekranu", @@ -582,7 +583,9 @@ "pause": "Wstrzymaj", "play": "Odtwarzaj", "previous": "Poprzedni", + "raise-to-top": "Przenieś na górę", "random-wallpaper": "Losowa tapeta", + "reset-scale": "Zresetuj skalę", "toggle-mute": "Przełącz wyciszenie", "widget-settings": "Ustawienia widżetu" }, diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index efc89dce1..42655b41d 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Ativar Bluetooth", "enable-dnd": "Ativar Não Perturbe", "enable-wifi": "Ativar Wi-Fi", + "lower-to-bottom": "Abaixar para o fundo", "next": "Próximo(a)", "open-calendar": "Abrir calendário", "open-display-settings": "Configurações de exibição", @@ -582,7 +583,9 @@ "pause": "Pausa", "play": "Jogar", "previous": "Anterior", + "raise-to-top": "Elevar ao topo", "random-wallpaper": "Papel de parede aleatório", + "reset-scale": "Redefinir escala", "toggle-mute": "Alternar mudo", "widget-settings": "Configurações do widget" }, diff --git a/Assets/Translations/ru.json b/Assets/Translations/ru.json index af49bd731..cc52ad0e6 100644 --- a/Assets/Translations/ru.json +++ b/Assets/Translations/ru.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Включить Bluetooth", "enable-dnd": "Не беспокоить", "enable-wifi": "Включить Wi-Fi", + "lower-to-bottom": "Опустить до дна", "next": "Следующий", "open-calendar": "Открыть календарь", "open-display-settings": "Настройки экрана", @@ -582,7 +583,9 @@ "pause": "Пауза", "play": "Играть", "previous": "Предыдущий", + "raise-to-top": "Поднять наверх", "random-wallpaper": "Случайные обои", + "reset-scale": "Сбросить масштаб", "toggle-mute": "Включить/выключить звук", "widget-settings": "Настройки виджета" }, diff --git a/Assets/Translations/tr.json b/Assets/Translations/tr.json index d489675f2..0762859d9 100644 --- a/Assets/Translations/tr.json +++ b/Assets/Translations/tr.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Bluetooth'u etkinleştir", "enable-dnd": "Rahatsız Etmeyin'i Etkinleştir", "enable-wifi": "Kablosuz Bağlantıyı etkinleştir", + "lower-to-bottom": "Alta doğru alçalt", "next": "Sonraki", "open-calendar": "Takvimi aç", "open-display-settings": "Ekran ayarları", @@ -582,7 +583,9 @@ "pause": "Duraklat", "play": "Oynat", "previous": "Önceki", + "raise-to-top": "En üste taşı", "random-wallpaper": "Rastgele duvar kâğıdı", + "reset-scale": "Ölçeği sıfırla", "toggle-mute": "Sesi kapat/aç", "widget-settings": "Araç takımı ayarları" }, diff --git a/Assets/Translations/uk-UA.json b/Assets/Translations/uk-UA.json index c490075e1..94fae078f 100644 --- a/Assets/Translations/uk-UA.json +++ b/Assets/Translations/uk-UA.json @@ -573,6 +573,7 @@ "enable-bluetooth": "Увімкнути Bluetooth", "enable-dnd": "Увімкнути режим \"Не турбувати\"", "enable-wifi": "Увімкнути Wi-Fi", + "lower-to-bottom": "Опустити донизу", "next": "Наступний", "open-calendar": "Відкрити календар", "open-display-settings": "Параметри дисплея", @@ -582,7 +583,9 @@ "pause": "Пауза", "play": "Відтворити", "previous": "Попередній", + "raise-to-top": "Підняти вгору", "random-wallpaper": "Випадкові шпалери", + "reset-scale": "Скинути масштаб", "toggle-mute": "Увімкнути/вимкнути звук", "widget-settings": "Налаштування віджета" }, diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index dd3ea2633..a5ccde306 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -573,6 +573,7 @@ "enable-bluetooth": "启用蓝牙", "enable-dnd": "启用勿扰模式", "enable-wifi": "启用 Wi-Fi", + "lower-to-bottom": "降至底部", "next": "下一首", "open-calendar": "打开日历", "open-display-settings": "显示设置", @@ -582,7 +583,9 @@ "pause": "暂停", "play": "播放", "previous": "上一首", + "raise-to-top": "置顶", "random-wallpaper": "随机壁纸", + "reset-scale": "重置比例", "toggle-mute": "切换静音", "widget-settings": "小部件设置" }, diff --git a/Modules/DesktopWidgets/DraggableDesktopWidget.qml b/Modules/DesktopWidgets/DraggableDesktopWidget.qml index ad62e5e94..5bf8e215d 100644 --- a/Modules/DesktopWidgets/DraggableDesktopWidget.qml +++ b/Modules/DesktopWidgets/DraggableDesktopWidget.qml @@ -26,7 +26,7 @@ Item { property real widgetScale: 1.0 property real minScale: 0.5 - property real maxScale: 3.0 + property real maxScale: 5.0 readonly property real scaleSensitivity: 0.0015 readonly property real scaleUpdateThreshold: 0.015 @@ -159,6 +159,54 @@ Item { } } + function raiseToTop() { + if (widgetIndex < 0 || !screen || !screen.name) { + return; + } + + var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || []; + var newMonitorWidgets = monitorWidgets.slice(); + + for (var i = 0; i < newMonitorWidgets.length; i++) { + if (newMonitorWidgets[i].name === screen.name) { + var widgets = (newMonitorWidgets[i].widgets || []).slice(); + if (widgetIndex < widgets.length && widgetIndex < widgets.length - 1) { + var widget = widgets.splice(widgetIndex, 1)[0]; + widgets.push(widget); + newMonitorWidgets[i] = Object.assign({}, newMonitorWidgets[i], { + "widgets": widgets + }); + Settings.data.desktopWidgets.monitorWidgets = newMonitorWidgets; + } + break; + } + } + } + + function lowerToBottom() { + if (widgetIndex < 0 || !screen || !screen.name) { + return; + } + + var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || []; + var newMonitorWidgets = monitorWidgets.slice(); + + for (var i = 0; i < newMonitorWidgets.length; i++) { + if (newMonitorWidgets[i].name === screen.name) { + var widgets = (newMonitorWidgets[i].widgets || []).slice(); + if (widgetIndex < widgets.length && widgetIndex > 0) { + var widget = widgets.splice(widgetIndex, 1)[0]; + widgets.unshift(widget); + newMonitorWidgets[i] = Object.assign({}, newMonitorWidgets[i], { + "widgets": widgets + }); + Settings.data.desktopWidgets.monitorWidgets = newMonitorWidgets; + } + break; + } + } + } + function openWidgetSettings() { if (!widgetData || !widgetData.id || !screen) { return; @@ -235,12 +283,36 @@ Item { } } - x: internal.isDragging ? internal.dragOffsetX : internal.baseX - y: internal.isDragging ? internal.dragOffsetY : internal.baseY + function handleContextMenuAction(action) { + if (action === "widget-settings") { + // Don't close - openWidgetSettings will use the popup window for the dialog + root.openWidgetSettings(); + return true; // Signal that we're handling close ourselves + } else if (action === "reset-scale") { + root.widgetScale = 1.0; + root.updateWidgetData({ + "scale": 1.0 + }); + return false; + } else if (action === "raise-to-top") { + root.raiseToTop(); + return false; + } else if (action === "lower-to-bottom") { + root.lowerToBottom(); + return false; + } else if (action === "delete") { + root.removeWidget(); + return false; // Let caller close the popup + } + return false; + } - // Scale from top-left corner to prevent position drift - scale: widgetScale - transformOrigin: Item.TopLeft + x: Math.round(internal.isDragging ? internal.dragOffsetX : internal.baseX) + y: Math.round(internal.isDragging ? internal.dragOffsetY : internal.baseY) + + // Note: We no longer use transform-based scaling (scale property) + // Instead, child widgets multiply their dimensions by widgetScale + // This prevents blurry text at fractional scale values Component.onCompleted: { // Initialize scale from widgetData when component is first created @@ -265,18 +337,18 @@ Item { Rectangle { id: decorationRect anchors.fill: parent - anchors.margins: -Style.marginS + anchors.margins: -outlineMargin color: DesktopWidgetRegistry.editMode ? Qt.rgba(Color.mPrimary.r, Color.mPrimary.g, Color.mPrimary.b, 0.1) : Color.transparent border.color: (DesktopWidgetRegistry.editMode || internal.isDragging) ? (internal.isDragging ? Color.mOutline : Color.mPrimary) : Color.transparent border.width: DesktopWidgetRegistry.editMode ? 3 : 0 - radius: Style.radiusL + radius: Math.round(Style.radiusL * root.widgetScale) z: -1 } Rectangle { id: container anchors.fill: parent - radius: root.roundedCorners ? Style.radiusL : 0 + radius: root.roundedCorners ? Math.round(Style.radiusL * root.widgetScale) : 0 color: Color.mSurface border { width: 1 @@ -325,6 +397,21 @@ Item { "icon": "settings" }); } + items.push({ + "label": I18n.tr("context-menu.reset-scale"), + "action": "reset-scale", + "icon": "aspect-ratio" + }); + items.push({ + "label": I18n.tr("context-menu.raise-to-top"), + "action": "raise-to-top", + "icon": "stack-front" + }); + items.push({ + "label": I18n.tr("context-menu.lower-to-bottom"), + "action": "lower-to-bottom", + "icon": "stack-back" + }); items.push({ "label": I18n.tr("context-menu.delete"), "action": "delete", @@ -333,18 +420,6 @@ Item { return items; } - function handleContextMenuAction(action) { - if (action === "widget-settings") { - // Don't close - openWidgetSettings will use the popup window for the dialog - root.openWidgetSettings(); - return true; // Signal that we're handling close ourselves - } else if (action === "delete") { - root.removeWidget(); - return false; // Let caller close the popup - } - return false; - } - // Drag MouseArea - handles dragging (left-click) MouseArea { id: dragArea @@ -381,9 +456,9 @@ Item { var newX = internal.dragOffsetX + deltaX; var newY = internal.dragOffsetY + deltaY; - // Boundary clamping - must account for scaled widget size - var scaledWidth = root.width * root.widgetScale; - var scaledHeight = root.height * root.widgetScale; + // Boundary clamping - widget dimensions already include scale + var scaledWidth = root.width; + var scaledHeight = root.height; if (root.parent && scaledWidth > 0 && scaledHeight > 0) { newX = Math.max(0, Math.min(newX, root.parent.width - scaledWidth)); newY = Math.max(0, Math.min(newY, root.parent.height - scaledHeight)); @@ -406,13 +481,15 @@ Item { onReleased: mouse => { if (internal.isDragging && internal.operationType === "drag" && widgetIndex >= 0 && screen && screen.name) { + var roundedX = Math.round(internal.dragOffsetX); + var roundedY = Math.round(internal.dragOffsetY); root.updateWidgetData({ - "x": internal.dragOffsetX, - "y": internal.dragOffsetY + "x": roundedX, + "y": roundedY }); - internal.baseX = internal.dragOffsetX; - internal.baseY = internal.dragOffsetY; + internal.baseX = roundedX; + internal.baseY = roundedY; internal.isDragging = false; internal.operationType = ""; } @@ -448,8 +525,8 @@ Item { } // Corner handles for scaling - using Repeater to avoid code duplication - readonly property real cornerHandleSize: 8 - readonly property real outlineMargin: Style.marginS + readonly property real cornerHandleSize: 8 * widgetScale + readonly property real outlineMargin: Style.marginS * widgetScale readonly property color colorHandle: Color.mSecondary // Corner handle model: defines position, direction, cursor, and triangle points for each corner @@ -501,8 +578,9 @@ Item { required property int index visible: DesktopWidgetRegistry.editMode && !internal.isDragging - x: modelData.xMult * (root.width + outlineMargin) - (modelData.xMult === 0 ? outlineMargin : cornerHandleSize) - y: modelData.yMult * (root.height + outlineMargin) - (modelData.yMult === 0 ? outlineMargin : cornerHandleSize) + // Position handles at corners of decoration rectangle (which extends by outlineMargin) + x: modelData.xMult === 0 ? -outlineMargin : (root.width + outlineMargin - cornerHandleSize) + y: modelData.yMult === 0 ? -outlineMargin : (root.height + outlineMargin - cornerHandleSize) width: cornerHandleSize height: cornerHandleSize z: 2000 diff --git a/Modules/DesktopWidgets/Widgets/DesktopClock.qml b/Modules/DesktopWidgets/Widgets/DesktopClock.qml index ebf83942b..e669d47f4 100644 --- a/Modules/DesktopWidgets/Widgets/DesktopClock.qml +++ b/Modules/DesktopWidgets/Widgets/DesktopClock.qml @@ -21,7 +21,8 @@ DraggableDesktopWidget { } readonly property real fontSize: { var size = widgetData && widgetData.fontSize ? widgetData.fontSize : 0; - return (size && size > 0) ? size : Style.fontSizeXXXL * 2.5; + var baseSize = (size && size > 0) ? size : Style.fontSizeXXXL * 2.5; + return Math.round(baseSize * widgetScale); } readonly property real widgetOpacity: (widgetData && widgetData.opacity !== undefined) ? widgetData.opacity : 1.0 readonly property string clockStyle: (widgetData && widgetData.clockStyle !== undefined) ? widgetData.clockStyle : (widgetMetadata.clockStyle !== undefined ? widgetMetadata.clockStyle : "digital") @@ -30,9 +31,9 @@ DraggableDesktopWidget { readonly property string customFont: (widgetData && widgetData.customFont !== undefined) ? widgetData.customFont : "" readonly property string format: (widgetData && widgetData.format !== undefined) ? widgetData.format : (widgetMetadata.format !== undefined ? widgetMetadata.format : "HH:mm\\nd MMMM yyyy") - readonly property real contentPadding: clockStyle === "minimal" ? Style.marginL : Style.marginXL - implicitWidth: contentLoader.item ? (contentLoader.item.implicitWidth || contentLoader.item.width || 0) + contentPadding * 2 : 0 - implicitHeight: contentLoader.item ? (contentLoader.item.implicitHeight || contentLoader.item.height || 0) + contentPadding * 2 : 0 + readonly property real contentPadding: Math.round((clockStyle === "minimal" ? Style.marginL : Style.marginXL) * widgetScale) + implicitWidth: contentLoader.item ? Math.round((contentLoader.item.implicitWidth || contentLoader.item.width || 0) + contentPadding * 2) : 0 + implicitHeight: contentLoader.item ? Math.round((contentLoader.item.implicitHeight || contentLoader.item.height || 0) + contentPadding * 2) : 0 width: implicitWidth height: implicitHeight @@ -49,6 +50,7 @@ DraggableDesktopWidget { width: height hoursFontSize: fontSize * 0.6 minutesFontSize: fontSize * 0.4 + scaleRatio: root.widgetScale } } @@ -66,9 +68,9 @@ DraggableDesktopWidget { family: root.useCustomFont && root.customFont ? root.customFont : Settings.data.ui.fontDefault pointSize: { if (model.length == 1) { - return Style.fontSizeXXL; + return Math.round(Style.fontSizeXXL * root.widgetScale); } else { - return (index == 0) ? Style.fontSizeXXL : Style.fontSizeM; + return Math.round((index == 0) ? Style.fontSizeXXL * root.widgetScale : Style.fontSizeM * root.widgetScale); } } font.weight: Style.fontWeightBold diff --git a/Modules/DesktopWidgets/Widgets/DesktopMediaPlayer.qml b/Modules/DesktopWidgets/Widgets/DesktopMediaPlayer.qml index 732fa351b..dfd991eac 100644 --- a/Modules/DesktopWidgets/Widgets/DesktopMediaPlayer.qml +++ b/Modules/DesktopWidgets/Widgets/DesktopMediaPlayer.qml @@ -57,15 +57,15 @@ DraggableDesktopWidget { readonly property bool showNext: hasPlayer && MediaService.canGoNext readonly property int visibleButtonCount: root.showButtons ? (1 + (showPrev ? 1 : 0) + (showNext ? 1 : 0)) : 0 - implicitWidth: 400 * Style.uiScaleRatio - implicitHeight: 64 * Style.uiScaleRatio + Style.marginM * 2 + implicitWidth: Math.round(400 * Style.uiScaleRatio * widgetScale) + implicitHeight: Math.round(64 * Style.uiScaleRatio * widgetScale + Style.marginM * widgetScale * 2) width: implicitWidth height: implicitHeight // Background container with masking (only visible when showBackground is true) Item { anchors.fill: parent - anchors.margins: Style.marginXS + anchors.margins: Math.round(Style.marginXS * widgetScale) z: 0 clip: true visible: root.showBackground @@ -78,9 +78,9 @@ DraggableDesktopWidget { maskSpreadAtMin: 0.0 maskSource: ShaderEffectSource { sourceItem: Rectangle { - width: root.width - Style.marginXS * 2 - height: root.height - Style.marginXS * 2 - radius: root.roundedCorners ? Math.max(0, Style.radiusL - Style.marginXS) : 0 + width: root.width - Math.round(Style.marginXS * widgetScale) * 2 + height: root.height - Math.round(Style.marginXS * widgetScale) * 2 + radius: root.roundedCorners ? Math.round(Math.max(0, (Style.radiusL - Style.marginXS) * widgetScale)) : 0 color: "white" antialiasing: true smooth: true @@ -103,9 +103,9 @@ DraggableDesktopWidget { // Visualizer overlay (visibility controlled by visualizerVisibility setting) Loader { anchors.fill: parent - anchors.leftMargin: Style.marginXS - anchors.rightMargin: Style.marginXS - anchors.topMargin: Style.marginXS + anchors.leftMargin: Math.round(Style.marginXS * widgetScale) + anchors.rightMargin: Math.round(Style.marginXS * widgetScale) + anchors.topMargin: Math.round(Style.marginXS * widgetScale) anchors.bottomMargin: 0 z: 0 clip: true @@ -120,9 +120,9 @@ DraggableDesktopWidget { maskSpreadAtMin: 0.0 maskSource: ShaderEffectSource { sourceItem: Rectangle { - width: root.width - Style.marginXS * 2 - height: root.height - Style.marginXS - radius: root.roundedCorners ? Math.max(0, Style.radiusL - Style.marginXS) : 0 + width: root.width - Math.round(Style.marginXS * widgetScale) * 2 + height: root.height - Math.round(Style.marginXS * widgetScale) + radius: root.roundedCorners ? Math.round(Math.max(0, (Style.radiusL - Style.marginXS) * widgetScale)) : 0 color: "white" antialiasing: true smooth: true @@ -204,14 +204,14 @@ DraggableDesktopWidget { } } ] - anchors.margins: Style.marginM - spacing: Style.marginS + anchors.margins: Math.round(Style.marginM * widgetScale) + spacing: Math.round(Style.marginS * widgetScale) z: 2 Item { visible: root.showAlbumArt - Layout.preferredWidth: 64 * Style.uiScaleRatio - Layout.preferredHeight: 64 * Style.uiScaleRatio + Layout.preferredWidth: Math.round(64 * Style.uiScaleRatio * widgetScale) + Layout.preferredHeight: Math.round(64 * Style.uiScaleRatio * widgetScale) Layout.alignment: Qt.AlignVCenter NImageRounded { @@ -220,7 +220,7 @@ DraggableDesktopWidget { radius: width / 2 imagePath: MediaService.trackArtUrl fallbackIcon: isPlaying ? "media-pause" : "media-play" - fallbackIconSize: 20 * Style.uiScaleRatio + fallbackIconSize: Math.round(20 * Style.uiScaleRatio * widgetScale) borderWidth: 0 } @@ -228,7 +228,7 @@ DraggableDesktopWidget { visible: !hasPlayer anchors.centerIn: parent icon: "disc" - pointSize: 24 + pointSize: Math.round(24 * widgetScale) color: Color.mOnSurfaceVariant } } @@ -242,7 +242,7 @@ DraggableDesktopWidget { NText { Layout.fillWidth: true text: hasPlayer ? (MediaService.trackTitle || "Unknown Track") : "No media playing" - pointSize: Style.fontSizeS + pointSize: Math.round(Style.fontSizeS * widgetScale) font.weight: Style.fontWeightSemiBold color: Color.mOnSurface elide: Text.ElideRight @@ -253,7 +253,7 @@ DraggableDesktopWidget { visible: hasPlayer && MediaService.trackArtist Layout.fillWidth: true text: MediaService.trackArtist || "" - pointSize: Style.fontSizeXS + pointSize: Math.round(Style.fontSizeXS * widgetScale) font.weight: Style.fontWeightRegular color: Color.mOnSurfaceVariant elide: Text.ElideRight @@ -263,14 +263,14 @@ DraggableDesktopWidget { RowLayout { id: controlsRow - spacing: Style.marginXS + spacing: Math.round(Style.marginXS * widgetScale) z: 10 visible: root.showButtons Layout.alignment: root.showAlbumArt ? Qt.AlignVCenter : Qt.AlignCenter NIconButton { visible: showPrev - baseSize: 32 + baseSize: Math.round(32 * widgetScale) icon: "media-prev" enabled: hasPlayer && MediaService.canGoPrevious colorBg: Color.mSurfaceVariant @@ -282,7 +282,7 @@ DraggableDesktopWidget { } NIconButton { - baseSize: 36 + baseSize: Math.round(36 * widgetScale) icon: isPlaying ? "media-pause" : "media-play" enabled: hasPlayer && (MediaService.canPlay || MediaService.canPause) colorBg: Color.mPrimary @@ -298,7 +298,7 @@ DraggableDesktopWidget { NIconButton { visible: showNext - baseSize: 32 + baseSize: Math.round(32 * widgetScale) icon: "media-next" enabled: hasPlayer && MediaService.canGoNext colorBg: Color.mSurfaceVariant diff --git a/Modules/DesktopWidgets/Widgets/DesktopWeather.qml b/Modules/DesktopWidgets/Widgets/DesktopWeather.qml index 97e84ccf9..d868808d9 100644 --- a/Modules/DesktopWidgets/Widgets/DesktopWeather.qml +++ b/Modules/DesktopWidgets/Widgets/DesktopWeather.qml @@ -44,47 +44,47 @@ DraggableDesktopWidget { return chunks[0]; } - implicitWidth: Math.max(240 * Style.uiScaleRatio, contentLayout.implicitWidth + Style.marginM * 2) - implicitHeight: 64 * Style.uiScaleRatio + Style.marginM * 2 + implicitWidth: Math.round(Math.max(240 * Style.uiScaleRatio * widgetScale, contentLayout.implicitWidth + Style.marginM * widgetScale * 2)) + implicitHeight: Math.round(64 * Style.uiScaleRatio * widgetScale + Style.marginM * widgetScale * 2) width: implicitWidth height: implicitHeight RowLayout { id: contentLayout anchors.fill: parent - anchors.margins: Style.marginM - spacing: Style.marginM + anchors.margins: Math.round(Style.marginM * widgetScale) + spacing: Math.round(Style.marginM * widgetScale) z: 2 Item { - Layout.preferredWidth: 64 * Style.uiScaleRatio - Layout.preferredHeight: 64 * Style.uiScaleRatio + Layout.preferredWidth: Math.round(64 * Style.uiScaleRatio * widgetScale) + Layout.preferredHeight: Math.round(64 * Style.uiScaleRatio * widgetScale) Layout.alignment: Qt.AlignVCenter NIcon { anchors.centerIn: parent icon: weatherReady ? LocationService.weatherSymbolFromCode(currentWeatherCode) : "cloud" - pointSize: Style.fontSizeXXXL * 2 + pointSize: Math.round(Style.fontSizeXXXL * 2 * widgetScale) color: weatherReady ? Color.mPrimary : Color.mOnSurfaceVariant } } NText { text: weatherReady ? `${currentTemp}°${tempUnit}` : "---" - pointSize: Style.fontSizeXXXL + pointSize: Math.round(Style.fontSizeXXXL * widgetScale) font.weight: Style.fontWeightBold color: Color.mOnSurface } ColumnLayout { Layout.fillWidth: true - spacing: Style.marginXXS + spacing: Math.round(Style.marginXXS * widgetScale) Layout.alignment: Qt.AlignVCenter NText { Layout.fillWidth: true text: locationName || "No location" - pointSize: Style.fontSizeS + pointSize: Math.round(Style.fontSizeS * widgetScale) font.weight: Style.fontWeightRegular color: Color.mOnSurfaceVariant elide: Text.ElideRight @@ -92,36 +92,36 @@ DraggableDesktopWidget { } RowLayout { - spacing: Style.marginXS + spacing: Math.round(Style.marginXS * widgetScale) visible: weatherReady && todayMax > 0 && todayMin > 0 NText { text: "H:" - pointSize: Style.fontSizeXS + pointSize: Math.round(Style.fontSizeXS * widgetScale) color: Color.mOnSurfaceVariant } NText { text: `${todayMax}°` - pointSize: Style.fontSizeXS + pointSize: Math.round(Style.fontSizeXS * widgetScale) font.weight: Style.fontWeightMedium color: Color.mOnSurface } NText { text: "•" - pointSize: Style.fontSizeXXS + pointSize: Math.round(Style.fontSizeXXS * widgetScale) color: Color.mOnSurfaceVariant opacity: 0.5 } NText { text: "L:" - pointSize: Style.fontSizeXS + pointSize: Math.round(Style.fontSizeXS * widgetScale) color: Color.mOnSurfaceVariant } NText { text: `${todayMin}°` - pointSize: Style.fontSizeXS + pointSize: Math.round(Style.fontSizeXS * widgetScale) font.weight: Style.fontWeightMedium color: Color.mOnSurfaceVariant } diff --git a/Modules/MainScreen/PopupMenuWindow.qml b/Modules/MainScreen/PopupMenuWindow.qml index b6255e634..6ac90ec67 100644 --- a/Modules/MainScreen/PopupMenuWindow.qml +++ b/Modules/MainScreen/PopupMenuWindow.qml @@ -65,6 +65,7 @@ PanelWindow { id: dynamicMenu visible: false screen: root.screen + minWidth: 180 onTriggered: (action, item) => { if (root.dynamicMenuCallback) { diff --git a/Widgets/NClock.qml b/Widgets/NClock.qml index b938962cc..7f9e3e361 100644 --- a/Widgets/NClock.qml +++ b/Widgets/NClock.qml @@ -53,6 +53,9 @@ Item { property real hoursFontSize: Style.fontSizeXS property real minutesFontSize: Style.fontSizeXXS + // Scale ratio for canvas line widths (used by desktop widget scaling) + property real scaleRatio: Style.uiScaleRatio + height: Math.round((Style.fontSizeXXXL * 1.9) / 2 * Style.uiScaleRatio) * 2 width: root.height @@ -98,6 +101,11 @@ Item { return root.minutesFontSize; }); } + if (item.hasOwnProperty("scaleRatio")) { + item.scaleRatio = Qt.binding(function () { + return root.scaleRatio; + }); + } } } @@ -107,6 +115,7 @@ Item { property color backgroundColor: Color.mPrimary property color clockColor: Color.mOnPrimary property color secondHandColor: Color.mError + property real scaleRatio: Style.uiScaleRatio anchors.fill: parent Canvas { @@ -134,7 +143,7 @@ Item { // Hour marks ctx.strokeStyle = Qt.alpha(clockColor, markAlpha); - ctx.lineWidth = 2 * Style.uiScaleRatio; + ctx.lineWidth = 2 * scaleRatio; var scaleFactor = 0.7; for (var i = 0; i < 12; i++) { @@ -156,7 +165,7 @@ Item { var hourAngle = (hours % 12 + minutes / 60) * Math.PI / 6; ctx.rotate(hourAngle); ctx.strokeStyle = clockColor; - ctx.lineWidth = 3 * Style.uiScaleRatio; + ctx.lineWidth = 3 * scaleRatio; ctx.lineCap = "round"; ctx.beginPath(); ctx.moveTo(0, 0); @@ -169,7 +178,7 @@ Item { var minuteAngle = (minutes + seconds / 60) * Math.PI / 30; ctx.rotate(minuteAngle); ctx.strokeStyle = clockColor; - ctx.lineWidth = 2 * Style.uiScaleRatio; + ctx.lineWidth = 2 * scaleRatio; ctx.lineCap = "round"; ctx.beginPath(); ctx.moveTo(0, 0); @@ -182,7 +191,7 @@ Item { var secondAngle = seconds * Math.PI / 30; ctx.rotate(secondAngle); ctx.strokeStyle = secondHandColor; - ctx.lineWidth = 1.6 * Style.uiScaleRatio; + ctx.lineWidth = 1.6 * scaleRatio; ctx.lineCap = "round"; ctx.beginPath(); ctx.moveTo(0, 0); @@ -192,7 +201,7 @@ Item { // Center dot ctx.beginPath(); - ctx.arc(0, 0, 3 * Style.uiScaleRatio, 0, 2 * Math.PI); + ctx.arc(0, 0, 3 * scaleRatio, 0, 2 * Math.PI); ctx.fillStyle = clockColor; ctx.fill(); } @@ -209,6 +218,7 @@ Item { property color progressColor: Color.mError property real hoursFontSize: Style.fontSizeXS property real minutesFontSize: Style.fontSizeXXS + property real scaleRatio: Style.uiScaleRatio anchors.fill: parent @@ -229,20 +239,20 @@ Item { var ctx = getContext("2d"); var centerX = width / 2; var centerY = height / 2; - var radius = Math.min(width, height) / 2 - 3; + var radius = Math.min(width, height) / 2 - 3 * scaleRatio; ctx.reset(); // Background circle ctx.beginPath(); ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI); - ctx.lineWidth = 2.5; + ctx.lineWidth = 2.5 * scaleRatio; ctx.strokeStyle = Qt.alpha(clockColor, 0.15); ctx.stroke(); // Progress arc ctx.beginPath(); ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + progress * 2 * Math.PI); - ctx.lineWidth = 2.5; + ctx.lineWidth = 2.5 * scaleRatio; ctx.strokeStyle = progressColor; ctx.lineCap = "round"; ctx.stroke(); diff --git a/Widgets/NPopupContextMenu.qml b/Widgets/NPopupContextMenu.qml index 674694ec0..deea14cfc 100644 --- a/Widgets/NPopupContextMenu.qml +++ b/Widgets/NPopupContextMenu.qml @@ -18,6 +18,7 @@ PopupWindow { property var anchorItem: null property ShellScreen screen: null + property real minWidth: 120 property real calculatedWidth: 180 readonly property string barPosition: Settings.data.bar.position @@ -74,7 +75,7 @@ PopupWindow { } } } - calculatedWidth = Math.max(maxWidth + (Style.marginS * 2), 120); + calculatedWidth = Math.max(maxWidth + (Style.marginS * 2), minWidth); } anchor.item: anchorItem