From 06774c065340939e6d0bae4bdd64dcf8fe4184b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A9sir=C3=A9=20Werner=20Menrath?= Date: Sat, 26 Jul 2025 11:44:23 +0200 Subject: [PATCH] commit two --- GEMINI.md | 5 + .../custom_file_dialog.cpython-312.pyc | Bin 14305 -> 32817 bytes audio.png | Bin 0 -> 16671 bytes custom_file_dialog.py | 582 ++++++++++++------ text-x-generic.png => document.png | Bin file-python.png | Bin 0 -> 16671 bytes folder-water-documents.png | Bin 0 -> 16671 bytes folder-water-download.png | Bin 0 -> 16671 bytes folder-water-music.png | Bin 0 -> 16671 bytes folder-water-pictures.png | Bin 0 -> 16671 bytes folder-water-video.png | Bin 0 -> 16671 bytes folder-water.png | Bin 0 -> 16671 bytes pdf.png | Bin 0 -> 16671 bytes picture.png | Bin 0 -> 16671 bytes tar.png | Bin 0 -> 16671 bytes video.png | Bin 0 -> 16671 bytes water-folder.png | Bin 1295 -> 0 bytes 17 files changed, 388 insertions(+), 199 deletions(-) create mode 100644 GEMINI.md create mode 100644 audio.png rename text-x-generic.png => document.png (100%) create mode 100644 file-python.png create mode 100644 folder-water-documents.png create mode 100644 folder-water-download.png create mode 100644 folder-water-music.png create mode 100644 folder-water-pictures.png create mode 100644 folder-water-video.png create mode 100644 folder-water.png create mode 100644 pdf.png create mode 100644 picture.png create mode 100644 tar.png create mode 100644 video.png delete mode 100644 water-folder.png diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000..733fad7 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,5 @@ +# Gemini Project Configuration + +## Language +Please respond in German. + diff --git a/__pycache__/custom_file_dialog.cpython-312.pyc b/__pycache__/custom_file_dialog.cpython-312.pyc index fd2297e27fd21fb17e9327091afadf174daa52b9..403f31c8a56e741e02ddb522cdd4ab900e26f776 100644 GIT binary patch literal 32817 zcmdsgd2}4ddFS*TKo4ec-}m4mI3NM=051@vc!1y`3KT_%6sZFmpa;N!00!zAhy*mS z7(XQj961DR#{^?L1Y;!xBkT%(yNRKV-xIxZ5@q9ko*{;raT|%`L~q~YU!h6at5xzg z`}?Yo84MaErTFEKEfUq$b$nG_^;Ok(Rn6a~rluI+_I>Y-KFgB^!#~lB>MTm&fr!8r zgJ2N20mC`@$(`fayYZX}Pvd}b(0tC!QJQJMGH5wx;S5H@VS`|P!ys7RHp-CBC9$|9 z#3j2;{b_1NvFF<+B_}`1Ir+Qv((dFWlizmBfWhP%yi zbx@dE_Mm~IDgs=<(5WQ{jCe!5>;fjdsZBzE;7$1^gZ!q!4H){>LUGT2TilBh6i{Ek zeRaIruN-Q5Y*=WmZqF-i{#>x|tq+GaYH*s{$C6tP4f);TUIdQ2U9YZ{Zh&W(KS5a9_sb?Nojt0KsqmYh6L{g$>8ID#X030>+YdDDr#l5XOIm4*oCP!0?_jUKVg^>aGO{18B zRP^er=vNU#PM6B%$RdOg#9z53e^6TZ{iY*JR zk)}hTrbBm{4$I#W-+5-_WnDXlz+-(!{J@|Lxqfvym0y|9CU#O>gc4LIHWm-6n>kD+ zW4q@Qw99D`ix9;yU9z}(XcE|ceclUNFVI?XlVjuQqYqKWk-j;G!fFpvtZxInONJTq zwe+j$pBT8pq-bXDmE!5*NM>ayvvPLpoH??7S7`mNrOf6_{@=c^x{s)TSReHu!1@T! zL^qC=8Q-Ku2RN|=qyCt^72w`hMupIK)F5MnNu;lpJHyU8qqEyJ)a@Q{$_UMpSD*xS z-dL83&M{OfM7(b!Jj~_P%*$sc&rBGVdHXY4YSf-_`N_#ABlhZ$y?XYUJNEVWOa^<} zYOJRPob^N)-?dgx=wZ5`ecuZh^>O34Y1}++rtL*{ao52ob*>0T!ql-;f90OA%~w`S`e+ z37ryLz=D1$Nr=R&pEf7v`peW%>={T7@NqdDu@p5V*a5dveTzMX)cLfxm2n!k2CV%x zu{1R#*yqz@{XA-@if>JUnk)9KHi*d}==kwu!8XpHHM}`?!En)Z)^LGyX0%I5o*|!G z^xvg9bC>$Q<1=o9NJA~9bh*0E_ln+;Az>`JstxYYCTujxg1g5xGJws!$1A$!bji{+ zfXsJkT06~mX|20Ui-Ab9P^_m|p6%sQazD0ePtT}WODRrxQj+K%@VI*Q+>`d7S+N=E;AiSO`&^mx@h zAksvZvM&sFdS7*mB6b-OWP<4K_5;FTXRjONgkKyLX|79_Q~uEbx0E#C^`0LY29WN7 zL!#&fb#mO*1z0pVlKJ?dwhm-Har|hj+*0!}KHr(bR%($3LEZr=O4H)`W6vX8V?M z8z)mHxQWdZuBpr@Z=LA4{QTtek<{u?YV}g;y1A@S>V^=%VS;;D+HzIRjosIG&-veZ z?dEGsRl9@yZbtCTbVd1;2wxWB%Vzvxz8Y_r(a{RmwVaWC z#X4>MhHb)f&uFn0MlyEKafc@ke8L+tbExD@fCnhd)fSa&<#HU_PnM|3< zoJhID7k~PR&5)6G`L)T{?i-9$brIE7@YMtNEO`CQmxZo--@N`%s^KqF^AFXU{&F1$ zzgyXakQhgGJ&l*O7JHp-FEhaDZ2{_%6~Dn5WkkgM@%csXsJgASqQVv1S}`JGC=gE- zZKka2;IWM@lIjShIsHJodHYu`SKX-Te$D|DEg}4yt<{56)v-{-Cv{OmKyn=}UuUjq#gPZcr7lon9tuvh5p@i8ic zv3lC>u9gCuYK-j@fI-V(f)h;Gvz2-n6i^z8ZbiEcdi#D1*%?)+?TrDWSneleVoq;o z*W1ejTC0c39#NV$tpo=lg)*%{v1nftFo~d_hKxc|FHtg@z(Rj_7m^9Ez>|;M8l{8W zIy3@01*L@wy^?+auC#?_wP&c(g_TzE5Mtm3Ef2$9&0V#Rc zrcD>OZ`F;Bh63-{Z%Y&Z`@}lspKc$1~=ZtbWmj5M|YR?C$P*S*D z-}ug%n`a{RPlW29xMf*{U{T_0LF8Cthv zkqfPBCa_h}f|5wV`cT38V7?Q%?9pO~hERC9u=rZZ)snfx;ld_Xx~L3~^k`8rJw8H9 z(SODf8(N4?ffJuGuI56YB9g8v1 z7>`pb?(0xW+i)Mh{V1hveT*$rD>n3No1hkD09%G3cm#Bax95}9MHKKKccc=_J?>~E zmV4YDhv0ohJ0G{t6U#kruP2t%`u!}#Ng8`=Z6C{OXzcM0fa9ybfOSr67-r0*nbteD zkBp@?Gz#ACkwGlslsJ~%&^Sm!-kTI7{Csn6}{?epKI#S$zZ zTf0-9?(_P+M+aTKZpl36^$tpza=mPY?i_H5NJyt@<0H~MK5zW{iZZ@I*T6u0895?W zhP{g|XobjlLs}3N0U-&p$BI|2$gwTs6f*c~P~wu|o-xCEh+D3yz47Ap7o)jOtefjL ze7K?UX43-q_6{tUshMGW<;P$T_gvo-&88?O83_J8k!lJ5Apvie5-_4;UT z9nz~dez*v0Wr9}EnIb&VjRmdjNrCo;mRi` zTJPA)KV44Gl-atZSQ{6!ZXF2Mup%mu1@Ts8xav?ml!dNaS>ei7iYiw=?sFFWJA3)P zRI2wgABm^Fd@%iBmf`)Z1H0QYOn;Tm!C%2a+K`8>&>PXMAn+f$J_iiy`U{?tNYWUw z&*>8TMuEhC+B`;Git91ZP{ci+-Vu?+SFTa-h+h>k973TLA_gxa z#>!T$4=cz>BKmy!Y>7~0J2TbaNT0Ao%hwYP1bQa*vUSorRUgeRo$*J?w}#5M2D6&( znYjAx6ISRRtUE|b141ZRP`9u%T3r*|c$BEG0!n+5Qxa!V=DH?8D{UrtMD4v4&94b= zKN37U7`*tUdj`Xk#uLV08VtkS(?-0Vqo;D+L`$_V*JwyIWW`R=HyXhsr zhy1)=^RG;twa>hoM$=Y+{|m;GgclEA116z|2lb=O{BaKRQQL3P_lhGHeO}YNub>#T zT~^IYLWDTMvyPa5K1r+37%+a$`m{AFu0ErX9QO?-z|@%TxLhVCoL9VS261`n+uE8J2UCY83z&tpNrRrCBCc08Ry_87Li&8h z+sfEY8ahdj#T;Pi2;_Bpoz_wFe735+iLUCk2vP4KE&m;y3vbYnDaW5J(m_ zlCTo0RSMV3;qRIeZlG`v$JUC*H>|>@`OWGaALj$S?hMPqI=n?~4`+C@)f~T*tzV6K zZ!1y#8&;>1F6#aQLFeFZD$rdS>|w067V*SSZG zM2fH@ZX|30+Zs?)=6A-hB@X5mwKcJ4z$WZMi<@FGYDj2CJn_;AZhp7Av+Ck%=6s7f z9xL`N{kr$8QTN{8Xx%!3@IVS`Alf~_wHhwlyN$gtw|Wt>k8yjzE~_1;jc;1bh#j{J zPYC#gt203;5 zK>lLc*Bwi}RYIGE=n-vy2K?65wd(fBsy!cN^}fCp@olSN#=brd-yhn}@zg-7ZcFm9 z{@5_n;;2;Q{Cum$k<~2>qzZ?Gt@CZ_n4_PxJsaP2Y;_6U*0HthbF3Mu>Ijaf1=7}l zxYl~1N9U#qhtb;Ot6MvNMEx?|b>Zk5>wd6=;jAFiWY|dUVIFGkW z#?3I75jO)Yi6H!a9XBBffCz9vN|F^w5IH1yMN&WACFX%?ws1ipV{P!Erh!3?5xnA}3l6ngA6c^&eF7gEOG=ZnAg8Gba8E_4D39h|ko7a+RDB7@w zmH{v1y1u;#$VGk&0GU zUY7W$J>7oDg?y6bsS%&&yi)M@{!D)FmXc0GK;>2I|GoLoIEVNSHSj-^N8P?c)JZ7D zFk&473?n!_jED(2Pbu~%oJe*Z5N>h9vQaDHjH*T?D)I{q-wcW|3m**Mq7d2J9@^Xf z!7EF9PhOITYApQ}J`PIHh7Q?QeZ|-vV(pQqz*`7Q9Le62V0hZ+71`v)pk70QJO`=0 z@;o)lv6O@fs^vgf8(t~-Nf(T=2ZqGcluMbD{Hrd}~F1MRdA%?`Jkd zDw4sylHsONM%}+a0fr^-f2*fw$UTIXYbY&QL{f1`*8N>wFqG?KsSLHL8s~b&R*p$& z#eIm9Y)`v}+`<`V+OMcYj+}Vr=(!W^9s7?d?KP#*7S>esCY_DSuZ6ci+327 z5>^uU$~MvIZ2m|ogDwy1VUX-FN`TdZa=apyWX`~PB{5Td#iFW2<*HHg2l|xgyu@g^ zi)hOsB$7;B{vlW#K!T1=QpzOzy~AWzAlaDVg71RI-`xjON55pp&WEEJO1>Odx1Xfe zD{Ax+e!ooi1TiNY77Qa{to#uR`YXuf`!j4(nE%VU1y{~apPli~b%b-bOr%8lED}J^ zoStiCGUny{qARaYzdk$m!^-#S->nblADOU6`J4z}7~%_OUY!$yd|{a1`f)+=HS1OD z?8ZedT+lp`%CfMN9;I`y1o;9ct60WwspHzwt4C)Cmr9xd zDasehhLf|K=T0v8Z`B4#;eTwoxa?Z<)#j+ZboS6f(+^s{-|}PeuV4GoYr%8Rlg+}5 z95XS15rKTVB*K@5_|nJ|Dv#@p1ALJcjzV%~A z)eY-)>stMB8#!?v=Xfx?t&+#m$SSZygQoX%DuX_~4b`$uq&{UJ9M;3_ksGaF;9E(6n&+ z=1{oiWbiDRvu4Ab_25VL^vg#kkIYof?w>ev$G+}fGC;yI)@mme%kScx5#d0vtZ~tF z>m(bAhOEVvC8(NGFi1Yn-i(n9;(<*!-S=4bb55QbSb|v ze$jGa0jgd+%@(d!woo}kymPK%VSkW!qF!~RjzdRY6)tLf_-HAOELkeYRECN#t|wU2 zwovyoW3AdbPqeuFTFccI>Hz15&ib1<3p?g=!p_}sdCpUwy;t{A9>u8O%&pCHO?NgN z`ak!bhSEL0BrMx$qCCk7+<8bh z#evvS8Fpw#M~^m!IF)G;jOSZX>S@%cX?|pQ1dV_ZF51z7>;@USWu z3QGd&Q0CZqR$|_mqk~rL6elA_#pe)t_XBvaVEG3;)Wa0a#D&p1l8Mf7nqc%O4kCj% zKwbrTWIV_yArPP$6fS@#S%+Y<$cp=D;INm=oA`%#8LL>ei6@dh?<1S<%kW^^o>LIX zSs%(-AIWJ7z>Kl#M8^ak}U?@*}-(0r3UM!Uzm}q_TM6|4S zqV;Ph?pY0+p5=nJy49Lp4IAgbAT~mlk5OAo$E)HWWbHX-I`OHEA^Jmcx>g;WU&Bp3 z+*7fFVUr$A9lT^m8EI4#TnrX7Pu6Tq(AwODtay!m5z=+^fc>PFNN{Qy%qN+n%4qGj4EOGI()sf0Ap~@{Fd83LU?F!4(#5uS9w#|v-lM#DW$X<2FUh`30 zc=e>AuVqX4C7|9{3}4CqO3tHABJ^ZO@n#ZV&GwUIgSmdHA;Cd5MUyqb38u+xy;F}c zoT3)OjdO8ub(Zl-ZMnzBV$@sE1(;Z=lVqIg(^*oX?7D ziCJ$-3fU9cIGdC62Cu^B$Us?}ntG~zjFUsHJ@!=lX51najwcC4?6A^mR-XvTKqsgHoUO@$PD2382%eOahO=X?h0P_WL&z3F;5rUcA^ zBq)wc=gU;3(^qpQbNYA1>QqC46sYsch4OianiDvk)4y9yk3EG7wSHi8nrKHWTVknd zXlQ%D{;<<6x(b>~6*7amPlXkG4%txKf!Mnm8c&bwhiWx8_MFTKq|aArc#{#x(4DQ- zFq+Y3^rIl6B_wc6a8UZi%pcax*Q)bvJTs7~TjzSL51PRMX8vInAlj^96OBb6Baqo+ z0`ajK7@HNy(w)6^fmFpnV8a`6=2vUv-pF#3@sUxekI(<+R*)_>p_rXkhq5?eJ^uo2 zcT?P(e;{zF6HJaDX{jbO)^g_ug3V#P4GSfI?->1eh52m0@vMh_|M3TOWMDwl?tP{1)1nX4Q+Jf~- z-7}}L1A)-mE1dv^im4q${J;P{-0tfZy#oU{v<(>?+D5`qk=7{^$irw9qQzHnz=xW= zLMFd$74fbSC>n{gTCMU=0OO;1_30(ULQiCSTWEV*w6OeI@zvtlXO{{$z!Y@HVGi=E z9rc$KNqzRY5r}4cdK?%HQi5Sj8g6p3Sh|MV$%${_arYv50z9T8yNP>+&bvp&HzISXpfo1S{}Dpy5r{Z(oa`?t zdOvyJhBubk(&`<70KfhKlS|ic-n)WzC5nO#;yMJ_AR2YGBbxS0(~d|vAQ(L`fbJAn z1vqd81jRS;7*6qBY5>uZ3V$W5zC_yh#=h7PB>}9DsB;Waw0eD{dQYf&&!TIodLIUd z;}}UdmZDtollYltlw+T{9)aICLM>?0|IA6v#x?e#Y3hf{mdqF+?GvRG)&oqYEq^Z6 zp-XM+^pQwZgJ4#^I?Xv zdk2^{Kzu++F!H_#BXX~Zvx!h9`02(Z?**V|7s0wiSu7qOokPs*9CSed?}kVp3}C2;GY&0DpbTATn_P&Jq$z%a-+$jdh1|h|vlq3<{4x+d>mmGT}X@ zbHwEoK6b9sOv?;F5M>Td z2r~Nq0gK^h&?{tSUn!g}oN0;_H-?HEZ|x6fwoN3FY;$mWka0wgklis?w0N52-4J%= zKgmtlK9;XUP|W7D3$CCy5AMVJU^Bus>=0@NJ-xw-yT*}!rap+!(A+HcB6L_{bK6860Z~GESZkKcNXSkW&b9JF& zh-9`wB$J&#$xoOjPA%sY&1`$C`-bPbC!DkCfuYn|IMKSCoqJ`+^bYpT=7?ic$gydm zn!dbsIXC~xndviEUYve$wrMGM{Y2Z(vI~h7-5ILfxtJ5K+#Ag(__(m-TH)2gXh!+$ z*y4r{UPPZ3y}(Tz`^cVm`NZUjS<~FX1=pf$;zZcKFKW+=*lR-enpt<)zVR3JTc?^L z+0NV9&S>q18)MhUz88qpwuEY17Egz3Tc^yCjH=riRUcGGj=dB*_7diOYNk@#Z1X}# zxUhNR7$CA*@(I3kS#3)Z$z!*WP`7C@YpJ5;7734wPQ*0}VrD9`Bq59^s~vq8WKtY}2-2Nh1VO0I+30hmpxVz4@S zN4R^*RPdhNkeV^IdGg4_!DxCG4#=jLNAvQhOwo+&saK}?ubY0k8y)}YC)tLKa=Hd1 zdl^cFqmxIcyupq8!}bFa`{9uN@CVNX?T5qmr+;S8qRTO|mCG@9l^;(r{3K=5@ja%W zv~ciOkR>)u1=`gf{4emBkK*AWl%WMX!KnlZ6M<=*YAln$3C4MoO55SS8uPd@&a{e; zWgL6X&KJez z%^Ef6&A4JV=StMC2Iiaelp{i^P&Qv4SA$tM7mh5f$fZ9IiW5EvuR^|HidOOP4WspX7Ji(z}Ck(d@{YMiL@QQCGWnL>A$ zDW%$B#VGza0AQT7hYm=Csr?IzAXZ*V1~cOZ!y+~zh1sMX7T^E#_piBSuF!_qHgOw# z$<#4AEN-V=D*RXE9Uu?JybuA%_DhWW2P>>F{+suXWwo@Z=XPaNyS;nGRFoJ?s}UM% z1{-S5I%rpZib3U!3cSBpCd zU@f)A))&W`Iw_iPR&IDBy^<+`l&Yd_Cu`IuievZobTU4fFwmEVax2+KnRomb#6OI8 z)RcfUoW4CEC*n-f))YesK2tXMfQ7{Z2}4Ln`Ss*(Z}-+T8AUp1Ao$bi;OffQ7S`5Odq2-pMte>>_VE%@=j!6B!Q2job;oUQv z^f_r5ZsiuQ;D~d70~|5#=}0YH&M&-jVfw<1{~O~|=4HqFh+})mu^k2zSDu=F3ifFg zRUcMuxV|&Ev1O@h5Bepu>=)UEu)&EGZw?i2o@$Lc)=wRc7MD)9ezax#59+>O_g^+f zwj2&^IUFr0Lq~6Qkcgw~ARNUKGgZcJ1j`9;}hQDn&n0BJn_|r7&i6YZa z3pw&j(@$)&{IrpS->p#Y$Zs&vdPMIJ7U6vn(;?_fK*x{cjsV@GC0ws2xrM<-9<(0% z2kCL)g}T#|4mbY#9_;(H>?b&tJ|WWvi0#L$74q_o>n(m8S?RiHtSjQD2+Ky`FH?w2 z60koL|0Az;Bn6W!%(_9lHCa?+f^5+YU zm5*a)AS%4Lr{371-{W$q!H1cV30xtvspBXZ=?#*JB(1EDWJ2$zMbu0bOM=5)he~e% zJ2V~*d39_D;<4kVYSuzn zsA~IC)y~DtP}T0G9EjyYIjs}c<ZrF!p zV-{U3qS?-7{5KJRdbY zOTK+IDQ-j<5%s6YExt@1aS6~rX_I(`l~6W~Ld`0XwK{F%DZ5iN7EtzLES7Dlmv>C= zxV&d_&rD9(R>s8CB_VssOvfF2c65vFk|~M(NDwSPq6!FzoEq_5@&5E(S5dt-z?~FepwNoB85dgvE2@xlkmIRA*CO z57m_Yf`m!p^Hh+?`-I)%2;%k8ZWTj8b^E>o5dY340JnWzn7nW~Fd3L>jg)K*m28~z zET!+9F#o%eSz98$gI0bKWM0dj7{mg!pverCN0k%=9KG;uffafTs|*>-A! zjD{#~#lX_QW2^r;9^xnD^^iyFt88Flmi?V3(yF<(Xr zeM8(8=ak$umLw;@Skm>E8$$&fBL$m61)G)%w&0vWX~ngduD(Qv9`Yt}liO4+7X7L5 zB`o$0+osInj151_$fffOdG~OBAvMAixqgQ)UA?|oPzPJJe+PTu7g@Dq1`pVg0Zewf zYyLx5bj)wHu>NmY=nPqG_KJ5vC+e*Kv3rcgAG045($)~nZsIT#oL^fbkgg-2R`(zL zCPa$Ca2|aoR_Ny>16{ouCi0aVP7UT>zC78we+E=Uqkwq zi`*Kmg#@G9xPmUyk(9?K4{D-jC%9PpsKH;XCJOjH4*DgE?`qcrF{(RBK7GvWO78v} z+=v4uj^bwqnjP)(ab(a}xV@N!Q+=+1F2}2Q9m{q=hws2C-9Ep=Ee^Owy8I0gR=7}B zUX29`b(2S{F+1HS`em&|4$euIVO$mL zk0<*fg`?Avr2gk&vriWe_a!XoL~e|gtfC|0j#&@V-2WA_fqanlw~_3cP0UI3c|L^*^80d=1^_(;!dbqqvf!x58F$yKt$5ZL+RyjRm}=F z2Cfe*Rc>8yg(`R4PTvtNuc8AwP*DL-ybYLFlGLxo#;v03=W|1Y*VCa zYp81L?ewk0b=s%xP~?U(s^}a}Q>eNroUx6W{5x)g6Wt%msJWBjU^Gv8$X*_{SFo^R zxcsp_Gn%z!Vdp{}j%Wolo`$wH^%>dTWrgBX+co|N`edzL1E)q>F|ZvBk&!RaVcG$0 zfyi0{5LF@jwI~D-8~>_=<%t+~Kcp^s8bfkG(I$5cTr8cP0#VtA4akALhOmzzo-F9rTA5IbhCY#~2I%2>fF3{uYRjuZAgi!9hVZ0QkOamZFYt&xo_A^b1jBO?mglj{r@PG;B@<`GqB&WsS-Kz@zDTBGBq9L%9-s6>KO7b1bv zmesXKk|X2Bgpt&N`OuM!Z_h(V3Q%kbjm2xiNaDH#Hi${`AkyajSR=UvP&zln#tv1# zL4(oo<|^*?4{9Qd#3dMW}4+ZQIu0#Lza$v_bsP(q74i_GQGbHMDwsyZ#_6 zQ#9k@bo@|yTsrpHL>DuwWL5$?d*kD`$glAXXt9p&T0={dhL(A8t<#Y@#J3JRoknfw z*(0pXi=XzB?=;|Ku@XZls~E!fi+9Om>jNqMq@?x}&pfsNxEQ49FnKYIE5~d6uawaW zq9ZL|y_@|mq1q%$1Jz=up36ggIo1i;LTRDmcKOzCR$g&_-H8Le#qSoA%-2CO-!@z% z3fX{sSeXtYF9@=&=})qOo5b5fEP9M9ik6iAk^*HAVeKfJ&w8iuW+6^1!@|b8N%`#? zf?35PRwE?Ma)yv?j97it{pXAcBKRbPtD!pCHrkIql~^aD$#%Fb0yS z@0dwC^I;V>;E;d$qE}XgHao-=nodQh-QpN!9rE}Tdb8Kv1N|6o=tzZe zXy1t6Ga#i19^d)S5g&}2#*_$dk8^`Kl)!E8iHZw6f-{Za+ee1z1B22GYEzJiFc%2kxZs$Zs< z1{~i%BQsr0o`TuETv#3{tP2&^%{4_f><(?%y;RsTd2C|;#4A(P(fr~_{`ye<`njB? z{Dz4m(USVPzPWS3qMZ{@GNQBMc6!BIT{n8K_uil%cj$<0I~>|}IK1vi_~fa`$>%~R zpNpKt(fpT!o!ybnS3;eyginf!iiO=1;g8hr3f1mf%5R=B$EiP-inmPh(Tw6?MbpA_ z3&(=xPlPg_n6lA&1KY%iy)tC4oU;Y(m3Qn-xWe2)Qu8)$MRIU`E7JeYeu#wUZMb5b zIKD3*+;(uM;r*R8tq#+V%Q^V^)acidcdboP-2M44Vgfb;Vxm)L05iC-CZ;A*BI?gL zT2|qi$46GkOvJg0p!@~E>JXF=ZPJA&e@Mu%1z8jtr1Z9}6lWQ0uh-saxZbdk6WM$) zwD}-zc~@5YueDezH{lx?{+= z>RbL1kz+-xP#oVP-`Vm<^fffQ@inp2mUP>~*OXtMjBhT5S#ygJSZlB~gL=7H2|F-u z+;Kyp9{+PTI#X~}olJUSL1N~ZPb7*~Yu%daj{6?eE79P?<q545b2YbZjWDB*rsrS&(&U$x(#s?1>qF^S z&LYm%kh3-7JQi{uTXG(cI6Felj^MM;1<$>(P`pPT5$+NWu-kTaA^j znn>}cBL9hca|mTV~nJKG)1 zt(&U~W;X=w4e@FDp}h5T*}>d;m;+>Q4%#HF_fU8U}v<%KgJunt)T&joQS4|We{N< zGY`TqR=F;A0{K>I=ho@>Q~cSDMe3*ZfCGWfhK4!++q)Jn+}^Nv!asFv>def^>9auy zR%$}&xSHq)9UC~pz7Uu2wL441<5d4s0N7u0&EJh$MSvcfW~0r4VtSvV?)?0`V8*(efzDyiG8R}i-fzmZ9OCY;vs(Jh_w%0SEN$FRE;n#Vb<)|!AVhw|e)C+d{ytI^sS`ztk|@cdDcO`L>zlG-#){-vr{nFCywmZH+Fgnt zKDsJupd=tyRDf1ul0sBs#3zVAX`pRr1g+hsA4XfCT=RsxY!pOkg#zj?MN)!P`P27i zZ*T9&J*#%oB{4fY^WMBSZ{Ezj_h#;2olYAC&##{T(Xg+TqW%*<)W@98Jbe=~Hz<~3 z=`eMUhPNS1jTp`uXr;_}&Io13uxZ46&P-DV>M+Hc-lJGEM~570W7_+!QOTbxn54ay zNBGg_rDdZiUW8Y{sGk>u{%}A;pr|wk^>i3Y{}_1T2p{JRtZRlEq*?ksEAU`=k2+^! zjgXp={y7V4hO~gSK+3QMkXl&=QX6Z9)Xv%7UX!C^1txTM(n(2l>V5yR=eBLq10N3@S*B z3Kgh%?agMxQz5HXqvlvcR*O`~u9j=>9GXQ=uxYT+Q`T*G$*U0pk!A zFuV=p@J-N;YBf>Q7V>2Q>@6ye_GYc!@S$H9YSZAnv*UHr#>j1nR>X-Juo1P1Vi(Oi|nu}%eISKNisep0XJZ&1M zyw1KcRMTF+$OS$AF=7129}I`Nh+ObeN5{nOjt;M3%GwhSdj?_R3eSyO+PCmHm8Q0C z8;*`}+eXJC!HI4C$J_dcxe-p-CgN+`IJCyM4MxK($G4A0hF~!=VFOd`UxX!c6Jpy$ z+YlGw_+S9>rrN#;euQI#{_Lz@s=G;c6ilo;m63J#^ww{~_O* zqkX-n&UmY3voJQw@iOD{1tUSx=aVh4P;wDbHj6<^m$e`mjr~Au7nGQNK7W7x)JRlCcbNVqlz=?SU~K8}_k5UbZ5%I62A* za+z8VMIb02Ai*ml8^nvU?e*cP7(F`TAL3-YB0*m;5REAKN|p%F%WmIjbaX6?fXIa)Gow6E2}HxP-4~7c0^z6-1o_#={UDI> zV1$j1dl}gTJsspxJ!CtI3f67x3SW&SCYBQdxW_2G7pDnhDIbI}iADt3>Vu~Jg5dKB z4B&W_=gRZF*~9w!qOSL~Es&Usn`H^clPas3FD(|;#`-`)8&fb0Nv5~Sm z6HLV~nzzkYuIxUxvg6l^V+*vNWNIX)2DpQ-uKl0XeO#BUJ95VvH^qm(Ew0oZ zSz)TBx+5uX_l!vaz4;A^X@+hoUrELzF`ku%&ZW~*!=425(u3wLA4YCR;InzpGA%WC z5l%Dk3L&c#1+-GOIo_1q(j{%_N-!^jbdpR3%C+PkQ};hl%c=UKw17MKKh!&3>#zjU z+cXqVRAyth!K#7ghM1`hWj1gENs?JGj1~>*ayCuJ=#XkUX+U5gv8F|{3Wer?t^r_S zEsF&?P|5DGZ|P0{;aHR(SA2=-~fLHUGrlNe_50>Te{Zin1OZ7 zQlZQ?uGK6$RWmRzKek1e3PWd)K*m7PS_3-n#X?nTvy?9*GoYT?*fsb(G%c)ku}GI@ ziH57@faZq9VwGl|7E9RDJiX8{kJj}fBT?u@g-Ta@=b>4a+lxH7xE!u|*m8iaSyKp~ zY9Dh(L1!LldIlqaOCEWk%{n!&y>)rFfEHF{k3b&WjKQk42bekYCJ$ytFY;rG4QgGe zQO#*@{dU<(mRYP)H3xd1(K&!`(y-N>Ztrmp=JY;mZZ)fz+B**?)p;mx)-cuFVoesu z8N(j%bxh4X99!7hHRGk%TOCt050!S6H|@PxrPiGPIA;yXLt9@WdQ|iz;?b3e&WzNju403pW?T||$j}~D2HKl#0N76LTg|bJiyKva zqA7itklw1(L|phy?=jjslZP8U>}G&{N##L%Yi(uejE;n~HEY@!GwP0M363e-lCw7& zb@#?KYfu*D%u23t7&Ee)f%h)0M9sZ$Zv;0k&#t0R#|w1OQ(W`BkWR_s7EO+ml()4{ zHf--uf;23Pwzp{@Dh~I14a8Fl%NA~8)E{AaWaADkTgJKI(6C568`;2(-!Ujo4q8WE zlWgRp`1)MDSs{?$G?JQ1S@Xz-xGffiE7#{|JLPQzhNq2h;w? z8);u@|9;sN5x8;LJU$#0IpD}JFeGmnhE9dCW8yHd9N`3TO)hf~wE~Y0U@TD{oiDxz zT9pkE0p#VH1pgu$4ySt}+lB#VDjE?10ct05YQ2h-(o&0zW0Q(^BU}8D0H99Ufz`-h zaA=I@_UBlxC|L|iJdHqtA*oq91i7_ONDZiERpf!xvt%YGC5I9s`BaE>>a@h}_6}W^7*PuAy=RwbCj`so+0*;C23XkE1=S+9lKQh4j_fPFu z?=t1Oj_uvyC`et{4;cj~fUV)83BJ^l_``QTdMCN(gtX^GsqF>r^g?b7Y)N@<+fiY2xM%uRThfzS?Afqsb2FH*8Y;Z6FF$QbTzyQw$ zhPeoUWE9d{&!bFb^J~0+ghTZVT$GE3_#o>8E!X;8LW&ff*Gf%TDq9rdvduRX^^J`Z z2i$xJG-*<{p^NTAt(uh0C;S6kSY}jh(*QWYauGVlX{T24_+^J8eBU54#@8aO ziGhou!a&R#!zQ;hc~N_WiIQp|>H?pgQEH{-oC?gX>_ z0ka{=G)YX;!s+;>6{ZP_03^w@NK8wdUTRojS`tj>GYeH#N!poOE#0EE(zD=SGA-}M zmJaBkJ!I_Y$Io>w^e#31aN9@Q04&KImYBn-!lIiE3(e?}AEBR7v~|nFs@hxLdGErp zrBI@(2OMfQI{3h<;u$X##kVi@ub^+;h0R)Lt#exzUQRIEl1!(>bSe$DV1v7`z1D~I zjkjX+vG}p&P@?`Qy3IAjCr1A~$uvkz1Mp5SH?1%Y3FehGRVhc~LT|FEOKR!@2jANL zjG<~hw~o#qT?nn#Y{$kb2}Y&FR3@1^iK$!I9zVTwd4;JdYH!Z)p!c-=hUQ+Cp7;n5`31s0- zFuU)k6}o#NxLoo{?Z+U%!%60Z#GJ@d=#y!M&cI$wRo7!c3RP+A&$o8m>0LU#d@0_0 zZ)*>K0p@DXj)oo^uB=Z#fGF7w40glE+DC6cQ^V4|)Z5^V<%`OwP&9S5#DuM5>}SoR zYwKaeC%yNP0Ja{UeN98~$r{CsjiwhD(d?}}ykrhHw6<9zz(OC_J}+!b&l@&n_iKon zHdrY!;~VN7>g1uFmJLY%1CYK^%tTOhBN;lDy?(nfquQ%!(+k?ft!~W|GpS?7mq2_g zbEu?&fmLoE%o^FN7hXW6LBmyZ8Wn-QdIkD{8}yn7`jM6pzv@_-my`to^)0i!0XE(rK$ztihK^m+i%Wg|q7Dm4#0W{SCTD7wA`MTV_n zt05Yq%FP{f>ryQOs-XB4`}f+Keos9)J?+zasOG*@Prqtw`aS)Mt<4#(dQH?MwUH8=)Lt}Ed?&<; zwfU;2)%x?bU@;Q~3bm^3X>W+F+0+$;rp^LgajRMjRQFGtzYOC-vV_``fJFh@K{9+wE&i06;GhTM z1{frP=s`Pw7-}BjKIx_T{RqXp#=)^R-{r}%h;XhEA0L-bw1`+5LzS!nS8Mn(;#VlW z6F@fes4MfJ0lalnABoZsb_k2$x0}P!aq!1!nVt|3Kka4tAgkw!=N`|lcg3#(o`AdX z6)Fzyz@5&e-FNmcZ(lzBapxypA9wwzdu7X!D-<#LfTr;xH~9$Hn<-N}92G-6CmIea zp(NsoV;q6!!a;6Owhu&kIHZT;V{w>A?~cb6#B0{vasB|7q7X?Ch~JI%(7_-cQS*E8 zD?3nxfR9*6WE$cXBuXUP#(DoJTq+m>8fT!2M{)D7Vd95ms;Ij+IyMmI+O&|tW_}!M zWEVth2BW^fa4^imNxEDB$IBugo#ZcKEd;zU2qIfph%&(mI`PPjhx&SDOAvxhyvSD} z4Ll!`3&KG`M5QUmFH6U#*8G0vtK?hC}lxFUnRfG6pdMya$1%5&s@iWq^t>9t0^g zV3`M#04772aF`52l0NDuR|%{TEF1A54?M=9cpO#Pg)Tp-P=W!anQxZJQHc?F3zcX9 zM7;2Bfb7D~2|ft_VK@XXEno{kYb+eb8wkVvc|sckD!xE;46Z!TL5SI5q~kVH#`uhE z#47_Pav#A)7)S>hu*4T8!4w;!D0ukpFE&-IV472nK^`NXO zS=KC-H7CnXlw1vYbnQuYkjkQ_Z&5k!3nBWyffn56X*FG#Bpv%cP~?T z^U?>6A2#1^PB7jz_u~ZS%H;&g90O z(#D;u6`fD00_XlY(|tJUKRkc<)`|HO@sgx>ujJjk+__rw>YVj{ap{dc*Z17mcYWVN zWumw>RnnL&@k%A$c;`}SyzO4eOZQ95Z=AV)=EnK!=NFFND{X&JUY#s&lgiuT?7i}x zsfy-gMVnO778jS^j7RQO?E9q~NIq_&tmR2K{fB=KUIR!lM?nguWi!_MO>ObWYSX@_ z)OPCyT5@=1dL*}J&NLTHZ780byxu-@5HrE+Z8HZSv~(;T`n+ZDTxYU)1HIb_dyyq zgQKzuIK8R%?aLdH!B;f?5Vcnq6(s2_$L3RoHQyatV3W;zrRKfMdp`}X*1Zm`IKM`x zJNY{RWD(i;!5Ivd9G2P+e^$BD|Mu#p^GM}_M&&C({F=1!OFxZ@@SA6~RAK!S%498m z=x|>SZeyqwx2jQ+;>+zp$wq&xxn#>WqL`7pHDct zla3zA(eo+4;^;{@j@@@``0ZmeAUqe)^7#9g57eDvm_{p`U&LN%oacy_+L?_e8)32LEgAqgp)}$Iyqk2xoPC1-WF3^vMH| zIzGN?2hdpgVf z>xa8MnJtNIQJyx>>#)Uid7d*{J^iqob$Q^#!aT|cAr6l*kvmH0n#hgpH?o<#3_*Gl zrN+%e**3lhpi}kh<&(1?{u=-Z9!SU)u$990xELQ?II+2h zCxHHc5&_({C9b`qE*W8fx}=?7Xeje!tIL;FFEBHwHmwzI_I{s{G5=RUkpDwSKpX!W z^BMgkvgYTo?1zx7k?!}QXsS8CbhD{Rh<*eTBIJ~7=Th&|?&XS4y`NUEI52i=Jw-pT zm)taeZm&(%Z(OH?4;nUMSsm!*wG*=^-tSWeBO^d)8Rs6E|383CzIY|yB|@}Cc|s;N zr@i%VhQZ)y0GXV+F7QP!p6jArMa#Zs4l}^eH-;AQfgs$9^l-rl=UIER))NJLn^Z+S zr+605d^~Iv4A8LXxrj$QT%_G=QN}5=lJN7;rZQ|eo^bk#t4OwEF$Ldx*CNxWL_bAv zoYq&Ul--@Q*TSfP4b*bG<-_*d?HK$%C~ZHOXza}l2W+#>4J#YIcF*y~`jJ72laWD> z0e{W_>j31G2c(B}Yo2V?=RbnVJBBP}{1Fsncjq1W)>{XmJ8%XEM_vB`08i0%gAS!H zX`;dAn037G`v2jV{~MsjuVoZH^Qju$DU-fb`(KFmx0qajB#=>7_&{|fVqAbsJ_ToK zvcAxh27R@Kun|@Dg(8Qmiu4x^iQY;DzZo!~PN|au++1@Xx%u7C}PCx>dKPqgqWN(gd`rN)P zRa_3%lDjzR@=7i^KZ!T4xZ0Agosw(ks%zJbG3745_U`PvtM2-wd$Z);950RwcPdxi zJ6D*U>qh{2BO~x#$mAP=FOnU|meN~xAXpFDNrJ-0X;aJ?BOwI{P&*(nMfs2>d1xv^ zlfx3LTB5zzO&M6uH$t^+1b2>H!d3==7#3zCdwv<~wHxZ>Hg+qN@mnDga7%)rPwW5x*+@YebH^G_(FwQTm}Oz&Jv z%3VA+z3OgCweOlUB??=AQds)90BXUSS1&Td)#3HSky%&p2xjfNGD#`x22IwDv?WD4 zoMS>wVy7C`YnZZhz}*SOJN_;92?I!=V7P!}%z^A32=hcea0AV!9&ado@t*CNLp%i|)(qyp_HuCuPXK!n%6ug1z2$$lHa^X{mQV}T>qq>-e*2QKY5pagEn8FpM(r1 z^TsC*qq*^kjWJh0DKVS-=_f9Ox%>%3k^*z*lMNO?EHs!Ke{G}9jikGzb@(kpfp`&Y zMUE#y9wq#O+aty=A^|ZP4GT(agz1k$sOd5nCWv>GRhKXemthn+?dMkk6USD-=>%Z| kn*J$O@-wRZrV#qLtM{PuZQIBGF3nA&G*5NGO7? z&`T6SK}9`u!S1Dz-7E^i!iaV^k!{Veb$3rQ)mEH!Ju`FWtb5jTWOmNXeE)Ce`^|Uu zEPHX^qKe`)TZRn)(n?DTD{-Aqigh@CJh!2`9aon11?2?*7aQ%tmBVlw)l?SGMQ@vP zcj89o>XOQGfE^P78g>H&a94vHU~3+Lw+dk95rFh9C$24?jR%IWDl0AoiTs_qdFBxA zN!?Piyar%O7AdIi^qg(DGo`k)yeP$!l97t0w{Oh8g(rd1!h)rB2<7KDHDL?mFbEg~ zhA;s{8~f$U`J?S4M;tdH^L&JmomR(cXEA3Un>FLWdR85;JvD$EO=ai%f}NFpecd2Q zA>R2Eb?L5UAcduUGp6sUQ#2M}V50T$5b$Xld}J-igtk9yuHPGJYgtnR2!(sn zv|NbXcf24_1JE+<<-teV@qj=LAhM`<*IGkJcmM>rmJoCSKuZX^0iYEGT>;Png6;r_ zhM-FTA|dD&fG7yM1|R~0?g6NUkZ=HkLGnf*`$1kTJ!q+KU{xj@fUd3%))@ZUn-JQ` z3L)VDeCccjkLMlmW&(k5=i#QKf2k;(SQN(NKJ0WN@P285_wOG;I4p6^KgwxYhlNz{ zDkU5M6V6GO3x8nX;)v@)@AnZE#HbJjj|*1&)!qU^b^x?-H+$ zdIFiDCIBYq)IfIDTG>>}OGxD|9W%dB{HGB?ak z;Q&TCa+w!F1iU(~$^H`w2k@Won5Tijx0quC4Fm!`0}XSH2?yZuzEE6<+w(lihEDe^ zN~g9%IDnUJCl%M!_Bz^zSEo3cf`M=VU;VeC6ao1b+X$sBvChlq1Ft;jaU1 zb`!jM(+Hp4tuSrs8W@v4<=2u(+COPM4nF@~a5|%>jivkSe)dcEwfkPbI>vaT%&C7n zaPdkG)92RTd&1!J1);b1x6Eoq;BZ)g1Uk^ctCRa&SoW4Gw&<;pd*W=9Ky7yN(>b<- zSI0KXKkI?FA`(x@m0(+b$H6{IqMJ&H(&`c8k{OVB4{*)l9oscW0n& z@+8|hYYNK1-_K)zcB7q0g&r9Qq>Q?c`5rH)p7Y8oX;Qnai zRgvHJ`EdD&3pqCqgFw;}sLmU|0S8w`{x5)_AeVHYv#!k@_ldjGqKd)`bE|g!1jiye A8UO$Q literal 0 HcmV?d00001 diff --git a/custom_file_dialog.py b/custom_file_dialog.py index a6ca54e..e4d74e6 100644 --- a/custom_file_dialog.py +++ b/custom_file_dialog.py @@ -1,7 +1,56 @@ +import os +import shutil import tkinter as tk from tkinter import ttk -import os -from functools import partial +from datetime import datetime + + +class Tooltip: + def __init__(self, widget, text, wraplength=250): + self.widget = widget + self.text = text + self.wraplength = wraplength + self.tooltip_window = None + self.id = None + self.widget.bind("", self.enter) + self.widget.bind("", self.leave) + self.widget.bind("", self.leave) + + def enter(self, event=None): self.schedule() + def leave(self, event=None): self.unschedule(); self.hide_tooltip() + + def schedule(self): self.unschedule( + ); self.id = self.widget.after(500, self.show_tooltip) + + def unschedule(self): + id = self.id + self.id = None + if id: + self.widget.after_cancel(id) + + def show_tooltip(self, event=None): + x, y, _, _ = self.widget.bbox("insert") + x += self.widget.winfo_rootx() + 25 + y += self.widget.winfo_rooty() + 20 + self.tooltip_window = tw = tk.Toplevel(self.widget) + tw.wm_overrideredirect(True) + tw.wm_geometry(f"+{x}+{y}") + style = ttk.Style() + try: + bg = style.lookup("Tooltip", "background", default="#FFFFE0") + fg = style.lookup("Tooltip", "foreground", default="black") + except tk.TclError: + bg = "#FFFFE0" + fg = "black" + label = ttk.Label(tw, text=self.text, justify=tk.LEFT, background=bg, foreground=fg, + relief=tk.SOLID, borderwidth=1, wraplength=self.wraplength, padding=(4, 2, 4, 2)) + label.pack(ipadx=1) + + def hide_tooltip(self): + tw = self.tooltip_window + self.tooltip_window = None + if tw: + tw.destroy() class CustomFileDialog(tk.Toplevel): @@ -9,249 +58,384 @@ class CustomFileDialog(tk.Toplevel): super().__init__(parent) self.parent = parent self.title("Datei auswählen") - self.geometry("800x600") # Standardgröße, kann angepasst werden - # Macht das Dialogfenster modal zum Hauptfenster + self.geometry("900x650") + self.minsize(650, 400) self.transient(parent) - self.grab_set() # Fängt alle Ereignisse ab, bis der Dialog geschlossen wird + self.grab_set() self.selected_file = None self.current_dir = os.path.abspath( - initial_dir) if initial_dir else os.getcwd() - self.filetypes = filetypes if filetypes else [("All files", "*.*")] - self.current_filter_pattern = "*.*" # Standardfilter - - # Icons (Platzhalter, müssten geladen werden) - # Sie müssen hier Ihre eigenen Icons laden oder generieren - # Beispiel: self.folder_icon = tk.PhotoImage(file="path/to/your/folder_icon.png") - # Für den Anfang verwenden wir leere PhotoImages - self.folder_icon = tk.PhotoImage( - file="./water-folder.png") - self.file_icon = tk.PhotoImage( - file="./text-x-generic.png") - self.iso_icon = tk.PhotoImage( - file="./media-optical.png") - - self._create_widgets() - - # Filter-Combobox initialisieren - filter_descriptions = [desc for desc, pattern in self.filetypes] - self.filter_combobox["values"] = filter_descriptions - # Ersten Filter als Standard setzen - self.filter_combobox.set(filter_descriptions[0]) - # Den initialen Filter explizit setzen, da <> nicht immer ausgelöst wird + initial_dir) if initial_dir else os.path.expanduser("~") + self.filetypes = filetypes if filetypes else [("Alle Dateien", "*.*")] self.current_filter_pattern = self.filetypes[0][1] + self.history = [self.current_dir] + self.history_pos = 0 + self.view_mode = tk.StringVar(value="icons") + self.resize_job = None + self.last_width = 0 - self._populate_files() + self.load_icons() + self.create_styles() + self.create_widgets() + self.update_status_bar() + self.after(50, self.populate_files) - # Behandelt das Schließen des Fensters - self.protocol("WM_DELETE_WINDOW", self._on_closing) - self.wait_window(self) # Wartet, bis das Fenster geschlossen wird + def load_icons(self): + try: + self.folder_icon_large = tk.PhotoImage( + file="./folder-water.png").zoom(1) + self.file_icon_large = tk.PhotoImage( + file="./document.png").zoom(1) + self.iso_icon_large = tk.PhotoImage( + file="./media-optical.png").zoom(1) + self.folder_icon_small = tk.PhotoImage(file="./folder-water.png") + self.file_icon_small = tk.PhotoImage(file="./document.png") + self.iso_icon_small = tk.PhotoImage(file="./media-optical.png") + except tk.TclError: + self.folder_icon_large = tk.PhotoImage(width=48, height=48) + self.file_icon_large = tk.PhotoImage(width=48, height=48) + self.iso_icon_large = tk.PhotoImage(width=48, height=48) + self.folder_icon_small = tk.PhotoImage(width=16, height=16) + self.file_icon_small = tk.PhotoImage(width=16, height=16) + self.iso_icon_small = tk.PhotoImage(width=16, height=16) - def _create_widgets(self): - # Hauptframe + def create_styles(self): + style = ttk.Style(self) + self.selection_color = "#0078D7" + style.map('Item.TFrame', background=[ + ('selected', self.selection_color)]) + style.configure("Treeview.Heading", relief="raised", + borderwidth=1, font=('TkDefaultFont', 10, 'bold')) + style.configure("Treeview", rowheight=24) + style.layout("Treeview.Row", + [('Treeview.row', {'children': [('Treeview.padding', {'children': [('Treeview.indicator', {'side': 'left', 'sticky': 'ns'}), ('Treeview.image', {'side': 'left', 'sticky': 'ns'}), ('Treeview.text', {'side': 'left', 'sticky': 'ns'})], 'sticky': 'nsew'})], 'sticky': 'nsew'})]) + + def create_widgets(self): main_frame = ttk.Frame(self, padding="10") main_frame.pack(fill="both", expand=True) - # Canvas-Bereich soll sich ausdehnen - main_frame.grid_rowconfigure(1, weight=1) - main_frame.grid_columnconfigure(0, weight=1) + paned_window = ttk.PanedWindow(main_frame, orient=tk.HORIZONTAL) + paned_window.pack(fill="both", expand=True) - # Pfad-Navigation - path_frame = ttk.Frame(main_frame) - path_frame.grid(row=0, column=0, sticky="ew", pady=(0, 5)) - path_frame.grid_columnconfigure(1, weight=1) + sidebar_frame = ttk.Frame(paned_window, padding=5) + paned_window.add(sidebar_frame, weight=0) + sidebar_frame.grid_rowconfigure(1, weight=1) - ttk.Button(path_frame, text="Up", command=self._go_up_dir).grid( - row=0, column=0, padx=(0, 5)) - self.path_entry = ttk.Entry(path_frame, state="readonly") - self.path_entry.grid(row=0, column=1, sticky="ew") + # --- Navigation buttons in Sidebar --- + sidebar_nav_frame = ttk.Frame(sidebar_frame) + sidebar_nav_frame.grid(row=0, column=0, sticky="ew", pady=(0, 10)) + self.back_button = ttk.Button( + sidebar_nav_frame, text="◀", command=self.go_back, state=tk.DISABLED, width=3) + self.back_button.pack(side="left", fill="x", expand=True) + self.home_button = ttk.Button(sidebar_nav_frame, text="🏠", command=lambda: self.navigate_to( + os.path.expanduser("~")), width=3) + self.home_button.pack(side="left", fill="x", expand=True, padx=2) + self.forward_button = ttk.Button( + sidebar_nav_frame, text="▶", command=self.go_forward, state=tk.DISABLED, width=3) + self.forward_button.pack(side="left", fill="x", expand=True) - ttk.Label(path_frame, text="Dateityp:").grid( - row=0, column=2, padx=(10, 5)) - self.filter_combobox = ttk.Combobox(path_frame, state="readonly") - self.filter_combobox.grid(row=0, column=3, sticky="ew") + sidebar_buttons_frame = ttk.Frame(sidebar_frame) + sidebar_buttons_frame.grid(row=1, column=0, sticky="nsew") + sidebar_buttons_config = [ + {'name': 'Downloads', 'unicode': '📥', 'path': os.path.join( + os.path.expanduser("~"), "Downloads")}, + {'name': 'Dokumente', 'unicode': '📄', 'path': os.path.join( + os.path.expanduser("~"), "Documents")}, + {'name': 'Bilder', 'unicode': '🖼️', 'path': os.path.join( + os.path.expanduser("~"), "Pictures")}, + {'name': 'Musik', 'unicode': '🎵', 'path': os.path.join( + os.path.expanduser("~"), "Music")}, + {'name': 'Videos', 'unicode': '🎬', 'path': os.path.join( + os.path.expanduser("~"), "Videos")}, + ] + for config in sidebar_buttons_config: + btn = ttk.Button(sidebar_buttons_frame, text=f" {config['unicode']} {config['name']}", + command=lambda p=config['path']: self.navigate_to(p), style="Sidebar.TButton") + btn.pack(fill="x", pady=1) + ttk.Style().configure("Sidebar.TButton", anchor="w", padding=5) + + content_frame = ttk.Frame(paned_window, padding=(5, 0, 0, 0)) + paned_window.add(content_frame, weight=1) + content_frame.grid_rowconfigure(1, weight=1) + content_frame.grid_columnconfigure(0, weight=1) + + top_bar = ttk.Frame(content_frame) + top_bar.grid(row=0, column=0, sticky="ew", pady=(5, 5)) + top_bar.grid_columnconfigure(0, weight=1) + self.path_entry = ttk.Entry(top_bar) + self.path_entry.grid(row=0, column=0, sticky="ew") + view_switch = ttk.Frame(top_bar, padding=(5, 0)) + view_switch.grid(row=0, column=1) + ttk.Radiobutton(view_switch, text="Kacheln", variable=self.view_mode, + value="icons", command=self.populate_files).pack(side="left") + ttk.Radiobutton(view_switch, text="Liste", variable=self.view_mode, + value="list", command=self.populate_files).pack(side="left") + self.filter_combobox = ttk.Combobox( + top_bar, values=[ft[0] for ft in self.filetypes], state="readonly", width=15) + self.filter_combobox.grid(row=0, column=2, padx=5) self.filter_combobox.bind( - "<>", self._on_filter_select) - # Optional: Pfad im System-Explorer öffnen - # Canvas für Dateianzeige (Kachelansicht) - self.canvas_frame = ttk.Frame(main_frame) - self.canvas_frame.grid(row=1, column=0, sticky="nsew") - self.canvas_frame.grid_rowconfigure(0, weight=1) - self.canvas_frame.grid_columnconfigure(0, weight=1) + "<>", self.on_filter_change) + self.filter_combobox.set(self.filetypes[0][0]) - self.canvas = tk.Canvas( - self.canvas_frame, bg="white", highlightthickness=0) - self.canvas.grid(row=0, column=0, sticky="nsew") + self.file_list_frame = ttk.Frame(content_frame) + self.file_list_frame.grid(row=1, column=0, sticky="nsew") + self.bind("", self.on_window_resize) - self.v_scrollbar = ttk.Scrollbar( - self.canvas_frame, orient="vertical", command=self.canvas.yview) - self.v_scrollbar.grid(row=0, column=1, sticky="ns") - self.canvas.configure(yscrollcommand=self.v_scrollbar.set) + bottom_frame = ttk.Frame(content_frame) + bottom_frame.grid(row=2, column=0, sticky="ew", pady=(5, 0)) + bottom_frame.grid_columnconfigure(0, weight=1) + self.status_bar = ttk.Label(bottom_frame, text="", anchor="w") + self.status_bar.grid(row=0, column=0, sticky="ew") + action_buttons_frame = ttk.Frame(bottom_frame) + action_buttons_frame.grid(row=0, column=1) + ttk.Button(action_buttons_frame, text="Öffnen", + command=self.on_open).pack(side="right") + ttk.Button(action_buttons_frame, text="Abbrechen", + command=self.on_cancel).pack(side="right", padx=5) - self.h_scrollbar = ttk.Scrollbar( - self.canvas_frame, orient="horizontal", command=self.canvas.xview) - self.h_scrollbar.grid(row=1, column=0, sticky="ew") - self.canvas.configure(xscrollcommand=self.h_scrollbar.set) + def on_window_resize(self, event): + new_width = self.file_list_frame.winfo_width() + if self.view_mode.get() == "icons" and abs(new_width - self.last_width) > 50: + if self.resize_job: + self.after_cancel(self.resize_job) + self.resize_job = self.after(200, self.populate_files) + self.last_width = new_width - # Frame zum Halten der Kacheln - self.inner_frame = ttk.Frame(self.canvas) - self.canvas.create_window((0, 0), window=self.inner_frame, anchor="nw") - - self.inner_frame.bind("", lambda e: self.canvas.configure( - scrollregion=self.canvas.bbox("all"))) - # Für Klicks auf leeren Bereich - self.canvas.bind("", self._on_canvas_click) - - # Buttons - button_frame = ttk.Frame(main_frame) - button_frame.grid(row=2, column=0, sticky="ew", pady=(5, 0)) - button_frame.grid_columnconfigure(0, weight=1) # Leerraum links - ttk.Button(button_frame, text="Öffnen", command=self._on_open).grid( - row=0, column=1, padx=(0, 5)) - ttk.Button(button_frame, text="Abbrechen", - command=self._on_cancel).grid(row=0, column=2) - - def _populate_files(self): - # Lösche alle vorhandenen Kacheln - for widget in self.inner_frame.winfo_children(): + def populate_files(self): + for widget in self.file_list_frame.winfo_children(): widget.destroy() - - self.path_entry.config(state="normal") self.path_entry.delete(0, tk.END) self.path_entry.insert(0, self.current_dir) - self.path_entry.config(state="readonly") + self.selected_file = None + self.update_status_bar() + if self.view_mode.get() == "list": + self.populate_list_view() + else: + self.populate_icon_view() + + def populate_icon_view(self): + canvas = tk.Canvas(self.file_list_frame, highlightthickness=0) + v_scrollbar = ttk.Scrollbar( + self.file_list_frame, orient="vertical", command=canvas.yview) + style = ttk.Style(self) + bg_color = style.lookup("TFrame", "background") + canvas.configure(bg=bg_color) + canvas.pack(side="left", fill="both", expand=True) + v_scrollbar.pack(side="right", fill="y") + container_frame = ttk.Frame(canvas, style="TFrame") + self.container_frame = container_frame + canvas.create_window((0, 0), window=container_frame, anchor="nw") + container_frame.bind("", lambda e: canvas.configure( + scrollregion=canvas.bbox("all"))) - files_and_dirs = [] try: - for item in os.listdir(self.current_dir): - full_path = os.path.join(self.current_dir, item) - if os.path.isdir(full_path): - files_and_dirs.append((item, "dir")) - elif os.path.isfile(full_path): - # Dateien nur hinzufügen, wenn sie dem aktuellen Filter entsprechen - if self._matches_filetype(item): - files_and_dirs.append((item, "file")) + items = os.listdir(self.current_dir) except PermissionError: - # Fehlerbehandlung für nicht zugängliche Verzeichnisse - ttk.Label(self.inner_frame, - text="Zugriff verweigert.").pack(pady=20) - return - except Exception as e: - ttk.Label(self.inner_frame, text=f"Fehler: {e}").pack(pady=20) + ttk.Label(container_frame, text="Zugriff verweigert.").pack(pady=20) return - # Sortieren: Ordner zuerst, dann Dateien, alphabetisch - files_and_dirs.sort(key=lambda x: (x[1] == "file", x[0].lower())) + item_width = 120 + item_height = 100 + frame_width = self.file_list_frame.winfo_width() + col_count = max(1, frame_width // item_width) + row, col = 0, 0 + for name in sorted(items, key=str.lower): + path = os.path.join(self.current_dir, name) + is_dir = os.path.isdir(path) + if not is_dir and not self._matches_filetype(name): + continue - # Kachel-Layout (Beispiel: 4 Spalten) - col_count = 4 - for i, (name, item_type) in enumerate(files_and_dirs): - row = i // col_count - col = i % col_count - - icon = self.folder_icon if item_type == "dir" else ( - self.iso_icon if name.lower().endswith(".iso") else self.file_icon) - - # Kachel-Frame item_frame = ttk.Frame( - self.inner_frame, relief="solid", borderwidth=1, padding=5) - item_frame.grid(row=row, column=col, padx=5, pady=5, sticky="nsew") - # Text soll sich ausdehnen - item_frame.grid_rowconfigure(1, weight=1) - item_frame.grid_columnconfigure( - 0, weight=1) # Icon/Text zentrieren + container_frame, width=item_width, height=item_height, style="Item.TFrame") + item_frame.grid(row=row, column=col, padx=5, pady=5) + item_frame.grid_propagate(False) - # Daten an den Frame anhängen - item_frame.file_path = full_path - item_frame.item_type = item_type - - # Icon + icon = self.folder_icon_large if is_dir else ( + self.iso_icon_large if name.lower().endswith(".iso") else self.file_icon_large) icon_label = ttk.Label(item_frame, image=icon) - icon_label.grid(row=0, column=0, pady=(0, 5)) - # Daten an das Icon-Label anhängen - icon_label.file_path = full_path - icon_label.item_type = item_type + icon_label.pack(pady=(10, 5)) + name_label = ttk.Label( + item_frame, text=self.shorten_text(name, 15), anchor="center") + name_label.pack(fill="x", expand=True) - # Dateiname - # wraplength für Zeilenumbruch - name_label = ttk.Label(item_frame, text=name, - wraplength=100, anchor="n") - name_label.grid(row=1, column=0, sticky="ew") - # Daten an das Name-Label anhängen - name_label.file_path = full_path - name_label.item_type = item_type + Tooltip(item_frame, name) + for widget in [item_frame, icon_label, name_label]: + widget.bind("", lambda e, + p=path: self.on_item_double_click(p)) + widget.bind("", lambda e, + p=path: self.on_item_select(p, item_frame)) - # Bindungen für Klicks (mit functools.partial) - item_frame.bind( - "", partial(self._on_item_click, full_path, item_type)) - icon_label.bind( - "", partial(self._on_item_click, full_path, item_type)) - name_label.bind( - "", partial(self._on_item_click, full_path, item_type)) + col += 1 + if col >= col_count: + col = 0 + row += 1 - item_frame.bind( - "", partial(self._on_item_double_click, full_path, item_type)) - icon_label.bind( - "", partial(self._on_item_double_click, full_path, item_type)) - name_label.bind( - "", partial(self._on_item_double_click, full_path, item_type)) + def populate_list_view(self): + tree_frame = ttk.Frame(self.file_list_frame) + tree_frame.pack(fill='both', expand=True) + columns = ("name", "size", "type", "modified") + self.tree = ttk.Treeview(tree_frame, columns=columns, show="headings") + self.tree.heading("name", text="Name", anchor="w") + self.tree.column("name", anchor="w", width=300, stretch=True) + self.tree.heading("size", text="Größe", anchor="e") + self.tree.column("size", anchor="e", width=120, stretch=False) + self.tree.heading("type", text="Typ", anchor="w") + self.tree.column("type", anchor="w", width=120, stretch=False) + self.tree.heading("modified", text="Geändert am", anchor="w") + self.tree.column("modified", anchor="w", width=160, stretch=False) + v_scrollbar = ttk.Scrollbar( + tree_frame, orient="vertical", command=self.tree.yview) + h_scrollbar = ttk.Scrollbar( + tree_frame, orient="horizontal", command=self.tree.xview) + self.tree.configure(yscrollcommand=v_scrollbar.set, + xscrollcommand=h_scrollbar.set) + self.tree.pack(side="left", fill="both", expand=True) + v_scrollbar.pack(side="right", fill="y") + h_scrollbar.pack(side="bottom", fill="x") + self.tree.bind("", self.on_list_double_click) + self.tree.bind("<>", self.on_list_select) - def _go_up_dir(self): - parent_dir = os.path.dirname(self.current_dir) - if parent_dir != self.current_dir: # Verhindert, dass man über das Root-Verzeichnis hinausgeht - self.current_dir = parent_dir - self._populate_files() + try: + items = os.listdir(self.current_dir) + except PermissionError: + return - def _on_item_click(self, path, item_type, event): - print(f"DEBUG: _on_item_click - Path: {path}, Type: {item_type}") - # Hier können Sie eine visuelle Auswahl hervorheben - self.selected_file = path # Temporär speichern + for name in sorted(items, key=str.lower): + path = os.path.join(self.current_dir, name) + is_dir = os.path.isdir(path) + if not is_dir and not self._matches_filetype(name): + continue + try: + stat = os.stat(path) + modified_time = datetime.fromtimestamp( + stat.st_mtime).strftime('%d.%m.%Y %H:%M') + if is_dir: + icon = self.folder_icon_small + file_type = "Ordner" + size = "" + else: + icon = self.iso_icon_small if name.lower().endswith( + ".iso") else self.file_icon_small + file_type = "Datei" + size = self._format_size(stat.st_size) + self.tree.insert("", "end", text=name, image=icon, values=( + name, size, file_type, modified_time)) + except (FileNotFoundError, PermissionError): + continue - def _on_item_double_click(self, path, item_type, event): - print( - f"DEBUG: _on_item_double_click - Path: {path}, Type: {item_type}") - if item_type == "dir": - self.current_dir = path - self._populate_files() + def on_item_select(self, path, item_frame): + for child in self.container_frame.winfo_children(): + child.state(['!selected']) + item_frame.state(['selected']) + self.selected_file = path + self.update_status_bar() + + def on_list_select(self, event): + if not self.tree.selection(): + return + item_text = self.tree.item(self.tree.selection()[0])['text'] + self.selected_file = os.path.join(self.current_dir, item_text) + self.update_status_bar() + + def on_item_double_click(self, path): + if os.path.isdir(path): + self.navigate_to(path) else: self.selected_file = path - self.destroy() # Dialog schließen und ausgewählte Datei zurückgeben - - def _on_open(self): - if self.selected_file and os.path.isfile(self.selected_file): self.destroy() + + def on_list_double_click(self, event): + if not self.tree.selection(): + return + item_text = self.tree.item(self.tree.selection()[0])['text'] + path = os.path.join(self.current_dir, item_text) + if os.path.isdir(path): + self.navigate_to(path) else: - # Optional: Fehlermeldung, wenn keine Datei ausgewählt oder Ordner doppelt geklickt wurde - print("Bitte eine Datei auswählen oder einen Ordner doppelt klicken.") + self.selected_file = path + self.destroy() - def _on_cancel(self): - self.selected_file = None # Nichts ausgewählt - self.destroy() - - def _on_closing(self): - self.selected_file = None # Nichts ausgewählt, wenn Fenster geschlossen wird - self.destroy() - - def _matches_filetype(self, filename): - # Wenn der aktuelle Filter "*.*" ist, passen alle Dateien - if self.current_filter_pattern == "*.*": - return True - - # Ansonsten prüfen, ob die Datei zum aktuellen spezifischen Filter passt - ext = self.current_filter_pattern[2:].lower() - return filename.lower().endswith("." + ext) - - def _on_filter_select(self, event): + def on_filter_change(self, event): selected_desc = self.filter_combobox.get() for desc, pattern in self.filetypes: if desc == selected_desc: self.current_filter_pattern = pattern break - self._populate_files() # Dateiliste neu laden mit neuem Filter + self.populate_files() - def _on_canvas_click(self, event): - # Wenn auf den leeren Bereich des Canvas geklickt wird, Auswahl aufheben + def navigate_to(self, path): + home_dir = os.path.expanduser("~") + abs_path = os.path.abspath(path) + if os.path.isdir(abs_path) and abs_path.startswith(home_dir): + self.current_dir = abs_path + if self.history_pos < len(self.history) - 1: + self.history = self.history[:self.history_pos + 1] + if self.history[-1] != self.current_dir: + self.history.append(self.current_dir) + self.history_pos += 1 + self.populate_files() + self.update_nav_buttons() + else: + print( + f"Info: Navigation außerhalb von {home_dir} ist nicht erlaubt.") + + def go_back(self): + if self.history_pos > 0: + self.history_pos -= 1 + self.current_dir = self.history[self.history_pos] + self.populate_files() + self.update_nav_buttons() + + def go_forward(self): + if self.history_pos < len(self.history) - 1: + self.history_pos += 1 + self.current_dir = self.history[self.history_pos] + self.populate_files() + self.update_nav_buttons() + + def update_nav_buttons(self): + self.back_button.config( + state=tk.NORMAL if self.history_pos > 0 else tk.DISABLED) + self.forward_button.config(state=tk.NORMAL if self.history_pos < len( + self.history) - 1 else tk.DISABLED) + + def update_status_bar(self): + try: + _, _, free = shutil.disk_usage(self.current_dir) + free_str = self._format_size(free) + status_text = f"Freier Speicher: {free_str}" + if self.selected_file and os.path.exists(self.selected_file) and not os.path.isdir(self.selected_file): + size = os.path.getsize(self.selected_file) + size_str = self._format_size(size) + status_text += f" | Dateigröße: {size_str}" + self.status_bar.config(text=status_text) + except FileNotFoundError: + self.status_bar.config(text="Verzeichnis nicht gefunden") + + def on_open(self): + if self.selected_file and os.path.isfile(self.selected_file): + self.destroy() + + def on_cancel(self): self.selected_file = None - # Optional: Visuelle Hervorhebung entfernen + self.destroy() - def get_selected_file(self): - return self.selected_file + def get_selected_file(self): return self.selected_file + + def _matches_filetype(self, filename): + if self.current_filter_pattern == "*.*": + return True + return filename.lower().endswith(self.current_filter_pattern.lower().replace("*", "")) + + def _format_size(self, size_bytes): + if size_bytes is None: + return "" + if size_bytes < 1024: + return f"{size_bytes} B" + if size_bytes < 1024**2: + return f"{size_bytes/1024:.1f} KB" + if size_bytes < 1024**3: + return f"{size_bytes/1024**2:.1f} MB" + return f"{size_bytes/1024**3:.1f} GB" + + def shorten_text(self, text, max_len): + return text[:max_len-3] + "..." if len(text) > max_len else text diff --git a/text-x-generic.png b/document.png similarity index 100% rename from text-x-generic.png rename to document.png diff --git a/file-python.png b/file-python.png new file mode 100644 index 0000000000000000000000000000000000000000..9bbed593c0fc4f1e6381ca9204ded61f3aab98e5 GIT binary patch literal 16671 zcmeI4e`p(39KgSKxix9BG#R?ZrI{T}q>9Qg7OW1|&ek?=oom^^A5*8|O8=WoT~SMm z_{RjnKPsZG;7~-+ZZHPQ9Ag_YaDQwl7DiYR8oOjk3tQTnrfYKN_q#1c;$8FZ?%gfH ze9QIj-ur&v`+h%n@7;UvuKj4o_71N*=mr39q_eFD_bs%!YVh~>eQ*AWJE^y|s}>-r3Uy@b3KpLmvX%z@(w80B>&uNbLc5;&Xt&zLB51 zH(^H2Yg;?oK%t+*r@kA;l-hlr&+i9#WCLwN|F@gp!9?dC>oDl`4TMf&Vc9fi?DMG6Y6g#v#3iWd~q-dRlJ`OZo_55NDCPAe0?| zR4N7WcpOaJ34@tT=8GjNB@UQZgeE5^l@euf$6bEMgmr|357yTv6WpDPz%P&v?>5A=~hD7%&WpYf|*P!@MBbl-{K0S<^Zy}Tcx_t zi@-{NjX@EfX%wKoj;Zy{wB?>>3*Q1T7Gw(y8RI&BNrrix^Blj#79`o&A+|jczQ)dw zwsI5h0I2h$_D@Z~>{YBkxA_(?L4=$u1hb(RAhRaIl_6IE^w^``oVzG8Nb@mRb@?EO zH?F}Pg5V|G`T!d6&@5!wmq9_DT(S^my&i@Jvwh;JJECPf^S2YE-kV zjcVraIMn4SL67z_nKONnTUFcuBypV2Q=Yr~gl2J4Hm;ecH-lRzSeWGKb>QFnB950f z_!nT8|0mcb(PxnABIM`QGYq7115m2&<~38$>;DQKRL;N(SSY1#TRt}cH00H~3z}Ca z;WHmTx;S+cilderAZ~pC&F!_M&yU~xa+I74zy9SU+yKzRhL$wKd95r%=?lKFAv-lA zZLig|mr0{l9a`8>6P|5e5hVC~EzbEk2{!<=q(!SbR?AGo8#m_#yz1fB36ev!q_qnB zCtBE`xxLxR&{B{z8LC|ev-L0HWT;~)na2TF0OZh9_ldX_xpuDTobmL^lV=$Jl)IdcEdXdGhehfp4ngqOPN_A;DUQoB#GP?#fQ+6SM2M z(Tf9PpPQ9kNL7cb1k?$1KK8@Mn6s7sFMzs+?$k}5_kS5qc8`%^q})T zbMHO(p5O1Bci&C8w5_hTA}eEN1^{GLRhHLdSw^pEdi*^3&G-FS=(bpEtN>^CXL>fI zqb@YnSJ;FHf0g`Aiva9<0bE#Re+jT-5x}bkfTafjW;7nUv}zeP=r>kZ zlmnrEM>|jajy1-{%CDOM78cS=Xg&UAGgcaYsH$0E_{T7F+C04z&bQ+vP*rYS-6{xW zWnEp^g9~SXGr$?(3~&at%77pTUSRJq88b|O3P7p_K`_bNC!vo3Aw7h^zPl~9^OLYs zwJSqF(Z0*=qyKu>x;zp{=)F=AaO8ARgiL)J=tT0zy&DI&!>Ln}((w{yC&~wQjJa1j z-QJkM(=jP`F0TYbV{UM`$u`U4tw(TM#}F=`Uu~Tsz%4;6X&==8QI{9qx}^1%w&l2& zO)g;wh$ZdAK^w!Ya=4|uhSO_7*l0+^zog>>G+v|q?r_=c>YTdiN1m57{ zsFonfCWB5~n_0`-7q+ z(5#7BmT&4j>^ln(RBhG8K_ZapWI literal 0 HcmV?d00001 diff --git a/folder-water-download.png b/folder-water-download.png new file mode 100644 index 0000000000000000000000000000000000000000..60c479098ba647a0a6c746311b47e1c7f8dcbee2 GIT binary patch literal 16671 zcmeHPduUTv82|1~+L+cfDlLi=u_&!st5c|s$%aj+G_khS;{K2_sR}-D4#g)5ThRTZ z8w@t~5Vv)RBKYj4e~6$J|C+BqeBirP$DGc>YN=^!9{2d2ZizSNBu#CWlicQf<>sF6 zJnr}Xe&_qnJqd^Is;{fI<&Dn+0Gr2M)qwX(dX31%&qJ%%x8u#c(pl>S`1Py&;L;q_ zl?@HmF6GXJ^3PD2wA|fL3$U#O!23CXAFI4i0XEG5c-90k=LdkX>wY}F@O^B^T~a=i z3GK=eP_p~%{+^eiMt@KP4ZR<#DEQC!ZEvahdu%|mZ}m)@LNuZSuKLIj@U z;wVaxWV^+zHs)CiXmo$1x0@CM^bUw9({+umL3m%l+Dk~lNPLfPdT$)KitRLa+3^{v zcl$Ls)7}MN{{9r-KB0(@72%72A~1Z+m|b)}=(aT%@CiK?Iaug~7|k0ZXudc!50 zQYX&5QN>kUkkIvn1Q;dkV<9cDm||5&)$u7nGzfKd0O@;y`&qhmFOM2vG$r`t9{%vE zf@-yaT2RQj&k>;bI-%@s2NX@4)!%vTBW{eLDx6Ip_xsy%{UY4G*T(tI5l~uM0!8H& zTt}l<6iu6r5EOXE0O8hv;RrsAIULnto!&VD^o`k2mIP$OEDwZHM!-PqWJ4SG8WaV( zb>H_qni5j-uWCRS`sU0M+td9U;dxE>? zPQl|p9>kp&{T|`1iN#P->5kj?|7;Kz0TfWaE%EPlw2vt8lt^I&P-C+fHiF3&1 z?ITiz5fa2~mI5r$bm@|SbTOYPc2m9v zq&kO_B~qq9vJ4u1yo>;&&tS6t%Lrf@47OkUjjbCldho%u78VP4qNwM|qZ?zVluuB{ zj4Ne38(9ywU2VDe^_K0vzuG$VIAR^zrKC*2iype;2+|KWP??^b?8NI&yk4K8G!Ovk ws$@ViAQ_MhL@}`VpCffxQA7VPKvcufmC5hk|JgQouZKRtGq0}dn5${WE9=Y^L;wH) literal 0 HcmV?d00001 diff --git a/folder-water-music.png b/folder-water-music.png new file mode 100644 index 0000000000000000000000000000000000000000..45b9e9dc3742914f681b4cc57bb31c4b7ac7eea9 GIT binary patch literal 16671 zcmeHPeP|R%6o0$94=?s|{kWJQ{-Icsp2p%ITCiH0yPhN=CM2PS7OBJvZAB|;{6fJV zZU5003N8JDiltau4A^M%M-^fqC|D^4t<<)Xv|??(gc#x_>FwQ4-z45;Zzq@A&E0OY zck{w#=Dm6I=Dpv%ncdqP?pQ;8mAi0pApp2*s)J2fR?=&M1OK1izNZHZ+Z+BmKfu`! z7e=?*kr!H;ssh3vKUKVq%+hVuO?3c=%K$>}0Yp#~>I2xn8epIq;MvasN_KyFp>YE? zI9{u*3Id^jUv+%@F-ly!t6ymWczQX#ghSsve*lHfeKmC(o&CF5ai*1fXWsuSP*^+>k?V<<^9R*+$$tO2|{$dxjw#u`$XH-8? zZ8$t8Z5o$i83j*mQtToz8HUCr2uoy#Z_S%0@v)8pTs^+oJOh9vLndiIt^cEu7(9r` zTYSf!!)Mv~MGOF$r2R~xjbT=WCHZyV`xj5bOQ-3lfO$boN_vm}IQxaKAtaZ*0Nf7o z1`)`+M2dF(exw>d?aUpS4gd|+ULfG+XqzZSx?37dgpgrbChgMH4H0QaorecT+)A_Upvw27MwT}3pzUsaAfCjclNFr!ZQHM$33xk)`v~!MtdjQAMOx%6m`2Y;btLd_3lOR>yf-G5{zW^P$cG$cI^;DMp?FGoh0Y zZF!#o%yWPlv)=jjXS#;*Z`rO(UypL`Wq*YIgExkI1 z0wCZU*;Hh+Po0<0s+Y=ECUQdocw$lN4bQu%G~u^ay+nsBRtyDTMX(O+4kzQT-QfV= z3sc`(Yt>^6WkJB?XyfG!&dH^4h;DNC`X^7tcuPu?f>(CYs;BIuxBmV5~WZC5`!cqII9_nDJV&w(!&BprRnLzV9{{!q< BL+=0p literal 0 HcmV?d00001 diff --git a/folder-water-pictures.png b/folder-water-pictures.png new file mode 100644 index 0000000000000000000000000000000000000000..7e043209ac55f043b20b508721c12e3305b8086c GIT binary patch literal 16671 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 literal 0 HcmV?d00001 diff --git a/folder-water.png b/folder-water.png new file mode 100644 index 0000000000000000000000000000000000000000..771c805aa53ca3d8670a9ecef09ac28b8de989dd GIT binary patch literal 16671 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 DVx{xK literal 0 HcmV?d00001 diff --git a/picture.png b/picture.png new file mode 100644 index 0000000000000000000000000000000000000000..61c337e3271449fb4354f42e4d091ba4a48a3581 GIT binary patch literal 16671 zcmeHPYiu0V75-+Qe(c)ow@Cs?NQ(qYTd07jRg2@0G@c4zi+ zcWl>oy2qNGx#ym9?>XPxd+uxG&EH(L+*>xQ41l+_W$9|VFJ@PXi+4+_HK#a&$_QKTXQMFffn6cH#Q@c)W{kje3{zY)1a5Zqhs0|0KRZ4E)1h0S#5nQzPo=F3T0XtcQ;Ta5mi02qu3*T<>NTxg_{PeTzb zHTq=&K-TO&qtJztmfU7Cz4VFZER1gaH=A`HKacsi5r0H$~yBm`)nRkTxcro z&Xzl+d~N_Pb$v1}L+6iEe_WO4Q05*5DxIMm#pKWOxz6VoGDy_8f$z)*nj2^<*E5=V zLIS#IYj^hvU|2CISV(dM5Ku}`Ut+yRzfxL|d9Aa6M`$;^++g7ql>oceT?#z#A<*7i zP_ZUq?k;dlnr%`pgmFwHk2r}r|LE0b=Tp@gFxyF{g}>NT^|5De06GS*8B?I~Cs4$qqF3)e{&YX~t(c80rP zLwjsBe)X?&*m(J$$*sI=rV-~iAHESC>P@h@X`y7GIkZ^3>$7xrSP#@v(;uQ3TkGaG zDOucHuet1GUcP%lwb?vX*g143dfuENC1VC<<#~BM#S!iL#oF(wOm_5((gbq$Ho zFtl)xwgV!xIE>SFfP=OJN?|Ma!Cp~Adjpw6%)_5c;MV!pn{CqgRF53HMBjK_};M!^(-*{8NxlX5tz8M(( z79he`Tjtlrr)ycNwq)|Et#k?a;T8Nt~j@k zNmBxVCiu}l*oJF0*JvCd8DF06LJ=Lkjc=JCY^c>8 z{+dww5$=1I+ZIWD4vEAtw|r7imS2GyrwzeLpn?Dh5Bv$Ld@Rijx$k+zBgfNtnG*4M z42%^Gh8`!m3_&8Vc5VS~021mj!oB9^%Zv-1`YqX(%QzjO&<+x@KK84z ze{%_0Zk2>WOQAEB=W}zQvoRqjgI9dX-^7g{EvA7&@~029%|xwNKc3m&#-=) zPGV^HgubP|r3RCE0S9hD-{4lM%V&@so(i*<%j3y(E|e0F9ja4Ixcme-uE8 z=xNCPZIHt>cB}b^#{!B@6P3a=r_lUqJS&N;0LTL`L6r_!DHGxTXDL`cXGxb=NvBV8 zq>y=7=G9NiWduM|{g9~dTP3~1MlFYbifpx>X!I?_Vh63NkLYCtKs>#j#(ayrHtdk2 zH2Z37T-Ih#4xMKKk;NQqWC9=>ct?u*yRDVR7S}#n*|Gcoh!Tlj3WzUr)uzYQfKku{ zK&0<4g?$l~TB5fEa8BIbe`?XWo+YV`7FqqdL`L%B!GUh0kO=_&kpBlZS3}{GcJ__B zhX9xY(sc!*_+-wSbyevLzOwBXMj_MdihlHu9;a{N$F8}TUkgF0(6tC(gRUu`lDD69 zC_&#bI-LvPaLi7!M(%n%=8yZ&9vFP$-i^|$JO571(Y5@iQrVnyQa<|*!$%iIwHZw; zLb8vQdg-zrEoU?YMdOPI6cH#QaKRxEY`XhVa%u(pzW@{D+?MzM*=)PBYXK{+b=j(= KFDzO2v;P8fUJ6|R literal 0 HcmV?d00001 diff --git a/tar.png b/tar.png new file mode 100644 index 0000000000000000000000000000000000000000..e2887cea49d6c631bfb11c4840324fc3ce941a28 GIT binary patch literal 16671 zcmeHPYiv|S6#njO+ittvh9GU)Qc0Q^W16BEAc2Z3w$Qp;T3Y>K)P#biAtj~;HE2cA z$Pa%ssFkXbA5DA(e4v!3q}nv1LKM-+Luh=2zJxCJv2E#Nckfl;b6mQ&MGNu{lQZ*jch+ozV7E)+?m2WNUs&A@Jf|z@FCuCsFOW0z7vwVBZX^dJjmhI?%i+hg2B0 zSU2QCqyOq#KCLC1xT^feb^_U%Gzq&te(-ssjCr=8FfXPjCN*|-tgWo2fjB`yuH}(k zg0OaNYb&vcN|b>p1M`>xArST*-|bkUxuut7LCPaGDS{x#foy}(4|feQW*A~oyOoTlX>LHfqH3OI4enR>KeWHYUweKD*xs@uU(lq34(CAPHPgI&X&iH>mx+#dHWgV+1uQKrkI%i{vY&^gp)cENpUYhz`G-ZvB0&T(~j&qzV;&@4Tw1=qK3pei;Is znlnXjG*`+_jHl|cFhhXMnv70=(yf#yCOg^&@8RGN8xsL^@|dgQ4;w?kTm>HpS6IW{ zpHtpp@2?NOx_KV~^PT|iLm-l?fN$tefU5Re(3+ zH}Mx80yiNj8P5JeIp#3p32rr_a)!1Z?lf^3xAd_cigS672hguarIk%98^a%5*` zWAEO*+#k4d*FIPfrI;zM{ABtqWJ4+Yr!$ zEiEl&FfCrZ7&ybI!>ZsG0g5tpJrD>{FgAhCovEH10W0lb=v)Ng z1KbF3scy(|fu|hBD8r??xRbz*fX@C7EM1fx5a6=p`_SIk5wJd772F7D{G$n*?|Bjl zN&nC1oBHQ0@Y-;d(R#RkMKiX&f>gqMS(o4%UnA@Hme z>V6Qn6yT9djrjb`VR&5Ep9YJH1Vf^M3wVE!_z^(86B1&~G2Y~_Gm+47n*$;NE*PIt z0vMLOUtKWTxuNibjfnu&<>{FlXjv2l+hx6$A;9SvpZcanZ+)AW#|NAYHim%CZ!f*2 zsh+{x94pg(kJ~fQeysgXeFd{G)qB48s&P?#x9Lukh1{jZ>QA^G%M|>-tzA_YK0Mn( z`akWvAcg>H(DU=5*iltqJ-B#J^j1c8Z`Sxp9+@W`0&9_blvJb&Q)3x9rb zk$yeKypb{OvQP(zKFCiYiEirCE!-Q~lImF}^pc)_icP=WqZ2#-du`%0Dp3Z)#ei{3 j=HsMoEB$`~Lgb@s{G}3$<%eHsa|L-DbH7}-`L+K6qH?p! literal 0 HcmV?d00001 diff --git a/video.png b/video.png new file mode 100644 index 0000000000000000000000000000000000000000..a0875907900e7c279597675ba95b0229e89e1bbd GIT binary patch literal 16671 zcmeI4Ur19?7{I@~Ki1^ z7w+TeU}dW>P!G^q4A9jLFoi^2-vExR2l(C$P<9SrdE3Q%jpb+{t);Hk3nKpOx!-ph zNvv(YrgngJYjEc}u5LMsg#2NDeGNaxJFSL|2Ykf?XcF*yJ=;4tuCj7)5NWW+2rvSS z03*N%FarN60ge=R_u2O=c%!k$z;Wdq$MGaREz3nwjG+EF7Kt_=J6QBp%2$(=5X+1r zT>d#3tqw;75Ji%fw&ffLyoEP-?KZooE|k>bRK!U6~}u|g_% zEHjV>rlO*iG^RIsqF9Ik^jh{($w?Fo5rCATRFp9QshCwcF|i7eLn{?^Sp}qGR^`OR zDnJgcRMce^kcwHA6BBVYD91>=ZqwF$C@skV197JzUR(OPfL3wCuY+*CAAKmIa-;qd zD0Mp&1&`y!@HUh`KIguS)Ty@pCaoP)iN*%z$T}kdtlaYhnfdZ&1 z%TDfud9l8HhV4%4o#{GLDK+mmeq!!c>rod&;O1|rkpkph>y$YkORIL<(Q%|M!$rd$+b;n1&%C(j?8=@=V*Gb&{} z(T+R*ien+_8K@I0Marm#WCHRfi25hgqZ;yyxxxrA0*nA7zz8TJkR3gb?!lvI6;x#X;^) zj5kl})B`yR$sR$z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZKG z?e4RsU= zC==AHEvD*vGQcm}{?WortNypQzJA%(D{Wp^`sT*Q4NArjjy`m@S~$(DZOyHV+!0b0 zLJzV+-!%yd@OU*nGGtL$-DAzdoO5iVXF`~8(3G{2vv*5B)nD~&u0Yp&J{gOGGFQfm z+#j*FD_?6G6fc}6$l%y0DRioGvTvz-gB0V+TPg}?k~9R(0!u!#9u}MV^j^sk*8l^UFQ?#=TH6#~i zu^VW}@@Sr7D=hK&z_FCeZ5P|CiZqkdP2CI^*D-20%G}?p7Gippb?&N56F%+wdTn*- zwN;jEM<2~RROG2!zcMu{_?F&7JGHX!f27xRA7Aa-Fz0}dWd8d*=f1twU9;7E>;GHp z7TkR)wd$$2n6l~YzmK0=J^%6b2WOv*tsh6<=UK&Wudi_JU#Q-|d+Fh#XE8?$mT##{ zeXh*I!}CX-F=X>iUdcDA*}DC9e-tXSD*nHITw?I$;ZNf$)$^InPKsF03;0^R`fAkH z=YPUhyT;o1dU>_%s$lzGzh`GUN8YqZqba&ZrI%0t`yVpz`Im0z6E|AYr?q@+ULO}B z*0Ac5d1cp@%V|a$t7E69%k+NY@>Jt7ae80g_-#t^cAlb&4338D{%i9XUVi>v*ub3k z`^(vTk{?9A7yoEoX!`Tr|KIbR_xd-TuU&si>RP&ghfXx(_E|~|912Vw45U!eLI?U5 zyQ^Jab@Q9Kecir-oQvhF{{B3&-QR2H^Cz~=U$>^!{h7SIE&bfzvb*j