From 8be01de949ea04eef9c78ea945c75611e0837156 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Sun, 16 Aug 2026 18:13:00 +0300 Subject: [PATCH 1/9] chore: update legendary --- packaging/requirements-flatpak.in | 2 +- packaging/requirements.in | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/requirements-flatpak.in b/packaging/requirements-flatpak.in index 1d12d96f5..4dd6051f9 100644 --- a/packaging/requirements-flatpak.in +++ b/packaging/requirements-flatpak.in @@ -3,7 +3,7 @@ installer setuptools-scm requests < 3.0 QtAwesome -legendary-gl @ git+https://github.com/RareDevs/legendary@9d32abcdd873b9193b403dc98f3f272cfcc8e897 +legendary-gl @ git+https://github.com/RareDevs/legendary@828850273f47432c086d758cd3391047d6dd8ddf orjson vdf @ git+https://github.com/solsticegamestudios/vdf@f47c683c1330f0fcddec034fd49c26e41acd63f2 pypresence diff --git a/packaging/requirements.in b/packaging/requirements.in index fdf95df7b..f11806691 100644 --- a/packaging/requirements.in +++ b/packaging/requirements.in @@ -4,7 +4,7 @@ setuptools-scm requests < 3.0 PySide6-Essentials >= 6.8.1 QtAwesome -legendary-gl @ https://github.com/RareDevs/legendary/archive/9d32abcdd873b9193b403dc98f3f272cfcc8e897.zip +legendary-gl @ https://github.com/RareDevs/legendary/archive/828850273f47432c086d758cd3391047d6dd8ddf.zip orjson vdf @ https://github.com/solsticegamestudios/vdf/archive/f47c683c1330f0fcddec034fd49c26e41acd63f2.zip pywin32 ; platform_system == "Windows" diff --git a/pyproject.toml b/pyproject.toml index 69c691b15..6616aa992 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "requests < 3.0", "PySide6-Essentials >= 6.8.1", "QtAwesome", - "legendary-gl @ git+https://github.com/RareDevs/legendary@9d32abcdd873b9193b403dc98f3f272cfcc8e897", + "legendary-gl @ git+https://github.com/RareDevs/legendary@828850273f47432c086d758cd3391047d6dd8ddf", "orjson", "vdf @ git+https://github.com/solsticegamestudios/vdf@f47c683c1330f0fcddec034fd49c26e41acd63f2", "pywin32 ; platform_system == 'Windows'", From 414fd61323585fa0e11908a0c637faec83e12b0c Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:24:20 +0300 Subject: [PATCH 2/9] stylesheets: update RareStyle --- .../stylesheets/RareStyle/__init__.py | 566 +++++++++--------- .../stylesheets/RareStyle/stylesheet.py | 11 +- .../stylesheets/RareStyle/stylesheet.qss | 8 +- .../stylesheets/RareStyle/template.qss | 20 +- 4 files changed, 311 insertions(+), 294 deletions(-) diff --git a/rare/resources/stylesheets/RareStyle/__init__.py b/rare/resources/stylesheets/RareStyle/__init__.py index 426e4bbcc..24dd3678f 100644 --- a/rare/resources/stylesheets/RareStyle/__init__.py +++ b/rare/resources/stylesheets/RareStyle/__init__.py @@ -1,283 +1,285 @@ # Resource object code (Python 3) # Created by: object code -# Created by: The Resource Compiler for Qt version 6.10.1 +# Created by: The Resource Compiler for Qt version 6.11.1 # WARNING! All changes made in this file will be lost! from PySide6 import QtCore qt_resource_data = b"\ -\x00\x00\x00\xa9\ +\x00\x00\x00\xaa\ \x00\ -\x00\x00\xe2x\x9c-N\xdb\x0a\x830\x0c}\xf7+B\ -\xf6l\x1b\xab\x952\xac\x0f\xfb\x93M\x9d-\xd4)\xb3\ -X\xd9\xd7\xafV\x0f\x07\x02\xe7\x92\xa4Y\xb7\x11\xcc`\ -G\xe35\xd6J!lv\x08\x8fy\xd7H@\x10\x15\ -Hj\xb0\xbd7Wb\x9f\xdcg\xd5h\xbc_\xee\x9c\ -\x87\x10X(\xd9\xfc\x1d\xb9 \x22\x1e\x17b\x9bAD\ -\xb3<\xbd\x81^\xe3$\x05A!\xc8\xe4\xa5\x14].\ -j&\x81\xf2J\x81(\x98O\xef`\xd1\xc5\xb8\xde\ -\xa4L)\x95I\x97\xcbg\x94\x15\x11I>\x88]\x01\ -\x5c\xed\xfa\x88\x0ez\x8b\xb3\xae\xaf\xa0*z\x0a\xa5\x1b\ - Q\x19\x1e\x95::\x13\xd8!\xfb\x89\xc8\x99\xc8.\ -Ng\xbe\x08/?M\x16/F\x9b\xc6\xf4(\xbb\xa2\ -\xfd\xff\xed~I\xdb3\x9b\ -\x00\x00\x09f\ +\x00\x00\xcex\x9cM\x8d\xc1\x0a\x830\x10D\xef~\xc5\ +\xb2=kv\x93`\xa4\x18\x0f\xfd\x93Rm\x12\xb0U\ +\x9a`\xa4__\x22\x1ezx\xbca\x18\x98>n\x0e\ +\xfc\x14\x9cO\x16\x8dj\x11\xb60\xe5\xdb\xb2[$ \ +0\xaa- \xe40&\x7f.\xf6\xd7\xfc\x8e\x16}J\ +\xebU\x88\x9cs\x93U\xb3|\x9c\x90D$\xe2\xe6p\ +\xa8\x00\x00\xfa\xf5\x9e<\x8c\x16_\xaa\xed\x80%=j\ +V\x06\xa8\x96\xba\x03f>,u\x17\x99\xb9\xf8\x9f\xfa\ +\xec\xca\xa6\xe4\xc3'_\x84g\x98g\x8b\x17\xad\xb4\xd1\ +#\x8a\xa1\xea\xcb\xef\xf0\x03I\xdb3\x9b\ +\x00\x00\x09k\ \x00\ -\x00[\x9fx\x9c\xed\x1cYs\xd38\xf8\xbd\xbf\xc2M\ -\x87\x19\xe8\xd4m\xec\x1c-fx\xa0\x94e\x99Y\x96\ -\xa3\x9d\xe5\x81\xd9\x07\xc7V\x12\x0d\x8eed\x99\xb60\ -\xfb\xdfW\xf2\x15[\x96l\xc7GB\x090\xcd\xe1\xc8\ -\xdf}H\xdf'\xeb\xecX\xb9YB_\x99C\x07(\ -\xf4\xdd\x0c\x08R\x17\xc0\x05\xd8$\xc0V\xe6\x18\xad\x94\ -\x81O\xee\x1d\xe0/\x01 \xa7\xde\xfd\xe0T\xb9z\xa7\ -\xfc\xfd\xeeFyu\xf5\xe6\xe6\xf0\xf0P9>;8\ -8V~\x1c(\xf4\x9f\x85\x1c\x84\x0d\x05/f\x8f\xf5\ -\xd1\xc5\x89\x92\xbc/\xe4F\ -\x18\x86\x1f\x09\xa9w=\x0b\xb2\xf88\xcc\xe2O\xc3\x97\ -\x8a,~\xc1T\xc0^&\xda\x93j\xf5JR\xdb\x1f\ -\xd8\x5c\x81\xcfs\xf6z\xbd4=\xf0|0\x1d\xfc\xdb\ -\x0d\xe3c\xa96^S\xca\xbcKt\xd7+\x1e\xb1\xe8\ -\x0aV>G.QoA\xe4\xea3\xe4\xd89X*\ -A\x1e%\xe9T\x07\xab8\xb3\xb8\xe0\x15\x9d\xb2\xed\x83\ -i\xdc\x80;\xb27\xbc\xc2\xd5\xde\xe8\xf5\x8a\x06\xea}\ -\xe2u\x9ft{\x83\x90\xd3Y`-\xb2\x9a.\xa2\x04\ -Q\x93b\x7f\x89V3\xd4#\xfa\x92\xb8\x1e\xcacB\ -W\xbf\x13:3\x99$\xb2\xb6\x18A3t\xa7z\xc8\ -\x0b\xbcp\x1a\x94!3]|\xef\x83e\x5c{\xd0\xdd\ -\x8ajv\xcf\xea\x15\x0a\xa8R\xf7\x88\xe1\xf7\x18-0\ -\xf0\xfdK\x13\xf7\xee\xf9\xbbf\x97\xddC\xe8\xccD5\ -\x1d\xb8p\x0d\xc5\xa239\x80#\x13\xb70r\x9c\xce\ -\x84P\x9cW\xf2 \x9a\x09A\xb4p\xebb\xe2>\x94\ -L\xdc\x93\x15N\x1a\xf6\xf8\xe2\x9a\x84L\x1aL\xc7#\ -\xfa\x17\xd7\x08\xd3\xdb\x0f\xd3\x9a\xe5\x12}\x03\xb8\x1cJ\ -\xb4P\x1c'\x1ag%\xcfp\xc1g$k\xd3\xf8\xf6\ -\xcd%@\x01\xd9\x18y\xaa\x8dn\x93\x95\x9a\x1f\xcc,\ -\x9a\x98\xa8\x15\xa8\x88.\xde\xa1k\xc4\xa2x\xd6\xa9S\ -\xc4\xd7\xe9\xd2@u\xc0\x9c\xa4\x03x\x1f\x99!B\xd0\ -J2&C\xab\x87|\xc8X\xa7\xab\x13\xe4)a\xd5\ -Ajf\xa2Rw4*D\x93\x1dz\xc1\x86\x9eS\ -c\xd3\xa6\xc3xh\xc2zj\xdape.(\xd3\x01\ -v\x1e\x0f\x8c\xb3u\x91\xde?\xfbH\xd7H\xd7\xec\xfb\ -Y*\xe5S\xff\xdbbP\x90=\x9fE\x1f\x92\x12Z\ -\xf9\xf1\x94\xf9\xf1t\xc4^&\xdd\xcb7\xf0\xd4Y@\ -I\x7f\x88\xb6\xdd\xbbX7p\x9e\x98\xd0\x04D}\xb5\ -\xf8\x08\x135\xf0\xf2FO\xb5\xf4[-\x9b\xa9%\x22\ -I\xa0\x19\xc6LC\xb5\x94D#q\xe7h\xe3FY\ -\xaeN$\x09x\xfd\xe1J\x9d\xbfGv\xd6\xa6\xdc\x13\ -\x92\xec\xb4\xd40\xace\xe0~\x11\x16_%3\x96\x8c\ -\x85\xe9\x8f\xa2\xafQ]\xbe\xb4\x01([\xfd$SC\ -\xc3\xa0\xb8\xd5\xb0\xbaN\xe7.\x04Zf\xbe\xefi(\ -.rA\x04}\x19\xafo\x05\xe8\x04\x85DA$\x88\ -\xe8\xad\xf4\x0d\x9eB:\xf4\xa7\xa1\x90:\xa9T\x80K\ -\x0a\xe5;\xbdc\xa7\x04\xc6qE\x22\xc1\x9f\x82D\x16\ -\x8dy\x0a\x97\xa6k\xb7-<4\xdc\x02Q\x5c\x83\xc9\ -\xb2\xce\x0a\xbaj\x22\x9e\xd10{5&uT\xd2=\ -)\xca\xbe\xe8\xf6q\xa3\x8d\x09\xa8x\x95k\xbf\x89P\ -p\x0e\x22E\x10V\xf1\xf9\x8b\x91\xf3\x95#X\xf3`\ -\xcc!\xf6\x93\x1ab\x8e\xee:\x04\x8a\xee\x8eZ\x0b\x5c\ -\xfb?^\x1d\xe5VV\xad\xb4\xcd\xaf\xbf\xb8^j\xaf\ -\x98\xf2=\xbe>Qq\xe2\xe3\x16\x97\xed\x90\x15\x8b\xac\ -y\x09\xf6\x8c\x8c\x13b\xbf\xd8\xde\x07\xfe\xf22;\xbf\ -\xad[i\xed\xbc\xe04\xe2\xae\xc4\xce6\xe5/\xc7Q\ -\xa2p=\xf4.\x1el\xea\xf3I'2\xac\x97\xef\x11\ -\xbfk\xfd6\xac\x02\xad\x05\xd6\x10@\x86\x82&\xe5\xa3\ -,\x01\x8d\xee\x17G\xf9\x06\x80^.\x81\xf5%S`\ -\xae\x9c\x0e\x7f\xa4\xbaG\x15\xc6\xc6\xdf\x93t\xca\xa9\xf3\ -\xbb6M$\x04\x95\x04P\xd1bnS3\xad\xbd\xe7\ -#\x01\x99\xc2L&\x0a\xeb+\xd2i~\xce\x0b2\xa2\ -|\x90\x5cJx\xcah\xfbW`k\xf2\x88\xcf\xb3\x0f\ -\x9e\xa54\x07\xac\xd3\xf9\xaf\xc3Sf\xd6\xf0\xcb0%\ -\x08\x86\x9b\x97.\xc4\xe1\xa6\x11\x1c\xb1\x8b7\x02%\xf0\ -\xabFp\x04\xb6\xdc\x0c\x8e\xc0~\x1a\x01\x12\xe9\xccb\ -\xf2\xe7\xc1\x14fF\xb5\x8a\x81_\x03\xfay]\x09\x14\ -\xaa\xb6Gt\x22\xb5\xf5\x88N\xa4\xdd>\xd1\x89\x8c\xa0\ -G|\x22[\xa1\x9f\x00\x01x\x05\xd9\xf6\xd2\x0e\x90.\ -Mg\xae\xd62\x9b\xed`\x16Y\xd0v0\x8b\x8ci\ -K\x98Ev\xb5\x1d\xd4\x92\x90]j\xd4\x93G\xf5\xb1\ -Z\x10[N\x95M\xc7\xd8\xf8xZ\xdfg\xd4\xe4\xce\ -z\x91\xaf[D%1\xaf[D%\xd1\xaecD%\ -q\xae[L\x95\x11\xae\x09\xba\x8c\xa5\xd75\x8c\xbeq\ -VF\xb5\x1epV\xc6\xb3>pVF\xb2\x1e\x90\x96\ -\xc7\xb0&\x08\xa3\xa8Uf\xb0\x9fC\xe8\xec\xd7\xe7\x03\ -\x82\x03\x90n5\xca\x15\xd8O'\xf16\xf9x\x1b\xaa\ -a\x10sV\xafQ.\xed\xe8G\xcd\x93FK\x12I\ -\xcf|\xcc\xdd\x19\xf7\xcc\xc3\xc2\x9atPE\x81U\xb0\ -ELR\x0e\xa3\xf7\xb2\x0d`\xd3\x11\x1f\x11\x08$u\ -\xf7\xd0\xec\xab\xb0\xb2f\xd5U\xd3ZX\xa4\xe4\xb4\xd2\ -+\xaek\xf8\x1d\xbc\xc6\xd0\xcb\xfb\xeb\xba?\x19\xabp\ -\xcc/\x97\xc7\xeb\xa5~\xd8Q\x5c\xbbZ\xb1M\xde\xaa\ -\xbf(\x7f\xa6V@\x82\xc1\xcc\xf0\x87\xa0\x90\xad\x15j\ -\xd3I\x7fO\xb4\xc9%\xe9/\x0a~\xaa\xd8\x94\x92\xb7\ -\xd3\xda}\x11C\xf9\xca\x1a\xc6Tr\xcc\xa8)\xab\x8f\ -\xc3\x01\xec\xdf\x9dFEy\xa2\xdc\xd37U;Y_\ -\xd6\xa3\xcb\xf4M\xc9\x5c\xf6\xa3P(\xa0\x8f\x1f\xa3\x09\ -J$O\x0a\xf2\x8c\xb7\xcf\xb4\x13i~\x13T\x95T\ -\xe5{\x0c\x05R\x15\xa9`C\xa9\xeaB\xa1\x0e\xfb\x93\ -)\x1b\xda\xa0\x19Y\xdcgY|f2^:\x84\xe1\ -\xb1\xfa\xc1\xca~\xac.G{\x1b\xab{HB\xda\xcc\ -\x88:\x10\x11\x1b\xda\xac\x19+\xf2\xa5R\xfe%\xa76\ -\x08\x14\xd6\x86\xa0L\x18hK\x0d\x93\x8d8gVG\ -\x101cbh\x15\xf9\xa0DcuRz\xcd\xe4\xc2\ -\xf7\xecJ\xd4\xd2\x0a\xabL?\x1cJ\xe6z\x5c\xba\xa8\ -\xd1\x1b\xe6}W\x92*\x0a\x9b\xcc\xe5\xe4\xe6\xdc\xbbu\ -\x02\xa610t\xf3a\xde\xcd\x15\xad\xf7d\x11\xf2\xd1\ -J\xa0\x91$$\x12-\x8aI.\xd2\x82\xf4\xdbHT\ -\x17\x0a\xb4\xff\xe4\x1b\xce]\x1a'\x96\xd2 \xb5q`\ -\xed\xc3\xe4:H-\xd14\xee!\xc8\xa8\x91\x11u \ -\xa1\xd0\x88\xda$\xbb\xfa\x93\x8f\x1a\xe9.\xd2W\x1br\ -\xca\xe7K\x9bQ\x13\xcaF\x9ch*\x83\x8d\x9011\ -\xac\xaaTP\xa6\xb1VyP\xae\xbaR\xb5\xb4\xc2)\ -\xd5\x0f[\xc0\x13\x93\x04\xed\x9f\xbd\xac\xf0\xd8]/\xd2\ -F[\xc9\x13\x0897i)\xa4\xa7m\xd1\xf9\xeeN\ -\xc9S\x9e\xc83-H\xeei\x94\x1bF\x0f\x8e_\x9a\ -\x8e\x83\x90\xbb\xa60\x83JxT]\xedM\x11\xbbd\ -5\xf5\x9a\xa3\xb7&t\xa3\x8f\xbd\x9arumFD\ -R\xb9\xffn\x80K\x16\xa7\xb2\xb8\x0a\xd5\xb4\xb8\xe4\x92\ -\xce\xde\xf2{\xd4K**\xcd\x85\x90\xd3\x14\xc5\xa0L\ -d\xda*\xadjT\x04\x8erx\xdd-p%\x89k\ -\xbd\x1d\xf4\x88\xe1\x0e?}\x82\xf6\x02\x90b13\xfb\ -'\x10\xcf\x94\xfe\xe9\xd1\xbb\xd4Ir\xfbxs\xbbI\ -w\x82^\xce}\x8dl%\xdf\x9a\xdb\x05\xb0\xc8&\xae\ -\xa1\x0d\xb6\x10\x11*\xd7\x8a\x22\x8a\x9a\x05\x84\xfaS\xa0\ -,\xaab<\x083\x19\x1f\x0e\x92\x15\xe0(\xef\xa9\x1c\ - \xc9Y\x9f2\x8a\xab\xa7\x85\xb2\x99IrZ\xd5\xd1\ -5\xcd\xee\xd6\xb2\xa0\xc5t\x87C\xd5\xf3t\xf9G\x86\ -\xf2\x86\xfb\x09\x9b\x9e\x07pdi\xb9\xed\xcd\xb5\x0e\x8f\ -(\xf1\xc8\x8e!\x97\xd3\xdc\xce\xe1\xba\x01\x18=\x1f\xf6\ -\x02\x033\x01x\x0d\x08\xa1\x8c\xfa\xd1/\x9b\xed\xe0\xac\ -\xab\xcb*\xac\x9dv\xbf\x8a\x19 }(N\x8c=c\ -\xb4u\xcf\x16\x5c?f\xc7=\x1f\x96D-\xc0?r\ -YxT-\xdd\x93\x9a4\xb4\xd3\xb3\x1f\xa3\x8f/\x11\ -v\x01N\x9a\xf0=\x9f\x17(9v\xe4H\x9f\x8f\xe9\ -\x7f\x99\xb8\x8f\xf4\xa9>\x1d\x8d\xa2\x9f\xcb\x8e\xd78\xd2\ -\xcf\xc7\xfaX\xcf\x1d\xf2\xa1|x1\xf3i8\xb1\xc8\ -\x1b\x02V}\x1ez\xb9E\xe6\xc2\xa3\x85\xf9\xb3\x0e\xd3\ -\xef6\xba}>\x18_\xa4;\x1b\x12\x00\xb3\xd9LH\ -\xa06\xd44M\x97\x12\xa8\xd9\xda\x5c\xd7s\xbba\x14\ -\xfe\xf8\xc0\xc2!\x94\xe9\x99\xb1\xd5#\xd7\x06Y1\xf4\ -\x7f\xe5\xfb\xdfP\ -\x00\x00\x00\xa9\ +\x00[\xf5x\x9c\xed\x5c[o\xdb6\x14~\xcf\xaf`\ +\x13\x0ch\x03+\xb1d\xc7\xe9X\xf4amw\x03\xd6\ +uY\x82\xeda\xd8\x03-\xd16QYT)\xaaI\ +7\xf4\xbf\x0f\xd4]\x14)\xc9\xba\xd8K\xdd\x025\x1c\ +\x9a\xe29\xfc\xce\x85\xe49G\xbc<\x07w\x1b\x12\x80\ +\x15q1 \x01@!\xa7\xc6\x1a{\x98!\x8e\x1d\xb0\ +bt\x0bN\x03\xfe\xc9\xc5\xc1\x06c~\xe1\x7f:\xbd\ +\x00o\xde\x81_\xdf\xdd\x81\xef\xdf\xfc|\xf7\xe4\xc9\x13\ +p~yrr\x0e\xfe=\x01\x00\x00\x9b\xba\x94A\xc0\ +\xd6\xcb\xa7\xd6\xec\xf9\x04\xa4\x1f\xcf^D?/)s\ +03\x0a\xbd\xc0\xb55\x01`aN\x809\xfb6\xed\ +\x85\xec\xf7kFC\xcf)\xf5\x9c\x89\x9e\xb3\xb9\xf8\xb8\ +~\xf6\xe2\xe4\xf3\xc99tH\x80\x96.v\xaa\xd4\xc1\ +\xe2z\x02\xc0\xb5)>\xae\xf5\xd4U\xbdZS\xc7\x0e\ +\xe1\x82\xfcA\xd9\xb8\xf9\x05-\xb1\x9bPN\x86\xbe'\ +\x0e\xdf@0\xf5\x1ftcq\x86\xbc\xc0G\x0c{<\ +\xee\xe2#\xc7!\xde\xba\xf0P\x80]lsB=C\ +\xc7\xca\xb7Br\x8b\xe8\xa3\xc0\x8a\x8c\xc6\x81yz\x8b\ +\xbdP\xc9\x89\x99q\x127GZ\x0eA@]\xe2\x94\ +~`\xc8!a\x00\x81\x95>\x90\xf1\x15\xb5\x88y\x93\ +\x80\xffA\xf0\xfd\xa8tD\x0b\x0d\xb9K<\x0c\xc14\ +\xfe{\xcd\x88#\x1aJ\x18\xcc\xa7\x13\x00\xe6BO\xe6\ +\x02\x83\x08\xb7\x0d\xbd7\x1clS\x86\x22\xf4b\x1c\xb1\ +\x93\x0dT\x07lE.\xedTS\xf4D.\xc7\xccC\ +\x1c\xeb\xe4%\xf1Z\xc0\x12B\xc2\xf1vtD\xb7\x88\ +\xad\x89g0\xb2\xde\xf0d\xe4\xcf'7w\x0c\xe3\xaf\ +\x02\x1dF\xa0)\x96\x87\x15\xa8\xf0H_%:\x90D\ +S0\xf7 \xd2\xcf'7?a\xe4`V\x10^y\ +](\xf5\x800\x88\xfd\xd8\xe8z\xa6X\xc5\xe7\xd1*\ +.V\xa0\xeb\xa6\xad\xccs!\x02\xf1qe>\xeb\xbc\ +\xb4\xfd\xc0\xd0\x16\xff\xb5\x12\x9f\xb7\x1b\xe4\xe3\x97\xa7\x8b\ +\xd3\xbf\x87\x99\xf8\x5c+\x8d\x1f\x19\x0d\xfdW\xf4aT\ +:-7\x08+\xeaq\xe3\x1e\xc7\xa6\xbe\xa4\xaeS\x1a\ +\xcb\xe0\xd4\x87\xc0\xbc\xb0\xf06YY<\xfc\xbdC\xf8\ +1\xa8\xc6\x1d~\xe0G3W\xb2=\x1a\xb9\xbeA\xfc\ +\xa8\xe6zL\xb2\xbd\xa3\xd4\x1d\xcc\xb1V\xa7\x9a\x1d\xa2\ +\x14^\xf3\xf3\xc9\xcdk\xba]\xd2\x11\xc9\xd7\xf8\xf5\x08\ +\x8f+s\x02\xae\xe6\x13p\x95bm\x0b\x86\x96\xf4\xc1\ +\xf0\xa9\x1f\xfa\xd1I\xa5\xc0fv\xf8>\x06\xcd\xb8\xf5\ +\x89\xb7\x17\xd1\x1c~\xaaoh\xb8t\xf1\x11M\xf87\ +F\xd7\x0c\x07\xc1+\xc4F\xb7\xfcCOW<\xc3\xf1\ +\x037\x90K\xd6\x1e\x046\xf68f\xb1\x8a\xdb\x8c\xba\ +\xee` T\xf7\x95\xe6 \xa8b+Cl\xdc\xa7\ +\x9a\x8d{z\xc2\xc9\xdc\x9e\x1c\x5c\xd3\xb0iN\xc0|\ +6\x01\xf3$F\x98=\xfe$\x8bYn\xe8G\x9c\x81\ +\xada<:(\xceS\x89\x8b\x90gt\xe0\x83i\xf8\ +(y|w\x04\xce!t\x18\xf5\x0d\x87\xde\xa7'\xb5\ + \x5c\xda\xd4\xe3\x8c\xba\x06edM<\x98@\xf1b\ +P\xa3H\xda9\xf5\x0d\x17\xafx\xd6A\xb6\x91%\xe5\ +\x9cn5}\x0a\xbc\xfa4 b\xea\x10p\xea\x83(\ +\xea\xb0S\xa8;\xee\x15\x91)v}.\xba^O'\ +\xc0\x5cL\x93\xae\xe9\xd43\xd5&[\xb4\xc6\x10\x84\xcc\ +}z\x0a/\xf3 }p\xf9;b\xf8V\xfc}\x99\ +\xa1|\x11|\x5c\x9fV\xb0\x97W\xd1\xc7$\x84^v\ +\xbc\x10v\xbc\x98\x89\x8f\xab\xe1\xf1\x0d}c\x19r\x9e\ +E!\xbe\xc2Z\x80u\x07\xe3I\xe4/\xeb[\x1b\xc1\ +\x04\x94q#\xf4\xcbjO\xef\xbd\xaf\x82\xd9M0\xb1\ +\x08\x14\xb2\x11\xc6\x9b\x0e\xb1\xa3Xj\xfc\x91:w\xb4\ +s\xaa\xac\x14)\xd2\xb8\xbc\xf1he\xe6?\xe2tr\ +U\x1e\x89Hqc\x0a\xa1\xbd\x09\xbd\xf7\xca\xf0\xabf\ +\xcfR\xd00\xeb\x9bbd\xbe6\x05\xa8;\xff\xa4\x9b\ +C\x08\x91\xe3\x18Q\x0a\xec#f\x9c\xd8\xa8\x9c\xf9\x84\ +\xc0\xa3\x1e\x8eG\xdf$'\x5c\x059E(Q\xe1\xa2\ +c~\x1bmC\xe60\x08\x97\xff\x1b\x0e9\xf5\xb5\x00\ +n(#\xffP\x8f\x1f\x94\xc1\xc4\xafh\x10\xfc_\xb0\ +(v\x1f2\x87\x1b\xe49}C\x0f\x1d\x8b \xaa\xa7\ +0\xdd.kK<#\x85g6-\xb6&\xac\xcej\ +\xf2'U\xec\xabf\x9f\xa4\xda\x04@\xd5V)\x01\xa7\ +\x22!\x19\x88\x96@\x14\xc7\x97\x1bc\xe3\xab'\x90\xcf\ +\x01\xae\x08\x0b\xd2(b\x89\xef6\x0c\xaa\x9e\x8e\x93\x0b\ +R\x01@r>*\x9d\xadzI[>\x81I\xd9\xd4\ +Q)\x95\xb3|c\x92\x92\xe0\x93\x8e\x97\xfd\x88U\xc3\ +\xace\x04G&&\x818.\xb5\xdf\xc2`\xf3\xaax\ +\xf0h\x1bk\x1d<\xe44\x93Z\x12c[\xc8\xcd\x89\ +\x97\xa8\xb4G\xd6%\x0f\x9b\xd9|\x9a\x8b\x8c\x22\xe6G\ +4\xdf\x5c\xbe\x1d\xe3@9`\x1d\x07(p\xd0%\x80\ +Td\xa0\xd3\xf3j/\xdfa\xa0\xd7\x1bl\xbf/\x84\ +\x98\x1b\xb7\xc3\xbf#\x87\xd0\x06e\x93\x9fIs\xe5\x10\ +\x12\xcf!6\xe2\xb4\xc6\x81\xaa\x82\x17\xbb\xaai\xeb\xc2\ +\xact\xc8l\xcct\xa3\x90\xb7h\xb7\xf9%+(@\ +\xf9(g\xa9\x99SA\xda_\xc2\xb4\xae\xbe\x91\xd7\xd9\ +G?\xa5l\x0d\xc8\x97\xf3/gN\x85]\xc3\x173\ +)\x853\xdc=t\xa1v7\x9d\xc6Q\x9bx\xa7\xa1\ +\x14v\xd5i\x1c\x85.w\x1bG\xa1?\x9d\x06R\xc9\ +\xcc\x16\xf8\xcb\xc3TvF\xad\x82\x81\x1fB\xc4p\x1e\ +\x09T\x8avDr*\xb1\x8dHN%\xdd1\xc9\xa9\ +\x94`Dz*]!\x9e\x839f[\x22\x0aL\x07\ + \xbaA\xee\xcah\xa56\xfb\xa1\xac\xd2\xa0\xfdPV\ +)\xd3\x9e(\xab\xf4j?\xa45.\xbbV\xa9\xc5\xd6\ +\xa7-U\x9b0\xdbm\xd2\xe9\x84\x9a\xecO\xdb\xdb\x8c\ +\x91>\xd9\xce\xf3\x0dK\xa8\xc6\xe7\x0dK\xa8\xc6\xdb\x0d\ +L\xa8\xc6\xcf\x0dK\xa9\xd1\xc3u!W\xd0\xf4\xb6\x8a\ +16\xcdF\xaf6\x02\xcdF\x7f6\x06\xcdFO6\ +\x02\xd1z\x1f\xd6\x85`\xec\xb5\xea\x14\xf6\xafht\xf1\ +\xeb\xcbS\xceB\x9c\x15\x1b\x95\x02\xec\x17WI\xa1|\ +R\x88\x0a!G\xcbv\x15\x0c\xda\x9c~\x9c<\xe9\x11\ +r\xab\xd4\x88d\xe9\xear\x8d@\x14X\xd3vj\x08\ +\xb0*\x8a\xc44\xe10k\x12\x95\x80-f\xb2G\xe0\ +\x84\xb7\xad\xa29V\xb0\x8aj5T\xd2Z\x19\xa4\x94\ +\xa42*\xad[\xf2\x0f\xfe\x91\x11\xbfl\xafy~2\ +\x11\xe1\x5c>.G\x0d\xb1\x0f\x8a2\x8a\xb9\xa9U\xd3\ +\xe4\xbd\xf2\x8b\xfa\xb7j\x15,@\xa1\x86\xa5l\x5c\x9a\ +%\xab\xc4\xa6\xd3\xfc\x9e\xaa\xa8+\xcd/*~j(\ +\xc2*\xebi\xeb\xbc\x08\x04\x1fD\xc2\x18\xb1\xb5Pj\ +\xec\xf1\xa7Q\x07\xf1\xef\xc1\x84`:\x01\x9fL\x08\x0c\ +s\x927[q\xb3\x05\x01(4\x07\xb1+T\xf0'\ +\xf71\x15!\x92g\x15<\x93\xf2\x99~\x90\x96\xcb\xa0\ +\x9aP\xd5W\x19*PU\x89`GT-%\xa8\xd3\ +\xf10\x15];$#\xab\x95\x96\xd5\x17\x9b\x93\xa3C\ +\xe4\x1e\x9b\xdf~\x1eG\xebJ\xbc\xf7\xd1\xba\xc7\x04\xd2\ +nJ4\x00D\xa2k\xb7d\xac\xca\x96j\xe7\xaf\xb9\ +\xb7A!\xb0>\x0c\x15\xdc@_n\x046\xea5\xb3\ +\xd9\x83\xa8'\xa6\x1e\xada=\xa8\x91X\x9b%\xbd\xe5\ +\xe2\x22\xe7\xecj\xc4\xd2\x8b\xaaN>\x12Iaz\xd2\ +r\xd1\x227,\xdb\xaef\xa9\xa8\x94\x99\xeb\xd9-\x99\ +w\xef\x05\xd80c3\x9f\x96\xcd\x1c\x98\xa3/\x16\xd1\ +\x8b]\xfb\xcdG\x8b\xe5.\x96W\x1f\ +v\xea\xf7K\xbbq\x13a\xa3^h\x1a\x9d\x8drb\ +\xea\xb1\x9a\x96\x82:\x89\xf5Z\x07\xf5\xa2\xab\x15K/\ +\x9aZ\xf9\x88\x03!=\x06F\xed\xfa\xd1\x8a\xe7\ +\xca\x01\x86S\xdf \xaaC\xa1y\xab\xa9\xdb\xed\xa4w\ +`\x9d\xddb\xc4\xecME3\xb2\xaa\x89\xa6w\xf4\xca\ +\xaf!\x95\x8d\xe1O\x86|\x1f\xb3X{K%\xd3\xad\ +\xae\xa4\xa8\xb1\xf2\x81G\xae\xe7\xb9\x9f\x11\x0f3`\xfc\ +\xce\xd9w\x0c\xa3t\xc0[\xcc9\xf1\xd6A\xfc\xcbn\ +U\xa1me\xd9Du\xd0\x8cZuU\xc9^\xb4S\ +S/(m\xdb\x1b\x0b\xf3W\xf7\xa4w\xceRO\x98\ +d\xbe\xf3~\x95\xd7\xdf\xb2:\xd74I\x9e\xdd(\x19\ +\x7f}M\x99\x87Y\x9a\xd8\x1f\xf9\x16B\xcde&g\ +\xd6j\xbe\x9a\xaftp\x9fY\x0bk1\x9b\xbdh\xbc\ +\xb4\xe3\xcc\xba\x9e[s\xabtu\x08\xb8\xf9n\x19p\ +\x86l\xfe3\xc7\xdb1\xaf\xd2\xdc\xe3\xe4~\x11\x17\x16\ +\xcb7(f\x7f;\xf4\xfe\xe5\xe9\xfcyV-\x91\x0e\ +\xb0\x5c.\x95\x0c\x9aS\xd34--\x83\xa6c\xae\xac\ +\x84nza\xb0|)a\xe5j\xcb\xec&\xda\xe6\x9e\ +\xb9B6t\xfd\x0f#,\xfbO\ +\x00\x00\x00\xab\ \x00\ -\x00\x00\xe2x\x9c-N\xdb\x0a\x830\x0c}\xf7+B\ -\xf6\xdc6\xd6\xd6\xc9\xb0>\xecO\x86:[\xd0)\xb3\ -X\xd9\xd7\xafV\x0f\x07\x02\xe7\x92\xa4^\xb7\x01l\xef\ -\x06\xeb\x0d\x96U\x85\xb0\xb9><\xe7\xdd \x01AT\ - \xa9\xc1u\xde^\x89}\x1a?\xabA\xeb\xfd\xf2\x10\ -\x22\x84\xc0C\xc1\xe7\xef $\x11\x89\xb8\x10\x9b\x0c\x22\ -\xea\xe5\xe5-t\x06'-\x09rI\x96\x15Z\xb6L\ -\x96\x5c\x031U\x81\xcc\xb9>\xa6\xaa\xb6\xc3!H\xd6\ -\xa1BR#GE1J\xd4R\xea\xb1\xabr\xf2\x87\ -\xe9\xd0\x89\xb7\x1bG\x837U\xa8\xbb\xeaP4Y}\ -\xfc\xd2\xfc\x01\x8eL7\x89\ -\x00\x00\x00\xaf\ +\x00\x00\xe2x\x9c-N\xd1\x0a\x830\x0c|\xf7+B\ +\xf6\xdc6\xd6\xe8\xca\xb0>\xecO\x86:[\xd0)\xb3\ +X\xd9\xd7\x8f\xaa\xe1\xc2\xc1]\x8e\x5c\xbdn\x03\xb8\xde\ +\x0f.X\xac\x8cA\xd8|\x1f\x9f\xf3n\x91\x80\xa02\ +&-B\xf4]p\xd7\xc5>\x8d\x9f\xd5\xa2\x0bay\ +(\x15c\x94\xb1\x90\xf3wP\x9a\x88\xd4\xba\x0d\xd8d\ +\x00\x00\xf5\xf2\x0a\x0e:\x8bS\xa9\x09rMN\x14\xa5\ +n\x85\xaed\x09$\xd8\x80\xcee\x99\x98\xcd\x96\x1c\x82\ +\xc3J*\x1c*\xb0\x19\x99H0QKGN\x5c\x91\ +\x13?<\x1e\x9d\xf3\xf6\xe3h\xf1\xc6\x05\xdf\xb9C\xd5\ +du\xea\xd2\xfc\x01\x8eL7\x89\ +\x00\x00\x00\xb4\ \x00\ -\x00\x00\xf8x\x9c-N\xd1\x0e\x83 \x0c|\xf7+\x9a\ -\xee\x19\xa9\x08\x8e,\xe2\xc3\xfed\x99NL\xdc4\x93\ -\x80\xd9\xd7\x0f\xd0\xe6\x92\xa6w\xbdk\xdb\xcd\x8f`\x87\ -i\xb4\xce`\xa35\x82\x9f\x86p_v\x83\x04\x04\x91\ -\x81\xcc\x86\xa9w\xf6\xdc\xd8\xdf\xf3g3h\x9d[o\ -\x9c\x87\x10\xcaP\x97\xcbw\xe4\x82\x88x\x0c\xc4\xae\x80\ -X\xed\xfap\x16z\x83o%\x08*A\x96\xd5J<\ -\x99hJ\x05\xc4\xa4\x06Q\x95*u\xa9}R\x08\xb2\ -\x94X\xc8l\x84M\xc2\xe1\x88\x13;\xb5h\xf29\x8c\ -r\x1a;\x83\x0e\xfc0\x9f?\xea5\xcd\xb3\xc1\x8b\xac\ -\xe5U\xf6\xc8\xbb\xa2M\x1fv\x7f\x82E<)\ -\x00\x00\x00\xb8\ +\x00\x00\xf8x\x9c-\x8e\xcb\x8a\xc30\x0cE\xf7\xfd\x8a\ +\x8bf\xedXu\x94T\x948\x8b\xfe\xc90i\xe3@\ +\xfa\xa01v\x99\xaf/v+\x10\x82s\xf4\x1a\xb64\ +#\x9c\x979DO\xbd*!-\xe7|\xba\xbf<1\ +\x18\xbdjIB^\xa6\x18\xbe\x1d\xaf\xebz\xdb<\x85\ +\x18\x1fGks\xceMn\x9b\xfbs\xb6\x8e\x99\xed\x96\ +f\x1aw\x000<~c\xc0\xe4\xe9\xda9\xc6\xdeq\ +0m\xe7\xfe\x8c\xeb\x9b\x0elD\xe1\xf6MW\xaah\ +*\x86QU\xa1\xa8\x14\xa2\xa1\x88\xcf\x04D\xcd\xd7\x19\ +\xd1T\x97q\xddV\xb1\xa9\xd8\x88\xfeS=\xff\x89\xcb\ +\xb2\xae\x9e~\xa4\x95\x83Ld\xc7\xddP>\x1c\xdf\x82\ +E<)\ +\x00\x00\x00\xbc\ \x00\ -\x00\x00\xf1x\x9c%N]\x0f\x820\x0c|\xf7W4\ -\xf5y\x1f\xdd\x06\x88a<\xf8O\xccTF\x02bt\ -a\xc4_o\x99M\xda\x5c\xaf\x97\xbbv\x9fu\x80x\ -\x1f\x87\x98<\xd6N#\xac\xe3=_\x96\xcd\xa3\x06\x0d\ -\xd6h(l\x1eo)z\xe4\x1da\x9b\xa7\xe7\xc7c\ -L\xe9uV*\xe7,\xb3\x95\xcb{PFk\xad\xd8\ -\x10\xfb\x03pu\xafk\x8ap\xf38;\x02ck\xe9\ -\x9a*\x1a{\x0a\x86\xa4+\xe6\x92\xf9J\xb6@\x0d8\ -\x9a\x04\x11Cj\x83h\xf9\xce-\x8c\x93u\x01\xd6\xb2\ -J\x17\x85$Q4T\xedh\x1f\x8e\x05\x9c@\x0d\xcf\ -/\x96\xe8\x7f=\xc6i\xf2x\x0c!\xa0\xea\x0f\xdd\xfe\ -Z\xff\x03\x96\x01:P\ -\x00\x00\x00\xaf\ +\x00\x00\xf1x\x9c%N\xcbn\xc30\x0c\xbb\xf7+\x04\ +\xf5lY\xb2\x95d.\xe2\x1c\xf6'\x83\xdb\xc5\x01\xd2\ +\x07\x16#.\xf6\xf5C<\x1e\x08\x82 H\x8e\xdb>\ +C\xbe-s.\x11{e\x84}\xb9\xd5\xcf\xe7;\x22\ +\x03\x83w\x0c\xcd\xad\xcb\xb5\xe4\x88\xde1\xc2\xfb\xbe>\ +\xb6\x88\xb9\x94\xd7\xc5\xdaZ+UO\xcf\x9f\xd9:f\ +\xb6\xdb>\xe3t\x02\x00\x18__%\xc35\xe2]\x05\ +\x9c\xefI\x87.;\xff\x91\x9c\x90\xb6r\x12p\x1d\x05\ +\x90\x01TV#\x12@$$\x13H!\x90\x1a\xa7\xd4\ +7\xe1=\x05\xe0\x96 98\x19\xe9\x0eu\x90\x92\x1a\ +\x15\x90\xc1\xa8\xfcb\x9b\xfe\xc7\xf7\xb2\xae\x11\xcf)%\ +\xb4\xd3i<\xaeM\x7f\x96\x01:P\ +\x00\x00\x00\xb3\ \x00\ -\x00\x00\xf8x\x9c-N\xd1\x0e\x83 \x0c|\xdfW4\ -\xdd3PQ\x0cY\xc4\x87\xfd\xc96\x9d\x98\xe84\x93\ -\x80\xd9\xd7\x0f\xd0\xe6\x92\xa6w\xbdk\x9b\xcd\x0f`\xfb\ -q\xb0\xce`\xad5\x82\x1f\xfbp_v\x83\x04\x04\x91\ -\x81\xcc\x86\xb1s\xf6\xdc\xd8\xe7\xe9\xb3\x19\xb4\xce\xad7\ -!B\x08<\x94|\xf9\x0eB\x12\x91\x88\x81\xd8^ \ -V\xb3>\x9c\x85\xce\xe0\xac$A!\xc9\xb2R\xc9\x17\ -\x935W@\xac\xd2 \x0b\xaeR\xaf\xb4O\x0aA\x96\ -\x12\x0b\x99\x8d\xb0I8\x1cqb\xa7\x16M>\x87Q\ -Ncg\xd0\x81\x1f\xe6\xf3G\xbd\xc7i2x\xadt\ -\xd9\xe9'\x8a\xf6\xd2\xa4\x0f\xdb?\x84\xe5<\x5c\ -\x00\x00\x00\xb6\ +\x00\x00\xf8x\x9c-\x8e\xdb\x0a\xc20\x0c\x86\xef}\x8a\ +\x9fx\xdd5\xeb\xba\x11d\xdd\x85o\xa2N\xd7\xc1<\ +\xe0J;|zi5\x10\x02\xdf\x97S\xbf\xc6\x09\xfe\ +:O>8\xeaD\x08q\xbe\xa6\xe3ss\xc4`t\ +\x229\x09i\x1e\x83\xffwl\xf7\xe5\xb1:\xf2!\xbc\ +\x0eZ\xa7\x94\xaa\xd4T\xcf\xf7\xa4\x0d3\xeb5N4\ +\xec\x00\xa0\x7f\x9d\x82\xc7\xe8\xe8\xde\x1aFm\xd8\xab\xa6\ +5\x17e\xba\xaa\x05++0u\xd5\xe6j%f\xc3\ +(*S\x14\x0a+>\x8b\xdf\x04\xac\xa8\xbfSVb\ +Y\xc6e[\xc1\xaa`e\xe5C\xe5\xfc/n\xf3\xb2\ +8\xda[iF9\x93\x1ev}\xfep\xf8\x02\x84\xe5\ +<\x5c\ +\x00\x00\x00\xb9\ \x00\ -\x00\x00\xf0x\x9c-\x8e\xd1\x0e\x820\x0cE\xdf\xf9\x8a\ -\xa6>\xb3\xad\xdb\x001\x8c\x07\xff\xc4Le$ F\ -\x17F\xfcz\xcb\xb4Ion\xda\x93\xdbv\xefu\x80\ -p\x1b\x87\x10\x1d\x1a\xad\x10\xd6\xf1\x96\xce\xcb\xe6P\x81\ -\x02\x9e@\x9e\xa6\xf1\x1a\xc3\x9f\xd8\xe6\xe9\xf1v\x18b\ -|\x9e\xa4L)\x89d\xc4\xf2\x1a\xa4VJI\x0e\xc4\ -\xbe\x00\xae\xeey\x89\x01\xae\x0egK\xd0\xd4\xc26U\ -\xd0\xe6\xe85\x09\x9b\xb3\x05\x81\xaeD\x0b\xd4\x80\xa5\xa9\ -$bK\xad/[\xdes\x97\xda\x8a:\x1bc\x98R\ -\x99\x10Tf\x86\xaa\xdd\xedb\x19\xe0\x03\xd4\xb0~0\ -_\xfe\xd5}\x9c&\x87\x07\xef=\xca\xbe\xe8\xf6\xcf\xfa\ -/WB:\x18\ -\x00\x00\x00\x9a\ +\x00\x00\xf0x\x9c-N\xc1j\xc30\x14\xbb\xf7+\xc4\ +\xdb\xd9/~\xf6K3\x8f8\x87\xfd\xc9p\xbb8\x90\ +\xaee1q\xd9\xd7\x8fx\x13H\xe8 $\x8d\xdb>\ +#_\x979\x97H\xdeY\xc2\xbe\x5c\xeb\xfb\xfd\x19\xc9\ +\xc2\xc2\xbbFB].%\xff'\x9e\xb7\xf5k\x8b\x94\ +Ky\xbcu]\xad\x95\xab\xe7\xfb\xf7\xdc9km\xb7\ +\xed3M'\x00\x18\x1f\x1f%\xe3\x12\xe9\xa6\x82\xe1\xcc\ +:\xf4\xd9\xf9\xd7\xe4\x84\xb5u\xb3\xc0\xf5\x1c \x03T\ +V#\x12 \x12\x92\x09\xac\x08\xac\xc6)\x9f\x9b\xf1\x9e\ +\x03lK\xb0\x1c\x9a\x8c\xf4\x87;DY\x8d\x0ad0\ +*?\xd4\x96\xff\xf0\xb9\xack\xa4\x97\x94\x12u\xd3i\ +<\x9eM\xbfWB:\x18\ +\x00\x00\x00\x9d\ \x00\ -\x00\x00\xcex\x9c5\x8d\xd1\x0a\x830\x0cE\xdf\xfd\x8a\ -\x90=\xd7\xa6VTF\xeb\xc3\xfed\x9b\xce\x16t\xca\ -,V\xf6\xf5\xcb\xa4\x06\x0e9\xb9\x84\xc4\xac\xdb\x00\xae\ -\xf7\x83\x0b\x16k]!l\xbe\x8f\xb7y\xb7H@\xc0\ -\x09\x1ci\xf4]pic\x9f\xc6\xf7j\xd1\x85\xb0\x5c\ -\xa5\x8c1\xe6Q\xe7\xf3g\x90\x05\x11I>\x88m\x06\ -\x5cf\xb9\x07\x07\x9d\xc5IW\x0d\xa8\x82\x9eB\xe9\x1a\ -H\x14%\x8fJ\x1d\x9dY\xd9!\xf9\x89H\x99H.\ -Ng\xbe\x08/?\x8e\x16/e\xa3\xbb\xe6\x81\xb2\xcd\ -\xcc\xffo\xfb\x03L{3\xce\ -\x00\x00\x00\xc9\ +\x00\x00\xcex\x9cM\x8d\xc1\x0a\x830\x10D\xef~\xc5\ +\xb2=kv\x13\xd1P\x8c\x87\xfeI[m\x12\xd0*\ +M0\xd2\xaf/\x11\x0f=<\xde0\x0cL\x176\x0b\ +n\xf4\xd6E\x83\xadj\x106?\xa6\xdb\xb2\x1b$ \ +hU\x93AH~\x88\xee\x5c\xec\xf3\xf4\x0e\x06]\x8c\ +\xebU\x88\x94R\x95T\xb5|\xac\x90D$\xc2f\xb1\ +/\x00\x00\xba\xf5\x1e\x1d\x0c\x06g\xd5h`I\xcf\x92\ +U\x0bT\xcaZ\x033\x1f\x96\xb5\x0e\xcc\x9c\xfdOy\ +vy\x93\xf3\xe1\x93/\xc2\xcbO\x93\xc1K\xad\xd5\xa0\ +\x1f(\xfa\xa2\xcb\xbf\xfd\x0fL{3\xce\ +\x00\x00\x00\xca\ \x00\ -\x00\x01\x0ax\x9c-\x8e\xcd\x8a\xc30\x0c\x84\xef}\x0a\ -\xe1=[\x96d;Y/q\x0e}\x93\xe2\xb6q \ -\xfdak\xea\xb2O\xbfN\xda\x0f$\xc4\xcc fx\ -<'\xc8\xa7y\xca%*+\xa4\xe09\x9f\xea\xfe\xf6\ -\x8a\x8a\x80\xa0)\xb0\xa9u>\x96\xfcI\xbc.\xcb\xf5\ -\x11U.\xe5\xfecL\xad\x15\xab\xc5\xdb\xefd\x84\x88\ -L{\xa8\xc6\x1d4\x86\xfb\xa1d8Fu\x91> \ -\xb1w\x1d\x88\xb3\xe8\xc5g-\xb6\xc7\xb0\xd2'-\x8c\ -\x0eH[A\xa6\x15\xd6\xe21h\xee\xb5\xe3\x85\xf9\xfb\ -\x13\xd4\xcc!\x05t\xbaM{\x84\xddvX\x8b\x01\xa8\ -\xc5\x02\xac>{\x14h\x8b\xc1\xa1\x07\xc7\x9a\xbb\xe6;\ -\xfeS[\xa77\xe7yY\xa2\xfaJ))3\xee\x86\ -\xb5\xf3\xf8\x0f\x89K?\x8a\ +\x00\x01\x0ax\x9c-\x8eKj\xc40\x10D\xf7s\x8a\ +FY\xab\xd5\xddj\xd9Q\xb0\xbc\xc8M\x82fb\x19\ +<\x1fba\x0d9}\xb03\x0f\x0a\x0a\xea-jX\ +\xb7\x09\xcae\x9eJM\xc6\x0b\x19\xd8\xe6K\xfb\xbc?\ +\x93! \xf0r\xc4@\x9b\xcf\xb5\xbc\x8c\xe7u\xb9\xad\ +\xc9\x94Z\x1f\x1f\xce\xb5\xd6\xb0y\xbc\xffLN\x88\xc8\ +\xad\xdbd\xc6\x13\x00\xc0\xf0\xf8\xaa\x05\xce\xc9\x5c\xa5\x8f\ +H\x1c\xb4\x03Q\x8fAB\xb1\xe2{\x8c;}\xb6\xc2\ +\xa8@\xd6\x0b2\xed\xb0\x95\x80\xd1ro\x95\x17\xe6\xf7\ +\x97h\x99c\x8e\xa86\xa2\x82(vG\xf1\x1e#\xd0\ +\xc2\x1ca\xdf9\xa0\x00\x07dP\x0c\xa0l\xb9\xc3\x08\ +\xca\xbf\xe6\xf8\xf4\xcf\xf7\xbc,\xc9\xbc\xe5\x9c\x8d\x1bO\ +\xc3\xfey\xfc\x03\x89K?\x8a\ " qt_resource_name = b"\ @@ -341,26 +343,26 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x1c\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x03\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01\x08\x00\x01\x00\x00\x00\x01\x00\x00\x0c\x14\ -\x00\x00\x01\x94\x0a\x06\xda?\ -\x00\x00\x01B\x00\x01\x00\x00\x00\x01\x00\x00\x0d\x83\ -\x00\x00\x01\x94\x0a\x06\xda@\ -\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01J\ -\x00\x00\x01\x9b\x08\x1d\xe9V\ -\x00\x00\x01|\x00\x01\x00\x00\x00\x01\x00\x00\x0e\xdb\ -\x00\x00\x01\x94\x0a\x06\xda@\ -\x00\x00\x01(\x00\x01\x00\x00\x00\x01\x00\x00\x0c\xd0\ -\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\ -\x00\x00\x00\xa6\x00\x01\x00\x00\x00\x01\x00\x00\x0a\xb4\ -\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\ -\x00\x00\x01b\x00\x01\x00\x00\x00\x01\x00\x00\x0e=\ -\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\ +\x00\x00\x01\x08\x00\x01\x00\x00\x00\x01\x00\x00\x0c%\ +\x00\x00\x01\x9f\xc4$\xe4$\ +\x00\x00\x01B\x00\x01\x00\x00\x00\x01\x00\x00\x0d\x9c\ +\x00\x00\x01\x9f\xc4$\xe4$\ +\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x01O\ +\x00\x00\x01\xa0\x0b\xcfV\xc5\ +\x00\x00\x01|\x00\x01\x00\x00\x00\x01\x00\x00\x0e\xfa\ +\x00\x00\x01\x9f\xc4$\xe4%\ +\x00\x00\x01(\x00\x01\x00\x00\x00\x01\x00\x00\x0c\xe5\ +\x00\x00\x01\x80\xe6\x9c>\xa8\ +\x00\x00\x00\xa6\x00\x01\x00\x00\x00\x01\x00\x00\x0a\xbe\ +\x00\x00\x01\x80\xbe\xdcK\xb0\ +\x00\x00\x01b\x00\x01\x00\x00\x00\x01\x00\x00\x0eY\ +\x00\x00\x01\x80\xe6\x9b\xdd\x00\ \x00\x00\x004\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\ -\x00\x00\x00X\x00\x01\x00\x00\x00\x01\x00\x00\x00\xad\ -\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\ -\x00\x00\x00\xdc\x00\x01\x00\x00\x00\x01\x00\x00\x0ba\ -\x00\x00\x01\x8f\xdd\xb9\xe7\xe2\ +\x00\x00\x01\x80\xe6\x9b\xec\xa0\ +\x00\x00\x00X\x00\x01\x00\x00\x00\x01\x00\x00\x00\xae\ +\x00\x00\x01\x80\xbe\xdcK\xb0\ +\x00\x00\x00\xdc\x00\x01\x00\x00\x00\x01\x00\x00\x0bm\ +\x00\x00\x01\x80\xbe\xdcK\xb0\ " def qInitResources(): diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.py b/rare/resources/stylesheets/RareStyle/stylesheet.py index 679a331b9..928798a83 100644 --- a/rare/resources/stylesheets/RareStyle/stylesheet.py +++ b/rare/resources/stylesheets/RareStyle/stylesheet.py @@ -1,4 +1,5 @@ import os +from pathlib import Path import qstylizer.parser import qstylizer.style @@ -15,13 +16,15 @@ compressAlgo = 'zlib' compressThreshold = 0 +workdir = Path(__file__).parent + def css_name(widget: wrappertype | QObject | type, subwidget: str = ''): return f'#{widget_object_name(widget, "")}{subwidget}' # style = qstylizer.style.StyleSheet() -with open(os.path.join(os.path.dirname(__file__), 'template.qss'), encoding='utf-8') as template: +with workdir.joinpath('template.qss').open('r', encoding='utf-8') as template: style = qstylizer.parser.parse(template.read()) background_color_base = QColor(32, 34, 37) @@ -71,7 +74,7 @@ def css_name(widget: wrappertype | QObject | type, subwidget: str = ''): if __name__ == '__main__': - with open(os.path.join(os.path.dirname(__file__), 'stylesheet.qss'), 'w', encoding='utf-8') as stylesheet: + with workdir.joinpath('stylesheet.qss').open('w', encoding='utf-8') as stylesheet: stylesheet.write(f'/* This file is auto-generated from "{os.path.basename(__file__)}". DO NOT EDIT!!! */\n\n') stylesheet.write(style.toString(recursive=True)) @@ -87,9 +90,9 @@ def css_name(widget: wrappertype | QObject | type, subwidget: str = ''): '--threshold', str(compressThreshold), '--verbose' if verbose else '', - os.path.join(os.path.dirname(__file__), 'stylesheet.qrc'), + workdir.joinpath('stylesheet.qrc').as_posix(), '-o', - os.path.join(os.path.dirname(__file__), '__init__.py'), + workdir.joinpath('__init__.py').as_posix(), ], True, ) diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss index 517ef9691..1e4b2d908 100644 --- a/rare/resources/stylesheets/RareStyle/stylesheet.qss +++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss @@ -270,7 +270,7 @@ QComboBox:!editable:hover { background-color: rgb( 60, 63, 65); width: 14px; subcontrol-position: top right; - border-bottom-width: 1; + border-bottom-width: 1px; image: url(":/stylesheets/RareStyle/sort-up.svg"); } *::down-button { @@ -840,7 +840,11 @@ QTabBar#SideTabBar:disabled { border-color: transparent; border-right-color: rgb( 60, 63, 65); } -QTabBar#SideTabBar::tab { +QTabBar#SideTabBar::tab:left { + margin-top: 3px; + margin-bottom: 3px; +} +QTabBar#SideTabBar::tab:right { margin-top: 3px; margin-bottom: 3px; } diff --git a/rare/resources/stylesheets/RareStyle/template.qss b/rare/resources/stylesheets/RareStyle/template.qss index 52507af54..69345e6df 100644 --- a/rare/resources/stylesheets/RareStyle/template.qss +++ b/rare/resources/stylesheets/RareStyle/template.qss @@ -153,7 +153,7 @@ QComboBox:!editable:hover { } *::up-button { subcontrol-position: top right; /* position at the top right corner */ - border-bottom-width: 1; + border-bottom-width: 1px; image: url(":/stylesheets/RareStyle/sort-up.svg"); } *::down-button { @@ -636,7 +636,8 @@ QTabBar#MainTabBar::tab { border-top-color: transparent; border-bottom-color: rgb( 72, 61, 139); padding: 3px 5px; -}/* +} +/* QTabBar#MainTabBar::tab:top:first, QTabBar#MainTabBar::tab:bottom:first { margin-left: 0px; @@ -646,7 +647,8 @@ QTabBar#MainTabBar::tab:top:last, QTabBar#MainTabBar::tab:bottom:last { margin-right: 0px; border-right: transparent; -}*/ +} +*/ QTabBar#MainTabBar::tab:top:hover { border-top-color: rgb( 72, 61, 139); } @@ -684,10 +686,15 @@ QTabBar#SideTabBar:disabled { border-color: transparent; border-right-color: rgb( 60, 63, 65); } -QTabBar#SideTabBar::tab { +QTabBar#SideTabBar::tab:left, +QTabBar#SideTabBar::tab:right { margin-top: 3px; margin-bottom: 3px; -}/* +/* Trying to fix requirements frame vertical side tab */ +/* padding-top: 12px;*/ +/* padding-bottom: 12px;*/ +} +/* QTabBar#SideTabBar::tab:left:first, QTabBar#SideTabBar::tab:right:first { margin-top: 0px; @@ -697,7 +704,8 @@ QTabBar#SideTabBar::tab:left:last, QTabBar#SideTabBar::tab:right:last { margin-bottom: 0px; border-bottom: transparent; -}*/ +} +*/ QTabBar#SideTabBar::tab:disabled { color: transparent; border-color: transparent; From 74b810fd36c14c719a14082ee9510efad9602386 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Sun, 16 Aug 2026 21:25:04 +0300 Subject: [PATCH 3/9] SideTabBar: add tab orientation option --- rare/components/tabs/library/__init__.py | 2 +- .../tabs/library/details/__init__.py | 8 +-- .../tabs/library/details/details.py | 1 + rare/components/tabs/store/widgets/details.py | 7 ++- rare/widgets/side_tab.py | 52 +++++++++++++++---- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/rare/components/tabs/library/__init__.py b/rare/components/tabs/library/__init__.py index 15bea71ac..6e2d5f401 100644 --- a/rare/components/tabs/library/__init__.py +++ b/rare/components/tabs/library/__init__.py @@ -42,7 +42,7 @@ def __init__(self, settings: RareAppSettings, rcore: RareCore, parent=None): library_page_right_layout.addWidget(self.head_bar) self.details_page = GameDetailsTabs(settings, rcore, self) - self.details_page.back_clicked.connect(self._on_back_clicked) + self.details_page.backClicked.connect(self._on_back_clicked) self.details_page.import_clicked.connect(self.import_clicked) self.addWidget(self.details_page) diff --git a/rare/components/tabs/library/details/__init__.py b/rare/components/tabs/library/details/__init__.py index 1440cca92..6f216f4cc 100644 --- a/rare/components/tabs/library/details/__init__.py +++ b/rare/components/tabs/library/details/__init__.py @@ -1,8 +1,8 @@ import contextlib import platform as pf -from PySide6.QtCore import Qt, Signal -from PySide6.QtGui import QKeyEvent, QShowEvent +from PySide6.QtCore import Signal +from PySide6.QtGui import QShowEvent from PySide6.QtWidgets import QTreeView from rare.models.game import RareGame @@ -87,10 +87,6 @@ def update_game(self, rgame: RareGame): self.setCurrentIndex(self.details_index) - def keyPressEvent(self, a0: QKeyEvent): - if a0.key() == Qt.Key.Key_Escape: - self.back_clicked.emit() - class GameMetadataView(QTreeView, SideTabContents): def __init__(self, parent=None): diff --git a/rare/components/tabs/library/details/details.py b/rare/components/tabs/library/details/details.py index 327ffd00a..8e245c836 100644 --- a/rare/components/tabs/library/details/details.py +++ b/rare/components/tabs/library/details/details.py @@ -129,6 +129,7 @@ def __init__(self, rcore: RareCore, parent=None): # lk: hide unfinished things self.ui.description_field.setVisible(False) self.ui.requirements_frame.setVisible(False) + self.ui.requirements_layout.setContentsMargins(0, 0, 0, 0) @Slot() def __on_install(self): diff --git a/rare/components/tabs/store/widgets/details.py b/rare/components/tabs/store/widgets/details.py index 0391c10f8..0c357ee05 100644 --- a/rare/components/tabs/store/widgets/details.py +++ b/rare/components/tabs/store/widgets/details.py @@ -22,7 +22,7 @@ from rare.utils.misc import qta_icon from rare.widgets.elide_label import ElideLabel from rare.widgets.image_widget import LoadingSpinnerImageWidget -from rare.widgets.side_tab import SideTabContents, SideTabWidget +from rare.widgets.side_tab import SideTabBar, SideTabContents, SideTabWidget logger = getLogger('StoreDetails') @@ -54,8 +54,11 @@ def __init__(self, installed: list, store_api: StoreAPI, parent=None): self.in_wishlist = False self.wishlist = [] - self.requirements_tabs = SideTabWidget(parent=self.ui.requirements_frame) + self.requirements_tabs = SideTabWidget( + orientation=SideTabBar.TabOrientation.Vertical, parent=self.ui.requirements_frame + ) self.requirements_tabs.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + self.ui.requirements_layout.setContentsMargins(0, 0, 0, 0) self.ui.requirements_layout.addWidget(self.requirements_tabs) self.ui.requirements_layout.setAlignment(Qt.AlignmentFlag.AlignBottom) diff --git a/rare/widgets/side_tab.py b/rare/widgets/side_tab.py index 2550bb4f9..4ba1f9622 100644 --- a/rare/widgets/side_tab.py +++ b/rare/widgets/side_tab.py @@ -1,4 +1,5 @@ from abc import abstractmethod +from enum import IntEnum from logging import getLogger from typing import Protocol @@ -7,7 +8,7 @@ Qt, Signal, ) -from PySide6.QtGui import QFontMetrics +from PySide6.QtGui import QFontMetrics, QKeyEvent, QPaintEvent from PySide6.QtWidgets import ( QLabel, QLayout, @@ -28,15 +29,29 @@ class SideTabBar(QTabBar): - def __init__(self, padding: int = -1, parent=None): + class TabOrientation(IntEnum): + Horizontal = 0 + Vertical = 1 + + def __init__( + self, + *, + padding: int = -1, + orientation: TabOrientation = TabOrientation.Horizontal, + parent: QWidget | None = None + ): super(SideTabBar, self).__init__(parent=parent) self.setObjectName(type(self).__name__) self.padding = padding + self.orientation = orientation self.fm = QFontMetrics(self.font()) # NOTE: if we ever implement a QProxyStyle, this is likely to conflict - def tabSizeHint(self, index): + def tabSizeHint(self, index) -> QSize: + if self.orientation == SideTabBar.TabOrientation.Vertical: + return super(SideTabBar, self).tabSizeHint(index) + width = QTabBar.tabSizeHint(self, index).height() if self.padding < 0: width += QTabBar.tabSizeHint(self, index).width() @@ -44,10 +59,13 @@ def tabSizeHint(self, index): width += self.padding return QSize(width, self.fm.height() + 18) - def paintEvent(self, event): + def paintEvent(self, event: QPaintEvent): + if self.orientation == SideTabBar.TabOrientation.Vertical: + super(SideTabBar, self).paintEvent(event) + return + painter = QStylePainter(self) opt = QStyleOptionTab() - for i in range(self.count()): self.initStyleOption(opt, i) painter.save() @@ -55,6 +73,7 @@ def paintEvent(self, event): opt.shape = QTabBar.Shape.RoundedNorth painter.drawControl(QStyle.ControlElement.CE_TabBarTabLabel, opt) painter.restore() + event.setAccepted(True) class SideTabContents: @@ -123,11 +142,18 @@ def setTitle(self, text: str) -> None: class SideTabWidget(QTabWidget): - back_clicked = Signal() + backClicked = Signal() - def __init__(self, show_back: bool = False, padding: int = -1, *, parent: QWidget | None = None): + def __init__( + self, + show_back: bool = False, + *, + padding: int = -1, + orientation: SideTabBar.TabOrientation = SideTabBar.TabOrientation.Horizontal, + parent: QWidget | None = None, + ): super(SideTabWidget, self).__init__(parent=parent) - self.setTabBar(SideTabBar(padding=padding, parent=self)) + self.setTabBar(SideTabBar(padding=padding, orientation=orientation, parent=self)) self.setDocumentMode(True) self.setTabPosition(QTabWidget.TabPosition.West) if show_back: @@ -136,12 +162,16 @@ def __init__(self, show_back: bool = False, padding: int = -1, *, parent: QWidge qta_icon('mdi.keyboard-backspace', 'ei.backward'), self.tr('Back'), ) - self.tabBarClicked.connect(self.back_func) + self.tabBarClicked.connect(self._on_tab_clicked) - def back_func(self, tab): + def _on_tab_clicked(self, tab): # shortcut for tab == 0 if not tab: - self.back_clicked.emit() + self.backClicked.emit() + + def keyPressEvent(self, a0: QKeyEvent): + if a0.key() == Qt.Key.Key_Escape: + self.backClicked.emit() def addTab(self, widget: QWidget | SideTabContentsProtocol, a1: str, title: str = '') -> int: container = SideTabContainer(widget, title, parent=self) From 71296558e535027e47595433c03f17b6d5f0bce2 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:09:12 +0300 Subject: [PATCH 4/9] DlThread: block SIGINT from reaching the DLM --- rare/components/tabs/downloads/thread.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rare/components/tabs/downloads/thread.py b/rare/components/tabs/downloads/thread.py index 4d82d29cd..564784fd8 100644 --- a/rare/components/tabs/downloads/thread.py +++ b/rare/components/tabs/downloads/thread.py @@ -2,6 +2,7 @@ import os import platform import queue +import signal import time from dataclasses import dataclass from enum import IntEnum @@ -74,6 +75,10 @@ def run(self): result.app_title = self.rgame.app_title start_t = time.time() + original_mask: set[int] | None = None + if platform.system() not in {'Windows'}: + # pylint: disable=E1101 + original_mask = signal.pthread_sigmask(signal.SIG_BLOCK, {signal.SIGINT}) try: self.item.download.dlm.logging_queue = cli.logging_queue self.item.download.dlm.proc_debug = self.debug @@ -156,6 +161,9 @@ def run(self): return finally: + if original_mask is not None: + # pylint: disable=E1101 + signal.pthread_sigmask(signal.SIG_SETMASK, original_mask) self._finish(result) def _handle_postinstall(self, postinstall, igame): From 64b95ca058e7de70f5185412bb86e9783a44786f Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 19 Aug 2026 03:07:08 +0300 Subject: [PATCH 5/9] packaging: add ruff and uv-build for flatpak --- packaging/requirements-flatpak.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packaging/requirements-flatpak.in b/packaging/requirements-flatpak.in index 4dd6051f9..5c2dc5bc4 100644 --- a/packaging/requirements-flatpak.in +++ b/packaging/requirements-flatpak.in @@ -1,4 +1,6 @@ +ruff build +uv-build installer setuptools-scm requests < 3.0 From 72f333edeec72e79e28e08f93e82436007d87891 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:20:54 +0300 Subject: [PATCH 6/9] SideTabWidget: add tab orientation option --- rare/components/tabs/store/widgets/details.py | 2 +- rare/widgets/side_tab.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/rare/components/tabs/store/widgets/details.py b/rare/components/tabs/store/widgets/details.py index 0c357ee05..0b4ea5970 100644 --- a/rare/components/tabs/store/widgets/details.py +++ b/rare/components/tabs/store/widgets/details.py @@ -55,7 +55,7 @@ def __init__(self, installed: list, store_api: StoreAPI, parent=None): self.wishlist = [] self.requirements_tabs = SideTabWidget( - orientation=SideTabBar.TabOrientation.Vertical, parent=self.ui.requirements_frame + tab_orientation=SideTabBar.TabOrientation.Vertical, parent=self.ui.requirements_frame ) self.requirements_tabs.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.ui.requirements_layout.setContentsMargins(0, 0, 0, 0) diff --git a/rare/widgets/side_tab.py b/rare/widgets/side_tab.py index 4ba1f9622..9eaa6a751 100644 --- a/rare/widgets/side_tab.py +++ b/rare/widgets/side_tab.py @@ -149,13 +149,14 @@ def __init__( show_back: bool = False, *, padding: int = -1, - orientation: SideTabBar.TabOrientation = SideTabBar.TabOrientation.Horizontal, + tab_position: QTabWidget.TabPosition = QTabWidget.TabPosition.West, + tab_orientation: SideTabBar.TabOrientation = SideTabBar.TabOrientation.Horizontal, parent: QWidget | None = None, ): super(SideTabWidget, self).__init__(parent=parent) - self.setTabBar(SideTabBar(padding=padding, orientation=orientation, parent=self)) + self.setTabBar(SideTabBar(padding=padding, orientation=tab_orientation, parent=self)) + self.setTabPosition(tab_position) self.setDocumentMode(True) - self.setTabPosition(QTabWidget.TabPosition.West) if show_back: super(SideTabWidget, self).addTab( QWidget(self), From b936a1227335228480d58f578624e7e10d561309 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:27:37 +0300 Subject: [PATCH 7/9] chore: fix some typing errors. --- .../tabs/library/widgets/library_widget.py | 13 ++++++++----- rare/widgets/loading_widget.py | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/rare/components/tabs/library/widgets/library_widget.py b/rare/components/tabs/library/widgets/library_widget.py index 7a0eef386..c6afc4a3a 100644 --- a/rare/components/tabs/library/widgets/library_widget.py +++ b/rare/components/tabs/library/widgets/library_widget.py @@ -8,19 +8,19 @@ QPixmap, QShowEvent, ) -from PySide6.QtWidgets import QLabel +from PySide6.QtWidgets import QLabel, QWidget from rare.widgets.image_widget import ImageWidget class ProgressLabel(QLabel): - def __init__(self, parent=None): + def __init__(self, parent: QWidget | None = None): super(ProgressLabel, self).__init__(parent=parent) - if self.parent() is not None: - self.parent().installEventFilter(self) self.setObjectName(type(self).__name__) self.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) self.setFrameStyle(QLabel.Shape.StyledPanel) + if parent is not None: + parent.installEventFilter(self) def __center_on_parent(self): fm = QFontMetrics(self.font()) @@ -29,6 +29,9 @@ def __center_on_parent(self): self.setGeometry(rect) def event(self, e: QEvent) -> bool: + # FIXME: investigate why this happens + if not isinstance(e, QEvent): + return True if e.type() == QEvent.Type.ParentAboutToChange: if self.parent() is not None: self.parent().removeEventFilter(self) @@ -41,7 +44,7 @@ def showEvent(self, a0: QShowEvent) -> None: if a0.spontaneous(): return super().showEvent(a0) self.__center_on_parent() - super().showEvent(a0) + return super().showEvent(a0) def eventFilter(self, a0: QObject, a1: QEvent) -> bool: if a0 is self.parent() and a1.type() == QEvent.Type.Resize: diff --git a/rare/widgets/loading_widget.py b/rare/widgets/loading_widget.py index ebc5f597a..fcad4be58 100644 --- a/rare/widgets/loading_widget.py +++ b/rare/widgets/loading_widget.py @@ -11,8 +11,8 @@ def __init__(self, autostart: bool = False, *, parent: QWidget | None = None): # The animation's exact size is 94x94 self.setFixedSize(96, 96) self.setMovie(QMovie(':/images/loader.webp', parent=self)) - if self.parent() is not None: - self.parent().installEventFilter(self) + if parent is not None: + parent.installEventFilter(self) self.setVisible(autostart) def _center_on_parent(self): From a24f9edb9a5ad042405310010dab2c0bc60adf31 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:28:57 +0300 Subject: [PATCH 8/9] AccountWidget: convert pop-up to a separate tab. The pop-up was nice, but it doesn't work well enough when running Rare in a gamescope session, so just use a full tab. We might find something to fill it with in the future. --- rare/components/tabs/__init__.py | 23 +---------------------- rare/components/tabs/account/__init__.py | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py index 63854a8f5..7db8ac013 100644 --- a/rare/components/tabs/__init__.py +++ b/rare/components/tabs/__init__.py @@ -30,7 +30,6 @@ def __init__(self, settings: RareAppSettings, rcore: RareCore, parent): self.args = rcore.args() self.main_bar = MainTabBar(parent=self) - self.main_bar.installEventFilter(self) self.setTabBar(self.main_bar) # Generate Tabs @@ -67,13 +66,8 @@ def __init__(self, settings: RareAppSettings, rcore: RareCore, parent): # Account Tab self.account_widget = AccountWidget(self.signals, self.core, self) self.account_widget.exit_app.connect(self._on_exit_app) - account_action = QWidgetAction(self) - account_action.setDefaultWidget(self.account_widget) - self.account_menu = QMenu(self) - self.account_menu.addAction(account_action) - self.account_tab = QWidget(self) self.account_index = self.addTab( - self.account_tab, qta_icon('mdi.account-circle', 'fa5s.user'), self.core.lgd.userdata.get('displayName') + self.account_widget, qta_icon('mdi.account-circle', 'fa5s.user'), self.core.lgd.userdata.get('displayName') ) # Open game list on click on Games tab button @@ -89,21 +83,6 @@ def __init__(self, settings: RareAppSettings, rcore: RareCore, parent): self.setCurrentIndex(self.games_index) - def eventFilter(self, w: QObject, e: QEvent) -> bool: - if not isinstance(e, QEvent): - return True - if w is self.main_bar and e.type() == QEvent.Type.MouseButtonPress: - tab_idx = self.main_bar.tabAt(e.pos()) - if tab_idx == self.account_index: - if e.button() == Qt.MouseButton.LeftButton: - origin = QPoint( - self.main_bar.tabRect(tab_idx).bottomRight().x() - self.account_menu.sizeHint().width(), - self.main_bar.tabRect(tab_idx).bottomRight().y(), - ) - self.account_menu.exec(self.mapToGlobal(origin)) - return True - return False - @Slot() def _on_shortcut_activated_games(self): self.setCurrentIndex(self.games_index) diff --git a/rare/components/tabs/account/__init__.py b/rare/components/tabs/account/__init__.py index a3fe30a86..9de5ba123 100644 --- a/rare/components/tabs/account/__init__.py +++ b/rare/components/tabs/account/__init__.py @@ -1,7 +1,7 @@ import webbrowser -from PySide6.QtCore import Signal, Slot -from PySide6.QtWidgets import QLabel, QPushButton, QSizePolicy, QSpacerItem, QVBoxLayout, QWidget +from PySide6.QtCore import QEvent, QObject, Qt, Signal, Slot +from PySide6.QtWidgets import QLabel, QLayout, QPushButton, QSizePolicy, QSpacerItem, QVBoxLayout, QWidget from rare.lgndr.core import LegendaryCore from rare.models.signals import GlobalSignals @@ -13,7 +13,7 @@ class AccountWidget(QWidget): exit_app: Signal = Signal(int) logout: Signal = Signal() - def __init__(self, signals: GlobalSignals, core: LegendaryCore, parent): + def __init__(self, signals: GlobalSignals, core: LegendaryCore, parent: QWidget | None = None): super(AccountWidget, self).__init__(parent=parent) self.signals = signals self.core = core @@ -33,13 +33,17 @@ def __init__(self, signals: GlobalSignals, core: LegendaryCore, parent): self.quit_button = QPushButton(self.tr('Quit'), parent=self) self.quit_button.clicked.connect(self._on_quit) + self.center_widget = QWidget(self) + center_widget = QVBoxLayout(self.center_widget) + center_widget.setSizeConstraint(QVBoxLayout.SizeConstraint.SetFixedSize) + center_widget.addWidget(QLabel(self.tr('Logged in as {}').format(username))) + center_widget.addSpacerItem(QSpacerItem(10, 10, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)) + center_widget.addWidget(self.open_browser) + center_widget.addWidget(self.logout_button) + center_widget.addWidget(self.quit_button) + layout = QVBoxLayout(self) - layout.addWidget(QLabel(self.tr('Logged in as {}').format(username))) - vspacer = QSpacerItem(10, 10, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) - layout.addSpacerItem(vspacer) - layout.addWidget(self.open_browser) - layout.addWidget(self.logout_button) - layout.addWidget(self.quit_button) + layout.addWidget(self.center_widget, alignment=Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop) @Slot() def _on_browser_clicked(self): From c18a07bc525d1b5aa77d0907fa76795a5d3e4a8f Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 19 Aug 2026 22:21:03 +0300 Subject: [PATCH 9/9] chore: fix code issues in static_css --- rare/resources/static_css/stylesheet.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rare/resources/static_css/stylesheet.py b/rare/resources/static_css/stylesheet.py index c618c54c8..c9c6c4fcd 100644 --- a/rare/resources/static_css/stylesheet.py +++ b/rare/resources/static_css/stylesheet.py @@ -1,4 +1,5 @@ import os +from pathlib import Path import qstylizer.style from PySide6.QtCore import QObject @@ -13,6 +14,8 @@ compressAlgo = 'zlib' compressThreshold = 0 +workdir = Path(__file__).parent + def css_name(widget: wrappertype | QObject | type, subwidget: str = ''): return f'#{widget_object_name(widget, "")}{subwidget}' @@ -239,7 +242,7 @@ def css_name(widget: wrappertype | QObject | type, subwidget: str = ''): if __name__ == '__main__': - with open(os.path.join(os.path.dirname(__file__), 'stylesheet.qss'), 'w', encoding='utf-8') as stylesheet: + with workdir.joinpath('stylesheet.qss').open('w', encoding='utf-8') as stylesheet: stylesheet.write(f'/* This file is auto-generated from "{os.path.basename(__file__)}". DO NOT EDIT!!! */\n\n') stylesheet.write(style.toString(recursive=True)) @@ -255,9 +258,9 @@ def css_name(widget: wrappertype | QObject | type, subwidget: str = ''): '--threshold', str(compressThreshold), '--verbose' if verbose else '', - os.path.join(os.path.dirname(__file__), 'stylesheet.qrc'), + workdir.joinpath('stylesheet.qrc').as_posix(), '-o', - os.path.join(os.path.dirname(__file__), '__init__.py'), + workdir.joinpath('__init__.py').as_posix(), ], True, )