From 0b1ac482a5e01cc3cfbd0d8c2ce57cd015499a7d Mon Sep 17 00:00:00 2001 From: GRiker Date: Mon, 12 Jul 2010 09:53:52 -0600 Subject: [PATCH 1/3] GwR sorting key fix for floats --- src/calibre/devices/apple/driver.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index 3156542a92..618fc27545 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -2586,14 +2586,20 @@ class ITUNES(DriverBase): if metadata.series and self.settings().read_metadata: if DEBUG: self.log.info(" using Series name as Genre") + + # Format the index as a sort key + index = metadata.series_index + integer = int(index) + fraction = index-integer + series_index = '%04d%s' % (integer, str('%0.4f' % fraction).lstrip('0')) if lb_added: - lb_added.sort_name.set("%s %04f" % (metadata.series, metadata.series_index)) + lb_added.sort_name.set("%s %s" % (metadata.series, series_index)) lb_added.genre.set(metadata.series) lb_added.episode_ID.set(metadata.series) lb_added.episode_number.set(metadata.series_index) if db_added: - db_added.sort_name.set("%s %04f" % (metadata.series, metadata.series_index)) + db_added.sort_name.set("%s %s" % (metadata.series, series_index)) db_added.genre.set(metadata.series) db_added.episode_ID.set(metadata.series) db_added.episode_number.set(metadata.series_index) @@ -2658,8 +2664,13 @@ class ITUNES(DriverBase): if metadata.series and self.settings().read_metadata: if DEBUG: self.log.info(" using Series name as Genre") + # Format the index as a sort key + index = metadata.series_index + integer = int(index) + fraction = index-integer + series_index = '%04d%%s' % (integer, str('%0.4f' % fraction).lstrip('0')) if lb_added: - lb_added.SortName = "%s %04f" % (metadata.series, metadata.series_index) + lb_added.SortName = "%s %s" % (metadata.series, series_index) lb_added.Genre = metadata.series lb_added.EpisodeID = metadata.series try: @@ -2667,7 +2678,7 @@ class ITUNES(DriverBase): except: pass if db_added: - db_added.SortName = "%s %04f" % (metadata.series, metadata.series_index) + db_added.SortName = "%s %s" % (metadata.series, series_index) db_added.Genre = metadata.series db_added.EpisodeID = metadata.series try: From 6a4ff480599ef7aae33abea1aa9e7facffbd2c6e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 12 Jul 2010 16:55:01 -0600 Subject: [PATCH 2/3] Fix #6156 (Error running Calibre on Xen virtual machine with Ubuntu Lucid 10.04) --- src/calibre/devices/scanner.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/scanner.py b/src/calibre/devices/scanner.py index ceba5d37d0..dd789dd668 100644 --- a/src/calibre/devices/scanner.py +++ b/src/calibre/devices/scanner.py @@ -98,6 +98,9 @@ class LinuxScanner(object): def __call__(self): ans = set([]) + if not self.ok: + raise RuntimeError('DeviceScanner requires the /sys filesystem to work.') + for x in os.listdir(self.base): base = os.path.join(self.base, x) ven = os.path.join(base, 'idVendor') @@ -145,8 +148,6 @@ class DeviceScanner(object): def __init__(self, *args): if isosx and osx_scanner is None: raise RuntimeError('The Python extension usbobserver must be available on OS X.') - if islinux and not linux_scanner.ok: - raise RuntimeError('DeviceScanner requires the /sys filesystem to work.') self.scanner = win_scanner if iswindows else osx_scanner if isosx else linux_scanner self.devices = [] From c56a4a5aaf6b6f3cd360808381aabfb7c0b6e574 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 13 Jul 2010 12:12:03 -0600 Subject: [PATCH 3/3] Fix #6165 (Error communicating with the device) --- resources/images/donate.svg | 53 ++--- resources/images/lt.png | Bin 0 -> 30594 bytes src/calibre/devices/prs505/sony_cache.py | 25 ++- src/calibre/gui2/device.py | 1 + src/calibre/gui2/dialogs/config/__init__.py | 7 - src/calibre/gui2/dialogs/config/config.ui | 48 ----- src/calibre/gui2/init.py | 6 - src/calibre/gui2/layout.py | 214 +++++++++++-------- src/calibre/gui2/search_restriction_mixin.py | 1 + src/calibre/gui2/ui.py | 9 +- 10 files changed, 169 insertions(+), 195 deletions(-) create mode 100644 resources/images/lt.png diff --git a/resources/images/donate.svg b/resources/images/donate.svg index b17d0ec7a0..603e672f6f 100644 --- a/resources/images/donate.svg +++ b/resources/images/donate.svg @@ -1,24 +1,31 @@ + + sodipodi:docname="donate.svg"> + @@ -180,8 +187,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="7.851329" - inkscape:cx="92.691163" - inkscape:cy="92.473338" + inkscape:cx="60.937831" + inkscape:cy="61.488995" inkscape:current-layer="layer1" showgrid="false" inkscape:document-units="px" @@ -189,10 +196,11 @@ guidetolerance="0.1px" showguides="true" inkscape:guide-bbox="true" - inkscape:window-width="1106" - inkscape:window-height="958" - inkscape:window-x="597" - inkscape:window-y="25"> + inkscape:window-width="1680" + inkscape:window-height="997" + inkscape:window-x="-4" + inkscape:window-y="30" + inkscape:window-maximized="1"> - - + + + Oz@Z0f2-7z;ux~O9+4z06=<WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bXU&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWwr)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>={htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!hR|78Dq|Iq-afF%KE1Brn_fm;Im z_u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000SaNLh0L01FcU z01FcV0GgZ_00007bV*G`2igY>5I8rCKP#XB03ZNKL_t(|+U&h~tS0Go-uFB2QtP+e zwU_Dcndw1vAcVXgI>VvJ9Sk~0zYpZA0N0N|#K@bv(A z4X^q_gom_JZv)<}M4kcO9724mcmBaY4ACb6iGhceihm0DWnlYS+X}uO0RMadlv>oE z4k7+$(^5_{U8oA!6<7c}f^@*ABhsXF*&4HS-k*Fu0AAy-%;*Cj;?oJ(0WJ$No1kAk z?F~^NCfKGC2sDYMR&vF`jjv;X*LVi-A-0Khrtfe50!E;Vun}m07)NO6GD~GNK-qM| z{sb6bR{@}3f`Y#q6+?K*5x)kmM~W#8N@SHt48SJAMk%ZnE?wE@oBq(_eDk}W;@U$C zlFGSx>mL8dPk+4pv7h>l!`E8?mF;@F{?2C}#%2~#7M&LmJvy_5lt{xsX<@Ob>RDwjp02%p2{-VX4*)x29WFn-n7=_O zSpqu6guEmSuq7b8ralim^=+HJtj3O&b=2ceCD|>Ld_Sx$t02E*j%i_rxDtBDLjYtb zo=%Bf4J^xyxwWJaI9$#kMs!M;LSYrS5GjqqXpK+chJjgG(z(bGJX($0q(+yW2xkz{C(=0Q~^BZAzHxTg5=Na?5 z*aPO%wR?SFfEZ$?KowS#DIwQzIIAf%poN1fryn9(gn4Pnt)=ODs?6X*PKXL!d8}D- zvTfM9$ijdmAu~aIOq>l~_aWS;RlgPjAOR=a-k+^DElD6mPgYgv_LSpvf%evm%x81% zovhiLTV|zVR_P^h@OlY=i3b;Dv|tp>tYN<@$Q3M0OQ|iA0ybCFR+E5&gv~OHf-EM; z1fw#B2p4BLNokI^JuZug7S0BZ4N)1bwU7R5r7w|y&34lqH(f_RwB+*&hDb6QYI8(U z&!{UnI%+sr&RNb%b{6$g!C`!jRRS*?ttpL{!ze|Jk>CR{3eI_=8<;7DQ3?y>A{1K4 zwJal?YGSk5GA;w=iA@)7$5xT4c_yvNBPLFe2H!E8GK^sBl9Ygs?2t$?DCq) z057{=Ng6i*pAtrmAieXE-6F$?5K$;`kf7~6(ZDRTD6QGH9S5_L?cngHkZI4ok+-3wH zxVzd?76pi+_kkEaF(yJxuXYBoK(2(v^~)EoKlRwd-*D~9Cr&i`itN8&S&26Kb>zHqSEwz&$b`ZrfFEOR=nxaOMmje|0{pt-_}LV{NRwGZBp0u z(hZInlb|y;ts@XwyMn`6;K)^6txq|A^bvmHqhI3N-*pvIVqRs;>TIX5>~`*Tf&tQf z_FgI45NQTS6k*i`&YPZY2s9o}wmq#2xR^NFbaWvRbk42w4L&8T&1nY5$-2iX!AID1 z{g_!r@bOh;PVehCij#GtHr>#kpPaB+t?Af!Yj;ROaC=-LKENFqp@&N+CLfYO%Lro-kIRV|pShIJ?@ z-6^ZphO1W&dE(&AE43=$&UXjJmpzVDJ$i6YA9kfoVD~yI!x8 zkFnL(l2RnaKuS}aQdt6!Vg%ohJhTF(4a!)E5o0p8F0o#B?3gv%l(CzgbJQ9R4)>W= zhR=QJ4o^R}kB_jN&x(1K?@pY8dd+VEF^*IaNoajy@PV1tG=rlLfx66aA>m?VUT7){ zr<*NGB8#$M)eeLZ*r^ImHVrO#a%&KTW*AT+Bf}Vz`WLWtU&&!6q;CMTTCJlShDO^A zQ5w955XPmcG+o~lV?t0!j407)r7)^b;FF)c$+d^~`NVJC z<{fXohzc$9x=4%CQkVI`RDH;6ehW}a&{M;|$~BqMv_oL0$RI{mZBK0tz4!E9urj9h zqwPSh1f_({;7Q#;Rpz7+Io-Bctub2Dhn|?Q6LP-BC=f}1z<|DA``5=Or+MG@!+bGg z(3X@E$qkT3?jd0CLysv6f^!f9SUVD6nI$hOPR=9SKA}ubh>jw)3{i9Ai#NG)?Gk<4 z@2?W;7ZoROI5UqBMpSJXL0BhD4z?^IVf>hHl&O$o?Er zn$z``y?H@01-@_bz31VBf-jwJu}Y|O4XvtTN>2e7UWHZjQqJEW9iPmbwsAYVOAtY{ zfnk6c&`J?gV!K{5JGh7+dXn=a@YN%gpal9MvfT~@=O}W;r=L6F+n&A57jJdE^Sb5E z+H&f9@mf#9uQZWoze_r%2r-Zn zxCA~V`WTX@T`FTS)}krVr6ns$j5Qc*i6N0!1th^(gVGA6Em~_x0a2Q^*`P$zZa1vG z!}%WH_qmV$8&A*ICtA|)h|#P?h5?xX;d-;-kt`>&MvNr|4>6FuN0b6(*mMJfi_}Fy zVSDh7%p^io?9DRn9pUWZEs)e8Nh_TKP?qaVY9N-iqb0PnI%_( zR+`did4^jD6EA9g@#3zjk-WB z$YRFeJ*&a-=*|wOZ9n2HNf@m;A2wt5Pzq}-${2K(VT+tBFDR>$BpRD#l=B67k&js+ zMzpc?UC-`(fgd_tKdxBsJi$5oX3N%x)HHn*5-E<^LIgx9lrc#3pbf5T5T!;w!kDpK zWXxzqRdafFO6y=x6c?6obmqBmP@(ODp>MI)APMp!XI2%e$j$wx&}*CuPWarKm>WGc zaD>_#tP*mqC~bzMNFhRLgeuPcx_->6k5-xV~ey+@)<=Vhj{@Mc-_(MS*C= z5M%J(M^aQNjU}iOjh=q@m=rNYBzTk^iK_%48cB)V8aCUOzVC2@!5GbAf1g{o@AA;a z#H!U?zE}}rPo`tq-^pcGnoCnD_?pcC52(Nx6C#Py8mc@aI>&5LLkxtJIIMD%D2NUt z5u+8(JCcIjXxb1F0i`0X_iWZ1Qu1ge_z)m5tv-d)8kC}%%_!=c*>aZ`7H&~+GN=r-s05E;4_QJUG#E=rFpH!E^% zmVwgr!{B^KgHoF09fUaY#Y#}d5@Ny)!?^lGAca7jx|7Nn1n^$7X<7tDnzRm?0h?Nq z_XHmxM08OwTg)hOeIc{VUJG5pm(2hpE)qn>6L%rfMktg51#Ryrtwm`;P*|;Lou@Jy zqlHcHF{NcU%Mc?R#7Gwtu?=V$K_fEKv2N(`ejs>{Hio_*xOnA|ox?*+QL%G)fDzEf zj-C@yIPYoJ8~VOM`GIa-ptUfxEw1m86s7B0??ZITSYp?XCJzym7PQS^*wS?^wqD?e z4a9&;ir_t>H7Ny>GHly`3j^AK%1ROjqXm&LW-zT0G3+cVmb3Cgk(os|c=IYP(g#|_ z=}7-l0zj)VF)Cq{Zpj$=WoD5W5EP4iv<*gJ2%dRnNimWc%|Tw`ykm$hb(%~wGWo63 zm|X-xlqM@n>iL5G%MWqo@yB`S`ePhkzRKa=f+wy&PGJm-MNL^0h(Pq7^Yazw+b!#L z!@Z+pzI^KihM~iUfbTobPft?U_JebNuvvz811W@2!6XW0Gn8ssuT~r`_lQb?_r&1w zZU7OKHi#HbHv@x%qRtVM;kpi;XCyqNK!_QI&6!mtb(QbunO(qF+!VS`i5HWYrJTM; zE6Sdw=(n#{_w41Fz!(vuQ6jX%z;2dfO-|=MJDDak8O<?G7JtM9P^?;n~Zh4 zWw$CQ%6+?` zvc}@W04PKfC%5l%a`zTP(=ZGUZ46D@41*hnqNqU|1P^ZfKU!-O51+sW0*SX<^?VKQjYn z2N$oudHL`=zl$XAnIAs&WZ$p<*_S`|5B~kl>dxnRmF5toeOMMK8v2-3X87Nea z4~bi=GeQ#ftH5q-pn6jH*4fI^5e@^Uf8 z2O^WPC$H$cmYu^3FO@M^N13*+ZJmT_(+i}#CL=gK@1|1 zomoj;<`-aFyd-u1i&FdjRepaI&4sIP_||vV7vA)3^Mfb8Et_9i7*lfe+((j`Uqj0N z9lO`R`8zhB`0*S6QUV~R2r_1Xu|!s&G(H8Yyx`flzlrPL_yjNh;%{si^EpG)vUlmy z1E5zLLta#9V@Hod2t?n|w=H>5(QHNlqDR|`D~APF4m3p`+1)A0 zGr976x`Ow`s@Y3!`h2#$@c8~C&%S&2(i^`^FRwpa%r21E``B`im@n8VEW^-6vJ_!^e(xq2n7kK#$z-Q{1o<~eLnfYPqE!@u*T52#OeBsq!d00Ll~98_ql#Q3{cesA6OmTWB<}+n(dmR zs4-d-yaOUJc=~=I%PdvB08tEGhmvt?>Drbo%MldYc0IVEAC!Q|s09$4A>N~+A1i{a zAO??`%0N-08(0O4bS*_$aMuYJ5)ysE8QOn#5|=axjl=6FMM zx?-N?gqS!xT5&L&EFBoCNCF(a!J^E8A(c5E;6dpUQr^~AazAG+h1IG z!<+W5y!l_L_8wrSSB|9GQ+LU%hF^l z7Khg^KJwPy+LXzT(P0!D52iSDH?P$qn-E!l6 zgDBxUz2~rP$?eD@1}ortJY(uLN>Cz%32(T*qo``M2t(Jh*gY7#fh4q63`39aI<{vg z)O&kmRgG4f7z2H?CB{HXk)az9(f9oZ!{9_w% zg)8O$Q;%`u6CY)CGJiF~ANhB`m;dy?{Zr%Mob=ME z5DChR|N4D@72gjSV>oMj+5~pm`#T?}GINxbX)^+`7!!F}F$^uHuoOkbFgRxOf^sp# z`kv5r1f79}5Ik8{(yI~uXSrpa{0Jr?`k49{{8+k*BFWg*R3=Aa07kH>iwf5^grO&R zho~_CQs^Wx6tUJ4QRwJd<{Qq=e}h?ceD8bqfW+;4eOk`){rceQzh<&|+Q0S= zbh)6YW|E{LsS=%)gnq-#PyP%qeD=c_lkwK?|H~Mw*m@`x%#@%t7@x5&=ipiv%friy z-OGJU{vOKge^x`W)g0S{E>)$&Esk@aAuS zBe@bbJ`h42eFIHLGlWrSDl%#G(pXLjBuQjdH8yWVr-gvUQ%^OuoQLsQJ5h9Kje%x7`xFCnX5ZlV>H)_1L^1#DF%My^EL7wjwVI zQgn3NHASA&HXF3fvDV(dG^y){HYRZ*3cQAC-(euQ}M8Q)G&SqV30#GKiUasAFJ-p{EZCo7cSY zeSePa_M9*N+}}o=V^%;WuwTR8Jf~h9;=6OP#!}5LK7R4BXRo~)vNQEc0$U{tt29xB z+-mYH$Hhot#%|f?KXsElQ`BX~b_lfnKxQ-^!~gc#n|$+opQ6YL)-IB1MV@6Ns3VaX z{eUNnF)*@qj-slFAreK%%8KoFgZF`EeLgysm7=ODl!onUg&RCYRgy>))eK3Aq3<7f z4%@LOJSbyE-Cqh*|3StcK#Zwt+GI03Y5^X&78%7M1nRoteCye6dVCn=C7|(9bNf8! zH@;-~$qyd!^S^Y1rjH!#&B>)Di6(7tu^q{K*nDxnO_7d1tu$aJJ!UVOCJee~L^;Ximqcd$%dvRrFo5}bFG#(=WK5V_Mj z{?;d+=bwJz7PB(r%I+?|dH0O-r}p{l|K$&H^zkoK7`QOcQ3AnxtR$?lgpj7jj6x8G zuEXZpSoe!iR~6n33jGOfB1d;%-{T3&bJPmRkR}q%(5;= zy&VCgN1a~`ftW@jXz04JhS!?DYcVFn2TxX%SR$EGl-7WEpaiWF_ijE`jJ`K0I9 zL_d~+Kw7WYZ49ATYV-rZ$oT^prIXTD07)UFkt&!l5Dlb&#<8_zA+rkCtZ3T?YYf^Ly57-k&iIxe z`j2_$+y4!A4=>>yWERAfWYrD~Ys4vVdy zO+JQEGOaRF?AWV1D(i54JF1LOlzBy|TA1kcqm#Q>tw!K08hl50dXwWXd<1`X6NZ-N z-WPcI>9^3gYhoI3A)!;E8K5W&OtDAbo{?uc^PMYi*t`0+OMlP+c!hRwdhq>I9B)+s zx)4#pqm1RtpLu}~{KJo-wIVNbig!QCKl{5M<^1L`w>B-ivznwdCv8hRc+Q4EAkjJZ zz!RvACI*kl=-IPHIf_BN$L2ZSd1gC1*lg4R4owegl#mrw$?EhRn`QLdEzu1aZAO48 z|TA-d~?ADGuL>w8z`b8Fd*AOk- zSv&l2o8`mr;Na1>W0a@wR&=XVLT8y*Gy1OO;+01jT*G2sBMNqRYtHW^hL|Ykmme?Z zS1!S?nm-61@bUpbBBn@)3Ks)08V2WRM5wfIeBSVpPrksf+&QPPivHK0<0n4wX}K-0@B8kn7o^>Ksi^ZWISQIsJ>r5yL3(ENA(M3q+Aw zOF=}6oXz@-y@QLa&yMlK$m{prmL&3k6+|SRZkjfD*QIHEX_}Zvv>DHF>g4rpCw8$z zh@(~^r8Ex77^Oz3t}1o!Ruj8mMCoyIXg(ZqvQeZ=vu+$sFTCLz7^~P_)}+throQ+M zY}-52wG?co@KMO}lB!rx6c%MGiqa6!)H$>vVU%D5nA+%7JtHq`!f>7>KagVQ;Wyf1 zw&S|ZSIh^zdBh0VTFfj8I9ytuJKk`5 z-lDal@sS}qPJ7Sswxb#Rv6&lm->1^b|)ggv}%Y zP3vW|>FAo4ys(H?EcfOFJ;$nZay=k1lIh5Wy&d9kG*%3$r(NAb&#thSgHr4i2h5wa}n5wa*-po=A|J9lO8(p7f$9)4zV@WlS{&0l}vs}caB(xi$} zNJ^xsUO%V{ED7ZkKmGSU#-~5}9J4Y*(pWYs0gZ6w8x9E}Qsx#>iq5xWSwWq8GBco* zOqnZF-gN7J_`Jz|08{CMp56VcY-yaOgj$Y=>| zVhE%dh$0VYZe=ng211C*B~O-(A|5@B#sd)Vfkajmw0#Vl&KYfUe9)sDZrIZI8%(+2 z>LN$S4H6wYi;Rjp2#F{ffBqu%@?m@wj1fc(nHinZOr{%2&^jm-%*x5n8euUtma}p} zNH>Wn%H=~(7xnJpeJk9nUIpA2N0LTufKkE_g{=z=BAlH!{MIL4z!n)cvnZqRlip4Y zJpYArvimyw7)AijXgAl>jKTYD=TY`OI)Q9fj6tW=h~^oaQQkS$C#Uqz(X<^(8DfIq z99cQTbuHRtq&Q}jsS}@o7?Lz8r4YRvF~<~pX5t`XO2i~FI5+wRv_WfwHlvAzG|ml< zLFDxK3}Qe@fUqUYHNh-7+rZtEfwqq*Wti6`rQP8B74>Y+`PnTJ8XtLZxHO6W1dIk_ zp~|2rpc}@U9|8=1T;kPoIfCWTlg%$(vgPijNlEloPz8&OS&&3-3_eAaBxae#h+wrL zMq%qCXKhbuh0}iE=Z{zX#0#e!ZyMHZ$ADs97Nc&^he-*PerGbsl;)!kIOpiQmZ59$ z-Z6A7O6f@grYVbz`FzIXPdjqp9|2VlW1ZOv!V{?TSwn+AoXZbB;O;$if(<%y_1F@7O^?=*^J#P z(QZ!Bs={xN(GrC&VrPXpmDk@nmS!)O;uiETg7`^XRix5ZJuZI7c`@rj$Ky!qR&@st18pX9@z z{9zVv+aITfSfTB^(Gi?!v~s6x**NghN4{_;@~N9SFPK!-t$BU0^OZ`_ zUw%HoR0b##g~0Q_sh5V zxBl4E{Mdi@tN6C3E;2fo#?VfQm_~ug{Tr14H+b?Ag75LpqO7H|BR^l)GrGR#+*lsF zew|J4c;VJ9+|W~$HS4nzilX2w#Az~l8V65}a>KOQY__E2M$zXms*99Ci9*b%Z1y3B z-~--!B#q^w+ieWf_yWdk6jNH%HdVv1ziVvNuaj@k%CuDJW8y{vwZDTk->c{;fRs z8+Z7``)`tBVo;~m}v$(NHPVd2ufRm_f%z`J%79DnoV1TogS?S3Sd-ZcUi%3 zH>kK)MLDB6yG{Q1nC3;swo}(^xc!+Av3K>Uu^O6YGcd9`zS>I-zQvNLGB`H4{?6-7u9WEXFha;&uj;N`ZsU$kN)vz`0&T? z@@se2eBj0rA3xeK%S*ICVT74A56mXkm^m{4kD@!T|{H~K)cZ4f=Wdh@D8 zX+>6)Xf5t&5c%?FewA6~&_Lr7E=*X!LowSQ^%MSxdU3%1)ptB= zvbz2%XaduNk6IX!e4Y_g!jQOfd5<6YPu@mZndushXgP*Nbx=W}_|ZT6fr*k8hN+%U zDUHnFw8yFkM34~tfXED`4Ow2`qo*oz@E$RvY)pyJH4R!@OlH}fAA@Mxc2w+Wr7*^z ztV#C+;NHFC4GDK2*eb0FN=U&^(@KR9z;#Wm_Gb*e8D-%jV-cwo#^z`OgHvhKIDGK* zF49Vch{1+)b}nCMeR716j-t%jnPn85wf**FZZAKboI^B4Y4zUc@5BA2gR9kb*lpv@}Fd{MLBoKPQJquzh=9m-@2hV9+o zuTWIIk|HR!XI_7uTG;u;%!M4d-{Z-1+no{>~Pn;DTe- zwrtv-A;!^S=KVOiE2T+OFB1=tkE=&(B!M;A*t@qDC5CFg7}0oM(046ockfcpmqa3E zJ%1sn5T7*Qm-XiT0Ry@t^&l3C9xJ9MFye?T(n9$xmM`^KI(X4L6G@Ybboe^D+qC+IH zUTp~h9((3l=6jd<&_DbeJpZLHV6yvIOwb8jc7ZUQQ&_{^#fP8K$}GPUAZT7m50EA? zWv&c^^K89PC=Jnb-~&%TbI5u~oHhfyvufPenx5VV zj2h?a+%L#eir6fhOdS^QJP=7;!e)lP>riSSkx<5Bl(1Ot(3d^U>Uylh-Mo9!#1IChCvqT85^y~dOcDb=LFXKr5uc2zp-9q+=shU}?0kmRSv+11grw+v z;%p1{@)dmOxLj?yebQqjr|?2u!^UY?xw5Fop+`$+q%bKDnfW&&W;TxX) z4(1mgCbRIlkAE1~H~i3_`;Yj@FT9_}u0M=ui}R2daN*)1U%c}fl5di!A3EIGf9Ptv zx%U}^LSA-9!{GMBZ}p${$ukjAW+a4^wMcY?5Lxc-hvU-? zL*J)NkD3IXdZMYg+3k{wU5p;Po|)C@!rm+!RyU5qutwXOplAYx~ zm!Ej=yC%cQtEdN1@}M5BG7F-}6fEi)h|m(b{^%U7GdBJB(5OXSk!1!;;L0Pr?C;dL z5ZJB8CxsY+TnlAx(Q48gO{(A+63uo?yV+0_<>>jh7Nr#-fwmdij$D71<+RO~#opoM z;|mWcWhI6X+ z&3=iNam;)-IJ7nRr0Iud8a^Qt^CqKCFfXuK#?W_Yqv@J0HZLZ9Uc`_vWku7p%ojVf z%^E#T5^L705d-)h5&aUA`)I39qBjv@=sQJTjC?^#qxrS(K<7z}iKIvfKE;$|>=aLf zGL#|)PhC~Bd$-fN>)K@qCCZ)ftxs6q`wee{um+!Sj8oE$cn+2oxgPS+-Z@hGtp_0r zetVCdz02cZEj1P|t2S}%t>4Wf-}v3ouK3u`{x8gSFL3SuW$jI4{mkzBzR%g7<-gpO z5rIrf3tSZVfbm zQQIhLyLM{VspHtLC2N;0X=XH>g`DAb_xsip8p-rSQh0(F9;Gd1j&1!=YP)c z_g$YWdF0wP?!EpBkH7alhy*7qsJ8Z)zxg`TO9dMjANwG=7eW7du7PhNE?(fgCkjpH z0)`daqZ%KfEG2*UZ$HOB{BK_P`m<*x`7i(DuVA}`)(RUUy=#~?EiR=2e^2L$p=wC$ zh%r)^H6a9&@F25Q`|5>lM$vQQ{vn%JuG6(EOi=-mcDZ7@eSx#%Bg)YT+q693ol8Kp zeZSOFg(QRw)*{M+l%VY`NKJ}SAQ0C1Ae2_wN)93pnF2*gN{Ol}>$9c5Ghg}5D?#K^ zNuXaYP(o6bf>AvoMGxMyySu?gt+y8^cV4r$y`Z$gHiw{cTACajOBy=d|Z-&S?Qljl0FMN25yQd8z=I&h^GZ$c#B3Yjc zBLqWKeBJ_rcL-{h^E1kNM5Q!^Hkh*HV7BDyg%?)}Ap>j_8Ah%*9>K_fYmYIb9WFlg ziI3fT^TmJmEgS+lSM4Hlanwdt49Ome6g79=YB)aioE%wB4m%F^Tjr+@=?d{R#lEK%Py_EH2!e}x95?$A^n9uph``^d=AAgkJ_>EuZ z-Jb z%phMMe1a)tph=mWX(&-)-uN7y69%v-WvpUrdy}fW#np=%U2n26soCBrcaHaO+=%@t z($qNDv78@c!$3=mjQh($gkuz}RxMW_dzSn6?vYH5w}Hd^N4N;HCNU~OmD|kE4v1=# z%?ro{kA2Q7R}+X86vN;)nLIu4%Fq%?FyroJbCc9F-OS><|7wUV7su|H6!gs!r8UdtB8ND{fz2BNq1ITyd_G?SKHI_y+O{LClR&gW87;l{vg`V; zC<~OyYF(wxfCYG@(&)mVgbIg8XOLtLok$T~lr)QmH674GV ztE0n8XGL+dIH9%Bxm>`dhIK`guu<^nvme6wNPl{l>2#B-(j4Bsg^xpvOMvNxM~M9q zMO`x4dF%yX3c`F#UVt#LbV5Lg5iPQr)5ZJ}Y>h@4q>(Z^ezZax#o|P8^N%CH{P*6= zfAAw0dH#tpE9W>~G$0b4ht`L441kn@nf0_S2Bc1#VN*znK;rwq_b>A8ANTeB2vmEwH87k`o8Z4 zIV?izEK^e^$H&It(Pc$F8po4`$3{;S0YNvu$bvUd;Zt9o^ZS4F7B9VYlSD+w5^WUq zsAPA0B1KqE7qfe>Hr67Lbjwpp16rkFc+HxC&5K@dv<*1<>(r!YDBbilIV&lRUX2&x& zw>LREIp+9&Lu0`?xNz|i3guAYSQPaR+mHW+kN$ZKBM&u)rs30RgC_=oG>WD5h#1-0 zEzp~e&wlxYy2vSEJ_ZUU@lNph8z2T7S!3N`3(sj|eu!&ZFKS}QB+3~So}!pw%8KYM z$M=rWRmH#lqd&$+o_&g+`?;T^GZocjgTCuBXW)B;8VIH#>P5Vr&y;|4cmHr6V{ktB za~fKg1+ME!F^f}$R0%pVRLYT2>YY{bEZ zq*YGw^uZ&YXJd1dzxosZ4#5Y0;a7j18?U{}U;XRaBxDp)hZF-o_#}c5au{0Ie~@>M(P%W8 zHGY59hD(WTo0C#tljP2cq%IYgw0oQTblx^!!CdbXS&?T@Bc_6UyqCudx! zE-^BBvbP>ag}}OOenQpUzxh?92wb^-oseL5=LY_{7xMZXpqO6a;Pz`ww?53y?xW8S zAyXP~|B|B6;b@lfd@ImK(S=<9vZqR(x*~YtnGqqR^Lbzmu59f}{twsDbpoa3dDFEN{Z96-JxU?r!sTlmzx5SrR-zkU zo?dzEeILAg>!r8;rC)%I1ZJX!6e)CpmV#0%O05V^^N;^`%d1}lVPPl)^xfsm2JEHa$1Wn^J*AFKx>TlB|-$o zbuBh0)ei2SU7p?hTJZh%6xApNdn%&sNM!{ge{gJo6ndm7Nl`PZb7oK*V6=Ok*(ZOK z*T4KJHh1=*F3^)bymKrU`%E`>^v?BJ-g`up_(Bt$ zr|l$1`;zfUvgkVsS)jFK=^T|5ymcB;h2nJHGc66e&~z?)@03g=k^#4wR7lLH(= z2$c1Rwrja@^A z3ayq2l6O{UQ=H4bl$5#iKq?($NVe~~VzO0v>k)&|B>FH!)?`zumfD}p8$yz4QbzIk z1xH~#$Fqd4wkeHgK%1FN6uaA#5*W4fyRS&Uz|@<<^{2GmoFFs)p>>AEU-|6saOdtV zc6av}jVCzgS=_tH-qpw0e&h+h_)mX{(RhoeKk|J{Mw)7KkJz6OtEW}H^W=wyyuro8 z=75K`hYOK?{89*H%Kmm2)1dB6ymiuZ*7m~@7MXXJkP^Rt_mpC9M$;#%LbJ4vzPDLS z856A=Sh;}>J9_h@z?n zwT_|h+iX(tc31%3fd)qB{6gy@kaEk&z(t=okqDxWF$wEJZwizBh&ls6c~T7-3@S3Vy->9OSyFwWlZiRieLn6O^s55y>@ka)GUtg$E4}{7T3=im!M?A zhJ3F-`_UifLqGIWJoE8?llOhc5Afs%zKi0{7uEq zNK$=beC zQk)N_g(=ZmL-d)YENfAhWw~hGs&j#q6v=fcJo|U{IXgP!bg2-*p@pQLOxfKWt8vBU z#o7K*vpjxX5DCuFu9nQ(h*G(8!9@rp$}C1=v1~ZH^E#D?T)s5r!Xr+umr z+t*08A-EOwCc}^%(CR$>)HmA?^IZ86Y*yYA%G#svnWnLovo24__2WA#?=# z&USI|7epWpoq{0oeTNTT?(FQ;Cv$tYYFZE;bU}&{T^I`OQO01sAmTBFWM^kXZ%)c9 z&FQVv)%@_)-a1S%O1?Q{q*mY~HY7CAJAn@g*Z0`AV{>B0&okbBB;z1T zWWT`1rL5Fi%?ZU;wfopdKJ?At0S~o@r<7eY-bbAGv?)!djGYXXY)mKl^B@y zl7rKT5k1pU#6~z0noAe6m}D|3&ei^JFYc8M~T=$6N{&5B}F;RDo0(py1H zf>BvA8pEwOzQ*$KHkTexY+rkd>BYy01GeaeU(2Jc~2Q|MYX0C<<^kalC}eB;L3i2?Tl{85NokBAxg2 z-V@dWQ4&H9q>#wSo)n4{A^3o`Jvv5O=ZUW4@|CN+eB%|0dQ7`qA`3$p%%x>H=FA@v zV#qp!^N_2zhrrX*v-#D>uEl(%WjfdoF|jJQ3yCB|N(q}qDj@~$g@hP+o0=hoKFz4m(a*;plMQx8ein-E1#s;xX9@8b)Nl>AEr=|5EA18x*p8rD(?2H zOt+rU_4LZKnHS*X8~Fv~!-673%A0^oaX{)M!4E#aXn6ItlEZ@$e{$P#b2+0hg1vFU zSWAS;mavh@eFA;(XqAVe*4pzc;GDM~vI62jhsUcsT} zRuv^e2vHSfy=cS9>9WT~$wuLL@3n#-`d2RVZ~xHKeDwXBeB_xNaP51`s5VT;Y7^LK zPHx}vtCO1<%&|0!Mb1Bt0T&}<6EQNOk|27JF`?@zrkdbwVDiYbY+ZRTN@|EXMrQNk zb-Z0B>w5HPdt>+72S4~wxc^}%zyN?zXoFIk)_Z({lcwjjgN}dvE1Uc;zr4-!j|%?t zzv8*}_$j~e@=bp2#u0tFps{mK8ixxGkp#WZwK9b^!vH?0fdpsG2|efUsj~9b@Q=~{C1sipV8GhcZ zC(KsaGJfk$$Qd=4bz_|C%qoc9XKI@jkGcFGxh3?{R%j4-s;ZZ~3>4A?tha z&ASIPIT!=Qx<^_ml+nZ(ax9H8##$SEaJDSVVGYz-V?Z2`Ly0Mj)KaP0ybWF3AaGo~ zdX-zZ?(>z;{t==(WZN8~O+@KHT~+LEPRdeo6_~H)hi@#KCPh(+<>G+k8;l4n+lWs& zOmo=0lwI{K{`#<7fZ7Cpf!ziI5~NT1uIVqqWRjcs82) zY}^}I+b}S6Ddm&E^|>D?I7f_u>DCrM`IA4%4}SbR(2|@hBss_bvy&%h{HEd0dQcJu z#KZY=ZnO>|}15h`-;+HO7$pn*8N{uf)3G9BO=loDf zSd5V%1ui63ZHp)hj#n$Bgj@G}?lcxH6HjlAd1iM+)6Xdek>)S_euEDhYbDks4wo%L zKtBX7C?U_uATi)}A$Vj^=XEV{SQkTxJaS=|FMaU~+_-m0HJ(ruC9Z4f`+j(UDl?da zxFiI>wzxld3UtPp*7X)$R)Um8nIfr-R4$g7vMxdh!FktLLvElPn#i2(@qLew3R73A zF3WP+_(j**ZG>cNqa+GJv@1e?#s{9==Kg-q-UaaU6`NCICbii+Sy<7WzHzH>PVP;% zuRP+tqifGF#U?H#tXCitr4l%w7?qiaNUCCc?@_AVN6{*O@<%2|%9aWyJJ<2Aeum&3 zqtW*6r6)f6{)0C@`^KN;7>;$N&;rz`y#T#Q*!V4L|=kBhOzGbT(p? z#%P5S1ur}q>AWNn>3uG2Rx&$rTNkiCydx%djXUHWJ*$L+b9kTC#4o@48e2O%e9sH- zr&}#(mJ1Tuc$$Xr$LutY1ZRg|zXJ^nKvbq!LQ39t=P#a+WDX%ll#)i6BDmi6-evtl zj3Hwo#t>t`b`3E_wY{@l&Q|Vp*#<%cVvCIZdCx+!GcIj)5IQE4it(s4+ney4u*DTzuxe-zZU3J}e?;?UC0~A`{r*0r>!j3(e7q;(z@=ce#6_@iDOM9cN9; ztm~O-gH!>R1e3z#5NQF0&VkZu9T77OgKHzo`YzUGiPi>f3Y_zN;Mw=!oae)+dB9oBS_~>!bBgy8MxH`uB4u@vZdc4mb#27sSkBtd2xnfU|cG!^HfUaTDFu~Mk(J`Yp!#G z)`3(?=hV=mEQS;pMG66DJs)`Qd-->N?1#C2?a|yGGPo+7wfSXL>YU=u?w_=N_z%Fr z%}hy^Oi^Ym-S*i_s1>>}2q8>NDOqdV0Y?y|gmd=%15uPE2qEjLsOBp-KbtoM+Y4!Q zmZbFyh>7SeQe$-{An*tgF+_9L<<9Tt0TPZe5<kV#;z2Hyb5j*#&EZfI&tkg$4<#oPaJ#-XUc{ zU6pKY)>UQL1LVQI*IudO>AoZ)Oi4StgZG}cj|A_}TUsF^W#p_`a^uBMad_*KB)>$Y zKuR7#pm&j`4`^KyWl7&P$YSGCwe{H3f7TrE(71Rtyzycw*2#f_djCjmAZ=G2iz}ski_7ylxDjP&&^XOzWr&1lkn5_WB!q z`U_vgu2xi4eSUJ3WsMwO7*m)WnD@@Q#`NG7aC$bMODU58R8gRmB>22)W{-fP(7HG~ zo3$w=SCo0pHARuhrXfU1ATh>hBehyAy2WDI(e@GV0#a*^W`TS2lEX!IGee>%DmJHe zwJ|Z5hb?U0%#U6Ru64+o#cV&z;nHyb%X|&Q;7QRlo@_AL*dqG;LFtEKIs}iwqmw7Z zL{)9#`vtn1?x_00Q$Qt^5`S(SVEw&RLJV5;EYXfJvFat(3O@0%V_rJyX}sj+qlQCq z%-{RT6)(M7<=8i+=!Wc_m?G9kn%^Y7>5 zA9x>?lB`zCoF>wD*8L0tmAW*1DqX+4_j2FQ=B602njhf2V^rkhy>o$*j0%R}an3T@+{4O>si?<0k5!f2iy_EAHxd|ACO}-sT!2xE5Ob8g_lh^(s`&Rlrue0w zIpzC4e!zeGH;(z8zuR(Y0>A#xcYy5fHBx4SMa=CZrFk0#Ov9os)llp>w3V${z$^_L zad7tzU-;se`23C6nRk||9uom&^dQkn6jgctRmqHFzk3Tv_wOIhloaQ$hZHgwQKp3V zF83BzWwBhYY>dH5ndc!Xz*OZBYTf6wj-oVmS*k_j=CgU5<#VA&8UwE7#+#OQc9e%p zsnJR@sg&NB))xkpF02l}_LX*dHZxj-5XmkN@ILDfybr8=B&NWk53H=mCP}|K=H%c_ zy1vJdPXX%!iCk`JM!WRwLZlSY_2%`>M?U<-*L&U%9Rh`5_!Q^*6B{x%FBNp&asSlt zKm77Gx9^tx)DL<-`gG#vZNty}!#(D!ib8@&k`O&2f+-9>#K9Ms&S~2mEfdavEv3k= zojB;^`ksrIF7uba|ND62(k`KIfrv-}*LSq51-9>Ty@km6?*4U7fcVz_!AuS;!Fm)` zg8?M@K=6^GFjYucZ>{q-=K_SG4PC07LC`fV3C#A^wmMsOv-!#qLe3n}5{}Ot&pvgL z+s6W>3_dE9AWg>=n-jAGYyq4dz4a2^>9Gr-j1lvbyPURxh4pma6Qa*%90DSEk}4_3 z7ZA$OyFlkXap*k0KMPpv5yF5h>1~fP)2n9u$YWn`4$$9>H_&J~lrsn_V{joGJ4R)0 z@I0I=e(qOy_(#7Yu|9EOlAE<#=jd%msdMIU>q6EB4B$rMLG#WK;7rOP4+Gxdyd#p$ zo5^*2;Y)wQ;bO^na|_#d`O1h1sSBjch+r31LmH^~x>vx>`^RU6F)_H@FPucmEgo8f z6j)~|ilXpB^}z=#RPGB@1GJn3n4+X>TH<(Yb}#Ih`>)=e%^F8YIZ$*33)tKf^ks#_j>ZQ`2`X+1Xm;y!!VBXgT)uoM$E#O%pT5tPQK z#L1nnVkXZu4{aPQmY*F5GAEjltyJKIh?D4Lh!^G>AOCo zXhVG5cr<2jYs#$YdF=5gc>2mCG|OcUla?wU-@)gJKKLO7T7Eqp#QG)Zw9&n_eTpeU z5(tq8Q>7H%TFSzd9$^v55}AG&^V?<;LHZ=$MM%?}{v$)4!5QaT1i%4Jm} z84=M_Y+ugC@M$9(aNUts@i#&j~t9)iK;tF)$Tn>_fXn1!WlzV}^Q01%Wm3sS^cyG9H%;;C|C znO3?CLWkg7KUCajkAQPogCGP&Q9??pE{n-*#e6nzo4&P#1lO-l`1Ge=r&5s@U%G>k zLne`cx;9M4<#<$banSAg<;mB+?AxDU3n;1zsWno{iiBTwzUlgw;5#O!XYaE!OiX=2#jRFB#-c(-ugUr%L0)c!b~4eX8TVyjXg9hI=fc0Fu^FrvbTho zAJocPLd>oc)DV4(d$jauLcmwn{V2q~Ll99>BtX49cF9)zDrVQqIpP^Ro9l-@m zS+O`hWwuywFkf-={sEtU=~X%x2sSs0r4-JCrLwGi;1cv;xPRv+5P;CN-K?xCq!hS* zcmYI07i)QVGIdp()6>(1RKlCmWL`q&YP+>YK}d<#sxXo?U%Evb3`tLLL9n+KxO=48 zo+R|-2|oYT1&6b&-kFSwdOB7YhkH2!tA2U-Vzeu-s|l<5ePAfPNcrK50UPk%lcZ#{ z_cYs&evs39H#oiZWg43)`ZWChC=95Q=sN1rWUCrYuDx3y@NikU5EOYmA*9H-ED%yr z7|mu~Fs?L03M#EAjH27bRy7(-cB!@n!9TS^;DS(KyFq|@1KF`v!B_w+%ru{q}3-)FdS ztL5&SukpeQPjj}&aroo9WIQT&9td=3ZL|N!O*6Nsigs~=Nk028Z2sgUa)+Uo8UG(m zx9M!hwP(JKOOHK^4}s%Fq*M_tJVq6iG9|RJ~*k~qI{(l!n1v``Rkd;`DC*5;>y68o9^C%E(F+hC zd-BP>qAJHRMgnlwbey(5$DQM#>1jh?6(UDX&vDb!c{u4D`|~Ajj5I#7v>^)|5G-xx zx06ydHoJt@WemBOFQIfXP{JN<@^RbSmZod@{EeI3Z!M2M`2^#tAbQVgKBpRw^V+D( zA?M!=tlnBG^A1KZ0r6};n@KGPbx+P8@ZO($1hm#@EzNAz&VzT}_nB!7(VvS|oVE0Q zhfuQG*_x=?qMt2SmV=W{Y;0ECJuBE9J8s>c@m(L@h3X=&zWfGS8?m{$$;P7+rq?rG^#A8f3q&^39 zvGI&F)4c~@0R4^RfcFj##%gdadb?;sinU~E`1Mc} z5fiwW2nmeNjiN*_=)ol@&Tf~$p@ZJ-=9sKZG)Kyh4I@<*2d?ICuy3vF1G)LFi z-clDuxqD%!e)FZf^V!n+@z#c3t~^&SmE7L%c7NnHbLM9t3@NP%|6Hu%h zy5(99Zb;G7hkTlxc9yfwG52A(1_Ti?RKG@yGTHMNBi=_2=MARFK}}LBT;C6ovOS~m z81HfoywZk#SPRc1X#VsS5cdxbW?7IThMpsdDN1bL5quD&g1RcIc^_LPariv1*siA- z;^MR^=-WBoxpI4JYcy{-TehL?oB8y@!nYV6v?+b0W_z_b~RkJ!m$BvLB%MhuJL`vv=j_N5?Bt(G+RLT)^ zF>?O16ar-min65dS4dq^PcMG3p6+h9i{rDw@bqWP0hN%AmNFDdF)^A-D<)d8H?9~d z&4$tJjY=+5hLI5LR)(!Yv8g4Sg=E7BHVet7(M%L<7Mh8cOq8IO5~J36ylZ<5uuYnu$t}T6I3c<*H=^uq`{+D>pUQa zn1@9h0?r5GnkJSSZEC!05mHjtThE(nYj=$Y$Zu>8PF@M3S*LhP!A4o41WXIX#pyVo z00J(KOEyZwNJ}n`D=v;}YNePK1|y-?IdZMk*+|5u3v&M@aZw+9Kn$DdkD72 z*?thC2>Pxg#Yj8Y!ITtOn=9bMko^~9cyI@5Ckh?ug%J2wn!s=*nBn6BL2qNw2AtG3kl=N-GXu8ev_#U(UH&`6J zL1hv`#4P5C0n{j8ov{a5Ppi@Pbty6)@NjoR}Uio#%|WKt@G$Z;=5q+ywL z^xjh$LuWmURZnR&i>{}$`Gt`}5e9mBO$iGr5K7{0k2WRN_xV`~IatNy`3sX`!1X=4 ztj>cQkpka!d75`_AhL!N=Ih`9Ku|`{Q;g?8kXWaJiLCiEMpu*ZNFN>^&9u@{O7%7Z zCY(Vslb3uJxJ~Tu;?a zyW0PP?Uu-*qV1L}yC#=(xvc$@O6ITGwHRsXRwqn1r)*!mMpcbCxO$YLcs6Vmt?R)L>5&Lg%U7=JF@0hENHuhlm)3 zc=y5ot|1VJ-uXo_$jH3y2Qy?|3uB5%NjVzTX8-=-Oo$XR#T-c_bYbw`=a(l-)2ofT z)Qcv}R$a&#R7liS4k&u`vf-qW6v{JSG&v7&bIN2~?Z}J;tTB2!yZ7R!lA9x>N(sSi zcEr*_3K2!5lAc-zlJ6+Wl6o`-rSK^r>j}nalDC9@g>$*h99iLAn>7j5=JQe&TjXNW zZ}j~0u_(nlC}LRm20xk{a?NZSdTs|`r}rUa{|Gu~QG`KPnX6|Ig5LS_l`q9y3K_k} zcDWwTc5RMqCuasi?h&#!BX-{QIbFeTjlXLI=TI*90<*FXSb*Y&fq zu0cqgwdb^f9{P+VqN>Wm%vS9zg%GXn&KXKE)Y{tK;&KZ5Xme6kr?b_`VqtA(v*uwk z9#QE;N($!^(~;ruaEbRYt|a4HZI5bp9$3j;yPDm$?cz2m38f^dJHp6pT^T$A000c4 zNkl^poj$1hK?eM{fWhd!pvU6l0*f+r$T<;MGyklW-A zs&AYUww|GcShIqXQc4PyxoIOaC}LC&iZ1m~%`Wm$J+3CX8Wo2r3udd9k=kJ*Sotr)fD!6jUkjV6^zP+w;p4rjHim^Ez*owcAimHGZ~FG z>%wd;TW5xyB>;=i9)BtN?pjflgyuL?z+@q0LfG!UMX$wFNcip1n;w90;Rp6}6dB8cQwp2nC_m=$~DTz`lyw9YU zHo3i|C=0r_C23i2Z*Poj;B+}(_3dggosJFL(}LSaH5aE2h2yBzJbrZp=R9q{Vp_)O zcv9~i&Rn@(zk#M(9ex(S`cZ8v`u3E*Us0HXLIldP=4>(N%yo1&BI^xAinxBoWV%VS zTA(EKealD<2A^Vtkdm|cOpGf{G1>d5Q2I9?$_B1W9nAR_kVB(<$W!K|Gzb)ZNNA}D zDRH(~(FKo4kyUT8-lIhB8|-Yz;M~w22DzbJNI5i*X<~>&b-br*8f@2Ln-%S1j_n)z zc9nl_Rs?79&M`kZLrRIW4%_#G-;g!d@!*eheZb;uHd|{Qv^JT9a&EAPDYQ~XD_H<@ z5xhqvlvLS;90z~H;6otAdNis>z|qm^vTL0{$bt|Rk8COCJj(uRlPg!YaV}xXElj<^ zc(TE`GCS{L>ALy;%YWqT3S>zL3A;K$%S3Ak=pqk4{!vzZ2SBSJB24*J9HOFw5m?KB`A4a|9+s z%`*EE%eq1-C6y2pU@=>C{bJ#Wc3nXq*h)9KywT&E86qWCi!)A+R~*j*^CnywNFlwx z2HMs9uxrlVY+OJ}NwYem_YB#G5$7^hTp39Ud2=eq+l(gLOeSMYy-8J1A$eT4#P_F2 zBJF%Xb*m$kh*AjY_1Eo)$UlpilJEh7BvZF=Zlmf#q>ze8&a#owqmU?-<(684Q3Wx7 z+>z4IdPnCSLTVg2CWf^;Sjuca9frcbZL%;l2FkJ`#6WPFAVT!Rr&QCmE6TE>YnFH) z@ILqY#B8XL!;XD;Q4i^F;rlG|XDD&kdf`2QgzSFN@y*mDqUTwtju`iBO<;i3RpSeE6R8}YD|emgm4w~ zaup9?w2m68&{$5V@G^f_vnjj;bb9AC82bPoigX3h06PHgot}*gO?L?_lS8Vt7QSv% zc-lJv4$sdonum{m!X)8q1_n)4#YGs9EQtGtaR0yKW&4}o{VnkMR2=}=CSY4f^)n*i zr)BhzY65WOfE&h9V7v$5#T}>GMl z;L%o7FgM(^4T7%-u8Pv%&YWG0|8@QHlRw;Eoqht~Qpz%^$9#^|q9XSK^GFdX&y3bb zRc3SqQ5Y5))-x*K!iRvNWY{K-mcEu1YzQ!76e30N0Gigp0jO+%6|Iu+czxSS&LBDH zk-dH*dZCLITuX{tc9QzVNkVAnY_ud=i@;uq+TRzTq#(?_4Pf{A`6QI4fU}m%($ES) z+!zF2zz2`5!C<768ofLl*HM|pOkxns0O#VNQ(2TS#_WxT=HO;w-E?llhZ^ep3K%M& zq}aIPSSJFeygGpyWN)B{N6|e&6P#~A)}pm7f@`>G zDk8U}sPb>-&Gh6iSEt7xHBEgA;6@O{7oufsvIg#obfjWr&<+3^IgTJnDufvH31Db6 zmTipND^yHlR@qiEe@VVU6*T}j0z-jg#?T0Y#b_ipAR%>f5U0l#Y@A+!M#to1?f%Zz(Ze4+_}*@*hkH9CKD({10r;0b4(gO6 z6|NYVabo$*Elbf;FfIdg(!LBpF?(N4&z_s@`-iq&z_t}wYYy$4*j4cLb(mc|`}gGh z>BqKNo-v1s5PU9@-b%ldmNz2#t@K}|HGmcg(OFTJ@wg29jERmsVulbakvdkQZdT!j z5`@zR`Fb(%v@9!Oi7D`c56oa_LK_&*nCM-A-VGt9NDjdX(E(8Oy(7NMFuGy_j;JMQ z8aYZ{@oy;O?6Hoj+-I$L~8^!8H|JeSJF}KmO<9`o$CPn#+vX%S_7Cf>(8D>a%-3 zk?)7X8F?vX8n`F(=f2FFrn8^UuetSo-SrhiBj2f`EqQvL!UTQy zv7s-0{p}-s-*pp1t&`xsI(i7-S6`2sCQ?n= zA_i|kXnKRbQO~I-UNdmmFqqsk_;`bRSfge7zJb?#!=~^2#zg&p|Iu4ML!A!Nx7deG h3_;(3FpO{c?|*NJ-*l1{&}#qy002ovPDHLkV1i0_d8+^b literal 0 HcmV?d00001 diff --git a/src/calibre/devices/prs505/sony_cache.py b/src/calibre/devices/prs505/sony_cache.py index b87ca937bc..3ac35df9b2 100644 --- a/src/calibre/devices/prs505/sony_cache.py +++ b/src/calibre/devices/prs505/sony_cache.py @@ -10,10 +10,10 @@ from base64 import b64decode from uuid import uuid4 from lxml import etree -from calibre import prints, guess_type +from calibre import prints, guess_type, isbytestring from calibre.devices.errors import DeviceError from calibre.devices.usbms.driver import debug_print -from calibre.constants import DEBUG +from calibre.constants import DEBUG, preferred_encoding from calibre.ebooks.chardet import xml_to_unicode from calibre.ebooks.metadata import authors_to_string, title_sort @@ -473,6 +473,13 @@ class XMLCache(object): # if the case of a tie, and hope it is right. timestamp = os.path.getmtime(path) rec_date = record.get('date', None) + + def clean(x): + if isbytestring(x): + x = x.decode(preferred_encoding, 'replace') + x.replace(u'\0', '') + return x + if not getattr(book, '_new_book', False): # book is not new if strftime(timestamp, zone=time.gmtime) == rec_date: gtz_count += 1 @@ -486,19 +493,19 @@ class XMLCache(object): tz = time.gmtime debug_print("Using GMT TZ for new book", book.lpath) date = strftime(timestamp, zone=tz) - record.set('date', date) + record.set('date', clean(date)) - record.set('size', str(os.stat(path).st_size)) + record.set('size', clean(str(os.stat(path).st_size))) title = book.title if book.title else _('Unknown') - record.set('title', title) + record.set('title', clean(title)) ts = book.title_sort if not ts: ts = title_sort(title) - record.set('titleSorter', ts) + record.set('titleSorter', clean(ts)) if self.use_author_sort and book.author_sort is not None: - record.set('author', book.author_sort) + record.set('author', clean(book.author_sort)) else: - record.set('author', authors_to_string(book.authors)) + record.set('author', clean(authors_to_string(book.authors))) ext = os.path.splitext(path)[1] if ext: ext = ext[1:].lower() @@ -506,7 +513,7 @@ class XMLCache(object): if mime is None: mime = guess_type('a.'+ext)[0] if mime is not None: - record.set('mime', mime) + record.set('mime', clean(mime)) if 'sourceid' not in record.attrib: record.set('sourceid', '1') if 'id' not in record.attrib: diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 91afac8aa2..d81918c307 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -765,6 +765,7 @@ class DeviceMixin(object): # {{{ self.book_details.reset_info() self.location_view.setCurrentIndex(self.location_view.model().index(0)) self.refresh_ondevice_info (device_connected = False) + self.tool_bar.device_status_changed(bool(connected)) def info_read(self, job): ''' diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index bf9dc0a623..b064dc53c2 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -334,7 +334,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): def __init__(self, parent, library_view, server=None): ResizableDialog.__init__(self, parent) - self.ICON_SIZES = {0:QSize(48, 48), 1:QSize(32,32), 2:QSize(24,24)} self._category_model = CategoryModel() self.category_view.currentChanged = self.category_current_changed @@ -389,10 +388,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): self.add_custcol_button.clicked.connect(self.add_custcol) self.edit_custcol_button.clicked.connect(self.edit_custcol) - icons = config['toolbar_icon_size'] - self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2) - self.show_toolbar_text.setChecked(config['show_text_in_toolbar']) - output_formats = sorted(available_output_formats()) output_formats.remove('oeb') for f in output_formats: @@ -845,8 +840,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): must_restart = self.apply_custom_column_changes() - config['toolbar_icon_size'] = self.ICON_SIZES[self.toolbar_button_size.currentIndex()] - config['show_text_in_toolbar'] = bool(self.show_toolbar_text.isChecked()) config['separate_cover_flow'] = bool(self.separate_cover_flow.isChecked()) config['disable_tray_notification'] = not self.systray_notifications.isChecked() p = {0:'normal', 1:'high', 2:'low'}[self.priority.currentIndex()] diff --git a/src/calibre/gui2/dialogs/config/config.ui b/src/calibre/gui2/dialogs/config/config.ui index b473ee7846..5f890631b2 100644 --- a/src/calibre/gui2/dialogs/config/config.ui +++ b/src/calibre/gui2/dialogs/config/config.ui @@ -422,54 +422,6 @@ - - - Toolbar - - - - - - - Large - - - - - Medium - - - - - Small - - - - - - - - &Button size in toolbar - - - toolbar_button_size - - - - - - - Show &text in toolbar buttons - - - true - - - - - - - diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 2d038d9ddc..2474685522 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -176,12 +176,6 @@ class ToolbarMixin(object): # {{{ def show_help(self, *args): open_url(QUrl('http://calibre-ebook.com/user_manual')) - def read_toolbar_settings(self): - self.tool_bar.setIconSize(config['toolbar_icon_size']) - self.tool_bar.setToolButtonStyle( - Qt.ToolButtonTextUnderIcon if \ - config['show_text_in_toolbar'] else \ - Qt.ToolButtonIconOnly) # }}} diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 1c853cbdff..0228249e8d 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -5,6 +5,8 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from operator import attrgetter + from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, QVariant, \ QAbstractListModel, QFont, QApplication, QPalette, pyqtSignal, QToolButton, \ QModelIndex, QListView, QAbstractButton, QPainter, QPixmap, QColor, \ @@ -13,41 +15,11 @@ from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, QVariant, \ from calibre.constants import __appname__, filesystem_encoding from calibre.gui2.search_box import SearchBox2, SavedSearchBox from calibre.gui2.throbber import ThrobbingButton -from calibre.gui2 import NONE +from calibre.gui2 import NONE, config from calibre.gui2.widgets import ComboBoxWithHelp from calibre import human_readable -class ToolBar(QToolBar): # {{{ - - def __init__(self, parent=None): - QToolBar.__init__(self, parent) - self.setContextMenuPolicy(Qt.PreventContextMenu) - self.setMovable(False) - self.setFloatable(False) - self.setOrientation(Qt.Horizontal) - self.setAllowedAreas(Qt.TopToolBarArea|Qt.BottomToolBarArea) - self.setIconSize(QSize(48, 48)) - self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - - def add_actions(self, *args): - self.left_space = QWidget(self) - self.left_space.setSizePolicy(QSizePolicy.Expanding, - QSizePolicy.Minimum) - self.addWidget(self.left_space) - for action in args: - if action is None: - self.addSeparator() - else: - self.addAction(action) - self.right_space = QWidget(self) - self.right_space.setSizePolicy(QSizePolicy.Expanding, - QSizePolicy.Minimum) - self.addWidget(self.right_space) - - def contextMenuEvent(self, *args): - pass - -# }}} +ICON_SIZE = 48 # Location View {{{ @@ -191,14 +163,15 @@ class LocationView(QListView): self.setTabKeyNavigation(True) self.setProperty("showDropIndicator", True) self.setSelectionMode(self.SingleSelection) - self.setIconSize(QSize(40, 40)) + self.setIconSize(QSize(ICON_SIZE, ICON_SIZE)) self.setMovement(self.Static) self.setFlow(self.LeftToRight) - self.setGridSize(QSize(175, 90)) + self.setGridSize(QSize(175, ICON_SIZE)) self.setViewMode(self.ListMode) self.setWordWrap(True) self.setObjectName("location_view") - self.setMaximumHeight(74) + self.setMaximumSize(QSize(600, ICON_SIZE+16)) + self.setMinimumWidth(400) def eject_clicked(self, *args): self.unmount_device.emit() @@ -207,6 +180,10 @@ class LocationView(QListView): self.model().count = new_count self.model().reset() + @property + def book_count(self): + return self.model().count + def current_changed(self, current, previous): if current.isValid(): i = current.row() @@ -248,12 +225,15 @@ class EjectButton(QAbstractButton): def __init__(self, parent): QAbstractButton.__init__(self, parent) self.mouse_over = False + self.setMouseTracking(True) def enterEvent(self, event): self.mouse_over = True + QAbstractButton.enterEvent(self, event) def leaveEvent(self, event): self.mouse_over = False + QAbstractButton.leaveEvent(self, event) def paintEvent(self, event): painter = QPainter(self) @@ -344,33 +324,84 @@ class SearchBar(QWidget): # {{{ # }}} -class LocationBar(ToolBar): # {{{ +class ToolBar(QToolBar): # {{{ def __init__(self, actions, donate, location_view, parent=None): - ToolBar.__init__(self, parent) - - for ac in actions: - self.addAction(ac) - - self.addWidget(location_view) - self.w = QWidget() - self.w.setLayout(QVBoxLayout()) - self.w.layout().addWidget(donate) - donate.setAutoRaise(True) - donate.setCursor(Qt.PointingHandCursor) - self.addWidget(self.w) - self.setIconSize(QSize(50, 50)) + QToolBar.__init__(self, parent) + self.setContextMenuPolicy(Qt.PreventContextMenu) + self.setMovable(False) + self.setFloatable(False) + self.setOrientation(Qt.Horizontal) + self.setAllowedAreas(Qt.TopToolBarArea|Qt.BottomToolBarArea) + self.setIconSize(QSize(ICON_SIZE, ICON_SIZE)) self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - def button_for_action(self, ac): - b = QToolButton(self) - b.setDefaultAction(ac) - for x in ('ToolTip', 'StatusTip', 'WhatsThis'): - getattr(b, 'set'+x)(b.text()) + self.showing_device = False + self.all_actions = actions + self.donate = donate + self.location_view = location_view + self.d_widget = QWidget() + self.d_widget.setLayout(QVBoxLayout()) + self.d_widget.layout().addWidget(donate) + donate.setAutoRaise(True) + donate.setCursor(Qt.PointingHandCursor) + self.build_bar() + + def contextMenuEvent(self, *args): + pass + + def device_status_changed(self, connected): + self.showing_device = connected + self.build_bar() + + def build_bar(self): + order_field = 'device' if self.showing_device else 'normal' + o = attrgetter(order_field+'_order') + sepvals = [2] if self.showing_device else [1] + sepvals += [3] + actions = [x for x in self.all_actions if o(x) > -1] + actions.sort(cmp=lambda x,y : cmp(o(x), o(y))) + self.clear() + for x in actions: + self.addAction(x) + ch = self.widgetForAction(x) + ch.setCursor(Qt.PointingHandCursor) + ch.setAutoRaise(True) + + if x.action_name == 'choose_library': + self.location_action = self.addWidget(self.location_view) + self.choose_action = x + if config['show_donate_button']: + self.addWidget(self.d_widget) + if x.action_name not in ('choose_library', 'help'): + ch.setPopupMode(ch.MenuButtonPopup) + + + for x in actions: + if x.separator_before in sepvals: + self.insertSeparator(x) + + + self.location_action.setVisible(self.showing_device) + self.choose_action.setVisible(not self.showing_device) + + def count_changed(self, new_count): + text = _('%d books')%new_count + a = self.choose_action + a.setText(text) + + def resizeEvent(self, ev): + style = Qt.ToolButtonTextUnderIcon + if self.size().width() < 1260: + style = Qt.ToolButtonIconOnly + self.setToolButtonStyle(style) + QToolBar.resizeEvent(self, ev) - return b # }}} +class Action(QAction): + pass + class MainWindowMixin(object): def __init__(self): @@ -385,12 +416,19 @@ class MainWindowMixin(object): self.centralwidget.setLayout(self._central_widget_layout) self.resize(1012, 740) self.donate_button = ThrobbingButton(self.centralwidget) - self.donate_button.set_normal_icon_size(64, 64) + self.donate_button.set_normal_icon_size(ICON_SIZE, ICON_SIZE) # Actions {{{ - def ac(name, text, icon, shortcut=None, tooltip=None): - action = QAction(QIcon(I(icon)), text, self) + all_actions = [] + + def ac(normal_order, device_order, separator_before, + name, text, icon, shortcut=None, tooltip=None): + action = Action(QIcon(I(icon)), text, self) + action.normal_order = normal_order + action.device_order = device_order + action.separator_before = separator_before + action.action_name = name text = tooltip if tooltip else text action.setToolTip(text) action.setStatusTip(text) @@ -400,56 +438,46 @@ class MainWindowMixin(object): if shortcut: action.setShortcut(shortcut) setattr(self, 'action_'+name, action) + all_actions.append(action) - ac('add', _('Add books'), 'add_book.svg', _('A')) - ac('del', _('Remove books'), 'trash.svg', _('Del')) - ac('edit', _('Edit metadata'), 'edit_input.svg', _('E')) - ac('merge', _('Merge book records'), 'merge_books.svg', _('M')) - ac('sync', _('Send to device'), 'sync.svg') - ac('save', _('Save to disk'), 'save.svg', _('S')) - ac('news', _('Fetch news'), 'news.svg', _('F')) - ac('convert', _('Convert books'), 'convert.svg', _('C')) - ac('view', _('View'), 'view.svg', _('V')) - ac('open_containing_folder', _('Open containing folder'), + ac(0, 7, 0, 'add', _('Add books'), 'add_book.svg', _('A')) + ac(1, 1, 0, 'edit', _('Edit metadata'), 'edit_input.svg', _('E')) + ac(2, 2, 3, 'convert', _('Convert books'), 'convert.svg', _('C')) + ac(3, 3, 0, 'view', _('View'), 'view.svg', _('V')) + ac(4, 4, 3, 'choose_library', _('%d books')%0, 'lt.png', + tooltip=_('Choose calibre library to work with')) + ac(5, 5, 3, 'news', _('Fetch news'), 'news.svg', _('F')) + ac(6, 6, 0, 'save', _('Save to disk'), 'save.svg', _('S')) + ac(7, 0, 0, 'sync', _('Send to device'), 'sync.svg') + ac(8, 8, 3, 'del', _('Remove books'), 'trash.svg', _('Del')) + ac(9, 9, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) + ac(10, 10, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) + + ac(-1, -1, 0, 'merge', _('Merge book records'), 'merge_books.svg', _('M')) + ac(-1, -1, 0, 'open_containing_folder', _('Open containing folder'), 'document_open.svg') - ac('show_book_details', _('Show book details'), + ac(-1, -1, 0, 'show_book_details', _('Show book details'), 'dialog_information.svg') - ac('books_by_same_author', _('Books by same author'), + ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'), 'user_profile.svg') - ac('books_in_this_series', _('Books in this series'), + ac(-1, -1, 0, 'books_in_this_series', _('Books in this series'), 'books_in_series.svg') - ac('books_by_this_publisher', _('Books by this publisher'), + ac(-1, -1, 0, 'books_by_this_publisher', _('Books by this publisher'), 'publisher.png') - ac('books_with_the_same_tags', _('Books with the same tags'), + ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'), 'tags.svg') - ac('preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) - ac('help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) # }}} - self.tool_bar = ToolBar(self) - self.addToolBar(Qt.BottomToolBarArea, self.tool_bar) - self.tool_bar.add_actions(self.action_convert, self.action_view, - None, self.action_edit, None, - self.action_save, self.action_del, - None, - self.action_help, None, self.action_preferences) - self.location_view = LocationView(self.centralwidget) self.search_bar = SearchBar(self) - self.location_bar = LocationBar([self.action_add, self.action_sync, - self.action_news], self.donate_button, self.location_view, self) - self.addToolBar(Qt.TopToolBarArea, self.location_bar) + self.tool_bar = ToolBar(all_actions, self.donate_button, self.location_view, self) + self.addToolBar(Qt.TopToolBarArea, self.tool_bar) l = self.centralwidget.layout() l.addWidget(self.search_bar) - for ch in list(self.tool_bar.children()) + list(self.location_bar.children()): - if isinstance(ch, QToolButton): - ch.setCursor(Qt.PointingHandCursor) - ch.setAutoRaise(True) - if ch is not self.donate_button: - ch.setPopupMode(ch.MenuButtonPopup) - + def read_toolbar_settings(self): + pass diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py index f677c839d8..a4186ad8d1 100644 --- a/src/calibre/gui2/search_restriction_mixin.py +++ b/src/calibre/gui2/search_restriction_mixin.py @@ -13,6 +13,7 @@ class SearchRestrictionMixin(object): self.search_restriction.setSizeAdjustPolicy(self.search_restriction.AdjustToMinimumContentsLengthWithIcon) self.search_restriction.setMinimumContentsLength(10) self.search_restriction.setStatusTip(self.search_restriction.toolTip()) + self.search_count.setText(_("(all books)")) ''' Adding and deleting books while restricted creates a complexity. When added, diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 6bd7b2b502..ba4c637932 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -167,8 +167,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, ToolbarMixin, # {{{ self.eject_action = self.system_tray_menu.addAction( QIcon(I('eject.svg')), _('&Eject connected device')) self.eject_action.setEnabled(False) - if not config['show_donate_button']: - self.donate_button.setVisible(False) self.addAction(self.quit_action) self.action_restart = QAction(_('&Restart'), self) self.addAction(self.action_restart) @@ -220,8 +218,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, ToolbarMixin, # {{{ if self.system_tray_icon.isVisible() and opts.start_in_tray: self.hide_windows() - self.library_view.model().count_changed_signal.connect \ - (self.location_view.count_changed) + for t in (self.location_view, self.tool_bar): + self.library_view.model().count_changed_signal.connect \ + (t.count_changed) if not gprefs.get('quick_start_guide_added', False): from calibre.ebooks.metadata import MetaInformation mi = MetaInformation(_('Calibre Quick Start Guide'), ['John Schember']) @@ -274,8 +273,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, ToolbarMixin, # {{{ SIGNAL('start_recipe_fetch(PyQt_PyObject)'), self.download_scheduled_recipe, Qt.QueuedConnection) - self.location_view.setCurrentIndex(self.location_view.model().index(0)) - self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection) AddAction.__init__(self)