From ce9d0b64f23458abd39eb8f9f306eeff642b1316 Mon Sep 17 00:00:00 2001 From: Jeffrey Hsu Date: Sun, 29 Jun 2025 02:27:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=B3=E4=BA=8E=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/3rd/matplotlib.svg | 352 ++++++++++++++++++++++++++++++++++++++ images/3rd/packaging.png | Bin 0 -> 1216 bytes module/about/schema.py | 8 + module/resources.py | 315 +++++++++++++++++++++++++++++++++- resources.qrc | 2 + ui/pyui/about_ui.py | 168 +++++++++++++----- ui/pyui/sub/picker.py | 2 +- 7 files changed, 799 insertions(+), 48 deletions(-) create mode 100644 images/3rd/matplotlib.svg create mode 100644 images/3rd/packaging.png create mode 100644 module/about/schema.py diff --git a/images/3rd/matplotlib.svg b/images/3rd/matplotlib.svg new file mode 100644 index 0000000..853eae0 --- /dev/null +++ b/images/3rd/matplotlib.svg @@ -0,0 +1,352 @@ + + + + + + + + 2022-09-27T22:26:51.030457 + image/svg+xml + + + Matplotlib v3.6.0, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/3rd/packaging.png b/images/3rd/packaging.png new file mode 100644 index 0000000000000000000000000000000000000000..682547caeb9c0432f57d101123987859117b25b4 GIT binary patch literal 1216 zcmV;x1V8(UP) z#}Bc1}Wpg?O&`4DK!NAvoYQ?K+6ye6jGOzxBB=H|Wc zIrlmDyzglOJY*y=0}mQbhz(AN4Niy+PKXUohz(ANjsJ9_8&B=`CAnx3ySzC#~GDpRd?= z;o9laP6*wGz%Q`riyaGIuUDhd)YR0pwzkgC&toJU4(s*$_4Rd96ab`ck$hqxx)x4!l|5`T!>0f`BQi17I{7$;$}Y+1Z1GgS!bS6pF5{E)rZ=Sil_o zy7XA2zrVk@xEP2KpE9S4^(i7v;&*L_zg3gq@^Mre4-pD2tpd6DKfaG#CTuj@mYd>5Rr zz<4s)o&@V7a3=vQdm+3^#>18npU>B7wOH4+wYB;A`5PM>7%wd?#ridy&Dc0Xp^z5J z%ge(d7{?bA5A3_l%uGzfU|CriZeLUgxoMddQiFQ)B+R5m>v#4Xct!C0MR4-EIu_6~+_6_IPBQoNvS06gW=B=0sr?!bRug zMoNbn-NNVdVWFVz=;$bk;K{kY%l?6Tgb=J;ESEpD5EzbZ;{Amwgyn{BPXsfg$UulU_OXHI}1HPI3YGTAvQQ6HaH\xbd\xb9Z\ +7\xaf\x96\xbb\xfdj\xbby2\xd1\xad\x9a4\xcb\xcd|\ +\xbbXm.\x9fL^\x1e.N\xd2\xa4\xd9\x1ff\x9b\ +\xc5l\xbd\xdd,\x9fL6\xdb\xc9\xa7O\x1f\x9d\xfd\xe2\ +\xd9\x1f\xcf\xbf\xfb\xeb7\x9f7\xfbW\x97\xcd7\x7f\xfe\ +\xec\xab/\xcf\x9b\xc9\xc9t\xfa\xbd=\x9fN\x9f}\xf7\ +\xac\xf9\xf6/_4\xba\xd5\xd3\xe9\xe7\x7f\x98\ +?H\xca\xab\xd5\xf2\xf5g\xdb\x9b'\x13\xd5\xa8\xa6#\ +\xf7\xffM\xba\x95\x8e\xada\x94R$\xd8D\xeaIC\ +\xc0\xe6\xecjy\x98-f\x87\x19>7g\xbb\xc5\xc5\ +\xe9\x9f\x9e\xfd\xbe\x17y1\xaf\xbc\xae_\xee\xd6\x85\xd3\ +b>]\xae\x97W\xcb\xcda_\x10\xf7\x8b\x9e\xcey\ +\xec|\xb7\x9c\x1dV\xaf\x96\xf3\xed\xd5\xd5v\xb3/\xd3\ +6\xfb\xc7\xc3H\xac\xf1V5(35\xe6\x04#N\ +\xf6o6\x87\xd9\xcd\x09\xcd#\xc9\x9a\xb3\xf9\xfc\xf4\xfb\ +\xed\xeeEyh\xce\x16\xf3\xd3\xc3\x9b\xebeC\x02\xef\ +\x96\xfb\xed\xcb\xdd|yT\xd8\xc5\xfcjE#\xa7\xdf\ +\x1eV\xeb\xf5\x97W\xb3\xcb\xe5d\xcaL\x80|\xf9\xd4\ +(,\xaa\xf2\x89\x89\xdf\x19sj\xc2\xa9\x87\x13Y\xe5\ +|<\x9b\x0ec\xea\x8c\x8b\xed\xeejvx\xba\x22N\ +\xa4\xd2\xdf\x00U\x19\xd6\x7fQ\x07\x165lw\x1d\xa1\ +\xc8\xff\xbbK\xa8\xad\x7f\xee \xac\x0e\xeb\xe5\xd3\xafg\ +\x87\xeb\xf5\xf6\xb0^\xfd\xd0\xbc\xb2mh\xd5o\x1b\x02\ +\xb2\x07\x92\xab\xfaU\xc1S\xd6\xe9&\xf5\x5c\xa7c\xb6\ +e\x80\x5c\xb8\x0c\x18\xf4v6\xed\xedKv\x9f\x0a\xc3\ +\x9f-\x96\x17\xfb2b\x7fx\xb3^6\xa4\xb0'\x93\ +\xc3\xf2\xe60\x9d\xef\xf7\x93\xa7\xbf\xfe\xe7\xfe\xb0\xdb\xbe\ +X\x9e\xc0K\x97\x7f\xdf\xae6\xa7\xcdn\xfbr\xb3\xf8\ +\xa4\x11\xf4\xf9\xec\xfa\xb4\xf9\xe1\xe5\xe1\xf0\xaf\xb3ia\ +SV\xe99\x9f]6\xab\xc5\x93\xc9\xc5\xea\xf2\xe5n\ +\xf9\xb7\xe2y\x03\xedzv\x98?\xefI\xcd\x19\x9e\x9e\ +7\xa0~\xcd\xde\xfd\xe8\xab\xb1\x9f\x0b\x82\xa2\xcfj\xf8\ +o\xf8\xfa\x1f\x8fh\xc3C\x02Zp\xbd>m6\xd8\ +\xf7\x9f4\xdb\xeb\xd9\x1c\xbep\xda\xa8\xce\x03\xce\xa6\x97\ +B\x8c\xd9\xcdr_\xa5\x90\x92\x99I\xaf[\x16-\xd9\ +6\xa5\xfe\xdfG\xe7\xa3\xc7\xb7\xfd\xfbq\xd8\xc7a\xff\ +\x9da\x9d\xf3'\x95\x5cp\x06\ +\xdd:\x9dcn\xb4\xf6m\xceIY[X\xf8\xd8\x22\ +\x14\xaa\x84/LhuR.\x80\x07\x05C\x9dC2\ +\x8d\xb6\xbeu\xd6*|\xeflkL\xb0)\xc8\x8f\xc4\ +\x83\x87\x88y\x92\x1b\xaf\xc1\x8b\xb3D\xc4BJZ\xe5\ +\x97\xa0n\xa1\x17\x04L\x8f\xa6M>\x05=\x1a\x08\xfe\ +\xd99\x9b\xb3d\x09\x01c\x80\x84q\xbc\xbe\xd3\xad\x8f\ +\xd9\xdb\x91\xb0\xd6\xb4\xd6\x04\xd2#\xc32\xae\xf5\xd6\x06\ +\xedn\xeb \xb4\xd1)\xab\x93\xd4\x86j=\xb8j-\ +\x95\x11Z\xeb\x94\xd1\xb7\xcc`Zm\x8c/s\xaa\x22\ +NT\xab\xdc-\xe32\xad:\x01\x93X\x0b\x95\x1d\xeb\ +`X\x97\x15P\xd4>H(\x14P\x91T\xfc\x0c\x9a\ +?a6\xeb\xa7N\x11l*k^q\x90\x01sY\ +\xb0*+\x8b\x7f\x1b%?c\xe61e\x08\xad\xb1&\ +Y\xc1b]\xe9\x96l\x1e6\x19\x9b\x91\xcd;\x02-\ +|A\xf8G\xf5\x19\xa9\xc7\xc1\xbf\xc6*g_\x94\x0e\ +Z\xbd\xf6\xa8+\xf7\xc6\xbe\x93\xe3\x1e_\x94?\x9f4\ +\xf4x\xc2\xb9\xae\xcd}\xbd\xd3\xa7\xbb!\xb9\x89\xd2b\ +v\xb3\xaa\xa9o\xf8\xfa\xe6\xb0\x9a\xbf\xa8\xc4\x81Jy\ +\xde,\x98\xfc\xd6\xa4HA\xca\xb4\xd1D3P&\xcd\ +|\xbd\xba>\xa1\xf1\xa8\xcaw\xeb_>\xbe\x9e\xcf\x7f\ +P\x17!\xb8\x94\x7fu4aw\xc5\x05\xa0-\x03\xfd\ +\xbd[m\xec\x7f|9\xdb\xd5z\xae\x22\x14\x1f$\x18\ +s\x1c\x8cy\x1706\xc3R\xd6\xc2E\x13\x9c*\x04\ +\xfd\x10\x00\xd9\xe3\x80\xec;\x00\xea>x\x94\xb9\xe6A\ +\xd8\xc6\x1d\x87\xe2\xde\x01J\xb5\xc8C2\x8d?\x8e\xc7\ +\xbf\x03\x9e\xde(\x0ff\xdb\x84\xe3P\xc2\xfb\x98\x86\xf7\ +\xcf\x03\x00\x14\x8f\x03\x8a\xef\xbcmjh{\x00`\xd2\ +q0\xe9\xbd\x82\xda\x076\xcf\xcfd&3\xceLo\ +~*3\xe5c\xb8\xb3i\x83S\xa2\xce\xae\x04\xb2c\ +\xf6\xce\x10\xc5i\xa7QI$d\xed\xacLD\xc9\x89\ +\x9c\x1cm6\xc8\xb9(\x0fL\xb4\xa9dm\x90\xa9\x04\ +\x08\xb6\x89\xb9EF\xf6\xca6Y\x81s\xa2Z!\xa6\ +\xd6\xe5\x14\xa2'\x9a\x8a.\xa1\xd6\x88\xb1\x0d\xc9\xeb\xae\ +\xbcL\xb95A[\xe3\x9b\x18\xda\x145U\x0f)\xb5\ +$F\x8eD\xa3J\xc3\xc6&\xa1\x8e\xb04\xb2\x89\xbe\ +\x8d)\xa8X\x8a\xcb\x84\x9a%dHMd\xeb\xc39!C\xee\xcdN\xed\x0b\x1a#\x0f\x13\xc7\xe8\ +\x5cq0k\xb5\x8d\xb6A+\xe43m\xad\xae\xd8\xec\ +\x9f\xc8\xd9*\xde\x81\xc8`\x99\x11c\x1d\xad\xc9PY\ +\x92\xad\ ++\xe2Je\xc0\x82\x19#\x1e\xaf\xcc\x90\x85\x98\x02\xb3\ +@$@\x8f\xf1\x8f\xc6\x88\x99\x95\x9f\x5c\xa4.>\xb2\ +\x81\x94\x94\xc5\xaf\xb0\xef\x82|0A\xea-]\xa2>\ +\xda\xc4kC\x19M\xc6\xa8\x9e\x10\xa9\x94\x87V\xba\x03\ +,x^\xa6\xf4\x07%\x03\xb6\x87\x03\x18\x87\xe4\x9a\x83\ +\xce\xe4l\x1a!\xdc\xfan\xbai\xb5Cb(gp\ +I\x19\xafIG\xa9\xcdF{\x0a\x0a\x81\xf2\x81\x8d\xe4\ +B\x0e\x1e\xed\xb4\xf2\x8d7\xb0\x96O\xd9\x0fA\x12)\ +:\x18\xdb\xb8\xd4&\x9b\x9c6\xe5\x90'{d\x9f\xd8\ +8\xdf\x06\xacW\x9c\x09\x1e\xed\xac\x0a\xbeq\x16\xf9D\ +\xd9\xd4y\x10\xf2>\xdc\xd4Y:\x911*+\xe4\xe5\ +D\x05\xaf1tJCil\xd8\xa9\xfdC\x97\xc2{\ +\xbc=\x8d\xb12\x17\x86:Z\x90\x91\xb2p\x0c\x94Q\ +0\xce\x11b1\x80'UF\x82y]s\xa4r\x16\ +O\x88\xdcc\xb8\x0d\xaa\x9ayxf\xb5T.B}\ +uA\xa1j\x9a,L\xc0vac\xb1\x05\x19\xa70\ +7\x85G\xe1\x06\xd57\x84\xc3\x08/\xaaP\x85\xcbu\ +\xc7\xbe\xd5\x15\xd9?\x85\xd3J\xbf\x1e\x9e\xbar\xbcG\ +<\x10\x19\xaf\xe0$\x00\x8f\xd7\x15\x88\x85\x94\x02\xb2\x00\ +$0\x8f\xe1\x8f\xc6\xf0L\xc1O\xaeR\x97\x1f[A\ +H+!\xf4\xb8\xef\xc0|0\xf1\xe9-G?\xfa\xe8\ +\xb9\x9c\x86\xaf\x19\xe5\x85\xe7V\x0aJ\xf9dB\xcc\xdd\ ++\x09\xe8\xc7\xe4\xe2.\xa8\xcf\x13\x9d\xab\xc2\xc5\x91\x19\ +\x1d\x9d=#oi\x1dUg@\x1b[\xe7}\xa0\xd2\ +\x06\xde\x19\xb5'\xcdZ|\xb4\xc8\x84pz\xb4\x02Z\ +E\xd3y\x8dq`Q\xe2\x84G\x94\xf7\xa6S<\x0a\ +]\xe4\x8eh\x1a\x0b\xab\x1a$\x8f.\x9c\xc5\x94\x1c6\ +\x8bU-\xeaW[r*\xf2\x04\xb2\x08\x9d\xa3\x83\x97\ +1\xbe;\xf2\xcf\x19\xdb\x22iU\x8e\xd7!hT\xa1\ +T\xca\xd6\x1a\xe5\x1a\xb8\x81\xf7n\xb0\xd8\xf0\xd4\xb58\ +=\xe2\x81\xc8p\x99\x11\xa3\x1d\xad\xc9`Y>\xc6\xca\ +@\x18\xea\x08\xb4\x18\xc0\x93*#f\xcek\x8e\xb4.\ +\xc4c\x91{\x10waUc\x0f\x04\xa1\x1cV\x18+\ +\xb1\xae)\x14N2\xb3!\x84u\xd8dlG\x86*\ +\x8cN\x91\x8e\x9d\x81=D\xbaM\xf5%F+\x1c\xaf\ ++\xc5\xaaCV/\x95\xae;\xf2\xef\xfa\xd8\x9d;\xf4\ +\x98+\x95!\x0bf\x02\xf3xi\x01Z\x08*P\x0b\ +L\x02\xf6X\x03\xa31b&\xf3\x13\xab\xf0\xf2cC\ +\x08i%\x84\x01\xd5]\xa0\x1f0X\xdd:\x9c\xea\xee\ +\x04\xd8{\xbd\x13\xf0U\x89\xf4\xf0{e\xbb3\x94\xe0\ +\xbdIC\xff\x96L\x0ct\xe4\x92Q\x82&:_\x80\ +2[\xe5J\xb0G\x85\x8e&\xdb\x95\x5c\xa1[\xf4\xd7\ +\xc4\x14\x1f,\xba\x89\x9e\x81F\xaa\xc8\x0e\xe5n2\x98\ +\xe5Q\xfa\x16\xa2S:\x10)\x07zAY\x09\xfc\xf2\ +\xe9=,\xf1X)7?\xf6j*\x08\xfb\xb89\xfd\ +\xad\xf6)7\xa1N\x1bx\xd8\xc8d\xdd\xe5\x93\xab\xd5\ +a\xb9;\xfeZ\xab\xb3\x8f\xbbw\xfb\x18J\xca\xd0#\ +\xc5\x93\x10\xa2R\xba6\x1e&\xa1\xe4i,\xbd\xebs\ +\x9e^\x87c/8\x13\xb4w\x8dE\x07\x02\xa3\xfa\xae\ +\xf1G\x1c\xa2\xce\xcbR\x07\x82\x0d\xd6q\xd0\xa6\xa5~\ +\x0c{\xc8\xa2;4\xda\xf4\xd5\x83W*\xa4R\x8c*\ +T\x0bT8\x846xK\xf6s\x06;\xd0j*p\ +\xde\xd7R\xf3\xe5\xc5\x85\xc9\xf7h)\x7f\xcf\x96\x82r\ +3\x1du{\xca\x06*\xa6>\x95\x22 i4{h\ +\xe0\xa8\x8aB\xc42H\x02\x91\xa22\xda\xc6\xc6Xh\ +\x1e\x06\x0b\x14\xeb#\x9dA\xc5\x06\xc1O\xc5\xec\xba\x92\ +\x1d\xed}T\xb0\x0dL\x93\xa8\xd0J\xb6\x1c\xa8d\x0d\ +#\xa7\xf2&\xb9T\xa1\x01=\x7fr\xdd\xed\x08\xaa\xd5\ +\x12\xaa\xe3\xf76\xd1\xc5EHJ\xdd\xa3\x89\xc2=\x9b\ +\x88\xb4m3\xb6\x0d\xbd\xdfOV\xe9\xbed\xc0\x16C\ +\xaa\xe8\x8e\xcb]\x86\x8a#\xd1\x0c\xf2N.\xa1\x0a\xbd\ +\x82R\x86\xa6c\x06\x92/\xa5UhPuw\x05@\ +F\x8ba\xe8\xb4'\xb7\x06\xd60\x98\x8e\xbck\xbd\x83\ +\xd9\x82\xc56B\x16w\xf4\xce*\x98HnAo\xf2\ +\xa3NT\xe7\xbf\xbf\x8d\xe6\xee^m\x14\xef\xd9F\xde\ +\xd3\xe1\xaf+\xc9\x024\x8b\x8cT\x8c\xe4\x11\x98P\xde\ +\x94#\x1a\xa84\x19\x8b\x9d\x00\xa2\xf2Y\xa7\xeeX\xc6\ +b\xd7\xa1\xda\xf2\x96N\xc4\xc0\xa2d\x17\xafa\xd1\xc2\ +\x00\xd6\xb3>\xe4\xae\xbb\xc16\x04\x8f\xb2\xeb\x94G\x9e\ ++\xe5\x82\xa6\x01D\x03't\x9dD\xa3\xab\x11hU\ +\xdf\xdbN&\xc3R\xcb{\xb4S\xbag;\xa1\x96B\ +q\xeb\xfaN\x10\x9d\x22vF\x7f\xdcoS\x8ad?\ +\xd0\xbd\xf3\xe4\xfa\x09AIg\x9f\xbb&1\xba\x88\xca\ +\x816V\x80uBW\x0a\x07\xe4\xb6\x90\xfb\x97BH\ +2t\xce_8\xa4`\xb0\x0b#\xfaxK\x9b\xb0\x14\ +\x8d\xc6\x19p\x8d\xa8\xd0\xe9nL\xdfO'\xb4\xb1\xff\ +A\xd4\x8b\x8b\x8b\x8b8\xbbGK\xe5\xfb.!\x90\xde\ +\xa9\xe5H\xdd\x09F\x0e*h]\x1b\xd4\x88*\x01\xdd\ +\x81\xc9\xa4K\x9d\xba{J\xb0K\xa9',\x9d\xd5\x18\ +\xaa'\xb4\xb5-Z\x91\xf2=6\x12\x1d9w\xa5?\ +\x86Dd\x8d\xf2\xae\x97^\x8c\xc5r\x8a\x03v\xd1\xaa\ +@\xf6B%\x02\xcb\x1b\xdb\x9b3\xd2\x15*P\x11\x0c\ +\xa3G4\xfc\x1fHS\xf5\xad\x8b<.\xb8u\x09\xe9\ +\x9c)\x91r:\xeaa\xba\xb2\x06\xa9R\x0ctO\xd0\ +\x22\xe4\x1b\x07\x07\x05|\x8c\xf3t\xf8\x82\x90\x84\xfe\xd2\ +\xa5\xfe\x92$U\x00\xf0u\xd7\xb8\xd2zzC}\x0a\ +i\xcf\xa5\xae\xccs\xc891\x1d\xbd3\xd4\xf5O\x96\ +^L\x22Q\xa1vW\xd8Z\xb4[J?\xe4\xe8\x8a\ +3\x0a\xc6\x0ck\x87R\xe4)o=\xedQ\xba\x8f\xee\ +B\x7f\xbd\x105\xa5K\xd1\xd3\x1bM\x04aD\xd8@\ +\x89\xd2X\xa4\xbc<\xbe=2\xdc\xef9\x17h{\x1a\ +#\xadL\x18\xe7h=\x09s\x90\x8dQ2\x88#\xf7\ +p\xce\xc5\xd7B1\x95\x8d`]W\x1ci\xbb\xca\xc6\ +\xe2\xf6\xf2\xdf\x01\xc4\xafZ\xbagVIe\x224\xc7\ +\xeb\x095\x97\xce\xb4\xaa\x9fm\x22\x0c%\xacw\xe4n\ +\xcb\xf9\x08e\xf5\x09\x01\x93\xbdGh\x9b]\x8d\x0e\x08\ +\xd8\x05\xd9/\xa5\xb3\x8e<\x9a\xaf\xa2\x9c\x0b\xc4\x95*\ +\x1137\xe9Y\xa3\xb5\xa5\x1f\xb2\xa4\x02\xb4\x00u\xf4\ +\xf6\xc8\xf9x\x04\xcf\x13\xdc\xe4\x1au\xf1[V\x10\xb2\ +J\x04=\xaa#@\xeb\x01\xc1O\x1d\x01\xa0\x1a\xf7\xf1\ +N\xb8qo\x0b6?sV0\xfc|\xa0\xfc\xd7\xff\ +[\x7fGA\x91\xf2\x1b\x0aC%>q\x98\xbc\xf3+\ +\x87\x8f\x11\xeac\x84\xfa\x18\xa1\xfe\x7f\x22\xd4\xc7\x1f\x0f\ +}\x1c\xf6\x01\x87\xddM8\xa8\xeb\xfb_\xc3\x0d9K\ +\xfcn\xef\x8c~\xe1\xf8\xf4\xd1\xbf\x01:\x8f<\x83\ +\x00\x00\x04\xc0\ +\x89\ +PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\ +\x00\x000\x00\x00\x000\x08\x02\x00\x00\x00\xd8`n\xd0\ +\x00\x00\x04\x87IDATx^\xed\x95mL[U\ +\x18\x801\xfe\xf0\xa7\xc6e&\xd3-\xdb\x1c \x0e\xdd\ +\xb2\xa8\xf1+F\x9d3\xfe\xd0%#\x9a\x98\x99\x18\xff\ +\xb0\x1ft2M\x99LZ\x91.\xb4`\x08\x1f]\xc6\ +\xc7\x0f\xb1\xc0\xa0\x85\x01\xbd-0J[\xd6i\xa0\x11\ +R>\x1ci\xd6RF[\xa0@kK\xf9\x10h\xcb\ +G\xf3\xfa\x96S\xaf\xf4\x0e\xbc&\xa6\xdbL\xee\x93\xe6\ +\xe6\xe6\xbd\xef9\xf79\xf7\xbc\xefi\x02&h|GB\x0d\x8f\xea\ +`\xea\x148_\x07{*,\xc8\xe8)\x18BEE\ +Emmm\xbb\x09\xc9\xe5rZ\x08\xc9\xc8\xc8@{\ +\xdc\xa3\xce\xce\xce\x92\x92\x92\xca\xcaJ\x89D\x823\x00\ +\x11\xe2]\x1f&M\x9e\x92\xab\xfe\xd9\xdc\x0fK?\xc2\ +b%,V\xc0\xbc\x14|\xb90y\x12\x1c/\xc1x\ +\x12\xd8\x9e\x00\x9f\x84\x9e\xf4^!\x8a\xa2\xfe\xa5\x10\x8f\ +\xc7\xc3O\xd2\xdb\xdb+\x16\x8b\x83\xc1 F\xfa\xfa\xfa\ +\xfe\x16*\xd4Z\x22M.\xa0\xb2[L\xe0\xbd\x00\x9e\ +\xcf\xc0\xfd)\xcc\x9c\x81\xa9\xf7\xc1\xf9\x06\xd8_\x80\xbb\ +\xfba\xf41\xb0$\xc0\x12EO\xba]\x08\xd7\x9a\x95\ +\x95500\x80\xe5\x8cB\xb8)$N\x0b544\ +\xd0Bsss\x98\xe3\xf1x\xb0\x15\xea\xea\xeaH0\ +Fhx\xca\x9f(\x8c4y\x91\xe67p\x9f\x8d\xd4\ +\xaf\xebC\x98|\x17\x9c\xaf\xc0x2\xd8\x9e\x04\xeb#\ +p'\x01,{!\xbcJ\xc6\xc3\x96\x10\x9f\xcf\xd7j\ +\xb5X\xd7\xb5\xb5\xb5\xf9\xf9\xf9\x1b\x1b\x1b\x18/--\ +\xc5\xfa5\x9b\xcd\xd88B\xa1\x90\x16\xca\xcb\xcb\xc3!\ +\x18\xc7\x17\x13\x0f\xec\xbb\xcc\xccLL\xc3`YY\x19\ +n_T\x08\xb9i\x99\x15R\x83z\xf3$\xcc\xa4E\ +\xebw\xf6\x1cxE\xf0\xfbEp\xf3`\x96\x073\xe7\ +a\xf5W\xda\x06\xb6\x84\xca\xcb\xcbGFF\x9a\x9a\x9a\ +\xb0\x93\xc9\x97G\xb0\xd7\xb0\xf3[ZZpS\xf0\xab\ +TWWc\xb0\xbe\xbe^\xa9T\xe2\x1e\xe1\xde\xd1\x1d\ +\x8e8\x9dN\xcc\xc4U\xb9\xddn\x12a\x9c\xd4\x9b0\ +\xf5\x1e8_\x8b\xd4\xaf\xfdy\x18?\x0cw\x93`\xf2\ +\xe3\xd8\x9c((Dw\xefnttt`\x7f\xc1\x96\ +P{{;\xf3\xf1N0\x84\xc2\xe0|\x15\xc6\x13\xc1\ +\xf6xd\x9b\x9co\xc3\xda\x148N\xc5\xe6Da\x15\ +\xc2E\xe7\xe4\xe4X\xadV\xf8\x0fB\x00\x8br\x18\xdb\ +\x13\xa9_3\xfe\x1e\x8d\xd8\xac\xec\xfc_FJ\x87\x19\ +\xdd\xc2\xe7\xf3a\xa1\xa0\xee\xe8\xe8(\x89\xe0\xc9\xb9\xbd\ +\xcb\xfe\x81{\x84\x10\xac\x5c,\x97?\xb4\x10\x18\x8el\ +\xe2\xfd\x85)\x84\xe5\x86\xad\x8b\x15\x1a\x08\x04\xf0J\x1a\ +\xe7~\xc2\x14ZYY\xc1\x13\x02\x8b\x7fll\x0c\xaf\ +x\xc0\xa3\x19#'\xae0\x85\x08\xe1\xbf`>\x88?\ +;\x0b=@8!68!68!68!6\ +8!68!6\x1e:\xa1?\x01S\xe1\x9f|\x8b\ +j\x8f\xf5\x00\x00\x00\x00IEND\xaeB`\x82\ " qt_resource_name = b"\ @@ -14195,6 +14488,14 @@ qt_resource_name = b"\ \x07\x87WG\ \x00q\ \x00t\x00.\x00p\x00n\x00g\ +\x00\x0e\ +\x03\x9b+G\ +\x00m\ +\x00a\x00t\x00p\x00l\x00o\x00t\x00l\x00i\x00b\x00.\x00s\x00v\x00g\ +\x00\x0d\ +\x04\xbey'\ +\x00p\ +\x00a\x00c\x00k\x00a\x00g\x00i\x00n\x00g\x00.\x00p\x00n\x00g\ " qt_resource_struct = b"\ @@ -14202,14 +14503,18 @@ qt_resource_struct = b"\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x12\x00\x02\x00\x00\x00\x02\x00\x00\x00\x04\ +\x00\x00\x00\x12\x00\x02\x00\x00\x00\x04\x00\x00\x00\x04\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x1e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x97\x0d\xb6\xa1\x16\ +\x00\x00\x01\x97\xa0\xe5\x95}\ +\x00\x00\x00p\x00\x01\x00\x00\x00\x01\x00\x03t\xf5\ +\x00\x00\x01\x97\xb7\xaf+u\ +\x00\x00\x00\x92\x00\x00\x00\x00\x00\x01\x00\x03\x82I\ +\x00\x00\x01\x97\xb7\xb1\xa2\xd4\ \x00\x00\x00^\x00\x00\x00\x00\x00\x01\x00\x03f\x83\ -\x00\x00\x01\x97\x12L\xfd\x82\ +\x00\x00\x01\x97\xa0\xe5\x95|\ \x00\x00\x004\x00\x00\x00\x00\x00\x01\x00\x03H\xd3\ -\x00\x00\x01\x96\xed\x00qM\ +\x00\x00\x01\x97\xa0\xe5\x95{\ " def qInitResources(): diff --git a/resources.qrc b/resources.qrc index 3c3579d..e3a07ca 100644 --- a/resources.qrc +++ b/resources.qrc @@ -4,5 +4,7 @@ ./images/logo.png ./images/3rd/qfluentwidgets.png ./images/3rd/qt.png + ./images/3rd/matplotlib.svg + ./images/3rd/packaging.png \ No newline at end of file diff --git a/ui/pyui/about_ui.py b/ui/pyui/about_ui.py index 71e0d5a..16db79f 100644 --- a/ui/pyui/about_ui.py +++ b/ui/pyui/about_ui.py @@ -1,14 +1,100 @@ -from PySide6.QtGui import QDesktopServices, Qt -from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout -from qfluentwidgets import PrimaryPushSettingCard, FluentIcon, GroupHeaderCardWidget, PushButton, ImageLabel, TitleLabel +from PySide6.QtGui import QDesktopServices, Qt, QColor +from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget +from qfluentwidgets import FluentIcon, GroupHeaderCardWidget, PushButton, ImageLabel, \ + TitleLabel, HeaderCardWidget, BodyLabel, HyperlinkLabel, SingleDirectionScrollArea +from qfluentwidgets.components.widgets.card_widget import CardSeparator +from module.about.schema import ThirdParty from ui.components.widget import Widget -from utils.function import DEVELOPMENT_ENV +from utils.function import RELEASE_ENV + +if RELEASE_ENV: + from build_info import * -class AboutWidget(Widget): - def __init__(self, key: str, parent=None): - super().__init__(key, parent) +class AboutCard(HeaderCardWidget): + def __init__(self, parent=None): + super().__init__(parent) + self.setTitle('关于本程序') + + self.vBoxLayout = QVBoxLayout(self) + self.vBoxLayout.setContentsMargins(0, 0, 0, 0) + self.lineVBoxLayout = QVBoxLayout(self) + self.lineVBoxLayout.setContentsMargins(24, 16, 24, 8) + self.textVBoxLayout = QVBoxLayout(self) + self.textVBoxLayout.setContentsMargins(24, 8, 24, 16) + self.viewLayout.setContentsMargins(0, 0, 0, 0) + + self.addLine('程序名称', '教学工具箱') + if RELEASE_ENV: + self.addLine('程序版本', '1.0.0#' + GIT_HASH) + self.addLine('作者', '许方杰') + if RELEASE_ENV: + self.addLine('构建时间', BUILD_TIME) + self.addLine('许可证', 'GNU 通用公共许可证 第三版(GPLv3)') + self.addLineUseLink('项目主页', 'https://cantyonion.site/git/cantyonion/JITToolBox') + + self.addText( + '教学工具箱是自由软件;您可以依据自由软件基金会发布的 GNU 通用公共许可证第三版条款,重新发布或修改它;许可证应使用第三版或(按您的选择)任何其更新的版本。') + self.addText( + '教学工具箱是以希望它有用为目的而发布的,但不附带任何担保;甚至没有适销性或特定用途适用性的隐含担保。请参看 GNU GPL 第三版了解更详细的内容。') + self.addTextWithLink('您应该已收到一份 GNU 通用公共许可证的副本;如果没有,请查看<', + 'https://www.gnu.org/licenses/gpl-3.0.html') + + self.vBoxLayout.addLayout(self.lineVBoxLayout) + self.vBoxLayout.addWidget(CardSeparator(self)) + self.vBoxLayout.addLayout(self.textVBoxLayout) + self.viewLayout.addLayout(self.vBoxLayout) + + def addLine(self, title: str, content: str): + hBox = QHBoxLayout(self) + mTitlte = BodyLabel(title, self) + mContent = BodyLabel(content, self) + mContent.setTextColor(QColor(96, 96, 96), QColor(206, 206, 206)) + mTitlte.setFixedWidth(100) + + hBox.addWidget(mTitlte) + hBox.addWidget(mContent) + + self.lineVBoxLayout.addLayout(hBox) + + def addLineUseLink(self, title: str, content: str): + hBox = QHBoxLayout(self) + mTitle = BodyLabel(title, self) + mContent = HyperlinkLabel(content, content) + mTitle.setFixedWidth(100) + + hBox.addWidget(mTitle) + hBox.addWidget(mContent) + + self.lineVBoxLayout.addLayout(hBox) + mContent.clicked.connect(lambda: QDesktopServices.openUrl(content)) + + def addText(self, text: str): + label = BodyLabel(text, self) + label.setWordWrap(True) + self.textVBoxLayout.addWidget(label) + + def addLink(self, text: str, url: str): + link = HyperlinkLabel(url, text) + link.setUrl(url) + self.textVBoxLayout.addWidget(link) + + def addTextWithLink(self, text: str, url: str): + hBox = QHBoxLayout(self) + label = BodyLabel(text, self) + link = HyperlinkLabel(url, url) + link.setContentsMargins(0, 0, 0, 0) + hBox.addWidget(label) + hBox.addWidget(link) + hBox.addWidget(BodyLabel(">。", self)) + self.textVBoxLayout.addLayout(hBox) + link.clicked.connect(lambda: QDesktopServices.openUrl(url)) + + +class AboutMain(QWidget): + def __init__(self, parent=None): + super().__init__(parent) self.logoImage = ImageLabel(':/images/logo.png') self.logoImage.scaledToHeight(100) @@ -18,48 +104,46 @@ class AboutWidget(Widget): self.hBox.addWidget(self.logoImage, 0, Qt.AlignLeft) self.hBox.addWidget(self.appNameLabel, 1, Qt.AlignLeft) - build_time_str = '' - if DEVELOPMENT_ENV: - from build_info import BUILD_TIME - build_time_str = f",构建时间:{BUILD_TIME}" + third_parties = [ + ThirdParty("PySide6", "https://qt.io", ":/images/3rd/qt.png"), + ThirdParty("QFluentWidgets", "https://qfluentwidgets.com", ":/images/3rd/qfluentwidgets.png"), + ThirdParty("openpyxl", "https://openpyxl.readthedocs.io/en/stable"), + ThirdParty("python-docx", "https://github.com/python-openxml/python-docx"), + ThirdParty("Matplotlib", "https://matplotlib.org", ":/images/3rd/matplotlib.svg"), + ThirdParty("packaging", "https://github.com/pypa/packaging", ":/images/3rd/packaging.png"), + ThirdParty("pywin32", "https://github.com/mhammond/pywin32") + ] + sorted(third_parties, key=lambda item: item.name) - self.version_card = PrimaryPushSettingCard( - text="获取源码", - icon=FluentIcon.INFO, - title="关于", - content=f"作者:许方杰。当前版本:1.0.0{build_time_str}\n" - f"本软件使用 GPLv3 开源协议进行分发,作者不对使用本软件造成的任何损失负责。" - ) - self.button_list = [ - PushButton("访问网站"), - PushButton("访问网站"), - PushButton("访问网站"), - PushButton("访问网站"), - ] - self.url_list = [ - "https://qt.io", - "https://qfluentwidgets.com", - "https://openpyxl.readthedocs.io/en/stable", - "https://github.com/python-openxml/python-docx" - ] self.group_card = GroupHeaderCardWidget(self) self.group_card.setTitle("第三方框架") self.vbox = QVBoxLayout(self) self.vbox.addLayout(self.hBox) - self.vbox.addWidget(self.version_card) + self.vbox.addWidget(AboutCard(self)) self.vbox.addWidget(self.group_card) self.vbox.addStretch(1) - self.group_card.addGroup(":/images/3rd/qt.png", "PySide6", self.url_list[0], self.button_list[0]) - self.group_card.addGroup(":/images/3rd/qfluentwidgets", "QFluentWidgets", self.url_list[1], self.button_list[1]) - self.group_card.addGroup(FluentIcon.LAYOUT, "openpyxl", self.url_list[2], self.button_list[2]) - self.group_card.addGroup(FluentIcon.LAYOUT, "python-docx", self.url_list[3], self.button_list[3]) + [self.addThirdParty(x) for x in third_parties] - self.version_card.clicked.connect( - lambda: QDesktopServices.openUrl("https://cantyonion.site/git/cantyonion/DefenseTopicGenerator") - ) - self.button_list[0].clicked.connect(lambda: QDesktopServices.openUrl(self.url_list[0])) - self.button_list[1].clicked.connect(lambda: QDesktopServices.openUrl(self.url_list[1])) - self.button_list[2].clicked.connect(lambda: QDesktopServices.openUrl(self.url_list[2])) - self.button_list[3].clicked.connect(lambda: QDesktopServices.openUrl(self.url_list[3])) + def addThirdParty(self, third_party: ThirdParty): + button = PushButton(FluentIcon.LINK, "访问网站") + button.setFixedWidth(120) + self.group_card.addGroup(third_party.qrc if third_party.qrc else FluentIcon.LAYOUT, third_party.name, + third_party.url, button) + button.clicked.connect(lambda: QDesktopServices.openUrl(third_party.url)) + + +class AboutWidget(Widget): + def __init__(self, key: str, parent=None): + super().__init__(key, parent) + + self.scrollArea = SingleDirectionScrollArea(orient=Qt.Vertical) + self.scrollArea.setWidget(AboutMain(self)) + self.scrollArea.setWidgetResizable(True) + self.scrollArea.enableTransparentBackground() + + self.vBox = QVBoxLayout(self) + self.vBox.setContentsMargins(0, 0, 0, 0) + self.vBox.setSpacing(0) + self.vBox.addWidget(self.scrollArea) diff --git a/ui/pyui/sub/picker.py b/ui/pyui/sub/picker.py index 10c1ea8..9e487b5 100644 --- a/ui/pyui/sub/picker.py +++ b/ui/pyui/sub/picker.py @@ -3,7 +3,7 @@ import sys from PySide6.QtCore import Signal from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QApplication, QGridLayout from qfluentwidgets import PushButton, SpinBox, PrimaryPushButton, \ - BodyLabel, CardWidget, SimpleCardWidget, FluentStyleSheet + BodyLabel, SimpleCardWidget from qfluentwidgets.components.widgets.card_widget import CardSeparator from ui.components.widget import RollingTextWidget