From 75c647cac7bf22104d25c09f4c77c91093a785e7 Mon Sep 17 00:00:00 2001 From: coderkun Date: Fri, 24 May 2024 16:45:40 +0200 Subject: [PATCH 1/7] Combine connection panel with server panel (close #102) --- data/ui/connection-panel.ui | 87 ---------------------- data/ui/server-panel.ui | 89 ++++++++++++++++++++++- data/ui/window.ui | 10 +-- data/xyz.suruatoel.mcg.gresource.xml | 1 - po/POTFILES | 2 - po/de.mo | Bin 3448 -> 3486 bytes po/de.po | 98 +++++++++++++------------ po/en.mo | Bin 3284 -> 3322 bytes po/en.po | 98 +++++++++++++------------ po/mcg.pot | 105 ++++++++++++++------------- src/connectionpanel.py | 89 ----------------------- src/meson.build | 1 - src/serverpanel.py | 84 +++++++++++++++++++++ src/window.py | 40 +++++----- 14 files changed, 345 insertions(+), 359 deletions(-) delete mode 100644 data/ui/connection-panel.ui delete mode 100644 src/connectionpanel.py diff --git a/data/ui/connection-panel.ui b/data/ui/connection-panel.ui deleted file mode 100644 index d9e7364..0000000 --- a/data/ui/connection-panel.ui +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - 1024 - 9999 - 6600 - 1 - 100 - - - horizontal - 6 - - - diff --git a/data/ui/server-panel.ui b/data/ui/server-panel.ui index 3907f50..7faef17 100644 --- a/data/ui/server-panel.ui +++ b/data/ui/server-panel.ui @@ -2,6 +2,13 @@ + + 1024 + 9999 + 6600 + 1 + 100 + horizontal end @@ -31,8 +38,84 @@ + connection + Connection + + + network-wired-symbolic + + + false + center + + + true + + + No service found + + + + + + + true + none + + + + Host + true + + + + + + vertical + + + + Port + start + false + + + + + + port_spinner + 6600 + server-port-adjustment + + + + + + + + Password + true + + + + + + + + + + + + status Status + false dialog-information-symbolic @@ -149,9 +232,10 @@ - + stats Statistics + false starred-symbolic @@ -298,9 +382,10 @@ - + devices Audio Devices + false audio-speakers-symbolic diff --git a/data/ui/window.ui b/data/ui/window.ui index aa73ed1..801e6a4 100644 --- a/data/ui/window.ui +++ b/data/ui/window.ui @@ -49,15 +49,9 @@ - - content_stack + true - - - true - - - + diff --git a/data/xyz.suruatoel.mcg.gresource.xml b/data/xyz.suruatoel.mcg.gresource.xml index 02141b3..45476d0 100644 --- a/data/xyz.suruatoel.mcg.gresource.xml +++ b/data/xyz.suruatoel.mcg.gresource.xml @@ -5,7 +5,6 @@ noise-texture.png ui/window.ui ui/shortcuts-dialog.ui - ui/connection-panel.ui ui/album-headerbar.ui ui/server-panel.ui ui/cover-panel.ui diff --git a/po/POTFILES b/po/POTFILES index 0263b63..7245744 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -1,5 +1,4 @@ data/ui/album-headerbar.ui -data/ui/connection-panel.ui data/ui/cover-panel.ui data/ui/library-panel.ui data/ui/playlist-panel.ui @@ -9,7 +8,6 @@ data/ui/window.ui src/albumheaderbar.py src/application.py src/client.py -src/connectionpanel.py src/coverpanel.py src/librarypanel.py src/main.py diff --git a/po/de.mo b/po/de.mo index 0977fc7f942005a8edfb232bdcba04bee1f0235e..a3e8ff0a625bf7f0d567683606d9c13091c57894 100644 GIT binary patch delta 1343 zcmYk*OK1~89LMp0P12-kd^C2|rm0P}t=3mxNww93^db~|Tr9R1p;{zXBB&7$ffWQR z2v#UL2vx*m5k2Ifr|Qj%UMwj1LJul*5&HcY$3gV)Bt~%px$G*9<|`oc z`F6|wFol}9h(WyX`j1cx&Eh(I?tFzC=)c2y{E6DYU(`lJH0sAt^LeP}5~vM!Vwm-9 zkQ+@rgzIqxH(?gJ>^hBJoWvHK!A6`z*0K+%1-_yp{f=C=NYjMNxD`F3Yrr(>{bQJ9 zeLK&MUYJBpbO$x@v>U&N+TcUyQ`Cm$P$x5wG5m&`aRK#wHQ_6Z9_q*&P|vsFZPMI} zz6M^@R2F=LTsBXm2|uGY_6vE|mN0=U*p43ID&j*l+VBz7dqftr5=^xCHxw&OGG!jGtkVuZt57DtAx3H4$JwqX}4x5KF1=3RdZHQy6dbDG4Ym@^* zt>bsnsObCOO;uDnS{Xn>WEjD9y;x-2KIBW^ypu$Pe{2{(FrQA&FWBe^t-6t)Sc9g)c-|a zh*F*^53r(+vya*`y%f9<$>qk+T*+R{l}1DLfp9w2-8YcVl=6|sRng(`OJmvG*?jI? JDHS~x_y>?~WQ+g+ delta 1311 zcmYMzOGs5g7{Kw*u2=19nr7vrhni*D!^gFU5^X|SmC(W#5!520FkBQNExHs%L5qrN z6V%3*Zb}NFpa_bPAfm@AiXd8)n;YIx*ExvJKQ=p_ zixYHQ@D#E~oK5a8pc`DqO1zagjtjYeh_(0<-S{)Q@VDgt2fAJ!o%a`gv05g%UmI3N zE~1l86$9IG3GPO&I7H)v!`O^xuo1_Qwc;_l!86R@6mrEon&tQbS709Nv7TLhK8r?r z5KGuUhUvJ_adhEPf56k|$du+f@xCZm+bIlyv`EAG^(ThH}4Ve-<(1YzluGm9U zjr-AqjAV$vAIUie4E@c-yXeL*(44(SQ}hL0@F)7*4EkbK9Mkz7=muHz8yUbl9711g z1f72pSK-xi;@?H*J_DZUE3#%xBUk*Q@xc_wT#Xqtr(I}H2b23F=zKr3rR2ES; zQZ4@7JE*x<8sEh5S\n" "Language-Team: \n" "Language: de_DE\n" @@ -15,22 +15,6 @@ msgstr "" "X-Poedit-Basepath: ../../..\n" "X-Poedit-SourceCharset: UTF-8\n" -#: data/ui/connection-panel.ui:29 -msgid "No service found" -msgstr "Keine Dienste gefunden" - -#: data/ui/connection-panel.ui:43 -msgid "Host" -msgstr "Host" - -#: data/ui/connection-panel.ui:56 -msgid "Port" -msgstr "Port" - -#: data/ui/connection-panel.ui:76 -msgid "Password" -msgstr "Passwort" - #: data/ui/cover-panel.ui:12 data/ui/shortcuts-dialog.ui:88 msgid "Show the cover in fullscreen mode" msgstr "Das Cover im Vollbildmodus anzeigen" @@ -79,15 +63,15 @@ msgstr "Einstellungen und Aktionen" msgid "search library" msgstr "Bibliothek durchsuchen" -#: data/ui/library-panel.ui:263 data/ui/playlist-panel.ui:107 +#: data/ui/library-panel.ui:264 data/ui/playlist-panel.ui:107 msgid "cancel" msgstr "abbrechen" -#: data/ui/library-panel.ui:270 data/ui/library-panel.ui:327 +#: data/ui/library-panel.ui:271 data/ui/library-panel.ui:328 msgid "queue" msgstr "einreihen" -#: data/ui/library-panel.ui:320 data/ui/playlist-panel.ui:163 +#: data/ui/library-panel.ui:321 data/ui/playlist-panel.ui:163 msgid "play" msgstr "abspielen" @@ -99,60 +83,80 @@ msgstr "Die Wiedergabeliste leeren" msgid "remove" msgstr "entfernen" -#: data/ui/server-panel.ui:35 +#: data/ui/server-panel.ui:42 +msgid "Connection" +msgstr "Verbindung" + +#: data/ui/server-panel.ui:55 +msgid "No service found" +msgstr "Keine Dienste gefunden" + +#: data/ui/server-panel.ui:69 +msgid "Host" +msgstr "Host" + +#: data/ui/server-panel.ui:82 +msgid "Port" +msgstr "Port" + +#: data/ui/server-panel.ui:102 +msgid "Password" +msgstr "Passwort" + +#: data/ui/server-panel.ui:117 msgid "Status" msgstr "Status" -#: data/ui/server-panel.ui:49 +#: data/ui/server-panel.ui:132 msgid "File:" msgstr "Datei:" -#: data/ui/server-panel.ui:60 +#: data/ui/server-panel.ui:143 msgid "Audio:" msgstr "Audio:" -#: data/ui/server-panel.ui:71 +#: data/ui/server-panel.ui:154 msgid "Bitrate:" msgstr "Bitrate:" -#: data/ui/server-panel.ui:82 +#: data/ui/server-panel.ui:165 msgid "Error:" msgstr "Fehler:" -#: data/ui/server-panel.ui:92 data/ui/server-panel.ui:106 -#: data/ui/server-panel.ui:120 data/ui/server-panel.ui:134 +#: data/ui/server-panel.ui:175 data/ui/server-panel.ui:189 +#: data/ui/server-panel.ui:203 data/ui/server-panel.ui:217 msgid "none" msgstr "nichts" -#: data/ui/server-panel.ui:154 +#: data/ui/server-panel.ui:237 msgid "Statistics" msgstr "Statistiken" -#: data/ui/server-panel.ui:178 +#: data/ui/server-panel.ui:262 msgid "Artists" msgstr "Künstler" -#: data/ui/server-panel.ui:198 +#: data/ui/server-panel.ui:282 msgid "Albums" msgstr "Alben" -#: data/ui/server-panel.ui:218 +#: data/ui/server-panel.ui:302 msgid "Songs" msgstr "Songs" -#: data/ui/server-panel.ui:238 +#: data/ui/server-panel.ui:322 msgid "Seconds" msgstr "Sekunden" -#: data/ui/server-panel.ui:267 +#: data/ui/server-panel.ui:351 msgid "Seconds played" msgstr "Sekunden gespielt" -#: data/ui/server-panel.ui:287 +#: data/ui/server-panel.ui:371 msgid "Seconds running" msgstr "Sekunden laufend" -#: data/ui/server-panel.ui:303 +#: data/ui/server-panel.ui:387 msgid "Audio Devices" msgstr "Audiogeräte" @@ -208,18 +212,18 @@ msgstr "Cover-Paneel" msgid "Library Panel" msgstr "Bibliothekspaneel" -#: src/connectionpanel.py:51 -msgid "use" -msgstr "verwenden" - #: src/librarypanel.py:291 msgid "Loading albums" msgstr "Alben werden geladen" -#: src/librarypanel.py:379 +#: src/librarypanel.py:370 msgid "Loading images" msgstr "Bilder werden geladen" +#: src/serverpanel.py:77 +msgid "use" +msgstr "verwenden" + #: src/utils.py:50 src/utils.py:67 msgid "{} feat. {}" msgstr "{} mit {}" @@ -228,19 +232,20 @@ msgstr "{} mit {}" msgid "{}:{} minutes" msgstr "{}:{} Minuten" -#: src/window.py:114 +#. Stack +#: src/window.py:106 msgid "Server" msgstr "Server" -#: src/window.py:115 +#: src/window.py:107 msgid "Cover" msgstr "Cover" -#: src/window.py:116 +#: src/window.py:108 msgid "Playlist" msgstr "Wiedergabeliste" -#: src/window.py:117 +#: src/window.py:109 msgid "Library" msgstr "Bibliothek" @@ -275,9 +280,6 @@ msgstr "Bibliothek" #~ msgid "Search Library" #~ msgstr "Bibliothek durchsuchen" -#~ msgid "Connection" -#~ msgstr "Verbindung" - #~ msgid "Keyboard Shortcuts" #~ msgstr "Tastenkombinationen" diff --git a/po/en.mo b/po/en.mo index 96e0ea4d54bdd476340ae5c8a189bcaf9578de95..3edbb64b9e3437e5d6cdcdd67584b3d236809cbf 100644 GIT binary patch delta 1345 zcmYk*TS!zv7{Kw-ysWF0T3fA|X=xX`n7W$Un-oYvK1K8rLDN6?J4V}9u|Y3 zAfg~5s1T%Hgq|YuO^GN810$k{q#%fh{{P)mIP5pSGjq*hH-+*^G=2lF5 z<8?`H0W-+E;WPT+_ozRQw0Jhe(5IN<9eT9Q=r}#4 z?7uJe(&5?m;d;D?X7mUdD~v`yLth+6&vpVm+gbE%%Q**aM8Br(=<^5Ag&s!7Jr?z! zOmku8=aAhFm(c}f(2Vb)89YWac#3BD0zKO)WbQDH?&KHbXtO0haus^7jc_g#at!B5 zH&I#q{x=W}gcCWrWi8Q>y~<_mVm1;f!ptmYX4b7XDD{NNu$FAuOzr=rE7#2Ku*ci! z_wROWBHTtZnOjYC zb808*GP4B(vBAMZ2T%1MAI#Lmr$*X~I`WHCwax8askV{Ru?KnoZ;#Z(NAv#ziB)F* delta 1315 zcmYMzO-PhM7{Ku{UBA{W&C2aV%`)4*OxH>cJOtGt%0u0{BoSQ{f;vctUJ@dxLkrd^ zI$52pixko4ArksH1Ql3B(4~XcA%dt4s{dan9QJvC^NzDK^USjrGH)`;$J&z1f!0H; zAiflZ(1#C-dC-2AgpkHxSc<7s2xVA>^RW&cZ^m-WVl8&yV%&v%!XX~6(~r&{oE=ZX zNjffg3fUtJ$M#kCpfV8?b;G%&@E9&!IQn zho$Tv2I#oZ33TBh|A42_%+E$Ip$8g8Z{{vm;RG(l*XaCdw0Z^f%KxDAE4ij?l(!xo ze^?Ph;zrNtFeki1Cr+Z{pV6!RieB9hw5AoL>p>gQg<8=0?Qy&dU9T5SY`kF zJ!pR=_iyJo1J*P_Gt8qKUq=_d72j{83qC^UJwXpPiEcO@{f?IOH(Js(r*xfW^m|#f zq`hhGKTGE@17>s{`A*13ub^MNf!6dUTGJP3O{bzI)WMoIp!0X22i=LTyC;tCLlZuT zTxK|u(D6irXvV{6CKu2QM$imL(VE^t_6+yXtDHbeI@9Jw&5YsDNjRsTs38^+n+co$ z?(2zU4G&M`=C-xO_L<&nMjmDZkt58^W@fgIS;A^G8xLmNM3_{!FSK=p$#fCk#zw;1 z\n" "Language-Team: \n" "Language: en\n" @@ -16,22 +16,6 @@ msgstr "" "X-Poedit-SearchPath-0: mcg\n" "X-Poedit-SearchPath-1: data/ui\n" -#: data/ui/connection-panel.ui:29 -msgid "No service found" -msgstr "No service found" - -#: data/ui/connection-panel.ui:43 -msgid "Host" -msgstr "Host" - -#: data/ui/connection-panel.ui:56 -msgid "Port" -msgstr "Port" - -#: data/ui/connection-panel.ui:76 -msgid "Password" -msgstr "Password" - #: data/ui/cover-panel.ui:12 data/ui/shortcuts-dialog.ui:88 msgid "Show the cover in fullscreen mode" msgstr "Show the cover in fullscreen mode" @@ -80,15 +64,15 @@ msgstr "Settings and actions" msgid "search library" msgstr "search library" -#: data/ui/library-panel.ui:263 data/ui/playlist-panel.ui:107 +#: data/ui/library-panel.ui:264 data/ui/playlist-panel.ui:107 msgid "cancel" msgstr "cancel" -#: data/ui/library-panel.ui:270 data/ui/library-panel.ui:327 +#: data/ui/library-panel.ui:271 data/ui/library-panel.ui:328 msgid "queue" msgstr "queue" -#: data/ui/library-panel.ui:320 data/ui/playlist-panel.ui:163 +#: data/ui/library-panel.ui:321 data/ui/playlist-panel.ui:163 msgid "play" msgstr "play" @@ -100,60 +84,80 @@ msgstr "Clear the playlist" msgid "remove" msgstr "remove" -#: data/ui/server-panel.ui:35 +#: data/ui/server-panel.ui:42 +msgid "Connection" +msgstr "Connection" + +#: data/ui/server-panel.ui:55 +msgid "No service found" +msgstr "No service found" + +#: data/ui/server-panel.ui:69 +msgid "Host" +msgstr "Host" + +#: data/ui/server-panel.ui:82 +msgid "Port" +msgstr "Port" + +#: data/ui/server-panel.ui:102 +msgid "Password" +msgstr "Password" + +#: data/ui/server-panel.ui:117 msgid "Status" msgstr "Status" -#: data/ui/server-panel.ui:49 +#: data/ui/server-panel.ui:132 msgid "File:" msgstr "File:" -#: data/ui/server-panel.ui:60 +#: data/ui/server-panel.ui:143 msgid "Audio:" msgstr "Audio:" -#: data/ui/server-panel.ui:71 +#: data/ui/server-panel.ui:154 msgid "Bitrate:" msgstr "Bitrate:" -#: data/ui/server-panel.ui:82 +#: data/ui/server-panel.ui:165 msgid "Error:" msgstr "Error:" -#: data/ui/server-panel.ui:92 data/ui/server-panel.ui:106 -#: data/ui/server-panel.ui:120 data/ui/server-panel.ui:134 +#: data/ui/server-panel.ui:175 data/ui/server-panel.ui:189 +#: data/ui/server-panel.ui:203 data/ui/server-panel.ui:217 msgid "none" msgstr "none" -#: data/ui/server-panel.ui:154 +#: data/ui/server-panel.ui:237 msgid "Statistics" msgstr "Statistics" -#: data/ui/server-panel.ui:178 +#: data/ui/server-panel.ui:262 msgid "Artists" msgstr "Artists" -#: data/ui/server-panel.ui:198 +#: data/ui/server-panel.ui:282 msgid "Albums" msgstr "Albums" -#: data/ui/server-panel.ui:218 +#: data/ui/server-panel.ui:302 msgid "Songs" msgstr "Songs" -#: data/ui/server-panel.ui:238 +#: data/ui/server-panel.ui:322 msgid "Seconds" msgstr "Seconds" -#: data/ui/server-panel.ui:267 +#: data/ui/server-panel.ui:351 msgid "Seconds played" msgstr "Seconds" -#: data/ui/server-panel.ui:287 +#: data/ui/server-panel.ui:371 msgid "Seconds running" msgstr "Seconds running" -#: data/ui/server-panel.ui:303 +#: data/ui/server-panel.ui:387 msgid "Audio Devices" msgstr "Audio Devices" @@ -209,18 +213,18 @@ msgstr "Cover Panel" msgid "Library Panel" msgstr "Library Panel" -#: src/connectionpanel.py:51 -msgid "use" -msgstr "use" - #: src/librarypanel.py:291 msgid "Loading albums" msgstr "Loading albums" -#: src/librarypanel.py:379 +#: src/librarypanel.py:370 msgid "Loading images" msgstr "Loading images" +#: src/serverpanel.py:77 +msgid "use" +msgstr "use" + #: src/utils.py:50 src/utils.py:67 msgid "{} feat. {}" msgstr "{} feat. {}" @@ -229,19 +233,20 @@ msgstr "{} feat. {}" msgid "{}:{} minutes" msgstr "{}:{} minutes" -#: src/window.py:114 +#. Stack +#: src/window.py:106 msgid "Server" msgstr "Server" -#: src/window.py:115 +#: src/window.py:107 msgid "Cover" msgstr "Cover" -#: src/window.py:116 +#: src/window.py:108 msgid "Playlist" msgstr "Playlist" -#: src/window.py:117 +#: src/window.py:109 msgid "Library" msgstr "Library" @@ -276,9 +281,6 @@ msgstr "Library" #~ msgid "Search Library" #~ msgstr "Search Library" -#~ msgid "Connection" -#~ msgstr "Connection" - #~ msgid "Keyboard Shortcuts" #~ msgstr "Keyboard Shortcuts" diff --git a/po/mcg.pot b/po/mcg.pot index 451e0a8..e2cffcb 100644 --- a/po/mcg.pot +++ b/po/mcg.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mcg\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-22 14:39+0200\n" +"POT-Creation-Date: 2024-05-24 16:44+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,22 +17,6 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: data/ui/connection-panel.ui:29 -msgid "No service found" -msgstr "" - -#: data/ui/connection-panel.ui:43 -msgid "Host" -msgstr "" - -#: data/ui/connection-panel.ui:56 -msgid "Port" -msgstr "" - -#: data/ui/connection-panel.ui:76 -msgid "Password" -msgstr "" - #: data/ui/cover-panel.ui:12 data/ui/shortcuts-dialog.ui:88 msgid "Show the cover in fullscreen mode" msgstr "" @@ -81,15 +65,15 @@ msgstr "" msgid "search library" msgstr "" -#: data/ui/library-panel.ui:263 data/ui/playlist-panel.ui:107 +#: data/ui/library-panel.ui:264 data/ui/playlist-panel.ui:107 msgid "cancel" msgstr "" -#: data/ui/library-panel.ui:270 data/ui/library-panel.ui:327 +#: data/ui/library-panel.ui:271 data/ui/library-panel.ui:328 msgid "queue" msgstr "" -#: data/ui/library-panel.ui:320 data/ui/playlist-panel.ui:163 +#: data/ui/library-panel.ui:321 data/ui/playlist-panel.ui:163 msgid "play" msgstr "" @@ -101,60 +85,80 @@ msgstr "" msgid "remove" msgstr "" -#: data/ui/server-panel.ui:35 -msgid "Status" +#: data/ui/server-panel.ui:42 +msgid "Connection" msgstr "" -#: data/ui/server-panel.ui:49 -msgid "File:" +#: data/ui/server-panel.ui:55 +msgid "No service found" msgstr "" -#: data/ui/server-panel.ui:60 -msgid "Audio:" -msgstr "" - -#: data/ui/server-panel.ui:71 -msgid "Bitrate:" +#: data/ui/server-panel.ui:69 +msgid "Host" msgstr "" #: data/ui/server-panel.ui:82 -msgid "Error:" +msgid "Port" msgstr "" -#: data/ui/server-panel.ui:92 data/ui/server-panel.ui:106 -#: data/ui/server-panel.ui:120 data/ui/server-panel.ui:134 -msgid "none" +#: data/ui/server-panel.ui:102 +msgid "Password" +msgstr "" + +#: data/ui/server-panel.ui:117 +msgid "Status" +msgstr "" + +#: data/ui/server-panel.ui:132 +msgid "File:" +msgstr "" + +#: data/ui/server-panel.ui:143 +msgid "Audio:" msgstr "" #: data/ui/server-panel.ui:154 +msgid "Bitrate:" +msgstr "" + +#: data/ui/server-panel.ui:165 +msgid "Error:" +msgstr "" + +#: data/ui/server-panel.ui:175 data/ui/server-panel.ui:189 +#: data/ui/server-panel.ui:203 data/ui/server-panel.ui:217 +msgid "none" +msgstr "" + +#: data/ui/server-panel.ui:237 msgid "Statistics" msgstr "" -#: data/ui/server-panel.ui:178 +#: data/ui/server-panel.ui:262 msgid "Artists" msgstr "" -#: data/ui/server-panel.ui:198 +#: data/ui/server-panel.ui:282 msgid "Albums" msgstr "" -#: data/ui/server-panel.ui:218 +#: data/ui/server-panel.ui:302 msgid "Songs" msgstr "" -#: data/ui/server-panel.ui:238 +#: data/ui/server-panel.ui:322 msgid "Seconds" msgstr "" -#: data/ui/server-panel.ui:267 +#: data/ui/server-panel.ui:351 msgid "Seconds played" msgstr "" -#: data/ui/server-panel.ui:287 +#: data/ui/server-panel.ui:371 msgid "Seconds running" msgstr "" -#: data/ui/server-panel.ui:303 +#: data/ui/server-panel.ui:387 msgid "Audio Devices" msgstr "" @@ -210,18 +214,18 @@ msgstr "" msgid "Library Panel" msgstr "" -#: src/connectionpanel.py:51 -msgid "use" -msgstr "" - #: src/librarypanel.py:291 msgid "Loading albums" msgstr "" -#: src/librarypanel.py:379 +#: src/librarypanel.py:370 msgid "Loading images" msgstr "" +#: src/serverpanel.py:77 +msgid "use" +msgstr "" + #: src/utils.py:50 src/utils.py:67 msgid "{} feat. {}" msgstr "" @@ -230,18 +234,19 @@ msgstr "" msgid "{}:{} minutes" msgstr "" -#: src/window.py:114 +#. Stack +#: src/window.py:106 msgid "Server" msgstr "" -#: src/window.py:115 +#: src/window.py:107 msgid "Cover" msgstr "" -#: src/window.py:116 +#: src/window.py:108 msgid "Playlist" msgstr "" -#: src/window.py:117 +#: src/window.py:109 msgid "Library" msgstr "" diff --git a/src/connectionpanel.py b/src/connectionpanel.py deleted file mode 100644 index a4060ed..0000000 --- a/src/connectionpanel.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python3 - -import gi -import locale - -gi.require_version('Gtk', '4.0') -gi.require_version('Adw', '1') -from gi.repository import Gtk, GObject, Adw -from mcg.zeroconf import ZeroconfProvider - - -@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/connection-panel.ui') -class ConnectionPanel(Adw.Bin): - __gtype_name__ = 'McgConnectionPanel' - __gsignals__ = { - 'connection-changed': (GObject.SIGNAL_RUN_FIRST, None, (str, int, str)) - } - - # Widgets - toolbar = Gtk.Template.Child() - zeroconf_list = Gtk.Template.Child() - host_row = Gtk.Template.Child() - port_spinner = Gtk.Template.Child() - password_row = Gtk.Template.Child() - - def __init__(self, **kwargs): - super().__init__(**kwargs) - - # Zeroconf provider - self._zeroconf_provider = ZeroconfProvider() - self._zeroconf_provider.connect_signal( - ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service) - - def on_new_service(self, service): - name, host, port = service - - row_button = Gtk.Button() - row_button.set_label(locale.gettext("use")) - row_button.connect("clicked", self.on_service_selected, host, port) - - row = Adw.ActionRow() - row.set_title(name) - row.set_subtitle("{} ({})".format(host, port)) - row.add_suffix(row_button) - - self.zeroconf_list.insert(row, -1) - - def on_service_selected(self, widget, host, port): - self.set_host(host) - self.set_port(port) - - @Gtk.Template.Callback() - def on_host_entry_apply(self, widget): - self._call_back() - - @Gtk.Template.Callback() - def on_port_spinner_value_changed(self, widget): - self._call_back() - - def set_host(self, host): - self.host_row.set_text(host) - - def get_host(self): - return self.host_row.get_text() - - def set_port(self, port): - self.port_spinner.set_value(port) - - def get_port(self): - return self.port_spinner.get_value_as_int() - - def set_password(self, password): - if password is None: - password = "" - self.password_row.set_text(password) - - def get_password(self): - if self.password_row.get_text() == "": - return None - else: - return self.password_entry.get_text() - - def _call_back(self): - self.emit( - 'connection-changed', - self.get_host(), - self.get_port(), - self.get_password(), - ) diff --git a/src/meson.build b/src/meson.build index d30b1c7..e2db64e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -23,7 +23,6 @@ mcg_sources = [ 'albumheaderbar.py', 'application.py', 'client.py', - 'connectionpanel.py', 'coverpanel.py', 'librarypanel.py', 'playlistpanel.py', diff --git a/src/serverpanel.py b/src/serverpanel.py index f29c7c4..cc765bc 100644 --- a/src/serverpanel.py +++ b/src/serverpanel.py @@ -4,13 +4,19 @@ import gi gi.require_version('Gtk', '4.0') gi.require_version('Adw', '1') +import locale + from gi.repository import Gtk, Adw, GObject +from mcg.zeroconf import ZeroconfProvider + @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/server-panel.ui') class ServerPanel(Adw.Bin): __gtype_name__ = 'McgServerPanel' __gsignals__ = { + 'connection-changed': + (GObject.SIGNAL_RUN_FIRST, None, (str, int, str)), 'change-output-device': (GObject.SIGNAL_RUN_FIRST, None, ( GObject.TYPE_PYOBJECT, bool, @@ -19,6 +25,15 @@ class ServerPanel(Adw.Bin): # Widgets toolbar = Gtk.Template.Child() + connection_status_page = Gtk.Template.Child() + status_page = Gtk.Template.Child() + stats_page = Gtk.Template.Child() + devices_page = Gtk.Template.Child() + # Connection widgets + zeroconf_list = Gtk.Template.Child() + host_row = Gtk.Template.Child() + port_spinner = Gtk.Template.Child() + password_row = Gtk.Template.Child() # Status widgets status_file = Gtk.Template.Child() status_audio = Gtk.Template.Child() @@ -43,12 +58,72 @@ class ServerPanel(Adw.Bin): # Widgets self._none_label = self.status_file.get_label() + # Zeroconf provider + self._zeroconf_provider = ZeroconfProvider() + self._zeroconf_provider.connect_signal( + ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service) + def set_selected(self, selected): self._is_selected = selected def get_toolbar(self): return self.toolbar + def on_new_service(self, service): + name, host, port = service + + row_button = Gtk.Button() + row_button.set_label(locale.gettext("use")) + row_button.connect("clicked", self.on_service_selected, host, port) + + row = Adw.ActionRow() + row.set_title(name) + row.set_subtitle("{} ({})".format(host, port)) + row.add_suffix(row_button) + + self.zeroconf_list.insert(row, -1) + + def on_service_selected(self, widget, host, port): + self.set_host(host) + self.set_port(port) + + @Gtk.Template.Callback() + def on_host_entry_apply(self, widget): + self._call_back() + + @Gtk.Template.Callback() + def on_port_spinner_value_changed(self, widget): + self._call_back() + + def set_connection_sensitive(self, sensitive): + self.connection_status_page.set_sensitive(sensitive) + self.status_page.set_visible(not sensitive) + self.stats_page.set_visible(not sensitive) + self.devices_page.set_visible(not sensitive) + + def set_host(self, host): + self.host_row.set_text(host) + + def get_host(self): + return self.host_row.get_text() + + def set_port(self, port): + self.port_spinner.set_value(port) + + def get_port(self): + return self.port_spinner.get_value_as_int() + + def set_password(self, password): + if password is None: + password = "" + self.password_row.set_text(password) + + def get_password(self): + if self.password_row.get_text() == "": + return None + else: + return self.password_entry.get_text() + def on_output_device_toggled(self, widget, device): self.emit('change-output-device', device, widget.get_active()) @@ -113,3 +188,12 @@ class ServerPanel(Adw.Bin): if id not in device_ids: self.output_devices.remove( self._output_buttons[id].get_parent()) + + def _call_back(self): + self.emit( + 'connection-changed', + self.get_host(), + self.get_port(), + self.get_password(), + ) + diff --git a/src/window.py b/src/window.py index db10c23..ed00409 100644 --- a/src/window.py +++ b/src/window.py @@ -14,7 +14,6 @@ gi.require_version('Adw', '1') from gi.repository import Gtk, Adw, Gdk, GObject, GLib, Gio from . import client from .shortcutsdialog import ShortcutsDialog -from .connectionpanel import ConnectionPanel from .serverpanel import ServerPanel from .coverpanel import CoverPanel from .playlistpanel import PlaylistPanel @@ -52,7 +51,6 @@ class Window(Adw.ApplicationWindow): # Widgets toolbar_view = Gtk.Template.Child() - content_stack = Gtk.Template.Child() panel_stack = Gtk.Template.Child() toolbar_stack = Gtk.Template.Child() # Headerbar @@ -81,8 +79,6 @@ class Window(Adw.ApplicationWindow): # Help/Shortcuts dialog self.set_help_overlay(ShortcutsDialog()) - # Login screen - self._connection_panel = ConnectionPanel() # Server panel self._server_panel = ServerPanel() self._panels.append(self._server_panel) @@ -104,7 +100,6 @@ class Window(Adw.ApplicationWindow): self.on_panel_close_standalone) self._panels.append(self._library_panel) # Stack - self.content_stack.add_child(self._connection_panel) self.panel_stack.add_titled_with_icon(self._server_panel, 'server-panel', locale.gettext("Server"), @@ -128,12 +123,12 @@ class Window(Adw.ApplicationWindow): # Properties self._set_headerbar_sensitive(False, False) - self._connection_panel.set_host( + self._server_panel.set_host( self._settings.get_string(Window.SETTING_HOST)) - self._connection_panel.set_port( - self._settings.get_int(Window.SETTING_PORT)) + self._server_panel.set_port(self._settings.get_int( + Window.SETTING_PORT)) if use_keyring: - self._connection_panel.set_password( + self._server_panel.set_password( keyring.get_password(ZeroconfProvider.KEYRING_SYSTEM, ZeroconfProvider.KEYRING_USERNAME)) self._playlist_panel.set_item_size( @@ -148,8 +143,9 @@ class Window(Adw.ApplicationWindow): # Signals self.connect("notify::maximized", self.on_maximized) self.connect("notify::fullscreened", self.on_fullscreened) - self._connection_panel.connect( - 'connection-changed', self.on_connection_panel_connection_changed) + self._server_panel.connect('connection-changed', + self.on_server_panel_connection_changed) + self.panel_stack.connect('notify::visible-child', self.on_stack_switched) self._server_panel.connect('change-output-device', @@ -219,7 +215,7 @@ class Window(Adw.ApplicationWindow): self.set_default_size(self._state.width, self._state.height) if self._state.get_property(WindowState.PROP_MAXIMIZED): self.maximize() - self.content_stack.set_visible_child(self._connection_panel) + self.panel_stack.set_visible_child(self._server_panel) if self._settings.get_boolean(Window.SETTING_CONNECTED): self._connect() @@ -344,8 +340,7 @@ class Window(Adw.ApplicationWindow): self.toolbar_view.add_top_bar(self.headerbar) self.toolbar_view.remove(panel.get_headerbar_standalone()) - def on_connection_panel_connection_changed(self, widget, host, port, - password): + def on_server_panel_connection_changed(self, widget, host, port, password): self._settings.set_string(Window.SETTING_HOST, host) self._settings.set_int(Window.SETTING_PORT, port) if use_keyring: @@ -471,7 +466,7 @@ class Window(Adw.ApplicationWindow): self._server_panel.set_output_devices(devices) def on_mcg_load_playlist(self, playlist): - self._playlist_panel.set_playlist(self._connection_panel.get_host(), + self._playlist_panel.set_playlist(self._server_panel.get_host(), playlist) def on_mcg_init_albums(self): @@ -481,7 +476,7 @@ class Window(Adw.ApplicationWindow): GObject.idle_add(self._library_panel.load_albums) def on_mcg_load_albums(self, albums): - self._library_panel.set_albums(self._connection_panel.get_host(), + self._library_panel.set_albums(self._server_panel.get_host(), albums) def on_mcg_load_albumart(self, album, data): @@ -514,22 +509,21 @@ class Window(Adw.ApplicationWindow): # Private methods def _connect(self): - self._connection_panel.set_sensitive(False) + self._server_panel.set_connection_sensitive(False) self._set_headerbar_sensitive(False, True) if self._mcg.is_connected(): self._mcg.disconnect() self._settings.set_boolean(Window.SETTING_CONNECTED, False) else: - host = self._connection_panel.get_host() - port = self._connection_panel.get_port() - password = self._connection_panel.get_password() + host = self._server_panel.get_host() + port = self._server_panel.get_port() + password = self._server_panel.get_password() self._mcg.connect(host, port, password) self._settings.set_boolean(Window.SETTING_CONNECTED, True) def _connect_connected(self): self._headerbar_connected() self._set_headerbar_sensitive(True, False) - self.content_stack.set_visible_child(self.panel_stack) self.panel_stack.set_visible_child(self._panels[self._settings.get_int( Window.SETTING_PANEL)]) @@ -539,8 +533,8 @@ class Window(Adw.ApplicationWindow): self._headerbar_disconnected() self._set_headerbar_sensitive(False, False) self._save_visible_panel() - self.content_stack.set_visible_child(self._connection_panel) - self._connection_panel.set_sensitive(True) + self.panel_stack.set_visible_child(self._server_panel) + self._server_panel.set_connection_sensitive(True) def _fullscreen(self, fullscreened_new): if fullscreened_new != self._state.get_property( From 08cd9dbe6593219820fb93e78e7136d74f867629 Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 10 Jan 2026 15:26:49 +0100 Subject: [PATCH 2/7] =?UTF-8?q?Set=20pixel=20size=20for=20=E2=80=9Cstandal?= =?UTF-8?q?one=E2=80=9D=20images=20(close=20#109)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/coverpanel.py | 1 + src/librarypanel.py | 1 + src/playlistpanel.py | 1 + 3 files changed, 3 insertions(+) diff --git a/src/coverpanel.py b/src/coverpanel.py index d9c5d31..312d4da 100644 --- a/src/coverpanel.py +++ b/src/coverpanel.py @@ -251,4 +251,5 @@ class CoverPanel(Gtk.Overlay): return self.cover_image.set_from_pixbuf( pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) + self.cover_image.set_pixel_size(min(width, height)) self.cover_image.show() diff --git a/src/librarypanel.py b/src/librarypanel.py index e2ae1fb..fd56f9f 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -456,6 +456,7 @@ class LibraryPanel(Adw.Bin): # Pixelpuffer auf Oberfläche zeichnen self.standalone_image.set_from_pixbuf( pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) + self.standalone_image.set_pixel_size(min(width, height)) self.standalone_image.show() def _get_default_image(self): diff --git a/src/playlistpanel.py b/src/playlistpanel.py index 34abfee..a9b1d8a 100644 --- a/src/playlistpanel.py +++ b/src/playlistpanel.py @@ -263,6 +263,7 @@ class PlaylistPanel(Adw.Bin): # Pixelpuffer auf Oberfläche zeichnen self.standalone_image.set_from_pixbuf( pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER)) + self.standalone_image.set_pixel_size(min(width, height)) self.standalone_image.show() def _get_default_image(self): From 9311f9974a1610c310fd10b9b7e925c1714596c7 Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 10 Jan 2026 15:42:24 +0100 Subject: [PATCH 3/7] Do not try to convert default icon to GDK pixbuf (close #110) --- src/coverpanel.py | 1 + src/librarypanel.py | 27 +++++++++++++++------------ src/playlistpanel.py | 26 +++++++++++++++----------- src/utils.py | 7 ++++--- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/coverpanel.py b/src/coverpanel.py index 312d4da..b6f3c67 100644 --- a/src/coverpanel.py +++ b/src/coverpanel.py @@ -236,6 +236,7 @@ class CoverPanel(Gtk.Overlay): pixbuf = self._cover_pixbuf # Check pixelbuffer if pixbuf is None: + self.cover_default.set_pixel_size(min(size_width, size_height)/2) return # Skalierungswert für Breite und Höhe ermitteln diff --git a/src/librarypanel.py b/src/librarypanel.py index fd56f9f..83cafe2 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -293,15 +293,13 @@ class LibraryPanel(Adw.Bin): def set_albumart(self, album, data): if album in self._selected_albums: + self._standalone_pixbuf = None if data: # Load image and draw it try: self._standalone_pixbuf = Utils.load_pixbuf(data) except Exception: self._logger.exception("Failed to set albumart") - self._standalone_pixbuf = self._get_default_image() - else: - self._standalone_pixbuf = self._get_default_image() # Show image GObject.idle_add(self._show_image) @@ -335,6 +333,8 @@ class LibraryPanel(Adw.Bin): self._grid_pixbufs.clear() for album_id in albums.keys(): album = albums[album_id] + grid_item = GridItem(album) + pixbuf = None try: pixbuf = Utils.load_thumbnail(cache, self._client, album, size) @@ -344,14 +344,13 @@ class LibraryPanel(Adw.Bin): except Exception as e: self._logger.exception("Failed to load albumart", e) if pixbuf is None: - pixbuf = self._icon_theme.lookup_icon( - Utils.STOCK_ICON_DEFAULT, None, self._item_size, - self._item_size, Gtk.TextDirection.LTR, - Gtk.IconLookupFlags.FORCE_SYMBOLIC) - if pixbuf is not None: + icon = self._get_default_icon(self._item_size, self._item_size) + grid_item.set_icon(icon) + else: self._grid_pixbufs[album.get_id()] = pixbuf - GObject.idle_add(self._library_grid_model.append, - GridItem(album, pixbuf)) + grid_item.set_cover(pixbuf) + + GObject.idle_add(self._library_grid_model.append, grid_item) i += 1 GObject.idle_add(self.progress_bar.set_fraction, i / n) @@ -440,6 +439,9 @@ class LibraryPanel(Adw.Bin): pixbuf = self._standalone_pixbuf # Check pixelbuffer if pixbuf is None: + icon = self._get_default_icon(size_width, size_height) + self.standalone_image.set_from_paintable(icon) + self.standalone_image.set_pixel_size(min(size_width, size_height)/2) return # Skalierungswert für Breite und Höhe ermitteln @@ -459,9 +461,10 @@ class LibraryPanel(Adw.Bin): self.standalone_image.set_pixel_size(min(width, height)) self.standalone_image.show() - def _get_default_image(self): + def _get_default_icon(self, width, height): return self._icon_theme.lookup_icon(Utils.STOCK_ICON_DEFAULT, None, - 512, 512, Gtk.TextDirection.LTR, + width, height, + Gtk.TextDirection.LTR, Gtk.IconLookupFlags.FORCE_SYMBOLIC) def _get_selected_albums(self): diff --git a/src/playlistpanel.py b/src/playlistpanel.py index a9b1d8a..3c18e9c 100644 --- a/src/playlistpanel.py +++ b/src/playlistpanel.py @@ -171,15 +171,13 @@ class PlaylistPanel(Adw.Bin): def set_albumart(self, album, data): if album in self._selected_albums: + self._standalone_pixbuf = None if data: # Load image and draw it try: self._standalone_pixbuf = Utils.load_pixbuf(data) except Exception: self._logger.exception("Failed to set albumart") - self._cover_pixbuf = self._get_default_image() - else: - self._cover_pixbuf = self._get_default_image() # Show image GObject.idle_add(self._show_image) @@ -197,6 +195,8 @@ class PlaylistPanel(Adw.Bin): cache = client.MCGCache(host, size) for album in playlist: + grid_item = GridItem(album) + pixbuf = None # Load albumart thumbnail try: @@ -207,12 +207,12 @@ class PlaylistPanel(Adw.Bin): except Exception: self._logger.exception("Failed to load albumart") if pixbuf is None: - pixbuf = self._icon_theme.lookup_icon( - Utils.STOCK_ICON_DEFAULT, None, self._item_size, - self._item_size, Gtk.TextDirection.LTR, - Gtk.IconLookupFlags.FORCE_SYMBOLIC) - if pixbuf is not None: - self._playlist_grid_model.append(GridItem(album, pixbuf)) + icon = self._get_default_icon(self._item_size, self._item_size) + grid_item.set_icon(icon) + else: + grid_item.set_cover(pixbuf) + + GObject.idle_add(self._playlist_grid_model.append, grid_item) if self._playlist_stop.is_set(): self._playlist_lock.release() @@ -247,6 +247,9 @@ class PlaylistPanel(Adw.Bin): pixbuf = self._standalone_pixbuf # Check pixelbuffer if pixbuf is None: + icon = self._get_default_icon(size_width, size_height) + self.standalone_image.set_from_paintable(icon) + self.standalone_image.set_pixel_size(min(size_width, size_height)/2) return # Skalierungswert für Breite und Höhe ermitteln @@ -266,9 +269,10 @@ class PlaylistPanel(Adw.Bin): self.standalone_image.set_pixel_size(min(width, height)) self.standalone_image.show() - def _get_default_image(self): + def _get_default_icon(self, width, height): return self._icon_theme.lookup_icon(Utils.STOCK_ICON_DEFAULT, None, - 512, 512, Gtk.TextDirection.LTR, + width, height, + Gtk.TextDirection.LTR, Gtk.IconLookupFlags.FORCE_SYMBOLIC) def _get_selected_albums(self): diff --git a/src/utils.py b/src/utils.py index ed8a04f..89b33af 100644 --- a/src/utils.py +++ b/src/utils.py @@ -86,11 +86,9 @@ class GridItem(GObject.GObject): tooltip = GObject.Property(type=str, default=None) cover = GObject.Property(type=Gdk.Paintable, default=None) - def __init__(self, album, cover): + def __init__(self, album): super().__init__() self._album = album - if cover: - self.cover = Gdk.Texture.new_for_pixbuf(cover) self.tooltip = GObject.markup_escape_text("\n".join([ album.get_title(), ', '.join(album.get_dates()), Utils.create_artists_label(album), @@ -103,6 +101,9 @@ class GridItem(GObject.GObject): def set_cover(self, cover): self.cover = Gdk.Texture.new_for_pixbuf(cover) + def set_icon(self, icon): + self.cover = icon + class SearchFilter(Gtk.Filter): From 0a109bc886a0b69824c26ea84358576fbc872d85 Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 10 Jan 2026 16:04:43 +0100 Subject: [PATCH 4/7] Fix handling and logging of thumbnail save failures --- src/librarypanel.py | 4 ++-- src/utils.py | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librarypanel.py b/src/librarypanel.py index 83cafe2..22a8b43 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -341,8 +341,8 @@ class LibraryPanel(Adw.Bin): except client.CommandException: # Exception is handled by client pass - except Exception as e: - self._logger.exception("Failed to load albumart", e) + except Exception: + self._logger.exception("Failed to load albumart") if pixbuf is None: icon = self._get_default_icon(self._item_size, self._item_size) grid_item.set_icon(icon) diff --git a/src/utils.py b/src/utils.py index 89b33af..4b58fb9 100644 --- a/src/utils.py +++ b/src/utils.py @@ -3,6 +3,7 @@ import gi import hashlib import locale +import logging import os gi.require_version('Gtk', '4.0') @@ -37,7 +38,12 @@ class Utils: if pixbuf is not None: pixbuf = pixbuf.scale_simple(size, size, GdkPixbuf.InterpType.HYPER) - pixbuf.savev(cache_url, 'jpeg', [], []) + try: + pixbuf.savev(cache_url, 'jpeg', [], []) + except Exception as e: + logger = logging.getLogger(__name__) + logger.warning("Failed to save thumbnail for album\"%s\": " + "%s", album.get_title(), e) return pixbuf @staticmethod From 9b29f7b274d8553ade36313b6ff4ed271c35b9b3 Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 10 Jan 2026 16:22:03 +0100 Subject: [PATCH 5/7] Preserve aspect ratio of album covers in grid views (close #111) --- src/librarypanel.py | 12 +++--------- src/playlistpanel.py | 12 +++--------- src/utils.py | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/librarypanel.py b/src/librarypanel.py index 22a8b43..02d8c08 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -444,15 +444,9 @@ class LibraryPanel(Adw.Bin): self.standalone_image.set_pixel_size(min(size_width, size_height)/2) return - # Skalierungswert für Breite und Höhe ermitteln - ratio_w = float(size_width) / float(pixbuf.get_width()) - ratio_h = float(size_height) / float(pixbuf.get_height()) - # Kleineren beider Skalierungswerte nehmen, nicht Hochskalieren - ratio = min(ratio_w, ratio_h) - ratio = min(ratio, 1) - # Neue Breite und Höhe berechnen - width = int(math.floor(pixbuf.get_width() * ratio)) - height = int(math.floor(pixbuf.get_height() * ratio)) + (width, height) = Utils.calculate_size(pixbuf.get_width(), + pixbuf.get_height(), size_width, + size_height) if width <= 0 or height <= 0: return # Pixelpuffer auf Oberfläche zeichnen diff --git a/src/playlistpanel.py b/src/playlistpanel.py index 3c18e9c..9f59e93 100644 --- a/src/playlistpanel.py +++ b/src/playlistpanel.py @@ -252,15 +252,9 @@ class PlaylistPanel(Adw.Bin): self.standalone_image.set_pixel_size(min(size_width, size_height)/2) return - # Skalierungswert für Breite und Höhe ermitteln - ratio_w = float(size_width) / float(pixbuf.get_width()) - ratio_h = float(size_height) / float(pixbuf.get_height()) - # Kleineren beider Skalierungswerte nehmen, nicht Hochskalieren - ratio = min(ratio_w, ratio_h) - ratio = min(ratio, 1) - # Neue Breite und Höhe berechnen - width = int(math.floor(pixbuf.get_width() * ratio)) - height = int(math.floor(pixbuf.get_height() * ratio)) + (width, height) = Utils.calculate_size(pixbuf.get_width(), + pixbuf.get_height(), size_width, + size_height) if width <= 0 or height <= 0: return # Pixelpuffer auf Oberfläche zeichnen diff --git a/src/utils.py b/src/utils.py index 4b58fb9..544e415 100644 --- a/src/utils.py +++ b/src/utils.py @@ -2,6 +2,7 @@ import gi import hashlib +import math import locale import logging import os @@ -36,7 +37,10 @@ class Utils: if albumart: pixbuf = Utils.load_pixbuf(albumart) if pixbuf is not None: - pixbuf = pixbuf.scale_simple(size, size, + (width, height) = Utils.calculate_size(pixbuf.get_width(), + pixbuf.get_height(), + size, size) + pixbuf = pixbuf.scale_simple(width, height, GdkPixbuf.InterpType.HYPER) try: pixbuf.savev(cache_url, 'jpeg', [], []) @@ -78,6 +82,19 @@ class Utils: m.update(value.encode('utf-8')) return m.hexdigest() + @staticmethod + def calculate_size(src_width, src_height, dest_width, dest_height): + ratio_w = float(dest_width) / float(src_width) + ratio_h = float(dest_height) / float(src_height) + ratio = min(min(ratio_w, ratio_h), 1) + if ratio == 1: + return (src_width, src_height) + + width = int(math.floor(src_width * ratio)) + height = int(math.floor(src_height * ratio)) + + return (width, height) + class SortOrder: ARTIST = 0 From 7d474598e393e2fb4486c1e70b6b1c57cb507321 Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 10 Jan 2026 16:34:13 +0100 Subject: [PATCH 6/7] Center non-square album covers on grid views (close #112) --- data/ui/library-panel.ui | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/ui/library-panel.ui b/data/ui/library-panel.ui index b5512e3..b835e3f 100644 --- a/data/ui/library-panel.ui +++ b/data/ui/library-panel.ui @@ -221,10 +221,14 @@ vertical + true + true contain false + true + true GtkListItem From 345e7697ff99192f98790e74344a2dd5b01ca90e Mon Sep 17 00:00:00 2001 From: Olli Date: Sat, 10 Jan 2026 16:35:46 +0100 Subject: [PATCH 7/7] Bump version to 4.0.2 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index a8e88cc..67b6caf 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mcg', - version: '4.0.1', + version: '4.0.2', meson_version: '>= 0.59.0', default_options: [ 'warning_level=2',