mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2025-12-06 06:36:15 +00:00
Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c9396f325 | ||
|
|
afccf048e7 | ||
|
|
f37625719d | ||
|
|
cad8fd671f | ||
|
|
68e76abfc7 | ||
|
|
45c8fe7782 | ||
|
|
5ebf4b5377 | ||
|
|
59fbe92fe4 | ||
|
|
b051e19f68 | ||
|
|
6b9370ac85 | ||
|
|
9702a300ca | ||
|
|
b043664617 | ||
|
|
368e80daf2 | ||
|
|
056217bf43 | ||
|
|
c1abb3a7dc | ||
|
|
52d2055699 | ||
|
|
e324a33137 | ||
|
|
6f4aa1a1a1 | ||
|
|
f49462f999 | ||
|
|
4fb1e2de1e | ||
|
|
6d05a20556 | ||
|
|
ec2fbb53dc | ||
|
|
fdc61acfe4 | ||
|
|
32712c7052 | ||
|
|
a0f6d14334 | ||
|
|
6ae8d8536e | ||
|
|
650dcb8811 | ||
|
|
970684e304 | ||
|
|
e786946abf | ||
|
|
da046cade6 | ||
|
|
43dee793de | ||
|
|
0a893f9c5f | ||
|
|
23887574cf | ||
|
|
2008ba85bc | ||
|
|
773318191d | ||
|
|
78cf0bc8a2 | ||
|
|
8b0e0f6e0e | ||
|
|
8c6b3a793f | ||
|
|
4c3eca80a4 | ||
|
|
f61f9a5809 | ||
|
|
518e90d910 | ||
|
|
d2e5d0664a | ||
|
|
602d79c98e | ||
|
|
4b13e89a64 | ||
|
|
1e8b122911 | ||
|
|
1f257ce847 | ||
|
|
df35589328 | ||
|
|
c92478d27d | ||
|
|
ffe39e0ec9 | ||
|
|
b12cf345dc | ||
|
|
fc4418be0c | ||
|
|
82bfa346a7 | ||
|
|
26ee5046f6 | ||
|
|
51ed6ea2b0 | ||
|
|
c53dd6fade | ||
|
|
bb24b6904d | ||
|
|
d5857e3363 | ||
|
|
559609be64 | ||
|
|
5cea61114b | ||
|
|
22794ea922 | ||
|
|
933ba54612 | ||
|
|
0d0b9a21f2 | ||
|
|
9ed9231070 | ||
|
|
b8b54825d5 | ||
|
|
250822e819 | ||
|
|
ece9789f6b | ||
|
|
f11d27bcf1 | ||
|
|
0e69256279 | ||
|
|
fa49d4aaa0 | ||
|
|
b1f7ae5d9a | ||
|
|
e6b0be77e7 | ||
|
|
49961882dd | ||
|
|
c1d2d82fa2 | ||
|
|
c35f37c7d7 | ||
|
|
e23cb90c5b | ||
|
|
b2688e9100 | ||
|
|
7f3842ddbf | ||
|
|
68b2c83be1 | ||
|
|
97fa2fb1b5 | ||
|
|
0ed8ed7fe5 | ||
|
|
a41be0b5d9 | ||
|
|
072d80e2f3 | ||
|
|
1f898171e0 | ||
|
|
ef64395dd4 | ||
|
|
a5c89fadb5 | ||
|
|
cccf0e6017 | ||
|
|
5da474007e | ||
|
|
ffd2cdaf74 | ||
|
|
5f3c088f22 | ||
|
|
382116e795 | ||
|
|
c7c49433f7 | ||
|
|
0d2d0f1931 | ||
|
|
2e947edc5a | ||
|
|
cdc32f3eac | ||
|
|
21736b3095 | ||
|
|
48852a9ca4 | ||
|
|
65fab7b367 | ||
|
|
dc414df9bc | ||
|
|
69a6c052db | ||
|
|
c422435d3d | ||
|
|
fc1742e167 | ||
|
|
061e7f32da | ||
|
|
8dda007847 | ||
|
|
1cdff28cca | ||
|
|
f32a34e320 | ||
|
|
0d0088bd52 | ||
|
|
a7a7a96585 | ||
|
|
026d602770 | ||
|
|
5b54be633d | ||
|
|
3bb10e9561 | ||
|
|
b9b233a873 | ||
|
|
388824bf37 | ||
|
|
25eb31747a | ||
|
|
f7109b0bf9 | ||
|
|
c41fa1aef7 | ||
|
|
1a0ea3893c | ||
|
|
0593543d7a | ||
|
|
fbf80ab577 | ||
|
|
b27728e5bf | ||
|
|
2379ad134b | ||
|
|
3ab9ffed78 | ||
|
|
3182d1969b | ||
|
|
591d099255 | ||
|
|
256f9b4a76 | ||
|
|
ff1509939a | ||
|
|
2c7038c504 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +0,0 @@
|
||||
.qmlls.ini
|
||||
|
||||
@@ -51,7 +51,7 @@ Singleton {
|
||||
lines.push("\n[templates.ghostty]")
|
||||
lines.push('input_path = "' + Quickshell.shellDir + '/Assets/Matugen/templates/ghostty.conf"')
|
||||
lines.push('output_path = "~/.config/ghostty/themes/noctalia"')
|
||||
lines.push("post_hook = \"grep -q '^theme *= *' ~/.config/ghostty/config; and sed -i 's/^theme *= *.*/theme = noctalia/' ~/.config/ghostty/config; or echo 'theme = noctalia' >> ~/.config/ghostty/config\"")
|
||||
lines.push("post_hook = \"grep -q '^theme *= *' ~/.config/ghostty/config; and sed -i 's/^theme *= *.*/theme = noctalia/' ~/.config/ghostty/config; or echo 'theme = noctalia' >> ~/.config/ghostty/config; and pkill -SIGUSR2 ghostty\"")
|
||||
}
|
||||
if (Settings.data.matugen.foot) {
|
||||
lines.push("\n[templates.foot]")
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"settings": {
|
||||
"general": {
|
||||
"title": "Allgemein",
|
||||
|
||||
"profile": {
|
||||
"section": {
|
||||
"label": "Profil",
|
||||
@@ -14,7 +13,6 @@
|
||||
},
|
||||
"select-avatar": "Avatar-Bild auswählen"
|
||||
},
|
||||
|
||||
"ui": {
|
||||
"section": {
|
||||
"label": "Benutzeroberfläche",
|
||||
@@ -31,6 +29,10 @@
|
||||
"animation-speed": {
|
||||
"label": "Animationsgeschwindigkeit",
|
||||
"description": "Globale Animationsgeschwindigkeit anpassen."
|
||||
},
|
||||
"animation-disable": {
|
||||
"label": "UI-Animationen deaktivieren",
|
||||
"description": "Alle Animationen für eine schnellere, reaktionsschnellere Erfahrung deaktivieren."
|
||||
}
|
||||
},
|
||||
"screen-corners": {
|
||||
@@ -60,20 +62,23 @@
|
||||
"label": "Standard-Schriftart",
|
||||
"description": "Hauptschriftart für die gesamte Benutzeroberfläche.",
|
||||
"placeholder": "Standard-Schriftart auswählen...",
|
||||
"search-placeholder": "Schriftarten suchen..."
|
||||
"search-placeholder": "Schriftarten suchen...",
|
||||
"scale": {
|
||||
"description": "Vergrößern oder verkleinern Sie die Größe des Standardtextes.",
|
||||
"label": "Standardmäßige Schriftgröße"
|
||||
}
|
||||
},
|
||||
"monospace": {
|
||||
"label": "Monospace-Schriftart",
|
||||
"description": "Monospace-Schriftart für Zahlen und Statistik-Anzeigen.",
|
||||
"placeholder": "Monospace-Schriftart auswählen...",
|
||||
"search-placeholder": "Monospace-Schriftarten suchen..."
|
||||
"search-placeholder": "Monospace-Schriftarten suchen...",
|
||||
"scale": {
|
||||
"description": "Die Größe des nichtproportionalen Textes vergrößern oder verkleinern.",
|
||||
"label": "Schriftgröße mit fester Breite"
|
||||
}
|
||||
},
|
||||
"accent": {
|
||||
"label": "Akzent-Schriftart",
|
||||
"description": "Große Schriftart für hervorgehobene Anzeigen.",
|
||||
"placeholder": "Display-Schriftart auswählen...",
|
||||
"search-placeholder": "Display-Schriftarten suchen..."
|
||||
}
|
||||
"reset-scaling": "Skalierung zurücksetzen"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
@@ -247,6 +252,10 @@
|
||||
"section": {
|
||||
"label": "Monitor-Anzeige",
|
||||
"description": "Statusleiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind."
|
||||
},
|
||||
"only-same-output": {
|
||||
"label": "Nur Apps vom gleichen Bildschirm",
|
||||
"description": "Zeige nur Apps vom dem Bildschirm an, wo sich das Dock befindet."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -278,6 +287,10 @@
|
||||
"section": {
|
||||
"label": "Monitor-Anzeige",
|
||||
"description": "Monitor auswählen, auf dem das Dock angezeigt werden soll."
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Zeige nur Apps aus der Ausgabe an, bei denen sich das Dock befindet.",
|
||||
"label": "Nur Apps von derselben Ausgabe"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -307,6 +320,10 @@
|
||||
"use-app2unit": {
|
||||
"label": "App2Unit zum Starten von Anwendungen verwenden",
|
||||
"description": "Verwendet eine alternative Startmethode zur besseren Verwaltung von App-Prozessen und Problemvermeidung."
|
||||
},
|
||||
"terminal-command": {
|
||||
"label": "Terminalbefehl",
|
||||
"description": "Befehl zum Starten eines Terminals. Z.B. 'kitty -e' oder 'gnome-terminal --'."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -487,7 +504,7 @@
|
||||
"predefined": {
|
||||
"section": {
|
||||
"label": "Vordefinierte Farbschemata",
|
||||
"description": "Um diese Farbschemata zu verwenden, müssen Sie Matugen ausschalten. Mit aktiviertem Matugen werden Farben automatisch aus Ihrem Hintergrundbild generiert."
|
||||
"description": "Wählen Sie aus einer Sammlung vordefinierter Farbschemata."
|
||||
}
|
||||
},
|
||||
"matugen": {
|
||||
@@ -829,21 +846,54 @@
|
||||
"search-placeholder": "Widgets suchen..."
|
||||
},
|
||||
"active-window": {
|
||||
"auto-hide": "Automatisch ausblenden",
|
||||
"scrolling-mode": "Scrollmodus",
|
||||
"show-app-icon": "App-Symbol anzeigen"
|
||||
"auto-hide": {
|
||||
"label": "Automatisch ausblenden",
|
||||
"description": "Widget automatisch ausblenden, wenn kein Fenster aktiv ist."
|
||||
},
|
||||
"show-app-icon": {
|
||||
"label": "App-Symbol anzeigen",
|
||||
"description": "Anwendungssymbol neben dem Fenstertitel anzeigen."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Scrollmodus",
|
||||
"description": "Steuern, wann Textscrolling für lange Fenstertitel aktiviert ist."
|
||||
}
|
||||
},
|
||||
"system-monitor": {
|
||||
"cpu-usage": "CPU-Auslastung",
|
||||
"cpu-temperature": "CPU-Temperatur",
|
||||
"memory-usage": "Speicherverbrauch",
|
||||
"memory-percentage": "Speicher als Prozentsatz",
|
||||
"network-traffic": "Netzwerkverkehr",
|
||||
"storage-usage": "Speichernutzung"
|
||||
"cpu-usage": {
|
||||
"label": "CPU-Auslastung",
|
||||
"description": "Aktuelle CPU-Auslastung in Prozent anzeigen."
|
||||
},
|
||||
"cpu-temperature": {
|
||||
"label": "CPU-Temperatur",
|
||||
"description": "CPU-Temperaturwerte anzeigen, falls verfügbar."
|
||||
},
|
||||
"memory-usage": {
|
||||
"label": "Speicherverbrauch",
|
||||
"description": "Aktuelle RAM-Nutzungsinformationen anzeigen."
|
||||
},
|
||||
"memory-percentage": {
|
||||
"label": "Speicher als Prozentsatz",
|
||||
"description": "Speicherverbrauch als Prozentsatz statt absolute Werte anzeigen."
|
||||
},
|
||||
"network-traffic": {
|
||||
"label": "Netzwerkverkehr",
|
||||
"description": "Upload- und Download-Geschwindigkeiten anzeigen."
|
||||
},
|
||||
"storage-usage": {
|
||||
"label": "Speichernutzung",
|
||||
"description": "Festplattenspeicher-Nutzungsinformationen anzeigen."
|
||||
}
|
||||
},
|
||||
"notification-history": {
|
||||
"show-unread-badge": "Badge für ungelesene Nachrichten anzeigen",
|
||||
"hide-badge-when-zero": "Badge ausblenden, wenn null"
|
||||
"show-unread-badge": {
|
||||
"label": "Badge für ungelesene Nachrichten anzeigen",
|
||||
"description": "Badge mit der Anzahl ungelesener Benachrichtigungen anzeigen."
|
||||
},
|
||||
"hide-badge-when-zero": {
|
||||
"label": "Badge ausblenden, wenn null",
|
||||
"description": "Benachrichtigungs-Badge ausblenden, wenn keine ungelesenen Benachrichtigungen vorhanden sind."
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"display-mode": {
|
||||
@@ -856,7 +906,10 @@
|
||||
}
|
||||
},
|
||||
"control-center": {
|
||||
"use-distro-logo": "Distro-Logo anstelle von Symbol verwenden",
|
||||
"use-distro-logo": {
|
||||
"label": "Distro-Logo anstelle von Symbol verwenden",
|
||||
"description": "Logo Ihrer Distribution anstelle eines benutzerdefinierten Symbols verwenden."
|
||||
},
|
||||
"icon": {
|
||||
"label": "Symbol",
|
||||
"description": "Symbol aus der Bibliothek oder eine benutzerdefinierte Datei auswählen."
|
||||
@@ -878,7 +931,10 @@
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"label-mode": "Beschriftungsmodus",
|
||||
"label-mode": {
|
||||
"label": "Beschriftungsmodus",
|
||||
"description": "Wählen Sie, wie Arbeitsbereichs-Beschriftungen angezeigt werden."
|
||||
},
|
||||
"hide-unoccupied": {
|
||||
"label": "Unbesetzte ausblenden",
|
||||
"description": "Arbeitsbereiche ohne Fenster nicht anzeigen."
|
||||
@@ -908,9 +964,18 @@
|
||||
"description": "Symbol aus der Bibliothek auswählen."
|
||||
},
|
||||
"browse": "Durchsuchen",
|
||||
"left-click": "Linksklick",
|
||||
"right-click": "Rechtsklick",
|
||||
"middle-click": "Mittelklick",
|
||||
"left-click": {
|
||||
"label": "Linksklick",
|
||||
"description": "Befehl, der ausgeführt wird, wenn die Schaltfläche links angeklickt wird."
|
||||
},
|
||||
"right-click": {
|
||||
"label": "Rechtsklick",
|
||||
"description": "Befehl, der ausgeführt wird, wenn die Schaltfläche rechts angeklickt wird."
|
||||
},
|
||||
"middle-click": {
|
||||
"label": "Mittelklick",
|
||||
"description": "Befehl, der ausgeführt wird, wenn die Schaltfläche mit der mittleren Maustaste angeklickt wird."
|
||||
},
|
||||
"dynamic-text": "Dynamischer Text",
|
||||
"display-command-output": {
|
||||
"label": "Befehlsausgabe anzeigen",
|
||||
@@ -922,11 +987,27 @@
|
||||
}
|
||||
},
|
||||
"media-mini": {
|
||||
"auto-hide": "Automatisch ausblenden",
|
||||
"show-album-art": "Albumcover anzeigen",
|
||||
"show-visualizer": "Visualizer anzeigen",
|
||||
"visualizer-type": "Visualizer-Typ",
|
||||
"scrolling-mode": "Scrollmodus"
|
||||
"auto-hide": {
|
||||
"label": "Automatisch ausblenden",
|
||||
"description": "Widget automatisch ausblenden, wenn keine Medien abgespielt werden."
|
||||
},
|
||||
"show-album-art": {
|
||||
"label": "Albumcover anzeigen",
|
||||
"description": "Albumcover des aktuell abgespielten Tracks anzeigen."
|
||||
},
|
||||
"show-visualizer": {
|
||||
"label": "Visualizer anzeigen",
|
||||
"description": "Audio-Visualizer anzeigen, wenn Musik abgespielt wird."
|
||||
},
|
||||
"visualizer-type": {
|
||||
"label": "Visualizer-Typ",
|
||||
"description": "Stil des Audio-Visualizers auswählen."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Scrollmodus",
|
||||
"description": "Steuern, wann Textscrolling für lange Track-Titel aktiviert ist."
|
||||
},
|
||||
"no-active-player": "Kein aktiver Player"
|
||||
},
|
||||
"clock": {
|
||||
"use-primary-color": {
|
||||
@@ -949,7 +1030,27 @@
|
||||
"label": "Vertikale Statusleiste",
|
||||
"description": "Verwenden Sie ein Leerzeichen, um jeden Teil in eine neue Zeile zu trennen."
|
||||
},
|
||||
"preview": "Vorschau"
|
||||
"preview": "Vorschau",
|
||||
"custom-font": {
|
||||
"description": "Wähle eine benutzerdefinierte Schriftart für die Uhrenanzeige aus.",
|
||||
"label": "Benutzerdefinierte Schriftart",
|
||||
"placeholder": "Benutzerdefinierte Schriftart auswählen...",
|
||||
"search-placeholder": "Schriftarten suchen..."
|
||||
},
|
||||
"use-custom-font": {
|
||||
"description": "Überschreibe die Standard-Schriftauswahl mit einer benutzerdefinierten Schriftart für die Uhr.",
|
||||
"label": "Benutzerdefinierte Schriftart verwenden"
|
||||
}
|
||||
},
|
||||
"taskbar": {
|
||||
"only-active-workspaces": {
|
||||
"label": "Nur von aktiven Arbeitsbereichen",
|
||||
"description": "Zeige nur Apps von aktiven Arbeitsbereichen an."
|
||||
},
|
||||
"only-same-output": {
|
||||
"label": "Nur vom gleichen Bildschirm",
|
||||
"description": "Zeige nur Apps vom dem Bildschirm an, wo sich die Taskbar befindet."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1088,13 +1189,16 @@
|
||||
"close": "Schließen"
|
||||
}
|
||||
},
|
||||
"launcher": {
|
||||
"pin": "An das Dock anheften",
|
||||
"unpin": "Vom Dock lösen"
|
||||
},
|
||||
"placeholders": {
|
||||
"search-icons": "z.B. noctalia, niri, battery, cloud",
|
||||
"profile-picture-path": "/home/benutzer/.face",
|
||||
"enter-width-pixels": "Breite in Pixeln eingeben",
|
||||
"enter-command": "Befehl eingeben (App oder benutzerdefiniertes Skript)",
|
||||
"command-example": "echo \"Hallo Welt\"",
|
||||
|
||||
"search-wallpapers": "Zum Filtern von Hintergrundbildern eingeben...",
|
||||
"search-launcher": "Einträge suchen... oder > für Befehle verwenden",
|
||||
"search": "Suchen...",
|
||||
@@ -1166,7 +1270,6 @@
|
||||
"frame-rates": {
|
||||
"fps": "{fps} FPS"
|
||||
},
|
||||
|
||||
"screen-recording": {
|
||||
"sources": {
|
||||
"portal": "Portal",
|
||||
@@ -1193,13 +1296,18 @@
|
||||
"title": "Sitzungsmenü",
|
||||
"click-again": "Erneut klicken für sofortige Ausführung",
|
||||
"action-in-seconds": "{action} in {seconds} Sekunden...",
|
||||
"lock-subtitle": "Sitzung sperren",
|
||||
"end-subtitle": "Sitzung beenden",
|
||||
"lock": "Sperren",
|
||||
"lock-subtitle": "Sitzung sperren",
|
||||
"lock-and-suspend": "Sperren und Ruhezustand",
|
||||
"lock-and-suspend-subtitle": "Sitzung sperren und System in den Ruhezustand versetzen",
|
||||
"suspend": "Ruhezustand",
|
||||
"reboot": "Neu starten",
|
||||
"logout": "Abmelden",
|
||||
"shutdown": "Herunterfahren"
|
||||
"logout-subtitle": "Sitzung beenden",
|
||||
"shutdown": "Herunterfahren",
|
||||
"reboot-subtitle": "Starten Sie Ihren Computer neu.",
|
||||
"shutdown-subtitle": "Schalte deinen Computer aus.",
|
||||
"suspend-subtitle": "System in den Ruhezustand versetzen"
|
||||
},
|
||||
"plugins": {
|
||||
"applications": "Anwendungen",
|
||||
@@ -1322,4 +1430,4 @@
|
||||
"description": "Das Control-Center-Widget wurde aus der Leiste entfernt. Um es erneut über die Leiste zu öffnen, fügen Sie das Widget wieder hinzu."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"settings": {
|
||||
"general": {
|
||||
"title": "General",
|
||||
|
||||
|
||||
"profile": {
|
||||
"section": {
|
||||
"label": "Profile",
|
||||
@@ -56,6 +56,7 @@
|
||||
}
|
||||
},
|
||||
"fonts": {
|
||||
"reset-scaling": "Reset scaling",
|
||||
"section": {
|
||||
"label": "Fonts",
|
||||
"description": "Choose the fonts used throughout the interface."
|
||||
@@ -64,19 +65,21 @@
|
||||
"label": "Default font",
|
||||
"description": "Main font used throughout the interface.",
|
||||
"placeholder": "Select default font...",
|
||||
"search-placeholder": "Search fonts..."
|
||||
"search-placeholder": "Search font...",
|
||||
"scale": {
|
||||
"label": "Default font size",
|
||||
"description": "Increase or decrease the size of the standard text."
|
||||
}
|
||||
},
|
||||
"monospace": {
|
||||
"label": "Monospaced font",
|
||||
"description": "Monospaced font used for numbers and stats display.",
|
||||
"placeholder": "Select monospace font...",
|
||||
"search-placeholder": "Search monospace fonts..."
|
||||
},
|
||||
"accent": {
|
||||
"label": "Accent font",
|
||||
"description": "Large font used for prominent displays.",
|
||||
"placeholder": "Select display font...",
|
||||
"search-placeholder": "Search display fonts..."
|
||||
"search-placeholder": "Search monospace font...",
|
||||
"scale": {
|
||||
"label": "Monospaced font size",
|
||||
"description": "Increase or decrease the size of the monospaced text."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -282,6 +285,10 @@
|
||||
"section": {
|
||||
"label": "Monitor display",
|
||||
"description": "Choose which monitor to display the dock on."
|
||||
},
|
||||
"only-same-output": {
|
||||
"label": "Only apps from same output",
|
||||
"description": "Show only apps from the output where the dock is located."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -311,6 +318,10 @@
|
||||
"use-app2unit": {
|
||||
"label": "Use App2Unit to launch applications",
|
||||
"description": "Uses an alternative launch method to better manage app processes and prevent issues."
|
||||
},
|
||||
"terminal-command": {
|
||||
"label": "Terminal command",
|
||||
"description": "Command to launch a terminal. E.g., 'kitty -e' or 'gnome-terminal --'."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -491,7 +502,7 @@
|
||||
"predefined": {
|
||||
"section": {
|
||||
"label": "Predefined color schemes",
|
||||
"description": "To use these color schemes, you must turn off Matugen. With Matugen enabled, colors are automatically generated from your wallpaper."
|
||||
"description": "Choose from a collection of predefined color schemes."
|
||||
}
|
||||
},
|
||||
"matugen": {
|
||||
@@ -816,21 +827,54 @@
|
||||
"search-placeholder": "Search widget..."
|
||||
},
|
||||
"active-window": {
|
||||
"auto-hide": "Hide automatically",
|
||||
"show-app-icon": "Show app icon",
|
||||
"scrolling-mode": "Scrolling mode"
|
||||
"auto-hide": {
|
||||
"label": "Hide automatically",
|
||||
"description": "Automatically hide the widget when no window is active."
|
||||
},
|
||||
"show-app-icon": {
|
||||
"label": "Show app icon",
|
||||
"description": "Display the application icon next to the window title."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Scrolling mode",
|
||||
"description": "Control when text scrolling is enabled for long window titles."
|
||||
}
|
||||
},
|
||||
"system-monitor": {
|
||||
"cpu-usage": "CPU usage",
|
||||
"cpu-temperature": "CPU temperature",
|
||||
"memory-usage": "Memory usage",
|
||||
"memory-percentage": "Memory as percentage",
|
||||
"network-traffic": "Network traffic",
|
||||
"storage-usage": "Storage usage"
|
||||
"cpu-usage": {
|
||||
"label": "CPU usage",
|
||||
"description": "Display current CPU usage percentage."
|
||||
},
|
||||
"cpu-temperature": {
|
||||
"label": "CPU temperature",
|
||||
"description": "Show CPU temperature readings if available."
|
||||
},
|
||||
"memory-usage": {
|
||||
"label": "Memory usage",
|
||||
"description": "Display current RAM usage information."
|
||||
},
|
||||
"memory-percentage": {
|
||||
"label": "Memory as percentage",
|
||||
"description": "Show memory usage as a percentage instead of absolute values."
|
||||
},
|
||||
"network-traffic": {
|
||||
"label": "Network traffic",
|
||||
"description": "Display network upload and download speeds."
|
||||
},
|
||||
"storage-usage": {
|
||||
"label": "Storage usage",
|
||||
"description": "Show disk space usage information."
|
||||
}
|
||||
},
|
||||
"notification-history": {
|
||||
"show-unread-badge": "Show unread badge",
|
||||
"hide-badge-when-zero": "Hide badge when zero"
|
||||
"show-unread-badge": {
|
||||
"label": "Show unread badge",
|
||||
"description": "Display a badge showing the number of unread notifications."
|
||||
},
|
||||
"hide-badge-when-zero": {
|
||||
"label": "Hide badge when zero",
|
||||
"description": "Hide the notification badge when there are no unread notifications."
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"display-mode": {
|
||||
@@ -843,7 +887,10 @@
|
||||
}
|
||||
},
|
||||
"control-center": {
|
||||
"use-distro-logo": "Use distro logo instead of icon",
|
||||
"use-distro-logo": {
|
||||
"label": "Use distro logo instead of icon",
|
||||
"description": "Use your distribution's logo instead of a custom icon."
|
||||
},
|
||||
"icon": {
|
||||
"label": "Icon",
|
||||
"description": "Select an icon from the library or a custom file."
|
||||
@@ -865,7 +912,10 @@
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"label-mode": "Label Mode",
|
||||
"label-mode": {
|
||||
"label": "Label Mode",
|
||||
"description": "Choose how workspace labels are displayed."
|
||||
},
|
||||
"hide-unoccupied": {
|
||||
"label": "Hide unoccupied",
|
||||
"description": "Don't display workspaces without windows."
|
||||
@@ -895,9 +945,18 @@
|
||||
"description": "Select an icon from the library."
|
||||
},
|
||||
"browse": "Browse",
|
||||
"left-click": "Left click",
|
||||
"right-click": "Right click",
|
||||
"middle-click": "Middle click",
|
||||
"left-click": {
|
||||
"label": "Left click",
|
||||
"description": "Command to execute when the button is left-clicked."
|
||||
},
|
||||
"right-click": {
|
||||
"label": "Right click",
|
||||
"description": "Command to execute when the button is right-clicked."
|
||||
},
|
||||
"middle-click": {
|
||||
"label": "Middle click",
|
||||
"description": "Command to execute when the button is middle-clicked."
|
||||
},
|
||||
"dynamic-text": "Dynamic text",
|
||||
"display-command-output": {
|
||||
"label": "Display Command Output",
|
||||
@@ -909,11 +968,27 @@
|
||||
}
|
||||
},
|
||||
"media-mini": {
|
||||
"auto-hide": "Hide automatically",
|
||||
"show-album-art": "Show album art",
|
||||
"show-visualizer": "Show visualizer",
|
||||
"visualizer-type": "Visualizer type",
|
||||
"scrolling-mode": "Scrolling mode"
|
||||
"auto-hide": {
|
||||
"label": "Hide automatically",
|
||||
"description": "Automatically hide the widget when no media is playing."
|
||||
},
|
||||
"show-album-art": {
|
||||
"label": "Show album art",
|
||||
"description": "Display the album artwork for the currently playing track."
|
||||
},
|
||||
"show-visualizer": {
|
||||
"label": "Show visualizer",
|
||||
"description": "Display an audio visualizer when music is playing."
|
||||
},
|
||||
"visualizer-type": {
|
||||
"label": "Visualizer type",
|
||||
"description": "Choose the style of audio visualizer to display."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Scrolling mode",
|
||||
"description": "Control when text scrolling is enabled for long track titles."
|
||||
},
|
||||
"no-active-player": "No active player"
|
||||
},
|
||||
"clock": {
|
||||
"use-primary-color": {
|
||||
@@ -924,6 +999,16 @@
|
||||
"label": "Use monospaced font",
|
||||
"description": "When enabled, the clock will use the monospaced font."
|
||||
},
|
||||
"use-custom-font": {
|
||||
"label": "Use custom font",
|
||||
"description": "Override the default font selection with a custom font for the clock."
|
||||
},
|
||||
"custom-font": {
|
||||
"label": "Custom font",
|
||||
"description": "Select a custom font for the clock display.",
|
||||
"placeholder": "Select custom font...",
|
||||
"search-placeholder": "Search fonts..."
|
||||
},
|
||||
"clock-display": {
|
||||
"label": "Clock display",
|
||||
"description": "Customize your clock's display by adding tokens from the list below. To use the 12-hour format, you must include the 'AP' token."
|
||||
@@ -937,6 +1022,16 @@
|
||||
"description": "Use a space to separate each part onto a new line."
|
||||
},
|
||||
"preview": "Preview"
|
||||
},
|
||||
"taskbar": {
|
||||
"only-active-workspaces": {
|
||||
"label": "Only from active workspaces",
|
||||
"description": "Show only apps from active workspaces."
|
||||
},
|
||||
"only-same-output": {
|
||||
"label": "Only from same output",
|
||||
"description": "Show only apps from the output where the bar is located."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1075,13 +1170,17 @@
|
||||
"close": "Close"
|
||||
}
|
||||
},
|
||||
"launcher": {
|
||||
"pin": "Pin to dock",
|
||||
"unpin": "Unpin from dock"
|
||||
},
|
||||
"placeholders": {
|
||||
"search-icons": "e.g., noctalia, niri, battery, cloud",
|
||||
"profile-picture-path": "/home/user/.face",
|
||||
"enter-width-pixels": "Enter width in pixels",
|
||||
"enter-command": "Enter command to execute (app or custom script)",
|
||||
"command-example": "echo \"Hello World\"",
|
||||
|
||||
|
||||
"search-wallpapers": "Type to filter wallpapers...",
|
||||
"search-launcher": "Search entries... or use > for commands",
|
||||
"search": "Search...",
|
||||
@@ -1179,13 +1278,18 @@
|
||||
"title": "Session Menu",
|
||||
"click-again": "Click again to execute immediately",
|
||||
"action-in-seconds": "{action} in {seconds} seconds...",
|
||||
"lock-subtitle": "Lock your session",
|
||||
"end-subtitle": "End your session",
|
||||
"lock": "Lock",
|
||||
"suspend": "Suspend",
|
||||
"lock-subtitle": "Lock your session",
|
||||
"lock-and-suspend": "Lock and Suspend",
|
||||
"lock-and-suspend-subtitle": "Lock session and put system to sleep",
|
||||
"suspend": "Suspend",
|
||||
"suspend-subtitle": "Put system to sleep",
|
||||
"reboot": "Reboot",
|
||||
"reboot-subtitle": "Restart your computer",
|
||||
"logout": "Logout",
|
||||
"shutdown": "Shutdown"
|
||||
"logout-subtitle": "End your session",
|
||||
"shutdown": "Shutdown",
|
||||
"shutdown-subtitle": "Turn off your computer"
|
||||
},
|
||||
"plugins": {
|
||||
"applications": "Applications",
|
||||
@@ -1299,7 +1403,7 @@
|
||||
},
|
||||
"weather": {
|
||||
"clear-sky": "Clear sky",
|
||||
"mainly-clear": "Mainly clear",
|
||||
"mainly-clear": "Mainly clear",
|
||||
"partly-cloudy": "Partly cloudy",
|
||||
"overcast": "Overcast",
|
||||
"fog": "Fog",
|
||||
@@ -1309,7 +1413,7 @@
|
||||
"thunderstorm": "Thunderstorm",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
|
||||
|
||||
"authentication": {
|
||||
"failed": "Authentication failed",
|
||||
"error": "Authentication error"
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
"animation-speed": {
|
||||
"label": "Velocidad de la animación",
|
||||
"description": "Ajusta la velocidad de la animación global."
|
||||
},
|
||||
"animation-disable": {
|
||||
"label": "Desactivar animaciones de UI",
|
||||
"description": "Desactivar todas las animaciones para una experiencia más rápida y responsiva."
|
||||
}
|
||||
},
|
||||
"screen-corners": {
|
||||
@@ -58,20 +62,23 @@
|
||||
"label": "Fuente predeterminada",
|
||||
"description": "Fuente principal utilizada en toda la interfaz.",
|
||||
"placeholder": "Seleccionar fuente predeterminada...",
|
||||
"search-placeholder": "Buscar fuentes..."
|
||||
"search-placeholder": "Buscar fuentes...",
|
||||
"scale": {
|
||||
"description": "Aumentar o disminuir el tamaño del texto estándar.",
|
||||
"label": "Tamaño de fuente predeterminado"
|
||||
}
|
||||
},
|
||||
"monospace": {
|
||||
"label": "Fuente monoespaciada",
|
||||
"description": "Fuente monoespaciada utilizada para la visualización de números y estadísticas.",
|
||||
"placeholder": "Seleccionar fuente monoespaciada...",
|
||||
"search-placeholder": "Buscar fuentes monoespaciadas..."
|
||||
"search-placeholder": "Buscar fuentes monoespaciadas...",
|
||||
"scale": {
|
||||
"description": "Aumentar o disminuir el tamaño del texto monoespaciado.",
|
||||
"label": "Tamaño de fuente monoespaciada"
|
||||
}
|
||||
},
|
||||
"accent": {
|
||||
"label": "Fuente de acento",
|
||||
"description": "Fuente grande utilizada para visualizaciones destacadas.",
|
||||
"placeholder": "Seleccionar fuente de visualización...",
|
||||
"search-placeholder": "Buscar fuentes de visualización..."
|
||||
}
|
||||
"reset-scaling": "Restablecer la escala"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
@@ -276,6 +283,10 @@
|
||||
"section": {
|
||||
"label": "Visualización en monitor",
|
||||
"description": "Elige en qué monitor mostrar el dock."
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Mostrar solo las aplicaciones de la salida donde se encuentra el dock.",
|
||||
"label": "Solo aplicaciones de la misma salida"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -305,6 +316,10 @@
|
||||
"use-app2unit": {
|
||||
"label": "Usar App2Unit para lanzar aplicaciones",
|
||||
"description": "Usa un método de lanzamiento alternativo para gestionar mejor los procesos de las aplicaciones y prevenir problemas."
|
||||
},
|
||||
"terminal-command": {
|
||||
"label": "Comando de terminal",
|
||||
"description": "Comando para iniciar un terminal. Por ejemplo, 'kitty -e' o 'gnome-terminal --'."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -485,7 +500,7 @@
|
||||
"predefined": {
|
||||
"section": {
|
||||
"label": "Esquemas de colores predefinidos",
|
||||
"description": "Para usar estos esquemas de colores, debes desactivar Matugen. Con Matugen activado, los colores se generan automáticamente a partir de tu fondo de pantalla."
|
||||
"description": "Elige entre una colección de esquemas de colores predefinidos."
|
||||
}
|
||||
},
|
||||
"matugen": {
|
||||
@@ -810,21 +825,54 @@
|
||||
"search-placeholder": "Buscar widgets..."
|
||||
},
|
||||
"active-window": {
|
||||
"auto-hide": "Ocultar automáticamente",
|
||||
"show-app-icon": "Mostrar icono de la aplicación",
|
||||
"scrolling-mode": "Modo de desplazamiento"
|
||||
"auto-hide": {
|
||||
"label": "Ocultar automáticamente",
|
||||
"description": "Ocultar automáticamente el widget cuando no hay ventana activa."
|
||||
},
|
||||
"show-app-icon": {
|
||||
"label": "Mostrar icono de la aplicación",
|
||||
"description": "Mostrar el icono de la aplicación junto al título de la ventana."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Modo de desplazamiento",
|
||||
"description": "Controlar cuándo está habilitado el desplazamiento de texto para títulos de ventana largos."
|
||||
}
|
||||
},
|
||||
"system-monitor": {
|
||||
"cpu-usage": "Uso de CPU",
|
||||
"cpu-temperature": "Temperatura de la CPU",
|
||||
"memory-usage": "Uso de memoria",
|
||||
"memory-percentage": "Memoria como porcentaje",
|
||||
"network-traffic": "Tráfico de red",
|
||||
"storage-usage": "Uso de almacenamiento"
|
||||
"cpu-usage": {
|
||||
"label": "Uso de CPU",
|
||||
"description": "Mostrar el porcentaje actual de uso de CPU."
|
||||
},
|
||||
"cpu-temperature": {
|
||||
"label": "Temperatura de la CPU",
|
||||
"description": "Mostrar lecturas de temperatura de CPU si están disponibles."
|
||||
},
|
||||
"memory-usage": {
|
||||
"label": "Uso de memoria",
|
||||
"description": "Mostrar información actual del uso de RAM."
|
||||
},
|
||||
"memory-percentage": {
|
||||
"label": "Memoria como porcentaje",
|
||||
"description": "Mostrar el uso de memoria como porcentaje en lugar de valores absolutos."
|
||||
},
|
||||
"network-traffic": {
|
||||
"label": "Tráfico de red",
|
||||
"description": "Mostrar velocidades de carga y descarga de la red."
|
||||
},
|
||||
"storage-usage": {
|
||||
"label": "Uso de almacenamiento",
|
||||
"description": "Mostrar información del uso del espacio en disco."
|
||||
}
|
||||
},
|
||||
"notification-history": {
|
||||
"show-unread-badge": "Mostrar insignia de no leídos",
|
||||
"hide-badge-when-zero": "Ocultar insignia cuando es cero"
|
||||
"show-unread-badge": {
|
||||
"label": "Mostrar insignia de no leídos",
|
||||
"description": "Mostrar una insignia con el número de notificaciones no leídas."
|
||||
},
|
||||
"hide-badge-when-zero": {
|
||||
"label": "Ocultar insignia cuando es cero",
|
||||
"description": "Ocultar la insignia de notificaciones cuando no hay notificaciones no leídas."
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"display-mode": {
|
||||
@@ -837,7 +885,10 @@
|
||||
}
|
||||
},
|
||||
"control-center": {
|
||||
"use-distro-logo": "Usar logo de la distro en lugar del icono",
|
||||
"use-distro-logo": {
|
||||
"label": "Usar logo de la distribución en lugar de icono",
|
||||
"description": "Usar el logo de tu distribución en lugar de un icono personalizado."
|
||||
},
|
||||
"icon": {
|
||||
"label": "Icono",
|
||||
"description": "Selecciona un icono de la biblioteca o un archivo personalizado."
|
||||
@@ -859,7 +910,10 @@
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"label-mode": "Modo de etiqueta",
|
||||
"label-mode": {
|
||||
"label": "Modo de etiqueta",
|
||||
"description": "Elegir cómo se muestran las etiquetas de los espacios de trabajo."
|
||||
},
|
||||
"hide-unoccupied": {
|
||||
"label": "Ocultar desocupados",
|
||||
"description": "No mostrar espacios de trabajo sin ventanas."
|
||||
@@ -889,9 +943,18 @@
|
||||
"description": "Selecciona un icono de la biblioteca."
|
||||
},
|
||||
"browse": "Explorar",
|
||||
"left-click": "Clic izquierdo",
|
||||
"right-click": "Clic derecho",
|
||||
"middle-click": "Clic central",
|
||||
"left-click": {
|
||||
"label": "Clic izquierdo",
|
||||
"description": "Comando a ejecutar cuando se hace clic izquierdo en el botón."
|
||||
},
|
||||
"right-click": {
|
||||
"label": "Clic derecho",
|
||||
"description": "Comando a ejecutar cuando se hace clic derecho en el botón."
|
||||
},
|
||||
"middle-click": {
|
||||
"label": "Clic medio",
|
||||
"description": "Comando a ejecutar cuando se hace clic medio en el botón."
|
||||
},
|
||||
"dynamic-text": "Texto dinámico",
|
||||
"display-command-output": {
|
||||
"label": "Mostrar salida de comando",
|
||||
@@ -903,11 +966,27 @@
|
||||
}
|
||||
},
|
||||
"media-mini": {
|
||||
"auto-hide": "Ocultar automáticamente",
|
||||
"show-album-art": "Mostrar carátula del álbum",
|
||||
"show-visualizer": "Mostrar visualizador",
|
||||
"visualizer-type": "Tipo de visualizador",
|
||||
"scrolling-mode": "Modo de desplazamiento"
|
||||
"auto-hide": {
|
||||
"label": "Ocultar automáticamente",
|
||||
"description": "Ocultar automáticamente el widget cuando no se está reproduciendo ningún medio."
|
||||
},
|
||||
"show-album-art": {
|
||||
"label": "Mostrar arte del álbum",
|
||||
"description": "Mostrar la portada del álbum de la pista que se está reproduciendo actualmente."
|
||||
},
|
||||
"show-visualizer": {
|
||||
"label": "Mostrar visualizador",
|
||||
"description": "Mostrar un visualizador de audio cuando se reproduce música."
|
||||
},
|
||||
"visualizer-type": {
|
||||
"label": "Tipo de visualizador",
|
||||
"description": "Elegir el estilo de visualizador de audio a mostrar."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Modo de desplazamiento",
|
||||
"description": "Controlar cuándo está habilitado el desplazamiento de texto para títulos de pista largos."
|
||||
},
|
||||
"no-active-player": "Sin reproductor activo"
|
||||
},
|
||||
"clock": {
|
||||
"use-primary-color": {
|
||||
@@ -930,7 +1009,27 @@
|
||||
"label": "Barra vertical",
|
||||
"description": "Usa un espacio para separar cada parte en una nueva línea."
|
||||
},
|
||||
"preview": "Vista previa"
|
||||
"preview": "Vista previa",
|
||||
"custom-font": {
|
||||
"description": "Seleccionar una fuente personalizada para la visualización del reloj.",
|
||||
"label": "Fuente personalizada",
|
||||
"placeholder": "Seleccionar fuente personalizada...",
|
||||
"search-placeholder": "Buscar fuentes..."
|
||||
},
|
||||
"use-custom-font": {
|
||||
"description": "Anular la selección de fuente predeterminada con una fuente personalizada para el reloj.",
|
||||
"label": "Usar fuente personalizada"
|
||||
}
|
||||
},
|
||||
"taskbar": {
|
||||
"only-active-workspaces": {
|
||||
"description": "Mostrar solo las aplicaciones de los espacios de trabajo activos.",
|
||||
"label": "Solo desde espacios de trabajo activos"
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Muestra solo las aplicaciones del resultado donde se encuentra la barra.",
|
||||
"label": "Solo de la misma salida"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1069,6 +1168,10 @@
|
||||
"close": "Cerrar"
|
||||
}
|
||||
},
|
||||
"launcher": {
|
||||
"pin": "Anclar al dock",
|
||||
"unpin": "Desanclar del dock"
|
||||
},
|
||||
"placeholders": {
|
||||
"search-icons": "ej., noctalia, niri, battery, cloud",
|
||||
"profile-picture-path": "/home/usuario/.face",
|
||||
@@ -1172,13 +1275,18 @@
|
||||
"title": "Menú de sesión",
|
||||
"click-again": "Haz clic de nuevo para ejecutar inmediatamente",
|
||||
"action-in-seconds": "{action} en {seconds} segundos...",
|
||||
"lock-subtitle": "Bloquea tu sesión",
|
||||
"end-subtitle": "Finaliza tu sesión",
|
||||
"lock": "Bloquear",
|
||||
"lock-subtitle": "Bloquea tu sesión",
|
||||
"lock-and-suspend": "Bloquear y Suspender",
|
||||
"lock-and-suspend-subtitle": "Bloquear sesión y poner el sistema en suspensión",
|
||||
"suspend": "Suspender",
|
||||
"reboot": "Reiniciar",
|
||||
"logout": "Cerrar sesión",
|
||||
"shutdown": "Apagar"
|
||||
"logout-subtitle": "Finaliza tu sesión",
|
||||
"shutdown": "Apagar",
|
||||
"reboot-subtitle": "Reinicia tu computadora.",
|
||||
"shutdown-subtitle": "Apaga tu computadora.",
|
||||
"suspend-subtitle": "Poner el sistema en reposo"
|
||||
},
|
||||
"plugins": {
|
||||
"applications": "Aplicaciones",
|
||||
@@ -1318,4 +1426,4 @@
|
||||
"charging": "Cargando.",
|
||||
"discharging": "Descargando."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
"animation-speed": {
|
||||
"label": "Vitesse d'animation",
|
||||
"description": "Ajustez la vitesse globale des animations."
|
||||
},
|
||||
"animation-disable": {
|
||||
"label": "Désactiver les animations de l'interface",
|
||||
"description": "Désactiver toutes les animations pour une expérience plus rapide et réactive."
|
||||
}
|
||||
},
|
||||
"screen-corners": {
|
||||
@@ -58,20 +62,23 @@
|
||||
"label": "Police par défaut",
|
||||
"description": "Police principale utilisée dans toute l'interface.",
|
||||
"placeholder": "Sélectionner la police par défaut...",
|
||||
"search-placeholder": "Rechercher des polices..."
|
||||
"search-placeholder": "Rechercher des polices...",
|
||||
"scale": {
|
||||
"description": "Augmenter ou diminuer la taille du texte standard.",
|
||||
"label": "Taille de police par défaut"
|
||||
}
|
||||
},
|
||||
"monospace": {
|
||||
"label": "Police à chasse fixe",
|
||||
"description": "Police à chasse fixe utilisée pour l'affichage des chiffres et des statistiques.",
|
||||
"placeholder": "Sélectionner la police à chasse fixe...",
|
||||
"search-placeholder": "Rechercher des polices à chasse fixe..."
|
||||
"search-placeholder": "Rechercher des polices à chasse fixe...",
|
||||
"scale": {
|
||||
"description": "Augmenter ou diminuer la taille du texte à chasse fixe.",
|
||||
"label": "Taille de police à chasse fixe"
|
||||
}
|
||||
},
|
||||
"accent": {
|
||||
"label": "Police d'accentuation",
|
||||
"description": "Grande police utilisée pour les affichages proéminents.",
|
||||
"placeholder": "Sélectionner la police d'affichage...",
|
||||
"search-placeholder": "Rechercher des polices d'affichage..."
|
||||
}
|
||||
"reset-scaling": "Réinitialiser l'échelle"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
@@ -276,6 +283,10 @@
|
||||
"section": {
|
||||
"label": "Affichage sur les moniteur",
|
||||
"description": "Choisissez sur quels moniteurs afficher le dock."
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Afficher uniquement les applications de la sortie où le dock est situé.",
|
||||
"label": "Seulement les applications de la même sortie"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -305,6 +316,10 @@
|
||||
"use-app2unit": {
|
||||
"label": "Utiliser App2Unit pour lancer les applications",
|
||||
"description": "Utilise une méthode de lancement alternative pour mieux gérer les processus des applications et prévenir les problèmes."
|
||||
},
|
||||
"terminal-command": {
|
||||
"label": "Commande du terminal",
|
||||
"description": "Commande pour lancer un terminal. Ex: 'kitty -e' ou 'gnome-terminal --'."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -485,7 +500,7 @@
|
||||
"predefined": {
|
||||
"section": {
|
||||
"label": "Jeux de couleurs prédéfinis",
|
||||
"description": "Pour utiliser ces jeux de couleurs, vous devez désactiver Matugen. Avec Matugen activé, les couleurs sont générées automatiquement à partir de votre fond d'écran."
|
||||
"description": "Choisissez parmi une collection de jeux de couleurs prédéfinis."
|
||||
}
|
||||
},
|
||||
"matugen": {
|
||||
@@ -810,21 +825,54 @@
|
||||
"search-placeholder": "Rechercher des widgets..."
|
||||
},
|
||||
"active-window": {
|
||||
"show-app-icon": "Afficher l'icône de l'application",
|
||||
"scrolling-mode": "Mode de défilement",
|
||||
"auto-hide": "Masquer automatiquement"
|
||||
"show-app-icon": {
|
||||
"label": "Afficher l'icône de l'application",
|
||||
"description": "Afficher l'icône de l'application à côté du titre de la fenêtre."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Mode de défilement",
|
||||
"description": "Contrôler quand le défilement de texte est activé pour les titres de fenêtre longs."
|
||||
},
|
||||
"auto-hide": {
|
||||
"label": "Masquer automatiquement",
|
||||
"description": "Masquer automatiquement le widget quand aucune fenêtre n'est active."
|
||||
}
|
||||
},
|
||||
"system-monitor": {
|
||||
"cpu-usage": "Utilisation du CPU",
|
||||
"cpu-temperature": "Température du CPU",
|
||||
"memory-usage": "Utilisation de la mémoire",
|
||||
"memory-percentage": "Mémoire en pourcentage",
|
||||
"network-traffic": "Trafic réseau",
|
||||
"storage-usage": "Utilisation du stockage"
|
||||
"cpu-usage": {
|
||||
"label": "Utilisation du CPU",
|
||||
"description": "Afficher le pourcentage d'utilisation actuel du CPU."
|
||||
},
|
||||
"cpu-temperature": {
|
||||
"label": "Température du CPU",
|
||||
"description": "Afficher les lectures de température du CPU si disponibles."
|
||||
},
|
||||
"memory-usage": {
|
||||
"label": "Utilisation de la mémoire",
|
||||
"description": "Afficher les informations actuelles d'utilisation de la RAM."
|
||||
},
|
||||
"memory-percentage": {
|
||||
"label": "Mémoire en pourcentage",
|
||||
"description": "Afficher l'utilisation de la mémoire en pourcentage au lieu de valeurs absolues."
|
||||
},
|
||||
"network-traffic": {
|
||||
"label": "Trafic réseau",
|
||||
"description": "Afficher les vitesses de téléchargement et de téléversement du réseau."
|
||||
},
|
||||
"storage-usage": {
|
||||
"label": "Utilisation du stockage",
|
||||
"description": "Afficher les informations d'utilisation de l'espace disque."
|
||||
}
|
||||
},
|
||||
"notification-history": {
|
||||
"show-unread-badge": "Afficher le badge non lu",
|
||||
"hide-badge-when-zero": "Masquer le badge si zéro"
|
||||
"show-unread-badge": {
|
||||
"label": "Afficher le badge non lu",
|
||||
"description": "Afficher un badge montrant le nombre de notifications non lues."
|
||||
},
|
||||
"hide-badge-when-zero": {
|
||||
"label": "Masquer le badge quand zéro",
|
||||
"description": "Masquer le badge de notification quand il n'y a pas de notifications non lues."
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"display-mode": {
|
||||
@@ -837,7 +885,10 @@
|
||||
}
|
||||
},
|
||||
"control-center": {
|
||||
"use-distro-logo": "Utiliser le logo de la distribution au lieu de l'icône",
|
||||
"use-distro-logo": {
|
||||
"label": "Utiliser le logo de la distribution au lieu de l'icône",
|
||||
"description": "Utiliser le logo de votre distribution au lieu d'une icône personnalisée."
|
||||
},
|
||||
"icon": {
|
||||
"label": "Icône",
|
||||
"description": "Sélectionnez une icône de la bibliothèque ou un fichier personnalisé."
|
||||
@@ -859,7 +910,10 @@
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"label-mode": "Mode d'étiquette",
|
||||
"label-mode": {
|
||||
"label": "Mode d'étiquette",
|
||||
"description": "Choisir comment les étiquettes d'espace de travail sont affichées."
|
||||
},
|
||||
"hide-unoccupied": {
|
||||
"label": "Masquer les inoccupés",
|
||||
"description": "Ne pas afficher les espaces de travail sans fenêtres."
|
||||
@@ -889,9 +943,18 @@
|
||||
"description": "Sélectionnez une icône dans la bibliothèque."
|
||||
},
|
||||
"browse": "Parcourir",
|
||||
"left-click": "Clic gauche",
|
||||
"right-click": "Clic droit",
|
||||
"middle-click": "Clic du milieu",
|
||||
"left-click": {
|
||||
"label": "Clic gauche",
|
||||
"description": "Commande à exécuter quand le bouton est cliqué à gauche."
|
||||
},
|
||||
"right-click": {
|
||||
"label": "Clic droit",
|
||||
"description": "Commande à exécuter quand le bouton est cliqué à droite."
|
||||
},
|
||||
"middle-click": {
|
||||
"label": "Clic milieu",
|
||||
"description": "Commande à exécuter quand le bouton est cliqué au milieu."
|
||||
},
|
||||
"dynamic-text": "Texte dynamique",
|
||||
"display-command-output": {
|
||||
"label": "Afficher la sortie de la commande",
|
||||
@@ -903,11 +966,27 @@
|
||||
}
|
||||
},
|
||||
"media-mini": {
|
||||
"show-album-art": "Afficher la pochette de l'album",
|
||||
"show-visualizer": "Afficher le visualiseur",
|
||||
"visualizer-type": "Type de visualiseur",
|
||||
"scrolling-mode": "Mode de défilement",
|
||||
"auto-hide": "Masquer automatiquement"
|
||||
"show-album-art": {
|
||||
"label": "Afficher la pochette d'album",
|
||||
"description": "Afficher la pochette d'album de la piste en cours de lecture."
|
||||
},
|
||||
"show-visualizer": {
|
||||
"label": "Afficher le visualiseur",
|
||||
"description": "Afficher un visualiseur audio quand la musique est en cours de lecture."
|
||||
},
|
||||
"visualizer-type": {
|
||||
"label": "Type de visualiseur",
|
||||
"description": "Choisir le style de visualiseur audio à afficher."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Mode de défilement",
|
||||
"description": "Contrôler quand le défilement de texte est activé pour les titres de piste longs."
|
||||
},
|
||||
"auto-hide": {
|
||||
"label": "Masquer automatiquement",
|
||||
"description": "Masquer automatiquement le widget quand aucun média n'est en cours de lecture."
|
||||
},
|
||||
"no-active-player": "Aucun lecteur actif"
|
||||
},
|
||||
"clock": {
|
||||
"use-primary-color": {
|
||||
@@ -930,7 +1009,27 @@
|
||||
"label": "Barre verticale",
|
||||
"description": "Utilisez un espace pour séparer chaque partie sur une nouvelle ligne."
|
||||
},
|
||||
"preview": "Aperçu"
|
||||
"preview": "Aperçu",
|
||||
"custom-font": {
|
||||
"description": "Sélectionner une police personnalisée pour l'affichage de l'horloge.",
|
||||
"label": "Police personnalisée",
|
||||
"placeholder": "Sélectionner une police personnalisée...",
|
||||
"search-placeholder": "Rechercher des polices..."
|
||||
},
|
||||
"use-custom-font": {
|
||||
"description": "Remplacez la police par défaut par une police personnalisée pour l'horloge.",
|
||||
"label": "Utiliser une police personnalisée."
|
||||
}
|
||||
},
|
||||
"taskbar": {
|
||||
"only-active-workspaces": {
|
||||
"description": "Afficher uniquement les applications des espaces de travail actifs.",
|
||||
"label": "Seulement depuis les espaces de travail actifs."
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Afficher uniquement les applications de la sortie où la barre est située.",
|
||||
"label": "Seulement à partir de la même sortie"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1069,6 +1168,10 @@
|
||||
"close": "Fermer"
|
||||
}
|
||||
},
|
||||
"launcher": {
|
||||
"pin": "Épingler au dock",
|
||||
"unpin": "Retirer du dock"
|
||||
},
|
||||
"placeholders": {
|
||||
"search-icons": "ex: noctalia, niri, batterie, nuage",
|
||||
"profile-picture-path": "/home/user/.face",
|
||||
@@ -1172,13 +1275,18 @@
|
||||
"title": "Menu de session",
|
||||
"click-again": "Cliquez à nouveau pour exécuter immédiatement",
|
||||
"action-in-seconds": "{action} dans {seconds} secondes...",
|
||||
"lock-subtitle": "Verrouiller votre session",
|
||||
"end-subtitle": "Terminer votre session",
|
||||
"lock": "Verrouiller",
|
||||
"lock-subtitle": "Verrouiller votre session",
|
||||
"lock-and-suspend": "Verrouiller et Mettre en veille",
|
||||
"lock-and-suspend-subtitle": "Verrouiller la session et mettre le système en veille",
|
||||
"suspend": "Mettre en veille",
|
||||
"reboot": "Redémarrer",
|
||||
"logout": "Déconnexion",
|
||||
"shutdown": "Éteindre"
|
||||
"logout-subtitle": "Terminer votre session",
|
||||
"shutdown": "Éteindre",
|
||||
"reboot-subtitle": "Redémarrez votre ordinateur.",
|
||||
"shutdown-subtitle": "Éteignez votre ordinateur.",
|
||||
"suspend-subtitle": "Mettre le système en veille"
|
||||
},
|
||||
"plugins": {
|
||||
"applications": "Applications",
|
||||
@@ -1318,4 +1426,4 @@
|
||||
"charging": "En charge.",
|
||||
"discharging": "En décharge."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
"animation-speed": {
|
||||
"label": "Velocidade da animação",
|
||||
"description": "Ajuste a velocidade global da animação."
|
||||
},
|
||||
"animation-disable": {
|
||||
"label": "Desativar animações da interface",
|
||||
"description": "Desativar todas as animações para uma experiência mais rápida e responsiva."
|
||||
}
|
||||
},
|
||||
"screen-corners": {
|
||||
@@ -58,20 +62,23 @@
|
||||
"label": "Fonte padrão",
|
||||
"description": "Fonte principal usada em toda a interface.",
|
||||
"placeholder": "Selecione a fonte padrão...",
|
||||
"search-placeholder": "Pesquisar fontes..."
|
||||
"search-placeholder": "Pesquisar fontes...",
|
||||
"scale": {
|
||||
"description": "Aumentar ou diminuir o tamanho do texto padrão.",
|
||||
"label": "Tamanho de fonte padrão"
|
||||
}
|
||||
},
|
||||
"monospace": {
|
||||
"label": "Fonte monoespaçada",
|
||||
"description": "Fonte monoespaçada usada para exibição de números e estatísticas.",
|
||||
"placeholder": "Selecione a fonte monoespaçada...",
|
||||
"search-placeholder": "Pesquisar fontes monoespaçadas..."
|
||||
"search-placeholder": "Pesquisar fontes monoespaçadas...",
|
||||
"scale": {
|
||||
"description": "Aumentar ou diminuir o tamanho do texto monoespaçado.",
|
||||
"label": "Tamanho da fonte monoespaçada"
|
||||
}
|
||||
},
|
||||
"accent": {
|
||||
"label": "Fonte de destaque",
|
||||
"description": "Fonte grande usada para exibições proeminentes.",
|
||||
"placeholder": "Selecione a fonte de exibição...",
|
||||
"search-placeholder": "Pesquisar fontes de exibição..."
|
||||
}
|
||||
"reset-scaling": "Redefinir escala"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
@@ -276,6 +283,10 @@
|
||||
"section": {
|
||||
"label": "Exibição no monitor",
|
||||
"description": "Escolha em qual monitor exibir a dock."
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Mostrar apenas aplicativos da saída onde o dock está localizado.",
|
||||
"label": "Apenas aplicativos da mesma saída"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -305,6 +316,10 @@
|
||||
"use-app2unit": {
|
||||
"label": "Usar App2Unit para iniciar aplicativos",
|
||||
"description": "Usa um método de inicialização alternativo para gerenciar melhor os processos de aplicativos e evitar problemas."
|
||||
},
|
||||
"terminal-command": {
|
||||
"label": "Comando do terminal",
|
||||
"description": "Comando para iniciar um terminal. Ex: 'kitty -e' ou 'gnome-terminal --'."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -451,7 +466,7 @@
|
||||
"predefined": {
|
||||
"section": {
|
||||
"label": "Esquemas de cores predefinidos",
|
||||
"description": "Para usar esses esquemas de cores, você deve desativar o Matugen. Com o Matugen ativado, as cores são geradas automaticamente a partir do seu papel de parede."
|
||||
"description": "Escolha entre uma coleção de esquemas de cores predefinidos."
|
||||
}
|
||||
},
|
||||
"matugen": {
|
||||
@@ -713,7 +728,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"widgets": {
|
||||
"tooltip": {
|
||||
"placeholder": "Espaço reservado"
|
||||
@@ -811,21 +825,54 @@
|
||||
"search-placeholder": "Pesquisar widgets..."
|
||||
},
|
||||
"active-window": {
|
||||
"auto-hide": "Ocultar automaticamente",
|
||||
"show-app-icon": "Mostrar ícone do aplicativo",
|
||||
"scrolling-mode": "Modo de Rolagem"
|
||||
"auto-hide": {
|
||||
"label": "Ocultar automaticamente",
|
||||
"description": "Ocultar automaticamente o widget quando nenhuma janela está ativa."
|
||||
},
|
||||
"show-app-icon": {
|
||||
"label": "Mostrar ícone do aplicativo",
|
||||
"description": "Exibir o ícone do aplicativo ao lado do título da janela."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Modo de rolagem",
|
||||
"description": "Controlar quando a rolagem de texto está habilitada para títulos de janela longos."
|
||||
}
|
||||
},
|
||||
"system-monitor": {
|
||||
"cpu-usage": "Uso de CPU",
|
||||
"cpu-temperature": "Temperatura da CPU",
|
||||
"memory-usage": "Uso de memória",
|
||||
"memory-percentage": "Memória em porcentagem",
|
||||
"network-traffic": "Tráfego de rede",
|
||||
"storage-usage": "Uso de armazenamento"
|
||||
"cpu-usage": {
|
||||
"label": "Uso da CPU",
|
||||
"description": "Exibir o percentual atual de uso da CPU."
|
||||
},
|
||||
"cpu-temperature": {
|
||||
"label": "Temperatura da CPU",
|
||||
"description": "Mostrar leituras de temperatura da CPU se disponíveis."
|
||||
},
|
||||
"memory-usage": {
|
||||
"label": "Uso de memória",
|
||||
"description": "Exibir informações atuais de uso da RAM."
|
||||
},
|
||||
"memory-percentage": {
|
||||
"label": "Memória como percentual",
|
||||
"description": "Mostrar o uso de memória como percentual em vez de valores absolutos."
|
||||
},
|
||||
"network-traffic": {
|
||||
"label": "Tráfego de rede",
|
||||
"description": "Exibir velocidades de upload e download da rede."
|
||||
},
|
||||
"storage-usage": {
|
||||
"label": "Uso de armazenamento",
|
||||
"description": "Mostrar informações de uso do espaço em disco."
|
||||
}
|
||||
},
|
||||
"notification-history": {
|
||||
"show-unread-badge": "Mostrar selo de não lidas",
|
||||
"hide-badge-when-zero": "Ocultar selo quando for zero"
|
||||
"show-unread-badge": {
|
||||
"label": "Mostrar distintivo de não lidos",
|
||||
"description": "Exibir um distintivo mostrando o número de notificações não lidas."
|
||||
},
|
||||
"hide-badge-when-zero": {
|
||||
"label": "Ocultar distintivo quando zero",
|
||||
"description": "Ocultar o distintivo de notificação quando não há notificações não lidas."
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"display-mode": {
|
||||
@@ -838,7 +885,10 @@
|
||||
}
|
||||
},
|
||||
"control-center": {
|
||||
"use-distro-logo": "Usar logo da distro em vez do ícone",
|
||||
"use-distro-logo": {
|
||||
"label": "Usar logo da distribuição em vez de ícone",
|
||||
"description": "Usar o logo da sua distribuição em vez de um ícone personalizado."
|
||||
},
|
||||
"icon": {
|
||||
"label": "Ícone",
|
||||
"description": "Selecione um ícone da biblioteca ou um arquivo personalizado."
|
||||
@@ -860,7 +910,10 @@
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"label-mode": "Modo de Rótulo",
|
||||
"label-mode": {
|
||||
"label": "Modo de rótulo",
|
||||
"description": "Escolher como os rótulos de espaço de trabalho são exibidos."
|
||||
},
|
||||
"hide-unoccupied": {
|
||||
"label": "Ocultar desocupados",
|
||||
"description": "Não exibir áreas de trabalho sem janelas."
|
||||
@@ -890,9 +943,18 @@
|
||||
"description": "Selecione um ícone da biblioteca."
|
||||
},
|
||||
"browse": "Navegar",
|
||||
"left-click": "Clique esquerdo",
|
||||
"right-click": "Clique direito",
|
||||
"middle-click": "Clique do meio",
|
||||
"left-click": {
|
||||
"label": "Clique esquerdo",
|
||||
"description": "Comando a executar quando o botão é clicado com o botão esquerdo."
|
||||
},
|
||||
"right-click": {
|
||||
"label": "Clique direito",
|
||||
"description": "Comando a executar quando o botão é clicado com o botão direito."
|
||||
},
|
||||
"middle-click": {
|
||||
"label": "Clique do meio",
|
||||
"description": "Comando a executar quando o botão é clicado com o botão do meio."
|
||||
},
|
||||
"dynamic-text": "Texto dinâmico",
|
||||
"display-command-output": {
|
||||
"label": "Exibir Saída de Comando",
|
||||
@@ -904,11 +966,27 @@
|
||||
}
|
||||
},
|
||||
"media-mini": {
|
||||
"auto-hide": "Ocultar automaticamente",
|
||||
"show-album-art": "Mostrar arte do álbum",
|
||||
"show-visualizer": "Mostrar visualizador",
|
||||
"visualizer-type": "Tipo de visualizador",
|
||||
"scrolling-mode": "Modo de rolagem"
|
||||
"auto-hide": {
|
||||
"label": "Ocultar automaticamente",
|
||||
"description": "Ocultar automaticamente o widget quando nenhuma mídia está sendo reproduzida."
|
||||
},
|
||||
"show-album-art": {
|
||||
"label": "Mostrar arte do álbum",
|
||||
"description": "Exibir a arte do álbum da faixa atualmente sendo reproduzida."
|
||||
},
|
||||
"show-visualizer": {
|
||||
"label": "Mostrar visualizador",
|
||||
"description": "Exibir um visualizador de áudio quando música está sendo reproduzida."
|
||||
},
|
||||
"visualizer-type": {
|
||||
"label": "Tipo de visualizador",
|
||||
"description": "Escolher o estilo de visualizador de áudio a exibir."
|
||||
},
|
||||
"scrolling-mode": {
|
||||
"label": "Modo de rolagem",
|
||||
"description": "Controlar quando a rolagem de texto está habilitada para títulos de faixa longos."
|
||||
},
|
||||
"no-active-player": "Nenhum player ativo"
|
||||
},
|
||||
"clock": {
|
||||
"use-primary-color": {
|
||||
@@ -931,7 +1009,27 @@
|
||||
"label": "Barra vertical",
|
||||
"description": "Use um espaço para separar cada parte em uma nova linha."
|
||||
},
|
||||
"preview": "Pré-visualização"
|
||||
"preview": "Pré-visualização",
|
||||
"custom-font": {
|
||||
"description": "Selecione uma fonte personalizada para a exibição do relógio.",
|
||||
"label": "Fonte personalizada",
|
||||
"placeholder": "Selecionar fonte personalizada...",
|
||||
"search-placeholder": "Procurar fontes..."
|
||||
},
|
||||
"use-custom-font": {
|
||||
"description": "Substitua a fonte padrão por uma fonte personalizada para o relógio.",
|
||||
"label": "Usar fonte personalizada"
|
||||
}
|
||||
},
|
||||
"taskbar": {
|
||||
"only-active-workspaces": {
|
||||
"description": "Mostrar apenas aplicativos de áreas de trabalho ativas.",
|
||||
"label": "Apenas de espaços de trabalho ativos"
|
||||
},
|
||||
"only-same-output": {
|
||||
"description": "Mostrar apenas os aplicativos da saída onde a barra está localizada.",
|
||||
"label": "Apenas da mesma saída"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1070,6 +1168,10 @@
|
||||
"close": "Fechar"
|
||||
}
|
||||
},
|
||||
"launcher": {
|
||||
"pin": "Fixar no dock",
|
||||
"unpin": "Desafixar do dock"
|
||||
},
|
||||
"placeholders": {
|
||||
"search-icons": "ex., noctalia, niri, battery, cloud",
|
||||
"profile-picture-path": "/home/usuario/.face",
|
||||
@@ -1105,8 +1207,8 @@
|
||||
"bottom_right": "Inferior direito",
|
||||
"bottom_center": "Centro inferior",
|
||||
"top_center": "Centro superior",
|
||||
"center_left": "Esquerda central",
|
||||
"center_right": "Direita central"
|
||||
"center_left": "Centro à esquerda",
|
||||
"center_right": "Centro à direita"
|
||||
}
|
||||
},
|
||||
"bar": {
|
||||
@@ -1122,19 +1224,6 @@
|
||||
"comfortable": "Confortável"
|
||||
}
|
||||
},
|
||||
"launcher": {
|
||||
"position": {
|
||||
"center": "Centro (padrão)",
|
||||
"top_left": "Superior esquerdo",
|
||||
"top_right": "Superior direito",
|
||||
"bottom_left": "Inferior esquerdo",
|
||||
"bottom_right": "Inferior direito",
|
||||
"bottom_center": "Centro inferior",
|
||||
"top_center": "Centro superior",
|
||||
"center_left": "Centro à esquerda",
|
||||
"center_right": "Centro à direita"
|
||||
}
|
||||
},
|
||||
"display-mode": {
|
||||
"on-hover": "Ao passar o mouse",
|
||||
"always-show": "Sempre mostrar",
|
||||
@@ -1186,13 +1275,18 @@
|
||||
"title": "Menu da Sessão",
|
||||
"click-again": "Clique novamente para executar imediatamente",
|
||||
"action-in-seconds": "{action} em {seconds} segundos...",
|
||||
"lock-subtitle": "Bloqueie sua sessão",
|
||||
"end-subtitle": "Encerre sua sessão",
|
||||
"lock": "Bloquear",
|
||||
"lock-subtitle": "Bloqueie sua sessão",
|
||||
"lock-and-suspend": "Bloquear e Suspender",
|
||||
"lock-and-suspend-subtitle": "Bloquear sessão e colocar o sistema em suspensão",
|
||||
"suspend": "Suspender",
|
||||
"reboot": "Reiniciar",
|
||||
"logout": "Sair",
|
||||
"shutdown": "Desligar"
|
||||
"logout-subtitle": "Encerre sua sessão",
|
||||
"shutdown": "Desligar",
|
||||
"reboot-subtitle": "Reinicie o seu computador.",
|
||||
"shutdown-subtitle": "Desligue o seu computador.",
|
||||
"suspend-subtitle": "Colocar o sistema em suspensão."
|
||||
},
|
||||
"plugins": {
|
||||
"applications": "Aplicativos",
|
||||
@@ -1332,4 +1426,4 @@
|
||||
"charging": "Carregando.",
|
||||
"discharging": "Descarregando."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1429
Assets/Translations/zh-CN.json
Normal file
1429
Assets/Translations/zh-CN.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -107,13 +107,15 @@
|
||||
"backgroundOpacity": 1,
|
||||
"pinnedExecs": [],
|
||||
"useApp2Unit": false,
|
||||
"sortByMostUsed": true
|
||||
"sortByMostUsed": true,
|
||||
"terminalCommand": "xterm -e"
|
||||
},
|
||||
"dock": {
|
||||
"autoHide": false,
|
||||
"exclusive": false,
|
||||
"backgroundOpacity": 1,
|
||||
"floatingRatio": 1,
|
||||
"onlySameOutput": true,
|
||||
"monitors": [],
|
||||
"pinnedApps": []
|
||||
},
|
||||
@@ -148,7 +150,8 @@
|
||||
"ui": {
|
||||
"fontDefault": "Roboto",
|
||||
"fontFixed": "DejaVu Sans Mono",
|
||||
"fontBillboard": "Inter",
|
||||
"fontDefaultScale": 1,
|
||||
"fontFixedScale": 1,
|
||||
"monitorsScaling": [],
|
||||
"idleInhibitorEnabled": false
|
||||
},
|
||||
|
||||
@@ -8,6 +8,7 @@ set -euo pipefail
|
||||
# Configuration
|
||||
FOLDER_PATH="Assets/Translations"
|
||||
REFERENCE_FILE="en.json"
|
||||
TRANSLATE_MODE=false
|
||||
|
||||
# Colors for terminal output
|
||||
RED='\033[0;31m'
|
||||
@@ -32,6 +33,152 @@ check_dependencies() {
|
||||
print_color $YELLOW "On macOS: brew install jq" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if $TRANSLATE_MODE && ! command -v curl &> /dev/null; then
|
||||
print_color $RED "Error: 'curl' is required for translation mode but not installed." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get Gemini API key
|
||||
get_gemini_api_key() {
|
||||
if [[ -z "${GEMINI_API_KEY:-}" ]]; then
|
||||
print_color $RED "Error: GEMINI_API_KEY environment variable is not set" >&2
|
||||
print_color $YELLOW "Please set it with: export GEMINI_API_KEY='your-api-key'" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "$GEMINI_API_KEY"
|
||||
}
|
||||
|
||||
# Function to get value from JSON using key path
|
||||
get_json_value() {
|
||||
local json_file=$1
|
||||
local key_path=$2
|
||||
|
||||
# Convert dot-separated path to jq path
|
||||
local jq_path=$(echo "$key_path" | sed 's/\./\.\["/g' | sed 's/$/"]/' | sed 's/^\.//')
|
||||
local jq_query=".${jq_path}"
|
||||
|
||||
# Use a more robust approach: split by dots and build path
|
||||
local -a path_parts
|
||||
IFS='.' read -ra path_parts <<< "$key_path"
|
||||
|
||||
local jq_filter="."
|
||||
for part in "${path_parts[@]}"; do
|
||||
jq_filter="${jq_filter}[\"${part}\"]"
|
||||
done
|
||||
|
||||
jq -r "$jq_filter // empty" "$json_file" 2>/dev/null || echo ""
|
||||
}
|
||||
|
||||
# Function to list available Gemini models
|
||||
list_gemini_models() {
|
||||
local api_key=$(get_gemini_api_key)
|
||||
|
||||
print_color $BLUE "Fetching available Gemini models..." >&2
|
||||
echo "" >&2
|
||||
|
||||
local response=$(curl -s -X GET \
|
||||
"https://generativelanguage.googleapis.com/v1/models?key=${api_key}" \
|
||||
-H "Content-Type: application/json" 2>/dev/null)
|
||||
|
||||
# Parse and display models
|
||||
echo "$response" | jq -r '.models[] | "- \(.name) (\(.displayName))"' 2>/dev/null || {
|
||||
print_color $RED "Failed to parse models list" >&2
|
||||
echo "$response" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Function to translate text using Gemini API
|
||||
translate_text() {
|
||||
local text=$1
|
||||
local target_language=$2
|
||||
local api_key=$3
|
||||
|
||||
# Escape text for JSON
|
||||
local escaped_text=$(echo "$text" | jq -Rs .)
|
||||
|
||||
# Prepare the API request
|
||||
local prompt="Translate the following English text to ${target_language}. Return ONLY the translation, no explanations or additional text:\n\n${text}"
|
||||
local escaped_prompt=$(echo "$prompt" | jq -Rs .)
|
||||
|
||||
local request_body=$(cat <<EOF
|
||||
{
|
||||
"contents": [{
|
||||
"parts": [{
|
||||
"text": ${escaped_prompt}
|
||||
}]
|
||||
}],
|
||||
"generationConfig": {
|
||||
"temperature": 0.3,
|
||||
"maxOutputTokens": 1000
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Make API call to Gemini
|
||||
local api_url="https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${api_key}"
|
||||
|
||||
print_color $BLUE " API URL: $api_url" >&2
|
||||
|
||||
local response=$(curl -s -X POST "$api_url" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$request_body" 2>/dev/null)
|
||||
|
||||
print_color $BLUE " API Response: $response" >&2
|
||||
|
||||
# Extract the translation from response - try multiple parsing approaches
|
||||
local translation=$(echo "$response" | jq -r '.candidates[0].content.parts[0].text // .text // empty' 2>/dev/null | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
|
||||
if [[ -z "$translation" ]]; then
|
||||
print_color $RED " Failed to parse translation. Full response:" >&2
|
||||
echo "$response" | jq . >&2 2>/dev/null || echo "$response" >&2
|
||||
echo ""
|
||||
return 1
|
||||
fi
|
||||
|
||||
print_color $GREEN " Parsed translation: $translation" >&2
|
||||
|
||||
echo "$translation"
|
||||
}
|
||||
|
||||
# Function to inject translation into JSON file using jq
|
||||
inject_translation() {
|
||||
local json_file=$1
|
||||
local key_path=$2
|
||||
local value=$3
|
||||
|
||||
# Split key path into array
|
||||
local -a path_parts
|
||||
IFS='.' read -ra path_parts <<< "$key_path"
|
||||
|
||||
# Build jq path array
|
||||
local jq_path="["
|
||||
for i in "${!path_parts[@]}"; do
|
||||
if [[ $i -gt 0 ]]; then
|
||||
jq_path+=","
|
||||
fi
|
||||
jq_path+="\"${path_parts[$i]}\""
|
||||
done
|
||||
jq_path+="]"
|
||||
|
||||
# Create a temporary file
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
# Use jq to set the value at the path
|
||||
jq --argjson path "$jq_path" --arg value "$value" 'setpath($path; $value)' "$json_file" > "$temp_file"
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
mv "$temp_file" "$json_file"
|
||||
return 0
|
||||
else
|
||||
rm -f "$temp_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to extract all keys from a JSON file recursively
|
||||
@@ -75,6 +222,9 @@ generate_header() {
|
||||
echo "Generated: $timestamp"
|
||||
echo "Reference file: $REFERENCE_FILE"
|
||||
echo "Folder: $(realpath "$FOLDER_PATH")"
|
||||
if $TRANSLATE_MODE; then
|
||||
echo "Mode: TRANSLATION ENABLED"
|
||||
fi
|
||||
echo ""
|
||||
echo "Notes:"
|
||||
echo "- Keys are compared recursively through all nested JSON objects"
|
||||
@@ -203,6 +353,49 @@ compare_language() {
|
||||
done
|
||||
rm -f "$temp_missing"
|
||||
echo ""
|
||||
|
||||
# Translate missing keys if in translate mode
|
||||
if $TRANSLATE_MODE; then
|
||||
print_color $BLUE "Translating missing keys for $lang_name..." >&2
|
||||
local api_key=$(get_gemini_api_key)
|
||||
local translated_count=0
|
||||
local failed_count=0
|
||||
|
||||
while IFS= read -r key; do
|
||||
if [[ -n "$key" ]]; then
|
||||
# Get English value
|
||||
local en_value=$(get_json_value "$ref_file_path" "$key")
|
||||
|
||||
if [[ -n "$en_value" ]]; then
|
||||
print_color $YELLOW " Translating: $key" >&2
|
||||
|
||||
# Translate the value
|
||||
local translated_value=$(translate_text "$en_value" "$lang_name" "$api_key")
|
||||
|
||||
if [[ -n "$translated_value" ]]; then
|
||||
# Inject translation into the file
|
||||
if inject_translation "$lang_file" "$key" "$translated_value"; then
|
||||
print_color $GREEN " ✓ Translated: $key" >&2
|
||||
translated_count=$((translated_count + 1))
|
||||
else
|
||||
print_color $RED " ✗ Failed to inject: $key" >&2
|
||||
failed_count=$((failed_count + 1))
|
||||
fi
|
||||
else
|
||||
print_color $RED " ✗ Translation failed: $key" >&2
|
||||
failed_count=$((failed_count + 1))
|
||||
fi
|
||||
|
||||
# Small delay to avoid rate limiting
|
||||
sleep 0.5
|
||||
fi
|
||||
fi
|
||||
done <<< "$missing_keys"
|
||||
|
||||
echo ""
|
||||
print_color $GREEN "Translation complete: $translated_count succeeded, $failed_count failed" >&2
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
echo "✅ No missing keys in $lang_name"
|
||||
echo ""
|
||||
@@ -351,6 +544,9 @@ main() {
|
||||
if [[ -n "$target_language" ]]; then
|
||||
echo "Target language: $target_language"
|
||||
fi
|
||||
if $TRANSLATE_MODE; then
|
||||
echo "Translation mode: ENABLED"
|
||||
fi
|
||||
echo "Report generated: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo ""
|
||||
echo "================================================================================"
|
||||
@@ -367,11 +563,13 @@ main() {
|
||||
|
||||
# Usage information
|
||||
show_usage() {
|
||||
echo "Usage: $0 [language_code]" >&2
|
||||
echo "Usage: $0 [--translate] [language_code]" >&2
|
||||
echo "" >&2
|
||||
echo "This script compares JSON language files in '$FOLDER_PATH' against the English reference." >&2
|
||||
echo "" >&2
|
||||
echo "Arguments:" >&2
|
||||
echo " --translate Enable automatic translation of missing keys using Gemini API" >&2
|
||||
echo " --list-models List all available Gemini models and exit" >&2
|
||||
echo " language_code Optional. Compare only the specified language (e.g., 'fr', 'es', 'de')" >&2
|
||||
echo " If not provided, all language files will be compared" >&2
|
||||
echo "" >&2
|
||||
@@ -380,14 +578,18 @@ show_usage() {
|
||||
echo " - Reference file: $REFERENCE_FILE" >&2
|
||||
echo "" >&2
|
||||
echo "Examples:" >&2
|
||||
echo " $0 # Compare all languages" >&2
|
||||
echo " $0 fr # Compare only French (fr.json)" >&2
|
||||
echo " $0 es # Compare only Spanish (es.json)" >&2
|
||||
echo " $0 # Compare all languages" >&2
|
||||
echo " $0 fr # Compare only French (fr.json)" >&2
|
||||
echo " $0 --list-models # List available Gemini models" >&2
|
||||
echo " $0 --translate # Compare all and translate missing keys" >&2
|
||||
echo " $0 --translate fr # Translate missing keys for French only" >&2
|
||||
echo "" >&2
|
||||
echo "Requirements:" >&2
|
||||
echo " - jq must be installed" >&2
|
||||
echo " - curl must be installed (for --translate mode)" >&2
|
||||
echo " - $REFERENCE_FILE must exist in $FOLDER_PATH" >&2
|
||||
echo " - Target language file must exist if specified" >&2
|
||||
echo " - GEMINI_API_KEY environment variable must be set (for --translate mode)" >&2
|
||||
echo "" >&2
|
||||
echo "Output:" >&2
|
||||
echo " - Comparison report is printed to stdout" >&2
|
||||
@@ -396,29 +598,39 @@ show_usage() {
|
||||
}
|
||||
|
||||
# Handle command line arguments
|
||||
if [[ $# -gt 1 ]]; then
|
||||
echo "Error: Too many arguments. Only one language code is allowed." >&2
|
||||
echo "" >&2
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -eq 1 ]]; then
|
||||
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
show_usage
|
||||
exit 0
|
||||
else
|
||||
# Validate language code format (basic check for reasonable filename)
|
||||
if [[ ! "$1" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]; then
|
||||
echo "Error: Invalid language code format '$1'. Use alphanumeric characters, hyphens, and underscores only." >&2
|
||||
echo "" >&2
|
||||
target_lang=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
# Run main function with target language
|
||||
main "$1"
|
||||
fi
|
||||
else
|
||||
# Run main function for all languages
|
||||
main ""
|
||||
fi
|
||||
exit 0
|
||||
;;
|
||||
--list-models)
|
||||
list_gemini_models
|
||||
;;
|
||||
--translate)
|
||||
TRANSLATE_MODE=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
if [[ -n "$target_lang" ]]; then
|
||||
echo "Error: Too many arguments. Only one language code is allowed." >&2
|
||||
echo "" >&2
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
# Validate language code format (basic check for reasonable filename)
|
||||
if [[ ! "$1" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]; then
|
||||
echo "Error: Invalid language code format '$1'. Use alphanumeric characters, hyphens, and underscores only." >&2
|
||||
echo "" >&2
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
target_lang="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Run main function
|
||||
main "$target_lang"
|
||||
@@ -53,9 +53,10 @@ Singleton {
|
||||
try {
|
||||
var data = JSON.parse(text())
|
||||
root.translations = data
|
||||
Logger.log("I18n", `Loaded translations for "${root.langCode}"`)
|
||||
|
||||
root.isLoaded = true
|
||||
root.translationsLoaded()
|
||||
Logger.log("I18n", `Loaded translations for "${root.langCode}"`)
|
||||
} catch (e) {
|
||||
Logger.error("I18n", `Failed to parse translation file: ${e}`)
|
||||
setLanguage("en")
|
||||
@@ -170,11 +171,24 @@ Singleton {
|
||||
|
||||
// Detect user's favorite locale - languages
|
||||
for (var i = 0; i < Qt.locale().uiLanguages.length; i++) {
|
||||
const userLang = Qt.locale().uiLanguages[i].substring(0, 2)
|
||||
if (availableLanguages.includes(userLang)) {
|
||||
setLanguage(userLang)
|
||||
const fullUserLang = Qt.locale().uiLanguages[i]
|
||||
|
||||
// Try full code match (such as zh CN, en US)
|
||||
if (availableLanguages.includes(fullUserLang)) {
|
||||
Logger.log("I18n", `Exact match found: "${fullUserLang}"`)
|
||||
setLanguage(fullUserLang)
|
||||
return
|
||||
}
|
||||
|
||||
// If full code match fails, try short code matching (such as zh, en)
|
||||
const shortUserLang = fullUserLang.substring(0, 2)
|
||||
if (availableLanguages.includes(shortUserLang)) {
|
||||
Logger.log("I18n", `Short code match found: "${shortUserLang}" from "${fullUserLang}"`)
|
||||
setLanguage(shortUserLang)
|
||||
return
|
||||
}
|
||||
|
||||
Logger.log("I18n", `No match for system language: "${fullUserLang}"`)
|
||||
}
|
||||
|
||||
// Fallback to first available language (preferably "en" if available)
|
||||
@@ -202,7 +216,7 @@ Singleton {
|
||||
const filePath = `file://${Quickshell.shellDir}/Assets/Translations/${langCode}.json`
|
||||
fileView.path = filePath
|
||||
isLoaded = false
|
||||
Logger.log("I18n", `Loading translations from: ${filePath}`)
|
||||
Logger.log("I18n", `Loading translations: ${langCode}`)
|
||||
|
||||
// Only load fallback translations if we are not using english and english is available
|
||||
if (langCode !== "en" && availableLanguages.includes("en")) {
|
||||
|
||||
@@ -50,7 +50,7 @@ Singleton {
|
||||
}
|
||||
|
||||
function loadFontWithCacheBusting() {
|
||||
Logger.log("Icons", "Loading font with cache busting:", cacheBustingPath)
|
||||
Logger.log("Icons", "Loading font with cache busting")
|
||||
|
||||
// Destroy old loader first
|
||||
if (currentFontLoader) {
|
||||
|
||||
@@ -71,7 +71,13 @@ Singleton {
|
||||
id: saveTimer
|
||||
running: false
|
||||
interval: 1000
|
||||
onTriggered: settingsFileView.writeAdapter()
|
||||
onTriggered: {
|
||||
settingsFileView.writeAdapter()
|
||||
// Write to fallback location if set
|
||||
if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) {
|
||||
settingsFallbackFileView.writeAdapter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
@@ -90,15 +96,10 @@ Singleton {
|
||||
}
|
||||
onLoaded: function () {
|
||||
if (!isLoaded) {
|
||||
Logger.log("Settings", "----------------------------")
|
||||
Logger.log("Settings", "Settings loaded successfully")
|
||||
Logger.log("Settings", "Settings loaded")
|
||||
|
||||
upgradeSettingsData()
|
||||
|
||||
validateMonitorConfigurations()
|
||||
|
||||
kickOffServices()
|
||||
|
||||
isLoaded = true
|
||||
|
||||
// Emit the signal
|
||||
@@ -106,11 +107,25 @@ Singleton {
|
||||
}
|
||||
}
|
||||
onLoadFailed: function (error) {
|
||||
if (error.toString().includes("No such file") || error === 2)
|
||||
if (error.toString().includes("No such file") || error === 2) {
|
||||
// File doesn't exist, create it with default values
|
||||
writeAdapter()
|
||||
// Also write to fallback if set
|
||||
if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) {
|
||||
settingsFallbackFileView.writeAdapter()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback FileView for writing settings to alternate location
|
||||
FileView {
|
||||
id: settingsFallbackFileView
|
||||
path: Quickshell.env("NOCTALIA_SETTINGS_FALLBACK") || ""
|
||||
adapter: Quickshell.env("NOCTALIA_SETTINGS_FALLBACK") ? adapter : null
|
||||
printErrors: false
|
||||
watchChanges: false
|
||||
}
|
||||
JsonAdapter {
|
||||
id: adapter
|
||||
|
||||
@@ -224,6 +239,7 @@ Singleton {
|
||||
property list<string> pinnedExecs: []
|
||||
property bool useApp2Unit: false
|
||||
property bool sortByMostUsed: true
|
||||
property string terminalCommand: "xterm -e"
|
||||
}
|
||||
|
||||
// dock
|
||||
@@ -232,6 +248,7 @@ Singleton {
|
||||
property bool exclusive: false
|
||||
property real backgroundOpacity: 1.0
|
||||
property real floatingRatio: 1.0
|
||||
property bool onlySameOutput: true
|
||||
property list<string> monitors: []
|
||||
// Desktop entry IDs pinned to the dock (e.g., "org.kde.konsole", "firefox.desktop")
|
||||
property list<string> pinnedApps: []
|
||||
@@ -277,7 +294,8 @@ Singleton {
|
||||
property JsonObject ui: JsonObject {
|
||||
property string fontDefault: "Roboto"
|
||||
property string fontFixed: "DejaVu Sans Mono"
|
||||
property string fontBillboard: "Inter"
|
||||
property real fontDefaultScale: 1.0
|
||||
property real fontFixedScale: 1.0
|
||||
property list<var> monitorsScaling: []
|
||||
property bool idleInhibitorEnabled: false
|
||||
}
|
||||
@@ -515,17 +533,4 @@ Singleton {
|
||||
const widgetAfter = JSON.stringify(widget)
|
||||
return (widgetAfter !== widgetBefore)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Kickoff essential services
|
||||
function kickOffServices() {
|
||||
LocationService.init()
|
||||
NightLightService.apply()
|
||||
ColorSchemeService.init()
|
||||
MatugenService.init()
|
||||
WallpaperService.init()
|
||||
FontService.init()
|
||||
HooksService.init()
|
||||
BluetoothService.init()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ Singleton {
|
||||
"keyboard": "keyboard",
|
||||
"shutdown": "power",
|
||||
"lock": "lock",
|
||||
"lock-pause": "lock-pause",
|
||||
"logout": "logout",
|
||||
"reboot": "refresh",
|
||||
"suspend": "player-pause",
|
||||
@@ -70,6 +71,8 @@ Singleton {
|
||||
"chevron-down": "chevron-down",
|
||||
"caret-up": "caret-up-filled",
|
||||
"caret-down": "caret-down-filled",
|
||||
"star": "star",
|
||||
"star-off": "star-off",
|
||||
"battery-exclamation": "battery-exclamation",
|
||||
"battery-charging": "battery-charging",
|
||||
"battery-4": "battery-4",
|
||||
|
||||
@@ -13,7 +13,7 @@ Variants {
|
||||
|
||||
required property ShellScreen modelData
|
||||
|
||||
active: Settings.isLoaded && modelData && Settings.data.wallpaper.enabled
|
||||
active: modelData && Settings.data.wallpaper.enabled
|
||||
|
||||
sourceComponent: PanelWindow {
|
||||
id: root
|
||||
@@ -41,16 +41,10 @@ Variants {
|
||||
property string futureWallpaper: ""
|
||||
|
||||
// Fillmode default is "crop"
|
||||
property real fillMode: 1.0
|
||||
property real fillMode: WallpaperService.getFillModeUniform()
|
||||
property vector4d fillColor: Qt.vector4d(Settings.data.wallpaper.fillColor.r, Settings.data.wallpaper.fillColor.g, Settings.data.wallpaper.fillColor.b, 1.0)
|
||||
|
||||
// On startup assign wallpaper immediately
|
||||
Component.onCompleted: {
|
||||
fillMode = WallpaperService.getFillModeUniform()
|
||||
|
||||
var path = modelData ? WallpaperService.getWallpaper(modelData.name) : ""
|
||||
setWallpaperImmediate(path)
|
||||
}
|
||||
Component.onCompleted: setWallpaperInitial()
|
||||
|
||||
Connections {
|
||||
target: Settings.data.wallpaper
|
||||
@@ -64,7 +58,6 @@ Variants {
|
||||
target: WallpaperService
|
||||
function onWallpaperChanged(screenName, path) {
|
||||
if (screenName === modelData.name) {
|
||||
|
||||
// Update wallpaper display
|
||||
// Set wallpaper immediately on startup
|
||||
futureWallpaper = path
|
||||
@@ -230,6 +223,7 @@ Variants {
|
||||
easing.type: Easing.InOutCubic
|
||||
onFinished: {
|
||||
// Swap images after transition completes
|
||||
currentWallpaper.source = ""
|
||||
currentWallpaper.source = nextWallpaper.source
|
||||
nextWallpaper.source = ""
|
||||
transitionProgress = 0.0
|
||||
@@ -239,9 +233,20 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
function setWallpaperInitial() {
|
||||
// On startup, defer assigning wallpaper until the service cache is ready, retries every tick
|
||||
if (!WallpaperService || !WallpaperService.isInitialized) {
|
||||
Qt.callLater(setWallpaperInitial)
|
||||
return
|
||||
}
|
||||
|
||||
setWallpaperImmediate(WallpaperService.getWallpaper(modelData.name))
|
||||
}
|
||||
|
||||
function setWallpaperImmediate(source) {
|
||||
transitionAnimation.stop()
|
||||
transitionProgress = 0.0
|
||||
currentWallpaper.source = ""
|
||||
currentWallpaper.source = source
|
||||
nextWallpaper.source = ""
|
||||
}
|
||||
@@ -255,8 +260,12 @@ Variants {
|
||||
// We are interrupting a transition
|
||||
transitionAnimation.stop()
|
||||
transitionProgress = 0
|
||||
currentWallpaper.source = nextWallpaper.source
|
||||
|
||||
const newCurrentSource = nextWallpaper.source
|
||||
currentWallpaper.source = ""
|
||||
nextWallpaper.source = ""
|
||||
|
||||
currentWallpaper.source = newCurrentSource
|
||||
}
|
||||
|
||||
nextWallpaper.source = source
|
||||
|
||||
@@ -12,7 +12,7 @@ Variants {
|
||||
delegate: Loader {
|
||||
required property ShellScreen modelData
|
||||
|
||||
active: Settings.isLoaded && CompositorService.isNiri && modelData && Settings.data.wallpaper.enabled
|
||||
active: CompositorService.isNiri && modelData && Settings.data.wallpaper.enabled
|
||||
|
||||
property string wallpaper: ""
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
active: Settings.isLoaded && BarService.isVisible && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) : false
|
||||
active: BarService.isVisible && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) : false
|
||||
|
||||
sourceComponent: PanelWindow {
|
||||
screen: modelData || null
|
||||
@@ -55,6 +55,12 @@ Variants {
|
||||
right: Settings.data.bar.floating && Settings.data.bar.position !== "left" ? Settings.data.bar.marginHorizontal * Style.marginXL * scaling : 0
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (modelData && modelData.name) {
|
||||
BarService.registerBar(modelData.name)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
|
||||
@@ -22,7 +22,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: root.label
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mSecondary
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.fillWidth: true
|
||||
@@ -67,7 +67,7 @@ ColumnLayout {
|
||||
// One device BT icon
|
||||
NIcon {
|
||||
icon: BluetoothService.getDeviceIcon(modelData)
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: getContentColor(Color.mOnSurface)
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
@@ -79,7 +79,7 @@ ColumnLayout {
|
||||
// Device name
|
||||
NText {
|
||||
text: modelData.name || modelData.deviceName
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
elide: Text.ElideRight
|
||||
color: getContentColor(Color.mOnSurface)
|
||||
@@ -90,7 +90,7 @@ ColumnLayout {
|
||||
NText {
|
||||
text: BluetoothService.getStatusString(modelData)
|
||||
visible: text !== ""
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: getContentColor(Color.mOnSurfaceVariant)
|
||||
}
|
||||
|
||||
@@ -103,21 +103,21 @@ ColumnLayout {
|
||||
// Device signal strength - "Unknown" when not connected
|
||||
NText {
|
||||
text: BluetoothService.getSignalStrength(modelData)
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: getContentColor(Color.mOnSurfaceVariant)
|
||||
}
|
||||
|
||||
NIcon {
|
||||
visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
|
||||
text: BluetoothService.getSignalIcon(modelData)
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: getContentColor(Color.mOnSurface)
|
||||
}
|
||||
|
||||
NText {
|
||||
visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked
|
||||
text: (modelData.signalStrength !== undefined && modelData.signalStrength > 0) ? modelData.signalStrength + "%" : ""
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: getContentColor(Color.mOnSurface)
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ ColumnLayout {
|
||||
NText {
|
||||
visible: modelData.batteryAvailable
|
||||
text: BluetoothService.getBattery(modelData)
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: getContentColor(Color.mOnSurfaceVariant)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,13 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "bluetooth"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("bluetooth.panel.title")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
@@ -88,21 +88,21 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "bluetooth-off"
|
||||
font.pointSize: 64 * scaling
|
||||
pointSize: 64 * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("bluetooth.panel.disabled")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("bluetooth.panel.enable-message")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
@@ -186,7 +186,7 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "refresh"
|
||||
font.pointSize: Style.fontSizeXXL * 1.5 * scaling
|
||||
pointSize: Style.fontSizeXXL * 1.5 * scaling
|
||||
color: Color.mPrimary
|
||||
|
||||
RotationAnimation on rotation {
|
||||
@@ -200,14 +200,14 @@ NPanel {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("bluetooth.panel.scanning")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("bluetooth.panel.pairing-mode")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ NPanel {
|
||||
text: grid.title
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mPrimary
|
||||
}
|
||||
@@ -83,7 +83,7 @@ NPanel {
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("calendar.panel.week")
|
||||
color: Color.mOutline
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightRegular
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
@@ -113,7 +113,7 @@ NPanel {
|
||||
return Qt.locale().dayName(dayIndex, Locale.ShortFormat)
|
||||
}
|
||||
color: Color.mSecondary
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
@@ -148,7 +148,7 @@ NPanel {
|
||||
NText {
|
||||
anchors.centerIn: parent
|
||||
color: Color.mOutline
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
text: {
|
||||
// Calculate the date shown in the first column of this row
|
||||
@@ -229,7 +229,7 @@ NPanel {
|
||||
text: model.day
|
||||
color: model.today ? Color.mOnPrimary : Color.mOnSurface
|
||||
opacity: model.month === grid.month ? Style.opacityHeavy : Style.opacityLight
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: model.today ? Style.fontWeightBold : Style.fontWeightRegular
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,13 @@ Item {
|
||||
width: pillHeight + Math.max(0, pill.width - pillOverlap)
|
||||
height: pillHeight
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onTooltipTextChanged() {
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: pill
|
||||
width: revealed ? pillMaxWidth : 1
|
||||
@@ -77,8 +84,8 @@ Item {
|
||||
return centerX + offset
|
||||
}
|
||||
text: root.text + root.suffix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightBold
|
||||
color: forceOpen ? Color.mOnSurface : Color.mPrimary
|
||||
visible: revealed
|
||||
@@ -119,7 +126,7 @@ Item {
|
||||
|
||||
NIcon {
|
||||
icon: root.icon
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
color: hovered ? Color.mOnTertiary : Color.mOnSurface
|
||||
// Center horizontally
|
||||
x: (iconCircle.width - width) / 2
|
||||
@@ -195,14 +202,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: tooltip
|
||||
positionAbove: Settings.data.bar.position === "bottom"
|
||||
target: pill
|
||||
delay: Style.tooltipDelayLong
|
||||
text: root.tooltipText
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: showTimer
|
||||
interval: Style.pillDelay
|
||||
@@ -220,7 +219,7 @@ Item {
|
||||
onEntered: {
|
||||
hovered = true
|
||||
root.entered()
|
||||
tooltip.show()
|
||||
TooltipService.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||
if (disableOpen || forceClose) {
|
||||
return
|
||||
}
|
||||
@@ -234,7 +233,7 @@ Item {
|
||||
if (!forceOpen && !forceClose) {
|
||||
hide()
|
||||
}
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
|
||||
@@ -58,6 +58,13 @@ Item {
|
||||
width: buttonSize
|
||||
height: revealed ? (buttonSize + maxPillHeight - pillOverlap) : buttonSize
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onTooltipTextChanged() {
|
||||
TooltipService.updateText(root.tooltipText)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: pill
|
||||
width: revealed ? maxPillWidth : 1
|
||||
@@ -91,8 +98,8 @@ Item {
|
||||
return offset
|
||||
}
|
||||
text: root.text + root.suffix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -144,7 +151,7 @@ Item {
|
||||
|
||||
NIcon {
|
||||
icon: root.icon
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
color: hovered ? Color.mOnTertiary : Color.mOnSurface
|
||||
// Center horizontally
|
||||
x: (iconCircle.width - width) / 2
|
||||
@@ -236,15 +243,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: tooltip
|
||||
target: pill
|
||||
text: root.tooltipText
|
||||
positionLeft: barPosition === "right"
|
||||
positionRight: barPosition === "left"
|
||||
delay: Style.tooltipDelayLong
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: showTimer
|
||||
interval: Style.pillDelay
|
||||
@@ -262,7 +260,7 @@ Item {
|
||||
onEntered: {
|
||||
hovered = true
|
||||
root.entered()
|
||||
tooltip.show()
|
||||
TooltipService.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||
if (disableOpen || forceClose) {
|
||||
return
|
||||
}
|
||||
@@ -276,7 +274,7 @@ Item {
|
||||
if (!forceOpen && !forceClose) {
|
||||
hide()
|
||||
}
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
|
||||
@@ -29,7 +29,7 @@ Item {
|
||||
id: loader
|
||||
|
||||
anchors.fill: parent
|
||||
active: Settings.isLoaded && widgetId !== ""
|
||||
active: widgetId !== ""
|
||||
sourceComponent: {
|
||||
if (!active) {
|
||||
return null
|
||||
|
||||
@@ -160,7 +160,7 @@ PopupWindow {
|
||||
Layout.fillWidth: true
|
||||
color: (modelData?.enabled ?? true) ? (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) : Color.mOnSurfaceVariant
|
||||
text: modelData?.text !== "" ? modelData?.text.replace(/[\n\r]+/g, ' ') : "..."
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
@@ -175,7 +175,7 @@ PopupWindow {
|
||||
|
||||
NIcon {
|
||||
icon: modelData?.hasChildren ? "menu" : ""
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: modelData?.hasChildren ?? false
|
||||
color: (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface)
|
||||
|
||||
@@ -35,13 +35,13 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: Settings.data.network.wifiEnabled ? "wifi" : "wifi-off"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: Settings.data.network.wifiEnabled ? Color.mPrimary : Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wifi.panel.title")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
@@ -92,14 +92,14 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "warning"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mError
|
||||
}
|
||||
|
||||
NText {
|
||||
text: NetworkService.lastError
|
||||
color: Color.mError
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -130,21 +130,21 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "wifi-off"
|
||||
font.pointSize: 64 * scaling
|
||||
pointSize: 64 * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wifi.panel.disabled")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wifi.panel.enable-message")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
@@ -173,7 +173,7 @@ NPanel {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wifi.panel.searching")
|
||||
font.pointSize: Style.fontSizeNormal * scaling
|
||||
pointSize: Style.fontSizeNormal * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
@@ -242,7 +242,7 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: NetworkService.signalIcon(modelData.signal)
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: modelData.connected ? Color.mPrimary : Color.mOnSurface
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ NPanel {
|
||||
|
||||
NText {
|
||||
text: modelData.ssid
|
||||
font.pointSize: Style.fontSizeNormal * scaling
|
||||
pointSize: Style.fontSizeNormal * scaling
|
||||
font.weight: modelData.connected ? Style.fontWeightBold : Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
elide: Text.ElideRight
|
||||
@@ -266,19 +266,19 @@ NPanel {
|
||||
text: I18n.tr("system.signal-strength", {
|
||||
"signal": modelData.signal
|
||||
})
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NText {
|
||||
text: "•"
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NText {
|
||||
text: NetworkService.isSecured(modelData.security) ? modelData.security : "Open"
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ NPanel {
|
||||
id: connectedText
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("wifi.panel.connected")
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
}
|
||||
@@ -314,7 +314,7 @@ NPanel {
|
||||
id: disconnectingText
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("wifi.panel.disconnecting")
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
}
|
||||
@@ -330,7 +330,7 @@ NPanel {
|
||||
id: forgettingText
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("wifi.panel.forgetting")
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ NPanel {
|
||||
id: savedText
|
||||
anchors.centerIn: parent
|
||||
text: I18n.tr("wifi.panel.saved")
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
}
|
||||
@@ -439,6 +439,7 @@ NPanel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Style.marginS * scaling
|
||||
text: passwordInput
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurface
|
||||
echoMode: TextInput.Password
|
||||
@@ -456,12 +457,12 @@ NPanel {
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
NText {
|
||||
visible: parent.text.length === 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: I18n.tr("wifi.panel.enter-password")
|
||||
color: Color.mOnSurfaceVariant
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -508,13 +509,13 @@ NPanel {
|
||||
RowLayout {
|
||||
NIcon {
|
||||
icon: "trash"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mError
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wifi.panel.forget-network")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mError
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -557,14 +558,14 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "search"
|
||||
font.pointSize: 64 * scaling
|
||||
pointSize: 64 * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wifi.panel.no-networks")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ Item {
|
||||
id: fullTitleMetrics
|
||||
visible: false
|
||||
text: windowTitle
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
}
|
||||
|
||||
@@ -239,13 +239,13 @@ Item {
|
||||
property real scrollX: 0
|
||||
x: scrollX
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
spacing: 50 * scaling // Gap between text copies
|
||||
|
||||
NText {
|
||||
id: titleText
|
||||
text: windowTitle
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mOnSurface
|
||||
@@ -328,29 +328,17 @@ Item {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onEntered: {
|
||||
if (barPosition === "left" || barPosition === "right") {
|
||||
tooltip.show()
|
||||
} else if ((tooltip.text !== "") && (scrollingMode === "never")) {
|
||||
tooltip.show()
|
||||
if ((windowTitle !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
||||
TooltipService.show(root, windowTitle, BarService.getTooltipDirection())
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: tooltip
|
||||
text: windowTitle
|
||||
target: (barPosition === "left" || barPosition === "right") ? verticalLayout : windowActiveRect
|
||||
positionLeft: barPosition === "right"
|
||||
positionRight: barPosition === "left"
|
||||
positionAbove: Settings.data.bar.position === "bottom"
|
||||
delay: Style.tooltipDelay
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: CompositorService
|
||||
function onActiveWindowChanged() {
|
||||
|
||||
@@ -19,9 +19,9 @@ NIconButton {
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
||||
icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off"
|
||||
tooltipText: I18n.tr("tooltips.bluetooth-devices")
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
icon: BluetoothService.enabled ? "bluetooth" : "bluetooth-off"
|
||||
onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this)
|
||||
onRightClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ Rectangle {
|
||||
|
||||
// Resolve settings: try user settings or defaults from BarWidgetRegistry
|
||||
readonly property bool usePrimaryColor: widgetSettings.usePrimaryColor !== undefined ? widgetSettings.usePrimaryColor : widgetMetadata.usePrimaryColor
|
||||
property bool useMonospacedFont: widgetSettings.useMonospacedFont !== undefined ? widgetSettings.useMonospacedFont : widgetMetadata.useMonospacedFont
|
||||
readonly property bool useCustomFont: widgetSettings.useCustomFont !== undefined ? widgetSettings.useCustomFont : widgetMetadata.useCustomFont
|
||||
readonly property string customFont: widgetSettings.customFont !== undefined ? widgetSettings.customFont : widgetMetadata.customFont
|
||||
readonly property string formatHorizontal: widgetSettings.formatHorizontal !== undefined ? widgetSettings.formatHorizontal : widgetMetadata.formatHorizontal
|
||||
readonly property string formatVertical: widgetSettings.formatVertical !== undefined ? widgetSettings.formatVertical : widgetMetadata.formatVertical
|
||||
|
||||
@@ -61,12 +62,12 @@ Rectangle {
|
||||
spacing: Settings.data.bar.showCapsule ? -4 * scaling : -2 * scaling
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: Qt.formatDateTime(now, formatHorizontal.trim()).split("\\n")
|
||||
model: Qt.locale().toString(now, formatHorizontal.trim()).split("\\n")
|
||||
NText {
|
||||
visible: text !== ""
|
||||
text: modelData
|
||||
font.family: useMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault
|
||||
font.pointSize: {
|
||||
family: useCustomFont && customFont ? customFont : Settings.data.ui.fontDefault
|
||||
pointSize: {
|
||||
if (repeater.model.length == 1) {
|
||||
return Style.fontSizeS * scaling
|
||||
} else {
|
||||
@@ -91,12 +92,12 @@ Rectangle {
|
||||
anchors.centerIn: parent
|
||||
spacing: -2 * scaling
|
||||
Repeater {
|
||||
model: Qt.formatDateTime(now, formatVertical.trim()).split(" ")
|
||||
model: Qt.locale().toString(now, formatVertical.trim()).split(" ")
|
||||
delegate: NText {
|
||||
visible: text !== ""
|
||||
text: modelData
|
||||
font.family: useMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
family: useCustomFont && customFont ? customFont : Settings.data.ui.fontDefault
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: usePrimaryColor ? Color.mPrimary : Color.mOnSurface
|
||||
wrapMode: Text.WordWrap
|
||||
@@ -106,14 +107,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
NTooltip {
|
||||
id: tooltip
|
||||
text: I18n.tr("clock.tooltip")
|
||||
target: clockContainer
|
||||
positionAbove: Settings.data.bar.position === "bottom"
|
||||
positionLeft: barPosition === "right"
|
||||
positionRight: barPosition === "left"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: clockMouseArea
|
||||
@@ -122,14 +115,14 @@ Rectangle {
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
if (!PanelService.getPanel("calendarPanel")?.active) {
|
||||
tooltip.show()
|
||||
TooltipService.show(root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection())
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
onClicked: {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
PanelService.getPanel("calendarPanel")?.toggle(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,7 @@ NIconButton {
|
||||
// If we have a custom path or distro logo, don't use the theme icon.
|
||||
icon: (customIconPath === "" && !useDistroLogo) ? customIcon : ""
|
||||
tooltipText: I18n.tr("tooltips.open-control-center")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
baseSize: Style.capsuleHeight
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
@@ -56,7 +54,7 @@ NIconButton {
|
||||
height: width
|
||||
source: {
|
||||
if (customIconPath !== "")
|
||||
return customIconPath
|
||||
return customIconPath.startsWith("file://") ? customIconPath : "file://" + customIconPath
|
||||
if (useDistroLogo)
|
||||
return DistroLogoService.osLogo
|
||||
return ""
|
||||
|
||||
@@ -11,9 +11,7 @@ NIconButton {
|
||||
|
||||
icon: "dark-mode"
|
||||
tooltipText: Settings.data.colorSchemes.darkMode ? I18n.tr("tooltips.switch-to-light-mode") : I18n.tr("tooltips.switch-to-dark-mode")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
colorBg: Settings.data.colorSchemes.darkMode ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary
|
||||
|
||||
@@ -15,9 +15,7 @@ NIconButton {
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off"
|
||||
tooltipText: IdleInhibitorService.isInhibited ? I18n.tr("tooltips.disable-keep-awake") : I18n.tr("tooltips.enable-keep-awake")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
|
||||
@@ -42,10 +42,28 @@ Item {
|
||||
// Fixed width - no expansion
|
||||
readonly property real widgetWidth: Math.max(1, screen.width * 0.06)
|
||||
|
||||
readonly property bool hasActivePlayer: MediaService.currentPlayer !== null && getTitle() !== ""
|
||||
readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player")
|
||||
|
||||
readonly property string tooltipText: {
|
||||
var title = getTitle()
|
||||
var controls = ""
|
||||
if (MediaService.canGoNext) {
|
||||
controls += "Right click for next.\n"
|
||||
}
|
||||
if (MediaService.canGoPrevious) {
|
||||
controls += "Middle click for previous."
|
||||
}
|
||||
if (controls !== "") {
|
||||
return title + "\n\n" + controls
|
||||
}
|
||||
return title
|
||||
}
|
||||
|
||||
implicitHeight: visible ? ((barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling)) : 0
|
||||
implicitWidth: visible ? ((barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (widgetWidth * scaling)) : 0
|
||||
|
||||
opacity: !autoHide || getTitle() !== "" ? 1.0 : 0
|
||||
opacity: !autoHide || hasActivePlayer || (!hasActivePlayer && !autoHide) ? 1.0 : 0
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: Style.animationNormal
|
||||
@@ -136,21 +154,22 @@ Item {
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Style.marginS * scaling
|
||||
visible: (barPosition === "top" || barPosition === "bottom") && getTitle() !== ""
|
||||
visible: (barPosition === "top" || barPosition === "bottom")
|
||||
z: 1 // Above the visualizer
|
||||
|
||||
NIcon {
|
||||
id: windowIcon
|
||||
icon: MediaService.isPlaying ? "media-pause" : "media-play"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc"
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: !showAlbumArt && getTitle() !== "" && !trackArt.visible
|
||||
visible: !hasActivePlayer || (!showAlbumArt && !trackArt.visible)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: showAlbumArt
|
||||
visible: showAlbumArt && hasActivePlayer
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
@@ -172,6 +191,10 @@ Item {
|
||||
Item {
|
||||
id: titleContainer
|
||||
Layout.preferredWidth: {
|
||||
if (!hasActivePlayer) {
|
||||
// When no active player, take full width to center the placeholder
|
||||
return mainContainer.width - Style.marginXXS * scaling * 2
|
||||
}
|
||||
// Calculate available width based on other elements in the row
|
||||
var iconWidth = (windowIcon.visible ? (Style.fontSizeL * scaling + Style.marginS * scaling) : 0)
|
||||
var albumArtWidth = (showAlbumArt ? (18 * scaling + Style.marginS * scaling) : 0)
|
||||
@@ -180,7 +203,7 @@ Item {
|
||||
return Math.max(20 * scaling, availableWidth)
|
||||
}
|
||||
Layout.maximumWidth: Layout.preferredWidth
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.alignment: hasActivePlayer ? Qt.AlignVCenter : Qt.AlignCenter
|
||||
Layout.preferredHeight: titleText.height
|
||||
|
||||
clip: true
|
||||
@@ -188,7 +211,7 @@ Item {
|
||||
property bool isScrolling: false
|
||||
property bool isResetting: false
|
||||
property real textWidth: fullTitleMetrics.contentWidth
|
||||
property real containerWidth: width
|
||||
property real containerWidth: 0
|
||||
property bool needsScrolling: textWidth > containerWidth
|
||||
|
||||
// Timer for "always" mode with delay
|
||||
@@ -235,8 +258,15 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
onWidthChanged: updateScrollingState()
|
||||
Component.onCompleted: updateScrollingState()
|
||||
onWidthChanged: {
|
||||
containerWidth = width
|
||||
updateScrollingState()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
containerWidth = width
|
||||
updateScrollingState()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mouseArea
|
||||
@@ -249,29 +279,31 @@ Item {
|
||||
Item {
|
||||
id: scrollContainer
|
||||
height: parent.height
|
||||
width: childrenRect.width
|
||||
width: parent.width
|
||||
|
||||
property real scrollX: 0
|
||||
x: scrollX
|
||||
x: hasActivePlayer ? scrollX : 0
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
spacing: 50 * scaling // Gap between text copies
|
||||
|
||||
NText {
|
||||
id: titleText
|
||||
text: getTitle()
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
text: hasActivePlayer ? getTitle() : placeholderText
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mOnSurface
|
||||
horizontalAlignment: hasActivePlayer ? Text.AlignLeft : Text.AlignHCenter
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NText {
|
||||
text: getTitle()
|
||||
text: hasActivePlayer ? getTitle() : placeholderText
|
||||
font: titleText.font
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Color.mOnSurface
|
||||
visible: titleContainer.needsScrolling && titleContainer.isScrolling
|
||||
horizontalAlignment: hasActivePlayer ? Text.AlignLeft : Text.AlignHCenter
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
visible: hasActivePlayer && titleContainer.needsScrolling && titleContainer.isScrolling
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,13 +353,13 @@ Item {
|
||||
width: Style.baseWidgetSize * 0.5 * scaling
|
||||
height: Style.baseWidgetSize * 0.5 * scaling
|
||||
anchors.centerIn: parent
|
||||
visible: getTitle() !== ""
|
||||
|
||||
NIcon {
|
||||
id: mediaIconVertical
|
||||
anchors.fill: parent
|
||||
icon: MediaService.isPlaying ? "media-pause" : "media-play"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc"
|
||||
color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
@@ -339,10 +371,10 @@ Item {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
cursorShape: hasActivePlayer ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
onClicked: mouse => {
|
||||
if (!MediaService.currentPlayer || !MediaService.canPlay) {
|
||||
if (!hasActivePlayer || !MediaService.currentPlayer || !MediaService.canPlay) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -360,39 +392,15 @@ Item {
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
if ((tooltip.text !== "") && (barPosition === "left" || barPosition === "right")) {
|
||||
tooltip.show()
|
||||
} else if ((tooltip.text !== "") && (scrollingMode === "never")) {
|
||||
tooltip.show()
|
||||
var textToShow = hasActivePlayer ? tooltipText : placeholderText
|
||||
if ((textToShow !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
||||
TooltipService.show(root, textToShow, BarService.getTooltipDirection())
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: tooltip
|
||||
text: {
|
||||
var title = getTitle()
|
||||
var controls = ""
|
||||
if (MediaService.canGoNext) {
|
||||
controls += "Right click for next.\n"
|
||||
}
|
||||
if (MediaService.canGoPrevious) {
|
||||
controls += "Middle click for previous."
|
||||
}
|
||||
if (controls !== "") {
|
||||
return title + "\n\n" + controls
|
||||
}
|
||||
return title
|
||||
}
|
||||
target: (barPosition === "left" || barPosition === "right") ? verticalLayout : mediaMini
|
||||
positionLeft: barPosition === "right"
|
||||
positionRight: barPosition === "left"
|
||||
positionAbove: Settings.data.bar.position === "bottom"
|
||||
delay: Style.tooltipDelay
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,7 @@ NIconButton {
|
||||
|
||||
icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off"
|
||||
tooltipText: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? I18n.tr("tooltips.night-light-forced") : I18n.tr("tooltips.night-light-enabled")) : I18n.tr("tooltips.night-light-disabled")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
onClicked: {
|
||||
// Check if wlsunset is available before enabling night light
|
||||
if (!ProgramCheckerService.wlsunsetAvailable) {
|
||||
|
||||
@@ -53,9 +53,7 @@ NIconButton {
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell"
|
||||
tooltipText: Settings.data.notifications.doNotDisturb ? I18n.tr("tooltips.open-notification-history-disable-dnd") : I18n.tr("tooltips.open-notification-history-enable-dnd")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
|
||||
@@ -19,9 +19,7 @@ NIconButton {
|
||||
tooltipText: I18n.tr("tooltips.power-profile", {
|
||||
"profile": PowerProfileService.getName()
|
||||
})
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
colorBg: (PowerProfileService.profile === PowerProfile.Balanced) ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary
|
||||
colorFg: (PowerProfileService.profile === PowerProfile.Balanced) ? Color.mOnSurface : Color.mOnPrimary
|
||||
|
||||
@@ -12,9 +12,7 @@ NIconButton {
|
||||
|
||||
icon: "camera-video"
|
||||
tooltipText: ScreenRecorderService.isRecording ? I18n.tr("tooltips.click-to-stop-recording") : I18n.tr("tooltips.click-to-start-recording")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
baseSize: Style.capsuleHeight
|
||||
colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
|
||||
@@ -15,9 +15,7 @@ NIconButton {
|
||||
baseSize: Style.capsuleHeight
|
||||
icon: "power"
|
||||
tooltipText: I18n.tr("tooltips.session-menu")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mError
|
||||
colorBorder: Color.transparent
|
||||
|
||||
@@ -53,7 +53,7 @@ Rectangle {
|
||||
id: percentMetrics
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightMedium
|
||||
font.pointSize: textSize
|
||||
font.pointSize: textSize * Settings.data.ui.fontFixedScale
|
||||
text: "99%" // Use the longest possible string for measurement
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ Rectangle {
|
||||
id: tempMetrics
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightMedium
|
||||
font.pointSize: textSize
|
||||
font.pointSize: textSize * Settings.data.ui.fontFixedScale
|
||||
text: "99°" // Use the longest possible string for measurement
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ Rectangle {
|
||||
id: memMetrics
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightMedium
|
||||
font.pointSize: textSize
|
||||
font.pointSize: textSize * Settings.data.ui.fontFixedScale
|
||||
text: "99.9K" // Longest value part of network speed
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ Rectangle {
|
||||
|
||||
NIcon {
|
||||
icon: "cpu-usage"
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
@@ -114,8 +114,8 @@ Rectangle {
|
||||
|
||||
NText {
|
||||
text: `${Math.round(SystemStatService.cpuUsage)}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: isVertical ? -1 : percentTextWidth
|
||||
@@ -147,7 +147,7 @@ Rectangle {
|
||||
|
||||
NIcon {
|
||||
icon: "cpu-temperature"
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
@@ -155,8 +155,8 @@ Rectangle {
|
||||
|
||||
NText {
|
||||
text: `${Math.round(SystemStatService.cpuTemp)}°`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: isVertical ? -1 : tempTextWidth
|
||||
@@ -188,7 +188,7 @@ Rectangle {
|
||||
|
||||
NIcon {
|
||||
icon: "memory"
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
@@ -196,8 +196,8 @@ Rectangle {
|
||||
|
||||
NText {
|
||||
text: showMemoryAsPercent ? `${Math.round(SystemStatService.memPercent)}%` : `${SystemStatService.memGb.toFixed(1)}G`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: isVertical ? -1 : (showMemoryAsPercent ? percentTextWidth : memTextWidth)
|
||||
@@ -229,7 +229,7 @@ Rectangle {
|
||||
|
||||
NIcon {
|
||||
icon: "download-speed"
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
@@ -237,8 +237,8 @@ Rectangle {
|
||||
|
||||
NText {
|
||||
text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.rxSpeed) : SystemStatService.formatSpeed(SystemStatService.rxSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: isVertical ? -1 : memTextWidth
|
||||
@@ -270,7 +270,7 @@ Rectangle {
|
||||
|
||||
NIcon {
|
||||
icon: "upload-speed"
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
@@ -278,8 +278,8 @@ Rectangle {
|
||||
|
||||
NText {
|
||||
text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.txSpeed) : SystemStatService.formatSpeed(SystemStatService.txSpeed)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: isVertical ? -1 : memTextWidth
|
||||
@@ -311,7 +311,7 @@ Rectangle {
|
||||
|
||||
NIcon {
|
||||
icon: "storage"
|
||||
font.pointSize: iconSize
|
||||
pointSize: iconSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.row: isVertical ? 1 : 0
|
||||
Layout.column: 0
|
||||
@@ -319,8 +319,8 @@ Rectangle {
|
||||
|
||||
NText {
|
||||
text: `${SystemStatService.diskPercent}%`
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: textSize
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
font.weight: Style.fontWeightMedium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: isVertical ? -1 : percentTextWidth
|
||||
|
||||
@@ -13,10 +13,27 @@ Rectangle {
|
||||
property ShellScreen screen
|
||||
property real scaling: 1.0
|
||||
|
||||
// Widget properties passed from Bar.qml for per-instance settings
|
||||
property string widgetId: ""
|
||||
property string section: ""
|
||||
property int sectionWidgetIndex: -1
|
||||
property int sectionWidgetsCount: 0
|
||||
|
||||
readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right"
|
||||
readonly property bool compact: (Settings.data.bar.density === "compact")
|
||||
readonly property real itemSize: compact ? Style.capsuleHeight * 0.9 * scaling : Style.capsuleHeight * 0.8 * scaling
|
||||
|
||||
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId]
|
||||
property var widgetSettings: {
|
||||
if (section && sectionWidgetIndex >= 0) {
|
||||
var widgets = Settings.data.bar.widgets[section]
|
||||
if (widgets && sectionWidgetIndex < widgets.length) {
|
||||
return widgets[sectionWidgetIndex]
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
// Always visible when there are toplevels
|
||||
implicitWidth: isVerticalBar ? Math.round(Style.capsuleHeight * scaling) : taskbarLayout.implicitWidth + Style.marginM * scaling * 2
|
||||
implicitHeight: isVerticalBar ? taskbarLayout.implicitHeight + Style.marginM * scaling * 2 : Math.round(Style.capsuleHeight * scaling)
|
||||
@@ -41,36 +58,36 @@ Rectangle {
|
||||
columnSpacing: isVerticalBar ? 0 : Style.marginXXS * root.scaling
|
||||
|
||||
Repeater {
|
||||
model: ToplevelManager && ToplevelManager.toplevels ? ToplevelManager.toplevels : []
|
||||
model: CompositorService.windows
|
||||
delegate: Item {
|
||||
id: taskbarItem
|
||||
required property Toplevel modelData
|
||||
property Toplevel toplevel: modelData
|
||||
property bool isActive: ToplevelManager.activeToplevel === modelData
|
||||
required property var modelData
|
||||
|
||||
visible: (!widgetSettings.onlySameOutput || modelData.output == screen.name) && (!widgetSettings.onlyActiveWorkspaces || CompositorService.getActiveWorkspaces().map(ws => ws.id).includes(modelData.workspaceId))
|
||||
|
||||
Layout.preferredWidth: root.itemSize
|
||||
Layout.preferredHeight: root.itemSize
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
|
||||
Rectangle {
|
||||
id: iconBackground
|
||||
anchors.centerIn: parent
|
||||
IconImage {
|
||||
|
||||
id: appIcon
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: taskbarItem.isActive ? Color.mPrimary : root.color
|
||||
border.width: 0
|
||||
radius: Math.round(Style.radiusXS * root.scaling)
|
||||
border.color: "transparent"
|
||||
z: -1
|
||||
source: ThemeIcons.iconForAppId(taskbarItem.modelData.appId)
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
opacity: modelData.isFocused ? Style.opacityFull : 0.6
|
||||
|
||||
IconImage {
|
||||
id: appIcon
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
source: ThemeIcons.iconForAppId(taskbarItem.modelData.appId)
|
||||
smooth: true
|
||||
asynchronous: true
|
||||
Rectangle {
|
||||
anchors.bottomMargin: -2 * scaling
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
id: iconBackground
|
||||
width: 4 * scaling
|
||||
height: 4 * scaling
|
||||
color: modelData.isFocused ? Color.mPrimary : Color.transparent
|
||||
radius: width * 0.5
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,29 +103,20 @@ Rectangle {
|
||||
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
try {
|
||||
taskbarItem.modelData.activate()
|
||||
CompositorService.focusWindow(taskbarItem.modelData.id)
|
||||
} catch (error) {
|
||||
Logger.error("Taskbar", "Failed to activate toplevel: " + error)
|
||||
}
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
try {
|
||||
taskbarItem.modelData.close()
|
||||
CompositorService.closeWindow(taskbarItem.modelData.id)
|
||||
} catch (error) {
|
||||
Logger.error("Taskbar", "Failed to close toplevel: " + error)
|
||||
}
|
||||
}
|
||||
}
|
||||
onEntered: taskbarTooltip.show()
|
||||
onExited: taskbarTooltip.hide()
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: taskbarTooltip
|
||||
text: taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown app."
|
||||
target: taskbarItem
|
||||
positionAbove: Settings.data.bar.position === "bottom"
|
||||
positionLeft: Settings.data.bar.position === "right"
|
||||
positionRight: Settings.data.bar.position === "left"
|
||||
onEntered: TooltipService.show(taskbarItem, taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown app.", BarService.getTooltipDirection())
|
||||
onExited: TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ Rectangle {
|
||||
|
||||
modelData.secondaryActivate && modelData.secondaryActivate()
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
trayTooltip.hide()
|
||||
TooltipService.hideImmediately()
|
||||
|
||||
// Close the menu if it was visible
|
||||
if (trayPanel && trayPanel.visible) {
|
||||
@@ -135,15 +135,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
onEntered: trayTooltip.show()
|
||||
onExited: trayTooltip.hide()
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: trayTooltip
|
||||
target: trayIcon
|
||||
text: modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item"
|
||||
positionAbove: Settings.data.bar.position === "bottom"
|
||||
onEntered: {
|
||||
trayPanel.close()
|
||||
TooltipService.show(trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
|
||||
}
|
||||
onExited: TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@ NIconButton {
|
||||
compact: (Settings.data.bar.density === "compact")
|
||||
icon: "wallpaper-selector"
|
||||
tooltipText: I18n.tr("tooltips.open-wallpaper-selector")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent)
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
|
||||
@@ -19,7 +19,8 @@ NIconButton {
|
||||
colorFg: Color.mOnSurface
|
||||
colorBorder: Color.transparent
|
||||
colorBorderHover: Color.transparent
|
||||
|
||||
tooltipText: I18n.tr("tooltips.manage-wifi")
|
||||
tooltipDirection: BarService.getTooltipDirection()
|
||||
icon: {
|
||||
try {
|
||||
if (NetworkService.ethernetConnected) {
|
||||
@@ -40,10 +41,6 @@ NIconButton {
|
||||
return "signal_wifi_bad"
|
||||
}
|
||||
}
|
||||
tooltipText: I18n.tr("tooltips.manage-wifi")
|
||||
tooltipPositionAbove: Settings.data.bar.position === "bottom"
|
||||
tooltipPositionLeft: Settings.data.bar.position === "right"
|
||||
tooltipPositionRight: Settings.data.bar.position === "left"
|
||||
onClicked: PanelService.getPanel("wifiPanel")?.toggle(this)
|
||||
onRightClicked: PanelService.getPanel("wifiPanel")?.toggle(this)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@@ -274,7 +275,7 @@ Item {
|
||||
Loader {
|
||||
active: (labelMode !== "none")
|
||||
sourceComponent: Component {
|
||||
Text {
|
||||
NText {
|
||||
x: (pill.width - width) / 2
|
||||
y: (pill.height - height) / 2 + (height - contentHeight) / 2
|
||||
text: {
|
||||
@@ -284,9 +285,9 @@ Item {
|
||||
return model.idx.toString()
|
||||
}
|
||||
}
|
||||
font.pointSize: model.isFocused ? workspacePillContainer.height * 0.45 : workspacePillContainer.height * 0.42
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: model.isFocused ? workspacePillContainer.height * 0.45 : workspacePillContainer.height * 0.42
|
||||
font.capitalization: Font.AllUppercase
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightBold
|
||||
wrapMode: Text.Wrap
|
||||
color: {
|
||||
@@ -418,7 +419,7 @@ Item {
|
||||
Loader {
|
||||
active: (labelMode !== "none")
|
||||
sourceComponent: Component {
|
||||
Text {
|
||||
NText {
|
||||
x: (pillVertical.width - width) / 2
|
||||
y: (pillVertical.height - height) / 2 + (height - contentHeight) / 2
|
||||
text: {
|
||||
@@ -428,9 +429,9 @@ Item {
|
||||
return model.idx.toString()
|
||||
}
|
||||
}
|
||||
font.pointSize: model.isFocused ? workspacePillContainerVertical.width * 0.45 : workspacePillContainerVertical.width * 0.42
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: model.isFocused ? workspacePillContainerVertical.width * 0.45 : workspacePillContainerVertical.width * 0.42
|
||||
font.capitalization: Font.AllUppercase
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.weight: Style.fontWeightBold
|
||||
wrapMode: Text.Wrap
|
||||
color: {
|
||||
|
||||
@@ -28,7 +28,7 @@ NBox {
|
||||
|
||||
NIcon {
|
||||
icon: "disc"
|
||||
font.pointSize: Style.fontSizeXXXL * 3 * scaling
|
||||
pointSize: Style.fontSizeXXXL * 3 * scaling
|
||||
color: Color.mPrimary
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
@@ -68,13 +68,13 @@ NBox {
|
||||
|
||||
NIcon {
|
||||
icon: "caret-down"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NText {
|
||||
text: playerSelectorButton.currentPlayer ? playerSelectorButton.currentPlayer.identity : ""
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -147,7 +147,7 @@ NBox {
|
||||
NIcon {
|
||||
icon: "disc"
|
||||
color: Color.mPrimary
|
||||
font.pointSize: Style.fontSizeXXXL * 3 * scaling
|
||||
pointSize: Style.fontSizeXXXL * 3 * scaling
|
||||
visible: !trackArt.visible
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
@@ -162,7 +162,7 @@ NBox {
|
||||
NText {
|
||||
visible: MediaService.trackTitle !== ""
|
||||
text: MediaService.trackTitle
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.Wrap
|
||||
@@ -174,7 +174,7 @@ NBox {
|
||||
visible: MediaService.trackArtist !== ""
|
||||
text: MediaService.trackArtist
|
||||
color: Color.mPrimary
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -183,7 +183,7 @@ NBox {
|
||||
visible: MediaService.trackAlbum !== ""
|
||||
text: MediaService.trackAlbum
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ NBox {
|
||||
text: I18n.tr("system.uptime", {
|
||||
"uptime": uptimeText
|
||||
})
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ NBox {
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode) : ""
|
||||
font.pointSize: Style.fontSizeXXXL * 1.75 * scaling
|
||||
pointSize: Style.fontSizeXXXL * 1.75 * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ NBox {
|
||||
const chunks = Settings.data.location.name.split(",")
|
||||
return chunks[0]
|
||||
}
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
|
||||
@@ -56,13 +56,13 @@ NBox {
|
||||
temp = Math.round(temp)
|
||||
return `${temp}°${suffix}`
|
||||
}
|
||||
font.pointSize: Style.fontSizeXL * scaling
|
||||
pointSize: Style.fontSizeXL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
|
||||
NText {
|
||||
text: weatherReady ? `(${LocationService.data.weather.timezone_abbreviation})` : ""
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
visible: LocationService.data.weather
|
||||
}
|
||||
@@ -88,7 +88,7 @@ NBox {
|
||||
NText {
|
||||
text: {
|
||||
var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/"))
|
||||
return Qt.formatDateTime(weatherDate, "ddd")
|
||||
return Qt.locale().toString(weatherDate, "ddd")
|
||||
}
|
||||
color: Color.mOnSurface
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@@ -96,7 +96,7 @@ NBox {
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||
icon: LocationService.weatherSymbolFromCode(LocationService.data.weather.daily.weathercode[index])
|
||||
font.pointSize: Style.fontSizeXXL * 1.6 * scaling
|
||||
pointSize: Style.fontSizeXXL * 1.6 * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
NText {
|
||||
@@ -112,7 +112,7 @@ NBox {
|
||||
min = Math.round(min)
|
||||
return `${max}°/${min}°`
|
||||
}
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,19 @@ Variants {
|
||||
|
||||
delegate: Item {
|
||||
id: root
|
||||
|
||||
required property ShellScreen modelData
|
||||
property real scaling: ScalingService.getScreenScale(modelData)
|
||||
property bool barIsReady: BarService.isBarReady(modelData.name)
|
||||
|
||||
Connections {
|
||||
target: BarService
|
||||
function onBarReadyChanged(screenName) {
|
||||
if (screenName === modelData.name) {
|
||||
barIsReady = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ScalingService
|
||||
@@ -40,19 +51,14 @@ Variants {
|
||||
function onPinnedAppsChanged() {
|
||||
updateDockApps()
|
||||
}
|
||||
}
|
||||
|
||||
// Initial update when component is ready
|
||||
Component.onCompleted: {
|
||||
if (Settings.isLoaded && ToplevelManager) {
|
||||
function onOnlySameOutputChanged() {
|
||||
updateDockApps()
|
||||
}
|
||||
}
|
||||
|
||||
// Update when Settings are loaded
|
||||
Connections {
|
||||
target: Settings
|
||||
function onSettingsLoaded() {
|
||||
// Initial update when component is ready
|
||||
Component.onCompleted: {
|
||||
if (ToplevelManager) {
|
||||
updateDockApps()
|
||||
}
|
||||
}
|
||||
@@ -105,7 +111,7 @@ Variants {
|
||||
// Strategy: Maintain app positions as much as possible
|
||||
// 1. First pass: Add all running apps (both pinned and non-pinned) in their current order
|
||||
runningApps.forEach(toplevel => {
|
||||
if (toplevel && toplevel.appId) {
|
||||
if (toplevel && toplevel.appId && !(Settings.data.dock.onlySameOutput && toplevel.screens && !toplevel.screens.includes(modelData))) {
|
||||
const isPinned = pinnedApps.includes(toplevel.appId)
|
||||
const appType = isPinned ? "pinned-running" : "running"
|
||||
|
||||
@@ -187,7 +193,7 @@ Variants {
|
||||
|
||||
// PEEK WINDOW - Always visible when auto-hide is enabled
|
||||
Loader {
|
||||
active: Settings.isLoaded && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide
|
||||
active: (barIsReady || !hasBar) && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide
|
||||
|
||||
sourceComponent: PanelWindow {
|
||||
id: peekWindow
|
||||
@@ -233,7 +239,7 @@ Variants {
|
||||
|
||||
// DOCK WINDOW
|
||||
Loader {
|
||||
active: Settings.isLoaded && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0)
|
||||
active: (barIsReady || !hasBar) && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0)
|
||||
|
||||
sourceComponent: PanelWindow {
|
||||
id: dockWindow
|
||||
@@ -373,14 +379,6 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
// Individual tooltip for this app
|
||||
NTooltip {
|
||||
id: appTooltip
|
||||
target: appButton
|
||||
positionAbove: true
|
||||
visible: false
|
||||
}
|
||||
|
||||
Image {
|
||||
id: appIcon
|
||||
width: iconSize
|
||||
@@ -422,7 +420,7 @@ Variants {
|
||||
anchors.centerIn: parent
|
||||
visible: !appIcon.visible
|
||||
icon: "question-mark"
|
||||
font.pointSize: iconSize * 0.7
|
||||
pointSize: iconSize * 0.7
|
||||
color: appButton.isActive ? Color.mPrimary : Color.mOnSurfaceVariant
|
||||
opacity: appButton.isRunning ? 1.0 : 0.6
|
||||
scale: appButton.hovered ? 1.15 : 1.0
|
||||
@@ -481,8 +479,8 @@ Variants {
|
||||
onEntered: {
|
||||
anyAppHovered = true
|
||||
const appName = appButton.appTitle || appButton.appId || "Unknown"
|
||||
appTooltip.text = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
|
||||
appTooltip.isVisible = true
|
||||
const tooltipText = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
|
||||
TooltipService.show(appButton, tooltipText, "top")
|
||||
if (autoHide) {
|
||||
showTimer.stop()
|
||||
hideTimer.stop()
|
||||
@@ -492,7 +490,7 @@ Variants {
|
||||
|
||||
onExited: {
|
||||
anyAppHovered = false
|
||||
appTooltip.hide()
|
||||
TooltipService.hide()
|
||||
if (autoHide && !dockHovered && !peekHovered && !menuHovered) {
|
||||
hideTimer.restart()
|
||||
}
|
||||
@@ -508,7 +506,7 @@ Variants {
|
||||
// Close any other existing context menu first
|
||||
root.closeAllContextMenus()
|
||||
// Hide tooltip when showing context menu
|
||||
appTooltip.hide()
|
||||
TooltipService.hide()
|
||||
contextMenu.show(appButton, modelData.toplevel || modelData)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -14,9 +14,12 @@ PopupWindow {
|
||||
property var toplevel: null
|
||||
property Item anchorItem: null
|
||||
property real scaling: 1.0
|
||||
property bool hovered: menuMouseArea.containsMouse || activateMouseArea.containsMouse || pinMouseArea.containsMouse || closeMouseArea.containsMouse
|
||||
property bool hovered: menuMouseArea.containsMouse
|
||||
property var onAppClosed: null // Callback function for when an app is closed
|
||||
|
||||
// Track which menu item is hovered
|
||||
property int hoveredItem: -1 // -1: none, 0: focus, 1: pin, 2: close
|
||||
|
||||
signal requestClose
|
||||
|
||||
implicitWidth: 140 * scaling
|
||||
@@ -70,25 +73,64 @@ PopupWindow {
|
||||
visible = false
|
||||
}
|
||||
|
||||
// Close menu when clicking on background, track hover for the whole menu area
|
||||
MouseArea {
|
||||
id: menuMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: function (mouse) {
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
root.hide() // Close on right-click
|
||||
} else {
|
||||
root.hide() // Close when clicking on the background (outside menu content)
|
||||
// Helper function to determine which menu item is under the mouse
|
||||
function getHoveredItem(mouseY) {
|
||||
const itemHeight = 32 * scaling
|
||||
const startY = Style.marginM * scaling
|
||||
const relativeY = mouseY - startY
|
||||
|
||||
if (relativeY < 0)
|
||||
return -1
|
||||
|
||||
const itemIndex = Math.floor(relativeY / itemHeight)
|
||||
return itemIndex >= 0 && itemIndex < 3 ? itemIndex : -1
|
||||
}
|
||||
|
||||
// Handle menu item clicks
|
||||
function handleItemClick(itemIndex) {
|
||||
switch (itemIndex) {
|
||||
case 0:
|
||||
// Focus
|
||||
if (root.toplevel?.activate) {
|
||||
root.toplevel.activate()
|
||||
}
|
||||
root.requestClose()
|
||||
break
|
||||
case 1:
|
||||
// Pin/Unpin
|
||||
if (root.toplevel?.appId) {
|
||||
root.toggleAppPin(root.toplevel.appId)
|
||||
}
|
||||
root.requestClose()
|
||||
break
|
||||
case 2:
|
||||
// Close
|
||||
// Check if toplevel is still valid before trying to close it
|
||||
const isValidToplevel = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel)
|
||||
|
||||
if (isValidToplevel && root.toplevel.close) {
|
||||
root.toplevel.close()
|
||||
// Trigger immediate dock update callback if provided
|
||||
if (root.onAppClosed && typeof root.onAppClosed === "function") {
|
||||
Qt.callLater(root.onAppClosed)
|
||||
}
|
||||
} else {
|
||||
Logger.warn("DockMenu", "Cannot close app - invalid toplevel reference")
|
||||
}
|
||||
root.hide()
|
||||
root.requestClose()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: ["Escape"]
|
||||
enabled: root.visible
|
||||
onActivated: root.hide()
|
||||
Timer {
|
||||
id: closeTimer
|
||||
interval: 500
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
root.hide()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -98,15 +140,35 @@ PopupWindow {
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
|
||||
// Prevent clicks inside the menu from closing it
|
||||
// Single MouseArea to handle both auto-close and menu interactions
|
||||
MouseArea {
|
||||
id: menuMouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
hoverEnabled: true
|
||||
cursorShape: root.hoveredItem >= 0 ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
|
||||
} // Do nothing, just consume the click
|
||||
onEntered: {
|
||||
closeTimer.stop()
|
||||
}
|
||||
|
||||
onExited: {
|
||||
root.hoveredItem = -1
|
||||
closeTimer.start()
|
||||
}
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
root.hoveredItem = root.getHoveredItem(mouse.y)
|
||||
}
|
||||
|
||||
onClicked: mouse => {
|
||||
const clickedItem = root.getHoveredItem(mouse.y)
|
||||
if (clickedItem >= 0) {
|
||||
root.handleItemClick(clickedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
ColumnLayout {
|
||||
id: contextMenuColumn
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginM * scaling
|
||||
@@ -114,12 +176,12 @@ PopupWindow {
|
||||
|
||||
// Focus item
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
height: 32 * scaling
|
||||
color: activateMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||
color: root.hoveredItem === 0 ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusXS * scaling
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.marginS * scaling
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -127,42 +189,28 @@ PopupWindow {
|
||||
|
||||
NIcon {
|
||||
icon: "eye"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: activateMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("dock.menu.focus")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: activateMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: activateMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (root.toplevel?.activate) {
|
||||
root.toplevel.activate()
|
||||
}
|
||||
root.requestClose()
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pin/Unpin item
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
height: 32 * scaling
|
||||
color: pinMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||
color: root.hoveredItem === 1 ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusXS * scaling
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.marginS * scaling
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -174,9 +222,9 @@ PopupWindow {
|
||||
return "pin"
|
||||
return root.isAppPinned(root.toplevel.appId) ? "unpin" : "pin"
|
||||
}
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: pinMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
@@ -185,36 +233,21 @@ PopupWindow {
|
||||
return I18n.tr("dock.menu.pin")
|
||||
return root.isAppPinned(root.toplevel.appId) ? I18n.tr("dock.menu.unpin") : I18n.tr("dock.menu.pin")
|
||||
}
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: pinMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: pinMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
if (root.toplevel?.appId) {
|
||||
root.toggleAppPin(root.toplevel.appId)
|
||||
}
|
||||
//root.hide()
|
||||
root.requestClose()
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close item
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
Layout.fillWidth: true
|
||||
height: 32 * scaling
|
||||
color: closeMouseArea.containsMouse ? Color.mTertiary : Color.transparent
|
||||
color: root.hoveredItem === 2 ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusXS * scaling
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.marginS * scaling
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -222,40 +255,16 @@ PopupWindow {
|
||||
|
||||
NIcon {
|
||||
icon: "close"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
color: closeMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("dock.menu.close")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: closeMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
||||
onClicked: {
|
||||
// Check if toplevel is still valid before trying to close it
|
||||
const isValidToplevel = root.toplevel && ToplevelManager && ToplevelManager.toplevels.values.includes(root.toplevel)
|
||||
|
||||
if (isValidToplevel && root.toplevel.close) {
|
||||
root.toplevel.close()
|
||||
// Trigger immediate dock update callback if provided
|
||||
if (root.onAppClosed && typeof root.onAppClosed === "function") {
|
||||
Qt.callLater(root.onAppClosed)
|
||||
}
|
||||
} else {
|
||||
Logger.warn("DockMenu", "Cannot close app - invalid toplevel reference")
|
||||
}
|
||||
root.hide()
|
||||
root.requestClose()
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,11 +302,34 @@ NPanel {
|
||||
positionViewAtIndex(currentIndex, ListView.Contain)
|
||||
}
|
||||
}
|
||||
onModelChanged: {
|
||||
|
||||
}
|
||||
|
||||
delegate: Rectangle {
|
||||
id: entry
|
||||
|
||||
property bool isSelected: mouseArea.containsMouse || (index === selectedIndex)
|
||||
// Accessor for app id
|
||||
property string appId: (modelData && modelData.appId) ? String(modelData.appId) : ""
|
||||
|
||||
// Pin helpers
|
||||
function togglePin(appId) {
|
||||
if (!appId)
|
||||
return
|
||||
let arr = (Settings.data.dock.pinnedApps || []).slice()
|
||||
const idx = arr.indexOf(appId)
|
||||
if (idx >= 0)
|
||||
arr.splice(idx, 1)
|
||||
else
|
||||
arr.push(appId)
|
||||
Settings.data.dock.pinnedApps = arr
|
||||
}
|
||||
|
||||
function isPinned(appId) {
|
||||
const arr = Settings.data.dock.pinnedApps || []
|
||||
return appId && arr.indexOf(appId) >= 0
|
||||
}
|
||||
|
||||
// Property to reliably track the current item's ID.
|
||||
// This changes whenever the delegate is recycled for a new item.
|
||||
@@ -321,7 +344,7 @@ NPanel {
|
||||
}
|
||||
|
||||
width: resultsList.width - Style.marginS * scaling
|
||||
height: entryHeight
|
||||
implicitHeight: entryHeight
|
||||
radius: Style.radiusM * scaling
|
||||
color: entry.isSelected ? Color.mTertiary : Color.mSurface
|
||||
|
||||
@@ -332,136 +355,152 @@ NPanel {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
id: contentLayout
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginM * scaling
|
||||
spacing: Style.marginM * scaling
|
||||
|
||||
// Icon badge or Image preview
|
||||
Rectangle {
|
||||
Layout.preferredWidth: badgeSize
|
||||
Layout.preferredHeight: badgeSize
|
||||
radius: Style.radiusM * scaling
|
||||
color: Color.mSurfaceVariant
|
||||
clip: true
|
||||
// Top row - Main entry content with pin button
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM * scaling
|
||||
|
||||
// Image preview for clipboard images
|
||||
NImageRounded {
|
||||
id: imagePreview
|
||||
anchors.fill: parent
|
||||
visible: modelData.isImage
|
||||
imageRadius: Style.radiusM * scaling
|
||||
|
||||
// This property creates a dependency on the service's revision counter
|
||||
readonly property int _rev: ClipboardService.revision
|
||||
|
||||
// Fetches from the service's cache.
|
||||
// The dependency on `_rev` ensures this binding is re-evaluated when the cache is updated.
|
||||
imagePath: {
|
||||
_rev
|
||||
return ClipboardService.getImageData(modelData.clipboardId) || ""
|
||||
}
|
||||
|
||||
// Loading indicator
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: parent.status === Image.Loading
|
||||
color: Color.mSurfaceVariant
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
running: true
|
||||
width: Style.baseWidgetSize * 0.5 * scaling
|
||||
height: width
|
||||
}
|
||||
}
|
||||
|
||||
// Error fallback
|
||||
onStatusChanged: status => {
|
||||
if (status === Image.Error) {
|
||||
iconLoader.visible = true
|
||||
imagePreview.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Icon fallback
|
||||
Loader {
|
||||
id: iconLoader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginXS * scaling
|
||||
|
||||
visible: !modelData.isImage || imagePreview.status === Image.Error
|
||||
active: visible
|
||||
|
||||
sourceComponent: Component {
|
||||
IconImage {
|
||||
anchors.fill: parent
|
||||
source: modelData.icon ? ThemeIcons.iconFromName(modelData.icon, "application-x-executable") : ""
|
||||
visible: modelData.icon && source !== ""
|
||||
asynchronous: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback text if no icon and no image
|
||||
NText {
|
||||
anchors.centerIn: parent
|
||||
visible: !imagePreview.visible && !iconLoader.visible
|
||||
text: modelData.name ? modelData.name.charAt(0).toUpperCase() : "?"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
|
||||
// Image type indicator overlay
|
||||
// Icon badge or Image preview
|
||||
Rectangle {
|
||||
visible: modelData.isImage && imagePreview.visible
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 2 * scaling
|
||||
width: formatLabel.width + 6 * scaling
|
||||
height: formatLabel.height + 2 * scaling
|
||||
Layout.preferredWidth: badgeSize
|
||||
Layout.preferredHeight: badgeSize
|
||||
radius: Style.radiusM * scaling
|
||||
color: Color.mSurfaceVariant
|
||||
clip: true
|
||||
|
||||
NText {
|
||||
id: formatLabel
|
||||
anchors.centerIn: parent
|
||||
text: {
|
||||
if (!modelData.isImage)
|
||||
return ""
|
||||
const desc = modelData.description || ""
|
||||
const parts = desc.split(" • ")
|
||||
return parts[0] || "IMG"
|
||||
// Image preview for clipboard images
|
||||
NImageRounded {
|
||||
id: imagePreview
|
||||
anchors.fill: parent
|
||||
visible: modelData.isImage
|
||||
imageRadius: Style.radiusM * scaling
|
||||
|
||||
// This property creates a dependency on the service's revision counter
|
||||
readonly property int _rev: ClipboardService.revision
|
||||
|
||||
// Fetches from the service's cache.
|
||||
// The dependency on `_rev` ensures this binding is re-evaluated when the cache is updated.
|
||||
imagePath: {
|
||||
_rev
|
||||
return ClipboardService.getImageData(modelData.clipboardId) || ""
|
||||
}
|
||||
|
||||
// Loading indicator
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: parent.status === Image.Loading
|
||||
color: Color.mSurfaceVariant
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
running: true
|
||||
width: Style.baseWidgetSize * 0.5 * scaling
|
||||
height: width
|
||||
}
|
||||
}
|
||||
|
||||
// Error fallback
|
||||
onStatusChanged: status => {
|
||||
if (status === Image.Error) {
|
||||
iconLoader.visible = true
|
||||
imagePreview.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Icon fallback
|
||||
Loader {
|
||||
id: iconLoader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginXS * scaling
|
||||
|
||||
visible: !modelData.isImage || imagePreview.status === Image.Error
|
||||
active: visible
|
||||
|
||||
sourceComponent: Component {
|
||||
IconImage {
|
||||
anchors.fill: parent
|
||||
source: modelData.icon ? ThemeIcons.iconFromName(modelData.icon, "application-x-executable") : ""
|
||||
visible: modelData.icon && source !== ""
|
||||
asynchronous: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback text if no icon and no image
|
||||
NText {
|
||||
anchors.centerIn: parent
|
||||
visible: !imagePreview.visible && !iconLoader.visible
|
||||
text: modelData.name ? modelData.name.charAt(0).toUpperCase() : "?"
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
|
||||
// Image type indicator overlay
|
||||
Rectangle {
|
||||
visible: modelData.isImage && imagePreview.visible
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.margins: 2 * scaling
|
||||
width: formatLabel.width + 6 * scaling
|
||||
height: formatLabel.height + 2 * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
color: Color.mSurfaceVariant
|
||||
|
||||
NText {
|
||||
id: formatLabel
|
||||
anchors.centerIn: parent
|
||||
text: {
|
||||
if (!modelData.isImage)
|
||||
return ""
|
||||
const desc = modelData.description || ""
|
||||
const parts = desc.split(" • ")
|
||||
return parts[0] || "IMG"
|
||||
}
|
||||
pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
font.pointSize: Style.fontSizeXXS * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text content
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0 * scaling
|
||||
|
||||
NText {
|
||||
text: modelData.name || "Unknown"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurface
|
||||
elide: Text.ElideRight
|
||||
// Text content
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0 * scaling
|
||||
|
||||
NText {
|
||||
text: modelData.name || "Unknown"
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurface
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NText {
|
||||
text: modelData.description || ""
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
visible: text !== ""
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: modelData.description || ""
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
visible: text !== ""
|
||||
// Pin/Unpin action icon button
|
||||
NIconButton {
|
||||
visible: !!entry.appId && !modelData.isImage && entry.isSelected && (Settings.data.dock.monitors && Settings.data.dock.monitors.length > 0)
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
icon: entry.isPinned(entry.appId) ? "unpin" : "pin"
|
||||
tooltipText: entry.isPinned(entry.appId) ? I18n.tr("launcher.unpin") : I18n.tr("launcher.pin")
|
||||
onClicked: entry.togglePin(entry.appId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -469,12 +508,17 @@ NPanel {
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
selectedIndex = index
|
||||
ui.activate()
|
||||
}
|
||||
onClicked: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
selectedIndex = index
|
||||
ui.activate()
|
||||
mouse.accepted = true
|
||||
}
|
||||
}
|
||||
acceptedButtons: Qt.LeftButton
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,7 +536,7 @@ NPanel {
|
||||
const prefix = activePlugin?.name ? `${activePlugin.name}: ` : ""
|
||||
return prefix + `${results.length} result${results.length !== 1 ? 's' : ''}`
|
||||
}
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignCenter
|
||||
}
|
||||
|
||||
@@ -69,9 +69,15 @@ Item {
|
||||
|
||||
if (!query || query.trim() === "") {
|
||||
// Return all apps, optionally sorted by usage
|
||||
const favoriteApps = Settings.data.appLauncher.favoriteApps || []
|
||||
let sorted
|
||||
if (Settings.data.appLauncher.sortByMostUsed) {
|
||||
sorted = entries.slice().sort((a, b) => {
|
||||
// Favorites first
|
||||
const aFav = favoriteApps.includes(getAppKey(a))
|
||||
const bFav = favoriteApps.includes(getAppKey(b))
|
||||
if (aFav !== bFav)
|
||||
return aFav ? -1 : 1
|
||||
const ua = getUsageCount(a)
|
||||
const ub = getUsageCount(b)
|
||||
if (ub !== ua)
|
||||
@@ -79,7 +85,13 @@ Item {
|
||||
return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase())
|
||||
})
|
||||
} else {
|
||||
sorted = entries.slice().sort((a, b) => (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()))
|
||||
sorted = entries.slice().sort((a, b) => {
|
||||
const aFav = favoriteApps.includes(getAppKey(a))
|
||||
const bFav = favoriteApps.includes(getAppKey(b))
|
||||
if (aFav !== bFav)
|
||||
return aFav ? -1 : 1
|
||||
return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase())
|
||||
})
|
||||
}
|
||||
return sorted.map(app => createResultEntry(app))
|
||||
}
|
||||
@@ -92,7 +104,18 @@ Item {
|
||||
"limit": 20
|
||||
})
|
||||
|
||||
return fuzzyResults.map(result => createResultEntry(result.obj))
|
||||
// Sort favorites first within fuzzy results while preserving fuzzysort order otherwise
|
||||
const favoriteApps = Settings.data.appLauncher.favoriteApps || []
|
||||
const fav = []
|
||||
const nonFav = []
|
||||
for (const r of fuzzyResults) {
|
||||
const app = r.obj
|
||||
if (favoriteApps.includes(getAppKey(app)))
|
||||
fav.push(r)
|
||||
else
|
||||
nonFav.push(r)
|
||||
}
|
||||
return fav.concat(nonFav).map(result => createResultEntry(result.obj))
|
||||
} else {
|
||||
// Fallback to simple search
|
||||
const searchTerm = query.toLowerCase()
|
||||
@@ -118,6 +141,7 @@ Item {
|
||||
|
||||
function createResultEntry(app) {
|
||||
return {
|
||||
"appId": getAppKey(app),
|
||||
"name": app.name || "Unknown",
|
||||
"description": app.genericName || app.comment || "",
|
||||
"icon": app.icon || "application-x-executable",
|
||||
@@ -137,10 +161,20 @@ Item {
|
||||
Quickshell.execDetached(["app2unit", "--", app.id + ".desktop"])
|
||||
else
|
||||
Quickshell.execDetached(["app2unit", "--"].concat(app.command))
|
||||
} else if (app.execute) {
|
||||
app.execute()
|
||||
} else {
|
||||
Logger.log("ApplicationsPlugin", `Could not launch: ${app.name}`)
|
||||
// Fallback logic when app2unit is not used
|
||||
if (app.runInTerminal) {
|
||||
// If app.execute() fails for terminal apps, we handle it manually.
|
||||
Logger.log("ApplicationsPlugin", "Executing terminal app manually: " + app.name)
|
||||
const terminal = Settings.data.appLauncher.terminalCommand.split(" ")
|
||||
const command = terminal.concat(app.command)
|
||||
Quickshell.execDetached(command)
|
||||
} else if (app.execute) {
|
||||
// Default execution for GUI apps
|
||||
app.execute()
|
||||
} else {
|
||||
Logger.log("ApplicationsPlugin", `Could not launch: ${app.name}. No valid launch method.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ Loader {
|
||||
}
|
||||
|
||||
function formatTime() {
|
||||
return Settings.data.location.use12hourFormat ? Qt.formatDateTime(new Date(), "h:mm A") : Qt.formatDateTime(new Date(), "HH:mm")
|
||||
return Settings.data.location.use12hourFormat ? Qt.locale().toString(new Date(), "h:mm A") : Qt.locale().toString(new Date(), "HH:mm")
|
||||
}
|
||||
|
||||
function formatDate() {
|
||||
// For full text date, day is always before month, so we use this format for everybody: Wednesday, September 17.
|
||||
return Qt.formatDateTime(new Date(), "dddd, MMMM d")
|
||||
return Qt.locale().toString(new Date(), "dddd, MMMM d")
|
||||
}
|
||||
|
||||
function scheduleUnloadAfterUnlock() {
|
||||
@@ -147,9 +147,8 @@ Loader {
|
||||
NText {
|
||||
id: timeText
|
||||
text: formatTime()
|
||||
font.family: Settings.data.ui.fontBillboard
|
||||
// Smaller time display when using longer 12 hour format
|
||||
font.pointSize: Settings.data.location.use12hourFormat ? Style.fontSizeXXXL * 4 * scaling : Style.fontSizeXXXL * 5 * scaling
|
||||
pointSize: Settings.data.location.use12hourFormat ? Style.fontSizeXXXL * 4 * scaling : Style.fontSizeXXXL * 5 * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
font.letterSpacing: -2 * scaling
|
||||
color: Color.mOnSurface
|
||||
@@ -174,8 +173,7 @@ Loader {
|
||||
NText {
|
||||
id: dateText
|
||||
text: formatDate()
|
||||
font.family: Settings.data.ui.fontBillboard
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
font.weight: Font.Light
|
||||
color: Color.mOnSurface
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@@ -385,8 +383,8 @@ Loader {
|
||||
NText {
|
||||
text: I18n.tr("lock-screen.secure-terminal")
|
||||
color: Color.mOnSurface
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -396,13 +394,13 @@ Loader {
|
||||
NText {
|
||||
text: keyboardLayout.currentLayout
|
||||
color: Color.mOnSurface
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
NIcon {
|
||||
icon: "keyboard"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurface
|
||||
}
|
||||
}
|
||||
@@ -412,15 +410,15 @@ Loader {
|
||||
visible: batteryIndicator.batteryVisible
|
||||
NIcon {
|
||||
icon: BatteryService.getIcon(batteryIndicator.percent, batteryIndicator.charging, batteryIndicator.isReady)
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: batteryIndicator.charging ? Color.mPrimary : Color.mOnSurface
|
||||
rotation: -90
|
||||
}
|
||||
NText {
|
||||
text: Math.round(batteryIndicator.percent) + "%"
|
||||
color: Color.mOnSurface
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
}
|
||||
@@ -443,8 +441,8 @@ Loader {
|
||||
NText {
|
||||
text: Quickshell.env("USER") + "@noctalia:~$"
|
||||
color: Color.mPrimary
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
|
||||
@@ -452,8 +450,8 @@ Loader {
|
||||
id: welcomeText
|
||||
text: ""
|
||||
color: Color.mOnSurface
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
property int currentIndex: 0
|
||||
property string fullText: I18n.tr("system.welcome-back", {
|
||||
"user": Quickshell.env("USER")
|
||||
@@ -482,16 +480,16 @@ Loader {
|
||||
NText {
|
||||
text: Quickshell.env("USER") + "@noctalia:~$"
|
||||
color: Color.mPrimary
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("lock-screen.unlock-command")
|
||||
color: Color.mOnSurface
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,8 +500,8 @@ Loader {
|
||||
NText {
|
||||
text: I18n.tr("lock-screen.password")
|
||||
color: Color.mPrimary
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
|
||||
@@ -545,8 +543,8 @@ Loader {
|
||||
id: asterisksText
|
||||
text: "*".repeat(passwordInput.text.length)
|
||||
color: Color.mOnSurface
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
visible: passwordInput.activeFocus && !lockContext.unlockInProgress
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -612,8 +610,7 @@ Loader {
|
||||
return Color.mError
|
||||
return Color.transparent
|
||||
}
|
||||
font.family: "DejaVu Sans Mono"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
@@ -647,8 +644,8 @@ Loader {
|
||||
anchors.centerIn: parent
|
||||
text: lockContext.unlockInProgress ? "EXECUTING" : "EXECUTE"
|
||||
color: executeButtonArea.containsMouse ? Color.mOnPrimary : Color.mPrimary
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
}
|
||||
|
||||
@@ -767,8 +764,8 @@ Loader {
|
||||
|
||||
text: messages[index % messages.length]
|
||||
color: Color.mError
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
|
||||
x: baseX
|
||||
@@ -885,7 +882,7 @@ Loader {
|
||||
id: iconPower
|
||||
anchors.centerIn: parent
|
||||
icon: "shutdown"
|
||||
font.pointSize: Style.fontSizeXXXL * scaling
|
||||
pointSize: Style.fontSizeXXXL * scaling
|
||||
color: powerButtonArea.containsMouse ? Color.mOnError : Color.mError
|
||||
}
|
||||
|
||||
@@ -894,7 +891,7 @@ Loader {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Style.marginM * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
radius: Style.radiusS * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
@@ -905,7 +902,8 @@ Loader {
|
||||
anchors.margins: Style.marginM * scaling
|
||||
anchors.fill: parent
|
||||
text: I18n.tr("lock-screen.shut-down")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
@@ -936,7 +934,7 @@ Loader {
|
||||
id: iconReboot
|
||||
anchors.centerIn: parent
|
||||
icon: "reboot"
|
||||
font.pointSize: Style.fontSizeXXXL * scaling
|
||||
pointSize: Style.fontSizeXXXL * scaling
|
||||
color: restartButtonArea.containsMouse ? Color.mOnPrimary : Color.mPrimary
|
||||
}
|
||||
|
||||
@@ -945,7 +943,7 @@ Loader {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Style.marginM * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
radius: Style.radiusS * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
@@ -956,7 +954,8 @@ Loader {
|
||||
anchors.margins: Style.marginM * scaling
|
||||
anchors.fill: parent
|
||||
text: I18n.tr("lock-screen.restart")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
@@ -988,7 +987,7 @@ Loader {
|
||||
id: iconSuspend
|
||||
anchors.centerIn: parent
|
||||
icon: "suspend"
|
||||
font.pointSize: Style.fontSizeXXXL * scaling
|
||||
pointSize: Style.fontSizeXXXL * scaling
|
||||
color: suspendButtonArea.containsMouse ? Color.mOnSecondary : Color.mSecondary
|
||||
}
|
||||
|
||||
@@ -997,7 +996,7 @@ Loader {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: Style.marginM * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
radius: Style.radiusS * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
@@ -1008,7 +1007,8 @@ Loader {
|
||||
anchors.margins: Style.marginM * scaling
|
||||
anchors.fill: parent
|
||||
text: I18n.tr("lock-screen.suspend")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ Variants {
|
||||
property ListModel notificationModel: NotificationService.activeList
|
||||
|
||||
// If no notification display activated in settings, then show them all
|
||||
active: Settings.isLoaded && modelData && (Settings.data.notifications.monitors.includes(modelData.name) || (Settings.data.notifications.monitors.length === 0))
|
||||
active: modelData && (Settings.data.notifications.monitors.includes(modelData.name) || (Settings.data.notifications.monitors.length === 0))
|
||||
|
||||
Connections {
|
||||
target: ScalingService
|
||||
@@ -37,11 +37,11 @@ Variants {
|
||||
screen: modelData
|
||||
|
||||
WlrLayershell.namespace: "noctalia-notifications"
|
||||
WlrLayershell.layer: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.alwaysOnTop) ? WlrLayer.Overlay : WlrLayer.Top
|
||||
WlrLayershell.layer: (Settings.data.notifications && Settings.data.notifications.alwaysOnTop) ? WlrLayer.Overlay : WlrLayer.Top
|
||||
|
||||
color: Color.transparent
|
||||
|
||||
readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right"
|
||||
readonly property string location: (Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right"
|
||||
readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top")
|
||||
readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom")
|
||||
readonly property bool isLeft: location.indexOf("_left") >= 0
|
||||
@@ -162,7 +162,7 @@ Variants {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 2 * scaling
|
||||
color: "transparent"
|
||||
color: Color.transparent
|
||||
|
||||
property real availableWidth: parent.width - (2 * parent.radius)
|
||||
|
||||
@@ -307,7 +307,7 @@ Variants {
|
||||
NText {
|
||||
text: `${model.appName || I18n.tr("system.unknown-app")} · ${Time.formatRelativeTime(model.timestamp)}`
|
||||
color: Color.mSecondary
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -317,7 +317,7 @@ Variants {
|
||||
|
||||
NText {
|
||||
text: model.summary || I18n.tr("general.no-summary")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
textFormat: Text.PlainText
|
||||
@@ -330,7 +330,7 @@ Variants {
|
||||
|
||||
NText {
|
||||
text: model.body || ""
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurface
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
|
||||
@@ -32,13 +32,13 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "bell"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("notifications.panel.title")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
@@ -88,21 +88,21 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "bell-off"
|
||||
font.pointSize: 64 * scaling
|
||||
pointSize: 64 * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("notifications.panel.no-notifications")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("notifications.panel.description")
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
@@ -199,13 +199,13 @@ NPanel {
|
||||
|
||||
NText {
|
||||
text: model.appName || "Unknown App"
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mSecondary
|
||||
}
|
||||
|
||||
NText {
|
||||
text: Time.formatRelativeTime(model.timestamp)
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mSecondary
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ NPanel {
|
||||
// Summary
|
||||
NText {
|
||||
text: model.summary || I18n.tr("general.no-summary")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Font.Medium
|
||||
color: Color.mOnSurface
|
||||
textFormat: Text.PlainText
|
||||
@@ -230,7 +230,7 @@ NPanel {
|
||||
// Body
|
||||
NText {
|
||||
text: model.body || ""
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
@@ -22,7 +22,7 @@ Variants {
|
||||
property ListModel notificationModel: NotificationService.activeList
|
||||
|
||||
// If no notification display activated in settings, then show them all
|
||||
property bool canShowOnThisScreen: Settings.isLoaded && modelData && (Settings.data.osd.monitors.includes(modelData.name) || (Settings.data.osd.monitors.length === 0))
|
||||
property bool canShowOnThisScreen: modelData && (Settings.data.osd.monitors.includes(modelData.name) || (Settings.data.osd.monitors.length === 0))
|
||||
|
||||
// Loader is only active when actually showing something
|
||||
active: false
|
||||
@@ -104,7 +104,7 @@ Variants {
|
||||
id: panel
|
||||
screen: modelData
|
||||
|
||||
readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.osd && Settings.data.osd.location) ? Settings.data.osd.location : "top_right"
|
||||
readonly property string location: (Settings.data.osd && Settings.data.osd.location) ? Settings.data.osd.location : "top_right"
|
||||
readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top")
|
||||
readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom")
|
||||
readonly property bool isLeft: (location.indexOf("_left") >= 0) || (location === "left")
|
||||
@@ -243,7 +243,7 @@ Variants {
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -253,8 +253,8 @@ Variants {
|
||||
NIcon {
|
||||
icon: root.getIcon()
|
||||
color: root.getIconColor()
|
||||
font.pointSize: Style.fontSizeXL * root.scaling
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
pointSize: Style.fontSizeXL * root.scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
@@ -266,11 +266,11 @@ Variants {
|
||||
|
||||
// Progress bar with calculated width
|
||||
Rectangle {
|
||||
width: Math.round(220 * root.scaling)
|
||||
Layout.preferredWidth: Math.round(220 * root.scaling)
|
||||
height: panel.barThickness
|
||||
radius: Math.round(panel.barThickness / 2)
|
||||
color: Color.mSurfaceVariant
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
@@ -299,12 +299,12 @@ Variants {
|
||||
NText {
|
||||
text: root.getDisplayPercentage()
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeS * root.scaling
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
pointSize: Style.fontSizeS * root.scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
width: Math.round(50 * root.scaling)
|
||||
Layout.preferredWidth: Math.round(50 * root.scaling)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,8 +340,8 @@ Variants {
|
||||
id: percentText
|
||||
text: root.getDisplayPercentage()
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeS * root.scaling
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
pointSize: Style.fontSizeS * root.scaling
|
||||
family: Settings.data.ui.fontFixed
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@@ -389,7 +389,7 @@ Variants {
|
||||
NIcon {
|
||||
icon: root.getIcon()
|
||||
color: root.getIconColor()
|
||||
font.pointSize: Style.fontSizeXL * root.scaling
|
||||
pointSize: Style.fontSizeXL * root.scaling
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
|
||||
Layout.bottomMargin: vMargin + Math.round(Style.marginM * root.scaling) + balanceDelta
|
||||
Behavior on color {
|
||||
@@ -410,10 +410,10 @@ Variants {
|
||||
// Make visible and animate in
|
||||
osdItem.visible = true
|
||||
// Use Qt.callLater to ensure the visible change is processed before animation
|
||||
Qt.callLater(function () {
|
||||
osdItem.opacity = 1
|
||||
osdItem.scale = 1.0
|
||||
})
|
||||
Qt.callLater(() => {
|
||||
osdItem.opacity = 1
|
||||
osdItem.scale = 1.0
|
||||
})
|
||||
|
||||
// Start the auto-hide timer
|
||||
hideTimer.start()
|
||||
@@ -524,11 +524,11 @@ Variants {
|
||||
root.item.showOSD()
|
||||
} else {
|
||||
// If item not ready yet, wait for it
|
||||
Qt.callLater(function () {
|
||||
if (root.item) {
|
||||
root.item.showOSD()
|
||||
}
|
||||
})
|
||||
Qt.callLater(() => {
|
||||
if (root.item) {
|
||||
root.item.showOSD()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ NPanel {
|
||||
id: root
|
||||
|
||||
preferredWidth: 440
|
||||
preferredHeight: 410
|
||||
preferredHeight: 480
|
||||
panelAnchorHorizontalCenter: true
|
||||
panelAnchorVerticalCenter: true
|
||||
panelKeyboardFocus: true
|
||||
@@ -32,26 +32,31 @@ NPanel {
|
||||
"icon": "lock",
|
||||
"title": I18n.tr("session-menu.lock"),
|
||||
"subtitle": I18n.tr("session-menu.lock-subtitle")
|
||||
}, {
|
||||
"action": "lockAndSuspend",
|
||||
"icon": "lock-pause",
|
||||
"title": I18n.tr("session-menu.lock-and-suspend"),
|
||||
"subtitle": I18n.tr("session-menu.lock-and-suspend-subtitle")
|
||||
}, {
|
||||
"action": "suspend",
|
||||
"icon": "suspend",
|
||||
"title": I18n.tr("session-menu.suspend"),
|
||||
"subtitle": "Put the system to sleep"
|
||||
"subtitle": I18n.tr("session-menu.suspend-subtitle")
|
||||
}, {
|
||||
"action": "reboot",
|
||||
"icon": "reboot",
|
||||
"title": I18n.tr("session-menu.reboot"),
|
||||
"subtitle": "Restart the system"
|
||||
"subtitle": I18n.tr("session-menu.reboot-subtitle")
|
||||
}, {
|
||||
"action": "logout",
|
||||
"icon": "logout",
|
||||
"title": I18n.tr("session-menu.logout"),
|
||||
"subtitle": I18n.tr("session-menu.end-subtitle")
|
||||
"subtitle": I18n.tr("session-menu.logout-subtitle")
|
||||
}, {
|
||||
"action": "shutdown",
|
||||
"icon": "shutdown",
|
||||
"title": I18n.tr("session-menu.shutdown"),
|
||||
"subtitle": "Turn off the system",
|
||||
"subtitle": I18n.tr("session-menu.shutdown-subtitle"),
|
||||
"isShutdown": true
|
||||
}]
|
||||
|
||||
@@ -97,6 +102,9 @@ NPanel {
|
||||
lockScreen.active = true
|
||||
}
|
||||
break
|
||||
case "lockAndSuspend":
|
||||
CompositorService.lockAndSuspend()
|
||||
break
|
||||
case "suspend":
|
||||
CompositorService.suspend()
|
||||
break
|
||||
@@ -268,7 +276,7 @@ NPanel {
|
||||
"seconds": Math.ceil(timeRemaining / 1000)
|
||||
}) : I18n.tr("session-menu.title")
|
||||
font.weight: Style.fontWeightBold
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: timerActive ? Color.mPrimary : Color.mOnSurface
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -377,7 +385,7 @@ NPanel {
|
||||
return Color.mOnTertiary
|
||||
return Color.mOnSurface
|
||||
}
|
||||
font.pointSize: Style.fontSizeXXXL * scaling
|
||||
pointSize: Style.fontSizeXXXL * scaling
|
||||
width: Style.baseWidgetSize * 0.6 * scaling
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -401,7 +409,7 @@ NPanel {
|
||||
NText {
|
||||
text: buttonRoot.title
|
||||
font.weight: Style.fontWeightMedium
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: {
|
||||
if (buttonRoot.pending)
|
||||
return Color.mPrimary
|
||||
@@ -426,7 +434,7 @@ NPanel {
|
||||
}
|
||||
return buttonRoot.subtitle
|
||||
}
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: {
|
||||
if (buttonRoot.pending)
|
||||
return Color.mPrimary
|
||||
@@ -456,7 +464,7 @@ NPanel {
|
||||
NText {
|
||||
anchors.centerIn: parent
|
||||
text: Math.ceil(timeRemaining / 1000)
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ NBox {
|
||||
|
||||
NText {
|
||||
text: sectionName + " Section"
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@@ -225,7 +225,7 @@ NBox {
|
||||
|
||||
NText {
|
||||
text: modelData.id
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: root.getWidgetColor(modelData)[1]
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
@@ -312,10 +312,10 @@ NBox {
|
||||
z: 2000
|
||||
clip: false // Ensure ghost isn't clipped
|
||||
|
||||
Text {
|
||||
NText {
|
||||
id: ghostText
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnPrimary
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ Popup {
|
||||
text: I18n.tr("system.widget-settings-title", {
|
||||
"widget": widgetSettings.widgetId
|
||||
})
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mPrimary
|
||||
Layout.fillWidth: true
|
||||
@@ -69,6 +69,7 @@ Popup {
|
||||
|
||||
NIconButton {
|
||||
icon: "close"
|
||||
tooltipText: "Close"
|
||||
onClicked: widgetSettings.close()
|
||||
}
|
||||
}
|
||||
@@ -132,7 +133,8 @@ Popup {
|
||||
"Spacer": "WidgetSettings/SpacerSettings.qml",
|
||||
"SystemMonitor": "WidgetSettings/SystemMonitorSettings.qml",
|
||||
"Volume": "WidgetSettings/VolumeSettings.qml",
|
||||
"Workspace": "WidgetSettings/WorkspaceSettings.qml"
|
||||
"Workspace": "WidgetSettings/WorkspaceSettings.qml",
|
||||
"Taskbar": "WidgetSettings/TaskbarSettings.qml"
|
||||
}
|
||||
|
||||
const source = widgetSettingsMap[widgetId]
|
||||
|
||||
@@ -23,26 +23,28 @@ ColumnLayout {
|
||||
settings.autoHide = valueAutoHide
|
||||
settings.showIcon = valueShowIcon
|
||||
settings.scrollingMode = valueScrollingMode
|
||||
console.log(JSON.stringify(settings))
|
||||
return settings
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.active-window.auto-hide")
|
||||
label: I18n.tr("bar.widget-settings.active-window.auto-hide.label")
|
||||
description: I18n.tr("bar.widget-settings.active-window.auto-hide.description")
|
||||
checked: root.valueAutoHide
|
||||
onToggled: checked => root.valueAutoHide = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.active-window.show-app-icon")
|
||||
label: I18n.tr("bar.widget-settings.active-window.show-app-icon.label")
|
||||
description: I18n.tr("bar.widget-settings.active-window.show-app-icon.description")
|
||||
checked: root.valueShowIcon
|
||||
onToggled: checked => root.valueShowIcon = checked
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
label: I18n.tr("bar.widget-settings.active-window.scrolling-mode")
|
||||
label: I18n.tr("bar.widget-settings.active-window.scrolling-mode.label")
|
||||
description: I18n.tr("bar.widget-settings.active-window.scrolling-mode.description")
|
||||
model: [{
|
||||
"key": "always",
|
||||
"name": I18n.tr("options.scrolling-modes.always")
|
||||
|
||||
@@ -16,7 +16,8 @@ ColumnLayout {
|
||||
|
||||
// Local state
|
||||
property bool valueUsePrimaryColor: widgetData.usePrimaryColor !== undefined ? widgetData.usePrimaryColor : widgetMetadata.usePrimaryColor
|
||||
property bool valueUseMonospacedFont: widgetData.useMonospacedFont !== undefined ? widgetData.useMonospacedFont : widgetMetadata.useMonospacedFont
|
||||
property bool valueUseCustomFont: widgetData.useCustomFont !== undefined ? widgetData.useCustomFont : widgetMetadata.useCustomFont
|
||||
property string valueCustomFont: widgetData.customFont !== undefined ? widgetData.customFont : widgetMetadata.customFont
|
||||
property string valueFormatHorizontal: widgetData.formatHorizontal !== undefined ? widgetData.formatHorizontal : widgetMetadata.formatHorizontal
|
||||
property string valueFormatVertical: widgetData.formatVertical !== undefined ? widgetData.formatVertical : widgetMetadata.formatVertical
|
||||
|
||||
@@ -29,7 +30,8 @@ ColumnLayout {
|
||||
function saveSettings() {
|
||||
var settings = Object.assign({}, widgetData || {})
|
||||
settings.usePrimaryColor = valueUsePrimaryColor
|
||||
settings.useMonospacedFont = valueUseMonospacedFont
|
||||
settings.useCustomFont = valueUseCustomFont
|
||||
settings.customFont = valueCustomFont
|
||||
settings.formatHorizontal = valueFormatHorizontal.trim()
|
||||
settings.formatVertical = valueFormatVertical.trim()
|
||||
return settings
|
||||
@@ -72,10 +74,26 @@ ColumnLayout {
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.clock.use-monospaced-font.label")
|
||||
description: I18n.tr("bar.widget-settings.clock.use-monospaced-font.description")
|
||||
checked: valueUseMonospacedFont
|
||||
onToggled: checked => valueUseMonospacedFont = checked
|
||||
label: I18n.tr("bar.widget-settings.clock.use-custom-font.label")
|
||||
description: I18n.tr("bar.widget-settings.clock.use-custom-font.description")
|
||||
checked: valueUseCustomFont
|
||||
onToggled: checked => valueUseCustomFont = checked
|
||||
}
|
||||
|
||||
NSearchableComboBox {
|
||||
Layout.fillWidth: true
|
||||
visible: valueUseCustomFont
|
||||
label: I18n.tr("bar.widget-settings.clock.custom-font.label")
|
||||
description: I18n.tr("bar.widget-settings.clock.custom-font.description")
|
||||
model: FontService.availableFonts
|
||||
currentKey: valueCustomFont
|
||||
placeholder: I18n.tr("bar.widget-settings.clock.custom-font.placeholder")
|
||||
searchPlaceholder: I18n.tr("bar.widget-settings.clock.custom-font.search-placeholder")
|
||||
popupHeight: 420 * scaling
|
||||
minimumWidth: 300 * scaling
|
||||
onSelected: function (key) {
|
||||
valueCustomFont = key
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
@@ -182,12 +200,12 @@ ColumnLayout {
|
||||
// Horizontal
|
||||
Repeater {
|
||||
Layout.topMargin: Style.marginM * scaling
|
||||
model: Qt.formatDateTime(now, valueFormatHorizontal.trim()).split("\\n")
|
||||
model: Qt.locale().toString(now, valueFormatHorizontal.trim()).split("\\n")
|
||||
delegate: NText {
|
||||
visible: text !== ""
|
||||
text: modelData
|
||||
font.family: valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
family: valueUseCustomFont && valueCustomFont ? valueCustomFont : (valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault)
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: valueUsePrimaryColor ? Color.mPrimary : Color.mOnSurface
|
||||
wrapMode: Text.WordWrap
|
||||
@@ -213,12 +231,12 @@ ColumnLayout {
|
||||
|
||||
Repeater {
|
||||
Layout.topMargin: Style.marginM * scaling
|
||||
model: Qt.formatDateTime(now, valueFormatVertical.trim()).split(" ")
|
||||
model: Qt.locale().toString(now, valueFormatVertical.trim()).split(" ")
|
||||
delegate: NText {
|
||||
visible: text !== ""
|
||||
text: modelData
|
||||
font.family: valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
family: valueUseCustomFont && valueCustomFont ? valueCustomFont : (valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault)
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: valueUsePrimaryColor ? Color.mPrimary : Color.mOnSurface
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
@@ -28,7 +28,8 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("bar.widget-settings.control-center.use-distro-logo")
|
||||
label: I18n.tr("bar.widget-settings.control-center.use-distro-logo.label")
|
||||
description: I18n.tr("bar.widget-settings.control-center.use-distro-logo.description")
|
||||
checked: valueUseDistroLogo
|
||||
onToggled: {
|
||||
valueUseDistroLogo = checked
|
||||
@@ -58,7 +59,7 @@ ColumnLayout {
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: valueIcon
|
||||
font.pointSize: Style.fontSizeXXL * 1.5 * scaling
|
||||
pointSize: Style.fontSizeXXL * 1.5 * scaling
|
||||
visible: valueIcon !== "" && valueCustomIconPath === ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ ColumnLayout {
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: valueIcon
|
||||
font.pointSize: Style.fontSizeXL * scaling
|
||||
pointSize: Style.fontSizeXL * scaling
|
||||
visible: valueIcon !== ""
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ ColumnLayout {
|
||||
NTextInput {
|
||||
id: leftClickExecInput
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.custom-button.left-click")
|
||||
label: I18n.tr("bar.widget-settings.custom-button.left-click.label")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.left-click.description")
|
||||
placeholderText: I18n.tr("placeholders.enter-command")
|
||||
text: widgetData?.leftClickExec || widgetMetadata.leftClickExec
|
||||
}
|
||||
@@ -66,7 +67,8 @@ ColumnLayout {
|
||||
NTextInput {
|
||||
id: rightClickExecInput
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.custom-button.right-click")
|
||||
label: I18n.tr("bar.widget-settings.custom-button.right-click.label")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.right-click.description")
|
||||
placeholderText: I18n.tr("placeholders.enter-command")
|
||||
text: widgetData?.rightClickExec || widgetMetadata.rightClickExec
|
||||
}
|
||||
@@ -74,7 +76,8 @@ ColumnLayout {
|
||||
NTextInput {
|
||||
id: middleClickExecInput
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.custom-button.middle-click")
|
||||
label: I18n.tr("bar.widget-settings.custom-button.middle-click.label")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.middle-click.description")
|
||||
placeholderText: I18n.tr("placeholders.enter-command")
|
||||
text: widgetData.middleClickExec || widgetMetadata.middleClickExec
|
||||
}
|
||||
|
||||
@@ -32,26 +32,30 @@ ColumnLayout {
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.media-mini.auto-hide")
|
||||
label: I18n.tr("bar.widget-settings.media-mini.auto-hide.label")
|
||||
description: I18n.tr("bar.widget-settings.media-mini.auto-hide.description")
|
||||
checked: root.valueAutoHide
|
||||
onToggled: checked => root.valueAutoHide = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("bar.widget-settings.media-mini.show-album-art")
|
||||
label: I18n.tr("bar.widget-settings.media-mini.show-album-art.label")
|
||||
description: I18n.tr("bar.widget-settings.media-mini.show-album-art.description")
|
||||
checked: valueShowAlbumArt
|
||||
onToggled: checked => valueShowAlbumArt = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("bar.widget-settings.media-mini.show-visualizer")
|
||||
label: I18n.tr("bar.widget-settings.media-mini.show-visualizer.label")
|
||||
description: I18n.tr("bar.widget-settings.media-mini.show-visualizer.description")
|
||||
checked: valueShowVisualizer
|
||||
onToggled: checked => valueShowVisualizer = checked
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
visible: valueShowVisualizer
|
||||
label: I18n.tr("bar.widget-settings.media-mini.visualizer-type")
|
||||
label: I18n.tr("bar.widget-settings.media-mini.visualizer-type.label")
|
||||
description: I18n.tr("bar.widget-settings.media-mini.visualizer-type.description")
|
||||
model: [{
|
||||
"key": "linear",
|
||||
"name": I18n.tr("options.visualizer-types.linear")
|
||||
@@ -68,7 +72,8 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
NComboBox {
|
||||
label: I18n.tr("bar.widget-settings.media-mini.scrolling-mode")
|
||||
label: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.label")
|
||||
description: I18n.tr("bar.widget-settings.media-mini.scrolling-mode.description")
|
||||
model: [{
|
||||
"key": "always",
|
||||
"name": I18n.tr("options.scrolling-modes.always")
|
||||
|
||||
@@ -25,13 +25,15 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("bar.widget-settings.notification-history.show-unread-badge")
|
||||
label: I18n.tr("bar.widget-settings.notification-history.show-unread-badge.label")
|
||||
description: I18n.tr("bar.widget-settings.notification-history.show-unread-badge.description")
|
||||
checked: valueShowUnreadBadge
|
||||
onToggled: checked => valueShowUnreadBadge = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("bar.widget-settings.notification-history.hide-badge-when-zero")
|
||||
label: I18n.tr("bar.widget-settings.notification-history.hide-badge-when-zero.label")
|
||||
description: I18n.tr("bar.widget-settings.notification-history.hide-badge-when-zero.description")
|
||||
checked: valueHideWhenZero
|
||||
onToggled: checked => valueHideWhenZero = checked
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ ColumnLayout {
|
||||
NToggle {
|
||||
id: showCpuUsage
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.cpu-usage")
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.cpu-usage.label")
|
||||
description: I18n.tr("bar.widget-settings.system-monitor.cpu-usage.description")
|
||||
checked: valueShowCpuUsage
|
||||
onToggled: checked => valueShowCpuUsage = checked
|
||||
}
|
||||
@@ -43,7 +44,8 @@ ColumnLayout {
|
||||
NToggle {
|
||||
id: showCpuTemp
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.cpu-temperature")
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.cpu-temperature.label")
|
||||
description: I18n.tr("bar.widget-settings.system-monitor.cpu-temperature.description")
|
||||
checked: valueShowCpuTemp
|
||||
onToggled: checked => valueShowCpuTemp = checked
|
||||
}
|
||||
@@ -51,7 +53,8 @@ ColumnLayout {
|
||||
NToggle {
|
||||
id: showMemoryUsage
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.memory-usage")
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.memory-usage.label")
|
||||
description: I18n.tr("bar.widget-settings.system-monitor.memory-usage.description")
|
||||
checked: valueShowMemoryUsage
|
||||
onToggled: checked => valueShowMemoryUsage = checked
|
||||
}
|
||||
@@ -59,7 +62,8 @@ ColumnLayout {
|
||||
NToggle {
|
||||
id: showMemoryAsPercent
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.memory-percentage")
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.memory-percentage.label")
|
||||
description: I18n.tr("bar.widget-settings.system-monitor.memory-percentage.description")
|
||||
checked: valueShowMemoryAsPercent
|
||||
onToggled: checked => valueShowMemoryAsPercent = checked
|
||||
visible: valueShowMemoryUsage
|
||||
@@ -68,7 +72,8 @@ ColumnLayout {
|
||||
NToggle {
|
||||
id: showNetworkStats
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.network-traffic")
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.network-traffic.label")
|
||||
description: I18n.tr("bar.widget-settings.system-monitor.network-traffic.description")
|
||||
checked: valueShowNetworkStats
|
||||
onToggled: checked => valueShowNetworkStats = checked
|
||||
}
|
||||
@@ -76,7 +81,8 @@ ColumnLayout {
|
||||
NToggle {
|
||||
id: showDiskUsage
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.storage-usage")
|
||||
label: I18n.tr("bar.widget-settings.system-monitor.storage-usage.label")
|
||||
description: I18n.tr("bar.widget-settings.system-monitor.storage-usage.description")
|
||||
checked: valueShowDiskUsage
|
||||
onToggled: checked => valueShowDiskUsage = checked
|
||||
}
|
||||
|
||||
43
Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml
Normal file
43
Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml
Normal file
@@ -0,0 +1,43 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Widgets
|
||||
import qs.Services
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginM * scaling
|
||||
|
||||
// Properties to receive data from parent
|
||||
property var widgetData: null
|
||||
property var widgetMetadata: null
|
||||
|
||||
// Local state
|
||||
property bool valueOnlyActiveWorkspaces: widgetData.onlyActiveWorkspaces !== undefined ? widgetData.onlyActiveWorkspaces : widgetMetadata.onlyActiveWorkspaces
|
||||
property bool valueOnlySameOutput: widgetData.onlySameOutput !== undefined ? widgetData.onlySameOutput : widgetMetadata.onlySameOutput
|
||||
|
||||
function saveSettings() {
|
||||
var settings = Object.assign({}, widgetData || {})
|
||||
settings.onlySameOutput = valueOnlySameOutput
|
||||
settings.onlyActiveWorkspaces = valueOnlyActiveWorkspaces
|
||||
console.log(JSON.stringify(settings))
|
||||
return settings
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.taskbar.only-same-output.label")
|
||||
description: I18n.tr("bar.widget-settings.taskbar.only-same-output.description")
|
||||
checked: root.valueOnlySameOutput
|
||||
onToggled: checked => root.valueOnlySameOutput = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("bar.widget-settings.taskbar.only-active-workspaces.label")
|
||||
description: I18n.tr("bar.widget-settings.taskbar.only-active-workspaces.description")
|
||||
checked: root.valueOnlyActiveWorkspaces
|
||||
onToggled: checked => root.valueOnlyActiveWorkspaces = checked
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,8 @@ ColumnLayout {
|
||||
NComboBox {
|
||||
id: labelModeCombo
|
||||
|
||||
label: I18n.tr("bar.widget-settings.workspace.label-mode")
|
||||
label: I18n.tr("bar.widget-settings.workspace.label-mode.label")
|
||||
description: I18n.tr("bar.widget-settings.workspace.label-mode.description")
|
||||
model: [{
|
||||
"key": "none",
|
||||
"name": I18n.tr("options.workspace-labels.none")
|
||||
|
||||
@@ -396,14 +396,14 @@ NPanel {
|
||||
NIcon {
|
||||
icon: modelData.icon
|
||||
color: tabTextColor
|
||||
font.pointSize: Style.fontSizeXL * scaling
|
||||
pointSize: Style.fontSizeXL * scaling
|
||||
}
|
||||
|
||||
// Tab label
|
||||
NText {
|
||||
text: I18n.tr(modelData.label)
|
||||
color: tabTextColor
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@@ -456,13 +456,13 @@ NPanel {
|
||||
NIcon {
|
||||
icon: root.tabsModel[currentTabIndex]?.icon
|
||||
color: Color.mPrimary
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
}
|
||||
|
||||
// Main title
|
||||
NText {
|
||||
text: I18n.tr(root.tabsModel[currentTabIndex]?.label) || ""
|
||||
font.pointSize: Style.fontSizeXL * scaling
|
||||
pointSize: Style.fontSizeXL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mPrimary
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -91,14 +91,14 @@ ColumnLayout {
|
||||
|
||||
NIcon {
|
||||
icon: "download"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: updateArea.containsMouse ? Color.mSurface : Color.mPrimary
|
||||
}
|
||||
|
||||
NText {
|
||||
id: updateText
|
||||
text: I18n.tr("settings.about.noctalia.download-latest")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
color: updateArea.containsMouse ? Color.mSurface : Color.mPrimary
|
||||
}
|
||||
}
|
||||
@@ -200,7 +200,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: (modelData.contributions || 0) + " " + ((modelData.contributions || 0) === 1 ? "commit" : "commits")
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: contributorArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ ColumnLayout {
|
||||
// AudioService Devices
|
||||
ColumnLayout {
|
||||
spacing: Style.marginS * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: I18n.tr("settings.audio.devices.section.label")
|
||||
@@ -175,14 +176,15 @@ ColumnLayout {
|
||||
Repeater {
|
||||
model: AudioService.sinks
|
||||
NRadioButton {
|
||||
required property PwNode modelData
|
||||
ButtonGroup.group: sinks
|
||||
required property PwNode modelData
|
||||
text: modelData.description
|
||||
checked: AudioService.sink?.id === modelData.id
|
||||
onClicked: {
|
||||
AudioService.setAudioSink(modelData)
|
||||
localVolume = AudioService.volume
|
||||
}
|
||||
text: modelData.description
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,12 +206,14 @@ ColumnLayout {
|
||||
|
||||
Repeater {
|
||||
model: AudioService.sources
|
||||
//Layout.fillWidth: true
|
||||
NRadioButton {
|
||||
required property PwNode modelData
|
||||
ButtonGroup.group: sources
|
||||
required property PwNode modelData
|
||||
text: modelData.description
|
||||
checked: AudioService.source?.id === modelData.id
|
||||
onClicked: AudioService.setAudioSource(modelData)
|
||||
text: modelData.description
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,7 +309,7 @@ ColumnLayout {
|
||||
NText {
|
||||
text: modelData
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: Style.marginS * scaling
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.bar.appearance.margins.vertical")
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.bar.appearance.margins.horizontal")
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
|
||||
@@ -188,12 +188,14 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
visible: !Settings.data.colorSchemes.useWallpaperColors
|
||||
}
|
||||
|
||||
// Predefined Color Schemes
|
||||
ColumnLayout {
|
||||
spacing: Style.marginM * scaling
|
||||
Layout.fillWidth: true
|
||||
visible: !Settings.data.colorSchemes.useWallpaperColors
|
||||
|
||||
NHeader {
|
||||
label: I18n.tr("settings.color-scheme.predefined.section.label")
|
||||
@@ -259,7 +261,7 @@ ColumnLayout {
|
||||
var chunks = schemePath.replace(".json", "").split("/")
|
||||
return chunks[chunks.length - 1]
|
||||
}
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: getSchemeColor(modelData, "mOnSurface")
|
||||
Layout.fillWidth: true
|
||||
@@ -324,7 +326,7 @@ ColumnLayout {
|
||||
|
||||
NIcon {
|
||||
icon: "check"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSecondary
|
||||
anchors.centerIn: parent
|
||||
|
||||
@@ -126,7 +126,7 @@ ColumnLayout {
|
||||
|
||||
// Reset button container
|
||||
Item {
|
||||
Layout.preferredWidth: 40 * scaling
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
Layout.preferredHeight: 30 * scaling
|
||||
|
||||
NIconButton {
|
||||
@@ -168,13 +168,13 @@ ColumnLayout {
|
||||
|
||||
// Empty container to match scale row layout
|
||||
Item {
|
||||
Layout.preferredWidth: 40 * scaling
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
Layout.preferredHeight: 30 * scaling
|
||||
|
||||
// Method text positioned in the button area
|
||||
NText {
|
||||
text: brightnessMonitor ? brightnessMonitor.method : ""
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -186,22 +186,18 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Brightness Step Section
|
||||
ColumnLayout {
|
||||
spacing: Style.marginS * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NSpinBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("settings.display.monitors.brightness-step.label")
|
||||
description: I18n.tr("settings.display.monitors.brightness-step.description")
|
||||
minimum: 1
|
||||
maximum: 50
|
||||
value: Settings.data.brightness.brightnessStep
|
||||
stepSize: 1
|
||||
suffix: "%"
|
||||
onValueChanged: Settings.data.brightness.brightnessStep = value
|
||||
}
|
||||
// Brightness Step
|
||||
NSpinBox {
|
||||
Layout.fillWidth: true
|
||||
label: I18n.tr("settings.display.monitors.brightness-step.label")
|
||||
description: I18n.tr("settings.display.monitors.brightness-step.description")
|
||||
minimum: 1
|
||||
maximum: 50
|
||||
value: Settings.data.brightness.brightnessStep
|
||||
stepSize: 1
|
||||
suffix: "%"
|
||||
onValueChanged: Settings.data.brightness.brightnessStep = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +254,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.display.night-light.temperature.night")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
@@ -280,7 +276,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.display.night-light.temperature.day")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
@@ -327,7 +323,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.display.night-light.manual-schedule.sunrise")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
@@ -345,7 +341,7 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.display.night-light.manual-schedule.sunset")
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,13 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("settings.dock.monitors.only-same-output.label")
|
||||
description: I18n.tr("settings.dock.monitors.only-same-output.description")
|
||||
checked: Settings.data.dock.onlySameOutput
|
||||
onToggled: checked => Settings.data.dock.onlySameOutput = checked
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
|
||||
@@ -187,6 +187,7 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
@@ -236,25 +237,79 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
NSearchableComboBox {
|
||||
label: I18n.tr("settings.general.fonts.accent.label")
|
||||
description: I18n.tr("settings.general.fonts.accent.description")
|
||||
model: FontService.displayFonts
|
||||
currentKey: Settings.data.ui.fontBillboard
|
||||
placeholder: I18n.tr("settings.general.fonts.accent.placeholder")
|
||||
searchPlaceholder: I18n.tr("settings.general.fonts.accent.search-placeholder")
|
||||
popupHeight: 320 * scaling
|
||||
minimumWidth: 300 * scaling
|
||||
onSelected: function (key) {
|
||||
Settings.data.ui.fontBillboard = key
|
||||
ColumnLayout {
|
||||
NLabel {
|
||||
label: I18n.tr("settings.general.fonts.default.scale.label")
|
||||
description: I18n.tr("settings.general.fonts.default.scale.description")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
from: 0.75
|
||||
to: 1.25
|
||||
stepSize: 0.01
|
||||
value: Settings.data.ui.fontDefaultScale
|
||||
onMoved: value => Settings.data.ui.fontDefaultScale = value
|
||||
text: Math.floor(Settings.data.ui.fontDefaultScale * 100) + "%"
|
||||
}
|
||||
|
||||
// Reset button container
|
||||
Item {
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
Layout.preferredHeight: 30 * scaling
|
||||
|
||||
NIconButton {
|
||||
icon: "refresh"
|
||||
baseSize: Style.baseWidgetSize * 0.9
|
||||
tooltipText: I18n.tr("settings.general.fonts.reset-scaling")
|
||||
onClicked: Settings.data.ui.fontDefaultScale = 1.0
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
NLabel {
|
||||
label: I18n.tr("settings.general.fonts.monospace.scale.label")
|
||||
description: I18n.tr("settings.general.fonts.monospace.scale.description")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.fillWidth: true
|
||||
|
||||
NValueSlider {
|
||||
Layout.fillWidth: true
|
||||
from: 0.75
|
||||
to: 1.25
|
||||
stepSize: 0.01
|
||||
value: Settings.data.ui.fontFixedScale
|
||||
onMoved: value => Settings.data.ui.fontFixedScale = value
|
||||
text: Math.floor(Settings.data.ui.fontFixedScale * 100) + "%"
|
||||
}
|
||||
|
||||
// Reset button container
|
||||
Item {
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
Layout.preferredHeight: 30 * scaling
|
||||
|
||||
NIconButton {
|
||||
icon: "refresh"
|
||||
baseSize: Style.baseWidgetSize * 0.9
|
||||
tooltipText: I18n.tr("settings.general.fonts.reset-scaling")
|
||||
onClicked: Settings.data.ui.fontFixedScale = 1.0
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,14 +53,14 @@ ColumnLayout {
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.launcher.settings.background-opacity.label")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("settings.launcher.settings.background-opacity.description")
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
@@ -99,6 +99,16 @@ ColumnLayout {
|
||||
onToggled: checked => Settings.data.appLauncher.useApp2Unit = checked
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
label: I18n.tr("settings.launcher.settings.terminal-command.label")
|
||||
description: I18n.tr("settings.launcher.settings.terminal-command.description")
|
||||
Layout.fillWidth: true
|
||||
text: Settings.data.appLauncher.terminalCommand
|
||||
onEditingFinished: {
|
||||
Settings.data.appLauncher.terminalCommand = text
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
|
||||
@@ -46,7 +46,7 @@ ColumnLayout {
|
||||
"name": LocationService.stableName,
|
||||
"coordinates": LocationService.displayCoordinates
|
||||
})
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignRight
|
||||
|
||||
@@ -77,7 +77,7 @@ ColumnLayout {
|
||||
text: (modelData.name || "Unknown")
|
||||
color: Color.mPrimary
|
||||
font.weight: Style.fontWeightBold
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
}
|
||||
|
||||
NTextInputButton {
|
||||
@@ -327,7 +327,7 @@ ColumnLayout {
|
||||
id: chipLabel
|
||||
anchors.centerIn: parent
|
||||
text: parent.label
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
pointSize: Style.fontSizeS * scaling
|
||||
color: parent.selected ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ Rectangle {
|
||||
return Color.mOnSurface
|
||||
}
|
||||
}
|
||||
font.pointSize: Style.fontSizeXXL * 1.5 * scaling
|
||||
pointSize: Style.fontSizeXXL * 1.5 * scaling
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
text: root.message
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
wrapMode: Text.WordWrap
|
||||
visible: text.length > 0
|
||||
@@ -124,7 +124,7 @@ Rectangle {
|
||||
Layout.fillWidth: true
|
||||
text: root.description
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
wrapMode: Text.WordWrap
|
||||
visible: text.length > 0
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ Variants {
|
||||
scaling: ScalingService.getScreenScale(modelData)
|
||||
|
||||
// Only activate on enabled screens
|
||||
active: Settings.isLoaded && modelData && (Settings.data.notifications.monitors.includes(modelData.name) || Settings.data.notifications.monitors.length === 0)
|
||||
active: modelData && (Settings.data.notifications.monitors.includes(modelData.name) || Settings.data.notifications.monitors.length === 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,11 +93,11 @@ Item {
|
||||
// Activate the loader and show toast
|
||||
windowLoader.active = true
|
||||
// Need a small delay to ensure the window is created
|
||||
Qt.callLater(function () {
|
||||
if (windowLoader.item) {
|
||||
windowLoader.item.showToast(data.message, data.description, data.type, data.duration)
|
||||
}
|
||||
})
|
||||
Qt.callLater(() => {
|
||||
if (windowLoader.item) {
|
||||
windowLoader.item.showToast(data.message, data.description, data.type, data.duration)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onToastHidden() {
|
||||
@@ -128,7 +128,7 @@ Item {
|
||||
|
||||
screen: root.screen
|
||||
|
||||
readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right"
|
||||
readonly property string location: (Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right"
|
||||
readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top")
|
||||
readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom")
|
||||
readonly property bool isLeft: location.indexOf("_left") >= 0
|
||||
|
||||
406
Modules/Tooltip/Tooltip.qml
Normal file
406
Modules/Tooltip/Tooltip.qml
Normal file
@@ -0,0 +1,406 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
PopupWindow {
|
||||
id: root
|
||||
|
||||
property string text: ""
|
||||
property string direction: "auto" // "auto", "left", "right", "top", "bottom"
|
||||
property int margin: Style.marginXS // distance from target
|
||||
property int padding: Style.marginM
|
||||
property int delay: 0
|
||||
property int hideDelay: 0
|
||||
property int maxWidth: 320
|
||||
property real scaling: 1.0
|
||||
property int animationDuration: Style.animationFast
|
||||
property real animationScale: 0.85
|
||||
|
||||
// Internal properties
|
||||
property var targetItem: null
|
||||
property real anchorX: 0
|
||||
property real anchorY: 0
|
||||
property bool isPositioned: false
|
||||
property bool pendingShow: false
|
||||
property bool animatingOut: true
|
||||
|
||||
visible: false
|
||||
color: Color.transparent
|
||||
|
||||
anchor.item: targetItem
|
||||
anchor.rect.x: anchorX
|
||||
anchor.rect.y: anchorY
|
||||
|
||||
// Timer for showing tooltip after delay
|
||||
Timer {
|
||||
id: showTimer
|
||||
interval: root.delay
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
root.positionAndShow()
|
||||
}
|
||||
}
|
||||
|
||||
// Timer for hiding tooltip after delay
|
||||
Timer {
|
||||
id: hideTimer
|
||||
interval: root.hideDelay
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
root.startHideAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
// Show animation
|
||||
ParallelAnimation {
|
||||
id: showAnimation
|
||||
|
||||
PropertyAnimation {
|
||||
target: tooltipContainer
|
||||
property: "opacity"
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
|
||||
PropertyAnimation {
|
||||
target: tooltipContainer
|
||||
property: "scale"
|
||||
from: root.animationScale
|
||||
to: 1.0
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.OutBack
|
||||
easing.overshoot: 1.2
|
||||
}
|
||||
}
|
||||
|
||||
// Hide animation
|
||||
ParallelAnimation {
|
||||
id: hideAnimation
|
||||
|
||||
PropertyAnimation {
|
||||
target: tooltipContainer
|
||||
property: "opacity"
|
||||
from: 1.0
|
||||
to: 0.0
|
||||
duration: root.animationDuration * 0.75 // Slightly faster hide
|
||||
easing.type: Easing.InCubic
|
||||
}
|
||||
|
||||
PropertyAnimation {
|
||||
target: tooltipContainer
|
||||
property: "scale"
|
||||
from: 1.0
|
||||
to: root.animationScale
|
||||
duration: root.animationDuration * 0.75
|
||||
easing.type: Easing.InCubic
|
||||
}
|
||||
|
||||
onFinished: {
|
||||
root.completeHide()
|
||||
}
|
||||
}
|
||||
|
||||
// Function to show tooltip
|
||||
function show(target, tipText, customDirection, showDelay) {
|
||||
if (!target || !tipText || tipText === "")
|
||||
return
|
||||
|
||||
delay = showDelay
|
||||
|
||||
// Stop any running timers and animations
|
||||
hideTimer.stop()
|
||||
showTimer.stop()
|
||||
hideAnimation.stop()
|
||||
animatingOut = false
|
||||
|
||||
// If we're already showing for a different target, hide immediately
|
||||
if (visible && targetItem !== target) {
|
||||
hideImmediately()
|
||||
}
|
||||
|
||||
// Set properties
|
||||
targetItem = target
|
||||
text = tipText
|
||||
pendingShow = true
|
||||
|
||||
if (customDirection !== undefined) {
|
||||
direction = customDirection
|
||||
} else {
|
||||
direction = "auto"
|
||||
}
|
||||
|
||||
// Start show timer
|
||||
showTimer.start()
|
||||
}
|
||||
|
||||
// Function to position and display the tooltip
|
||||
function positionAndShow() {
|
||||
if (!targetItem || !targetItem.parent || !pendingShow) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get screen dimensions - try multiple methods
|
||||
var screenWidth = Screen.width
|
||||
var screenHeight = Screen.height
|
||||
|
||||
// Try to get screen from target item
|
||||
if (targetItem) {
|
||||
if (targetItem.screen) {
|
||||
screenWidth = targetItem.screen.width
|
||||
screenHeight = targetItem.screen.height
|
||||
scaling = ScalingService.getScreenScale(targetItem.screen)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate tooltip dimensions
|
||||
const tipWidth = Math.min(tooltipText.implicitWidth + (padding * 2 * scaling), maxWidth * scaling)
|
||||
root.implicitWidth = tipWidth
|
||||
|
||||
const tipHeight = tooltipText.implicitHeight + (padding * 2 * scaling)
|
||||
root.implicitHeight = tipHeight
|
||||
|
||||
// Get target's global position
|
||||
const targetGlobal = targetItem.mapToGlobal(0, 0)
|
||||
const targetWidth = targetItem.width
|
||||
const targetHeight = targetItem.height
|
||||
|
||||
var newAnchorX = 0
|
||||
var newAnchorY = 0
|
||||
|
||||
if (direction === "auto") {
|
||||
// Calculate available space in each direction
|
||||
const spaceLeft = targetGlobal.x
|
||||
const spaceRight = screenWidth - (targetGlobal.x + targetWidth)
|
||||
const spaceTop = targetGlobal.y
|
||||
const spaceBottom = screenHeight - (targetGlobal.y + targetHeight)
|
||||
|
||||
// Try positions in order of available space
|
||||
const positions = [{
|
||||
"dir": "bottom",
|
||||
"space": spaceBottom,
|
||||
"x": (targetWidth - tipWidth) / 2,
|
||||
"y": targetHeight + margin * scaling,
|
||||
"fits": spaceBottom >= tipHeight + margin * scaling
|
||||
}, {
|
||||
"dir": "top",
|
||||
"space": spaceTop,
|
||||
"x": (targetWidth - tipWidth) / 2,
|
||||
"y": -tipHeight - margin * scaling,
|
||||
"fits": spaceTop >= tipHeight + margin * scaling
|
||||
}, {
|
||||
"dir": "right",
|
||||
"space": spaceRight,
|
||||
"x": targetWidth + margin * scaling,
|
||||
"y": (targetHeight - tipHeight) / 2,
|
||||
"fits": spaceRight >= tipWidth + margin * scaling
|
||||
}, {
|
||||
"dir": "left",
|
||||
"space": spaceLeft,
|
||||
"x": -tipWidth - margin * scaling,
|
||||
"y": (targetHeight - tipHeight) / 2,
|
||||
"fits": spaceLeft >= tipWidth + margin * scaling
|
||||
}]
|
||||
|
||||
// Find first position that fits
|
||||
var selectedPosition = null
|
||||
for (var i = 0; i < positions.length; i++) {
|
||||
if (positions[i].fits) {
|
||||
selectedPosition = positions[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none fit perfectly
|
||||
if (!selectedPosition) {
|
||||
// Sort by available space and use position with most space
|
||||
positions.sort(function (a, b) {
|
||||
return b.space - a.space
|
||||
})
|
||||
selectedPosition = positions[0]
|
||||
}
|
||||
|
||||
newAnchorX = selectedPosition.x
|
||||
newAnchorY = selectedPosition.y
|
||||
|
||||
// Adjust horizontal position to keep tooltip on screen
|
||||
if (direction === "auto") {
|
||||
const globalX = targetGlobal.x + newAnchorX
|
||||
if (globalX < 0) {
|
||||
newAnchorX = -targetGlobal.x + margin * scaling
|
||||
} else if (globalX + tipWidth > screenWidth) {
|
||||
newAnchorX = screenWidth - targetGlobal.x - tipWidth - margin * scaling
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Manual direction positioning
|
||||
switch (direction) {
|
||||
case "left":
|
||||
newAnchorX = -tipWidth - margin * scaling
|
||||
newAnchorY = (targetHeight - tipHeight) / 2
|
||||
break
|
||||
case "right":
|
||||
newAnchorX = targetWidth + margin * scaling
|
||||
newAnchorY = (targetHeight - tipHeight) / 2
|
||||
break
|
||||
case "top":
|
||||
newAnchorX = (targetWidth - tipWidth) / 2
|
||||
newAnchorY = -tipHeight - margin * scaling
|
||||
break
|
||||
case "bottom":
|
||||
newAnchorX = (targetWidth - tipWidth) / 2
|
||||
newAnchorY = targetHeight + margin * scaling
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Apply position
|
||||
anchorX = newAnchorX
|
||||
anchorY = newAnchorY
|
||||
isPositioned = true
|
||||
pendingShow = false
|
||||
|
||||
// Show tooltip and start animation
|
||||
visible = true
|
||||
|
||||
// Initialize animation state
|
||||
tooltipContainer.opacity = 0.0
|
||||
tooltipContainer.scale = animationScale
|
||||
|
||||
// Start show animation
|
||||
showAnimation.start()
|
||||
|
||||
// Force anchor update after showing
|
||||
Qt.callLater(() => {
|
||||
if (root.anchor && root.visible) {
|
||||
root.anchor.updateAnchor()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Function to hide tooltip
|
||||
function hide() {
|
||||
// Stop show timer if it's running
|
||||
showTimer.stop()
|
||||
pendingShow = false
|
||||
|
||||
// Stop hide timer if it's running
|
||||
hideTimer.stop()
|
||||
|
||||
if (hideDelay > 0 && visible && !animatingOut) {
|
||||
hideTimer.start()
|
||||
} else {
|
||||
startHideAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
function startHideAnimation() {
|
||||
if (!visible || animatingOut)
|
||||
return
|
||||
|
||||
animatingOut = true
|
||||
showAnimation.stop() // Stop show animation if running
|
||||
hideAnimation.start()
|
||||
}
|
||||
|
||||
function completeHide() {
|
||||
visible = false
|
||||
animatingOut = false
|
||||
pendingShow = false
|
||||
text = ""
|
||||
isPositioned = false
|
||||
tooltipContainer.opacity = 1.0
|
||||
tooltipContainer.scale = 1.0
|
||||
}
|
||||
|
||||
// Quick hide without delay or animation
|
||||
function hideImmediately() {
|
||||
showTimer.stop()
|
||||
hideTimer.stop()
|
||||
showAnimation.stop()
|
||||
hideAnimation.stop()
|
||||
pendingShow = false
|
||||
animatingOut = false
|
||||
completeHide()
|
||||
}
|
||||
|
||||
// Update text function for binding support
|
||||
function updateText(newText) {
|
||||
if (visible && targetItem) {
|
||||
text = newText
|
||||
positionAndShow()
|
||||
}
|
||||
}
|
||||
|
||||
// Reset function to clean up state
|
||||
function reset() {
|
||||
// Stop all timers and animations
|
||||
showTimer.stop()
|
||||
hideTimer.stop()
|
||||
showAnimation.stop()
|
||||
hideAnimation.stop()
|
||||
|
||||
// Clear all state
|
||||
visible = false
|
||||
pendingShow = false
|
||||
animatingOut = false
|
||||
text = ""
|
||||
isPositioned = false
|
||||
|
||||
// Reset to defaults
|
||||
direction = "auto"
|
||||
delay = 0
|
||||
hideDelay = 0
|
||||
|
||||
// Reset container state
|
||||
tooltipContainer.opacity = 1.0
|
||||
tooltipContainer.scale = 1.0
|
||||
}
|
||||
|
||||
// Tooltip content container for animations
|
||||
Item {
|
||||
id: tooltipContainer
|
||||
anchors.fill: parent
|
||||
|
||||
// Animation properties
|
||||
opacity: 1.0
|
||||
scale: 1.0
|
||||
transformOrigin: Item.Center
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * root.scaling)
|
||||
radius: Style.radiusS * root.scaling
|
||||
|
||||
// Only show content when we have text
|
||||
visible: root.text !== ""
|
||||
|
||||
NText {
|
||||
id: tooltipText
|
||||
anchors.centerIn: parent
|
||||
anchors.margins: root.padding * root.scaling
|
||||
text: root.text
|
||||
pointSize: Style.fontSizeS * root.scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WordWrap
|
||||
width: root.maxWidth * root.scaling - (root.padding * 2 * root.scaling)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
reset()
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import QtQuick.Controls
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Commons
|
||||
import qs.Modules.Settings
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
import "../../Helpers/FuzzySort.js" as FuzzySort
|
||||
@@ -51,18 +52,29 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "settings-wallpaper-selector"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: Color.mPrimary
|
||||
}
|
||||
|
||||
NText {
|
||||
text: I18n.tr("wallpaper.panel.title")
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "settings"
|
||||
tooltipText: I18n.tr("settings.wallpaper.settings.section.label")
|
||||
baseSize: Style.baseWidgetSize * 0.8
|
||||
onClicked: {
|
||||
var settingsPanel = PanelService.getPanel("settingsPanel")
|
||||
settingsPanel.requestedTab = SettingsPanel.Tab.Wallpaper
|
||||
settingsPanel.open()
|
||||
}
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
icon: "refresh"
|
||||
tooltipText: I18n.tr("tooltips.refresh-wallpaper-list")
|
||||
@@ -122,11 +134,11 @@ NPanel {
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
contentItem: NText {
|
||||
text: parent.text
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
pointSize: Style.fontSizeL * scaling
|
||||
font.weight: screenTabBar.currentIndex === index ? Style.fontWeightBold : Style.fontWeightRegular
|
||||
font.family: Settings.data.ui.fontDefault
|
||||
family: Settings.data.ui.fontDefault
|
||||
color: screenTabBar.currentIndex === index ? Color.mOnSecondary : Color.mOnSurfaceVariant
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -177,7 +189,7 @@ NPanel {
|
||||
NText {
|
||||
text: I18n.tr("wallpaper.panel.search")
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
Layout.preferredWidth: implicitWidth
|
||||
}
|
||||
|
||||
@@ -355,7 +367,7 @@ NPanel {
|
||||
|
||||
NIcon {
|
||||
icon: "check"
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSecondary
|
||||
anchors.centerIn: parent
|
||||
@@ -393,7 +405,7 @@ NPanel {
|
||||
text: filename
|
||||
color: Color.mOnSurfaceVariant
|
||||
opacity: 0.5
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
pointSize: Style.fontSizeXS * scaling
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Style.marginS * scaling
|
||||
Layout.rightMargin: Style.marginS * scaling
|
||||
@@ -431,7 +443,7 @@ NPanel {
|
||||
}
|
||||
NIcon {
|
||||
icon: "folder-open"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
pointSize: Style.fontSizeXXL * scaling
|
||||
color: Color.mOnSurface
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
@@ -9,6 +9,13 @@ Singleton {
|
||||
|
||||
property bool hasAudioVisualizer: false
|
||||
property bool isVisible: true
|
||||
property var readyBars: ({})
|
||||
|
||||
// Registry to store actual widget instances
|
||||
// Key format: "screenName|section|widgetId|index"
|
||||
property var widgetInstances: ({})
|
||||
|
||||
signal barReadyChanged(string screenName)
|
||||
|
||||
// Simple timer that run once when the widget structure has changed
|
||||
// and determine if any MediaMini widget has the visualizer on
|
||||
@@ -28,14 +35,24 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// Registry to store actual widget instances
|
||||
// Key format: "screenName|section|widgetId|index"
|
||||
property var widgetInstances: ({})
|
||||
|
||||
Component.onCompleted: {
|
||||
Logger.log("BarService", "Service started")
|
||||
}
|
||||
|
||||
// Function for the Bar to call when it's ready
|
||||
function registerBar(screenName) {
|
||||
if (!readyBars[screenName]) {
|
||||
readyBars[screenName] = true
|
||||
Logger.log("BarService", "Bar is ready on screen:", screenName)
|
||||
barReadyChanged(screenName)
|
||||
}
|
||||
}
|
||||
|
||||
// Function for the Dock to check if the bar is ready
|
||||
function isBarReady(screenName) {
|
||||
return readyBars[screenName] || false
|
||||
}
|
||||
|
||||
// Register a widget instance
|
||||
function registerWidget(screenName, section, widgetId, index, instance) {
|
||||
const key = [screenName, section, widgetId, index].join("|")
|
||||
@@ -202,4 +219,17 @@ Singleton {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getTooltipDirection() {
|
||||
switch (Settings.data.bar.position) {
|
||||
case "right":
|
||||
return "left"
|
||||
case "left":
|
||||
return "right"
|
||||
case "bottom":
|
||||
return "top"
|
||||
default:
|
||||
return "bottom"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ Singleton {
|
||||
"ActiveWindow": {
|
||||
"allowUserSettings": true,
|
||||
"showIcon": true,
|
||||
"autoHide": true,
|
||||
"autoHide": false,
|
||||
"scrollingMode": "hover"
|
||||
},
|
||||
"Battery": {
|
||||
@@ -56,7 +56,8 @@ Singleton {
|
||||
"Clock": {
|
||||
"allowUserSettings": true,
|
||||
"usePrimaryColor": true,
|
||||
"useMonospacedFont": true,
|
||||
"useCustomFont": false,
|
||||
"customFont": "",
|
||||
"formatHorizontal": "HH:mm ddd, MMM dd",
|
||||
"formatVertical": "HH mm - dd MM"
|
||||
},
|
||||
@@ -81,7 +82,7 @@ Singleton {
|
||||
},
|
||||
"MediaMini": {
|
||||
"allowUserSettings": true,
|
||||
"autoHide": true,
|
||||
"autoHide": false,
|
||||
"scrollingMode": "hover",
|
||||
"showAlbumArt": false,
|
||||
"showVisualizer": false,
|
||||
@@ -109,6 +110,11 @@ Singleton {
|
||||
"showNetworkStats": false,
|
||||
"showDiskUsage": false
|
||||
},
|
||||
"Taskbar": {
|
||||
"allowUserSettings": true,
|
||||
"onlySameOutput": true,
|
||||
"onlyActiveWorkspaces": true
|
||||
},
|
||||
"Workspace": {
|
||||
"allowUserSettings": true,
|
||||
"labelMode": "index",
|
||||
|
||||
@@ -16,6 +16,9 @@ Singleton {
|
||||
return monitors.find(m => m.modelData === screen)
|
||||
}
|
||||
|
||||
// Signal emitted when a specific monitor's brightness changes, includes monitor context
|
||||
signal monitorBrightnessChanged(var monitor, real newBrightness)
|
||||
|
||||
function getAvailableMethods(): list<string> {
|
||||
var methods = []
|
||||
if (monitors.some(m => m.isDdc))
|
||||
@@ -119,6 +122,52 @@ Singleton {
|
||||
// Signal for brightness changes
|
||||
signal brightnessUpdated(real newBrightness)
|
||||
|
||||
// Execute a system command to get the current brightness value directly
|
||||
readonly property Process refreshProc: Process {
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
var dataText = text.trim()
|
||||
if (dataText === "") {
|
||||
return
|
||||
}
|
||||
|
||||
var lines = dataText.split("\n")
|
||||
if (lines.length >= 2) {
|
||||
var current = parseInt(lines[0].trim())
|
||||
var max = parseInt(lines[1].trim())
|
||||
if (!isNaN(current) && !isNaN(max) && max > 0) {
|
||||
var newBrightness = current / max
|
||||
// Only update if it's actually different (avoid feedback loops)
|
||||
if (Math.abs(newBrightness - monitor.brightness) > 0.01) {
|
||||
// Update internal value to match system state
|
||||
monitor.brightness = newBrightness
|
||||
monitor.brightnessUpdated(monitor.brightness)
|
||||
root.monitorBrightnessChanged(monitor, monitor.brightness)
|
||||
//Logger.log("Brightness", "Refreshed brightness from system:", monitor.modelData.name, monitor.brightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to actively refresh the brightness from system
|
||||
function refreshBrightnessFromSystem() {
|
||||
if (!monitor.isDdc && !monitor.isAppleDisplay) {
|
||||
// For internal displays, query the system directly
|
||||
refreshProc.command = ["sh", "-c", "cat " + monitor.brightnessPath + " && " + "cat " + monitor.maxBrightnessPath]
|
||||
refreshProc.running = true
|
||||
} else if (monitor.isDdc) {
|
||||
// For DDC displays, get the current value
|
||||
refreshProc.command = ["ddcutil", "-b", monitor.busNum, "getvcp", "10", "--brief"]
|
||||
refreshProc.running = true
|
||||
} else if (monitor.isAppleDisplay) {
|
||||
// For Apple displays, get the current value
|
||||
refreshProc.command = ["asdbctl", "get"]
|
||||
refreshProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
// FileView to watch for external brightness changes (internal displays only)
|
||||
readonly property FileView brightnessWatcher: FileView {
|
||||
id: brightnessWatcher
|
||||
@@ -126,23 +175,11 @@ Singleton {
|
||||
path: (!monitor.isDdc && !monitor.isAppleDisplay && monitor.brightnessPath !== "") ? monitor.brightnessPath : ""
|
||||
watchChanges: path !== ""
|
||||
onFileChanged: {
|
||||
reload()
|
||||
if (monitor.ignoreNextChange) {
|
||||
monitor.ignoreNextChange = false
|
||||
return
|
||||
}
|
||||
if (text() === "")
|
||||
return
|
||||
var current = parseInt(text().trim())
|
||||
if (!isNaN(current) && monitor.maxBrightness > 0) {
|
||||
var newBrightness = current / monitor.maxBrightness
|
||||
// Only update if it's actually different (avoid feedback loops)
|
||||
if (Math.abs(newBrightness - monitor.brightness) > 0.01) {
|
||||
monitor.brightness = newBrightness
|
||||
monitor.brightnessUpdated(monitor.brightness)
|
||||
//Logger.log("Brightness", "External change detected:", monitor.modelData.name, monitor.brightness)
|
||||
}
|
||||
}
|
||||
// When a file change is detected, actively refresh from system
|
||||
// to ensure we get the most up-to-date value
|
||||
Qt.callLater(() => {
|
||||
monitor.refreshBrightnessFromSystem()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +230,7 @@ Singleton {
|
||||
|
||||
// Always update
|
||||
monitor.brightnessUpdated(monitor.brightness)
|
||||
root.monitorBrightnessChanged(monitor, monitor.brightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,20 +267,21 @@ Singleton {
|
||||
value = Math.max(0, Math.min(1, value))
|
||||
var rounded = Math.round(value * 100)
|
||||
|
||||
if (Math.round(monitor.brightness * 100) === rounded)
|
||||
return
|
||||
|
||||
if (timer.running) {
|
||||
monitor.queuedBrightness = value
|
||||
return
|
||||
}
|
||||
|
||||
// Update internal value and trigger UI feedback
|
||||
monitor.brightness = value
|
||||
brightnessUpdated(monitor.brightness)
|
||||
monitor.brightnessUpdated(value)
|
||||
root.monitorBrightnessChanged(monitor, monitor.brightness)
|
||||
|
||||
if (isAppleDisplay) {
|
||||
monitor.ignoreNextChange = true
|
||||
Quickshell.execDetached(["asdbctl", "set", rounded])
|
||||
} else if (isDdc) {
|
||||
monitor.ignoreNextChange = true
|
||||
Quickshell.execDetached(["ddcutil", "-b", busNum, "setvcp", "10", rounded])
|
||||
} else {
|
||||
monitor.ignoreNextChange = true
|
||||
|
||||
@@ -10,7 +10,7 @@ Singleton {
|
||||
id: root
|
||||
|
||||
// Public API
|
||||
property bool active: Settings.isLoaded && Settings.data.appLauncher.enableClipboardHistory && cliphistAvailable
|
||||
property bool active: Settings.data.appLauncher.enableClipboardHistory && cliphistAvailable
|
||||
property bool loading: false
|
||||
property var items: [] // [{id, preview, mime, isImage}]
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Singleton {
|
||||
|
||||
// Generic workspace and window data
|
||||
property ListModel workspaces: ListModel {}
|
||||
property var windows: []
|
||||
property ListModel windows: ListModel {}
|
||||
property int focusedWindowIndex: -1
|
||||
|
||||
// Generic events
|
||||
@@ -82,10 +82,17 @@ Singleton {
|
||||
workspaceChanged()
|
||||
})
|
||||
|
||||
backend.activeWindowChanged.connect(activeWindowChanged)
|
||||
backend.activeWindowChanged.connect(() => {
|
||||
// Sync active window when it changes
|
||||
// TODO: Avoid re-syncing all windows
|
||||
syncWindows()
|
||||
// Forward the signal
|
||||
activeWindowChanged()
|
||||
})
|
||||
|
||||
backend.windowListChanged.connect(() => {
|
||||
// Sync windows when they change
|
||||
windows = backend.windows
|
||||
syncWindows()
|
||||
// Forward the signal
|
||||
windowListChanged()
|
||||
})
|
||||
@@ -97,7 +104,7 @@ Singleton {
|
||||
|
||||
// Initial sync
|
||||
syncWorkspaces()
|
||||
windows = backend.windows
|
||||
syncWindows()
|
||||
focusedWindowIndex = backend.focusedWindowIndex
|
||||
}
|
||||
|
||||
@@ -111,10 +118,28 @@ Singleton {
|
||||
workspacesChanged()
|
||||
}
|
||||
|
||||
// Get window title for focused window
|
||||
function syncWindows() {
|
||||
windows.clear()
|
||||
const ws = backend.windows
|
||||
for (var i = 0; i < ws.length; i++) {
|
||||
windows.append(ws[i])
|
||||
}
|
||||
// Emit signal to notify listeners that workspace list has been updated
|
||||
windowListChanged()
|
||||
}
|
||||
|
||||
// Get focused window
|
||||
function getFocusedWindow() {
|
||||
if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) {
|
||||
return windows.get(focusedWindowIndex)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Get focused window title
|
||||
function getFocusedWindowTitle() {
|
||||
if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length) {
|
||||
return windows[focusedWindowIndex].title || ""
|
||||
if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) {
|
||||
return windows.get(focusedWindowIndex).title || ""
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -139,12 +164,34 @@ Singleton {
|
||||
return null
|
||||
}
|
||||
|
||||
// Get focused window
|
||||
function getFocusedWindow() {
|
||||
if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length) {
|
||||
return windows[focusedWindowIndex]
|
||||
// Get active workspaces
|
||||
function getActiveWorkspaces() {
|
||||
const activeWorkspaces = []
|
||||
for (var i = 0; i < workspaces.count; i++) {
|
||||
const ws = workspaces.get(i)
|
||||
if (ws.isActive) {
|
||||
activeWorkspaces.push(ws)
|
||||
}
|
||||
}
|
||||
return activeWorkspaces
|
||||
}
|
||||
|
||||
// Set focused window
|
||||
function focusWindow(windowId) {
|
||||
if (backend && backend.focusWindow) {
|
||||
backend.focusWindow(windowId)
|
||||
} else {
|
||||
Logger.warn("Compositor", "No backend available for window focus")
|
||||
}
|
||||
}
|
||||
|
||||
// Close window
|
||||
function closeWindow(windowId) {
|
||||
if (backend && backend.closeWindow) {
|
||||
backend.closeWindow(windowId)
|
||||
} else {
|
||||
Logger.warn("Compositor", "No backend available for window closing")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Session management
|
||||
@@ -167,4 +214,16 @@ Singleton {
|
||||
function suspend() {
|
||||
Quickshell.execDetached(["systemctl", "suspend"])
|
||||
}
|
||||
|
||||
function lockAndSuspend() {
|
||||
try {
|
||||
if (PanelService && PanelService.lockScreen && !PanelService.lockScreen.active) {
|
||||
PanelService.lockScreen.active = true
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.warn("Compositor", "Failed to activate lock screen before suspend: " + e)
|
||||
}
|
||||
// Queue suspend to the next event loop cycle to allow lock UI to render
|
||||
Qt.callLater(suspend)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,6 +278,22 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
function focusWindow(windowId) {
|
||||
try {
|
||||
Hyprland.dispatch(`focuswindow ${windowId}`)
|
||||
} catch (e) {
|
||||
Logger.error("HyprlandService", "Failed to switch window:", e)
|
||||
}
|
||||
}
|
||||
|
||||
function closeWindow(windowId) {
|
||||
try {
|
||||
Hyprland.dispatch(`killwindow ${windowId}`)
|
||||
} catch (e) {
|
||||
Logger.error("HyprlandService", "Failed to close window:", e)
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
try {
|
||||
Quickshell.execDetached(["hyprctl", "dispatch", "exit"])
|
||||
|
||||
@@ -10,7 +10,7 @@ import qs.Services
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property string dynamicConfigPath: Settings.isLoaded ? Settings.cacheDir + "matugen.dynamic.toml" : ""
|
||||
property string dynamicConfigPath: Settings.cacheDir + "matugen.dynamic.toml"
|
||||
|
||||
// External state management
|
||||
Connections {
|
||||
@@ -47,11 +47,6 @@ Singleton {
|
||||
|
||||
// Generate colors using current wallpaper and settings
|
||||
function generateFromWallpaper() {
|
||||
if (!Settings.isLoaded) {
|
||||
Logger.log("Matugen", "Settings not loaded yet, skipping wallpaper color generation")
|
||||
return
|
||||
}
|
||||
|
||||
Logger.log("Matugen", "Generating from wallpaper on screen:", Screen.name)
|
||||
var wp = WallpaperService.getWallpaper(Screen.name).replace(/'/g, "'\\''")
|
||||
if (wp === "") {
|
||||
|
||||
@@ -6,6 +6,9 @@ import qs.Commons
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Sorts floating windows after scrolling ones
|
||||
property int floatingWindowPosition: Number.MAX_SAFE_INTEGER
|
||||
|
||||
// Properties that match the facade interface
|
||||
property ListModel workspaces: ListModel {}
|
||||
property var windows: []
|
||||
@@ -91,32 +94,7 @@ Item {
|
||||
onRead: function (line) {
|
||||
try {
|
||||
const windowsData = JSON.parse(line)
|
||||
const windowsList = []
|
||||
|
||||
for (const win of windowsData) {
|
||||
windowsList.push({
|
||||
"id": win.id,
|
||||
"title": win.title || "",
|
||||
"appId": win.app_id || "",
|
||||
"workspaceId": win.workspace_id || null,
|
||||
"isFocused": win.is_focused === true
|
||||
})
|
||||
}
|
||||
|
||||
windowsList.sort((a, b) => a.id - b.id)
|
||||
windows = windowsList
|
||||
windowListChanged()
|
||||
|
||||
// Update focused window index
|
||||
focusedWindowIndex = -1
|
||||
for (var i = 0; i < windowsList.length; i++) {
|
||||
if (windowsList[i].isFocused) {
|
||||
focusedWindowIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
activeWindowChanged()
|
||||
recollectWindows(windowsData)
|
||||
} catch (e) {
|
||||
Logger.error("NiriService", "Failed to parse windows:", e, line)
|
||||
}
|
||||
@@ -147,8 +125,9 @@ Item {
|
||||
updateWorkspaces()
|
||||
} else if (event.WindowFocusChanged) {
|
||||
handleWindowFocusChanged(event.WindowFocusChanged)
|
||||
} else if (event.WindowLayoutsChanged) {
|
||||
handleWindowLayoutsChanged(event.WindowLayoutsChanged)
|
||||
}
|
||||
// Removed OverviewOpenedOrClosed handling
|
||||
} catch (e) {
|
||||
Logger.error("NiriService", "Error parsing event stream:", e, data)
|
||||
}
|
||||
@@ -156,19 +135,81 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
function getWindowPosition(layout) {
|
||||
if (layout.pos_in_scrolling_layout) {
|
||||
return {
|
||||
"x": layout.pos_in_scrolling_layout[0],
|
||||
"y": layout.pos_in_scrolling_layout[1]
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
"x": floatingWindowPosition,
|
||||
"y": floatingWindowPosition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getWindowOutput(win) {
|
||||
for (var i = 0; i < workspaces.count; i++) {
|
||||
if (workspaces.get(i).id === win.workspace_id) {
|
||||
return workspaces.get(i).output
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function getWindowData(win) {
|
||||
return {
|
||||
"id": win.id,
|
||||
"title": win.title || "",
|
||||
"appId": win.app_id || "",
|
||||
"workspaceId": win.workspace_id || -1,
|
||||
"isFocused": win.is_focused === true,
|
||||
"output": getWindowOutput(win) || "",
|
||||
"position": getWindowPosition(win.layout)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort windows
|
||||
// 1. by workspace ID
|
||||
// 2. by position X
|
||||
// 3. by position Y
|
||||
function compareWindows(a, b) {
|
||||
if (a.workspaceId !== b.workspaceId) {
|
||||
return a.workspaceId - b.workspaceId
|
||||
}
|
||||
if (a.position.x !== b.position.x) {
|
||||
return a.position.x - b.position.x
|
||||
}
|
||||
return a.position.y - b.position.y
|
||||
}
|
||||
|
||||
function recollectWindows(windowsData) {
|
||||
const windowsList = []
|
||||
for (const win of windowsData) {
|
||||
windowsList.push(getWindowData(win))
|
||||
}
|
||||
windowsList.sort(compareWindows)
|
||||
windows = windowsList
|
||||
windowListChanged()
|
||||
|
||||
focusedWindowIndex = -1
|
||||
for (var i = 0; i < windowsList.length; i++) {
|
||||
if (windowsList[i].isFocused) {
|
||||
focusedWindowIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
activeWindowChanged()
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
function handleWindowOpenedOrChanged(eventData) {
|
||||
try {
|
||||
const windowData = eventData.window
|
||||
const existingIndex = windows.findIndex(w => w.id === windowData.id)
|
||||
|
||||
const newWindow = {
|
||||
"id": windowData.id,
|
||||
"title": windowData.title || "",
|
||||
"appId": windowData.app_id || "",
|
||||
"workspaceId": windowData.workspace_id || null,
|
||||
"isFocused": windowData.is_focused === true
|
||||
}
|
||||
const newWindow = getWindowData(windowData)
|
||||
|
||||
if (existingIndex >= 0) {
|
||||
// Update existing window
|
||||
@@ -176,8 +217,8 @@ Item {
|
||||
} else {
|
||||
// Add new window
|
||||
windows.push(newWindow)
|
||||
windows.sort((a, b) => a.id - b.id)
|
||||
}
|
||||
windows.sort(compareWindows)
|
||||
|
||||
// Update focused window index if this window is focused
|
||||
if (newWindow.isFocused) {
|
||||
@@ -186,6 +227,9 @@ Item {
|
||||
|
||||
// Only emit activeWindowChanged if the focused window actually changed
|
||||
if (oldFocusedIndex !== focusedWindowIndex) {
|
||||
if (oldFocusedIndex >= 0 && oldFocusedIndex < windows.length) {
|
||||
windows[oldFocusedIndex].isFocused = false
|
||||
}
|
||||
activeWindowChanged()
|
||||
}
|
||||
}
|
||||
@@ -223,32 +267,7 @@ Item {
|
||||
function handleWindowsChanged(eventData) {
|
||||
try {
|
||||
const windowsData = eventData.windows
|
||||
const windowsList = []
|
||||
|
||||
for (const win of windowsData) {
|
||||
windowsList.push({
|
||||
"id": win.id,
|
||||
"title": win.title || "",
|
||||
"appId": win.app_id || "",
|
||||
"workspaceId": win.workspace_id || null,
|
||||
"isFocused": win.is_focused === true
|
||||
})
|
||||
}
|
||||
|
||||
windowsList.sort((a, b) => a.id - b.id)
|
||||
windows = windowsList
|
||||
windowListChanged()
|
||||
|
||||
// Update focused window index
|
||||
focusedWindowIndex = -1
|
||||
for (var i = 0; i < windowsList.length; i++) {
|
||||
if (windowsList[i].isFocused) {
|
||||
focusedWindowIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
activeWindowChanged()
|
||||
recollectWindows(windowsData)
|
||||
} catch (e) {
|
||||
Logger.error("NiriService", "Error handling WindowsChanged:", e)
|
||||
}
|
||||
@@ -258,8 +277,17 @@ Item {
|
||||
try {
|
||||
const focusedId = eventData.id
|
||||
|
||||
if (windows[focusedWindowIndex]) {
|
||||
windows[focusedWindowIndex].isFocused = false
|
||||
}
|
||||
|
||||
if (focusedId) {
|
||||
const newIndex = windows.findIndex(w => w.id === focusedId)
|
||||
|
||||
if (newIndex >= 0 && newIndex < windows.length) {
|
||||
windows[newIndex].isFocused = true
|
||||
}
|
||||
|
||||
focusedWindowIndex = newIndex >= 0 ? newIndex : -1
|
||||
} else {
|
||||
focusedWindowIndex = -1
|
||||
@@ -271,6 +299,25 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
function handleWindowLayoutsChanged(eventData) {
|
||||
try {
|
||||
for (const change of eventData.changes) {
|
||||
const windowId = change[0]
|
||||
const layout = change[1]
|
||||
const window = windows.find(w => w.id === windowId)
|
||||
if (window) {
|
||||
window.position = getWindowPosition(layout)
|
||||
}
|
||||
}
|
||||
|
||||
windows.sort(compareWindows)
|
||||
|
||||
windowListChanged()
|
||||
} catch (e) {
|
||||
Logger.error("NiriService", "Error handling WindowLayoutChanged:", e)
|
||||
}
|
||||
}
|
||||
|
||||
// Public functions
|
||||
function switchToWorkspace(workspaceId) {
|
||||
try {
|
||||
@@ -280,6 +327,22 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
function focusWindow(windowId) {
|
||||
try {
|
||||
Quickshell.execDetached(["niri", "msg", "action", "focus-window", "--id", windowId.toString()])
|
||||
} catch (e) {
|
||||
Logger.error("NiriService", "Failed to switch window:", e)
|
||||
}
|
||||
}
|
||||
|
||||
function closeWindow(windowId) {
|
||||
try {
|
||||
Quickshell.execDetached(["niri", "msg", "action", "close-window", "--id", windowId.toString()])
|
||||
} catch (e) {
|
||||
Logger.error("NiriService", "Failed to close window:", e)
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
try {
|
||||
Quickshell.execDetached(["niri", "msg", "action", "quit", "--skip-confirmation"])
|
||||
|
||||
@@ -25,12 +25,10 @@ Singleton {
|
||||
property var activeMap: ({})
|
||||
property var imageQueue: []
|
||||
property var progressTimers: ({})
|
||||
|
||||
// Simple image cacher
|
||||
PanelWindow {
|
||||
implicitHeight: 1
|
||||
implicitWidth: 1
|
||||
color: "transparent"
|
||||
color: Color.transparent
|
||||
mask: Region {}
|
||||
|
||||
Image {
|
||||
@@ -137,7 +135,6 @@ Singleton {
|
||||
|
||||
const dest = Settings.cacheDirImagesNotifications + imageId + ".png"
|
||||
|
||||
// Skip if already queued
|
||||
for (const req of imageQueue) {
|
||||
if (req.imageId === imageId)
|
||||
return
|
||||
@@ -149,7 +146,6 @@ Singleton {
|
||||
"imageId": imageId
|
||||
})
|
||||
|
||||
// If we have a single item in the queue, process it immediately
|
||||
if (imageQueue.length === 1)
|
||||
cacher.source = path
|
||||
}
|
||||
@@ -262,7 +258,6 @@ Singleton {
|
||||
items.push(copy)
|
||||
}
|
||||
adapter.notifications = items
|
||||
// Actually write the file
|
||||
historyFileView.writeAdapter()
|
||||
} catch (e) {
|
||||
Logger.error("Notifications", "Save history failed:", e)
|
||||
@@ -275,10 +270,8 @@ Singleton {
|
||||
for (const item of adapter.notifications || []) {
|
||||
const time = new Date(item.timestamp)
|
||||
|
||||
// Check if we have a cached image and try to use it
|
||||
let cachedImage = item.cachedImage || ""
|
||||
if (item.originalImage && item.originalImage.startsWith("image://") && !cachedImage) {
|
||||
// Try to generate the expected cached path
|
||||
const imageId = generateImageId(item, item.originalImage)
|
||||
if (imageId) {
|
||||
cachedImage = Settings.cacheDirImagesNotifications + imageId + ".png"
|
||||
@@ -301,15 +294,54 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function getAppName(name) {
|
||||
if (!name?.includes("."))
|
||||
return name || ""
|
||||
const entries = DesktopEntries.byId(name)
|
||||
if (entries?.length)
|
||||
return entries[0].name || name
|
||||
const parts = name.split(".")
|
||||
return parts[parts.length - 1].charAt(0).toUpperCase() + parts[parts.length - 1].slice(1)
|
||||
if (!name || name.trim() === "")
|
||||
return "Unknown"
|
||||
|
||||
name = name.trim()
|
||||
|
||||
if (name.includes(".") && (name.startsWith("com.") || name.startsWith("org.") || name.startsWith("io.") || name.startsWith("net."))) {
|
||||
const parts = name.split(".")
|
||||
let appPart = parts[parts.length - 1]
|
||||
|
||||
if (!appPart || appPart === "app" || appPart === "desktop") {
|
||||
appPart = parts[parts.length - 2] || parts[0]
|
||||
}
|
||||
|
||||
if (appPart) {
|
||||
name = appPart
|
||||
}
|
||||
}
|
||||
|
||||
if (name.includes(".")) {
|
||||
const parts = name.split(".")
|
||||
let displayName = parts[parts.length - 1]
|
||||
|
||||
if (!displayName || /^\d+$/.test(displayName)) {
|
||||
displayName = parts[parts.length - 2] || parts[0]
|
||||
}
|
||||
|
||||
if (displayName) {
|
||||
displayName = displayName.charAt(0).toUpperCase() + displayName.slice(1)
|
||||
displayName = displayName.replace(/([a-z])([A-Z])/g, '$1 $2')
|
||||
displayName = displayName.replace(/app$/i, '').trim()
|
||||
displayName = displayName.replace(/desktop$/i, '').trim()
|
||||
displayName = displayName.replace(/flatpak$/i, '').trim()
|
||||
|
||||
if (!displayName) {
|
||||
displayName = parts[parts.length - 1].charAt(0).toUpperCase() + parts[parts.length - 1].slice(1)
|
||||
}
|
||||
}
|
||||
|
||||
return displayName || name
|
||||
}
|
||||
|
||||
let displayName = name.charAt(0).toUpperCase() + name.slice(1)
|
||||
displayName = displayName.replace(/([a-z])([A-Z])/g, '$1 $2')
|
||||
displayName = displayName.replace(/app$/i, '').trim()
|
||||
displayName = displayName.replace(/desktop$/i, '').trim()
|
||||
|
||||
return displayName || name
|
||||
}
|
||||
|
||||
function getIcon(icon) {
|
||||
@@ -326,13 +358,10 @@ Singleton {
|
||||
|
||||
function generateImageId(notification, image) {
|
||||
if (image && image.startsWith("image://")) {
|
||||
// For qsimage URLs, try to use a combination that's unique per user
|
||||
if (image.startsWith("image://qsimage/")) {
|
||||
// Try to use app name + summary for uniqueness (summary often contains username)
|
||||
const key = (notification.appName || "") + "|" + (notification.summary || "")
|
||||
return Checksum.sha256(key)
|
||||
}
|
||||
|
||||
return Checksum.sha256(image)
|
||||
}
|
||||
return ""
|
||||
@@ -368,7 +397,6 @@ Singleton {
|
||||
for (var i = 0; i < historyList.count; i++) {
|
||||
const notif = historyList.get(i)
|
||||
if (notif.id === notificationId) {
|
||||
// Delete cached image if it exists
|
||||
if (notif.cachedImage && !notif.cachedImage.startsWith("image://")) {
|
||||
Quickshell.execDetached(["rm", "-f", notif.cachedImage])
|
||||
}
|
||||
@@ -381,7 +409,6 @@ Singleton {
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
// Remove all cached images
|
||||
try {
|
||||
Quickshell.execDetached(["sh", "-c", `rm -rf "${Settings.cacheDirImagesNotifications}"*`])
|
||||
} catch (e) {
|
||||
|
||||
@@ -15,19 +15,13 @@ Singleton {
|
||||
|
||||
Component.onCompleted: {
|
||||
Logger.log("Scaling", "Service started")
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Settings
|
||||
function onSettingsLoaded() {
|
||||
// Initialize cache from Settings once they are loaded on startup
|
||||
var monitors = Settings.data.ui.monitorsScaling || []
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].name && monitors[i].scale !== undefined) {
|
||||
currentScales[monitors[i].name] = monitors[i].scale
|
||||
root.scaleChanged(monitors[i].name, monitors[i].scale)
|
||||
Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale)
|
||||
}
|
||||
// Initialize cache from Settings once they are loaded on startup
|
||||
var monitors = Settings.data.ui.monitorsScaling || []
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].name && monitors[i].scale !== undefined) {
|
||||
currentScales[monitors[i].name] = monitors[i].scale
|
||||
root.scaleChanged(monitors[i].name, monitors[i].scale)
|
||||
Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
114
Services/TooltipService.qml
Normal file
114
Services/TooltipService.qml
Normal file
@@ -0,0 +1,114 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Modules.Tooltip
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property var activeTooltip: null
|
||||
property var pendingTooltip: null // Track tooltip being created
|
||||
|
||||
property Component tooltipComponent: Component {
|
||||
Tooltip {}
|
||||
}
|
||||
|
||||
function show(target, text, direction, delay) {
|
||||
// Don't create if no text
|
||||
if (!target || !text) {
|
||||
Logger.log("Tooltip", "No target or text")
|
||||
return
|
||||
}
|
||||
|
||||
// If we have a pending tooltip for a different target, cancel it
|
||||
if (pendingTooltip && pendingTooltip.targetItem !== target) {
|
||||
pendingTooltip.hideImmediately()
|
||||
pendingTooltip.destroy()
|
||||
pendingTooltip = null
|
||||
}
|
||||
|
||||
// If we have an active tooltip for a different target, hide it
|
||||
if (activeTooltip && activeTooltip.targetItem !== target) {
|
||||
activeTooltip.hideImmediately()
|
||||
// Don't destroy immediately - let it clean itself up
|
||||
activeTooltip = null
|
||||
}
|
||||
|
||||
// If we already have a tooltip for this target, just update it
|
||||
if (activeTooltip && activeTooltip.targetItem === target) {
|
||||
activeTooltip.updateText(text)
|
||||
return activeTooltip
|
||||
}
|
||||
|
||||
// Create new tooltip instance
|
||||
const newTooltip = tooltipComponent.createObject(null)
|
||||
|
||||
if (newTooltip) {
|
||||
// Track as pending until it's visible
|
||||
pendingTooltip = newTooltip
|
||||
|
||||
// Connect cleanup when tooltip hides
|
||||
newTooltip.visibleChanged.connect(() => {
|
||||
if (!newTooltip.visible) {
|
||||
// Clean up after a delay to avoid interfering with new tooltips
|
||||
Qt.callLater(() => {
|
||||
if (newTooltip && !newTooltip.visible) {
|
||||
if (activeTooltip === newTooltip) {
|
||||
activeTooltip = null
|
||||
}
|
||||
if (pendingTooltip === newTooltip) {
|
||||
pendingTooltip = null
|
||||
}
|
||||
newTooltip.destroy()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// Tooltip is now visible, move from pending to active
|
||||
if (pendingTooltip === newTooltip) {
|
||||
activeTooltip = newTooltip
|
||||
pendingTooltip = null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Show the tooltip
|
||||
newTooltip.show(target, text, direction || "auto", delay || Style.tooltipDelay)
|
||||
|
||||
return newTooltip
|
||||
} else {
|
||||
Logger.error("Tooltip", "Failed to create tooltip instance")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function hide() {
|
||||
if (pendingTooltip) {
|
||||
pendingTooltip.hide()
|
||||
}
|
||||
if (activeTooltip) {
|
||||
activeTooltip.hide()
|
||||
}
|
||||
}
|
||||
|
||||
function hideImmediately() {
|
||||
if (pendingTooltip) {
|
||||
pendingTooltip.hideImmediately()
|
||||
pendingTooltip.destroy()
|
||||
pendingTooltip = null
|
||||
}
|
||||
if (activeTooltip) {
|
||||
activeTooltip.hideImmediately()
|
||||
activeTooltip.destroy()
|
||||
activeTooltip = null
|
||||
}
|
||||
}
|
||||
|
||||
function updateText(newText) {
|
||||
if (activeTooltip) {
|
||||
activeTooltip.updateText(newText)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ Singleton {
|
||||
id: root
|
||||
|
||||
// Public properties
|
||||
property string baseVersion: "2.14.4"
|
||||
property string baseVersion: "2.15.0"
|
||||
property bool isDevelopment: false
|
||||
|
||||
property string currentVersion: `v${!isDevelopment ? baseVersion : baseVersion + "-dev"}`
|
||||
|
||||
@@ -26,6 +26,8 @@ Singleton {
|
||||
// Cache for current wallpapers - can be updated directly since we use signals for notifications
|
||||
property var currentWallpapers: ({})
|
||||
|
||||
property bool isInitialized: false
|
||||
|
||||
// Signals for reactive UI updates
|
||||
signal wallpaperChanged(string screenName, string path)
|
||||
// Emitted when a wallpaper changes
|
||||
@@ -75,18 +77,18 @@ Singleton {
|
||||
function init() {
|
||||
Logger.log("Wallpaper", "Service started")
|
||||
|
||||
// Rebuild cache from persisted settings
|
||||
var monitors = Settings.data.wallpaper.monitors || []
|
||||
translateModels()
|
||||
|
||||
// Rebuild cache from settings
|
||||
currentWallpapers = ({})
|
||||
var monitors = Settings.data.wallpaper.monitors || []
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].name && monitors[i].wallpaper) {
|
||||
currentWallpapers[monitors[i].name] = monitors[i].wallpaper
|
||||
// Notify listeners so Background updates immediately after settings load
|
||||
root.wallpaperChanged(monitors[i].name, monitors[i].wallpaper)
|
||||
}
|
||||
}
|
||||
|
||||
translateModels()
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
@@ -110,8 +110,11 @@ void main() {
|
||||
// Add extra range for smoothness to ensure complete coverage
|
||||
// Adjust smoothness for aspect ratio to maintain consistent visual appearance
|
||||
float adjustedSmoothness = mappedSmoothness * max(1.0, ubuf.aspectRatio);
|
||||
float radius = ubuf.progress * (maxDist + adjustedSmoothness);
|
||||
|
||||
// Start the radius from -adjustedSmoothness, this ensures the disc is completely hidden when progress=0
|
||||
float totalDistance = maxDist + 2.0 * adjustedSmoothness;
|
||||
float radius = -adjustedSmoothness + ubuf.progress * totalDistance;
|
||||
|
||||
// Use smoothstep for a smooth edge transition
|
||||
float factor = smoothstep(radius - adjustedSmoothness, radius + adjustedSmoothness, dist);
|
||||
|
||||
|
||||
Binary file not shown.
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
@@ -77,9 +78,8 @@ Rectangle {
|
||||
NIcon {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: root.icon !== ""
|
||||
|
||||
icon: root.icon
|
||||
font.pointSize: root.iconSize
|
||||
pointSize: root.iconSize
|
||||
color: {
|
||||
if (!root.enabled)
|
||||
return Color.mOnSurfaceVariant
|
||||
@@ -104,7 +104,7 @@ Rectangle {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: root.text !== ""
|
||||
text: root.text
|
||||
font.pointSize: root.fontSize
|
||||
pointSize: root.fontSize
|
||||
font.weight: root.fontWeight
|
||||
color: {
|
||||
if (!root.enabled)
|
||||
@@ -126,12 +126,6 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
NTooltip {
|
||||
id: tooltip
|
||||
target: root
|
||||
text: root.tooltipText
|
||||
}
|
||||
|
||||
// Mouse interaction
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
@@ -144,18 +138,18 @@ Rectangle {
|
||||
onEntered: {
|
||||
root.hovered = true
|
||||
if (tooltipText) {
|
||||
tooltip.show()
|
||||
TooltipService.show(root, root.tooltipText)
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
root.hovered = false
|
||||
if (tooltipText) {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
onPressed: mouse => {
|
||||
if (tooltipText) {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
root.clicked()
|
||||
@@ -169,7 +163,7 @@ Rectangle {
|
||||
onCanceled: {
|
||||
root.hovered = false
|
||||
if (tooltipText) {
|
||||
tooltip.hide()
|
||||
TooltipService.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user