From 47c6589e1d5a8c97ac5e015cd9395b403101532c Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 29 Jul 2026 06:54:12 +0800 Subject: [PATCH] feat: application icon for Windows taskbar + exe - scripts/gen_icon.py: generates 256x256 SSH client icon (dark terminal window with >_ prompt and SSH connection nodes), outputs multi-size ICO (16-256px) + PNG - resources/icon.ico + icon.png: generated icon files - main.py: _get_icon_path() searches _MEIPASS (onefile), exe dir, source dir; sets app + window icon - build.spec: bundles icon files via datas=, sets exe icon=icon.ico - Windows taskbar will now show the custom icon instead of default PyInstaller icon --- build.spec | 6 +- main.py | 33 +++++++++- resources/icon.ico | Bin 0 -> 13431 bytes resources/icon.png | Bin 0 -> 2082 bytes scripts/gen_icon.py | 130 +++++++++++++++++++++++++++++++++++++ scripts/resources/icon.ico | Bin 0 -> 13431 bytes scripts/resources/icon.png | Bin 0 -> 2082 bytes 7 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 resources/icon.ico create mode 100644 resources/icon.png create mode 100644 scripts/gen_icon.py create mode 100644 scripts/resources/icon.ico create mode 100644 scripts/resources/icon.png diff --git a/build.spec b/build.spec index 98b939d..0b84b55 100644 --- a/build.spec +++ b/build.spec @@ -31,8 +31,8 @@ a = Analysis( pathex=[str(ROOT)], binaries=[], datas=[ - # 如果后续要加资源文件(图标、配置模板),放这里 - # ('resources/icon.ico', 'resources'), + ('resources/icon.png', 'resources'), + ('resources/icon.ico', 'resources'), ], hiddenimports=hiddenimports, hookspath=[], @@ -80,5 +80,5 @@ exe = EXE( target_arch=None, codesign_identity=None, entitlements_file=None, - # icon='resources/icon.ico' if Path('resources/icon.ico').exists() else None, + icon='resources/icon.ico' if Path('resources/icon.ico').exists() else None, ) diff --git a/main.py b/main.py index 05154bc..552a3f2 100644 --- a/main.py +++ b/main.py @@ -20,11 +20,35 @@ _setup_path() from PyQt5.QtWidgets import QApplication from PyQt5.QtCore import Qt -from PyQt5.QtGui import QFont +from PyQt5.QtGui import QFont, QIcon, QPixmap from ui.main_window import MainWindow, APP_NAME +def _get_icon_path() -> str: + """找到 icon.ico / icon.png 的路径""" + # 搜索目录列表:源码运行 / PyInstaller onefile / PyInstaller onedir + search_dirs = [] + if getattr(sys, "frozen", False): + # PyInstaller onefile: 资源解压到 _MEIPASS + meipass = getattr(sys, "_MEIPASS", None) + if meipass: + search_dirs.append(Path(meipass)) + search_dirs.append(Path(meipass) / "resources") + # exe 同目录(onedir 模式或用户手动放) + search_dirs.append(Path(sys.executable).parent) + search_dirs.append(Path(sys.executable).parent / "resources") + else: + search_dirs.append(Path(__file__).parent) + search_dirs.append(Path(__file__).parent / "resources") + for d in search_dirs: + for name in ("icon.png", "icon.ico"): + p = d / name + if p.exists(): + return str(p) + return "" + + def main(): # Windows 上高 DPI 适配 if hasattr(Qt, "AA_EnableHighDpiScaling"): @@ -39,7 +63,14 @@ def main(): f = QFont("Consolas", 10) app.setFont(f) + # 设置应用图标(任务栏 + 窗口标题栏) + icon_path = _get_icon_path() + if icon_path: + app.setWindowIcon(QIcon(icon_path)) + w = MainWindow() + if icon_path: + w.setWindowIcon(QIcon(icon_path)) w.show() sys.exit(app.exec_()) diff --git a/resources/icon.ico b/resources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..21d8a7f13a0e409d80888a6634c959fef3425206 GIT binary patch literal 13431 zcmch;bx<77*Ec!~3oO2i1PyM%$wGkO4haw-Sb!kGLV#ewZE<%G1b2dKf(8%n8r*#e z?w9ZP_uQ(t?tSZhs-CKQ`=9AgpYAg=-RJa?o&f+5fB`_Ez+<5SBv1gr>9Iyi`X7vi z3IO$wZ8S9h!3tmi_=N@l+}!`cr|1BHg#`fO;{U_}FgK zldTMdygFB0P^@(Iu5s(b*5uI8bs2`?;AUs)cfr5eVk|4f$orRWxNsVUzgrr4M}Y7~ zd;1u#r={m}OFrshw$?g_!!j8GR>X=d4g*Y5n7yA)NKjDk{O(@W_=^Xnd$Z@o{dhX@ zDp`(X=lgj8c$sv+{pD~d)l}(Cs33uiY9{5GJcERzA!&RM_oPl9whG_+4@`yF(OedU zHkx=y<<65$sv)CKhoT;_lJY8)@`B!UC}Ua0bbVF+HoWAJ4Syg^ zYT{%X`Bjfb>FuS?JHKMOC$LxnfpzY2-8AkQi`CbGst{7ch7{p&+8)>1rL5K3+K0R| zb2dw}5!T=a-8x8Sv80Bi63;dJTAO;x*1>Y@sV+nYikGS-HMktd{<04+6I{Llx6RIC zP|xLjGmkjeKFW1g32D#?@9)YYkBL&u6h4f2`t(-keG~r=HRf&3;i@*>@lP_+Y8|*e z;IApNp}J^eN%Qj={2@BTsEE%OqaPr5r|NMOLxR|;sU;NVE8aMTN4E6JMK+J30Vv2Q zOP5I+`u=YO=pT_K{a1jNokcDm1!(j?0@RhDWT~!2+T%SexHY6}#ygmc_BMzJ*PFE!d&f`q?;vv zJ?z>ac04$zlcb|^nYuWWyZ`Q#_&&W?`^oV**5N$-(-*>rB?jUcsHFDZ1;4jNt&T4J z8!}IJb`P&Qy|Q~fc1`8b^|J*zRYs-8($DptwX=H7sH7m1&!3B42)Uo?|Io8ESu802 z1l~Z>s9IW&9XY3qxz{;-a=*z)M6J;*(c?@oBNx5=Zld%{r;9=giP)vBhUl;lQI={} zQ_RobE(70{hA^{#1$$^^m|9qbEj`)%aUs`P|5ILq218D|X56COk5gxF2t@!v3geOe zP%v0p8#Ln`z@n5Lq&FnhRj9^7^iVuak%8zVdsWDC=0pLeOqT?xtk?eLO7$#{-seMm0Q0 z?TwX9N6-Tpf6?fa$4N=Q-@H+qn+;o7U{0Cw5R#Y5RY_mz4eE&!X==2mf@(C2`P29J z_n+yve#t02OTib#qU~q6Y>B=2rP?*)FIn`#Il~HNEXd`P@!AmviZ%_qm&Y|7=aqtS zG6s}q{irr`+we%YJ}7E>I@Q?*)oFLshFA1`MV&ndK`TS?ycn!Jj)y?ngu{QoM=nb9 zfx=a}Yn`t@%kD%UAb~4I(&cnS{WqFG^GK)pR}&oE+)e=i4E>KL93;KB)RXx~6Vj#^ zlz#4%Fj}iYh;-*a21v?)iLshhZ2VbP<&d&A(oL!o$JxGK0lxBi)R}5BL=qMfA9UaH zX~s8cE0p-xq%MeQc2Wj=AO>23o_fZr(`neC`4YUbxyNN-ru$$`RiiT=*gX@W*RB8jAfiz0xc5{y zR$g`u0&nVDG78vx!JzwzUV?hBB3y;ok^`~ns+&5vck_hA`w)B7o54PRsEgMQt?tA>W^-Mvke3j?f631E?4W{ ziJssMk%cQ8`zxPn-Gu2&S4?eM=zOChn|19KluOAry67o>RbA=pEJ)`I_I37C^1`4= zVo+E+tfK+|V;rV%`|MBQ@noYIVZnysYO21tLay zn)Si79l|XOcD~?Z*obVH@^ykkB)hJR24+VEiTLFBXMQM5Z+>+yGB-U_`CT>KM!Wc1 zK=KyHYJ*yM<~d5dd0a7Fz6%vM+7W}p)|-2S1&jv#iodO0n7!t(y;O2L}H=dfvtmjZ> zX2LsgRCZ3dJKZrLDyZV+zv#&O95w%um9!0sx63j7fF_%#AM-2ZMQ zS}0dR0D#{3UmMBS_f~px#68~TW`|y#l}d5yO7fKTpU_yN@r%c@k%k(5s1RC}n1E%_ zqPV(xFjo4tii@~95}j)VLnow|1MQcTKT*i5PIcnIVh!IorH|6rF#>pwUtfk!FE(Ec z2@3yN7<9Xfp>aK++u$m7x)>T5dhp&HNJ|mK=Ene0hP!7Dm)jYf2K-^D=Nn~eRv^9L z-}UB8;0PlG$;!#G4Q@^~#!93A73PQQlI(r=XHZaKRC+7IFQl7#v|_;qd%u$c+MlaE zYJs|R3VP27imj$Ov)y*Tl;VD?ev(3ZMm$n5lp%JtrJ03VleCYu)U(jryOZIs;`Uv= z*lkO%v1w^P3CRr~tC2|OH&BmQYO&373ZR0GjrT@GMZpDKH@jY$E*l;B)v?wyYb@!R zqiLrWemV^cJ6q#P#5ZWV+)a3bpC|J@zz(DH_wVsHPuAmVGniu zB{)(L*jjJQQ>z`%c7bzCRjk6NzCr@uJs3ojYDt=7O1?tR)(~B>J7H6tV zZKG12ErV5#Lg=7qinjR-X3M|OrpJH3oYMuv>APnZg7{Lgd6Y=RUWj;JvoA~Pil^f* zBrtfH_YWv@tC0xs>TTTAYg|U?t?6cb+cb}B{BixmJz2y)4y?OJJz%|VF zbV=T}L3%q50~F}sBby^CCeUz4&?`kJV?#%fgt;9MTrpD!f4FCCdeh4TrRV zTzI#FgD+|?X5hMFr0;fXis$uL)oFiW@K58z%Jz6voVkU8OmZ!n9`!LN2(vhb6fVhf z#>-o0RZ?{Ur^h*@GP#~4d%`(@rpp zasi6TmQRc3e=d49h%s{?bI^1@V8?muNpA3WAl)5rGMG@#)R6Sr%rl6LH#NePv0sxG zo;R!4b_0eg;u_%Ho?OLEn3IfrjK}CVg!aw9?BU-#9z2u%%1L0X48bgoJM2S|_9t~9 zk9cWTd17T(rl6)I-d4jm%5naHcor#ZoX${0SLHFP$Ad=%VxS+cp33FbV{rbtMd5!ud?uE4tjkXjpCcy3K4Y5i!`!0ZNT{zyMhufWs<%W>h0;_LFhw&g2mEOoLBs$~Y__-7E7O6iLw#qnKtx8o31fRmHHrKi8~I`aIxL3*O@ADa@(M}nExhpuc) zJ4}A5(jEYQJJ@s)Qk>pbweFLWGEH6+xw?=>*|xpyLkkz$OcTrex<#Yh8ItmO`}u@D z3178#bbWtxMDvMqsjOChRZ=|am#rbc`lSBrn&1bIm|fL2I*PAm#7iwL;i^$3-Q@-i z+2CB%)aoKkWN+uOg&Q)Y7vFNC&iTwqP%hML*UVQMAITVp~qk~p*@%~lk z#UDpGW`FIXX*tRu*W1c?TQxf(%){SOUv{1C?U=s1PHnrypqYF*rQlcUpUSvpI1mx> ztF!ZZKM+^NKC(76AZq^_o`(c=kzsD##mW9z1p06de+Dzgqbt)C_kpceD67Y`rfgC*KY7WlGP6H4*|Q`Tjy^j{_L5A-M>U|b<_gtvYM-i5 z^PPJlQOl9-5a@T7TXTcWhtNr&x$fU- zl-4E&7D4IolQ)M;ttYelzdzc#AvcX-cvX?8sC!xhBqHFy2`sF##i7M0RfQ%Fh_9|= zyo?IFE*YZOPDhuQk=7|YpOxkub;JR(6F)zS7e(l;cAPp}dj7>sCOWj(7lXLC7%Yne zma(1WJ(E=z_cs`L`yN)bv^B<(ATi!AgN}69ilk3&I=Dk6D7EW(nn}kPLi_~Ej1s*( zJv@4b=TkcL0>RNfK1z2IDxQp?p<4b%v>;C4NQ|0pb*(|USswr*YsLawj~ZR z!xQ(CL1;rV7Nk$668e8xBW!SZN9YiPsSnw};`C8uwxoo#r%`hNOEWI|+-qHMwr z#Ys6P|C!mQj7gvuy!w-4aoMii`QgI7Z2mF+b$%$@azOz$wfdP^uooT$NNDkYO; zXp4vi6gX3~lGW~+i8Zu=(PVuX(iWl;gBU(V|HBWpb2jL8{w&(v?0mQtHvR3xWGSlE zye1<*KOlf(mxL$ZRtd6M-fHTt)z?{M4}IwH28rnF@<{DTL=xVG@kij||Ny|)TfYfdRt)f?t+OuAJ=dcO;2 zqH=NNF2X%;Y06!Om+-_{3?DS=ZZ(4cz1mM$BkEZ2RZE)UnsY}Ik@1{ zREL`+E)9F0!h<2jJ|Std#Ln!90OS3Dh-xZ0OyX4XD@AS3yS$&95e?+1&@)-MH3{9^ z$F}zHV2A?WO6(ci<)7itM##Ya!UW5SHB{V}uP`L$i0$UPTc(=8tPvxFVzFZBJqQYr5qA-z~AzbMImzPG9y|2n1rkI@W zjPQl(_sw=^h>V^|zZd7ZZL=bnn_0N>4^}JJIu>R8xE4Q;MU$$=G_gmF6~G8T*u>Sc zrCjig=Ph5X7C!hot{ndGFf)p{*WZ)G>8@_ClO%OR#mB)$ksRFKq(fpiPG&U%IyJbM@O5%$R zEQlt|UJ4SlXnxQZ)vm88G*}kbGHBx>=uCq;rD<9yaWWRHY$GQ{ZRbH{x6cgR>xFG0y@SgDUS&$oXl76 z*fudR@UARB8k3Xu^{SqTn=CbvQSDotN*}YY|MiRFRqa*?+1F8j0nc}-50ctjBOnfLL9Q`khJ=pNkKhQZXw0O=Nr0O!6=j7!4nwily{rGXs zq1Y|xLV-0_BQz9Z*W4G{KQ(84@$gFDZMV|oD3YYF>qAt&bzSNZGniJ%c<-HC$fEsl zl%~kTx|EgoeLay|qU(3Eje)R2m!qY~?7q+9%M$n;qJ~!NjU~HlW==shR-0rg^x&IzKv%52u*$^z{$F_8WxhIW~>gsgrto(V-6;*DZy}L~3d0x@JPPN&rrEdL; zH$fa;W=N4chp16M0KoSD%VYZH9nxR#-(pwUqP>)~G+Z|~HngrJnUfp;(De>Z1}Zd zwZ-~Vif4!@vindr&3e=4i(Idtedh1J#X}&1U;0NI*3tY_8QuEZK`J8404(#FQ6Yte z`2-qnT>kRVeip`sN#=Z~0knbbU7ZC525Q>uAV7!CA5n`g4K@peK93zkJu!W{xQScZ zFU>G9D@)gA)f2qUM|X4a=tz0dUa@9@JpIujG+Us6?e8mH9g@AumV7`3RE=%p*)tJ< zhR(j!8$Fo=_+ZQ%K01{gobs;AQI@9tMce0B{xk^TK}Pn0E`s>mnZrXqijWEC;KFeo zRABA|r6}IJd%3J@8ruhAXr^r`fb)8al*2z73{5^r%*uLi02pqL@h6u8U|@a;|M7Ls zhXJ?nU?M~M;eM7p4+2Sn9RA?Y9$qF%(!>ZJSneqUT;F8MTZH#?>h%x3AvPi`)dkbx zRaY>uev)}GU+%5>%sYq26dQ^rkr;1(?AcQ2GG_0Jr6Z>U$ph*T_qV_N+|yGdAiKl> zXxW3x{^ooyBSFo2;w7tlItf?;`-8Q>+AzN~xRgHrRovHLaEzgu=flWIdMUuLOG-OI z5A>G^28hqAL%b`m7{R~&@0<~si*{E2&jPW8qu0yS4a5Lu>CO^ z%0q>BoS?YqXV&21#<(<;SUQ?l6$|8KeZoXw1@y5~i+m`R5FWZ9zc`HyjBzn#^WP_u z6v07Qy84izMeDJzJ=34X6ldFrqu4U|3ZY$g^{LYIgG8O4pX;mkV-GL@tdA??EfyS1 zRi*iOA4Y%Ou4eU+8&pwHaIm`hk3WA?3s=yJb>JDp*Z?VI(=nd-7l6C$%-|YAn;Fj) zJK5=O|08XBeEhAWfVKvipPwHJg0boXlI4M*ql>km&ZUbFJ-Tw8RjEpLjZ7o2>b?4% zldfDJ|LWsYl(xW8)oR<5%|T|BJhPI7S3pBSfw|Ar!4YcH#07lcRpKRn8%`0C@H3;7 zEHWgTVeIQXLw_A{tUv~FUGZKQ%~TF47Eqls+W4qWfxfX3dT7^iuslRu%nrG%YfxUN z%x#QsH<~T;wkIlxLlQC(*STW;91`D71Sf*LX0T=W@TFJVCWp~y<0-kZOvnge{Z3ZE zl$J=sQ9eG1-eq=TDE}E!7=Oc_OlR-wqBz7?P4xTZm`;}Y^=Cd11lYW^^Tdcjrp(fq z;u%1}$b@$P%F8bCVUdC$%gD#`kLtdVIJd5?NUdTKJ|M8 z?ZAC|YB_z;hz>41dOU&8Em@M#$5Z#x+B^pH?=RU`*9rcN&d)a%&9SbyV*lQ-M*)Ie z{GiXFk~*(o{=tyvb~jX@C{9e|tY!!fjOzXFn(T1L&vXTkjl;Je&q()f@{u#&m{)Gv zCR=~ve6!T0751_8vVQiY>~p{~xV!*JorVrVtGGW`(lHRN7BXWzk2}TLOOyUYwBWgA z?XCiX)?Z7DSsGQF26Ot#A2!Is=sBYQ>=-+P)$j4t2W=p?y|0TlksZ`zN+!KV{-Opz zwVpO<`}z%4-q4IbFNmA{PWOj!t$Z_^fZDS4PXp0 zc+e!Fx*cFSryN>lrZ%Z`;aTe-k>fsA^`EkQE^yvT&n<&Z8)xpU4~R2@do=;(4%^+E z+5L8mwIAMJYoAhZ0>(qA|L85#_gQBGkZw{+;Rbv=Gg~WbkT}%VZ7vrdMiau*huEkd zOqKQ^%Rr>!yu_DA>F#u@pL)^BH57)C%!&9EaoObec6!y^U!LIzmp9UN2UT7FgDr1j zuGW&upE3QoHSox~0Ekym8BmHO6#p0MxqzU5u$CA*(TD*|-w5`;HCp*-!gj{C02lyz zQH7lMuyU!QUZ~d(s34_H`y$yellv93=7p!|+!d4ox&yKNTT=OH?bVl3-N=r{$d!XZ z_v6vX4#R$=t|wsI--_F=10OW&&}dDP1ir`u)t*lW$gx`|h_DHZ+r0zdO>~i}1+$icE8% zk-(F}m{!kSm;dKuEF@<`*`0oL*j0291S9ST2&?5+QI}nIhT@IX5%VB zD8bmt?qbVUK9!OhnKZd=y(_Bwu4Y`fn)sdCY4J5uY{Lbm(gqL8Nsx9FPR-$hjrWyN9*TdkN2;~XwV{yu(- zytV2eWaQNP9?{`A_s2&aC0K-AVh{T2s`?y-sfHzq?~(CJAXljf;RC2G9v83GmDD{p zk_Pq*TL*c#H@sG=^{|z8N`SsxgyWm|!u%FYCrOlGWPRP7yho0vZE1dh77Vd|t!uaN zjjdvLF~JMvt#AS>mPZ?7wF_U{mi?6iRj zb_}QVy|7bNPuEzonu7c2$N~9kVF>UqY4jjxN}uV~Zz)f|45arZx9V{Y{S1Fsj;=hP z$$jPhbFay&X&3>&{{xk5Pln`;O{DdujO&O$9<9HL?nV>r;16VB&4L~24+v7zI7yLr zt-8>m_XN;{zQUbNY&F89O^7tQRpI<)d~XrHqo?-qf2YR(53TK&VkuYwI?%Jb!2S1Y0wiWkmV?TGL{6X8b_lJs_=|a;%1XingLe(Me&iC; z3?9a(C3$1pQJ@+W;n`r{$Dw9{Tc#t6E#S2^W}nMmU)ja%XS4(@wb!*pMJsZk1W--l z^M(+%Ai;r0zoc!zF$iLYy<{WdeiQqyr7T67T3m06ez$TvwoV(4b_uRHN>OoiZY>jmFFKH^ z!jd+9qDctg(tbo;)s9yNqz%pFch=I&Z%ef+okZ&H*Qkw;ESG}# zlcWknSD>qeVt$D)tUNvvmc4g?+gt^SwPQ4T;fRf6)fG|D5XKm85>D$?-^gL$0fo=~ z1ma>LK)H6MS;~}sFvLq|nm)I^v)9h*vb4wU#;>)9uz(LUPt@bA^~KYXxl2iCqqr>< z18v&Z<%GRMO|~+Fi`OghF*x1)56Bns`Q2-AYHxYd8SdFE&+@afGzE(PnvZ#ilJb^&V%qic$JK%53E8U2`*+!GSA;9hOFmJv z^MDwAElG`E5AU|O(|c@9JeT=R8@)rWL}WSYaxa^%x$gn?MDQ)TwlUs%~107%?%?r;_k-AB}M*^S?QF8l#lVf(WX3P;~mAK z^Y+NRE);*(^2J0=mev!EOHf;JyN4r|hRQp0cw6@Cw>itsxP zq&MVXu=&SMedVz07khi*IBUpBZ;#pbvCmrB|UuspOjD(b2%QGPDd9S&{kv|lf#-;v!J@CFt${4MV3+o6 z3Fmu%38I4O9=X5d-1BQ{#RUM|b_z+8rbLoDf48aA_G9B4F$!>cwvk8_wsO=HC+opR z^Vzg+%GI~nf8djCqHp-RIzVL4u8Pt-+ae!g=neC#t^7CU%rl6gGazP%|nTgpDh2c1$;KNjaKu;`QmbG)Y9HxXl&J*kHkk9#~iq#{!=-$nke-C9O_@P=ABvJU^Qmi-R#1 zX*`LUfcMWY1JhMGLnJz({<_-DLk@;n8B)a&=0V@G%7E@ zVJqbT8cA>cVh4cYNpm2QLs2&7&lqD6U+Vt8rPItnAbexA7!ROv7x39eM$y!YsLW$*BxhWhbTV}9$BZAPdBOKx3#1!U7EB6jU?QkzFz+Ulh3bK5 z?KoiOUdoeWb9eKx(jibkw3MTRy<<^58?KMCe}+VIyJ3k*UA9aD|P~(-+ipK^v<2(tp~(C zHBd)R&K``l9yWTS-rprri#eT%ZLN*y3<_4GBD!1d&X?ZEmajlT2)xJnp99j|=2~x# z-@dtV7W3Mr%?Lv1v3&sN;{vvg#ayU$E)bU?3f3lkL~pvt%@&2$eU#|+*|@Iv@WyMO z=@uM;E(#xILB7*QW!yVXso}XFXoyZQK!ELyja+aZmgNFz_CHQ3At0{^(C~o%rTtI9 zW6&jf*JC5c1!~vv1YWt4foKu+r7wa0ED{u#x03+7x1o``WZS@}q1jK)z!pveGiYXIF-nz=HBjdd;61W>yew*p0Hf4kED*dz#K6J{cr6L!36nP?M(bb# z7aD#G<+Il(OApSI8Fxub&EAvK5*$iSz^D!CxuCP0ishxvoz7ni9xV$S5Z;gVDZni0 z{)yr5X3-ShdC-6ph3%nV%f{9pd+H-HVCxg#n;mB$N$(hcft=LDY?2qi#}`W&++0ZX z?wtIDBYHYw&;RW+h9PpLb`um_h0T3AP41|C4Tfqm(AO>VJ9y(A}`Y!zddTD_pDR5>yDF&)r zh?2k?mpX3y5XI6l^9m@_qgvPJ)igvW?eCYJEAQ*bP(v^uM?m zmO(s|rhMeH0J4%1DXd`o>+1Fvc-+HV-&)d6hkDp%^<263Q!2Y-S6I47FAzYx*h%s= zz=oEIet4>icQ`;p1R(x_AA_ddPrP?`>Poi@ju7*>8Z0sJKE8>zauZ%mcfaL6NHhi0(iR%IPTP5(v_3BaVLW^r%VA)Nh{?OSu z%De39=9}?Sg4a0)ypwptqr`Duv?GthEvRmm^5B!n* z`jNbBFS40GkN4Q>(Y%?r$AN&fS%_@q-oODEqQh;tCprj02iQ>XkaXyyK|wCo6T zWGZ08eM)~a@dtWXRfsJJ=R`IW^8Xg->S)G#@OP!$UrSi^nT)iCPB08_w*B@*f5fab z)om#fTaN%GJJkqTpZ{)K^n*AN9QUs58A)>#>B#(dsaDHtn`Khf%tSsMq5swJ0^B(d Us9Pbfx;h#izW)&Z@BcUcFY;EOnE(I) literal 0 HcmV?d00001 diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..56c75e97a99c9726110721d43533b67e6cf20327 GIT binary patch literal 2082 zcmcgtX;_n28ogimAV5L_4*MbkwG~-q8FU~COF%4wgmnbe2r~>2HB4#)L?F>1h;{~A zThJ*8iXzIUA_j$!2sk*1Bv^I~%P0gWODqN9a!b>*e>AppbojH(+_+oaV#R86VcA{WPl8@=8S`BPM1w)QriB4=}7& zX<-SJUUTle@yWTuQ`M#io5b;2?4~TFL|G0%pE`-m$4$T>41r(yLu$oZra# zBW~;Y*C@_~eqH)`@#4o^`ds1cYg4kW-<9*~L!m59ZU+PgVey zG-~B7Il(Gto!LnyXlCy;MFVQ7Oof}*Y;7xWvLD%>ik3+{g<_5lUElh>!416IW> z6R`)9*5_r5dWob>Gx&C{@6CW~%w^D`=#;aTQBRf->$1k-wkW)?{Y$glme=i%@9;4) zEZA0S4r19gwQ^@64k5+}NvWFojnKA8&Fw*-XdRCAh>mjbiZ>4w|M@Z)Q3d2U%`VI$ zpmQ&;Z?Y;5GoRWt`pr?)qFg3(W$BpQ$;F5nn}X33Skm=o;(nTF*aHvg5#6uOWS9Tf zcxvG3$6<6MN%f<8`{X&Lw20KEkT(+5GyNjvdZTr_Lhi*@sOF>{uacW|*dggZ71=Dj zTboSk6nL+PywG37sb0Cktz5xpaKc?CyrxXKPh;O4@!$d9oM;X4s$88EtDfmDI-)GK zCNbqC=^Js}%Y986oPW0~*Cr1IHBRe892`>rF;K=D6KuYVJhYiX%3ZLjDBvVGB*N8t zAiedji^ii&?aV%l-EDZz^J|1nsYR@+h^UbN6wemTgq$62$L@V*aW-t9=lj+$J*9Ji zXzZ~jrwaz#Fl>xWk|7Fmfnr`DCH(^kJ_vT~fqv6Ig~aCoqOzO5-v#Q3%K=|znL#!j zUj3iIi|Zz+%*a9D$fh2T@)!1|^^K-w04cUbzgUu{AshVSSZO11Ls2I(LOqB(2_EGE z9Abrpi5LRtw}y2g_gccSR3-@V2e*98`JDbo275n5b0v+Viq%PV#$biAbdt{=9QJbx zWrBXX#@fD&{o%BAx-#yU)IG7ObO`tO?GQ*VRT)$N!zW(#7>9b97U|2}_8IAGhV_aW zkfwPan$G~G3GeU{bJM>h4|)JRp7g`ZSxE`IYcLHpWfvx6uV!V;PnJB0YPw}Q{))bmXkZ;Bs`&x0deM@_<#!N0{Et!JB^0| zIlVy@>Q0UDo^>v;Bkx@afGfW@MQgAM8SMo+zV?5|={_`^_rV)+B93k^3r1@XIVONd zWH5%Y;6#u?9L5S%I(_=deo8m||JQV&r}!Txtod-u*d-GZ(Tty;)PV*mf4c}qG+nFa zV$~6!Bc-wxCM27xB0ksMf|mc(Q%fXoZWD$XJyFoEK={JR5(o9rX=vBXU*TkLaozZq z)4s36f?5@&5j|D?n3kcf{0|>QfgF3XCE_E2P6QHa?m7ID#fk*T8!m{X*$iLIPQTv0 zk@dnd>-gN-N>wC2m(cjdHr@>?tE2IP)c5r0D1Ej2X7EucNi?9DzC+?4xC2sK&7{q zd^PaV*cYB+)l0kG5jg~rrx=9U>Tw)0o6VoS^|KR4TbN3a-rRHt2AocosJpm;V+-gO zdrUfyYU)FoCkK46IcDK7b_ 提示符 + SSH 连接线 +输出: resources/icon.ico (多尺寸) + resources/icon.png (256x256) +""" +import os +from PIL import Image, ImageDraw, ImageFont + +OUT_DIR = os.path.join(os.path.dirname(__file__), "resources") +os.makedirs(OUT_DIR, exist_ok=True) + +SIZE = 256 + +def draw_icon(size: int) -> Image.Image: + """绘制指定尺寸的图标""" + img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) + d = ImageDraw.Draw(img) + + pad = int(size * 0.06) + rect = [pad, pad, size - pad, size - pad] + radius = int(size * 0.18) + + # 背景渐变(模拟,用两层半透明) + d.rounded_rectangle(rect, radius=radius, fill=(30, 30, 46, 255)) + + # 上半部分亮色渐变 + inner = [pad + 4, pad + 4, size - pad - 4, size // 2] + d.rounded_rectangle(inner, radius=radius - 2, fill=(40, 40, 60, 255)) + + # 终端窗口 + tw_margin = int(size * 0.16) + tw_top = int(size * 0.20) + tw_bottom = int(size * 0.78) + tw_left = tw_margin + tw_right = size - tw_margin + tw_radius = int(size * 0.04) + + # 终端窗口阴影 + shadow_offset = max(2, size // 64) + d.rounded_rectangle( + [tw_left + shadow_offset, tw_top + shadow_offset, + tw_right + shadow_offset, tw_bottom + shadow_offset], + radius=tw_radius, fill=(0, 0, 0, 60) + ) + + # 终端窗口背景 + d.rounded_rectangle( + [tw_left, tw_top, tw_right, tw_bottom], + radius=tw_radius, fill=(12, 12, 20, 255) + ) + + # 终端标题栏 + tb_height = int(size * 0.055) + d.rounded_rectangle( + [tw_left, tw_top, tw_right, tw_top + tb_height], + radius=tw_radius, fill=(50, 50, 70, 255) + ) + # 底部直角覆盖(标题栏只有上面圆角) + d.rectangle( + [tw_left, tw_top + tb_height - tw_radius, tw_right, tw_top + tb_height], + fill=(50, 50, 70, 255) + ) + + # 三个小圆点(macOS 风格窗口按钮) + dot_r = max(2, int(size * 0.016)) + dot_y = tw_top + tb_height // 2 + dot_start = tw_left + int(size * 0.04) + dot_gap = int(size * 0.045) + for i, color in enumerate([(239, 83, 80), (255, 167, 38), (102, 187, 106)]): + cx = dot_start + i * dot_gap + d.ellipse([cx - dot_r, dot_y - dot_r, cx + dot_r, dot_y + dot_r], fill=color) + + # >_ 提示符 + cx = tw_left + int(size * 0.06) + cy = tw_top + tb_height + int(size * 0.10) + line_w = max(2, int(size * 0.022)) + arrow_len = int(size * 0.08) + gap = int(size * 0.02) + + # > 符号 + d.line([cx, cy, cx + arrow_len, cy + arrow_len // 2], + fill=(102, 187, 106), width=line_w) + d.line([cx, cy + arrow_len, cx + arrow_len, cy + arrow_len // 2], + fill=(102, 187, 106), width=line_w) + + # _ 光标 + cursor_x = cx + arrow_len + gap + cursor_w = int(size * 0.06) + cursor_h = max(2, int(size * 0.018)) + d.rounded_rectangle( + [cursor_x, cy + arrow_len // 2 - cursor_h // 2, + cursor_x + cursor_w, cy + arrow_len // 2 + cursor_h // 2], + radius=max(1, cursor_h // 3), fill=(137, 180, 250) + ) + + # SSH 连接线(底部装饰) + line_y = tw_bottom + int(size * 0.05) + if line_y < size - pad: + # 连接节点 + node_r = max(2, int(size * 0.012)) + n1 = (tw_left + int(size * 0.04), line_y) + n2 = (tw_right - int(size * 0.04), line_y) + d.ellipse([n1[0]-node_r, n1[1]-node_r, n1[0]+node_r, n1[1]+node_r], + fill=(137, 180, 250)) + d.ellipse([n2[0]-node_r, n2[1]-node_r, n2[0]+node_r, n2[1]+node_r], + fill=(137, 180, 250)) + d.line([n1[0]+node_r, n1[1], n2[0]-node_r, n2[1]], + fill=(137, 180, 250, 160), width=max(1, line_w // 2)) + + return img + + +def main(): + # 生成 256x256 主图 + icon = draw_icon(SIZE) + png_path = os.path.join(OUT_DIR, "icon.png") + icon.save(png_path) + print(f"Saved {png_path} ({SIZE}x{SIZE})") + + # 生成多尺寸 ICO(Pillow 自动从 256x256 缩放到各尺寸) + sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)] + ico_path = os.path.join(OUT_DIR, "icon.ico") + icon.save(ico_path, format="ICO", sizes=sizes) + print(f"Saved {ico_path} (sizes: {[s[0] for s in sizes]})") + print("Done!") + + +if __name__ == "__main__": + main() diff --git a/scripts/resources/icon.ico b/scripts/resources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..21d8a7f13a0e409d80888a6634c959fef3425206 GIT binary patch literal 13431 zcmch;bx<77*Ec!~3oO2i1PyM%$wGkO4haw-Sb!kGLV#ewZE<%G1b2dKf(8%n8r*#e z?w9ZP_uQ(t?tSZhs-CKQ`=9AgpYAg=-RJa?o&f+5fB`_Ez+<5SBv1gr>9Iyi`X7vi z3IO$wZ8S9h!3tmi_=N@l+}!`cr|1BHg#`fO;{U_}FgK zldTMdygFB0P^@(Iu5s(b*5uI8bs2`?;AUs)cfr5eVk|4f$orRWxNsVUzgrr4M}Y7~ zd;1u#r={m}OFrshw$?g_!!j8GR>X=d4g*Y5n7yA)NKjDk{O(@W_=^Xnd$Z@o{dhX@ zDp`(X=lgj8c$sv+{pD~d)l}(Cs33uiY9{5GJcERzA!&RM_oPl9whG_+4@`yF(OedU zHkx=y<<65$sv)CKhoT;_lJY8)@`B!UC}Ua0bbVF+HoWAJ4Syg^ zYT{%X`Bjfb>FuS?JHKMOC$LxnfpzY2-8AkQi`CbGst{7ch7{p&+8)>1rL5K3+K0R| zb2dw}5!T=a-8x8Sv80Bi63;dJTAO;x*1>Y@sV+nYikGS-HMktd{<04+6I{Llx6RIC zP|xLjGmkjeKFW1g32D#?@9)YYkBL&u6h4f2`t(-keG~r=HRf&3;i@*>@lP_+Y8|*e z;IApNp}J^eN%Qj={2@BTsEE%OqaPr5r|NMOLxR|;sU;NVE8aMTN4E6JMK+J30Vv2Q zOP5I+`u=YO=pT_K{a1jNokcDm1!(j?0@RhDWT~!2+T%SexHY6}#ygmc_BMzJ*PFE!d&f`q?;vv zJ?z>ac04$zlcb|^nYuWWyZ`Q#_&&W?`^oV**5N$-(-*>rB?jUcsHFDZ1;4jNt&T4J z8!}IJb`P&Qy|Q~fc1`8b^|J*zRYs-8($DptwX=H7sH7m1&!3B42)Uo?|Io8ESu802 z1l~Z>s9IW&9XY3qxz{;-a=*z)M6J;*(c?@oBNx5=Zld%{r;9=giP)vBhUl;lQI={} zQ_RobE(70{hA^{#1$$^^m|9qbEj`)%aUs`P|5ILq218D|X56COk5gxF2t@!v3geOe zP%v0p8#Ln`z@n5Lq&FnhRj9^7^iVuak%8zVdsWDC=0pLeOqT?xtk?eLO7$#{-seMm0Q0 z?TwX9N6-Tpf6?fa$4N=Q-@H+qn+;o7U{0Cw5R#Y5RY_mz4eE&!X==2mf@(C2`P29J z_n+yve#t02OTib#qU~q6Y>B=2rP?*)FIn`#Il~HNEXd`P@!AmviZ%_qm&Y|7=aqtS zG6s}q{irr`+we%YJ}7E>I@Q?*)oFLshFA1`MV&ndK`TS?ycn!Jj)y?ngu{QoM=nb9 zfx=a}Yn`t@%kD%UAb~4I(&cnS{WqFG^GK)pR}&oE+)e=i4E>KL93;KB)RXx~6Vj#^ zlz#4%Fj}iYh;-*a21v?)iLshhZ2VbP<&d&A(oL!o$JxGK0lxBi)R}5BL=qMfA9UaH zX~s8cE0p-xq%MeQc2Wj=AO>23o_fZr(`neC`4YUbxyNN-ru$$`RiiT=*gX@W*RB8jAfiz0xc5{y zR$g`u0&nVDG78vx!JzwzUV?hBB3y;ok^`~ns+&5vck_hA`w)B7o54PRsEgMQt?tA>W^-Mvke3j?f631E?4W{ ziJssMk%cQ8`zxPn-Gu2&S4?eM=zOChn|19KluOAry67o>RbA=pEJ)`I_I37C^1`4= zVo+E+tfK+|V;rV%`|MBQ@noYIVZnysYO21tLay zn)Si79l|XOcD~?Z*obVH@^ykkB)hJR24+VEiTLFBXMQM5Z+>+yGB-U_`CT>KM!Wc1 zK=KyHYJ*yM<~d5dd0a7Fz6%vM+7W}p)|-2S1&jv#iodO0n7!t(y;O2L}H=dfvtmjZ> zX2LsgRCZ3dJKZrLDyZV+zv#&O95w%um9!0sx63j7fF_%#AM-2ZMQ zS}0dR0D#{3UmMBS_f~px#68~TW`|y#l}d5yO7fKTpU_yN@r%c@k%k(5s1RC}n1E%_ zqPV(xFjo4tii@~95}j)VLnow|1MQcTKT*i5PIcnIVh!IorH|6rF#>pwUtfk!FE(Ec z2@3yN7<9Xfp>aK++u$m7x)>T5dhp&HNJ|mK=Ene0hP!7Dm)jYf2K-^D=Nn~eRv^9L z-}UB8;0PlG$;!#G4Q@^~#!93A73PQQlI(r=XHZaKRC+7IFQl7#v|_;qd%u$c+MlaE zYJs|R3VP27imj$Ov)y*Tl;VD?ev(3ZMm$n5lp%JtrJ03VleCYu)U(jryOZIs;`Uv= z*lkO%v1w^P3CRr~tC2|OH&BmQYO&373ZR0GjrT@GMZpDKH@jY$E*l;B)v?wyYb@!R zqiLrWemV^cJ6q#P#5ZWV+)a3bpC|J@zz(DH_wVsHPuAmVGniu zB{)(L*jjJQQ>z`%c7bzCRjk6NzCr@uJs3ojYDt=7O1?tR)(~B>J7H6tV zZKG12ErV5#Lg=7qinjR-X3M|OrpJH3oYMuv>APnZg7{Lgd6Y=RUWj;JvoA~Pil^f* zBrtfH_YWv@tC0xs>TTTAYg|U?t?6cb+cb}B{BixmJz2y)4y?OJJz%|VF zbV=T}L3%q50~F}sBby^CCeUz4&?`kJV?#%fgt;9MTrpD!f4FCCdeh4TrRV zTzI#FgD+|?X5hMFr0;fXis$uL)oFiW@K58z%Jz6voVkU8OmZ!n9`!LN2(vhb6fVhf z#>-o0RZ?{Ur^h*@GP#~4d%`(@rpp zasi6TmQRc3e=d49h%s{?bI^1@V8?muNpA3WAl)5rGMG@#)R6Sr%rl6LH#NePv0sxG zo;R!4b_0eg;u_%Ho?OLEn3IfrjK}CVg!aw9?BU-#9z2u%%1L0X48bgoJM2S|_9t~9 zk9cWTd17T(rl6)I-d4jm%5naHcor#ZoX${0SLHFP$Ad=%VxS+cp33FbV{rbtMd5!ud?uE4tjkXjpCcy3K4Y5i!`!0ZNT{zyMhufWs<%W>h0;_LFhw&g2mEOoLBs$~Y__-7E7O6iLw#qnKtx8o31fRmHHrKi8~I`aIxL3*O@ADa@(M}nExhpuc) zJ4}A5(jEYQJJ@s)Qk>pbweFLWGEH6+xw?=>*|xpyLkkz$OcTrex<#Yh8ItmO`}u@D z3178#bbWtxMDvMqsjOChRZ=|am#rbc`lSBrn&1bIm|fL2I*PAm#7iwL;i^$3-Q@-i z+2CB%)aoKkWN+uOg&Q)Y7vFNC&iTwqP%hML*UVQMAITVp~qk~p*@%~lk z#UDpGW`FIXX*tRu*W1c?TQxf(%){SOUv{1C?U=s1PHnrypqYF*rQlcUpUSvpI1mx> ztF!ZZKM+^NKC(76AZq^_o`(c=kzsD##mW9z1p06de+Dzgqbt)C_kpceD67Y`rfgC*KY7WlGP6H4*|Q`Tjy^j{_L5A-M>U|b<_gtvYM-i5 z^PPJlQOl9-5a@T7TXTcWhtNr&x$fU- zl-4E&7D4IolQ)M;ttYelzdzc#AvcX-cvX?8sC!xhBqHFy2`sF##i7M0RfQ%Fh_9|= zyo?IFE*YZOPDhuQk=7|YpOxkub;JR(6F)zS7e(l;cAPp}dj7>sCOWj(7lXLC7%Yne zma(1WJ(E=z_cs`L`yN)bv^B<(ATi!AgN}69ilk3&I=Dk6D7EW(nn}kPLi_~Ej1s*( zJv@4b=TkcL0>RNfK1z2IDxQp?p<4b%v>;C4NQ|0pb*(|USswr*YsLawj~ZR z!xQ(CL1;rV7Nk$668e8xBW!SZN9YiPsSnw};`C8uwxoo#r%`hNOEWI|+-qHMwr z#Ys6P|C!mQj7gvuy!w-4aoMii`QgI7Z2mF+b$%$@azOz$wfdP^uooT$NNDkYO; zXp4vi6gX3~lGW~+i8Zu=(PVuX(iWl;gBU(V|HBWpb2jL8{w&(v?0mQtHvR3xWGSlE zye1<*KOlf(mxL$ZRtd6M-fHTt)z?{M4}IwH28rnF@<{DTL=xVG@kij||Ny|)TfYfdRt)f?t+OuAJ=dcO;2 zqH=NNF2X%;Y06!Om+-_{3?DS=ZZ(4cz1mM$BkEZ2RZE)UnsY}Ik@1{ zREL`+E)9F0!h<2jJ|Std#Ln!90OS3Dh-xZ0OyX4XD@AS3yS$&95e?+1&@)-MH3{9^ z$F}zHV2A?WO6(ci<)7itM##Ya!UW5SHB{V}uP`L$i0$UPTc(=8tPvxFVzFZBJqQYr5qA-z~AzbMImzPG9y|2n1rkI@W zjPQl(_sw=^h>V^|zZd7ZZL=bnn_0N>4^}JJIu>R8xE4Q;MU$$=G_gmF6~G8T*u>Sc zrCjig=Ph5X7C!hot{ndGFf)p{*WZ)G>8@_ClO%OR#mB)$ksRFKq(fpiPG&U%IyJbM@O5%$R zEQlt|UJ4SlXnxQZ)vm88G*}kbGHBx>=uCq;rD<9yaWWRHY$GQ{ZRbH{x6cgR>xFG0y@SgDUS&$oXl76 z*fudR@UARB8k3Xu^{SqTn=CbvQSDotN*}YY|MiRFRqa*?+1F8j0nc}-50ctjBOnfLL9Q`khJ=pNkKhQZXw0O=Nr0O!6=j7!4nwily{rGXs zq1Y|xLV-0_BQz9Z*W4G{KQ(84@$gFDZMV|oD3YYF>qAt&bzSNZGniJ%c<-HC$fEsl zl%~kTx|EgoeLay|qU(3Eje)R2m!qY~?7q+9%M$n;qJ~!NjU~HlW==shR-0rg^x&IzKv%52u*$^z{$F_8WxhIW~>gsgrto(V-6;*DZy}L~3d0x@JPPN&rrEdL; zH$fa;W=N4chp16M0KoSD%VYZH9nxR#-(pwUqP>)~G+Z|~HngrJnUfp;(De>Z1}Zd zwZ-~Vif4!@vindr&3e=4i(Idtedh1J#X}&1U;0NI*3tY_8QuEZK`J8404(#FQ6Yte z`2-qnT>kRVeip`sN#=Z~0knbbU7ZC525Q>uAV7!CA5n`g4K@peK93zkJu!W{xQScZ zFU>G9D@)gA)f2qUM|X4a=tz0dUa@9@JpIujG+Us6?e8mH9g@AumV7`3RE=%p*)tJ< zhR(j!8$Fo=_+ZQ%K01{gobs;AQI@9tMce0B{xk^TK}Pn0E`s>mnZrXqijWEC;KFeo zRABA|r6}IJd%3J@8ruhAXr^r`fb)8al*2z73{5^r%*uLi02pqL@h6u8U|@a;|M7Ls zhXJ?nU?M~M;eM7p4+2Sn9RA?Y9$qF%(!>ZJSneqUT;F8MTZH#?>h%x3AvPi`)dkbx zRaY>uev)}GU+%5>%sYq26dQ^rkr;1(?AcQ2GG_0Jr6Z>U$ph*T_qV_N+|yGdAiKl> zXxW3x{^ooyBSFo2;w7tlItf?;`-8Q>+AzN~xRgHrRovHLaEzgu=flWIdMUuLOG-OI z5A>G^28hqAL%b`m7{R~&@0<~si*{E2&jPW8qu0yS4a5Lu>CO^ z%0q>BoS?YqXV&21#<(<;SUQ?l6$|8KeZoXw1@y5~i+m`R5FWZ9zc`HyjBzn#^WP_u z6v07Qy84izMeDJzJ=34X6ldFrqu4U|3ZY$g^{LYIgG8O4pX;mkV-GL@tdA??EfyS1 zRi*iOA4Y%Ou4eU+8&pwHaIm`hk3WA?3s=yJb>JDp*Z?VI(=nd-7l6C$%-|YAn;Fj) zJK5=O|08XBeEhAWfVKvipPwHJg0boXlI4M*ql>km&ZUbFJ-Tw8RjEpLjZ7o2>b?4% zldfDJ|LWsYl(xW8)oR<5%|T|BJhPI7S3pBSfw|Ar!4YcH#07lcRpKRn8%`0C@H3;7 zEHWgTVeIQXLw_A{tUv~FUGZKQ%~TF47Eqls+W4qWfxfX3dT7^iuslRu%nrG%YfxUN z%x#QsH<~T;wkIlxLlQC(*STW;91`D71Sf*LX0T=W@TFJVCWp~y<0-kZOvnge{Z3ZE zl$J=sQ9eG1-eq=TDE}E!7=Oc_OlR-wqBz7?P4xTZm`;}Y^=Cd11lYW^^Tdcjrp(fq z;u%1}$b@$P%F8bCVUdC$%gD#`kLtdVIJd5?NUdTKJ|M8 z?ZAC|YB_z;hz>41dOU&8Em@M#$5Z#x+B^pH?=RU`*9rcN&d)a%&9SbyV*lQ-M*)Ie z{GiXFk~*(o{=tyvb~jX@C{9e|tY!!fjOzXFn(T1L&vXTkjl;Je&q()f@{u#&m{)Gv zCR=~ve6!T0751_8vVQiY>~p{~xV!*JorVrVtGGW`(lHRN7BXWzk2}TLOOyUYwBWgA z?XCiX)?Z7DSsGQF26Ot#A2!Is=sBYQ>=-+P)$j4t2W=p?y|0TlksZ`zN+!KV{-Opz zwVpO<`}z%4-q4IbFNmA{PWOj!t$Z_^fZDS4PXp0 zc+e!Fx*cFSryN>lrZ%Z`;aTe-k>fsA^`EkQE^yvT&n<&Z8)xpU4~R2@do=;(4%^+E z+5L8mwIAMJYoAhZ0>(qA|L85#_gQBGkZw{+;Rbv=Gg~WbkT}%VZ7vrdMiau*huEkd zOqKQ^%Rr>!yu_DA>F#u@pL)^BH57)C%!&9EaoObec6!y^U!LIzmp9UN2UT7FgDr1j zuGW&upE3QoHSox~0Ekym8BmHO6#p0MxqzU5u$CA*(TD*|-w5`;HCp*-!gj{C02lyz zQH7lMuyU!QUZ~d(s34_H`y$yellv93=7p!|+!d4ox&yKNTT=OH?bVl3-N=r{$d!XZ z_v6vX4#R$=t|wsI--_F=10OW&&}dDP1ir`u)t*lW$gx`|h_DHZ+r0zdO>~i}1+$icE8% zk-(F}m{!kSm;dKuEF@<`*`0oL*j0291S9ST2&?5+QI}nIhT@IX5%VB zD8bmt?qbVUK9!OhnKZd=y(_Bwu4Y`fn)sdCY4J5uY{Lbm(gqL8Nsx9FPR-$hjrWyN9*TdkN2;~XwV{yu(- zytV2eWaQNP9?{`A_s2&aC0K-AVh{T2s`?y-sfHzq?~(CJAXljf;RC2G9v83GmDD{p zk_Pq*TL*c#H@sG=^{|z8N`SsxgyWm|!u%FYCrOlGWPRP7yho0vZE1dh77Vd|t!uaN zjjdvLF~JMvt#AS>mPZ?7wF_U{mi?6iRj zb_}QVy|7bNPuEzonu7c2$N~9kVF>UqY4jjxN}uV~Zz)f|45arZx9V{Y{S1Fsj;=hP z$$jPhbFay&X&3>&{{xk5Pln`;O{DdujO&O$9<9HL?nV>r;16VB&4L~24+v7zI7yLr zt-8>m_XN;{zQUbNY&F89O^7tQRpI<)d~XrHqo?-qf2YR(53TK&VkuYwI?%Jb!2S1Y0wiWkmV?TGL{6X8b_lJs_=|a;%1XingLe(Me&iC; z3?9a(C3$1pQJ@+W;n`r{$Dw9{Tc#t6E#S2^W}nMmU)ja%XS4(@wb!*pMJsZk1W--l z^M(+%Ai;r0zoc!zF$iLYy<{WdeiQqyr7T67T3m06ez$TvwoV(4b_uRHN>OoiZY>jmFFKH^ z!jd+9qDctg(tbo;)s9yNqz%pFch=I&Z%ef+okZ&H*Qkw;ESG}# zlcWknSD>qeVt$D)tUNvvmc4g?+gt^SwPQ4T;fRf6)fG|D5XKm85>D$?-^gL$0fo=~ z1ma>LK)H6MS;~}sFvLq|nm)I^v)9h*vb4wU#;>)9uz(LUPt@bA^~KYXxl2iCqqr>< z18v&Z<%GRMO|~+Fi`OghF*x1)56Bns`Q2-AYHxYd8SdFE&+@afGzE(PnvZ#ilJb^&V%qic$JK%53E8U2`*+!GSA;9hOFmJv z^MDwAElG`E5AU|O(|c@9JeT=R8@)rWL}WSYaxa^%x$gn?MDQ)TwlUs%~107%?%?r;_k-AB}M*^S?QF8l#lVf(WX3P;~mAK z^Y+NRE);*(^2J0=mev!EOHf;JyN4r|hRQp0cw6@Cw>itsxP zq&MVXu=&SMedVz07khi*IBUpBZ;#pbvCmrB|UuspOjD(b2%QGPDd9S&{kv|lf#-;v!J@CFt${4MV3+o6 z3Fmu%38I4O9=X5d-1BQ{#RUM|b_z+8rbLoDf48aA_G9B4F$!>cwvk8_wsO=HC+opR z^Vzg+%GI~nf8djCqHp-RIzVL4u8Pt-+ae!g=neC#t^7CU%rl6gGazP%|nTgpDh2c1$;KNjaKu;`QmbG)Y9HxXl&J*kHkk9#~iq#{!=-$nke-C9O_@P=ABvJU^Qmi-R#1 zX*`LUfcMWY1JhMGLnJz({<_-DLk@;n8B)a&=0V@G%7E@ zVJqbT8cA>cVh4cYNpm2QLs2&7&lqD6U+Vt8rPItnAbexA7!ROv7x39eM$y!YsLW$*BxhWhbTV}9$BZAPdBOKx3#1!U7EB6jU?QkzFz+Ulh3bK5 z?KoiOUdoeWb9eKx(jibkw3MTRy<<^58?KMCe}+VIyJ3k*UA9aD|P~(-+ipK^v<2(tp~(C zHBd)R&K``l9yWTS-rprri#eT%ZLN*y3<_4GBD!1d&X?ZEmajlT2)xJnp99j|=2~x# z-@dtV7W3Mr%?Lv1v3&sN;{vvg#ayU$E)bU?3f3lkL~pvt%@&2$eU#|+*|@Iv@WyMO z=@uM;E(#xILB7*QW!yVXso}XFXoyZQK!ELyja+aZmgNFz_CHQ3At0{^(C~o%rTtI9 zW6&jf*JC5c1!~vv1YWt4foKu+r7wa0ED{u#x03+7x1o``WZS@}q1jK)z!pveGiYXIF-nz=HBjdd;61W>yew*p0Hf4kED*dz#K6J{cr6L!36nP?M(bb# z7aD#G<+Il(OApSI8Fxub&EAvK5*$iSz^D!CxuCP0ishxvoz7ni9xV$S5Z;gVDZni0 z{)yr5X3-ShdC-6ph3%nV%f{9pd+H-HVCxg#n;mB$N$(hcft=LDY?2qi#}`W&++0ZX z?wtIDBYHYw&;RW+h9PpLb`um_h0T3AP41|C4Tfqm(AO>VJ9y(A}`Y!zddTD_pDR5>yDF&)r zh?2k?mpX3y5XI6l^9m@_qgvPJ)igvW?eCYJEAQ*bP(v^uM?m zmO(s|rhMeH0J4%1DXd`o>+1Fvc-+HV-&)d6hkDp%^<263Q!2Y-S6I47FAzYx*h%s= zz=oEIet4>icQ`;p1R(x_AA_ddPrP?`>Poi@ju7*>8Z0sJKE8>zauZ%mcfaL6NHhi0(iR%IPTP5(v_3BaVLW^r%VA)Nh{?OSu z%De39=9}?Sg4a0)ypwptqr`Duv?GthEvRmm^5B!n* z`jNbBFS40GkN4Q>(Y%?r$AN&fS%_@q-oODEqQh;tCprj02iQ>XkaXyyK|wCo6T zWGZ08eM)~a@dtWXRfsJJ=R`IW^8Xg->S)G#@OP!$UrSi^nT)iCPB08_w*B@*f5fab z)om#fTaN%GJJkqTpZ{)K^n*AN9QUs58A)>#>B#(dsaDHtn`Khf%tSsMq5swJ0^B(d Us9Pbfx;h#izW)&Z@BcUcFY;EOnE(I) literal 0 HcmV?d00001 diff --git a/scripts/resources/icon.png b/scripts/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..56c75e97a99c9726110721d43533b67e6cf20327 GIT binary patch literal 2082 zcmcgtX;_n28ogimAV5L_4*MbkwG~-q8FU~COF%4wgmnbe2r~>2HB4#)L?F>1h;{~A zThJ*8iXzIUA_j$!2sk*1Bv^I~%P0gWODqN9a!b>*e>AppbojH(+_+oaV#R86VcA{WPl8@=8S`BPM1w)QriB4=}7& zX<-SJUUTle@yWTuQ`M#io5b;2?4~TFL|G0%pE`-m$4$T>41r(yLu$oZra# zBW~;Y*C@_~eqH)`@#4o^`ds1cYg4kW-<9*~L!m59ZU+PgVey zG-~B7Il(Gto!LnyXlCy;MFVQ7Oof}*Y;7xWvLD%>ik3+{g<_5lUElh>!416IW> z6R`)9*5_r5dWob>Gx&C{@6CW~%w^D`=#;aTQBRf->$1k-wkW)?{Y$glme=i%@9;4) zEZA0S4r19gwQ^@64k5+}NvWFojnKA8&Fw*-XdRCAh>mjbiZ>4w|M@Z)Q3d2U%`VI$ zpmQ&;Z?Y;5GoRWt`pr?)qFg3(W$BpQ$;F5nn}X33Skm=o;(nTF*aHvg5#6uOWS9Tf zcxvG3$6<6MN%f<8`{X&Lw20KEkT(+5GyNjvdZTr_Lhi*@sOF>{uacW|*dggZ71=Dj zTboSk6nL+PywG37sb0Cktz5xpaKc?CyrxXKPh;O4@!$d9oM;X4s$88EtDfmDI-)GK zCNbqC=^Js}%Y986oPW0~*Cr1IHBRe892`>rF;K=D6KuYVJhYiX%3ZLjDBvVGB*N8t zAiedji^ii&?aV%l-EDZz^J|1nsYR@+h^UbN6wemTgq$62$L@V*aW-t9=lj+$J*9Ji zXzZ~jrwaz#Fl>xWk|7Fmfnr`DCH(^kJ_vT~fqv6Ig~aCoqOzO5-v#Q3%K=|znL#!j zUj3iIi|Zz+%*a9D$fh2T@)!1|^^K-w04cUbzgUu{AshVSSZO11Ls2I(LOqB(2_EGE z9Abrpi5LRtw}y2g_gccSR3-@V2e*98`JDbo275n5b0v+Viq%PV#$biAbdt{=9QJbx zWrBXX#@fD&{o%BAx-#yU)IG7ObO`tO?GQ*VRT)$N!zW(#7>9b97U|2}_8IAGhV_aW zkfwPan$G~G3GeU{bJM>h4|)JRp7g`ZSxE`IYcLHpWfvx6uV!V;PnJB0YPw}Q{))bmXkZ;Bs`&x0deM@_<#!N0{Et!JB^0| zIlVy@>Q0UDo^>v;Bkx@afGfW@MQgAM8SMo+zV?5|={_`^_rV)+B93k^3r1@XIVONd zWH5%Y;6#u?9L5S%I(_=deo8m||JQV&r}!Txtod-u*d-GZ(Tty;)PV*mf4c}qG+nFa zV$~6!Bc-wxCM27xB0ksMf|mc(Q%fXoZWD$XJyFoEK={JR5(o9rX=vBXU*TkLaozZq z)4s36f?5@&5j|D?n3kcf{0|>QfgF3XCE_E2P6QHa?m7ID#fk*T8!m{X*$iLIPQTv0 zk@dnd>-gN-N>wC2m(cjdHr@>?tE2IP)c5r0D1Ej2X7EucNi?9DzC+?4xC2sK&7{q zd^PaV*cYB+)l0kG5jg~rrx=9U>Tw)0o6VoS^|KR4TbN3a-rRHt2AocosJpm;V+-gO zdrUfyYU)FoCkK46IcDK7b