From 5278f698516aa255337bb171db2bf3272ddbb1f0 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 27 Feb 2020 10:52:48 +0100 Subject: [PATCH 01/96] Doc: Fix typo "ajust" Change-Id: I6a974dc9e9f9439392cf8029740fe72415f80e54 Reviewed-by: Mahmoud Badri --- .../src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc index 199c579bb7c..1e340182b51 100644 --- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc +++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-editor.qdoc @@ -161,7 +161,7 @@ or press \key R. You can use the scale handles to adjust the local x, y, or z scale of an - item. You can ajust the scale across one, two, or three axes, depending + item. You can adjust the scale across one, two, or three axes, depending on the handle. To adjust the scale across one axis, select the scale handle attached to From 171ad62aed7cd27e958ce47d3caa23c619eebe58 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 27 Feb 2020 10:50:01 +0100 Subject: [PATCH 02/96] Doc: Describe linking Qt Creator to a Qt installation ... for sharing auto-detected Qt versions and kits Change-Id: Ie0063b0a66a58508bb848b2b8fb4b29cadc35c26 Reviewed-by: Eike Ziller --- .../images/qtcreator-link-with-qt.png | Bin 0 -> 5515 bytes .../images/qtcreator-qt-versions.png | Bin 0 -> 14539 bytes .../images/qtcreator-qt4-qtversions-add.png | Bin 42241 -> 0 bytes .../creator-only/creator-configuring.qdoc | 9 ++- .../creator-projects-qt-versions.qdoc | 56 ++++++++++++++---- 5 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 doc/qtcreator/images/qtcreator-link-with-qt.png create mode 100644 doc/qtcreator/images/qtcreator-qt-versions.png delete mode 100644 doc/qtcreator/images/qtcreator-qt4-qtversions-add.png diff --git a/doc/qtcreator/images/qtcreator-link-with-qt.png b/doc/qtcreator/images/qtcreator-link-with-qt.png new file mode 100644 index 0000000000000000000000000000000000000000..5173be111d6da96523fc7d0bed6ae755aa111c2a GIT binary patch literal 5515 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 VT}rdN7#J8BJYD@<);T3K0RYfUwt4^n literal 0 HcmV?d00001 diff --git a/doc/qtcreator/images/qtcreator-qt-versions.png b/doc/qtcreator/images/qtcreator-qt-versions.png new file mode 100644 index 0000000000000000000000000000000000000000..8d456039e300c3fffe9cc3c31ef7e4dfad4247ff GIT binary patch literal 14539 zcmeAS@N?(olHy`uVBq!ia0y~yVCrRHV2tKqVqjpfcTnESz+f@S)5S5Q;?~=_w~J-2 z*FOJSKVjd6xXwGVokE@y1zct-sLtLok%2RE!6bnNtFLwPda1lE^5mQ}CHeR|rQB0> zi6XD3MOAS+1wG{4^yEfS2+JXL&62B^{F16yg|sP6pI^qR9%;Q%ZiQ{F`d9}`^R%{Z!5jI!>VM)viWna3%t_uTYdV2ujTR;Wz`cd&o;fSTPtt>Wg&m* zeUOq!d&~8TS3>8632yeaT!^GZRAN_tjI7m}H6SyZE*D7o9nQ4q6#%gs41Fwm1?J?{ z`^}%d{%O=ci;1efF){1T&Mz+d>A7mk$vDr6R=YbdC&$OHimhF9m+{+;tG6y)KVCKU z@@rY!Ic_V=Ep^Yyo?K~Hxp4Bex~P@sUb0-8HILKN_}j4=ua=qiy!;mFzdF-2iz)JR zd1kTYTsf;KRd!$Tf+)UF|2-ATd#4vjDPFPhQ~y!mufO*B7S+v5@+ZymJ`~jym2gYv z_~jOp%YSOZu7pk5f1-Q#mp5B=gSA&|t(@bRcGG8-)pB#*wX@G>-mUUl)wHg}YWdxb zwq>EbYMxP1m-3fXEoE6Q=;Zr+OYyYxliqC7x7e5#*GsHJZBWuc=VCANB`QZ z$X{nMxEOtV(>|YqnW7KB%wU;2-E+}7O|`IHX>wPuU7vk2GrG{?i^!F3+N1|2N zU2Xc#<)_TDoSSLmNulHO8l3#5-z~|myR-Yp%=J81#4bO~eYGH^EynSK)|_elJ3<$J zt+IHltIS%JEKofCtmQA24Qux`o+5rdu}~C`Af?Fd%53LG?UI3ewMiz`S;RYBT1L(rW9Ju6Q_b*=O+99tUO$KM>TeG%{dl>)v^E0k7P1m&GN}{ z4}HEx`t29_NuRDq7W(auf2CE~x8~XU4acSG<*)zTtMmTn`hqv#G`#cn-8i`G<{^># z8IE^$H@@Gy_GfkEy-)Y|r+svPX7}OY@%KAHUcUEXfAJ-O+sqC z*d4U^x0xP({(hoj%Y%~X+?AoE|E^s6dgfB*VFkLAZNtx9eYb&Ut9b7 zsYxRH74C^kWv$B$_&IX-EShpsq4vp%iTn2LtG&Crv60a=d+Vw={pIhSR@`1%x81jJ zR;5G6W6`HuoUWfZ(V=wnUf%RywpyUV(rv|Oi?s~fwzIP=7i_xBQL3^$^uq6XaucM~ z=D2Zya#nTI<>PvKSF=8+AN?|KZv3u_p2a)|U(UF~zHH)o_vV|cU%sj7J+JX9z;Cts z-tRdbcK@Anf1YeV6&$5*dPc3FDt+C@d>zfJ>*ihLv_2mb`|H>bzZNUEe!E{Uy7l)- zEYtSOzrSzq&RkXb8Ekg)ylM9vx&&?ssO6m&A0JP-|(D2+C}Gr;4Kc1 z_7&eO=gRMT_2N(4vbedlST`ZjN#n#i*Gb58u*>iNrgqI#R=+UZhhpDp)Zo@5o{f7<3}PomnOkM zb36rZX?RqxD6^O=v;14smax@D9`1I`2U~N0CcZC@`sP&ktg9m{tH*S5N!)gI`!?0b z4l8C`tYxgti!-YH7qe;U6TcWH5)!1a&+mYq1e)FzABa!%Pg`{Q%J zmONCH{mJu$zvRSkm(=#X=QF=+-Eg{pd}V~A^>y}5)molnn^&qSA1u03Hb+iQ?%q`$ z-xwc(IXS8v`z#cLOM+%>QVcqr!@KHJ!?LZ^qKmS>MzX9fH1KC$Y=%Mz;n z^-uHv)|$hYp>^%xKPx#uWeZ(HU6JKQ*9)Wc#m?v&R!8sRT0VDzoYUK_^QJi_sK1M? z@i=bBT*jHhd`Y#vcIl4o@vXuk`f>i^$M!xn$%^+ge{Vj$U!BEnb^Kgkg&Lcm`rba@ z)Ho-K%oe$ub*-Pff)#V_BHL$M`lv67#> zMZtpg>-qh{AANayyF8)C@YvddDVJ|=%MFg7YIBD<=(uYOmg#rWY zS8*>lJSI^tv0QM@F^OcJ>ynjVk&{L8$TwlwA)$m}s}yPSLYW$^reU$)P$vnmnoh?{xS&^SE! z|Dntt!(#=zLSMfWxO%nep5_^m70>j!8UTRv5K*iRhAk8Oudx-%8iBv9XD) zz1?>CUsfpl%+Ot~MY(4S^Lu^N-^r$wJ-#OwIa&HrYGMBWcRSu%7UuUD=BX_g-R0)y zCUWvy+3r3$+go~b`qsJMW%zn&s^#WIXN4~-DK*7@k(pWX&)ddb&H28i%jOTI(;VCO zecpHTMcK6YGUv8^#dEqpSf8Jm*i&e12`*-@xPg*D&+6hR*1hjvGOkR7M4Xgga*yG$ zvyZn_U8?ry_uv%<@!#qC*%!RI@}=aR@ZsMNO^!*Fw=cf`{D|zymon#nyZiarUpluW zk8ipCFLwXju5usy-M`;-f1gv$`8cfl{7&(!AGbxeTOHf`X43oAw{ffadj0+R?oQ9U zXKrF?Tc>ebX5O4x^So-_1pNDS<446Tqq-OS77CY5KQl)xOw{k`)*GkzQ&X4wL}yQw zN@Fjs`aV7+Evs3uTGHJHGFOMz!m=oUh zQ|0Le!`_0e+H2jHraal^`$cZ~_c^th?_a)8*kc%WTsqyS=XU$$!-o&=zP75lYU%0+ zRR-R#`8`-GJ8 z-|ODV|J{2>^yBrq811uvp4)dVQTP4x>G*#6l^@>!f4BGh|93wtv>kVy`Sa=iAEWnf zZ?8_jJbnMa+3PE3-v9S`!THLM&+lJzzE+vC=ytv3qLkmZ4^J$ZmLKUrTy0%VB;a1Kk2&|Jdi}b8&-PBW zzpVfNjr;bx&x=zx|2_O%fA*Z6^WzOAm3H6T{q?YXtK_u$ANSVY|MThD`<*{0Z@U-$ zGjYq*^>_dL)DN$JcWv>mRYIH3ta@`kKK9J(O4F5=H&+Lz*#Bi*Hgj|R=bXsnA>EbR zjy|tnxjV#S(W0M$%CWWovL8NCDV>$~Beu8a?)=r~ww-?2!u81I|BpqgjgNW{l<{R& z_iZ~dh2!JPxS}Zk*>&H)N;|gkB-kw%UbO%J>g{pYzhs#j923j8dAB*BS1&)-*Y93c zmExygz1tUwiyf4?_B6Xnb&B6I`vV%wPp>zYI>o=-diG__c;gq#q}7A%W7;n(eZFyU zcdqNF)JZ>6;vQD4FZy-Hd$(P=<;U>+e{agQ>u2RYkE?k%_v-U~vvU5w?2TS;t6sje zF7IjjdYxaLd2Rp8lOvbed^+_id;Oh1H?7U(JD>J%Uu5;|+^Otc>bsJ)&#zoHuh{CP z*hb$MS<~Y`vrFhNwaPsHlvhzA@Wvd;%$lM}p1U)vf@ZAU@vLu~)x8+4BjL$EJL5JS zpQIUM%dN8F^A45C-#4AA{Qpts@6961@8J*(N5wB0;7=U(ZvrMvCREk71(|F287ynk)p z-on?**XyjR|Npmq<^7$NPH${Kp30i{Z}-&5?FoC%t-tqYYJh_TfS|(-gq?qeq`;p)i=L=;@`A)BcogO>ypE-bJqx6ZQO8svw7J3+Emr~ z^3f`$NqPpaj*KOgR7Q(e%b5monAHlNy!wwX{|zC8!d{rX?!{KOwTVz zU`K=Dze@Ypmx4nr-d@tn{r)kfciz^e&R-lYqD-I16rWh#Ytvo*c9Hv&va5TKbe8V; zA?4cpXl?rDbybR7S0~IkaENi1wTRm0&EftNuWJ|cKRU+yT(?e3x?<9zbWi@X_qKgF zED>pO#6_GdFLz0x!0m@mQtuUqZtguOa^JJ@a=|WNi`why`r7_=Z{Z$I%hy)4}GtGv@UDBeHebUD5FNlSFeX-mHSS#!$5{%EFd zUKNzHV`5gmp;TgGNdsS$)RPj=HAh+yt+z3io4Cc9p?1zkL_ zwV^zDPM=?s?rV2eowsv3yZA3$x)|%~c_xHZb&d)bm zeh+lf+^tmph|zD}qumCvXJ5{>UC{UZ%iQ`B%a7rC{~p(`v6-0rJnql8+pF*Y^V;bW zSsi)v2g6;ztom0^uh!R88tyYc@#o0wWk(NfTq1h!$2@yxPsioDw!LN-d-g`ZDcJQR z^Wg`-tfRj#w|bx4HAl?9O}zco-_xwod-#^;id@&Ry4u$B$W1Q&v(<$Ye_vjzKJ57A zpDTa(w1|t0Vb4n(FYHrV?m8pt%IAOU?}@hio^1ZkD#*IA;QcSt5>a?dbi4KP_dgDw zo+)4d_}Z&eXWKtb@2=lll>N0gb@S`1%k^i^nI|6=bGF!SZ&H^_T-v`+XXigzyFxAO z|F6^2Q`wc)TKvpk`>*V2q59`X@%s~h?fLU6Keu&NxP4^g-;<^?)|SLq}#D@vT^?Dms7*FW?J1CzjVc3g$GXMFFF=-(Utrtm}C*7iJg z>g;2s&*JwlSo-cd_3hZEwHK;q{yc4-|Lmvu|14LNiD5tPF4q@-?yt3H=Z+WY=YCDQ zrMZsl-?f$ZWfQh#|J+@+r|g8<>`Xm7rJLIiESr=Nu>>?2AiZmpYcDgq_N7_eD>vor;JX$yfJ-Y?SUJtd$Tqw z%*mENTDA5~_hZp%oxg6bzHzzo;PlO38LqarMz3O8{&elrAH^w03-g1Yh@0R0bp2^r zq|WnG)q5Od41PVdE8hISwlLk+Znf=!mpPtym4o&lySQ;q-J7NVf6Y8y`2XnH|9@vk z|9@`2diuXdMTv4f(i^SrN!fXE=WTtqMAKsXwnyHMq5JHwwZ^??IO_ZE*TJkk7w5Ri z9(ZXjUt4(m|Bv|+`90#Y%2vl2;-InCyB*v8ZL6Oz)_+^W^LX0tbC>n+ zm37_UdZa+guUu{UPs!pQ!(+NebJ{LTB=h6`>x{{Z%w7=|pd@5#!qU}|-IeweZ z$98U2n(bGeVgIW2gZA4STX*iv{>aU0vG->Coyy<)Sd6F1SWfd1ne9=Fy~OY zfwjWX*(=m8*xxv_TW4DTNk+5Ba{0!+jGC5C=gx;lWX#)l>Co!EUVSnlXDyN>m02gw z+nu|4Q{ZB;>(+&ZP$J!@aOF68m*wz;R6&KG`lom}8v(cCv$ z$G_dVIlCA&nIq@N{(jBNww==jYwM4` zJnEMdWb;1yL*~(fU9&A^_eMUgo8*1k&0hW7PrrIE>8D#d-#^{@RDD6j{Sx8GE49b$ z^KVVw^tPFuVLtmOn|0D&=XGB0aFMw;$NGuoiFpB^Hoe>G+P{7SchhRV&n|CNV!AR# ze&+NYH(vCj^!EboHODe{J~Ds5EbDL7JoN_|ak&L&6ZyjnKe#-KzUTY>#oy}a%{{6q z->0VCInnZm<>lT*Y=%}p8U2lJ%UwH_rLp6KQ26Sku05BVYF6Iw%bD~xTJ7Glv%7g2 zmp}ZHrk|%(w9BAD^VJqplQWsWe@;1bd8Yf*#rZ#f>Q&VSY_OZWd_&W8)9;ZghBrixQ|*!N*o2fX%v>1$bX*!X5+mZdu1 z#V!2z48{J>xMJ^gM_uW%_QaV@((LEdz5QLkTz(t(Rcg!baCJwA)df;>)mbLTUZ1w7 zooC4%%ZZb^-y2*A{kSvSqPObfzmihF-|{CaR_yt*a|8GDx$YHuFT|45KP)P((QV25 z^3v?L(Y2*t3!;LTyj%M>uJY3Eb4R-(mWS=KkF7Ad_H+w-TZP6}l{=Hntco6XRn24y ziVy2jSbLeh@Wk4Qmlq|>wdTlvyyc{Ti{Pq)Tb=)JduNH}Y>3s}m!dBhsFK(Ju!P_C zeXerUGv&a4d&(t@zuU!LuNJqn6Jx7B{b(s`d1bPA>$ghn ztuI323k)XC&i1a8v9OrNa%oj@)w3@>KU!WnuQPDUdwgk8r@=efr(0^~Ig70ieXvC% z>Dphjcd~D83GQC?&0cxp4s%CMi@UGy&tJFm^`V4T!Ag(iu5-TafBve@^*Cqk?BCtR z;d5H6E85Qb72n$)s2uMn%Dq-0C3eHSF#e_OQ!UK7J1@HO?R*hF`L6q#$A#zq#BxvT zdAQie_xToK%|fS5pPuEF89a&S;OX1gW}$n?DM>TFyFRB>)pKicv1@SPnU^Q-s=l|} z^k~QSms5Z4OMR0z`MbaNi*Zq3w7NGlIU{Z};@k=RC9bnNLb?~KIz}vr0#eSEc_;VZtk7ccJ zowKed>+j>^=jQ+Ruh+5sVaxOLHiPjm^(jaBV|%I$`08^(BO`_G#lQNj-v#X6RAsG4Dy>sy#zUdc1LvPm8FH0`@{rk7OyZiB7;qCnL zVaj)Rm1du|jJ18ITi2-mui56@rig!~3m>q*&--4#^Zd_HW{~IRo_@)5$-PhJQN%m|e>xR9y3$7LI za@=iyP5PhCmd+}5`|~kpGJh9u{`Rsk*yN{TG)U##^O>Sw_ALkX;>W{^wxt=_8sF?05>uvllbI;uqQ`TvZ)ez*O+mQ;j7$H;7ty?omJ{7ap?=Jc!UQv8`- zb$`xNy=t*nySsY&S61+NS)SkT9IM#|A9hq$+9W=X1eyI`-amZr@w;76W}@IASvlw4 zP39(0Gst?eb{2H!di)K_5c4}ym)cryQ#md z)qj6`8?4+4HoNn3mg-v2oRQ$xjq9sT4Gb1!fCg?sgVZR4o?IX=mCG#`J@D;Y!vm9J z5|8_yY~iZ9f0;Sxa0|$!>gkt%yUWeA`=m}-hT;sq;tO3dGgKEFKrGlOb(uW{Fu6HSMcX8zTQQA_os)~ z>8vihl)YmX)ZBXywj6qX#gKnP+vWCS#TU4W(kQeUgn(~)OtCx+f#6VCODk3 z!D(`JpsbHY?FHZ0{ww!nPmlCjK2PS=`Lda!W%W@uzW&DZPi)%~q}J5y@Xsl~2Z zp3o6mUcc}BzHA#r=9HC3u6P}rIwvd?oKy;;K%;Z6QWCSRett+ex3`*IUe3DW{eveb zH#WcQURk1i*RbNlyT*?;%Wqj&&dixPWjB9cs%G5T%EH}iwa;rw%12y2p9m@=kL^A5 zQf865vHF^=8on=9mrE9@-+r7dYLWYS{+8)Xo=vkUlSsDc1*uH7 zxO;QXGl@eI$#;U7lR-wos}V?8ftGN9W-q|Gstre?|6^;^V|Yy0w7#DQYtUr0#(UR1!q7 zfZEM&pxIi`T(Tm_6HXk87Q7$}pwvN7Whv+cnt1L7PyJeesl$+oU@%o61)dOwP)(P? z)5D-eDqyF9r-tW%trmb#4@|%g#&F1_U7ycc=kI>IO_xKl<(21L-ST&LIF~>C(&qH* zu>8Lh$N!zql}PSc9WmF~JAk+6VaepB>v;3;?_*BxDJ)%WtUjmhvb2imv4_g-hR1j# z=UP5A0hb@3XhJYRF~z(5`iYm`*R#1de|!4I>Fuwj!Mq#ZO$le5bI#T{Ja|`G-IiSY zoWswjPtrR#_uaGNQzu%px9*fYw^rit%X3e+oW9v+c-Qsy%ZohGe7i()rt9&z`~CIX z#!?~oHbidugO}R7@|@p!teo;r=8|loQON8_hk2^J&ShuiHD}7W-0!eJWWh&-EFay$#t_mo9<<=)0`9cWW99E4Q@a6 z^s?e>ejSrGsvpaAU1qXeYf_@~MwN(-E1Rapapss*h$EN&x|u>7Mm&cY+~T?uw&omeloB( z4?pp;$y*8J(%Zi;cQuHWO1_+<;`_K}{?mtVR1dy<@_$XwxrEa$0<%<>-psYEeE49? z%)A-9&bGbGN>sjTId|Us^cocxv4e`szn*sTTYg4(!+DQ4>%3gqk1&NBq}|Z@#(U%0 zvvsMm#@ttzhz7qSE1Z)e$(afXGdmP-%btx&f6+)aIB!pc%Jg*kg^-$yvEqA2 z$IgV^$1mNe{cuC-p0<3NS@+8yS$hNherxDH?-l;ur@Jh6#gA+|U-5KXT|E&Vi?^Z; zy^Eg9dT;9fP&BRn*`5a_m%1X~&Gu%@4^Pan^`A2{Sk@ym_on2%^6h`GgsWdn%{%bb z%|bR-tlOh1?9R*1r(15z6z2ClEO~DGes1Hf1gk?=6;zp*D*V`GseA1ucc{hPmftV3 zpOi>2mxrx0Iu$$f^2Dt>I#+ie-4a*NeJsU1&Cnmq{Sl$Awb0N`M+D5O=1^XV?eZx9o4!cFK;hc91-lwWA*jIOV@AvE# z)hG9Jzdf+s=G|S1<+(qr=7<$mY^`1CTKIm~oO9xrXZe@q>PiaqS5LQ9o_0-no(p#| zThB?SFOh5Z8Tw6MyZm$X>B6$Erkkp*vULS_g>zRME$@D3*q+Q&elWA=VM%#SeN@r= zgO?<>+(_<-{3H{}T$ulP$qlE!U%xc_y{P{Cefir%7w@hspKoe?v3(BTeC5j?8*aN6 zzMrGv{b<{E&Pes!;+uACUu&@X$h~0wzUt!^u|@S(LTk>=lkJY}Uco2MW7%H2<3yj0 zyV&Cr!+^66e}TQEmOL-s;mUs!tZDC@$}w|Glp$>fEF~O&hm2Dm!1}-{BcqW_AAxSDt0N;m;Sk zS^s&9-uqkUuf92T`cq3IQ2GCE$^PO?OV&I6ygxtg_Vn522Xb$y_JCR{E1tZcIJKs= z{BC`}kAC-Ure52R-%l7EE0FU0{CzK|b8$G+;%?2#cOu6aw+jema;orZhc^XE%xf(z#>ou! zEx!EO#L%}eP1$Be*Zr?)er$8xUOxa&E+^lzuX%Lk%a(5&*}s*5TVZqVoe<98a${U- z6rf(Is>K_xvN=cnG~4P*`AhkVL0V_-3I)vHwPk|20N*)2wXWN{@+TRW7nO;Nl}K7% z=iPhPcMgw5ui2c-v(E9$%&tqRu%FX*SyVje<;|=_#rn0H6X);$qq@{`YvhxgI`=Hk z&wJ}DHurzdGL$;J6b2IiZo7`=*{vP1IIqSmF0 zcJ2*a&GYlfPva@&p**YKti80mdyz!poT)q(o3!Ug22P!kUCEM`xvQC}L>ak_6-=a@na?J01 zPH`|kz4}3k^puO7=c>-msY_O`oNMgVvtg3T(e-PmT>cpLw{&y;r&9LE2B*3Gu6y}k zN~-dDrqgHj{?|dC`#Z}f?b%`S`l0jrtR<%HVWF0>+eD^r7d!Loj$gJ!UxA_K`uI0; zzt2@|-q+TA)Ar0N*)tC%Hbv#UxZ6O=$!fQ&C*->Sgigf zu4gC_K08rLZBAaX-|fvi4zJuWY0|P+MOOPhW!o)(?Q%3W!2R((ez#q6)fQ_M!UWX9 zWBj|@yexDJ6hEDNHEH5@tsSpc9D8Z?y;S*q=$<8eG_o2lPdvGz$Us~+jaT-}!~>28 z0|e*jJ^r$;`LU?Q+JEz9tSm~DlD|E-x`w^%A$ z?JV4>`zjW-2eE3KYu^xZ8>a{240 zV%Pau=a})g?G!Gy<(VlSyVYf$aP+5GYk z6{i?Ag`0H?Q1y!}e?HnCz~7WZ5> zOSyO9;2Zh0ul&y*EUdqK#r#d*jpCF$^V=@7&ataBD(~|-`BLS0%C_*wHol%W-!zyV zEC};wOO7^RH=FZr+WS<&720#APcltNT(IZqtqpBvh3l@{NXnd9@z?V1$_=17THS|& z^{3XpaD2xbWs@7>+at@b8~a~S4biIcdl>?ctN-ys3o3N z?Dzf+<3VuAEPL`LGdtgxuU`*lf>va%cw6%S?{`Em2UK;eP@aCpR!P*d;WDU^9`Kw~ z0%V92q#X~XK<#)?>mEcawg}8|11W_zsf#ogF{XOiwy^B)rIl*?8nf2~h;Hsu^eer$ z-dxsy&qj}TTTA`UM6Rv6*>Kr+ep*Yw_Cr_a6kaI{G-G|RXz%==XVTZj@3%8FWL$3D zcbU_QM@vX6O(s*kVaiwM&6mzD@Y2z7@j6<(zI3K`_Y%`^E&k<#POsxwR=<`1^MHNv z;>Em$v%Z!bFS<1;vgydWBv#jyu*2e$jcaF$#Ydc&wy*5u%qg2(j9ylzo}Aa(+O(rM zcEV0cA&>LZrp(f1tT-zjH1A@`dCeDs*RQ?y>-c_a%Bc(g=2)NQ_2qF|5pKDbW39#C zBf|bGa=+%6-3rhItvv0o|MU3GQm^ozo8Ow>uL;&&eE92@$i?Q|w-4-4ol_QeS;)e0 zLF?+bGTm&^NvWCHcBL;btqDG|=+qJkzn{HbJIZB37cDkhaaUlu?2B7=FZyP^o4U5= zt9QNAktwl8bHq|z>%G+4Qq7$TZbh=B>x-7eSHCs=x?Zt-$Gmf8D@*z>YZV{MU#egG z(mSy`{?8-v|KUCbyVhFDUO2I{a?X?KU%bk1S$*QNRoT^j-$S$=nVnqls=qmwRkok^>dEwZ{DEvLdC zc(!U+?W2279gMq=DFh#w%;UpUp8c#OXJc$c+S}JJO^bG!dse33P0-K5=lcXsnFe`~@byy&<7JMI?|yXq}Nj0|0`Yj7-#d$Ogn zPbXS9-5~6C`nfq1=Y&1anmU8gTI%~bu4}blbev14`Y}E3{Tnxp@1fiN&rh2Cr|>?y zx9!rW=O?->ba#n;IKx{aZsQiKx_x_0uZ_Fd^AeK-a(*5E=iFU0$KCSm#Lmngv*S4y z<~=R>QXOgZW$iZKHMectmnr=H`@Vj^#=EsfE9$S71zU0UME@=K>sY&Oc10DB;uTM( zV{89cr&RrATMNpU2Q&ZWX+S#sATGSe56+L!>;$F2W8|RzKeUJdts-?Q*tHrw8lZ?o zf+fI>|*DL&w?brvJer(wA=jy!GkmqH0>*!`54$%Zh5f9SfZ zK2yH9K5EJq%hcFy=hIGKnVWXPc=jb%*^|~;Wy^o}TQ4q%yUA&EGHI#q>NUl8C)>W? zdppDFVAj7m|6k2n_2nez+@xvqg)94hR?eRA;?ABkkM`M_#}}8+Qu?*^MN_V>uSNPj z^Ql)eT|}7O)G!4U*=eNF4{ku z>uGf5tg}mvpZ<>)o4fbL6Yt_32EL!#R$trjO66!Av&5t5Cr2%Fe@#uF`kTutDXMGj z@~`Jk@XUO7g6q#Y^HZ7OlP-%bG&<^VB`2lw)19>A?~47^TpzVeUi!wgu_3oFt+6g} z<(odm)$exg_ulq$Lo~m>Oi0}R%gXbAi3Z3zfkv3Dx-Z{Ly0$lc?gq6!t=&INOg=4o z5oUS$w87hO-AQ{UvA%w3;=W`38s&*<&6=Fm8bL0~aZ|rOx(8Z)*`qco>)g-vLO!u` zCRl$KnW*x~YVn*IC+UyRZCE_2=^^C&ewT>OV0t|JIZZcY6*!e6YB= zsBL!nwyt@XgC_K)1$+h-=dxSpeQUaR&S`_pGO5ur8^I}U5 z->$oJyKzzY?7RCawsj;V@>up%pWgLnPN`+=wTX|snXNfPAKznKe){pfbH5+ON&fu6 zpT7T)#@_N}KYl6R+_>jWT*=S;eRE}&UwULM`t-W4pK#jlFGAXTMRJ}cw`Ki%XyUZu zutn|m^4Xznhf_6dda7@)*je}1&OJ<9wYBb5cID1T#VOl7KCK9{^_yOLq+ZI8PqT8# zNy+NH&rd`hds*;JyXR7U`nzxP>$-!C#eVeL#Yu2G@93R+T>MV@cdkP!n{qbq=Ve$f z=p=jSCEL|5ea){6YW$3Ue@&5NYq`v!Xc1d5E9X!C!UaO$NrceQqHphCxytU|apldz z)!^i%7vsP9>;sdmeW2EW-(ssd_d3n|!Fe}Oayh?@#f9tF+4Vssl;7c(+b)Bq#q#gh zN#xGE;wl8*5)-mwZS?j$$Jwi7t;-5zlv+T>fZ8MA28bY>L@K2qB^IQtGMxw-7Zu3z b|69*s)$nndAzKIo0|SGntDnm{r-UW|6@~lA literal 0 HcmV?d00001 diff --git a/doc/qtcreator/images/qtcreator-qt4-qtversions-add.png b/doc/qtcreator/images/qtcreator-qt4-qtversions-add.png deleted file mode 100644 index 6b292a697d194fa1fa0ae8d798e079bb468391a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42241 zcmeAS@N?(olHy`uVBq!ia0y~yVB%t6U~J)FVqjpn@o~O61H+ONo-U3d6}R5(EiH)& z-=$x1eb)YG|7V)MzPtU|-kIh3-}k(`zTJB6Y`;s6$8%0Ab?c_3g>}xHIdf)cQrfdg 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 uc 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 Zgjp4Z%ilB}+X!0T?&<31vd$@?2>>ibY0m%v diff --git a/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc b/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc index 51b50d93ef2..312d51bd393 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-configuring.qdoc @@ -74,9 +74,12 @@ Each kit consists of a set of values that define one environment, such as a \l{glossary-device}{device}, compiler, and Qt version. If you know you have - installed a Qt - version, but it is not listed in \uicontrol Tools > \uicontrol Options > - \uicontrol Kits > \uicontrol {Qt Versions}, you must add it. + installed a Qt version, but it is not listed in \uicontrol Tools > + \uicontrol Options > \uicontrol Kits > \uicontrol {Qt Versions}, select + \uicontrol {Link with Qt}. + + If the Qt version is still not listed under \uicontrol Auto-detected, select + \uicontrol {Add} to add it manually. For more information, see \l{Adding Qt Versions}. diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc index 58539f5534a..db9f985bd9c 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-qt-versions.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -42,12 +42,41 @@ \l{glossary-device}{device} manufacturers provide special Qt versions for developing applications for their devices. + \section1 Registering Installed Qt Versions + \QC automatically detects the Qt versions that are registered by your system or by installers. To view detailed information for each Qt version, select it in the list and select \uicontrol Details in the - \uicontrol {Qt version for} section. To add Qt versions, select - \uicontrol Tools > \uicontrol Options > \uicontrol Kits > - \uicontrol {Qt Versions}. + \uicontrol {Qt version for} section. + + \image qtcreator-qt-versions.png "Qt Versions tab in Kit options" + + To remove invalid Qt versions, select \uicontrol {Clean Up}. + + You can link to a Qt that you installed using the Qt Maintenance Tool to + automatically register the installed Qt versions. The mechanism does not + handle Qt versions installed by the system using some other package manager, + such as your Linux distribution, brew on \macos, or Chocolatey on Windows, + nor a self-built Qt. + + To link to a Qt installation: + + \list 1 + \li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits > + \uicontrol {Qt Versions} > \uicontrol {Link with Qt}. + \image qtcreator-link-with-qt.png "Choose Qt Installation dialog" + \li In the \uicontrol {Qt installation path} field, enter the path to + the directory where you installed Qt. + \li Select \uicontrol {Link with Qt} to automatically register Qt + versions and kits in the Qt installation directory. + \li Select \uicontrol {Restart Now} to restart \QC. + \endlist + + To remove the automatically detected Qt versions from the list, select + \uicontrol {Link with Qt} > \uicontrol {Remove Link}. + + If a Qt version is still not listed under \uicontrol Auto-detected, select + \uicontrol {Add} to add it manually. You specify the Qt version to use for each \l{glossary-buildandrun-kit} {kit} for building and running your projects @@ -67,8 +96,6 @@ \li Select the Qt version to view and edit it. - \image qtcreator-qt4-qtversions-add.png - \li In the \uicontrol{Version name} field, edit the name that \QC suggests for the Qt version. @@ -80,7 +107,10 @@ \endlist - \section1 Documentation + To remove a Qt version that you added manually, select it in the + \uicontrol Manual list and then select \uicontrol Remove. + + \section1 Registering Documentation By default, \QC registers only the latest available version of the documentation for each installed Qt module. @@ -109,13 +139,15 @@ If your build of Qt is incomplete but you still want to use QMake as build system, you need to ensure the following minimum requirements to be able to use that setup with \QC. \list 1 - \li qmake is an executable that understands the -query command line argument. - \li The bin and include directories have to exist. \QC fetches these directories by running \c{qmake -query}. - \li The mkspecs directory should be complete enough to parse .pro files. + \li qmake is an executable that understands the \c -query command line + argument. + \li The \c bin and \c include directories have to exist. \QC fetches + these directories by running \c{qmake -query}. + \li The \c mkspecs directory should be complete enough to parse .pro + files. \endlist - If your Qt version has no libQtCore.so, \QC is unable to detect the ABI. + If your Qt version has no \c libQtCore.so, \QC is unable to detect the ABI. */ - From bd03041428baa82e163e3a523cb3439e2086f0be Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 27 Feb 2020 13:15:30 +0100 Subject: [PATCH 03/96] QtSupport: Prevent misleading message about ABI mismatch MSVC 2015/17/19 are ABI compatible, but BaseQtVersion::validateKit() would emit a warning when using e.g. a Qt MSVC 2017 build with an MSVC 2019 toolchain. Change-Id: I50ba026ae7b55e052b26826076ef962f369a05a1 Reviewed-by: Oliver Wolff --- src/plugins/projectexplorer/abi.cpp | 6 ++++++ src/plugins/projectexplorer/abi.h | 1 + src/plugins/qtsupport/baseqtversion.cpp | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp index afaeb126e19..0cb6ca7fb80 100644 --- a/src/plugins/projectexplorer/abi.cpp +++ b/src/plugins/projectexplorer/abi.cpp @@ -666,6 +666,12 @@ bool Abi::isCompatibleWith(const Abi &other) const return isCompat; } +bool Abi::isFullyCompatibleWith(const Abi &other) const +{ + return *this == other || (wordWidth() == other.wordWidth() + && compatibleMSVCFlavors(osFlavor(), other.osFlavor())); +} + bool Abi::isValid() const { return m_architecture != UnknownArchitecture diff --git a/src/plugins/projectexplorer/abi.h b/src/plugins/projectexplorer/abi.h index 517046ec3bc..3da9334e2e2 100644 --- a/src/plugins/projectexplorer/abi.h +++ b/src/plugins/projectexplorer/abi.h @@ -134,6 +134,7 @@ public: bool operator != (const Abi &other) const; bool operator == (const Abi &other) const; bool isCompatibleWith(const Abi &other) const; + bool isFullyCompatibleWith(const Abi &other) const; bool isValid() const; bool isNull() const; diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index c9cb928a1ac..7c1a3c241d4 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -523,7 +523,7 @@ Tasks BaseQtVersion::validateKit(const Kit *k) qtAbiString.append(qtAbi.toString()); if (!fullMatch) - fullMatch = (targetAbi == qtAbi); + fullMatch = targetAbi.isFullyCompatibleWith(qtAbi); if (!fuzzyMatch) fuzzyMatch = targetAbi.isCompatibleWith(qtAbi); } From 956fd44c3e43ce2e86ebe7a9ae5b37419e96cde4 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 27 Feb 2020 13:45:24 +0100 Subject: [PATCH 04/96] TextEditor: Improve splitting top/bottom If the text cursor is visible, but in the bottom area of the editor, it would be no longer visible after splitting. That makes the probable "area of interest" vanish from sight. Check that condition (visible before, but would not be visible afterwards), and if that is the case center the text cursor in both resulting editors. Change-Id: I8c8dccd2d9db439c82d0aca34b8ef99fa97aa48e Reviewed-by: David Schulz --- .../coreplugin/editormanager/editorview.cpp | 9 +++++++++ src/plugins/texteditor/texteditor.cpp | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp index 9d2fe45ba70..67bbf228322 100644 --- a/src/plugins/coreplugin/editormanager/editorview.cpp +++ b/src/plugins/coreplugin/editormanager/editorview.cpp @@ -746,6 +746,7 @@ void SplitterOrView::split(Qt::Orientation orientation, bool activateView) editorView->setCloseSplitEnabled(true); // might have been disabled for root view m_view = nullptr; IEditor *e = editorView->currentEditor(); + const QByteArray state = e ? e->saveState() : QByteArray(); SplitterOrView *view = nullptr; SplitterOrView *otherView = nullptr; @@ -766,6 +767,14 @@ void SplitterOrView::split(Qt::Orientation orientation, bool activateView) otherView->view()->setCloseSplitIcon(Utils::Icons::CLOSE_SPLIT_BOTTOM.icon()); } + if (orientation == Qt::Vertical) { + // give the editor(s) the chance to adapt to the new layout, given the old state + if (duplicate) + duplicate->restoreState(state); + if (e) + e->restoreState(state); + } + if (activateView) EditorManagerPrivate::activateView(otherView->view()); emit splitStateChanged(); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 8dd3ff712c8..8feac6cbdac 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -2930,7 +2930,7 @@ QByteArray TextEditorWidget::saveState() const { QByteArray state; QDataStream stream(&state, QIODevice::WriteOnly); - stream << 1; // version number + stream << 2; // version number stream << verticalScrollBar()->value(); stream << horizontalScrollBar()->value(); int line, column; @@ -2950,6 +2950,9 @@ QByteArray TextEditorWidget::saveState() const } stream << foldedBlocks; + stream << firstVisibleBlockNumber(); + stream << lastVisibleBlockNumber(); + return state; } @@ -3000,6 +3003,19 @@ bool TextEditorWidget::restoreState(const QByteArray &state) gotoLine(lineVal, columnVal - 1); verticalScrollBar()->setValue(vval); horizontalScrollBar()->setValue(hval); + + if (version >= 2) { + int firstBlock, lastBlock; + stream >> firstBlock; + stream >> lastBlock; + // If current line was visible in the old state, make sure it is visible in the new state. + // This can happen if the height of the editor changed in the meantime + if (firstBlock <= lineVal && lineVal <= lastBlock + && (lineVal < firstVisibleBlockNumber() || lastVisibleBlockNumber() <= lineVal)) { + centerCursor(); + } + } + d->saveCurrentCursorPositionForNavigation(); return true; } From a670e203b1a78570ef969f893b470c68bed890a2 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Thu, 27 Feb 2020 16:15:44 +0100 Subject: [PATCH 05/96] Ensure that null dereference in test is not optimized away Change-Id: Icf8eb894a8277353448f46b18d5d6614be1d2350 Reviewed-by: hjk --- tests/manual/debugger/simple/simple_test_app.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index cda17dc97de..20734abede3 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -2356,7 +2356,8 @@ namespace final { // Continue. return; // Comment out. - *(int *)0 = a + b; + volatile int *ip = 0; + *(int *)ip = a + b; } void testEndlessRecursion(int i = 0) From 488bd7eddbe83f00b4f61be4ddbaadd08bb52d16 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 27 Feb 2020 14:46:16 +0100 Subject: [PATCH 06/96] CMake: Check parseGuard.guardsProject() ... before overwriting the current guard, retaining the state of the current guard in the error case. Change-Id: I45ec43d48a9a13b9b59a5bbe6415a457b974b654 Reviewed-by: Tobias Hunger Reviewed-by: Alessandro Portale --- .../cmakeprojectmanager/cmakebuildsystem.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 493939dd89a..fa8396e92d8 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -204,7 +204,7 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc) }); connect(project(), &Project::projectFileIsDirty, this, [this]() { - if (m_buildConfiguration->isActive()) { + if (m_buildConfiguration->isActive() && !isParsing()) { const auto cmake = CMakeKitAspect::cmakeTool(m_buildConfiguration->target()->kit()); if (cmake && cmake->isAutoRun()) { qCDebug(cmakeBuildSystemLog) << "Requesting parse due to dirty project file"; @@ -235,9 +235,20 @@ CMakeBuildSystem::~CMakeBuildSystem() void CMakeBuildSystem::triggerParsing() { qCDebug(cmakeBuildSystemLog) << "Parsing has been triggered"; - m_currentGuard = guardParsingRun(); - QTC_ASSERT(m_currentGuard.guardsProject(), return ); + auto guard = guardParsingRun(); + + if (!guard.guardsProject()) { + // This can legitimately trigger if e.g. Build->Run CMake + // is selected while this here is already running. + + // FIXME: Instead of aborting the second run here we could try to + // cancel the first one in the Build->Run CMake handler and then + // continue to here normally. This here could then be an Assert. + return; + } + + m_currentGuard = std::move(guard); if (m_allFiles.isEmpty()) m_buildDirManager.requestFilesystemScan(); From 9455b144b2e65cae9205731992c488687fd2b369 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 27 Feb 2020 22:41:19 +0200 Subject: [PATCH 07/96] VcsBaseEditor: Remove unused functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ida1df50aee0c146d8070e62292163d34cd53f65a Reviewed-by: hjk Reviewed-by: André Hartmann --- src/plugins/vcsbase/vcsbaseeditor.cpp | 16 ++-------------- src/plugins/vcsbase/vcsbaseeditor.h | 5 ----- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index aac8696c0e0..98165ec70d0 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -358,7 +358,7 @@ QAction *ChangeTextCursorHandler::createAnnotateAction(const QString &change, bo QAction *ChangeTextCursorHandler::createCopyRevisionAction(const QString &change) const { - auto a = new QAction(editorWidget()->copyRevisionTextFormat().arg(change), nullptr); + auto a = new QAction(tr("Copy \"%1\"").arg(change), nullptr); a->setData(change); connect(a, &QAction::triggered, this, &ChangeTextCursorHandler::slotCopyRevision); return a; @@ -564,7 +564,6 @@ public: int m_firstLineNumber = -1; QString m_annotateRevisionTextFormat; QString m_annotatePreviousRevisionTextFormat; - QString m_copyRevisionTextFormat; VcsBaseEditorConfig *m_config = nullptr; QList m_textCursorHandlers; QPointer m_command; @@ -579,8 +578,7 @@ private: VcsBaseEditorWidgetPrivate::VcsBaseEditorWidgetPrivate(VcsBaseEditorWidget *editorWidget) : q(editorWidget), - m_annotateRevisionTextFormat(VcsBaseEditorWidget::tr("Annotate \"%1\"")), - m_copyRevisionTextFormat(VcsBaseEditorWidget::tr("Copy \"%1\"")) + m_annotateRevisionTextFormat(VcsBaseEditorWidget::tr("Annotate \"%1\"")) { m_textCursorHandlers.append(new ChangeTextCursorHandler(editorWidget)); m_textCursorHandlers.append(new UrlTextCursorHandler(editorWidget)); @@ -819,16 +817,6 @@ void VcsBaseEditorWidget::setAnnotatePreviousRevisionTextFormat(const QString &f d->m_annotatePreviousRevisionTextFormat = f; } -QString VcsBaseEditorWidget::copyRevisionTextFormat() const -{ - return d->m_copyRevisionTextFormat; -} - -void VcsBaseEditorWidget::setCopyRevisionTextFormat(const QString &f) -{ - d->m_copyRevisionTextFormat = f; -} - bool VcsBaseEditorWidget::isFileLogAnnotateEnabled() const { return d->m_fileLogAnnotateEnabled; diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index 6e32037b680..5340a3d4b26 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -135,7 +135,6 @@ class VCSBASE_EXPORT VcsBaseEditorWidget : public TextEditor::TextEditorWidget Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory) Q_PROPERTY(QTextCodec *codec READ codec WRITE setCodec) Q_PROPERTY(QString annotateRevisionTextFormat READ annotateRevisionTextFormat WRITE setAnnotateRevisionTextFormat) - Q_PROPERTY(QString copyRevisionTextFormat READ copyRevisionTextFormat WRITE setCopyRevisionTextFormat) Q_PROPERTY(bool isFileLogAnnotateEnabled READ isFileLogAnnotateEnabled WRITE setFileLogAnnotateEnabled) Q_OBJECT @@ -188,10 +187,6 @@ public: QString annotatePreviousRevisionTextFormat() const; void setAnnotatePreviousRevisionTextFormat(const QString &); - // Format for "Copy" revision menu entries. Should contain '%1" placeholder - QString copyRevisionTextFormat() const; - void setCopyRevisionTextFormat(const QString &); - // Enable "Annotate" context menu in file log view // (set to true if the source is a single file and the VCS implements it) bool isFileLogAnnotateEnabled() const; From d9ca238ffeede9c9af780cc86615057ed3b079c5 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 27 Feb 2020 22:41:42 +0200 Subject: [PATCH 08/96] VcsBaseEditor: Remove default actions when right-clicking a reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2e8abd4487756be2535934ca8ab4d6b9105e6088 Reviewed-by: hjk Reviewed-by: André Hartmann --- src/plugins/vcsbase/vcsbaseeditor.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 98165ec70d0..5338580354c 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -964,13 +964,17 @@ void VcsBaseEditorWidget::slotCursorPositionChanged() void VcsBaseEditorWidget::contextMenuEvent(QContextMenuEvent *e) { - QPointer menu = createStandardContextMenu(); + QPointer menu; // 'click on change-interaction' if (supportChangeLinks()) { const QTextCursor cursor = cursorForPosition(e->pos()); - if (Internal::AbstractTextCursorHandler *handler = d->findTextCursorHandler(cursor)) + if (Internal::AbstractTextCursorHandler *handler = d->findTextCursorHandler(cursor)) { + menu = new QMenu; handler->fillContextMenu(menu, d->m_parameters->type); + } } + if (!menu) + menu = createStandardContextMenu(); switch (d->m_parameters->type) { case LogOutput: // log might have diff case DiffOutput: { From ae98f91f1bece4c51c592a9a4a9806abad672e0b Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 27 Feb 2020 15:44:51 +0100 Subject: [PATCH 09/96] Doc: Update info about finding with the locator - Describe the new bug filter - Describe the new URL template custom filter type - Update screenshots Change-Id: I830b3953e89e97a7e5a405687915b67153412d9a Reviewed-by: Eike Ziller --- .../images/qtcreator-add-online-doc.png | Bin 36820 -> 11916 bytes .../images/qtcreator-locator-customize.png | Bin 54490 -> 6396 bytes .../images/qtcreator-locator-example.png | Bin 0 -> 26022 bytes ...eator-locator-generic-directory-filter.png | Bin 0 -> 9531 bytes .../images/qtcreator-locator-open.png | Bin 30144 -> 11910 bytes .../images/qtcreator-locator-url-template.png | Bin 0 -> 7598 bytes doc/qtcreator/images/qtcreator-locator.png | Bin 49928 -> 15649 bytes .../qtcreator-navigate-customfilter.png | Bin 18754 -> 0 bytes .../images/qtcreator-navigate-popup.png | Bin 78369 -> 0 bytes .../src/editors/creator-locator.qdoc | 60 +++++++++--------- 10 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 doc/qtcreator/images/qtcreator-locator-example.png create mode 100644 doc/qtcreator/images/qtcreator-locator-generic-directory-filter.png create mode 100644 doc/qtcreator/images/qtcreator-locator-url-template.png delete mode 100644 doc/qtcreator/images/qtcreator-navigate-customfilter.png delete mode 100644 doc/qtcreator/images/qtcreator-navigate-popup.png diff --git a/doc/qtcreator/images/qtcreator-add-online-doc.png b/doc/qtcreator/images/qtcreator-add-online-doc.png index 4081f15fb8fb4bf4cf71d1c5f178df46712adb0a..761b3c74f8749a49a740699382836a19e84508e6 100644 GIT binary patch literal 11916 zcmeAS@N?(olHy`uVBq!ia0y~yV2WX2VEDJe;AlY1tGoDCAT+{o$2 zwsf1B=Ai}MJS`oo6csr=bxxkqxXINh@W>(0?dHmxcW0h`r>41W*|xI!Q}gPqYwzvK zzdwE7q&)lizoy*%Uh@5Av0wbx;`1-xecqe(_ExF)i>s@{*RS>6F1zFY<;L4zo}8^c z{`kv>=Iv{8mh&sz_& zeHTbGt=)U@&MGsl*sV?rR|M)j3u+Ml+T1GNZE;ZSU8P;%l>WDyZ`;!p&s=6K3^ zwEk!Pe%o*7+^g%Y<~&OO_p|brh+@kHp;xO`ud908YyPHWqDEM1)1$0-&D(!J|Nr|w zv~vc}(Qx@4TG#rx_y2pmUjNO9|KGz|xl2!<_CC4Gjn!4y`k3n}$DOI`LjJ8*o{~vj<$k=e{@)w$^yVvje{pHy8y#4RzZk)g8|26-A-=qJ({5!ud zrZOPl!{+Y!^Zy>c|Np`F>Hix`cZ}OsKf*U+tPRP4V$NK4kg+uJ)*TaCOc( z@5g)Aul?qgD#Uj;qj>9zI1a@tF?wk#NxT6ypXUBAIQx0_zMuZT^IegEh6^8S6F)3^Ws^5C6${}!39d#3vgmprYiJufNOcdL8Jlw&!2b~Y$E zWjrl3v=+>6e)Ltp?B9>_{5OBDJ=m(BBR9+X-{bH1D<0hSKl4A)QNZx?_H9~J_;cM; zwVRV14DD8YJ{HFuux8=vi2JrjuT1k_FCO5+p_{K{Wgpi5=Ey_ib2|{73hp)#@H=w(BprAG$`$UiOyPJZn+2D(2tgOPS5Rr`m3| z`v;#2i>)$V*+1>tt(cR#@q6Q5UUlSHsH&Fa8*}E@r+r+m52fQ@?RwW5&7<^B++5Ju z$xv$PX1V(wGIpU63HvI<)vXeP|GGU3eb#JtO5+hT|BkZh{Leewecnh}wrgBIJ#MU$1)Nq~%{p}Yx6kKkXXf0wmwaaFmOYdE1)RQeYb@(L zt|92ep>fG}P3|)jB62jNYm0yrhXxafatL%P)OF%e49S3s5>q4~DRpglwBMOS@rsJ2 z{^sm!YhJ#1v18ZWtyx!BnKeH0HP3%5v#b2}yx)e$B(6U^x3Kz1>lIE{N0*8Bu3j~@ zu-LJ^c5C(bcVAy$=l-^xS;U(C{msH?{bLf3cj@jD^V8t+<51$`<;}glEjRo3s@=Pz z7X*G0pUr#p;!3a7tdO53)`46>%0D@smUc#_o_1TXqx8kUbk`fXe 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 literal 36820 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 AI{*Lx diff --git a/doc/qtcreator/images/qtcreator-locator-customize.png b/doc/qtcreator/images/qtcreator-locator-customize.png index 6b7aacf7d304b3991202f146cf20f0fad94f2025..707712e41a37be24d10d02531dd07bbd624fd6c0 100644 GIT binary patch literal 6396 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 OFnGH9xvXi2uU-)mCgn83g>iNW#x=@njaS)R7G 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≪&b2Ao;7zswr_F)Rw zbW@rG3T7EYjV0BAZ%s>BKavu*@GjH)_AFFpVySFappYXEw_HL0K z0)jIX|8^#@eNgz#$aI0hW7_=q3Dc+Z*C(=R|4Xh3|5*CS;IoM$&osMO_PUPs0{0{T z91gzlvyqpZ zqEqJfr=Rlwe$VHh!^Gw=XYcP9^?$GTx1B1&RI;sM&U0{t;={VC;RTb zf%cN1;IMhI><2PWYWiOO^it!{Q|s6ZB|brhVn2RtzV9EJWysch&?TYm0MECw~Zx)`f_;&r+uIyR6 z^z43K_S)>4o_+7md?W46;z}2vPR#uOEw8-T@%F8s>C;~?-Yjk17}<;rq z_pS*sGiSWcFv$)4e$~A`BKv&9mrMQoD$>_!-jBMxojKF1`SV2E`h|8&tKUA*FtFY& zQ~T$hwfE!C|GH2AJeMOTus%5Q*P2y#`TxDF*cB3aq3-|1tDl}!JoxaiA~r0nG+yIL ze3UIu``(vDGXj>YeSQ=C@9c?>FOzb!m^{sEKD{U`*}XmDxYt^~7U%Bbe;?{h)-TF> zeUH6;UuOA>f`$9{ZK+PpUuDyHMvljBhSqe!l@e9E_6eVHS$cRMzunK2Ju$p&=1j&c zX&(Qj64*38I43<~bULtm#^lFLF@dX1Z{D>0U~X%B_u+{Xr%rkL`m)wAtzb?#efsq2 z6DKSb8_}<)-LNyhfd!8 z>i2E#lD4Vcty(Yj>nBgR_V%XKi_Dp`R(n2IU9DAq$WD9mq+6RF%+8;rGATnq-EE=i z8Ta3tU%I&8zxhqV{HJ-Q?7pWfzfF8_^#1ky>DO8;)Tjz{O8;Auq+N&ZtOVNBW&fAh61zbS!dH)br_ltatLrd zV4ux=i}6{l{%Wx`3=SD)v-1UJ91P)bjS<;bwL|^W zmz$HnZ*Ti-aiH91ap9G3t!FcqHZIYSx*z%afzS(4ZuftAw{PcP@>;fi?_1urk0(#% zG8WF$c)6JQ0yYJ1c5^Ru+VAhGde(U6fZpWf8bJy{I&gh(ZH|~4I@jKs6y6x}w zQPTXXHB&(ARsiD}F~4uew7qvN>)-#QcFVpUE6T4~N6dTl;^w~nH&3gob3S!)tV-3` zFl*@|ug|~toSy8X=(B8>91zCY_I!%EjIf5v1=*0d2b7zyn6KHQ)B&> zFtsqA7W=)=^R`&e4s%{?HEmID>GwAuKHaNZpm6<~%}%q>TrZ(z=YDO|lI?0dd-w9) z!-pql#7-3Cf4k^$0-N8yB8JUP7jylWH#j8CKmYx_zuECGHNL;Egrv4jnHlu* zyY3B^IcK*0yt?w1#EgwAc+#F;y6V1Lc-^ssbEh&g+G?&&zk7FX{+V_6EqB+KiOhSw zI`olXnZ=B=^6$Ui`ug(g>-lz{UWjyko7wx&$ky>qOjk_Yym#x)m%YwW-S_pWj;Zgo z`>$gqP8B?^|(ZQe>Lh>GF?9AG#RMKf7aYa1Y0s3IDbp z;CwNlF+^4LqeRZUkcDC!GGlh?Dc_zt zZBbi}jGN7!`G==#hA`=M>o&}E?5OZ#r*c+$r7{GuInb8Obyb=J~4U46QMa)POJQx#W?56%<7t+csQcwgN%1Y44-_Q zmdk{T+S67qagv+r_55Uyq@~_wzq2Xaic_Yt3;t$W8N*lo_(V@;q-3V1)!Z59-8?hz z&wq9N(J9_-TSRoHpFNcKaZY4U^n=%2cZxvaIJ+@2hT+&F>0`=9j~JMR%7qT~e{}V~ zJL!X|95d51@ftRRZvTd(onjB&BSilHifWR4lI&<{u_xlu*6V^7xc@bLp2%dvdnMwc z=7x<81}y8ly^e2)IA9wmB&Sg|Bd6weM5w=2L?VyaT(M{o?OQ)mXGz5^5nR8;d-3tL z@)5mkU)VP~?cI>b^DSw4=f)e?dlTy=GdZi9RX66&H=EizStnq{6@AZX$tMdYd~AOB z_V{fXZF4E_n{7giE%ce|IBXL8MDsm$);F+SE^@fT6It@&;xEMtHWT>+)s1%_U1UGN zQ*Ke?`>@_hd0R*00iKusjK&>ze>}9=-{2PiTR?yI&o}+?(du#EKHrp||M$0i{eS1=8=1$bLX7ro28RYn6BGwFo=JB<-!4uU%S+Wg*8f~ma>$6mhCPm z<~qgSedT6r>d{t7BgM92rzD?sA?t#)6yEn}_UUSM=pX9bv|&bFrC9vOPR=Q9CgFjF zfu5O(>zuPqW&}-9irrbAsv%nRARz3f|6-=Zf}?Ehp}J3!x35&+Z<)?!$2>8DNigMu zcmwZF$%+3m47#hC6eE~xYBx#i`_HaAe1IoeK=M%5`QQHwj4~7M)(U&izWc@e$&J&$ z!>_k>OP+kd#}ciP{!=Alag&iD3rB1Fk*qs~#}ECq=5P_3IHN@T5$AR@>*B8tYrU2o zkI2xpSg5t8;Q876mb=W&j%oeqN!c(tq1LFS?8vrOSIN8ozD_i<6Mk;L>@)A%JP!HJ zyti%Fr&*iS1Ti&+Uof+}6?b5P)~#vtb&9sHX5COMHrp%p@=S?5z9I$w24>yf`GU=} zj(A2}{QhwHw|isn+1{m%en<&}(b)Ti%ls#3N^JY49I(Dr3{gCv8q z&2-6Ui-Pj^9GDYn^X?;Cqh!Tj%Tr%Io;}`w__HeC$=g$=oaD`qEsM%Lf9aFMLt%r{ zW%BDpXUTrmo&2x2AVodmu|c5bou+TCFJ7L!Rk1Z9WA=x&SD)UD70orBsbv&@`GV<# zfS^rQYUR$a)2GX~{3`yzlzR9@l!Z*rO0RaW&#bnS10za49=w)d$F9t1K6PI~hW?%v zN_+lVPurM&@9uHhz_`S*N;vOY`A{(NQEtg~|?jobCi zM0?l2&0&3JtP>;@9b;v)UH0y5>6On8wkR0gn)f`U<)quXQ#W_N=w=f2UOLk$XjuUlQ~Uf_2!zI-;=AYzl!QLJM{#f^i0s47nj>xDkAjRg* zeBV)8=Ds_TBf78S4gFtJzB4K@YgY8v zT)qCjtIIqhI+lFgIZblrF_Wp=UHZ$IUtcW0$0_a|)PATjZ1%5hjgl7UAI4_o<^B8c zAznP&Xud2+Quve_+Z*6lujrNhm8W#7Ji?Y?}k>e9)t z_ql~v9c?&n9dyQ{t9j<>;zwtT!+tkOFI8Knu=?=(*cEwid*AslS@HGh+{vL!uU@W; z-+MaH^hM-L{gCu+a`JAscild0o!9OXV_p4Xe%`C%_U+48v*`HbPmw(=S%>7NzjZWYs(1XZ}F3yk-< z6>UDyNt@{^m?mhhX@mJO5(*o@_ zmR0Vk-c)WAn=PpEHu&IWc7DHfYpn{Nu(LhiUln{Wd7rY*aBlBI%Vd$B`B!bKYyLfW zq;n;9vXZvcH~(whALbbLG;wZTEx zQW1V&{8^&+gyHwKYqzAnDA<>*6`Z*dccY;(QyL+M&DH-o?C;|~wAf;?259YZ(Xg@{=zMMR`FOown;5SvoLYGNhuRFC zbJxZG9xxQCj;i>zn)lzPi8sD-o!`dwvb_A|W$oWr-|f}q+Ii8iaYf{(yDcmn$Cp1^ zX8(`dZf@J8WfT9g7&M31oVe3ev1qpZbpDgf2mW%rIQ_I}f99OMr&Qx{8Lx_yj+DedOxDU#|epk|wUv*eF;4C)P$ zkDsagGMhPm^gq$X+_K9tf$g4Y+m#zP%=d0Fi40CTU@0{7V^vT5FNuSPzi*LKR&km9 z;?0ylZ8MinJ-JY8=Y)k?Qr$UUJTy!;EG`H-lD%B@-HXMB>x{P_Sh47_dy?H(#-`gJ zvbzPu?v?l}TTFYo-CUG^<1^*I+0ki*Efe-H&}f(&d*b=0ikg@fp_MxScDtwubT(GW zF5A`+E9^UqU`2a*DB53?KO`Gm-DglDd+AqDtK3DX=Cc6 ze6-zwW6JYSE^jR2MYwC~yUtvD@b71d|MeB>Tg>i1TJ?gnYL`mDHdlp-t3#3!bN)3n z79KHb6?%S%eO8jyZ1uoZ3yLKz&g)Oso}&HH^~X)ac{+=dPi))0(@^2VtrL$tMZ8)Y zxb@{hQwxfycKnRn3p3sbonmnHxIkC?DdkIA;1WV&3wyZ_dT zlySVtp<`uf8>zqHbfHy3$>RGqt(k%Qj#&y??fQQ1@Z7D6t0y=f6_}xD;9SLgz(*;e z^U^ZEcklhTN0?Sc&k9{WVb&a0)6k{wP9*22uhX@^p1NIZyPuqle3@uQ(uq%-S&X$f zPrtOiD>2nM#H!g-QALP#*Q$9l*LL^+`*H8&lY(N;(9Z{geoQ`ZXM3~Ee7e;R5ih3j z%X@cN22U<(=g?Ena#HdPH`>PBY96`f(?PrQYyKasp1e(YtbeX4?~C;G zbhjm+x!eBiz9(fC9UEjGnUydxUp|zJ$#_Y9t^xD?SQ)LjmJqK4A~V~!ueY{kPzU#Z(y)^ zqU5q)ckezm5q!LMw@YMNWNe~eSmkS{CkK~LpS_k>HFD=s)8^Iv_v_1xGZ$!RPjz0b zYM8rv&p}x+k^Ze9IkBU_udY#K!RpZCjc=If?F;j4i zrD)W9um4Zq3%w}W*m3x1#0ev3P?xP)a)x!`iV8--kA@2?E1ti)IIny~`huNG%d^hx zw-5JL4|p}5@7b%aTX*-}6kC2OWY4S5PqH)u=0^N7y0mm*n5oIvwzD%0L*{0yH?BN* z=+UpIe-Ae*{hXbDH*gAnLhj?1C!v0^`?g;RoDhB4%=+TZ8*eT5-#W83vhB{~-qhZE zo4-%5;yzs!&fj!7_2|^s z*V4PE8{aPTv7FeYXaMqXTEooToc{$ImA<~a|L;|=wP$3rHT&kNQ&f`9{<)VE8+dzC z`8L(l8SC$USf9GOlSgg(*{9tuHDl3(&&YrN;Kl;XQT<9@{Cvx*-- zy=H6PH+AOBhfN_n1CpgmesBM~`l{jT!G>?3x8Jv|ojg=+; z@9N*XS$A3lDCHs^H| z4K)oVPX%vIC{_|-PTqV%Md`^ZRn^1h39JV{+}V00MTzxRzj4)(Yw8bmqs_!eeP+HsMom9Ipk>F`aT+oPk|oy1GDTOTab>W`1Sy8`mqG z82fn_K5??E5Up@}*exe)q4GF&S-#AS#^r)?u0l2w0v^$EzYebsICgU5 zqiedn&NJEUmtSOec)fF)q>Jvw7b`5(FHL7iD_pVTp^^Z{f=gd|nT=PN=x&&z!^-F1 zcla`MYmMHy^W6{q)xL@B%Gmg4{pN40#>px z32wiX6sPI1IHf`P$FXM(+-)8zLIs;#Z+PYiK78H1&qb%lFDdi&@$3HQ`@etV|K1!d z$(0u*^kz28m&gVYi!r`6Jp*ZP8K}Et{d$E*vxa}hY@5ZZB_%Z*$_r{lou1Qn^?0`TG3Za*Q-}k)wZ(qNcY{E5+58rC7C%- z$EY{^jK;c^nx?B*S&a6rSg>rJ#%-=-CR@8@#w$E!j-P5~pVt<%(qYk+6)9Si56_B? z2%MaHEis4l%i@mXN!?f3_J*CAJ|m~^(4k>?Hv z{MOW&6hwRoy*B66u3LLdcn?hSnK^4}WJpxpv{jQB3)iR|4UCy#EVx5l>Qp*2U(k$e zVdtyAn|Ez(6ImU(*mwp{mE!c16EnV4tqoaMx@2dU)~dNHtJGW)il)pwYASkEGKlYX z(7oN&Mc3wPi)RLHE`D31)VaDi9j?+cGaY3 z&6)dinO#Lfc2P=I_N++ea1LkiwBu3XgQJd^@ho~^0bETv@J+GoG9)})I4o13yCrc>2e^sI5? z(r-O2=I_-wr@Z7#uX|fju+;a!r0`xpmaxO=57%b3pNhD|sv>`Tw&4Elu4>o5S8m^K zv#|N|*;O)g4OiD4m5=!@UooxyidOFY^7QP|*AJAgOjy4(IJq*7C(G!zRrQ}258wUz zawR9&bJyn6pTED4U-Nt6wT;K0t@yyccW2ZtmG$Mxm5UBU?*0Cve8Zazxw(7`{KqEkr@la zmzwCy%f4T`PA0x~&&~NKmo%48%*>6n;rZ5G_jmX9cYA(L+h()r?b(pPr$?RlJ?*?T zaq4;b`D@v~^_A_-bn<+;BK^OKl;ystSL?FpeyRI7{r`(hugyEGYW~^vUNG8PE5iF` zp4;D_KVR1FJMFJu-h6TMgP7@FNm86HPCs`3)}F(4t2foY(Q(c})3orb)0b}6C}Bwh zji8(A7z-Gb9I#8?!^d=kW!g>NRq1WU4JqH}{csm$+9M~?I>TpbWcA(M{dPYe$N&3~ zc*OqV9pjhx>whe_|36=TZ?VPIxC6=)-xrz29$*NXUDVDnr`ts1ZH|WQ?QbO>ihr93=h`|o)FKFN-Ni2EPXe2>Q6mg zes!Z`5=ox7|NJ@k>)r49byjzSu07{GdnHq-@>=Em<>e)5=?ka+IhMbft*oZ`rwm(z zWZH_TA8*djkC&Cnt7bbJ`Lwb3DG#gbtoyrnS=_VPxWhQS%6#Iz$2T)`*L-(3`^0-? zw@>u8dn#8WmWA(~*|hyhB(q(-d+qIC&q6d`Zr?vG{9OL;=jmqUZl|A~eAM&wLDj^Y zn>Ktm*kf?%Lg170w zmxu0TX1=?%_wZ|OUZLpECl3~_J9bIXA|mJf)fK(l_VjFOJo@)<>h!3bQ)f0jnXdOv z-oKQ2>XFonO+tEeZY~Pf*m5nWX5#N3Nh`1Rsj6Qn_}oA1jAy*X?blup|DOH-?fpOb z{hnL4tbNxr?T%`qZ1==>eQl-(L^&Jhn@hw<>Yvn^JtO;(z>B5H3zsevQBtn{nz1%u z(Us+vIy)`@O0(bY_VrTp37KfQvo^fCd!|-&en$O@#Z?8zj00A9O2 zBlrJmZLU9E&70;^{P@w;&gCBYMz5aE*qEceB}Z7Tv)k>j_G4Y=;Cu7-Sc~|bFIuvA zui}Qsr!NNGUvwh)i`7!y`pVk72dkauSw8q$YEu4#Ihpn3{+~-%lvJs2vDy9T?U{*_ zLT+j|o-OJ=F=J+;?y4y3y))K%Hf|Jvlxn(co9DOhQ8Gw&ENEYlQSn(rC^91Ersaq5 z8>|yPE!D}ATz~eU@Ij3w){mylyEl)=)V|Z_FteLR$ik(Ug!jtFl>I*RaOcFXo~}mO z{M{bY_KR|{KATo%_p4%^q4w@=#=G`!-L^~m-b}NXJeMD??PV?a5L*%&d3Gst`||dC zPiIc-Gn#6Xs<&yc-TrOWWfw0_m^wK&AS-afi6ts!w=P{hE;} zoGEGj?@Lyg?5#7~Asy8{r}k4`!WM(oMRiM?-4jC2z58jUqoPy(xJcQ5O>X3;H*0>I zEf!yWc`H*-2fy>NRe#@J`1Pjf$>Q(sw^q5`J+N}A>WR7Y&dyz>^!wDoi_gA%Ik@+{ zva+R)73YC7*Y;J3&JEZ*cY=?iutZzldB2p)!nXgvI3_G9EKxLxshNIC_S5|D;?i1b z*UP^*OYaUpxY4Th+^(8$H^a*N_GT0mX9wt?jp&hKx%;mEZ+T6Jh3S9EsSkgQMXWX?g=$>qSq2kk? zQ`6q9d-ldeQ&r6OoY)5znS-TFrqh{Ci!9b;TiMN6)WVb5s=9sY>g_AlypJq3UaDC( zd!B1r)@82SQBtS8KJgeaPS!uQHjh#JRF;7HWQ|o@=3F~B@75(A2Y;cd>F3tIe35m2 zql9G2CZn@gZ(R)z&QR^(xqJGy@Y7c;O1;N~W*T)#-M)R>+A3Pw>v9g?>^R10-Pc~3 zc$0u8*RJ!>N(z3l zkwHM}_ydi+?3MbuXD(_?W!rpqfxv~GLB+G2k13wK{3$wGI@`PZ@)jYU^FPx#w@&N% zB4RhMh~eQ}pGLdI+g7ezx#>!#*@~W(8w`0LzsQ}*raAZARne>E+e}3=StMEydY@gp zj`do~)O(ZCo=osKbmh;sclTc9Fta{>rCYXl&hZDQbuwQD=|w)($aw#1oz4cs8Rk3v zBt*76)(D<+^CjDllG_J)Z+>FXE+S17_JIRmOE@*@gdo0qQjB>2iaVh7?V6tgxLI(Q~I7zJBLq2 zY!-ivVrRhhSzWu=KI(q(LZ@}v!rhwAry5r5kC-Q^$@yGZQAJSUW=|LUA7*2fmWRd+ z(^hQIzri?>>&y{>mHfXGFDJ@sOgVe#M2bdzulrtg=JlM6&sSGS&EnT&{3zzMfHUrm zoS5Oq6LnUTox4rtiZ~DaYq2pFlk4$Qet1T0`RaBGL%%e+H;XV?#x*a<=~04 zCvugh&R;BH9F`%a>Z|OU@GVQy;lmPbHoIT{3?4Ha=FTyC^h@~-=YgI1H@Vh3_`16s z_Q=;^=9o|$Fn{$2uQmyX2}%alM-$izdvqo;`Og>nIP;2n>8cIueb(0g6y4sx!)av@ z^U83mxo%2NjO#s`LUg(%*9aQ8R|q9s64^AbJ$=PL?jV!&Hjze2rp@xkvQCSW+BPkG zaq{rz&5JKo&G$TcXlHY#z%R%CwG1(G2l5>cGCa9q*q1O%Vf*?2zxC}bY%O-$+|4?F zRehgt!iEDg*;*n>xLW7T;88jBpkaw&vfQ>KEk{~XKKu#Hkm-z4ZT}t~oax7N~S+gIJjx|h7J!`^S`|X#+z;$gb7b-^pLXIo|0g_lY7b~ z|2dby<7uu5-&QS_JQ%N0uNr_f9%-`HGl$ zWQvSZ+yYkRfTN+_4`2B3{_fq)Vl;E%$rYMs9~!P)_2tnXnd(`a*X*y(sY={RQ`dPjx&dQ>uJ#>(z5k&PL&p5m!u1jO@*A zXDyw~%omk?>v`BT>(@mI&-i9$ua9|IvMpq0-1Up5wx*Y_heSmfzlfW={`3`x9A)r2 z8NnHMdzQTHS-1Fsg_ioRen$#It>v-PhyTgMoiyt37ckt-jv#z_%YV+#L>lT%t zDYm&hA>8&^^_K@Lob*qH$a zckS)Vzx%Jr^WRls6Y}KERCnV^9zM|*&pfqW_^<8Xi{0@u70axaZ~NY#79_#*>TK#m zCvaX~%VezHaC1h~0hUj3R-Toqm|wGe@XaqQ`~HzFoA;e< z>pS=2*NO>zeJ-t2e5R$FR!?gaU9#lNw$`UF+aAvR`_bs){l8`hZ*AHl`C(1YnrACH z)_j@Pd)2f3o`ukz+jnNXe4%O5akHeSHScdYciM!)d2t2?=AnL7voG$cv4~dOeOl|w zymdPjUVu`*@e+*RJwofJ_@%eTHUD`>;UODAjZ`y798=vK;9L(h!38#l5t zGI-?IM5N3(5*9r*+eoaO{hHd=_ zctWn;`H8b8=LgYpY&(|9p^?y7_dKXScy2S4?iwL__3*R0+H zJdKh;ENSLy3@tOGOt;k+{r~YI!P+1vaI@lEk9m<-9(c8<=$ueg_S`Bub!u8G$NDHH zMum{Vmrs5@tJta_7|`aIy0m2N+c=rG`#wKtzIt$0-^bR6Ma+&fj9zk1S^lZJtw#O( zx^w6He|_4rXUe0stNU$wcka}EyxI9_(!|uX=a2rq+&g9SG>zSgFxoFbV6LW+cC7D2hpXZff zC&QF{+GJVCW>2k@z;&ww9=UqX?@K-K>w^gw^QrQ}){2#RVL2j)ITc&D7N1-Zs>M=c z=dbbT^NxV?AqtZU6svnxFU>epwUyTb&b#zyUiSxfZYFs;str}CdxKF z_d|{_G=Zuu&slAYFRV0?DVVn`(BAuJTH{Blc^k!?ode+}unH*x9Uu{r-CM%Jy(|K*$s^=T#Z~XSC`-RA~ zeW$h?W(pSF7x{>Qfi=nIAYU?ep3-#OA^NH``j$r91W)b3NOIdX>c}{4^o!3sy z=Ajk+O9dv~-0A$hF_3dQ+cmxhu?lg`A4(ef&IwY|hXS`dA3D0TCE5Pcqse6tN~TD6 z-PQ{FnIq&U-}Jt#>aNNOC4s3uZGB~nwdL;nm6+PM&h0tu#4{taLNvsvRm@(XX2GLA zU!8Z{O@9yfJ@oh}d&qERlCNXrQcs_y1`Uxj4*6v6`~H3Y{B`T|T>ZXHyS>Fh%x7_| zxy~~M*7Tr1+COf5*#EKlk<3(yx>F@==dQHxUv*gVfbQ|G-`)=+Dymzpt=v zbWl|J*On~x=H;n?qcX4%r>Yn0?3W2;c+Y&6KZKp0>earIB znTbYqU&TyUCokH*bKUOkr`6Iq-cH>s%PVFV2w|6}UQ0v~_6=9jVX{DL5{ZRg*= zd3%;;O7PTejfv;aoqKpNZpE#4IWunlJ^%mle><7;!UiW9oMp04|J%!}{_$OGUta3_ zO}EcY6)$P+zrXWV|z@98g>wNCRbO)kvUTIgw%_4`)VrJy3U>oyMq zN{(A!HGgHjYgf#xQ>g(bUVVAB)4^oZOTX|h(#liecOOqN;VQz)pJ))eY|kY>3f6vlb1RMOH6a#thpY3t@4jBTVtX@!TX}z zmAlt3UVK&a&|7V($|t=idi?2$l-FU;Ut5^XINpE7`w)PdmOxyx;!a>pZTQ zSYOi=k+R*_)2%KUf4a8#xUOW*iVIBNRE}TTQ*R%l^FSqN<0i%Xmk#ZyHoh=x=B&GW zM53hEypiaC*Lzzx@@?(AO{?18PB0Jl44c-+I{jD|_pL+f?_z3yeR=r4Uu;(Jrr*xf zPlsh5%lT4LUYcn7>*vd7E{9_tT>LlV>LljMD&MfgtA9RTb5WI8bDpJ73EcAlHE=I3 zG%-rczI%V3DW}1QD}|-c-uQ&SJ@DvWv;V(`hr5@qJa_8XI?wk9)8lK(c0PZ->f942 zO?|!aRa3ZM7%YA|i%XW}*z7M-ze7HJDabvNYP9>*?{=%r9U?y$r0=$EK7GY3FNZhk z?c3eie`OxM&yc*^FF&uH|C_hy{(tu;tG?a*x_k0v?|q)y(^sEeBX|458aA=0)t7!e z5In+g=2O_WX`3!-?b-JLnQos|9P1ONLs{r=~4ddkv6P1gUOW|ZQR=y(3u zr3F`W=EQM}WeQDRv17I%`{wF{HD-VHS|hFB-S1`D^Z75=rTxFZKWgedd*F>*#bWE% z*Yni^gfdKOLo13cedp+$dmTMnTCXtF_uLgDp_NmEZ-3r;OQkK_)N1zY9GjZwhfnsE%W+{WMDm!`FKfAwSC)T>vn1w72Z@1>x+@9XwGTb52;8YBDd_HLCK z$;yT;>*npeP_x+Y$a$%cbKm-Auw3zaFaPgpj*DCRj#p~x?4L4bq$w3#n63P1X-Ure zzNkyPa;jno?MYvFDC8zx1s)^R$EA}RdfFA-WZ=NVj5r0b)GHo_q}=Lmz(>_#Ys8ejSM2M zUfRF;+DX3!GhRRYW@csC`DDwqtD8@(aXn^y^UI|#r#_r(^LCyr&YNH9c6p7a_ruTc za^zYMF1ma|Cj0i$_E(Il()n?)}-7nszQnK6;JT`q}(BCgQhNFXz*% zJ*>KO>*sf3d=n%0S8TYIqg34W_xb9|U3;cBZ=To{GSiRy>4wwpW@T<%?=SsOK3L5h z`DM++y(fIu&N;v1XHBfY)kBjtrf_Nc%t?ZFoXVINOCIDBx~Xk@JNrB@+9{xG*)@GOYr~4n@11ci%D$z(R)9zn|<%Toms!$ zYh?c9EuCs+6&!cnIxbDH!1O4yvT0WA#Yb)?B75)fpMCLE;_=Hlkvki;&Pqw7|nTYYz6d3mUtg4@rgPJkPfJcYgC>GK~wI^;5K8*mR#AD}O+V+1WWin2)jvHnQD}?}@Nb z;^x0~_`?=mt$D(|fsYP$Z48;S{9;dtl-TW1n^*e(PG6pIG~$ZV*V79epM9NmJ=XF6 zrn48e{diWfj{n@>^9`m4ryVH1m?UrUV_QXuDl>mtOXjxafgKxba;0+I((7j4VY}M$ z^2dP|bAG9^yI0n`8#@{AFACT*i%%>+LdQ|}+K(HRNBzvE1@d(-@Q~@|H8lEQKD}l0^_L%ae`OY!SN_rF zXne+kH#%Ok+`10Dx!NcxGAT`9(&PmN1x`*uN+SIKrqw+^-5b{3$Lw~^eA*?A6r~$# z70Ua|GtwpYUw~C9%Kn6fEPfut3GpecX4krH8K=9Wn@{C!82XIS;1zpAK&EI zTaPZv#!sJe?ooHkfwLzbcDL5Zbt{Lw2oCbGl6x>K;j!81rtwZ$wb1CyQ`^tM z&1I_1Z9hcg+ctgZ49zMsQq-Kuux9FmfHd%e3X#T}zD&kkzOjOp-|rPwI~NvaZd+Y( zZ1)`f{?*V3XkpSpeBdH3?$57#A4Hd}AM<&Mf$)7h7B7l zchv5<5H%_C;_rL)KmY%Em~cqxx!5+}-%S(W7Hqh%^4QOn`&f)0XJqWYxy~%SoHgNm z^ulwO=JXx?%E#WHwd(WQzFl0a6WiTyyF1K3c<{{T=NE6XP477!{Nl2xS6$WHj4!Y5 zJ^j17^O(%$)vq5lmmk_}d$UqExY(C1`|`z~hu^;K{yaIsGw$4xhs*!}wf~p7E2uSn zjp4<~pM|HgZnP0{PK))<_Rg+O_MI8nHl5cAG_9%0v{{-ZEhMz^%i;cW&G(irJ$mcW znst`^QqT z^U4W-mSe78Zv6Rjp=L*sSM}2=)i?L_U8T9XN&-=@ax&&~w}$PCZI!i{aq~9+-@`eFW@o<5_FnAU z8_d1CyLRf?;ET!e%Q~X=SC~xjO@G>3`{TuuwYxSf*l{8C`liT=TBD7J&Lv-ZCtxaU z{qWeLJDmrfIYrk#zjW@I(`rlAYPFiuZAPz77)2GhpbyI$Pp`?BQ=n|}FUX4a*(g7woQ9z@-}E&2K-&%AoMxw%<# zk#_Mfa%Dcv-?MqHvP$TBJG$j^X*qoeB|qrl*O~F+gF^E>v+>2b?Mf5z3fxp|gpmSTS?_uTD}R^7pcKPyZYZ`_rgQ$ZydpF8W{`&}&kwrSg!ON&bQX3h?}w9Ufa)bv7pT6lNr z%Gkxl-j|t6rylh(3w@b2PxiHUcp_8s#}(DNWlOX}m0AwCaJW4AaM{Xjn$7CVTW3}o zH7?vd)$ivxr0V+r5vKHxhGG7c$M*Jf$-BvG%;FFK0Q~ zw)#9eamiXOY})hRbE6izOb?AqVXsP9cq=ewj@tP*d#xk)57CCpB$_L|-Q`)pQ%HYoHoFAaobNfih(X_$ciM(VW^+YDO~r`} znJFb!x^hR|R0ZFwsi~_l>KiT)vE}@9K!|e#+uWlIgFDJ6FW4aQq%KfMSV(wMXGMXH z^*m+=Z@(sIm4kv0#5F>C-&=Ct=Syb(5%7R{^5I5C#g8*(ncUrTR;MsY>L+okT22-g zPSiBG<6Iys_%HEzosUP#?p@oTM;TtayIt7Rp@mg}SDNXta#h-deK7{rvx5Jxc{Ihm zWD01I|K{p6hM%vJe}>O2`KkTRX5PVL&p!VAv%hN3kF{o>A~f_wp8sB86Mr)02zbnE zHLJ0W@Jzwe4gWS)G(WdC-gowEi+Vu3y8H1Jg7t6e_L*kQ>AS3QENENim;FV1D&9nF z|9X>ok@t?8H@9xuLwYurK%@ccnuE>(0F=J2#ddX!cT? zIGNMMf|=`H1(Tq?$v$VNoc02-f~M=%DTx=h9ruhPsLn}jWkWxZB0C48>Fookg@&t*^X!6UeCsbKex8a%WQYb6cd}R z9k^_nC9jcLWL{yKghh^Po^N$^@Jz2$erlJdu4L7{8=D$w)uX%hMoy7px9-JR!MW>h zojcqvfA;EZ1Fgt3y_}ctG)`R!PTCTrB4oTbG0*(TM(?B3ey!B~U$HH8dRD-pm|53m zWll1DDHIx)9G&gF(nn)U$hY}6zY4Zpb66g9<=m=w@A_)Gr#L*y>b>@7)2(mEf}*=j z_b*$!)JXi))&Rpj64K5I^ZV!Zhom^KyfAU?;g3p&jrl7wUgoYpH+e%QPv5PFr`E5{ zUw6jad*k#iW!s)D^EhcT?^=qs#`^4hosG+GaAn<&(o)c$?U$%+?Dg8(I;tqhg{ALG z+DXmzdAY0BUf`;9n4hn^CNDpiOV&>6Y`SpEt3%8BrtK1%Iip(p(%Kn5Lanp!KD~MW z#WdAP;KjvV2i_c0^R2Jhxpm{NT|uvnrhh%l{=7>1dGqDFS3}ndJKWf@uh!5!YQ68- zILll7znZNduDvvgEB-=!S`yc$+s$_GAH4Xmc>n+YfA4rwyR!3ackB_lbL+mgw{X*a z{fSGn=JTI1U#hxiuFHdyJ^`1qGm`682`(X16ueO-$Z*SW3uFuVpv#+VBKP!8q{&~@!ljl5^J=$twT+L^G zd`ivXI0O6^^t_t!s~9c5ShYKd;Z@uHkq71x?Fy)t5dtY-Hn;q5|LdxVfSmT z8})szM|sys-&104o__I7^vn$zEzIxEGCh?|{rqhH{|^>BHvax_*MFK+@PVV#Ph9<` zlj|2c`<=jp#O1;(&wTOoFIgmW%60pW@4vWxmoop`eE32_eeSy8Q-ZIKhc~y*dUEP0 zclp{+)A#$GllsJ7ed|`*^jESrO{>&)z29!Ma+=@v{B4eN9F_!~ywmhhIDY?x=5TIh zwfj@W`CQGO`%c;abL*lc?H$*`ZX0jEbE-;vXURL03%Qk(9~8u|dA|9~-P5N{&G-VZ z@7TY8p40N1)zib>w5M|Y&C%GhzxdzF-^;Ha72Wrt&3mTGiI?B1mbp#)d%9P1f7RrB zPi^0vyc*ha;3}x2=fgJP!{4(uUWe}g zd8=Rl``Fx+g~?C9Og{h4-@~^uTAbhQRIkpyfYre%W$WbDURA&AIVs~3Z{*c%M*S(l z&z^mG`$J7O?d+0r>-djlQTbo)o|rMGTT@|Ym?p!lY9`kJ!%c#7vK0P)n(q1Q(#MaD z*A^Z>3*>)eEG4I+t%Nxd2*?#{QGvUEiM@w%^Ox|?fDG7D8-%-??D z-#cF4x8Ig6U%M)|X4yRF1=D?7rb+p_=o~NJGwHBV`B~qow_1F>V=q|eJ}UTBCHB01 z_2*f4)4jhYZ9HAOB{VYZ@#kH}A|jD>`^!_SQjWgQ-1zUAZrb@@Clgj4obk@!*4w?( z>KC7iS-S0D)oJ~3rLbgIQt?}{#c`|k4PzX=yE$Ier{oTB$e{+-)5K7Qq|eOope-oNluC12!mERvF+11C5aCM9#s4d}kcmvy&)zqt6gZRM+DtnUwgJNNG4&o2&!(;bukygA78 zJnczF@#?5mn_5$>WE&+RvuiOKb}WAim#pl&v+32VRj*!6TJ+|N$!@0;O2r{!o4Z;& zbAC<@65ycFH~bt!9@+-$c+++QSFuco$I^0j+8q@OnVDOx&JHB!lL zvdi;~oJv*8OdGM-taGbZuP%Gh>S7eW^s={W%rb{OlUF};wt1vp$bR}p!e8`C^5Q~O zN!F=bw=Nai+u)*fvGvxSPrptzl`snI{v2Y}EOblp>atg&PHf(b%%xp*76vV!%$3;Q z^@HzdRcxs@YaYGYWV74URcD%H51V5D$%z>~Ri^Epm#w+8wYp;ZN>t|`oA{br z`?Xfr945KRRoXk`7tXVA&)Q;rxo1!G!?3@42F>jsXP{~`uBYrz0QV6#T}X1 zcvRc&aH3mt+`z!fac922=)LzE zKf0slu&@|5D7Yqk<2u;Wy76bw)O&N%{Jl3Xm)dGH)k{q@dv5RL#iomHY~0U%GQvi4 z#~&A_XP-attP|_jo^(oe$Jg(B&nA3Q`IvU&@)aXS15>;5_Lxqu<-td5XWZXrE)lM= zV{W^g#FF~Emc|t?g*aT(x~J+399k_=WUSPpJo&xau@#H*&1cxA)-tor{PU;j_xJbFYs{27Tfm*naOqj` zn|~K9@A3Y9_jdU^HG`7AMT=}!-@Lki>pf*9fv1^MC(HeRRI%EpBhYo#sfm{R>(_2P z({|o5OHCF_THGY zI$4T4eb2-Tj~4hIO!1VRy0ubBDDvrwxslvwdd<3inrOKPn{N@~s+5X(_GQt!_WytO z+ue9$*l}Wo(Q|KZhK0#8kx{3ABqii7RlWZ~w(h}ghP0A9qW#)OYIAb)*REN2h&?Ok z5@fZ*dcDl3V9Cl7qo5gcvwTGpA2q#u+Pn1GmoMjh{Z~7@h`HBWwd~p7<@0sFPZis8 zp7G$Ll=~1K5@_$pyx_#`=>uy=w)9HfgOnPyT#x^ZoPPUEaUN z4?XPMHI4K8p53QXqb+{cW*GRNIA$q#(fIQur_Y9+%EdKhr#2V-IQOv4`=EkxUh>k+ zf`sB7d(NF(w`kF$BTJqfTC}L0Up_4@jp?*{SDH)Lfj6PMC8wrd?BDm}#iNq{3K99n zJ7=lg2`(*j4?l2s!I?L;-zWDkjy@RhBVpgsrKaNNU6o$H4qkgUQb5W-{Sv3=tGxB= zH}6`Ke8)O+X=V4y*|+bk-X6daB4#;plD$yv`C0`Ghf9Jle(|h?}r`OkLoxd>! z%a5&k8{NO=ydQ7rl)?gewcfVWpK|p--W@&p@8HDrEiosypJg%6^6?1_`~K}$Pv58a z|J)|Lz8~>EM>gtH$+G7>bst`~KRkQjT38APSMYkav8K*Q z(mC(g^wgP+pCh6p_7<0H*j@bV-|qIQQEZ)c-UoS@7Kcp>FDoy1O*+|j|NX}bg?G%| zqBRcS@oDWc<9D`wVV#lXiFP`TlkabRF*Doa{EM5Pw!O&7T^_!>Qp?I&=i&;{Z+kA) zOg|ZB`SZiy%U-fG9heO+fBDILcWdh1$FDD&9#dJEn)!RfL9fOQUtQKE8Oao6w^>nKBz)39(*3Z-&v~1BlN5~w&kK3@ zJxJTJo!Pfc@N9(WE#4`sB%99cD=65vYtPxYuTT2Cx7vHB$V+2}i%zJtb$HpH$9g^K z>vCV8Gw`|YbApN@GykFBr&n%%bds&K^2*^#gGE(x?~Ccpby^YiwdF9#nRmuvNUBtH7{ zT|&LMsCZw1+JWL*5++RN&0fu0?-{P9dim1q<$dSx*Vag7o|?v8vi0AGmc|2GQa5%~ zRpi$npS)hQGq`Kocl~$vH3D-ouNQ2%^Rf9m|DBs`dY#8y&Y$t#bY{k^Ew}c*c=+>W zVa56I1t}BqwISQeZ{GYl|NrIssF*0G#XQ?j3xKQdSD(+^h~eu$UN`IUnTLftVpgy* z*Ds8bZ0PY=H_3bH2A;IPKZRO@G}%w}M=%=H)S68{{)~Z{ssC`JTTy~ro(XSK z@2h{bezZ9xEbd^-v8iorbeceCe!9{_Ov+>lf+U=RGXdH zBt_cT=c#QA(3;#CdFFkg>O+t96=e{&^_R5PdSnJKD(|SEj{Pj!LifajrHnvQgWV73k@mtiHdC7KX z)sJe*&;0Y{(Xqybjk6ww98fG^Nb)Ze`u|(Bckl1|o$WvRKPDSSrU-pJ$s+M2{By75 z(X|)uG#*@b%BLXfQFY(i`rODQojV4Tmx+anyr_^#xZU-?qxPxDhpCGFvpa%)7cstI zuaw%jKK4=cd4^9 zQ+y6C-(nHtAX)I@;X0ccDvt{ob`(@|Tv`n7ShAY1A z-}|1ar#G?hZvGn9<8>_4W!>NQ9p|~0y^dJ3Tz*EvzKtJ#&Ul?{m}JdzowxaH`PH)N zOFT0yVpZl&SRu<5Z)?Hj!*ka4oZhc&-4d?Ovf2_hX0_WEISV8bPvl(n6;+d)-88#3 z#!T8i;EXiq-IKjP12dm3nzoCHoBeykqUEoD=S`h4-QwQK?Z%D#jo?Lxdo7-y+v~vh zaqa)d`Tzdj|2Hc~Gw*fAsjX>W+iLDA2_25R`24Qr9X_2IrA+G#lTU1~Eh@6H4mx)1 zIlDy4qCI_>r#f^@y(DH4hK#-k)-7iEd7;&F#DP7Q1I; ztva__=GT+>|Mm4Yvo@VNk)m+a{~ABb_1Qr?{@>QGTbTKw_3quJzRv8=-QT?v@{GE8 z>RofWe&4ZIIs%S&4e!oAmYQvpCC2poV#j_BZ|79)=;zz??pF%Tc&k?sD)Z-M{on8R z<-?Adus2u@dYC3?`sXOaqIEZF-+#RJ#G~9ldzaJH z`-c0??q{&GO}LuYxX9$!hq{D3yOQ_%zc=$Pjn#f1EA!?0^-_nOsdmce7%s_kd~>?= z<W?_J->JC%%N|4>+eLplDlKmac*knd*eYF+!9|3>%9O_gJ-zIrS$TwU=n!PI-M zsq|i(TLtUg_E!kZT>VO>yRH4psw=Pj{O8ULwh-g&3-7oYazyl#ZDrbw4K-!oGq(9@ zlHUOnS$=W6j3QTW=?eDmYadG%>Y%l4bjKR@YOZ{;%S%QKvQzY5zD@^AJ3 zxeD(ixz3oD_y1bXW%T;nyZ!P-{bk>IO+ued>tB=4|LpI#v%5uv=DR99;mccBlAdT{ zRAgLdK0|QEqE8pUP7QlqzvFbqynelFvxQFbfVb3vuEZ-&E2+JEk^Q%*&8z(TRlnD6 zzsYK={kq$iFa3Ysg5Z^UoO9($MVBp0OS{4IYR;@}|IT$iI@bF8z3lX?lP*$uGkJ5` ze!V(fy}bGJS4~f+*RS4XPVSxKbI`*j?&y(g)2a_moOEs9p3N8HgYDmZJ8Sa%n%|z{ z%7FMNxsEEMmXcZf691ogEO24QvRijIH-EF4d^6KL>T+9ndD^P4CxdpY7lq9AS{YxP zzS+M0eCthJDaDfpyLMlmzqao8^?Vf-)%y#zqQuQ?_gZ?YJov|v&l8d^`mIfAp3&@V zwLMdopPj=uUuWCXS(kG7R$q%V-BiCTU_!9XjvY5AX`Xs<+wxP1^wJ4t$DRDImp4kP z>CC%h7x`}E((6C_`=jT?C{1mJt!-vIqY&&p@20u!1YJ=FCdt+_8%0b^u0MUzd-SgC z(HNnlGwzF8Sls-0HvI&PQ}VBxjQ17hR|226ggItN&s5RQd#`cEM}JM$>XRW8f6i)q zcQ8j+K_$*>_5bp8i=fruLzaL6OL<553>5a=u-A=f*6*`1IzgU(&ox zd;xc6cUPJ7`)>~Z5bou@1q+2J$|;&q#rvYo|w;k6jk&bA%v_er1m!Ft&Gef*rCP8UDEW3mc)>n_;N0fPRwoXb8DBt)Y>NaA;xxqJc!gRM|pHC-kQNGTe8l%4bsM(T3feWX9aGv17;&dr?)|#}6 z=Z}g4&mS&s?)Xut`9p1k^Bzx?J)Syz8!8>7XAzW=B5 zrafRXL$=t|#(6WRFS;;4K-F>0$?W%en>v1$uzfD;vlE%~r1z&yYh!1h4rl>;+}$~n z0>vF`=3bt+cJAA?Yu7&gc zW#8!PPd9g;?hUPEZMBpPo6P)T&6kyx%(q|L3MoxI793?<{3gxxfL!arNy}~+8Ow5U z+MAtcacpq%c3kJXUgSdxTl3X<6Bkb7Xl!9l(3_YWz3cls!6$0ZpNKz6lQ@$ZX{jlc z8)~rUg@CiE&OSxm%QNR4dTg|khr#~9;xjk*9{%Vxeeo*Y0*Mu;O*&MaENT}ztraOY zoOox})Lhe5FL}z`4&P`?Keu%8qHn$?R<6y+#e`2mUJ-t{L-`j_v-lnzqWr_v+U%~i>tQu zyz|Xp-l4bd-Tcq%^7Gx5R3oi&^WNSnE6M+U;eGD(M#Up7Q}jb`FWS9SXM3K>pWnaT zA0A%4cBvvSvy;;b&z#$DPX1dE`|I`opS$Dt&(zqwt>VvK%~P9t=UR3<%m}=?eb>gV zd#i8UjyllzzvUrz4 zy2+=1_5V)Gw{?r&`tqqVKco0{LfNXwQ=Y~0GIA{CdhcRgoOaKy=6@Iaqv$J>me$3e zLi4QD_8fo0+w$+v^m;yi@ec>(YqXc2h4_2%!Jbt*-F07nA8)_7cI{TJ&4QDbO;3NN zm}#}+l8TX8T-|9Pc%t<6-n$qAd1o74BYblud={BrME z|F*~1RBcL{Jjv6fz&Plq<~qmkUM2PQ3)eTD->9FL`_1H9|9StNTV}pne0=w2=TceK zmr}EAcGu?CIUG6qD*XN5hZp~?`hV~Jee3L^XTG^>Eh<%FlRx}B$6y?IQL?i~B(l*& zNHX0%HdAEMftWpew!NBiNAW`5`xnjN!7^#zbkWKh%lP=2v*#~<=3N|}K5hAWNr#?F z=YDy)tKv(Rr=~1fzCu*0*v+-@^OsZKuB{37Vx4s)UBV&k_^Gd*O;>(Ch_f|ln6T1Q z=k%A0sTGSh8<<~TH1+kHwbItk3~BowtT-FExBBZjpXhy-XXnk$6ZsTTAu;1z(6q_t zeEgEKF7Hk6XP0?1h4201%i8Y?#5y&$>?kUdjtb-d#@;<;S5w~on)MMUq`CKRx4%Cn zsV!ov$ksgxRk=3~D80-|ce;Fai%M$z0sDXq$AoW_4)o~wt^V-qdU0sLd3M<7z6$e+ zkM8YTldjEOvSfF;CF@>oX>VW2nSU>yl`}kVC2Yrg?(27+vZu36Z}!$6JaFkp$cGmt zhgU9`@X~_$L_)^u_4^i;R~0i#IJg{OD7wbOqu`K!)UVin$1H6V)%{Z^cr3`8Q~Pi+ z=ju&a&kIf}T{Jo8{_SsZZL@8!YMEjidz0h4Z!QJd$(!~k*XaH7TXN3NJIMUb@4xQK zer209YBP_UUp3!X`Y~fqnEL4~yM4Rv2QN6A6KQpipXYmdiOI824f@7NpZql`Qj@kPe^S8$K`DCS^S|hUEBV2IW2BDet?

O{JEdbWkNUHo|K2-D7^p$XGDzN~A~k(_-@Kw@?EF?F}! zbF4(0+uAc7(xjaqt$06k)=Vjlb0I>SDOTOE$ge;+gKulWUUp%-UBXHskE+&6z0@%oiW-@3ApvYt}Y? z^5oenmJ+EpScAv-JWqr{(#&W>Hi12tOs*6#_VMt@1xl$J8X77}uIJ)C;Lh+`SCLcb zSVZABUbAi{)+a9mq0$MqAoFj&i!4u$ao;&NxNYA)x5)hJ4M&-Y>4AH$oL2$}X>axFKS@)R}p+)7$uc zpo>kk(-;~*9lRboW9FIl&y|lyF7vpeulPLs`s3)&(`T-ckDnxQ>&R1X7N%#VEB%+4 zD>?kHda&>4+z)Gc6ht5kP|l7;I|G}+Fd+Wb{Eq4}?fmZsY4 zY5lX!`A#-COjdtV{L$+1iL*a^`Ptu{b(jX~oUZRPo$nPcs+YUd`-zjnpU`KeYuEG6 z$S4u&oiv5xzo3xjq+c%=)UTORrmo1ir`pqV$8o{?(>#@mjI-F)exGJ77k)3)xq;)m z{icH#-K&51-ruAvI$4-`rIM2oqfLwFNr77axPuZ?Ia-cQ+<)|nbCvPL9;f8!*yQEm z?`74|9k1Ss%#W3?Rvt^)r)GYf^ZmC?Jxw{g`#N7Ni<`eBQ!08&xP8Fv zl^(gXYahI4Dl-gWVuLif3^IRhKJI?eL80W!J9T*(zgIJkG4|J&CYn}!*sy%#imHUX zb=ucMcK>>LxcT6|rGHN!&RX8#v{-m@5zv%td$%!>7McKQRqdgZY7*x;gF_xM-VS>t9`TKFN zPb6M=2|i>Dw8zeS*0m5fx%e~JrleYIey!FVzWZ=m^zXy>>#MeG-dg`}U;Ubui7AQO zw9m&_O3%~y`8NN(NZdbY|4e82UQG`_`%W)x@87bZzi+O6aruAjn3vS=?LAx4 z&Yuc7eBzV%d>gJG%HiMd&D5HzzB>E<-}d^>p65c7PD*gwep^4$$djck?{`wk-r(a) zF9^&Pg-o5!nH?A{TPd+lWaGUWZO15!DiO)E=icnyC4Vx|k!zO6vJ2Px*6DqDGJAE} z;>}ab?<<7r%jK5be4H@t`pykDcOPiYzc+7%hr-3^XNQE7?@BK$ovzV1`Qp}%c9*T+ zTHcotyV#-B>veK*xAAWI+HZw7Zl78@;RVN;IBkQ)6I{<7`t+tmb!tynu@ZRTORXs~ z^oQdTKUF1xm9su|Uj8e|92#T4zq)kW{=GY6QcT0Y>7Ofq{_50oyNZhX+Q(1clqerQ zu<(+kzwYKapH{v-c}m4-ap}ti`|m^;?yM=@QC;!jgO)*(+0t`4vGe5Lt~vYtX7HwI z=G$+rj*%^%w{Vk)R%hRxp7p&>G1_V#`RjDg`Xt^D`)>dVmVyksJw?T;S$o4+6t6${ zA*{J2N_4tk>W3+r>zZ=feGfe2T;escBR}`^J$}C%b8e>X74dgFmc4Le;zXub2Ro)@ zwMx87@CvDtoZrZq@+~LaukG%NNt-1?=Gmz3UT`7rN)b!Z;yCUS1)0vM)zb_G&5yqp zopt`nso>x*TAHuR+MhjcVYnY)*4_=S6T;`FA4_pMDOROp!5bm>Vb(N5ckrr%E54u-M6LX9R!b zJ#;8A`oSk@!uIG{#or!dDG|H9N5%E{(h9ikLv6PA^ocjKs&wl^c0czr7^|I|c%ozK z)PKLS3}>C3u`HHarQKiyMz$@;P{2eVgR&N#32 z$3a2pv5Eo*cv+ZW-m(An)$jk_y*5=fYuBz-F=5M6Jb6x7rcY2{5MnW&QS6s+&hq&j z2O$Q=Neqkz>7A2uytnN>z3$5T-C^IWSEr@zomsj0S^Lk_Ykw3s>ua1Yda>zsspq1z zd#|TUvJ~h$e7N`f;hfFq?PM0cV2hU%%PCp-KTelB#N`)?{IC`vi04CZpXvoC+6& zPb6^jsJe=}o^%qjoZ+N8Su>?RF!4p^k^qf>)67+Tov*E@$b`91D+xR5-TGnc6c-zp zpQ};~{YbLzj2o6{E!W1crY;@>IiIqD;{?xVR@Be>0t$usn-o1~%78Xl30G>Rc=^*$^5mtx8N^pUuT-kY_EkAH8-S7O?6YAcp_zyo>Abc|Bt>mrEb2d z!*=q&_Th62-Y)O(GM1cjp|&MmR;DFnna1wi!rEP3@=oqE_iA~1EjH%j?w)5?D)b?lW- zRgy%=-u7KbWY#TQv(hF=JUrBV%ce~mH|A*@yKa1WDjy1}MR zk8Ty{iMkx0&b#LC&-(xS%iD^V*aS$=&0cfUD*k-Z#-XA-PswdjJ0lFn(^n?s!0;DPQPF5IJ;|`(ap%)MsM%km0IhY zX#C)6QM-i@h>eZS>KJij97J_SuXZOz+?S@BjbnP_)R|g&Qk0j3-2>@yMB+Zc*BJ{q@|LGZp0yO_OXg+O4B&oMGI`QEV-?&?$7)%}=-c-?rX# z{VX@%QgvnS!MB^wonN=t;-ioAPFF2qDW{v)lB4~SI{#kWe6?}Yseh@*W6CYsd2*HG zs=n{r>#y3>ddA{HqXyO!{wudI97 zkKgM&xODIF^UD<%jj`qzt#drQ+O<`T+{T*x9?8&M^5LD=S^5@UWMJHK&P0pmb1f)%OOq=~I zfU_rQauaLh*vhPywW`AT-%OqNQHsa{W2x4vD++unU6gspphK)YJ_?eOWFww5Fo?M=;F zvuIgq>B5=S_AcQzPd1rsly6b_`t#q<%abd+ukN%64GG^Hs@WcS=!M$fpw z<!$ zpO#*}PPbp>n5$pDjLD1}B4QuIb{@O+_qlbbROXD6dp18`rMWJ$%=(O5WW~J&rws!y zo4zY8&7N}W(XxY!CcWAjy4uop_O*8wTX@BnO!qx&&T(?iC(Zjs!91=t-$Wp7eRJ* zcK74%>dTiGe*8G$*omW_mpM+onXAuuI3QK`on2j7SxrSr#_M$_SG;+VtM79rYxdg{ z&8o9c|C%=2NMzy3uhQ-P{{4G$Sv_k!o;*KPZS+-_PvvL|e-BUUiye<#j6+gQyiRUl zgOsk%UwU%8+&p`0+ncxU zzgyRnJn7}dXN_+k`_Fs3E_9jJ%NpO$YhHgjx%0Z!1dY&HuhhTwee>h@yUw09S$Na! z-QFxFd49ir>N8b(XPfLWnxyjJ{#?9UlzJ+_>eIP>dQ+y7th|JxZ_a`Kv*6*eq5BQWJ=YDDHN zZGo<(Nu41oLbY3+zMQVneH5=J-nFEdHECnSA?0^JfAt^yTg7_r`t_;L1ijyJsU8Ws zI6>vaGoh`nE|0+HoSG`^Q{r&%o|9= z9CQR8Y<>Cqr^Nr2SHtSvL>(Ty2+{~Wd-m)^w!=qXc8WR(Ou6}Vf+Ty*`TF?!uBx|>IE0Vs#r>V?9k*HY;i32Yu1~+GAkga7 zD&INt%8~sgVt%vS0@B`xq!r9-C2L){4OSr zEeGP7nU||;@V+|+POP%0d8&R&Q)i}ktxHtj9F=<@mf&(!48|L3fi ziippxyLe;Q4Vk>dQ(jG1b=~(-=)~;@TlXu6F(@V&+)SMH;n}n>-yPTDUvQw<32ODy5)(SqP-C|-X5o~>5h5Ye9({HZ zvb0foBoNhfdG=E6x&I#Z`={Tw3X7?}_cBWK%7q7ADPCJcp2(kS(&}=O%+Y&ruvEZJ z{LlXG{nsq+Jm_9h)H+8aoK;_Oy3>C(kxNO1twu||v;+m#HGQ-Zyuvd{IJsQO)$_GS z=q@&`a)U~ym6Ix@*R1~~G12^%xUYz_;6cNc0tGk2H~;4J(v!s603;uj_SJC-(w(33AukBRVU9L2VSMAY>{XRGEm)v|=t4m3#ivoh* z|JjvaoxVYLzI61Xxchf+S~shn@=87wX%KQC!F@{q+v>I{=6M&lNPauJc2Y)S+51;F zZ>sm-*?iJ!UBG)yMnOqOyxl|F--8{{MUVZSB2@hvv*% z$@~7|!Fxq+bA&#rUrf&z+2O;@Be{8YznxumioBNaXNmBFUw2ot2rTvDy%{uN3BS3Y zpWm+CyI;Dj<`D)Zf9old&8JSju-U-B>WB>2)P*PC-YzP8DHP3Du3M<&=(hZ@+0`KH zecvAC6ldkVzufO9Wo`Z4@0!t;M~4)j2bDL@V4e9jr}pNJhu@Y6p0f1%5_|dD&8e!- zKP8CFpM7N$Q>x>w=V7_RKb@6=Vx=v+Mav+^M0dd?MByMT#9MNdyh zr=+x$owa?-mThwK@~=y(1fB2DpQ`)>aFw2}G!if8X^ zH)++?WL|xFE8@ke^n3psMDD-2S#suvd7JkZ^LLYOr1aUWPQQQcw0eC;*4A^)XR>bX zniaGn$M^rEs%B3OBa<7~b{Q41+5da7WBuNJ`?eYBTCdK&buD}W=cHpk);6gZdtS}F zJ5Q$2z;#YQO5R+F=px1_TIgFH&n?_U$LMc+*l|&!?VeL%Uo~vbvKvwbS>N2{CJ;@ zr0&9(KTZTsk2OiSKmVns=G$#=EZmDP`&8cCxa-fl;Ok2!3D3E<_u;G+QwkGndY0<*rwb)#}Z?e@E6g;Q1~7Z@;xJ8F6h|EbPPVJ$v#qk4Z*_ zH+SdvEeqGR{mhec@@uAZakFUU)N7Z|uf3ZYqbA$!xA)>S$*Icc-o@UFlG4!1D9y>e zrqZp!b5C^7F9&nwn!-t5PxGe#KCQps#>S?FMd1IgI*Uvx$C-Oy=eR}aP1p9!n;ZM7 zD!lsDdX}-RWi%#r! zT7D(MB(;3kop&==zMEm7*LkW#>s?V*S+28bmf}>s3s-s8_UJ-eay_~vVoDNBqa z!au(%p2)!TTKwtLr}aONim%Ph<*83}Tf@+_;Edi;8{-o@mQ6T$P%*_wbXw!WPnT|O zn_jg<=2Ei)SNDm{&jU0+XmDyt9(3gmlWo2wrNef2zZj2->aXWBTPHl=++ZLfV%=ms z+jBW48@_j7l;Zk%wxoP#>S^hqzjUu;~ zJV}`ubMTY+=0}O(ez(ZvW&0yvFosR!3)TLaplS0=;E8F%8J=gphxcFU=28%Ob-Mb+ zho@ZH4GJ2Y%kLW{A3n*+Z5aG#wejJSO%EOjEIOcPDBTm$Cn=WEmj77CqJ5$1w_CFx z#_GKDSr)XyBqQYS4>uu0(OdTIQoA%~-q_+)r^Tu8Z(hrLX0`c=tO6{l-|~*1xuLU9 zWm!JgCcSUd-LkjFXt~Za+O_3YuoP=;J&%?5+=RGDNz)ZiHa^=n?-h@r$Lmz-KHrB~ zr>ext`O9ke&DDJ#vC7S5nSf_rLDb;@rZamP-49IFGb&Fj z6i>B`{rYpG72jNqGWWLiJ1=;je0pHjrH~EEXYFTpo=z25q-t{daPfoKXC|8-2KhA# z>1>!I+srr9{z7Ms>G3oBxcg=*YHTjoH4b164l&>TN;=28`|QiD^P_GDzvz0@|L^wy zpS$ncX=MHRp49VRaKW)<~GCS$O7Zkhs*w4nxxVkq!40$Cb#mLH4oQBLu+lt z7`Jq;MM2!ByEbhNG7DYM*Vp5JUiX|=-{b=`B*PbYpViYkce&l`f^;qyFdO`rp@| zzk6elJ2`c!sk+{>9mU!2Q_gSRZx*=nTwcYeFUspr7Z+@bpPbR5ms40(BR4(2bgAcA z)oG4LEeyW$gbp4$V zXJ&{nNqh-%yLxNy;lfpaEbkxtv?O=ib`7JIsfVmKTiH(+{cCH){Y=}r|BkNo%=Z2J5;gp$%YrFR02I>no~C# z&;8_ZFE94x+Vyic{f>IH^18;ag;Td)oH^6?`i@zZ_B$_IU5}a&X<78`MZ%7=F)_K-`~EE;`;3Me46;C#ak^G_w^oB`nC1;_okC2 zO0jZLX&aMwA3rxQD>!G4na|8C7VjlB_k5mk(`f(It8sfXB2Qe~sIt=6yL<9iX5o7) zH?hmJaZTMA#i_nHyL6@T)GrIStDKMUc)g8? zeW%-b!Ts3tWi#2uYwzteVeLJ2?DB)TCwvl4y_AsFOAB=UdRh9g>q4H$jk)=Xys2%V zig3CLBa7XIE3bAYPp>XaO8tM+y>{g(0pFkZit`uxT;KHVw!OWaNNf6y>u)PJ-a38u-KSp7)Hf+e znJF6}tgUTZT$o>-dUD&&&DV1#xtOl0so54MAb9^_%xgU_&(*RwzwHPYyPM}7os;={ zVX??7^R#cfrd6N*Bz4=|b~Sgm-28kqH^;?`&)oAhU#wucKR<6*le6e{y|;eT+l@t^ zN~d4*nId_L$8l!tw6A9#sLpsarD@f-bA6fX^VezGPg(AF#*g>$$I!r)oNTPlOFT?w zUNPEeW3+bJ(ye<}@7}&tP0@)_d%j_1*NiVc5xq=e<%*l$R(|@?G;7^7sp7i4C2`X8 zXGmy0<-EccoU~?!Gk>>s*4vkQr;R>jmh4kow`ZB1ve$BN14lW=x!T_AGv2>m;m`3n zFtzQ=5{Za(7s;t}1XhZinDTRLuB|NZ2fq#NT=tDkOS{q^I@i~>$~ zi99d=kV8C=w5KyD{m`>%6abe3hrKQb+-YPAJuvf8z+6A&HY527{`}q%f~j^Lsz)B@H}Ad~!GASx{h9uIVc-HMc2$;R_h;n%4|7pfk*eTVdvsyt z!GkIq_YXchd_#P)%bM)7ifRisE!@Z6?xe;l_|>MuW(Bj;cX7!^Cj}o5j^`6R|FtU= z_w_$NVBO^J^KgN1vFZ;4=Nade#O5vDJ8Mbd)Rbdtd?)jnSDP7hzSMxUEWBrayz%eq z{Z7*dGYyz~J~y}8TO0|Hp3NEW8d*QTw4GD)(4>F_(|H?=j7B1Y-spg|5SQ!74CvC0c!%)5d z`LB7NY{+18&UKIW^U>&bToIzf&wIH=Q^YGZ!$Rbm5ZAtZ-OL+a87toAoHkpvu!AG) zp3}XDGbF>#x(B4ax0^ljV2}L$$}bmxzI?d&v1xVkjv1m%t_=(K8O)BT6t>G-VK3t| zW&5Iye`PyGmRW2*{H;IU#{QPAjqRO`bA23j9&Pi)q-Odo+c;HfZU^_?mKwHRAr9H; z1_x&yZ(SuAa8%;kv;BfXB0h@*mmaeWF?y-^$3dx`BUo&&^x8{?Fa_wSsArXIVtH0+t`h1RU#Lf6|@E~)STZ=Rkm z)YI>pcCG)cpZPS^36@bsojch3ckU|*R-V9#5|jQYzPJDX^60$s^xSR6 zc4nDnS1pa~%+u%QynJEz<2Sqa zPF-mD`r4_0xo*qfw=7+xzPEqdnw1w%Dx1C5o_R3joxsA(Q;BPhHRV4k{eC<9+r@_` zS;V|7oQkl4C*!I^t*S$56S6XZVKO0O2bp1zCg$iItMD z(oDk{p54#&=h<6T|J!Z{96y37_tczP>&YBh6Dyt^5BxJw2`DqjO(bN~Nv;=YZ>P{!Q1Px6aCpzq~w3 z+l&3}YTwRBvzw-be$QGr?Tqi5?Yg~7m%5$XVS8Kp_x#$jsJV0OQeuDZNc)@1 z_uI@5|Cl+Ur0Z@EXb_?7e$nsa+CV-D@8dv2$5!c#D%ETaDV@#D_^Pme*)6Oz4PkIecYWz6Ec3)o4?DbJvWu>E6N8;_2;1!JA^=tv&qq?%v|~ zLZ?>^sT=itzt1}3^LX3RTPeN*t<&$C)>nM_^73I`c%+E`e3R#v)qCoIIaO$4!&!0XO?y2KJnu~5YL&URF)X8(b7SDF zfTb!b9&{l=*RRy$_YM7pfewDZz_V362rT$mxUXOr8p%9UA5f?{Q7-rZaM{oC8yjEv>~-Z|XaS86=r z-1HBU<@vGdc?FW?9nwyQ{bl+Op1r+Y{>Oh;rFx5|aG~9v>gV51@9sEzFo{v6(y1yg zY*OQ2g$K>E%bDK&d9kDRciMqkvG_Af?e-LYz9!q_Egdggy8>cM+L}`K{@&h(hKAkw3JKe{+y7A2-TOUZr|yg9 zc-QSa>gx9$`1RoLjj-8k)s`r$7{dH&Mw|5x-`c|6sn19{<9ku2UzHQ~VQ^>o! zv-ow}f6Mp(U+t~F^K9qW#+Z}U@Bco!^;PIcpN}5hXx@MJ?d;Icy&%493 zW0gE>4M%-!+6Ap@=jB?*&VM@NH1n^mz3+ybx>Uym*&bSk<=|H=f#lxy7Db!JmJ3N9E&NynYdX@3~Lwh<^X~6QlX^ zJsxiR^?Fy&i~fA`nN`IX_QpjmjjGT4F2`j*idD|EUM^<-cC%)pPhisDUk_JazqWj0 zr`PX0^WWuK+E~}7W-6MmyMK)NPthqIg$K9RR(CC7yTADI+M8lxnhzdv^McB+Mx)&( zM%+6}U#o2{y?HY%*xJzWo~>opI<47Jv%15JlwRxje-CGO-)2`;6c7-*bMI^2Ztm0a zUv{(^H@}bDUHbXjTlObk7S24}y!GU@V*%F=^INQ3w|Vl?e}czv)_>+%&bio>xw+Z< zbHClko{Ymr+w5v@%~s(FdAfG4g?I3l%uw&%*344veS3c<#nw!Heqgp{-T&+6A2{~U zG1~q4b@q3mUw!{R?f#mQ_(ArOU(U>hXAA<;rhBI`n&;i^$tzt5uV3!lHwwyADn+jl*SYOecyPuKbKRDHbLXihhHC6 z*Dp2K+y8R%`M8L*W5tuKoO1vc@d+qNSMBhtsn!>Z)JsI}rW< zL-+T*nElE*bGDT)ExcE)Ft4PFJ9PigucbDJ^jDs_xBugTD{1%VY3})aPd_iwT=^6a zb86Ym6t@2kR!X{MFY5n1?Os;%asB%4+W+6`ZC{<-`}yD7L!GksQw)`V>~lJqH1pN` zzmMbk;%3{(Bcm6sP`aUM*La+2BoAZmW<}B7(wqX6Xdv~@zkU1gvw`)nDPq}_-2O~$vWxtm!?96sFVr}9JqiE+ zVfAkx-|v^sJ^tMM@RQ0UmBL&59^b0l@_bf6C)4`-J6M0pZkIDyeEN9J?&ZhT&$T6e z-O8W$;`6U<=jC#((-&Eq>{CiUySH}7>v>YEc&EB;`*uy!`CaU8L4n8%Z*8sb-=5)h zMZHb4?>dmdQzkh9wO+Ksn{r>*4=d0>OG>mzs+^i2v zn{c%9x;@|j@2xl99zD+W^T+k|&Rj|t19sQFJ+}6?_@v#1%$q*{z4>FiBB$UyhM9j{ zlxh!zM;{c?Rwvs50{#EihsRd z`I}Gf-t^B?cKlBUlUB3B@Kgv!nxO5_f zt-HeY-0jN1C(GIRwYma5L^QZ+m(~@o2xASGUsQLyyrHR}V4jgg{`(NuI=1%9qBV2ZQiap94_mvZv0`x?oa8m?aoiNS3Tbrc6(Chn-h}v9fOl< z=BMus)9=ucjh>suDLi4OOw1f%P`mEl+%q#wCY`g{YkL1wUBTUm{TnU>hTgH+V2~EZ z`6ZdpKQqO{Kz7=OL(1=0o$gT#*{=7lM?@=c;?cck@y<>){ig%hic4s#KM$>z5`G-}X^1gLE{CSqB%-JXRo`1W>(pYckX7g#?w+6}S zr^J?(pOee;xjJpzuRi`)kA>U5@9CYW6#MeW$;Q=6fm}b=YZyDx_$QBJ*54mB@ufTFoK9JMW}VfBUrRjJW=ciJ6z;IAE(*yF zP@g_sU8~imcV%|Y!o3DkpL#4~py9cCn&kAuDVk?`l~>E%Usi5p9pmC@NOp#*VC3f@7gb4ydbBkTq*(n(R_`X{p zo-0xZ>{4Z;>dIw*FO+s27Cja6FwkwWn`+v@4;*soC%(&i+cbtO?(XTj($y++Ec9(9 zTe6_4eMd#)kH?`0`g0Dw1a%v}l~0wFK4+!Iy)E@X{Tz9zd+D1bj!Z7}lKd22EVVMk zXsX*{XYMEL`@S4lV)E_$rt5;|++R#j7qsp2Nt*Ft{hS$l=D%%kSa9avtTPX6CLf!w zlP4o9pL>>X>IqjLt}B@gOABw9unGGasLl0Lny48ti+z`y1(O}WmbF8#l31$`-@*$W zXH4|i^`b63=2*J+f%S_2Cv$B6t)hKE__(+x8eRW|M4J&XTuLBQ<^F3W;m`e=#H^Jx|`-ZTGN zyF!3ysji&N{I`|qT$fEhNCqsNdg{5es`jE7zS+EczkH}R?Br*xs}`IS|L=0IR8b+@ z$IjQ{H5?ygq?#RTIR0Jct^O34rm^|G?b8UJd5IZ+Ggd8B(Xm;0eWPvI>?Qp@LEeco zH-4BQv3Q32^yBFvre-OsE(J>;zPzR}a$jDQ>#?5_#T4GRelo+GLC(7>XiXW^NE zwEL5D{gaPh%ipiWm200p z>94PPbgC0z~+Tx+<2 z>HI^}#J)tmt=+kV{h&&tjh30+=E{EuE*)AhQCqEine?SiQO9hgXG`Z@|5A_|m->D4 z|4;kh_KCHqrs!0CGoNPmZF_jJ(iTzXbC(aBw%5M?cv*e5x8M84pIh(c=t<5pvF}Zj z>|DK0E;=^Hn|GhQkC5i#$3on@!pfGdUSN4^M}b9B-}%=wzgorWt*_p)e9MNyH<#;w z#+y}LIuyk9X5Zhhs@LyLQ#JLuZLqg;Q*QaX_qKNRIa}Afx2d$bH|5N~l{Fk3r{1hR z)#I4DyzI?-zRV>PLiz0{%C)6N%YGA54xbRQH)rMGPS7n{LRwOU6`uVe{ zpef5fl}C8SrRe_EYVt|5Im&fVBM3v{_3LVD zikF#bOh}n`b9TN@Z%1FZpYNJ^5w|1dyLhL5Tk|GFifQt%?boX~X1bb1nYCMG?Ph7AvbpZs^#~0{WQ>7oxfrE!t`UNVV@Ee z7FWJ3*kcqXKRdz4&{VIYRy#K^>TSo_;03&AWbL<@xd|G*W}3P6%6INZEo3F{PFnd>Ry zw&`ib;We%^V*?ec``3F)N85k33JW(k7gy8T`s+;V+`qk3r}o?beeC2L<9Pi;-}$}o ztTvq6e&T4;x88cI_*LB=XJ?nc-x+>~{r0yvCr-?|*Lm%d#xkqo)Y`QU>INeH>#VH~ zH`N(kFZB2+D)lMdT)y&++4B72Rr@2vV>52wkKcYPzUJH0h|Yy26=~JQho9O;$*iAp zV#?v$@p8UXUtRWId$0C-SM~kvGlax$+E~R-UYh7WZQXkPi z&GMKWdoLh*(n1k~n@+t4SG3A%e%a`@cFx&}(vOm_C_Oy-C*Xr}N1E)q_nN_`Qz zJ!Yp^YBcAhv+>G{M>)-0c;=s%_4+LhBy}9b0<2GbY)FWxb9~(kXW4OK%iccX%$j z^7(;=Qeel-^pb7$Z!_3a~iNTzE!+#ZdsU2vn|riXjCsIdiX<|+o=d?nwXdv z85t=lG5x#xvLtG)*(Lb`W|3~Y!v_u=aG3db!b+s-o+6A}{kIL4vcze9RWmROpRB|cP#rWxyoR;#1YVY4!yfbR`)y%^p_bXysLv%#CRO=U? za4B;BcOhf8X3S6Bmv!E0GJ4YwKIxkJFl%Yg@uvosHI*~;YF2DkCQR}?5+lZa%Su6LV*~fmAd48r3{N$&!pILP z7g{t{CT8WXnBleb0DoQZNf#m4q}vCL;oYi20auP@ zcOD7a8RGIJu%Ua0%|wxHVxNC98NQi+wka!m!mWiK8Fwrv>~4%kZ`8svXM~{#?5A-xGa$Iy|*CG=2Jd&b`ii zDILGz+tsN@B#d>Q|NpZ*-L9A^UMMX~GIGP2Z>mRIPL;gW-OHT(*LJO}sb|zm4U>B@ zky8Yw-!-z@ZDb#p7R1$aHSfJomWxkfXlU6UKc#6W_9+{SO;+taalfMG#_WZQ+V1Sv z_l&>!(d3zisHAQ5yU591ZmFAY#^mNjrk4MI@+Kg*tnBK8JC{6a`(_;G^*?jcub=aB z`c~5t{__!5+MiQ$^nSNXWr-U#?+Xc-?zOb(-mN7|mOOcqvV##8R$XU~NOHH&yLZRM zx8&WGbAjoFS$|(_I-VFCRsU)u|8tS4dA5HqU7I#5!0zYG_w#(OKRx!`bX|V#IsbJ( z{Oq%Iz4B&#ma&%YK0R$?h-)AAeUi($Nb;KIOHqoAU zYkQwh756=NZcVhm-(2TqONyR9%c*KnRJFFgxL~5w<2TVpk3UNCY}2cL@#W{{(&K&U z`&{Kh6E;U~D%IJvFz4#F2@9VGN|>1GAOHE}$fcV`FROn2Idh%wfBm-D#EvuBv$y+% zq+hx9@59Tq>g@l=?oGR?uyErJd$+WJM?zOv-?RLi`jeeszmDawBo7<7tUD$>RZ^vQ zd6eAVA8%g%Ot1ejeeumKPnTb>ZsyzD-!96vwcEg_dR&@qnoX$TmkoO!&h4!eoho&G z-@ox;`&9p7pF;JXe1$DV6&-%6jB zF8%q;emMXfrOC)5~!WH*- z8rhlbyAnS=RcrO9H}B-CxwX`kWsER(x!+x6dvE%)@S+nR1Yxk@lN_kuLfu|1cPCTs3WtNNXj zy=qzV8S_x?<{({f_u{XH;zrtUW^6uZ{&e>8vb5|63$Hz$+ zd0Y?mt4`0dSh7KH`C?mD&Gnf@Wm~k4+dP%h;#yRAYg)gXSKXR33xYo`x_8`lbI*wf zEmx#knRwV&{?q_fls)FUo4>r&jrR4?2$r%-x-VtCTxAOH8~eJVsy(J5bJt#!a9=ym zN?6}!d->s8OT|ANedxKkZ}IZy?Rl?Vyk_jmDfo49@o{zb-^{YDC$}!1{Wx^O!;1!+ zP2*&JPxP!llPx!Y{)*F@vW30jhn#yi-#&bFVO!V6bbtA;BCe{l-1+3^&zJjIrEN5s z%SzV!trg?^)8SKj^KhXvm7bjo$>cXNWE?;bu z(`0rWG{16w*F2lLJ$oPegr9yK{cEqkysf4EyG)tq$ub; z_0^0cPnNJO4$_;r%EYQyDo!zE@zoWgb&;n+7aCmE3R%i`x$f_Tm}NY@U7hByrYLQ+ zQEIDLTd>t@9Z#$IB86qEPl|YjX3U7<6J|}(a?VK-vN4ZY9JK22LtBk2f^5xZK3`vz z{|w8rJ7e&eBXRYOf~6v#6lU5aX1Mei8qGPbeCf+yHYVOvKQ8nMAI|pN5z`oIi8(WX?R9 zu;+QwqiJ6ri7D#ru-O0R)Z{oDFQ2t_GYbko8cd9MKVSH5z1~9EN0vb^Py6nh#l_~Y zP^TdG>)5@7)!o;Hy5sZos^6;WZJYG_tXkdAECq#|;qU!F{k_{0?>nolOPYtRn{%pQ zr|0FE8I}hWCP`GT_g(p{=#PK1bOHYhe!143da-uzJ1^&3z1{!$__Al+F8bVIp7Go} z_gitE;$dcHeyn@qjk^5(aKu{;$#5e@|>pU(cMwzkBy?8U+uo`qfYuYDE# zc}3QT5bw!ryPo}jEp7kfeLm0gx4-89d(eLW_q|v1u6&sP|0(u-(~;j+W&9o|6h8(or~c>*veP(GaujETm3i0^z#+5=-7#?^kP!Pm#>O@ zaHUmz$KTUISKr&%l!o8^d8_=~`T6(a`&QkXU*#OSet+7W8UJG+zIt3=xcA5O|Ftvg zPsP0{*Jn8Jbmc4g&cnB|)I<0Fl;8Jf?V(^@t$fkYT%jG^C++tu;3aqb zjp>E$tL@jGs^#7D(KhjD*@d5-LQk(gQ!vkFvRmle)=!o# z*Pk7ozl-ay@ygPxB`3E&d=n#H?L0pubZ1!3_S^|Yuh_1s$5$I|ZT_(={GD#V)n8n- z>!m`!?hKA^-ckPDBxP=$!oI5Ik9N*9cP&-mzR4DvTPOd2fBs*EN`+kwKZ=)r>!_P? zKlxHmgxpIykruwzPQXszv5$I!3q17DW?DwPY# z2n|(idS|}lf=FWfKG)B`ZGWoDtvcnST9UkM)hnx|m9wwA7KA@p6}Er!l2ui?Qf)`J zdWAoAShznpR%hew6|15cYx`D~U0blqzNh@*x~o;{a;39Z*;Ps0*Qr0f@!XGnA@4)> z{Qg(FajO43HOY;}_m2Nq@pu0ze~+)5Mec_+`D|cYvj5Ae!p>+LLo zp$s?lLPH<_4)qWH$zYzoo2m&){ARFEt+^Q16R_v^(d(b5Pm*EIUR}OxU;o3$DoZSXo)T|d@!_A>Mz#p=P~AV9 zepxU7#qImYwtp29L*UhIQ&;_3ktH*2t-t<@g{zM0KaE@^wRm$-!?S=;!(VgM8IEx2 zuUh5mm9cr%vUQb-pz3#6x49T%!~V@TTm{+>tSkO|tzr4m z&7bwtdihKKTP4>PSRdY^#Sl?FrDose+lI-pp;KqB`V^Lb?o&wF>RmCLOjkYn^Y`C% zy>xBO@1bY&LN_d3lMx%r(9ruZ_I=fLrbVmvK3KSTRqp-EYOk7C9TH;?ySbK&K_UDq z_tRC2R;_q-)Mk^!HTO_P1_lODQOeMuy>!*}d3*Ul#qkCvvBj&*^Xh0$B`@f{@xqmt=FchROV$mu#|E*KD{krtq zzGoE^Na?Cj)6Z9eLhb+m>AwH}M)Up3f2!a@m?3QWs-?^S9i4x->YZ)=@9XFPtaw^{ zzBZLRG|K@)b_P_FlJd6G2 z7W=kO77tTD{PDqqw7{$H_C7usS9eT)z1$t0sQr~66fEnV|K5qXQFe9PYP~h337Y+` zCL(@zJF1;U?ggGddjCgXg)kOBUZdywi^1=bBWs%cYw`m#(_J-nPo`#TxCfoxQi!(=Shs=3TXF{a3b{Ur!#o zTrV)Ol9&JVjrqW=#3@R3sqbW5vNiYp*t*Q6y5pKgsrrAWJVCz8Uz!g(hy=t*zdq^n zVwq-L{sY!LzNs&Nro4Oiq)(!Hsa#+7-5oy?0xYU_+n81@FLeAYpjXx`9)8tMzF~>w zXTPJ%HPNU-Sq^_8o>dF)+S z^X1Bw0O8Q7-B-VdhA!P-wECC+!c`0#Iv2`*ZPnd(ck!I5@&6yKj^&(orS;A6Zx3dM z^s)s`-gs>9!ArGDwO&ExMzdGW3gG7!>3{7|@&Awc4u;UT9~mc{{W|H8!`vP-|sS>?8N``KCR-aWeKIP+D4v=IM>JqM-t>DF5-DcMcv6x&z* z>8(e0S^skf5ssTu?|ioNH=N+waDJQRggH-V&amQt_tV(i`C5ba1l!PwMuh@VE9aiE zFE!+Lz3-%I>3FZ=n*ZJQ-D->Ghl$DuYU~xy&$=GAXtwtKl|O!d+?wlmk7?DdQr3p= zns2gKt}64p`h2!+sABuG?iZPhSGApg|cH6G&S+jXGS(H|-@(q?w-=VVp z&fO9`D`{3K8CBd)5FEyHleto&& zU#%e9oc)@z_6#3go%ssq=?dgon(ncg>tOx2uOcJJ|L^Xwd25bFO8=W?P#*5h?f1p@ z-}`_{m#Ow2gw~(ExAIiF!n3^xLIXoRm#vzX{yqMcXlQP5sJZ4VjTYCrk!q`U$uC}a zd2(>%PQLYiYD-sf+1gHbUlHS$m>cr7Y+gmcDqV&HN{d#l><(edF%Aj+arTYlRqmCm zLS~w9E?g0OE3s;yz*e?{uU4+Q+Wz6q*P!2P{NA20NURCiDm^84=k=$%FE3kl^1jfe z_@{zCyH2w^*z{I~nAS>}y5I3mUwpLZ$&ZLjIV|Fb^!=9!-kA}kb19wuWp3C0+^khv zU$%VeIC8{MURtkshxgX0^W`ToZu1FUU;l0E_kUOK@BbaXzv5#|=zNIWp8p@bpSu!JJpK%5k_toN1>HSsdtF!LMT-|bm zC$#tR9z~v&aV?XkK0C$t{bXqF+08naB;xwAruO=V=WSTD>M3)6;8i7~yH?$+FS9$8 zEa-S&7Jl`X`^Kv43&XEYeiW>G_^_+Q?q}<_txXGEYtv|B)4yubD&AFDmB*LcueP}w zv^CWHslA>{s@RHEYZ(N(ZL1{i1oH2HzN$*ZC9K_}ca`5fHtB0$x35?wdBH!}@2aHY z!4+BzI#VtFWs7D71WQglCCQvtl(1#PE+gMyzR>GymS(axyouf;W~cLIQDEqNUvcdV zuQ@wrq*@(_Ek1jTi=i}huA=#Gy*Gu;+U@>LKlaFqXG%Xz`6JS4HM!@B1cRS^lrFn+^{t~!;)fcn zSFZA~a17n<96G=9nfw25x9@N34y}Fo{@=r$`E}|mUVT0P$1ODUb7|<~Kg&yELno>W zJhSXQcF^eVg8f~~+Z_LF{&>SRG4-o*cR?zLxHqTSon%p-zBE%&R>3{#!HO7>3m))_o1%R^5x=6#&* zHl4p=x9rCo-7iaiI#mA5>pHbsFxznH%Y=YE${$lQV)a_nw5NZbb4V!p=3;OA^DnKV zZ5Ca4Ufs;Ns%zD?ir2UA{p;ym{_h93JoltkwqG}|zbeddYVDFaVap;{y$NGwFwlN` zsrIRP%IcHB^YYIx|`%2jiNuZsA)f|>{cp$(@)z*Rg0r1lQD+PX@M6IACjG^|>* z3dC6PYV&pbKlk|mOz;2m$Nk>#$t$!#!Z9(SZ#Sy<-F@@|+$H;YX!-vC8`;lJlD(qLD}A+B=;L{znw+TWU8 zLmAg`)ZIUk(|lQ#ZkNKR@|&PKMdbR;`-!C;of;<(D7KR&f<9?YKR^?8Y{^P*#SJt&>-UJzhC? z(W-v+q$BohVZD={ty;DB+7iZ&!h+=dsK<8}p7l8{{dS?RU;K(F%juzaTMpDtA2=)Ea3I{Kz$pilOS z6=z?s%rt-5SrOpY8ZH{n*3h?P;+3M!r=+d=OZ7GDWlF+MuBgpjb44upP?na?CC-jj zOb4#5SS59TebuT{>;aLC#?Nf7E?Skl>Xn*ntHeTnE*uqx4QFN7#PW-ISJk|G%ao-3 zj$KQho+M+=`B!f0swl(2K%H$axSzDL;d2b2lW$)_1R(#rXFM2dMOo4cR)4LE%()S?RWnDJN7I zAMBanJ$d;Ax4!OzoJp*+RT!SU>t4l_leBJC*;zkMhSE?`tL{}y2h3K!+B#4Bzjx@_ z>!H1$=U*xfb)DxRAur$CoVv@ge)hGO$Ic#477s1$T=k11o8yMpsg0#GnFWl4eUH06 zemQ5Am2CgAlWUgQtPkn=-R^bn{AX{eYoWf=`2;Q>dbCArCUZibSSV|RcZ=h-aE1=! zMKLy4{pX)r9=dc@m2%9p*CpvQ!dMxi7p=N}rYck`zcj5bYvn3VKkdspS6A7t9N{fr8G1vS8-vqEStX-3_U29{rHp2n46{~LfeEA$w&IPkovp=xT zXGBFGF|*I)4_$uF@Wb^tA8#-|=vw{i&b(C$Qu zJ2b!gpS;_7&b)mxW5Q<-<&~$r_GVb+y|B5qcgdf^3z4dezir(Z6z#*gdgTTWb%j-2 z4AF~MW!3C|wNgvoA(i#ajL#w6tG2CNHCse9smt!v42j!yJ-ht;{ZgM=?Xj9UWtG;N zk1=u!izHilwPtRMUX{DTxW(If_tv(W=^=Ap`c{6QdU@@n?vok}H~2zz{}g?nClc^} zv60E^_}L1pSMY|iHoWayRTjB&RsOnF{yYJPzq<;UXf2lTG*|cUe#10%`>jQ*cII_u z{`eRFdu5i^tiaIIhqk5Yyw?&xE9l93BP(<&->u-#syZIzFh9!kz3^)2>Lf_7sE5z_>l~##ZC~HG*(A8|)@PE@+&04=&>bd>W z*Q>g08V%$#O{V>vn->*2=dg*~?iH)NL$104+ZquQSADyixOG!>=$)xrch_p=?X&7% z^{O_~_3xh73>((XC=D&Ij#*R|{dQxd!;QOH8>WXQo&U0$mm#4UG`6a@?Uik*(MPFO zb1&Uo6?An+`c$2;m0oWgqw)_)e|R~$T{zbH&exL7p5?8q4ZX+Thi%oEQswqBbZWR+ zw(0C0Zk1DiZ(?GI5e*Ifz0$7sp~2^n?o-jZA)$MFvmm|Wt;c>on`~XYV%4SlFCXhL zGKBihkJ~$Gap2)#)&|v$#uWtxpMMpFgdWX)J@vI4{~{&zGH!+f){w1I{%=J>Yi$IT z{~2z`nqm?j`gW@t?}KXwDm)T*LzX?Qmy?yMEAv`{AyfGmY+_0~Q@P4D^mfQq-!3bz#6b1*&QcEIu3UBL!xKTR>46c_p?l}5%T39Wel_LRa~HGH?CMR|s-~?7xKr_F&#Ta|p#L|n zXqN|14OpGoR9N5O9TvKDxl&@u_UaH*`S1Rrp=~)+Pj^iL)hyez5Df$e-uvQ?7c%N@ z1<#e5HF>#fS>vhb+`y|bZ=6mT|9dSIx^;!)s#k$ek3A0yotPh>c|l_n!v?8P-{)q! zE}@^_G_kYm|Gvu5mpYGO6&FLeEzV*i>x-rA5~Nb&WJ0ZlvdWI`Rb_q*0#m1`dWVW$ zlF8rW%;Ye8)v{J?CGQH+2a}3Ik1h%{WOVR(cwN1E)v6VnW4Ib(LK$`(T2;07`KkXw zD7_>#{@!Co%U(QFZ%zDy(MQraeMMyRTqmo8CEyaobMB`@A2VjnTeD@J3d5DWJIh#Z zNKHD^{w+eEVU23hqU-bRnZ=y9P2E*o~|g1WMp7iw*^a4vi@FP z=-JiTj0eJkdo$LVoH@B`6+?k*Xer;e@?_AojTG~0*MQ>IRj2Yo!99)@S`0B3SGX7& zR_R59t9@vh;SlNxZXhr~W{4OZLVvGZ6_p&iHtK5Tb}dL-B5c{Jz2BG|z}gaASKTUa zzj`V!v@m>C$@Wz{e!j9Wg*vJ5{TU(AY7t+Wc+Gne*!VE(nN zM&@IE!FRW_Uax&OTZ%EnsD{qH9V}Xuv9DvE*{ZA^cPehwC5K#fk$JrJ)&nOl$7d7o zDY#BB3e$UY*5Ya1v#nt!SG}X{!b4+^ZC|?9>Q(8R8jYFT*J)Xv-!<`zZ%opy&gr+W zAIp1vEc4g9e4Dj48`BvgB+cLNdo?#Gdf8{!$7}9}e7*59P2#M-^O99{ulJcp3&**d zGccINgudIE0 zGU|2YBB#Q~8$YiKkM#VT9K8OHZ>ZDSWt_+UGU`Q!PMz1)a`EoFz^gTP_M6RGe>Yr( z;e|s^5L+l~gSLF=+f6~C_haBANhbDhSNiduJ$YGax5Lx5+g4=hl_@@v{9oF+D(Z?t z=+_lRkBe8YI$^#-Bts;UA)#8hmh9gP+ za`QUZTyP3qeEy}v(!i@HFDD${^-nC+m+kdoNyUS)AzO=?8dfaPiCnd6!n2CUvO)~E zLQHjI1S1cvW|%%@wU*nHWTu9)YZ7I)@0PDJ|6Z2&?C{@H<=RT#>$DhR3`6%`D}GwP za@EgWs|x=G?^?I&gfPeCcDH27;F8ai4;lQrS@CAkD!sr^`9xmE=+60JrBhO~x^DU@ zf<|5Zp9fxD;#c{w!o=4?Y)sV>8ftW|<% zr?y!}hKn++Te0fg!EbqMx>hkcBqwa;$XXW=3Tm-HCY2kw+oKp60my!t6K`!;V+0W>sd1M}M7XHM4^Es^80; z(3M$tHhYP!4!OF=XXWl|utv+K#FuQ7-*Is>NS|LcJ>YCv^wywi=hq+Z8O>s5hzKUP zENMDC$0;;)&$aNn&+k_Azq?n^7`iQxwPE$TRaYyrmalmAxKrX|e`Dz4B|BGTtvAhN z*xsg?c;Lk{Bi;X>UtG8`+j`mI+iHvsTZ{Bo@3Q}-damvFv2T7QQ^QUldV24YOYOHa z{|c;Rq2m_C@n09eYuoa0i}%5`{C|6Ae9H8^K5bn}hShStGx>W~YU=n&zCt$T%AOC-f0q5}lYeh-mZY_K)j~PR zGFFBiO|);QByG4Hu}pfF`MF!Zp{G@@Tyfd^ugkGMQk~&|Xb64UCQqj%#neICCgSQx zRkT7EmM4LF9)=V*O@ckd7p*$UvueinF3FjX4sfWou091_I#1Hi|3Ca4_y4&vTCtT zaPXNju9qyAFIHIfuTm>L#eIBnX4R%kRg)M3b{EbTO33ywlE0O_mtn)S4$ohOyjLvN zdY#)U#bf0fy7lg_%+PmR*M3g3oXE}a;MJ;ErkmrYo{FA3bAHsStftGSOuWCodK-3i z&n_{B9Mh|A<%YuVixGA6vCTi@}5~tXuGBDyJ%F=wekDXe89(jW9!k za46n>54nRD;Q3GOt)-#Sg3%kw*4pdJmmdhqUh{1YFGE5x&OXno%9%msYt0{AR_9mW z)s}Mj60h1_Q85Oyd9L~kwaTOSE}U!f?!>KxV>w&77{UWXuhy;dkGD8ub9K?DFzL|H z{KZnXrlwb1Lf01V`}yRY%&Jvi%70mSGdP4^ULL;wNyZU7R)*E7=^GxrUA$x!TVn63 zDC5VUgcusmhF#6F*%}=3^`lGAkK+ec1zw5?-FkhNNkjDE2?hxz!851*uPn)Ub5<5( zOe48keV5nj)Q3g+nTzbI)9Nke^6}>`-o+VzVCVW@f#uG(3T`cZaIO8Ho6pZJOR~Mg zjZEeSi$61u3yCfXjW05@x%fSL`o+H$k2ROA(oX!$FuSEEqpR>Iv-*@vMu%S~OncV4 z>Y&WBKYhO)uNHoH^9{ZF`ryI4;hT+e`dAslJwu;=3u%>^rN3x-?r_jK^Bs6iU)-Fbd4IfvnI`)0_yj7nVL&6U9So&{Wku`hOF3&)BMV(hqbONvbm8h9B zZ_cSxr4^+{nxUam^K6`+8gXSWUbX%6k>;RW=ea?@=bTuUm+OBm>b#I>mvsN!@V%$J zUdhj{dYZRND9hB>;2nR#$yKYqgsAkqE9+nNtoes==+;R*4Xc1DQ4dTgdXZ zXHPOG#xD3279C9vP|A-5&$vRT-d)AO5b6pV)Z9_9LX?3aGtvh_XRYAkao&tuseN|$b1m!(}B z=EQ5Aa8>;0{g40Wlqlrw<6_uwlCm~PT=L~pzDM2GTtBrpf|0?@kJz&0MpdY-%zWPO zul$`i;M4DwW?z6`aKga?ppQkUU6HLENRWis&7$~*$T2HgxGrWw03{8@8|2?yEEBpPp%L{i1zbMt9~oTJH4K@4b-`rdbeO_ zc|4h&8(o$!)7EcWw11N~!v?D>47Czj*Jm<3t0*XVpc3R}e)zS*;%BY$kIbJQZuqxR z&{r~at(#};&xECpp-Z1JG2~2Jb?)s-E=!Ym7k}x{&{Na6dBYa3QhOw^{wkYz5QkC! zmt$&8Q#Ka$mtO#loLpUrb>t+j%|7}55!GdLD|XiA)@)I&(|Mey?1Lw( zb=smdli$xuVQ4rV82WTdlG^3G?<=zMraeme5+0jqwqQQb$J;AotC<7A-5pWF-JM*t z?v8k1=xn`!Q!A!kX}c585Yf5nlurZe$}FSA)e;xZFDssTV^v9Th$zE4zjaye{=CKW zjyQ#+HLkkF#jx?l;`VeU?JWUUUldz;WQLS}GP$u~-G0~5$p?QGxOo(ahrXS|prEDc zJ#CfN63crP?JNzuR+*hWo;7a)8^h`|p`zXaM_CvId9SMfUb$+Uzu{V~=z6bz*&b23 zfzb>NyjX{0D>F={8M>O=Yw|3f-+Nqd)hnUUuY%VEHcb7I8S4HrMcL3(dzrA0`{S23 zt7cu%)R*aB_VT3HYfmPJx5sk58rCYFtjXyA%5)$~sn=jlBU0z*q{CO^rEjvMpP$WI zx60b*>^j|8er*PZ1It!pZ^F2K5Mo#ray>NmOVaAv#Mn@V9bBud*l+LN2r8m`8?P#9 ze<^|&L5vK)TItgRQredAHmW|#?p?#xZLL=m-ZS+wF|27^l{W9z(XhSC{nX-|w+359 zhpv+PzGl)4;zMC>}aWcMMa1IISMPz`ySx7vKm&7~OZI#7s>451BTqhXcsqO6bWI_KCI|P>RDNBC8$8IvEUTvIic76=3-vu> z7`K{NZ;3#P+{<2H7R_YX{LSiM=={z7Y1>|{xW4i8!jyZvRz2CnQ-5qnbW_j%X`(!`k1hM+3A|-^5PlVJNU%wdzekN)xz=^Z1`}=vGTfg_HhQ zE7vveRk3FbWo&dXuSJLt7H10@fS1S(B}!&=3%a(j0+4mM7d~R_lJ+aFf^ql*~-@9{jwej|c zcXubrU*E9&b*bW}GHT-RVw0T*9m8*MKt=b;gJ8za$)}mF{ zEbiA7rSpY`{<5x}qsox8ca>b<`L^F*)jNMP#mHGVUlJEzx@w{{JAc=V49&%%p?9Ti zc2qCkna0pi8iK!vb#p4#9#+)#EpO-IST*^4-z)dKyqSkHr#D5*|B^O*dU?`1-Pn^C zO8jDH+^-1Cy%<`1^5zGZ`}v9sw%2SG{W~?5so|=k^Hi&EnSJc+?0Q$UM2+|Goyv&& z!B`t?*Y~4(|C@xRS6Ld^4Sz_jN&=Na9CR*){LCL`)Cv6#`Ko@;()fEw_xptFB?roU zUafqg%W&Y=D(s6(WLr0^n7r8~^n3D$!m1)I?duP(o?H?VnpyFQW9n&*HNC6uofGEw z+R9scieo8`G2cxRSxbBNW=~>d&~p!+D%&OT9MlrBdlxUg?D{LsBUgT9ls1J=xg~A2 zzf}LEze6ZvLh<5Nv0Zw0=({IscwtS_6t{ZU$#b(z&ma_gj96Ml0uXa`;`v8X$^>eiirXfFp^l|?-#xZOj}NgZBy z{BOwDXZOyXt=SR(Gw<`26(&Dk(WyYHj`(Qew|Y|XTDE4tz|iG0q6!`ht#UMcyhpoO zJHF(#2v}4s_ex{{u}r?3AA25CiLnC)v0$rn*LU2Xz&dP z-8%o(WpO@Z|E(+bTy+b*dV7VNzb~(8U}*N7e7l{-?W?r@&b2!y#IP+cl>d18;lIBo zAE{;3>!0hG*1{cfHOSm`G5hyjD_`9^a5_)vAOpkeHTXw~H)&%XCEl_w^S1TH(5Rcd z)2qLWe!Xe@`|!(>iVW$izCW1G)n4u2C4H&wvL5SpyD#QRr)m@a3Fc2KzrQ zy0vKauSuI9cJ90Heh-?LEB<7Hb|ik z`j~+ReX92~ze|tHUhB7a%hTe}tEn~7w^l8VJASTxQswJalRg{$k^HTuXZZHW>9^UB z7wdjZF4Wh2c5a=^1IdKu0OpTMX)j$bAVz#nruNj%3al&NStsi?OMJI)U})*imkn=c z=%`h3Gi=yLr!HD*yOJ>a{B}dvDm6}K^DjB;soYB94!ml!`@zA3r|Zi8Z#*NMG0Q@< zdG`t}hMcl>)b6aUcI0&L3I6f*}vmbwLtt_R{^aAy-vby;5GIn4taf@~XZ|C*6`Jh54w@ z=sR|~GQ@OcaGZsl@8!u;uT5rYxYc`m3PZH>q@Ne$Ub8lAb?Mvrn=|NmQB~cXY*UGn zu2oh?MVe+yr_U~Lv)dt+cjNWnIl5sC3=O?F=Bv6Ms4|4C)OtMdt)=yEX9wo#J^jA# zRpYJ}*;Nc?V%yiPx+k8s!F+ekPFF2ZiFXw10^6mlo~3%--FmOVf4wV{4z-XYkr6S z)rQu`p&+M4i$8^r|7@LfGqQKptO+T5!d6FmC<+9I<~BMh?cHm-ycbl$>@`T~NLw}Q zdT_Rqr$_JiN7j)$k9;{e_l)w9P4h2RIY&RgxX_hFoI!8y?DF`poy&tlr!JZmu-ZHM z?BZ3wYL-XnFdQ($(XeT?SbBY{OQ@>`aMVp&DhM!usZx|!qTgt1>Or*?L}&~yz4)u0NVYKThw(4 zK3sg=_wCAcOFA;X1zw%ux?ue(vC~s7PP3HR9hNnHiRRja%Y{F>hBAT{d=-WMULQF1 zEVc>j#|yUcxk-i2wc#~e^Ey8;RG86sdGtzSr>5O2vL>#cwM=`8@03$3R?j_VQTTL{ zQ>d%jfio-&A)*PFi$ZUQPK^m=a0pFb%WxqZeSSK)$L(>#%)ATn=M1edGX0VO_^tr| z=K)tE7HZ5idzkLK)RM<&Qq=3vfU7h31UIGaZ4jF&v_k7Zljp5Yqz{^+T9{7WsJ z-jo%vGTh)Ie$tt>p)@7^0q>`0cf+Ue;1vaJLSBNu?eHn&|K}GUer-Lx@xN#P?AP3( z&@tUdIXl*$?)NX58ispBW%I+7ANT$TuL&+cu=-m;j`mId@9M8Uy6L_D68V4qKC5~m z2D2#`%U?NeZ=6MV`Rl33rLUd_hQ3|k{xRxpkz%XEkNMwh@+Uu=wC7X0@x?pm_n6&S zt~-C#sx`;wavplM=KHqdfbyU(j&Z4{SYGq8)hyY1ds?`-S<5uW1Y=4T!j_60T6FG` zP-t(U=hD38n~G%P=K6SridI$W^#|fh{VE}{EY zzx(8KIaQ50l9wSoI+T0=oxSR;SAMVHIs5Cn+6k>J=TOFk-5B}WR<}vdCesgjSJR^x zUcc(!u3WXQW`|eIy*b(0OD#Pa96}kl#fC0z{uXj|hD`!5s70-NF7)k-m5JvjM|7Oh z2?&j5R1mBF^1&yiRcw`1vGdlql8CHrykP#VIGNDvparp;Ss0>E-i#VQVZU!|VCa;Qnz4O!lkgGMZS1tZ)#)gMJ;cT(=TwJ)p z$9&Z~8AF~&+16VEL#MA;)xV*wVeJwB)mEnt%}kmWB(Z*e-?7VD6n?K&|+2mc$8PMHwFTXo&lNy}bNWX6VXQ_c*5iw7M&~ER^xUG%URf z&}2@6cf`eAs~8w=FJD!B;Mgh#hSWP#Kyy5xa*hEMLZFTWj8mL9{!O1B^6$;R zE5vX@03>@OD>QW8ujlc5YrlP+KCkC{^-a)lEdv9CcgWQTE2muwi?90M4p{{sv2|72 zyr@;Lp3koje9Qg8`uzSD$TZNakgZ>??EkSj`uyJKx&MF7l;2wOZfAe{-LTc$qL3D+ ztgTGh^*E$Hv^Tf)?HWCoeUC*L9MZp(t-Q$=a{aV!(BG2bgyUC#PN_(FP@^q!m9Z*RZ4 zef>gj760>J3?lCzf86u>>$#2UtyP~MG1pwYrS~NyF*`K$>|(A-R)3G3uKzrJ|A%Mg z%l^OUe{cKem3{4>Vy@Mz_W%6T9qMZWUK%skhIiYlFNW_TRl9X#LPHl{3;6n4{Z{AX zxqjMP@)B3A26N5%JFoARSper@0@zkjj!7I7?l$==+k zv0#tcwaGIl+2OCLXY=l8B-WB99wC+4QHH&+yY~U4R^QHebovV_$B&uP0vEE)d7AArHa2d-c?+ZWwN8S z$MhX<)v7bD^C$I4rYmiY4!$ZUrXhE|@x#BL`2~!tZarpJn0Cgd!c`qfBW{YC!-I) zyjgJHOeL;8d->so`&RY5S=Dy#oaHo=8Ua+{)6~uxiz=1()p}uW<`C^_u1CmSek0%D-#Hs*Z)zoNTn*{@2d@TOq!V zEpU1M2@buR>lmUx$YX`&&9{$wEI+r*!|KAaRd%x1_Uj*N_-wxP zF}uRPj1!9IHnSemZGS%D*y-flhmx<_)xKWYpM7=m_p(#bVz;uS*REXUGtW<0Zj-s5 z+G>VXw{}H`B5$gV{qgTbjGWt#NrvU=ji#ZZO)q2(vv1wXTDGciS_n_QRkO&$px^J^ zGv_&MxGK@THMPZdwqECr+zgLCb4TiI#;dliz(}6!2dx z7wS8|t$xzXd1{j{HiaEKJ}FIkhd|xel%T2aBEIfjy)x_5wtFkwLOt0WLiJayx^Dmb zR`vf^@9+Oz9lxhy-70^c9q}iH->zDf*_XL+)xyA)t5!`}@7{OCJv4XoNeRQVNh|D1 zq@-3IEes58c)RHEl20E>?-_<~{TN-dZPmB4p}yT`1Fl*ekUccvm8(W%=DIfp^JA`F zvpKEQ`|#|H^YIYT8dxqkEcc`DF(I?FDqqLef_{fXR{kg(QH%)l{zgBB0{IxUKi2cBhv^if( z^_(`ZI}pLrV0?C}B}3*U28Nu_V_8A?4K1s@}ibWygRSXaMmm3OL^4n)gd~!X5C5f4ShOiNlMhz zm{ny3@2^_Sik}&#TFlV$s`Mwrj@yF$duRBmhu!d97JApm*zvSy#Y4HHYt~yduc``q z#!#Vsb^H8qx%2>Dt?O->p)0gjRWXLvV&8E)cTtH~gUB`2Jk?a!33pd9Bs>m^n%&l> zed$^zOU=bhtlMsNiqAA={#)_NH8iy7@4x106Ia?Yae$55=XG#PudaKyvtQePYe?=^r2RR!4hkN1TgDxH zb;shXDVM@SAB(O3T%_@B$1a6D|23_)@(d9MN!jun83Ia;<#t8}=4#HbslS-gzv!0H zr=MlB3bU8qn)NxU{@kf;q2ARxFU>YTE%SPLEc~X{s^h-5!%Rb-Zf97V%XvF_=J|8g znx=VcOs}&m{IxLM*Ux)GHeTG}XXcukKW2%pt6JB7*roV=_r+DKo&~ac&aHd=bpOxO z@fDw~FV}xL{#~x_>wLR^maU;z@7Mf0x{6iGzx31c8K720h$*O55$hBZ`hMY4>z^+k zUY9d3eVid88nADl!P`}<-fZ5?wR+Z@rcDeR+9XVS?l)PpUySNns{MKI-T0}u*IVB` z`B&|>`PPhI2NM*yG`4qqO}W1^ZT&g+?`-^!`o8ToS@D1J&fSx{o!(5XvRGI8_))Xt z-7cx=|8u7BKW=)a81sfrf8DBDJBCd=mpFZ1r+dLp{Ext{mA7-A=KlV_`uyx2Z+fEx zuU>Tvb+!rhT=nby@%vx*3HXQB?0dHI7SmFuV+pIk%k0`XAR zhNZRBm;bJGv((;yC|~XO3Ge+U>vI0$>{{aCna!xr>bhFCoVPdsZg@Urv!3~ix5u}( z?$R_aR&D>c3;zGT%2E52Q|RVA4Rc=8KhrAq%DZm9SF)qP zM#eAp^+NMS=f6rl+Pi!C#Tw@L6SJ1c)7_vgY_NilJz(<7#fOI_xZ?VHQO{uWnO%1^P)oagp$Th}C`J9Xs=r_cN_nKk>?*S()g)%JEt z>g@Wr=aW*gTby+K?B8eeuC>m2{PdIIzL@$YU$@&``TXF)fqK5r+k^IW{;QjArLpnq zs;r!^wOqfWR;`*F{Pky=f9Q+Ezli3^<%e%oie|cV?FDT(U%Hv?t#DYnuJ4r%?_Zg7 zt?*0Rx%u+(cgHtL_XdV)&Z@k8i*>JNR{0lo=cmTmC$8>!={9Tes(q^~``*{Rm19ik zG+Zt@@$}tlC)raKK4;sv2!tq^8_g~bTs5oZZ;v_4a?5jVZ;b0#y-4`VHkUm@@a4)? zx`7+_I)0gYVcq_%K6idF01roB3{ zYwfZU!I=kTHuGuaXRp0$vwZ2p%NcSD&T4VqlCtA`DLvh8=HpMfQ}cZ%FMED<*<s>?B--bYkS_jQKxTtTGH**p_SR5t_Su zVo+%Q(M#_PkA27zdN=hu2ZMIss%3gXoEy#tgg!Li%sxwh$tpFQNU5N;ewpnre>z>s z+Pve}>a4GdN3uWPDBxM}Z09`Fc+Ont@gbdiRom425-!EsF>DSAy+3P4!t=$omqeZl z`^|gXtFmg=t~9GwZ5I8>>iYLN0`FND{+xKaI&}Jv8m_r{yUx7!u%Vr3pAY@o$@pFRQ1!J-DNGJhv*#>a z)!KeF)bz>Pu-zBqLxcN$QZLR((q&u_8Y-Qy5*+$= z^;pBBoY1$kS4Z*aZC{xs^MEhW<2B_g zx>t!!e0eQ0X09DW?y6UN_q=?sw7TDjQDJRj+bS{nRgc_`EIu(m>vO#OqHy0;T5=t^ zi%%HRM>*x4s*mY7#k1*p7=yskcO8PC z+bo@p7!P#EPGShSG4J2?oO_c(t{xY*fA@cmf7FVy#df7$!@Lfc3gOAu|O^wq&z*D+i$%9(YncK3>`Z4r%e{th=B zkWM2pR9EY}KD}Od%Btyi6OM+T`okspzQ=P;Vs4{Kt2v+E^~#qK=czwFtHSF1w4&P=cSlE43N?(T@I;{V>s&-?wXylGY3|1GU{a_#SM>+ zOkAdTWtm`TqSo70QJfn>L$+@7$XZuk*m7&8OVRq>nKP4i*jrvUT5Gre@~xPqNf)m@ zVawj9^!!Ci@{7Wiw+`+NZ(Tk0@~RZRh6&sB%MJ0R=U6l+_E~FD{T5+>(}Z# zYrCc{VOZepm3{d_f$J@+-UfZE-o$%bTg=q_p{JTKG5>%2dT#0J6zwfJH@kTkull@V z)stU;*>yi&DdUbgbZk}8oZ8sX(uK2g7#SS08McaLv~VvEb}ro|w`MV@W9a+wis;I$ zGdwfwpBLR+rSI+?rTl~ZVG>&{i(?^Wbw85kHE zL|42j-pm&QK9-VUhtR5D55Lzv*kAMHx&5bm^IgEpSrU3fLMvaH$N%{9-TvEy_5a^q z^oa(auEMaOb^D&Dy6@kVoe2XC?aV|OoO%18gFAM?m9Nh~9w|>Xnwfld4R_vGllT8v zdHJ9JsZr(LaZgA(z4PDczgw#Enzr^VO+Ol!-u~Ir z>Xv(X*fzy!AFupi*&=W(H{mhYrpS$<%CVono!s#8q|V#9b3fkun$f-X+&YfBYPWAY z85t(5`sG+$;~-=Iu>bq)6>hbKMuyl;P3Bep}-ljBjN%&cGBf$#pD zyO;MrptWk*;e{3KPlfqRL#*cScl_Bqqdakizu)oyuh*2D{jOi~X+@%JfVE*;Vf|Fj z1LqtV7{tS_?z9bE*#4C}^y|gTYN30TU5;}G%lUtb|Nm=stX04UuEf%B)lpX-xSp!n zx_WZtyEk7p{@(b;E&0t`gNswPWab(NoqlC>Jv${xmW%~BLn}4}p%6nRTDF1M&Lhq7QcXe*g5M)qT@k;;yC;k6{Z)Yq-KB++> zdOcFbEi5JJx_agLuR09Vv=Xc?KEK1=t2w{SzdgKnZP>1ho}r(Y2|wqyDzfly7fhmgZ0cm4#8MkDbb51KP4x)3vr!Y ztJlBqTwQv4&59$rznFen&vpyVf13F0M%YugOZ@()t)utIZgoGK?;Ik^knnc#s`YmC?>^`Oq#=6v06uT;<2g}XzSJpG)yYEE1@xSGw?;#o6~;lip_z2=iRdpYjz zT-~)HX1dGC#S=NWmT5}H7Kcg;Gf%qHqr#~0_7zX)S=%+5wp+d(KipHk?XC0FYm-kb zs!0F6BCGg9$uaBbKY~swpz`6y6&8lf)y2Byb%(rUk3vl(w={w0@ASu6+ z$)T=4wm9@Dv%lMcV*g1;wdS6`H8pF7%38Bkt9+PN+DtfHDAf7oy~p+PZN8yLh5hpO zdz^otfk{ll&1%tp3k^*6$8WSv!PqJ-O6Weh|~VBKKb?L(ojSvzr#%W zNv@p0`DLM^8}%$zW>xs#lhnVKYJNy#t;CV_KC4%Cq}i?2DpNbRDQl(T$!$4%Cf3Zb z*kUc)zsLGmuvAMKd&%-?W#rnr_$y<6~3wN7QIYhO}NTb&2J104AN^>olf|8@Z8ly z>Ou?*3<|-a)o(hJw_D6vg>)41!;i}L#}2~4#%b+gSIhUkj(vT``rglTdVjWm{;YME zTc^{se$Q#;niF<^U;2NpmttpUXFs0QUw?Gtf@I^6uUt=7{hR;)`2V=2)r>`<;vB0^ zfy`?JAM%+KI+t@*7sN);I;B-s{QuAY|63n>K_qiGSVyi;KhUetMR&h2E75{d<7DzNp~+y^|*o+nXFedAR-iyIQZgE}@nd78Vu( zp&?%RGxy@qq`%cs-re_a%htNZzU%I1IH^8bI!$`K9STk`JD8}Ix*ACJ}R z@s)l$H+Q}(Lc39D=+WS*%k94J``&K+>Z`JFv}@@4J*%|*|DIp#K6&k;Ro=FCzgqKa zzW0Wk?d?pJS--&Fyy>8dCYMoPPu8pa6X7Xz8 zt&9FX+_Gt<)vBtUkN+vo`<1=_+iR`Ahxdi)U+Gue7Il{8#oAS`!mq8-H~kxZR_67m zx8hb;mU_R6{=J*~b=_t5eTP>UVipl)e+r4jJ z=5|+pkdRvp^+?C-X?u2sjX-+$`%{{QpSG3om+O4)1c72|B) zE#H6OZ|qjP58eTxSC{-sE(+WHtlmK}qWgF7hR3^QxKFn4WLtIXss8G|Hu3SLq(m>E?#B-{eAua@AdMbdvC4!_2J=kCyA@CUar0U`?q~^ z{GG7+)i>%xH?I*B2z~p_Q*8dfAJ^wvPW&g4E&R1@fy1BWuB{W(zV7?Qy>p}eyOy0V zdd>gHo_h3gzSdsxxf9=RyH}?(Ln}*4=hVEPllCvnSrFTD`)jXesi>^Rd}ql}-}lzF zCq6Cz9}%bYcrCBL_4MHXAG+CRncOK*e-ygi;jxeZTcMk4_KPoM{y6i8-fd|Qd#{&o zrvzR-*6*jbe4+8r|A$U8Yu=yu?fKrA(A>SP;d8FO+<&R2S2omi|LQl_W4}#Y^Y`59 zp5Id*OWo9O`;ev`uHf2b+xSQV$1wWvh3h4{V?UjLHcUf=fnk>9>kF&`dti-%qf-^IFalKz%G_D{{@h2D7W=X-1)dMMzk z;akb=_m`~txqWHPiPN%^_%szyR?p;GS;03`#xr)sKfABbPq&NaZ>~{3b?cMy*W=Sp zh991L<$lA?`9(jE-+D74p)mSkyz}(eKi``?Av<94rDRrce)_Rkw_<=bCQzVl^nioKR`NND8C_kZub*YpkCwkm0L z)}8;)|NZ^H!scstyiMJ=U%RVUtO^TSzWi9^+3e6acie+Y89ztum5>(i(Ri)+oOMOk2*>);7}ik@J2%cW3Zadl{)q zx1WVy{Zbp>v}#**RDbk@Y4+1sO*_B7hT$o5wyyF~lfP3!ti!8Wa^)v|nY;eatd%uE z`>g%DY7ZCu?)kAQAawn9Kb`%vPvosRwqL06^!sBDtInu+FwO2=CB=Jv{tB~u)2_}k z{kl-aN?OJ0Qk;Ed<|aFA)i-F zS@2@#|MfMS&IV^|*oGHSYno%{N?T5avp zPua^JPA=LQ6ROx|yzE}O)@v_u@vEVxr3sa8E_U(r7q0r{>Z9<(CAoj?!8WzS{jR~K zp=*EaGQF{A?b4dJk>R|{ZvFGj`?29nK&a`X|Mq|1z1I@_`Dyz8Kf&k!&*t{(=bAcg z)v7;R7p+o?ZeVFR?Yj2!{nV(d`hPDyFcM<8=OKJ^lKkW8?nX+Y|LcDq(oSqU&)Tz~ z+Q!sReUj3oFX|_AHDXlf{=DQH`uXF&ZMXTi2W`=tUA6f3grd{T)y^sxw_OeNJ?Z~$ znara#Cj&1Rb3fm$#$Zw(@uVTMCf4r4vG1yqhHLl#)jr|pxjZ!Vcv<@DEW0()M?|%M zn!R-2EW_*bPh4-`$0yZS{_J^PofoU_yX}rsRjhxg?b1=^Z=TdY{NZrw-8TF8-2dL+{n-EF)c*&)t8Q(%<9|6RG%`Pnf5Fej(C2y6gy-+G zR^E5>)BpH?ikiXpPkhcxUS74&I)7c3*}VIyf(uG$L*rKAK`d2@n zuNGQ-?LYs@uKho}_g_hk3Z3Dgx;(UXXINoWs7Cs!1*@j-VLdQ+e(rsy2S=^TZ!k3^ zo4Ws0-L+DCVf@CWAH(acU;o;-K68KCU)$XW*?0SVjkx#VRW9R#MXUCInt9&lzLfvg zZBZYu+>|*g%5Yk!m7&QFvAx>uj(T>}T2`(5d@Z8a z@UrfWwX0hD|L?9hzuvmy)w5Kl6{Y|D{rvu2ka^X5%71O&@5QTRKw!nIG}-XT(C4h7 zdw(r}3Tds{wQ$uf{t(g7rw>5DA#{6G==GW9dp^$kvcLJQRF zWna~`O3xv5{kM<*e>MMK4Q_i{SXh|7{_&sDtTs|U@-0g&Xzh%rtDnm{r-UW|Zi*VB literal 0 HcmV?d00001 diff --git a/doc/qtcreator/images/qtcreator-locator-generic-directory-filter.png b/doc/qtcreator/images/qtcreator-locator-generic-directory-filter.png new file mode 100644 index 0000000000000000000000000000000000000000..ad9ee4192656713f14a7dfa6410d0140c2c5f892 GIT binary patch literal 9531 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 Q7#J8lUHx3vIVCg!0PA;0wEzGB literal 30144 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≧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 F2>{paf*}9^ diff --git a/doc/qtcreator/images/qtcreator-locator-url-template.png b/doc/qtcreator/images/qtcreator-locator-url-template.png new file mode 100644 index 0000000000000000000000000000000000000000..e0932c7be64322c1fabd53b5ce7a0310edcb00fa GIT binary patch literal 7598 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 E0BjnJq5uE@ literal 49928 zcmeAS@N?(olHy`uVBq!ia0y~yV9H})VEDzs#=yWJao}`51H+;7o-U3d6}R5peO{k@ zz4m=|l}Ybjk6Css8?3DyCS?x|IILGnU$x_;*DG6_QYSB&|STrm*;!U z#_Li0uNHoJ5!feZd+Oog_P|h4-^+O%p`ok~ncV|L?&O)zT2}br0Ha*h3&ptFuc2`j z4_O@rSR8-!R{s0>yz<-4^p`s%5Bgp&ZEJ70EO{Z&&M&|3*h1&_``=zSeYpMT!a`>m ztC9|7_dWvy1Bd$h{R$jS3V)7$`TEt+#H1xr!rXiZFAvWi*Zlhob7SBB-*@*r>%;Ax zI}UO*DR7u8?U1!9>9~3G=4|OZZ0zjoFJ8Cr2$o+oX-D(HgN{|d+3sI@HkXHo$H1WC z?^{+!fq#eZ30=#tlh5ld=D)-A{`lHU{Ej;;_gA;`%coUU{rbzBcXw|y%bo3?=g+r4 zR{Pbtq>TSkx$MK-j1BYWt<$Ue^-EGlD1U_lhxxq=4-{%`@0OI6UcP&E`-bNlS7s&~D7_cA%5 z;Kkoc`?fZT7a(Qr|Guy0Z~BnPlgG^5Eb~Gp#juL~|A$Y8e$U@MNw}`?_kEf1tM^Iw zCrmcxw>{(jd=HPzi$(E!RyHZzxuBj~EAwJsbHQ8gKd<`h5Bk@AQLg(lIebTTYRg{P z?H8}#cfa1qT=Mov zz&4isMty?4EpvI%i*I(js(-J~ynpxd`3n~Wnwy!wl$9pWTl4Ws_WlR%_P-SSYqmAK z3{e05O?JWd`U#Eu^7!Q5EUHhKFpv57jm_!&zxhfo-maZ6uhCgX>ebTSN{kz$>H#bi=HnZQ{|J~}msfkDYcgMWjo7-)- zzg@mOe?sFtzi;nupU$oRw&A;j`d??~FQw&|E?zu%F<_qm-*=jG-1Cy(=Z3Ef|5GdK zQn0)6;M<^z-MRl6e*U!nvHZQ<@+~Fo>{jd&HOmtl{x#PuDW7t`{;#@CfXwpz_l|;h zSR8j8Jh*oHZL9uCzkl)n_!|5@LFUb~zGQccJbt6c+lvbs0a-Qeg$>ge zJF`z%)SZ))KdHk)(kk)!ZWowtguY(s}M&@Vadp zdaNJWCg>9Prc^fc4PB* zh2`=;CH?QmKWLo)-~8Y2_Fo8oGsW>WbHeLBm|lDS z$mY}Q`bYc!zubI=T{SEIAD?~IL(jM$_xvk;Llq`Eqso zk7vR4NA&ByDJ)#fTvA^CaiU^xaeRFv`?fK1{-3^_wtuYu|Izu1PaB{AI2iw*bN)J(fUlSTJd&?FSHAC)Z{5G^ z{|`v(??3YR{GTcF|NrRT!6%#g>x-?;-w){0Qal=5{~>wa&r8C4zCC82ajE^qySL)?>8yfx z@=^+wma$TK_@^ z@1>3I2iLcI#Ql-F|39d=|IW7gbKC3BqzBdZT#J%E}(G|0x@{9l&%Ev1n{Zp2){*?FmPSs1B45h6hitj>SzJ4cq&{v>kw!odfiM0<@ z_x-+UYIo_Pqq{r1tnBX(*W@4m|M&mj#QS$Sgsp#@)PFvF|G34i{+t<>k`WI(PWV=Bnu7P;%W;J*J)nPg?}-uZh){`1kT&OUQ~i}~L%ckY*Y_`Cks{2lhsANDD` zOMZPh$HK%R{yXEZEj;@FpO|jCX8q#DjpJW_o-e!~TmG^4ea-ACg%b{ctp540I9~PL zWsYOcEyl|$-kz^Nd(^``xZL)rxqgeKr0(at?`yknIIznGO%so=oyC20bIn8TXqnw> zCvUx9J@NQ?)*H7?&pxjIqNDm$BKB_Vo3}P@AC1p{JoNnaoA)msD6iv*|MBmM$0U90BpMA^PO z*IfU7*8g-PQ~vj^=Rdy5+ntHAIDOf^ruDOA1_^=pImjsOG8d2YDc&HzoYs)ENW*k$0qFv5jgm^jdlCF zcaD8>l27>eRkggY|Ei(h$9M7W=e%y=suwar5q70rrTfo0g!gmgH7VSgvhdQ=^Zy$D zzn=fU=eb;E&vE(xHp}&E+QQ>&=0t5hb$#9stKO2n_Wi%P>%M$(u6g|WyYOVc4JF^N zSNsiM|MAf4`a|0Bmi`(sPga`Wd+;-T-t+x`AOC-{dNuQn)$xzt|NF$d?b#chJ6|p8 z|8&3qe5JVm^X{z{$E*1-T)yvL{#;Q=zIxXDzdw%K{OW!Gf!)4hhGhTLPtWH)?Umnm z`Ui^^RD6$>#gv`Jd+=k9)ZMe*J{P?(XV+pGu`BAHHK3_V}u}ymHAG zJ~6$zW_7#hL0J-p4+9Ip5yViT`uwdYjYh=T&!w|9iFn z!=uB`HSYaoSYKo2e!P*f?)gdcA9p`-ESIaD7QgS4&icO(>mT{g`yHD${aNM9=l0K{ z`R&fX&fjxj()%*2>LURw6`F4Ia^~%=ZI-dOI>9~P`j9lgysMPlqlD|#>)*YSv^jX= zjE-aNjK+I*-~#la>EU0$*ew_KPKt?L9NQpAvSTmvT-!T&n>KFPbFSsBAD>)M--FDu6X{RtChF?m~8Fe8E@@uZW;b! z^Ly~Edg8l1bN@9mwz09lc=Ph$qt3uJAt&_NEvu^4fAf7=&?+=V%XQhE<2TA5l<~9+ zzx*M~BR5sz<1UM`-va8U;(4==Y;+d#+kWb8Epx;hyF0f6f3f*J;;b%~1XQUF!WtzhCU_5-;9AJg{%? zo4dQ$*PfSpv;6e|yKnFA9^d!(_se(L(?8wVUarqx{Y!GsvfBHm-*+_b^S*!k^ucp+ zZ0&3>-@i<`e{b)byW9Jj=idFo&+|^MUjH|L+4k&tU&}V;zmK!3X49LW{eBT@?EU+8eX0B%+wgRK zXJ_UwC8b-R&-nWN(#@NC*RNc^>>6IK|Cf1h__?cBJ+HspX~kc5$=t#r-~ai$kKZrf zyz89rFFyC~ULIcFOLr?LyxZsat9n=2?Kh7d!ukI)H5+p?lWi3+-Z5x_p-^EG~=#S3$uQiiiElcec4_UE5HKkh-OSq znYnW1%GuI)LVVpX_h#S7VOt!>+@0ilnYZL{g}1b$0L#Owh}+)-eBH0|m>kxM6L$R3 z@F(xS(804x(kWsgb-!kG9@Xp>PW$+bqp2V}ScG-+(WaY=7G(VIOU}>|^E{L?ZGy<# z`#(NgbuCg@{mXh=U@7zJyPbFQoG;&dYZdb3wZ(p=(=*QgZ+!jt`@UmooReJ-DXm`d z=>1%UJ5mRI19{(=H7~bIet3SKnIP}WIU)~z1zMsf^{vUWIKD_nZF=OK?nfIkPrRCX zV97q;j$O~r&+1D0Dmd47f{&ho-6N;4t=}$h+`i?ie*NE1SA_2NmFt{XalCO&R{rI< z!;7qDMxC4J>lUcXwQ8UBm7=eE!;K5tom!ggN?faNo4tK~wU9jtWJO1R^7go$_qM-& zZ~gcG?Z1(GWiCBg&9tU(QDot-W1aeH9%{lqEj24vZMyw$?cbWuAMdZspMERm@2;%t zg+8H|C#d{f)*9xxV`=m4rOWeH<$d@x{mh?Vx6_#HWGAcKQ*ac>+p3^WCri`A z=KgcL5@Yt|eO>i9o^SiDt=AW=3Xi?Kbi?Y{+i~XiN_3~s&s!z2E^yhS&pno*DT4P{ z1n=D1e@E@)fyC=S53`@$^Q~d#MZv$a_E$NZ6!ysb-`44x+Zi(P)GeK9$;T~T@=T2K z6WlP%a!KEYIbMQg*>g-hXXuE@Jnnw-{O}x^ZCmDF%g|aSwy2=0`N$6TZr4;5i-T7# z8SVVaqBq-5W#_q9XLPz>mae+0W-Tpx>7~rov&K20VFkNmeb$@pD5&Z_cFgSO6_#CV zg#4b|yk~hj%(D0T%M_)l%F{a*W$C3Eu}ZDg)oNwYtF~TnVv^|pBTSz^awsoUoi&y1 zYj5zCPue{aZx5sf%K9unJ>}Bn8U1pHpY%=e(K9rjpH!MB)4j-e>KP+rIhA>O8+HaJ z7pAq{oN6|Cl>z$JQ%r zYNZ`LnX}N(QZ)5P-{K$7Hkoi~SH$>{WZl$je5ZER zxkrCY?3T-hUJVrGJ%5GiY1rHohFy2w8pbQOJ~?CCy=JQp@$-_64O`?)6%_$L+#Pm0d9lw`@Cd$7|ZwqlI%8bI-9W zpSHDPPHV}W3D>(8WqOEdUrd?z=aG3IUzZArA^uy%4Hm-$+9XVe&U%QjGd5-%19Vb@0 z_1(P6lpeLZ;_l)ltEF{Va$LfsLc-HGNS}HqY_7ifr`6W0l3ymP2Odk)6#KlSTXfZG zV~e-RI@6_e^v`SxTR*wy_s6!$D$kzH@O_%GMBPx6t@D!D$$|!#mFKc-I`p?4o4GmK zr|;*?lh-5seT~F?i@&{Ld%Zff>|CtM)EUb+?e)#NGsl{dFp4_=HHn1^R{^VNp(}5Pt|8kC*H4ZTBpEqDF0LE?8suH*?PeqErxSV z5;yJQY&+C*Jk8^Y)Sc4nu{mMaJC84)Im=vS*)N#nP8WMCfg>div0B za_`cwTWOu*%ghNm7O`4nrtIdVBHs;#zihrHwLSU7#ceE@)M;}yq$jcaR88IFr-icrlV;W^ zHLW^von`y0QzD-xCPy6h4mnkMs+V_CV)Np|LdhRXwXSkKb?V#T{`AO(CY{@zDqdHn zFP7Q9Lgz`e${|NFyZx?uE}7=3{^*DLGY#<~ z78#*!8C^kUCvV))n3*(n#qFlZ9u`ie9b2DA$w-^+Sg!e5fBoDg+g24E`XaY_Rf+n) z8!V3NxqVweqclvB*Cb{}EW5YDSW+Unrm#0EwKwpsMR`W@nzieNKfaQYpC(~8yTEVR z%4JD&EHd-X8($6)@o&jl>yo9_VJ)z<;1|zo;jkqaSv@Ma;U@aW_D!G-?m zH#KyUJp87e5*0F@tn*~MWvstYk6u7_Xs5nj;5xAxd@VEL*H4a~muwfTFu&)aOy|Zq zeZo@nmzVxy(l%6|v`8s(&5=p0TsJF^r5A0vmTqubs(Wehn)5p*ite$0C0;uok)Ja$w#UH8 ztnL1L)ma*`l~LhVu2xA8{I6t)PU^8J71?SVBBh^Kv}%{r0qLZ*+Z+uIPyYC0b=Ilt z!VQ+2S#yuRl+eCvHS>zfv|HN&T%~KX2vs)pLc#ZFScm9Y?76FNRRdS6RoX(xRR3>KapDQ=_>oSvg%Q} z;|~LN^H6h%Z4s8C0Y9F z^(qy@&4`Opc~qQm zanBjGX&pVgCa6mOej#%6mzs31QE+46p2x*1%bPvA{7UT3URlwoYvR5%EZOjtV_1mF zRks8+-|Xz}Yi`|Vykw>;CK}#3leX$jPTr<{5{{uNGRbcrZ=a=_)+A^0TBG~t>R)D$ zRIRMN4`e%k@0lFY^Vn!jkMB8Sb6JFDY`C|+^n&t;u+z7Gp- z%sgqbV*Sy=TU$nRnBMvcd$uHfoW(yed~Ly=XUwZtDV^jJ^E{X|@xtA@Yg)@S&iXIN zlv;H!E_Y>I*6!;0!6Krrxz`J`=g04RRsD8-WLfxft*%|xQW?=$C(tG2z~ z5nIjo^j2%)t=lo{w^g5s?OL_{@ak*(%ujEsN=;q9O3AZm_uOUszs5xE?seT&_UiQ1 z*MaN4MDKnTCGz&vYvq&Sb#a&1eeunjAAIxe>}8oA;d|G;l`5Oww{lB=WvKMqORpD8 zp4g=GZ?B+B!ETf7xp&qFd#=`a^|jT^QJ{sNEA+B~j9k;h!kD&?^S+*7aTGZC_V4`1 z%cN$gI_qo{V|nOo#d5pum2%qy7RMiNBSW>EW-D+sDR3NGD}U$7UG=<8x7IyZyC(x` z_6xK`8|*mQbucI7@xEz2SF;o}AN2~dJiHdapuqNb^1k19wypktyr%wDP~7ID*VdZ7 z`uObnw^{pMnLm>O)iYn$YR&D<{PSGA?dL6bRh=%5{3eAvx4Jn+&K}rs%aG^sT5Zqu z&5N=!+IUx=ZCj=pVZuMTxVWc(*ZMb0D}$RRiXKiop0zbm;#%~Z(z@W68fP80-!jN4 z<5~UozOB{bRpF;9UxaDzQvBz~t+eCs>~=5zS-fG-LjJwhK3wx{O^;{Q`>RWLtxGhU zdHeL{qx$m{ILw<@DMs6#Sr>NGvUJwkvr5Jr1w}%0r~jKUHG6){%B*(k=Z*nHZb}gErJ3~h(&AVFoXSP@Q39e0LD@8h6PF~XEPudt^ z5c%Y8kiy$dl4_e-yVvZ~)L8X)TiVLKxl@)UPE0)`#+}yPvuOM2(iy&LI@<(=X37Mv zZ(6b@~^OB0Q+ut6Oa$MecbJ4c*D>Y86YEwBqWBsfB-G#Ax{#K}2(L8(C?qa9P$fxu7o1d}e zojF@W)^8#l#YEN4dbyBFrgC|=r z>7amJyJ+OqKoj0}^AlU{SEq7>1P883USql~VkXbRXj>hzS8I+ekI)l|kdSvY+~cF8 z66vWY^ySuu6I|Oa3KXB#);X4ZgNN61yWot-gi1@#8}A(_rRK~t_`K4j`y)r&Iwi?( zr*oa^&YM=}oa#Du;*6E`ZOfWTJxgA$DC0lq&~tOAO6Sqa8b5Y3{|OuJcQ1O`!=n5n z#&6GJN40eE2){EzpW0{4@t-(n{-NaS8&+7&J7Ll}Rdkv1ztvegUrL-aTqYK*qyC(8 zN2$v0{u@6;ioLaU&iFmLU=lKWa_3Ifu(0blGja{yPQLZ^MvuVHVCyyhtcE4pVY_9o zXLNj+!R~4-!RaFLv6AzLddKo39i^;*%`5x*T{eR6UI=DRkvB zX&HI5jCGoSE`M*cj14mMe!t=5o@Ghbjz?&U%;@jwc%a5{$X6ojiot8WM>CCf9%WFQ z+>&zRV_(msO|NFy3WvNdeRkaTMAq--^n{gX{1Ow(ryR(5e^fGJN$A-J8((^Kb-gQk z{LRf{de<3uw+-w{Yn~Q`bl=VqnY3f>+p{-T-(;E^)_HRU|Nk#sYttq>t@Bv9rQ!BV z<*DlfPKar2_nSO}Q+Q77z1-kMA#sP2S4i0>DgBHh}5a>Cgkv~6u z_blc3+X}O1DO=57ytOP-drfYblA~C+uGuQfqN8Hz=jN&H4_mNn^Wj%D0`2*;UL8|A z>N77Zd+vtgU5mE0PrG|j^ICD`s-?QKUVq-PnDbn$g?D1@+*ilgK2KB-URkICReNXFBu+kZN$2X@&pBb6L|)BKnZE4f zujLx~<|m(WP0{8RQ+HaEd-w3qYgUWR^jAhrZOxc)B57LKS|7de#k1m*O015ya;KkI zpSm(P&q!WQ*=E1n>Wd2^Gy*lwJia6n$m{r{fZe>-e1~tF>A&av?LQB(f;u{V!fB~-gR4RdbZUFdLCa(3LpjkWWBzxypAem-ZzG|!2r%q+@3 z#??JvEPgZVSx2A6L|w5f0h4-*q^7U^8{!ujs*>GswWxDvq5ipmo}$esuRV*@o3l!& z%p&rHdFHiGI;zVhKHre!)DOCUPicB&Qc)30y2ZhryY)6juD^I|r$cUK*Txe}U*Gx` z%~V~sjM<{}?WzaM9?m>d@XBZI&yO4r3m9%^^aSm7I-|Vs=kpWd*E-aVL&BFCcxn~z zR6F@mfIHhVjmhlHy3AL-Ldm-hy>Oa#=$4LNcE_J%W>fEQeQf23bFW@EYfV;<&$)oy zEjMmi9shZj>G5Q4lhv6#r#b(0yMB6oI^}fev*RLtuann=OZ)u3b@1$(-;wui&hIUs zo0?wTJhh_bMN;3bPb`NwojX)D_vlfJqgkDW(^-|bxY*54th4m4H9huGIBm^0g}kFK z2`hcd6dNjUxNeG3G2QR5?oPs~+9qoqxv)>7*FL*u9aWk2ljUH_)H_Zs2V9z-ePesQ zy4%OEH&MKL8khXH2W6LX1U|j~^YilIn%9%X)?6!J|907HskF_k-HW=x*(uU9D{zg= zG_EV3IIjpFH>_5VJf9{}zH-K%;4806#TLbdob5{6D(p4orlw9(M6N_z<1(!keH>52 zCTGr{`&eD{*yPA*>FE)gPiA(ucCNp^@*Mldz9X9X(>f~duqZjk>|>bOYdj@b_=nry zAI^47A9-d+r=~rhl#_p*b9bppJ9Gc>qaF5l@{G41yS9=|SdV*>>)xytCB40AQnx2A zma(jxv-lgw)S`(U?nlMqmQ09OpXU)AJNLt0^X56P%*jiaS}b*% zH^KX$pl8sD)EUun%O}o1m^0}k%W{s2wLQzTo`^BeXrHU1tt#}<^4e+NXUA3gw363M zUA^S`rYqN`Uq~^2yi)4t5s}4p_KO<@k4^uSlON7uovQPwbM}Ws-aNH#(fQ%e!|$7Y zyt{tJ#@i)2pLW-N3N?^a)LQO0app(m=#Y;m-33~t_g@MOyl9gcrfr>LHrvGf^%}M0 z2vK9T-yEBZi+|iLQ*m_;3!U>gSjV@e?E8_Nc6(P-j&sj%+_@}4>>;DIo$eNZ&T#ziz`GUVootlp@JP2Ma&VzMXSLI>w@WUdWB}f3n(EK3Mu-T568@j;CSEKkhgjQob!CY_`cP z)h6Y)3xm3|)QxtZdKuRI>lxqLv}qq)tan6)axZjg%}Hwda7QTmcC^WA-E(>7Ge3A; z=b5V4|9gTeYvjcZ{bz&j-FticrLoSr^8q?fICqE2TohUQhO5!ge&#bZ>Dkda+p>Im zB`ThK&9T3mQe|==Xy=id3X%IMlde7Ei(aei_0sdsMO8B{&yu5uDpq-wDW3Wf({y&O z?yO$luAeM^&OB4O-uoBKo;R;@{_7np*%rsmmAB7%=FUH}a5s<7wD13(Xur-oroNn` z$0G2kN}!`ao{;O+4ZCW3j;l%V|1|h=cW3f3y}zqAN#+0hy!6Ae+aFk!k0c4Y-3e2< z+I9Ky!Mx3jUY5Bv3o1Qii0fx}4&J!y_H*u^?g62quG@`-dIY-r9+%ykAR>D9m72iJ z1RIG1%U)mKQW%x`r89KaPSrWr$}D;AK1(x^NVAbrmg+SyGwZtj^jMndg02$9`XZyP z`C`EDT{d~-S6`Dh$E_+&KmJtqVCLq9nbXC# z-Yn?d`rGW;=frZ0f}OSzyv%ps9eP`~aJ81%^!XnndJNYyhX!7JEBEK1fwG=@*>?8! zvkuqRR5S-BO%(83-IY`NaPPAGFq6Z_GBmtQq>g3g|G%wTC*Sg2c}H)5|Ni|4eJ9;s z>M-y3p4JWV={JgM=Uy+B^_-Mnb@tLbcOemqK03 zMMH1fUR(Nprrt@}mF3*KbY;3P62sUM2emLRI{Wwppuy(Gd502W(i(l@@G1!8Vh1 zs(s}pm$bO2J3L!JgC-9{mv%Ls%(?mXTCKx-byb| zY`U^f?DW?u+b`UHYH=jS((%U!w(Z{1!uEfxh3Y@=>HN`h%yV-^GmGO6R_EDi4`g~b zZJDFCcb4MjSxRCbV(xjw-CetE{kwH)p;y0st69BN$lFkU(vldyi0SWJr{9XZcRhIT zrd=OjC1>V~-zt$&W;~Q=Z&q7=_4(6nzqUTFIK8t(8fnwXKm5_(bZ{_T>xU3sMm zc%x17R-}%^v*pl-g3GzWB2h(rGI_> zkCdc%9+p2Jpu7CzDxp(LKfn4F&9rD;^hN#o-tL<+dX7xfysEWinvjUu>?hOJ4O2K> zHzyWbY?KOTTAa9barE3D<;}B~y?U|j+fNf;=dD&VB0P+x%l5yXccn?8hM{TpKI@cK zui5l#FP`z2Gc}aEaDV54h0Bz){SFy>UMse|R?Ir-BL`pL$tZyqX{kGJj)bkwxgN&Z z-}9)jvQuwq(synVFGq1Knv@v6OAMaUxP>0Kka_M3Dh6BKHwxs7B9TvwOjsAC(PMf~l`CR5~R&!8V=Zl<4UV4r8Qp+Pw336I>EWa#r zU3!jvb=S^-86kG(b98)cVil$3kLG;c7cI-o*1$Zdg{EAKfAEUokJp@N`G4 z>a4tihaq#n-eG%wetx>*isWhfyv*{^w`QEpn>h2^zNJ6bDR9Uic%ZiW?b>zwN~Rx) zx64klT(`HlbHd#R+v;A`$^ARF*yhuX$2Grl_~xHgX_~FTVg9A__LHcow_d3{v+gf= z^Tg9ar#+Eoq#}Dc+tcuHDMk zxnlB5pYEqCWH;+H%~q&c&^&w5w)xv?fAt)(ug#zF)pe@yvhNW$msoT7oS7IEskU`a zTAoqM-GKZ5IOl>&N39)ew_EHFP0_OOGZ8!ZdV`?PwjIx7x;^__YPC-P{KWNmp{3Vz zKSTM>O;LKA1vm}trZ0{1Ff`qN>}GKEk;jEmSD8Kr^h`awSwyUP2h-*&(b8vF=C}ll zMokS>TF7v*(?D)^o66~k+Q}ka(Pz$|*${JY!8SQ{lg+1QUNU;Tu=3RN^BYW-C3i2e zEdHqUT2S`$3#H{!tZB}|YjWl)?v_ZdscWsuZ1qs^*b}fk&{JsMoaOsMlhU%W)LD^eZ zqzLy|@`&6$on+;|c#`_wSxQgLCR`Ov6Z+h9bIpmaxt%+|OfCLtt1)Zx$DcY|-6ne} z9$az#z@i%*=Tlc~o0T$ovc(!Xwdc<`e#>}>u}|D-(daOtb*tENvnUa-)MskP4ZO7$ z8)vTi$@5T9dy`rzI5 zGgWma-MYsUmv=qyGB0!FB#V{R9x2*ud@3xe4wdYjHdpEN488B}0xkS$vgTJ69$Y@D zv%;f`161E{w+h{!RKBb5Ms8A7mqJa%^Bpr&o$oNPI11E7ADVsRn74r4oz-4PC!0Y= zEbljg%7>lMVN3;xU^I9b^U#uG&(C>U$i8JLzuW)Hls7VPVyJJ9k3PqtvxQgX=Dqzr z;orCK^1i#*oxQ(4y?RBtO}hez(vG`t9;j)uO-}6H|EsU_`1|b(GOml?3vqQep3~Fw ztMKO9>E@MUpax9I;jX-h`(K`$x0{Jxl}yq!?LVJbd%a*;^xF59mp*KJF2Lf*vi*DZ ziZ4rUCgeFi&X1RQcCcD?$=$@u z_=QK;Tn{aOP21+HIR}^YPS6OCnE7R~mywuf(v6gZNfQJ1ZZ*UB= zx`#JPzuTgqeN{$S?{=OiAGg}(r$xLbCzBp7@l@ItqiFijb(*M-8291b#{)xIyB96Y zd=>iC13XZyrsHQ}mNQ{q@XzDn?LV(%a&G=|ZnaNnq!YK^hOL3eTNJ7+R%I;vnYJIQvpm(GJDZ{{otia!4S zt5DCm$q^?fd8$i(y){v!)_h0rt4r3m+v?B$xN!Ys&>~R3g3IO2w+}5j_5a7=M7z?cgDD&LeGWGFbqrGbapkf9 zhnd${CPfP6uTtPJ|I-CLw*61r-Zo_W&IV`SyMa6+nT_!5Kn&wp@o z8)ugWc^7&`i(72JyWp11*|0*%Rn79hdt2o}(Cyv29pAkKTncte9(>z!GC^z6 z$L;z&pC8n|b>(^=cH8%AXo#-UzHR4b92WTfh_k7nxXtT&mdWPg7sveze7ux$J88c7fXwj^R7dc*kHGZ>Y+l@Q-6z6s< z)HYhRY*CitwO5gc{&{ZtX(MbWt8Cz|H(OCcYUzfJXT!FhdKsMV;X3EXvP(Jhtd2f& zo4d4AVB$@lt#54hoscl*_t8S`dq zucg;iMEf6ntT5pDyXqo~blGy@!&%4Q6(pJRn5>rFeYkPi%80vmfBqTn$>TR$-M1*J zuDVbv3MJ%(`mUP`3s z?NrXDg3pI$FIyO6YU&)iUWX$fL^Lw6e16qSjjpDY?}oOqmno$02t09V@G>cXXP&34nTg54S()ob77n@>daBc3bXPIjiw{u7U7HmkME) zhuf>Jt}Lpon_Xec;`pP1&AdBjLS(?t)#<)driJ#+1}nL?RKrLuxZ3|>;^r2W)gF_2 zmfZaKqh^Q9xBAOk<)K&C70(Zp^_+C8dh)+$@sJg#p4!E4j(@d#p7*}KvL=O^7frJl zZ8e|r|4-%2{q>bIrdsw2r!l{^Iy8Hi^~-P}ZEse`9g+)ujSJY9N1lCp;wiVt=hZ$( zk9D4NE3|4_GwrmBTFr?~yLSHy*9PuUG847nfP}GG_PlP!ZXYf&*aw-Ykc`dV8fofz#Gb_$eLHc(?5S>bo>^t=IY8jS`}IyyFGF1&5I?nXE!8nzJ0M&w)>`6%E}`vjZ4MU(<3!a zR*Fp8v6gGs+0N5Xovxdj%;r9Sf}?D8n`^1itT`$#N*A5D^)!29)Yr01p}T#jjhjwq zI)|FLE&9A>oyy1ECW7}^9v&9BqxW`-!fH1Enp21L_opUVE!tmPDd2lp$-3kE`$re^ z?GK;6|Ie&kRDFU<p2@?dq{3Mbn~cC%=8GH9670+HTIGhcYwOCPyE6JbU5AJ88+q?Q`F% z8UOQ+j(F)Y>DY~urkZs=J9l`USgP22>}E#Z=8YQ zs;G{b_C=RzTSHnN?`7ucKNGlKeCFKP1%^8Pe&kz-|Fkv^IY5FKp z-tWA{OQ&A9%|~B-(%F@lnzZx8wU?K3a<4>oxShzkbM){09}+hu^;fOxda2j+!I3|2 z`k~vLn;VZW{k(oX|K}ISQ`_!mPOkJlzG&5%tx`2#z4<@=(cb@vUv5`>LzPUohPD#N zAzto0Go{m}diP4Zg7nU36-jLuOsHM#QlfIE$nJcOibKxQgGY^Zi&}m4Vk{0jnH;Hl zEpzsa(Pr<>zxgtr=d91a@2=dh@4~lxwGpFBOSQ{`eeabE)jzQaedkq~5FQ#H zF0Y~*q;xd;iN_L`z$G3NuQ&!i>UiX_*mQRC*=u3R#%b2a*QGtbA$i-m{!Dqi!s}P> zR;^Q8eZ%!qe9fBGyJQ+2+@fyqKYVw7^ZBb+r?mJ_vX#1Qy{7nz^krL(puD~eu_Otn zMcHOAe>Fs}k2T8qK4Y!Er1|M3UB~CF-PPjb`0dG*O5^s0)hoVD|FT+DYO!E%(!5hA zHP_#@T57-R!MnNMQoF0qgx3l&c00V95M|_IaX-Q4jllOTiC1!KH1Ql=UnMVq4_`d-haN`?hjXf&By4P=i2#`rbTP*(CqpY(;U6e^7+)$ zlE1H7Jx$`8KXuV=sfoM!^0p?mH9u4hzby81uF}(_z76;NRe~23l^jX1e7r#7@T5;x zJKh?_nRKd3&EcC};UoU>*bL9rUB`_KT8_xBEBN;?{@K*es^aDMpIkjE_%CAas)ent1I;S9js$KYkN~>^zs;c~n!>6TPe8Roov&XwtF!pDWNXH>$uFnut(gx;PlwB*UVwB=&!Z2!AvKhD=bT(CKR z)7N#XjyfgNJ@d*BrSJdI|Km@3U2Em{h6yWI^Kx}9vf2J1&4d49P3tQ^uGs($N!bMZI*DC zuCb5_hAgub4d1qB&*N;#Op)Xv`&t_d-ntLqD?2tjht{4l`#}nsHzcl5=E|*zCXD4`^?iFGByRa&^Epfs9`bnvY z5=_44>-yiiNm$K#`8c8E+@}?d*QfN?bc#AHkbdU;d{1UV{rfvUrw?5ymGM)*JkE`adT(siBw;QobS7j_-q|voV>!seOD9lo9d-mx;Sfg-MfQ^bvTygc-5 zLDHw&@>e<8bz^?{e^_|N*U|f`tz+Pn=X(#AT;Bb8VfFd1%UC{6tDa!8c6pwazOV3O z&1D)(f4=*^vs_AfX{X|o+g@dN-WUFAG4wCzzxOAGXQSeov*#i+qx!$NhKf8*x7m?8 zS*-qduKNAobK2f+t6%d$&6nF+Ky6;v!^#(GOEkJZow+_KGS9|Nep{;Yl1}@`rKJ%^ z9{U!TZ1TVJd|&Stuw_+5BkdEvypEgSdR-T5YbEG9pyVtFr5|GxF&^#)EVV(L=ef;=oASpP)4W7zpi zvHGdXr(G(Yzifl1%zwD@Qtnx``DQ=w|GRN=yWL9VrGI~{2`0S zTh`D1yqhvb@4{8rFp;N~6WEMm5`Ui3o+HwEz1JWtkSSR(j4tn%g4J_kDb6b#D6Lhr^iC_TKV7s#hA-xw!SQCxr!yRc%`Q!-m=t;`ACEJ+@#S zwSSFT-DbL|c)m?J^FgD(MDoS4Wg%VO)4zL9-VrlV*bMgg+A2=3vX&Xp2~E2e#&~= zG#eX5>92yPh?pPPnQ>#H(AtAD{5H2; z*PXb}pto%P$&5Xc!p0YPgnd~oW!ArVD|TU<>7w1WYHN+;9v+!%mr@gSaMK@|p0JYg z&$A7C?JlQDM(;3S%H->k%n457=sf*p!rAFJJAW0#wd*_2a9JIDELIz8xHdh>Ok#J5>0i|Tk5mTl2G#Vvow=k&9- z!_PKo{jC3Y>frh~jyb=CXPucXCzYQ5=h*Un2e$A38vf_s@$@OD(rZ4S-|umE<>Mgn z$iOM-XQyO@^&AfCo*Ogk@4Jq<6AsL-bt<_1_QLxs9@E@8Pd`Tl`%tO|cx&#me!{#9#^t6y2=do6wWlue$uHme>k z>pyuj)~Y>qm3nR1W8ti;Vz0YRr_OM=%zDnD@nngM;X7Ajl|$bie6KVtF+W;1|F9F! zbo0Y0Rw>V`dJ?NY{QUFd4`b49=67>?PpTaH@rQBGMw`D!RWGM;zW+L9qoU8Dr+nh# z%3KRM7J3M*bhn7pyK(mqsEOW17t_%~H7 z33$3ttpxr^`DRB|0mf0e_em@`~QovQcpGG zf1X>ua#u(}u*lP!!n+#nix2#Ks~y$OnT`)6a?{Kj&WmIkkV!$)_(T>^+=Zb-6h1{|EPwFU-cZ5O-rPV?LOVoRlCgk`m$q(!$I<;k9-?i2LzhvjL`@ZVmlcqgwllfJ5*Zl3@cX;(tgP))EKYqPmH@W#!)B1lG zpRZW?V421#C_ z`4`g`OUyHAK04{ITl3eOO+F4vHgbP1S{#2Yy4Q>4;Yow2xq;o?zk`>uFAn}yZ7tz9 z_eR|OhmM^&mD8^k%C3KRD3irfV*aJ$#%%e6m_x^df1t+hG%$@69Q* zJT>j~4*O84m1UOkTEF+nw&; z_ka1Hm+^l)?*I8A`E{=1{Qr0R126HIlui_Nt(<113?(bh2gpPlbnv>^`54j=8&Q z(e`kaiMNw)tbQz}_^O#TJY734e($Lj6BTFaZ`!lxQPIvvS*Ggp+fK;&?ATR$w90as zz(?UTQ!Q&V&iFm4DsGyv<8f-+X>C2dbCLSiDwjF4j@R;)H|;1XHdYHvE3r*0y`?<+ zgCb9(q-T)klY;x&k&nJj(h)i7=KSLNQ*WL`AwAQ`GqYMs8xv<{M0M;v*pOxBoVnk3 z^*pBt!9MlpclMPY+*0pzqHOc!H-(jzM~~j@ax?8+xy(!S=}|rQN&b<4X1}-kdDuUD z#`;YmT+Z$8>-!_~7wT({kU?;gdI=6CG571*!H}tr}yo*q}yUnwd)jWA?u#2NM`>ZxYCt{XDHmVVk~(hS0(18z=4) zSh|;4=pH-o%T|-Z`2LT-@9=NkyXoG-^IN`dD@eULZ+mUs?Z-#A-MwzlZXPsi_Ia_s z2j71h_zGv<|1DE@rrcuPA`ShBg4^0NYhLosO*l}s>q6Oo=?$HE93{!YIzhAY_3Kt@ zbba!fzi01KzbAW{cF(T9Z7p(p@ArIu(MPocRc5T&@*^w*4yM8W>VgownO+dyLuq{i{FE zuYa&0@^;I1_4^L2yFN_PxUwR&h~>_*Ra@3-oGMo3nVgU}|K`hCe~TvGIyvFy63;8i z3uekG+1cBDUslq#CFhQuz2W-r3xlN84)JU}km!8CnGH8 zS0Z{(#I@2dc*(4n%kRh-Tb+BnXJ_wW;e{c3!dqi&F7#Y}{Z+$7XPbyW(u9X*l{<9#ea=MxlyvMeR@gAkuvrb+uF~h zX`jWGyyfU|vXPw~|*Kh6nvDW^N+4_>hIlpJ=>qVSYs=y0*s^}MId|*k_U|j3eR6}R z)sw>)Oj4e8Z1xo1pMLq}feW!YGYkFHlFK$L+H|Viec18zky*L^@{}gSs@K+Y%4Ua1 zTdOQ)G`cFcef>Ghd%D4Ej&Q1!@7(iSYx!cq<=g9LZqAz7je@?HrzIigDzy49$jvoPw4qxB*wc1Bp?Em9-m5T*k4eq%) z0U}Q=?FuK`c^ywyTdTBA+Wh9XqbuKEJEa;;vIpWd9Y=De@QT;=_@ z7u4^1vSZGH=lqk`P01)>>uGO)vikU)eO8O(&P+O&>Uq@ZNAt$t$;&PaPl{VPZL&re zSKfKG9WSq6Ub6o`XD_G^I(5#;ZLd$hzP-(*>9l@LZ+_k5%{70x>kpXMe}4Rig*V1Y z_fV+F)5^7llYa!6sx22U;rnhW=QopwpW~En+_q#H^Vum*c`|y;)7L%Le{(tiNx_bu z*UMwYoPMn+^N;Lfd-GP_&~k3zsplE~>Q}fm%f7M2@XmTO_l(7ETV?6ai*tA~-^v@? z?mz3P?7wW+@rpZ3Z_e6eCq21KJwyMTq~8_wPTJG1$3*Uxv-!aCBLCTkKVes#Ay{oL*=oBK|MHnq_CL9T)G zUI&}UM!9SXz4ce|ZQ9g=1GnC2mG1udlX*w(`My#4&>`>%VOR$p=Xwde}p?k~S{ zwSF4R`ZDp<^G?=1H|A;VcF*0lmf7p5O`W&Ex$qZX*i62ASLAelX(E>YrtV)>zr zU5(~J4^~(|c#_e-;rOvHtnyOAyYBs5wQeD(tIP9h$5!b{^`B$a|JMGLd$nWd#6u6B z^-lkJ;dHb`sqp16@vy)t&+~(ipKZOIsvuX@^|fI0_v)w4_cn^O?_Bx#SwUt-+sS2S za}F5jF3EhfEB>*sg0A_ad%rV}J^Pn2D`VZ+*QJM#Y|3pB_?~^bvs_~Fy4fI0&%D~f z`q#`lGkELXAQ4c(UU~8Q4$tDv=X`yOwZMh>o)-ttZjzsw7XX$HjC-J-_v~x%_V2$O zpIC315-8$Y8NXtwT-TyMd)UqIZm?W8v*vlQ)X5pG&h`8YeZ5*<9((&SVP*F!jZ^-O zCcZq$mzhJvg%sERo-MQ_bMJRm`DI_f`SRvVC*P~LzdK>}$4h(m&5!cmY8K(O^Cp9$ z&sH5!@%EduY4!$B7u|nHugCs*u|4KTjhWxy%seNnw(5TW|L4B{*n9r2+RIB9!DAwo zZDyyBePioX3tD0nY4lQLVZek0m5!%<8?Rd}oW!YoB>3GUliZy6h60nG-<}K4zg3s< zo^&e3BmI(#vLe$%0XhE(fAS_ju3}qhzfNXStD^3me-bNmrn#83sQMlWo-^Nor7gr* zs%ufx?P$Ma3v&xG%W{szf7am37OdmXov z@3fm2x4)5Z>3)|B0v4sr)0f5fZ(J9z{_%PAo?j2I?~ItYDM~lv?evpZy;T--Y8_X0 zJ1e^+ZGrUc>)HIR7Meab7lqUxn=W51D!$#%a-EuC%ynHR-_EkXBL3G)=gjKU^J$sD zk|e40&-cUaIs5y(#XX8Yv-n?rzjuDchsw~s7Op>k^5-o}-TZWu<`Un3Z{@9j-a5YZ zEbnW>{{KrCE^aTX`PBbk^#8;7y7|#-e=N&iuxmrtBAe?Eo-MsGb92V@i}oeWv;D+p zaRlDc75=h3qtETl(?b%M{9kT3Ut+c}&TE0>q=1E9<+~E@*el6=QCPB-Gq2I)X_Q>N z!r6oWIRAc}RJh;u(0gYOVdohwr*qHw-TslEQ+W90p@&~4Xoh>ZJ)Xk<`wRbPj_ID8 zYR**HE#JDoIdi7RWtZ}unlio-eo`~cw-+q$dh^yiLq=|c@aBuomVMt=yBrEUrOy29 zGv`*PNgj#wZ_EGYS+6_W#n$RyO7FXra|`Yscw8pj^S0p5OC#z2jJMZs+RAN;=vkTC z^h$H?qCZM3=BGF9e7RxeGv9yr>t8)EE@wG+++^nTphcdupQitxvj4|1^&8%|GhRi{ zTcly%`XJ0=X5r2^lls*=)tzpH&3bsW$I0aI#{v&sY4y<81>0s_dZ%Z(KPK2``HQuA z#`)Vac>Pz1FP;&U#4$M`ssHCLU!9HT-(Fv5u}U=4FTA9@I3j7Ynr?*6!%x@dL>c)i zi5@mPBy;YW%(PEazV9yiUi{*3JqNekTySZQQM?)Ft4AxBC5gKJl;q1>mRfu`(Kwgu-|c>xJyw%< zlzdMXzq@Ojoy+5I`JbM~%RLs1mdG-n4hoEwm+pL=!(aa+^xA3F#pm=A%bUKvoDidO z_+x@YuKL-$|C7w~=U!+?> zam4K6UBSs=qW!50q^}1rm9K2>eyX|IbM_MJGw%wH-1F=ER5$%xUEh;;Q~2-iO|h6~ zFyAlp$zh44%YnzEB%(YydN4d$@EV*2{JQ^N#FEJz?h}&*WAD< z^WQ%xJDhmgdcvQ0`#aB)pR@73JsB$!b6dao&#~)2eyyJ`v_%FyXK{I^)?2-ZuURLg zZ(H!n9zJ7WF?&LPN@nlzH)5Br+*+<SVioS@_XO+iRE2?7WqC+NV|(>F=1?a#~jJ+^&{wb1h0_mm42>SaPb)(EsTI|Mv#| zo9;YMx~Z1%s^U=Mp}OyBtFC;RWNopqe#Y@DCQ8-LdSS7L>?WUjvbg5Y9@h)$!e^&x zK1otJm790ha z=C0LEvq5G4_T1^S53f2||EsZCf8WB#mvVc`HBYRz+;+qEx5@mnQ^+!K1zzx+&l z>6u*dg*8*3KGj`!?p%iabi<_z)q9>yy*k0?h<8=_funDu*N8hCH44m}%hnqul-PPB z`}<0jJv)>|cP(~4Xb`<`socE@C1{Vo2)mB&7HE&4NM@7la2 zf3KD9P+Ru)=8o-IsN?W&u?F;o1RzpVYjVa&TS_T>FwA1k3X)R{(IA}zX4O` zzkZO$G5c5FN%eI+d**!?xV6T2qxV%)$G|D`wLZUP&3}LQx}4qtZQs}X*w=5CyKH-` z>dF3m{Z+reUB6quzWw}j&i5Zb?B~3!6qyrnI=w*plkB;l7q8pY@VzhT(i z&!6+POqcYYzVRo#)FD8`wela&;RC50S6v+gLkfO>G*jo;>gEd?kr#P-lt0hu)(&tN z10)dl;(^){U#mPriwP1*pT94UmdSZkvg^XS*CL=s0jPz+m3Q89M`qjE!n04_|2uQ= z?#zVKUqwK@x-}ZR&x$P#dGS)(O1o>(pOzMZ+5Z-QYwl%kQ@sDVr%`0~InMWCO-Bsm zzA%fPUpn>5ZS!cG7v5P5BtLbUn$}BQX=8V-Y;2lsk~?SD*|{qp?EiD&;4bx>Wwtwi ztkW!w+xEKVU-bP)XB`D|ZwGMah`Lsu)8Tok78%mjdZ6uWCe>JU|9k*$BuGnhR&mRp}&Je#l z;d^zXm!{yd)(Jv?cLna5@a$Q{r9&pVJkAU5bH^{+X?eW*ed?_5@tZm4iM5poYs(qM zueFHPdnq6Kaku%wkUQ0H_cCP8`rfa9#@BOF^?$W>=Y73|ojZO%|9;|UOn>!<&l}(U zuPyd@eekDe@ZIO4qIcf0Zjb-9H2%@_x|h>`JYcu~v2ShR?uQ$G-k5o?{`bP>hZ9py z|9tYG?C`ozC)d|a4d2ab(hlxK{eQ5GQ-A3_&F7D8ZTy%MBR$F|T=APW;e7vndBu5W zCZ1gKvHA{&Vj=sZ6mC|b!2iw*kEu=YnC$0Tc)L#NA*}fG_ae`AFtqJGgVED^YPdAj^##24%_iu_STuJKHv9I zS^hawDbES#L_6A>BDVEsRUcea?Qms3r~9lAfs*TX?tL?%H}$3dxfya(H^fN2E9k0O z=%DlBpa4_iua0G(o^0Z*$>TmPtt4_|&TM^&gU>%c_{!d?X8gp+lj)zr#*%qCMs3H< z3|l(YXDEbg2yp+t;LG3WFvUg7U2X26?A@H{**(v-zZKOj;mYsg%A5UQ+WF@+k7q%W>J|`kj%wDGrc?ju>YarwGF&!A&tTtY!@8$ejZbk( z$9kANTzqG~vAt&Eo)YHrwEmMTyw#>J+`r>NPUW$xYih5`Cuf#e?zKs;E$n_**IBdp z@Se~^sSze@+I&WwukKntU(NdZD{J~|W3|o3dhwR&`z4NjQ_bXC)}!vN_E>LW$h?a$ zbMxk|jfjmY2+|I=mHYg#zrHEexc#{PgqBZz*Wko;MQQwSTo< z!eZ-jlbPWMeFLY6tL<3&a=ly1WL37)s$Zw{PF-OrQKDgbYtOe^xyKG$hOe)iax$*Q zca9eg$*7S=d zo^P#oY)$i?)yiPL)nM+^uC#;ac_q_J3a5u(Gge!Dy)xBw!M#_TrLJByZN7VP*5NIl zOUx1qb~LM&F3G&dpV#dtT3s!z9F}GxXB4yU<@My8TxpS6!EJkm+qyNUF6q7OHOcph zrrei^EnYiHCLc>Uny7X%uKq~gwRXXEo9*H!6h$B5XZzy6YKb@Vy_&~jiyzLpUHz>bK|}D`T;@M#sF(Zx&fzbm{u{azf6kBMAme1h#GvDrIYyYriYF-LG0@ zQR1VMEEgw~U;gpeYR6Y=(@WO5Vrz}`Vgp{!y|}W)u*GF^+^MsilfxvhpEfUGx%B4k z`#}3w#`$jxE^FS9U1PCIB!iFriZP>%l3TUSqIsVlbBRR6-dz@ZUa0Fx$I(M6-+t@N za-Fj)WqZAw@q4wM=7|+Ej*IZKZa+9Db92M%W_@9;`5Pp@zwn*5#hWp1-%F*P<|$Tk zMzi`fTzvC(-TA>BSoGUj>@1V{9JT7j#(kSKrPd0UO|nbbawg@5+OusZOm>w-i=O&j zoTq>Lh*F|ZC&#{!nI|(GtTaA6;gkFxr6O#2Yq90e1;W!8*71vq-ihn5%A57jZH8I> zr%Lhvzjpg=@)U0W_HMSY-S@NktIl$EE&3zUJiFbg`snQSb1z$FUCcA{aP9tbExG6= z*W;5@itZfqGo9hr_GELU+v;MsxygOAelKx)_xqskcKd`Y_f>;m6<%AtP;%1UhoXD4 zSe$2ZI6v|Yk(?iAn6v$b?{l78p-C&bE^k)d>o-6A-5$TyQ4dm#679uPqK~}PefH-0 zVT)4ztLK`&)_A;rGQ&&Jvn>Ba$IydUS%2Z-wUf^A(TJ z&6>QJuY0rU*&vzvRp*knE~z(4*eNr)yM4u$<2uunt0o&Sn_C;S)9Uiqro8F{b9b-5 zd`9i&>u)QT{GG8;>h#Zsmg8#G7AaR&3h_;!F?X(Ej(lNBfZ`M#nd)+%;_j>K@?;8niCX5&E4ZNX;Jb&(OXa{j zPk$_MTpOYy#UaLS($vL|Phs1&rQ=C?=GIwLf*eZ@A1HCxFqY`cx$vc~uT*~|- z$89a3KGo|%+3h1-yWfNs{kWsGLsM(VUV+j(R=g+wfAUp#5B+>{x2OEfIMc$FOnbT( z{n?V;#o2gz>BEvt3sYw2S=USNoOx}ea6Mjc{p{`Bi4RILcYJaG-NdDNv2~}Wc+uad z!5!^hxp$<~WA?`hfA=nXv8(U%u5+^#%~kDrE+5*o?!S(%Pxa>#|H~$GX7wqqEw9j* z4)%(f)u*?{{nZZ3_4bR?JeEA&ckkt@`2Y68my48rD{E^W|JrlEC~sM-z^7b$Va;{t z58wOZv-i8*v%~hznir2Q%jsD7dPm91v@j9TJ8@I2^6b|88l~CRiLV3?+jnv0=^v9a z&%E^_Yx@MS$f@%V1)JX-f3FY<8T~o<_9$oGved^PZ)B|s0X6SLp1Sho?Ml3SYwDi| z-FlxiyK{YGWn2T}KHOazwCL{*-W%r9942=iF8BWC{#L)Jc-K9a1!C{DK_iT|J0vfu z32pkZT7UPC^!Q>y&Pe}t50`0lecIP%ChTwEw=iVkgzm@NRNHguCSN2?s4@8~!#!g2YKn9%Em4^likzZT5()D&nGT7CWAgKt?UOU%+sf{y2VnH0wE z_T^}~Gv(+7UgonmWNw?t+pN6YdSt?+f?Xa)8Hp8#MZRkv*(=ARc=7A&>#@@rF0Sh@ z-7nKVWp?uGe0}>xputxEtDmx>H-pBvzVXkg`F>d{ZvEdDr*5I;#y-^_wc>xQUH?h_ z{x7cmHQ#;hen!`y_`dI_Yt>T*K3~zNp(0NsZ4mYgeH5HU#kQxVv>t1Z+jsKxEZ=oy4!Y7#+nYna z^LeHhoAm$gd7iFw%r>Zw|B~#&i*t+1>P{7!dRL{-54Zbgc`s(Zz;{;7cW;G?XIBJ^ z9y{%QF1>b>q4_(PxrOCNQYw#qNa5cAW!I#7*HRfaMqdoCAXdg ztNp)kU;5$b_4yZ4?g`zgu{(o^Ls2`Du6Uvc+msug%y!-FeeX zo4rppr>4yLd(m?GV@3Dl?J{rDKYFcP79r}&y8XM@oh6yYmlKOE1^!ImUr=B-VaJ!_ z?AzDQ&W!u}_521Kp3QULe7<`BuTbfF$I7pob-%g8TjI-BfcnUrdGo>=Zk=p77{|5T z*}3>PhkH_rSM`@?;(LBRn|&wF-@+ziL$%G5H{V{@JlT5Nr`^{`QU1^cLnc?h_xp~m zy*lY-$pJqz-^I4eg8Lq9IJBkBIIEZKbE0tnLxnK;3)%9Q-t=ZpSKhN_sUk1`G=r68 z*JZ?QcDT$sx9ND?-@zDORi@lat=+b4+xFux zcl4gW;_=R3V%xVHx%@NvvRMvEew&?JWT-#&pK9}6jZ3EtETjX^gh-xwZgMH{P^;MH z%;|ftH9Yl9y&O?j;kSCyqJY(tJddsXc5cVkR{|SNL%oARQ#ijKY+*S@ zv%}f=axd5X`zY`5sNl%V`#Zh!&AU8Ie_oCM%ki{f_N5nk`#=5aI53Ud8Jt)@2Adz2 zU2G`m&)$ z$9M5!V?(?tzz4edY>m@PAE^ps2^eOIh61TI>4c(<;x3s!G{W&zd zb%NTmy_tLTmQ>nW7yM2CtebrQTk6+`*YC_O-LNjc{JjMK-gj0kUYGamPxOx4-)|x> zQa+cFf%#YvesmDExuLH8!mrkeg4{V_fC#k-a@O(B7JAO)T-?=F>L9-`)$U%II+94AMLoW^!mG9 zkerK`u>YP@CAH^nR-OI%v+G_RW3aKo8Q&GgEtUIU?pbD^A(B7q*|M2?_GPNo>#yK+ ze&G3Zh5R&5FJWgdlUR4-C(R9&wQJm+mp7)ZxE2nY&In#pD13dcaNJz3f4}3cB1&1K z&z1i?roHD#Q02F%TCvB%Wk!|Xb`?L{%e=_0b6K8U*CLzbLjo+9QlFi+WM66VF=_VE zms5OBc>hW```rG2;LGUm^OvuwEw1ng)ygu3U0f6;(eCB zJ#*Tjia&xzKTYHgAK+2b2z~u#i4w=&Uyct>-8k%OjpR3?f88$KDlg$s?d6)s4X13 z7t8qjTh7(9j6SRRe#wfj=PDjw>-t!8HtB}a6W(HjI0NZ(7Pj*PPqzy?eboc6r&Zk% zIqmGU%W8tAKY#Bp{4lj&%3`a!$;|x|AH93N|BUur4fAB-eV_N*KRA&;VgC=A_`i>G zl~#qXT%>W{YKN!&(#ML;k8Rq#kH7q~*;=MJLNCDPh0!binZ3JJk}CPEa-;SNetyg} z>wn=v-$&=S@A!SueCJlXWXs&i9^w*xZf{(C-=xg_x4`@DjR;FOv`|Lb`oZ@7pIFP9&3Zrkf1Y|iR-o$ULU8qCvg73}*H!n@>@pwT-*xh| zThqC$qjh?o|0>Sx30}U(`q7)DlMD8`ue+6WQ7evpyQOvB$+NlQezEuJABpMAD=0Kw zD$yy_$0B%8=JCrJH313BzRm2}b%ihLOrQ6T634x}pCs%*mSMJZ&W4+p_PQt={+TH9 z_T!{I_Zvks4Q9y)t>vFtntkH!^a(T7PT!m``QVH&!=B61%Z)9U&iW$gx3nXT`^&ZI zU!*g2G_MGoy9OS7`|;q})E$M@I(1)C#s7acpL67pnBQMdd540}Zf)jv-=*hlpWN|h z%KiU;*B1yBZLWW9{^Qp4Ji##kJ0h-?$Cil9_{Z}0;H=FbJ6_(@p40FDK~k;t-K5a< zZU^F@UhS`KnLL+aVbT1}ew@?u+rPffFEE{bL7pemoa@H7wB?yQEG(<9p;XDD)IBM-097%lb^DFJ|}lDVaByryw}vN zk6fzu3CmTQXR-FC=I4t&SF;?q&Pm>Hy*Rq_;U~2hXTw5_1!sM>ynJxR)1$2IS6P;c zWX%Q7NB@XhYB&Gv{JOZu@wK--tr9n`wLN=I&wl1yp_3i_FZ}~nhH>o7ZCWWbHA!mw z!fP2CU7uvkG&qE}+k35yN?w08(L_Fw@8`$X$43?`=A3p{nRq1K`%S_e7n6<+e^rWA zvwGQjkI7yAv)7kF?484u6s@-ByQZ{H5&QPFt*L6Khn3h-`MyaVEEAWx8cb7rv|S*q zA!p~oyuBVbvJ*XK7wqy#Rd-epP@2{A(2QqI!K_>N7^lYYWJa+lc`7mLANnTPx%|U! z)_oCezwX&Rb;{cO)4SCS6o;OrcW&{X{Qo6X{A<(6X|G?}HKayo%-XkdVv5%sJ=w%t z9L~pAaxQrr23k`4{L2&HMVV51caO+&Jp8^(&}jkpdM<~oUCik>IIb+in#uijQXy&bmgJG zMH>4f4*G806$Gv}0}nz5_gz`Hr%T?++3tH`{W336a1|T(<1D8-@5%drwsmLydugt& z(Y0vL{@KDMF}o_sp9`Xz1CZ_uw45kAy6vNsmm z#~a7<%#53JId|HJSypWmBrdsl2s`JL&FXr+pIg&B-e~C&foFgJ>+4Eip0eYNgnD{; z#oMBj89N>nnI@?}I(k7~CfGwbGpb)E_|EU$J2l@IzOQYW@cp>N^?I`-%VauC&bIe$ zw0ySL(8+^Gv7r63NcpE9xgSqNC|;fH;2L=FY}JKNS|S^MJdZE_^gO;qkjt*}aFciO zM2nq|Uf2H#|MOz^{=PP5E1UNHM@x=| z)84D8MzKY8R*zn6IGj>@G^@nri1x&L7S(e#PhV#JeO1J5$AJarsoVBED7mCA?Rz<9 z?=khdugN9ej&~liupgFu{k7{^o!sZR2O%O)#m#rz<<5`xo1Kz#IpyDJ`O2Efl`E|a zQ?33i&aaYus-VH4*R9yy$?Sfd3iqk z$|KEPuSI{)l=%5rv|LYpiBhHCxiFJYnOyA2d2`Qae7|;QpVjhRpc%p7Q!6#T-kX$X z>%6GuNRpY#!^tV%mfzWF@pMDn^97M=Z_Gl|SzQAU<^~I;oX-6G?9v1Ke>pzc$?{~QPgZ&Tl_y6bb&9*Zyn_D@{RM7Nps9tIjE2EJo(+=xztqdMa zF&if+a0+pIzELD2RVP&? zRqaYwO8eDc`Ha~^Yim?y_oSj4I~zwP3ybe}SfBrUXZif^Uhh5szD4KgwpyeIA2}(? z!LnTWPKo}>n%+x6BCjtPG*`{ox;8iL(c~r5PK!KZJX5CLooyP{?fQ-HT(IW4AdM%U zYRe)c)&_O3OI~7rl70J3@2VS5zqdvwTJ^lWW69KMI_s;@)?TsA`xJf5#EXA&Ev;(q z{hAsxtL5q{rA$Y$>(U}=%si5gTwB#ne$dc4&rmLJPq)dZw|Hq=Oi5JYHa+ES$Ru1mrMr^pmO-2TDW}4@Nqdi+`lMqQD|*OR z;YY1_-l{YMgPeke%RbcqPwJRk`ZRd4cj(EsT$}UV+wVVqc*(|lZTgRI+xMNk(;>TB z$L$Ua)4`Vtr=^sGBg@LNeEQisbV4)o)(C#u)vd4oQ(Y<;WyY*Ag! zLcu=^4Z2@Tiv%a;^a;F{u0C^L@lM!xzLolCg*bcyZr@X!JtHY^tDmW{v%#b#x7JMV zQD2c`?%~^SXu1E~C#SBEbuOy&6>R1v*4IxDshCoe+uIR*baq7g?mZ29l@VDc5qCpCVRh<1%dj5+yWzq}Z=$Y^TF8=4w?e#(4 z>=N6$FPb$v6wJyvv8nwHVpA)(coa&fBn!|J!zd|rvEPYw^t^`r``A$xmjb&Vz2xDw{)z88y!9zWzpQS zSifJ%OjLCC!}P@3=1Va%99Os0%n^vQ)hm|~T(w9>wIY0q^>Uf7i&egsPq}_uaKZ80 z6R+}LzuBj?cXQ7Y8TYAj?rXB%*S}9brTyw-_S++DE@7o6Z#5YA{yO;S_*|Pmle%HYk2;?VTf>q8u#oi+nrY9g*e`{IIL9Wu}E1Q{#jG$FuLGTs@$+ z)pd@AB~#;rIG4aax79~B3UILO=MP+}}JlRBABKpz_IUD_N~4mmHG|#mnWt?4O#BJe~Rf|`Q7W88XtVOT2)f#_PGA{ z<-~dWb&{vHR0wmh#HU_dR%^oGczHsp{NzrSi-PYppM1H}|EcTV$N!ofTl(K!m%V+- zFL}4sDvyP#0(Yu|mpYp@Kbmx^{@+c5{`XsT9qnub4mPgKj97bkjw96`sxAg@5K1hDq~IOLsaksVFI2MK(HDL#u3e zi*Jyh+u4xNTCiN`YCE=~R$-uf#akWQR&snv(TY@id`DXUk zXw$82S{G&gLPAB~F)$t6t8%B$SUqQ*=AU?b`DaP7X(!TZJ_XNMmRQc}sWa`yjh$zH z?zLL1?AN9$8#^ba(V@WW(Ajl6W<+LhydR;MvE##!Jr=Qy$CfYJ5wrM-R;ZXd^NqJw z4^N78duJYVl6y0$Nm)X1-;6{(yT-#8`A!6x%C?)k~EQk)NXTW0jA&z#%yh`VKGk9wzn z-=a*vLz6Y9O?xKEyK93r(~)C++f0ocZ$C^_yZ+$MKfU6|dLp6D(@bj?dz*Ye-D5qc z!hLdxd9=#08kXZ~o+^`D_OMkcxLIv>$};NF%C1m0OiEVHnABx%bl54ab7h7=WMF_S zi^`-cv~uZTm6aF z)fDMx0n^OuK862za5cQ*?cMnwUVX0qu|-iu@PUE=hhN|hUva4|*Pa`+z4chtv!*Zj z)=ERko=rh|#`4mN0&|z&S`n<3AGBValeJ0by4g*QYd3CWPM9a@Xlu0PYun{3=EXfN zmu2F1c`OcEwsZIKPhT`tyfJQ#UJv zep-d=Tv;RI$xFO% z+f+OiIz9Q`H;y@L9!ke9xOVFC_FEJ78lF0<_W7g8S?=jKHB%+#&R7&ta4Rby^Ic$^-{eywJAOP^d`0ZIfr;x5 zZVs03lL{_>-BvJL;_8q3ddo9k*;Ceh^B2pT<}vU3y}G%dZYb1Fl-i!R_uQ+NLmO0# zG&oqAE(_)PsZBGlc=1sC&HFc(H1vc@Tr_f~&E#;4)ST+!*EccZ_Tz=8cZWz<$5`A@ zvy@Ycy_K{&E=AG!bi|3famLFsDh_`RnH}jg(Ik4Usm&<`<(FJnW0;n!DQj9iESY)s zkIto!TbAoAbf126<+FlSW=b!OvQK|L^R#=)^kkm7!81-?UAgXvgv_OxtK~j@Si1Pz z8xv1Gy~{Zw1t*(Z#8yoaKmM^#Rb$;#4vDaot#7@b%Xx18et}sg@BN1D^$w=y-R1_~ z$*X-LWYsL$h9jSfo^DHfAk8cBSLk zf+xyPI3IjsJ2_R_=V#6hk@g+OSemL`cf8znaKl{%kt;vH?he~meYNlQSIyUV`dV(U ze!s^v_s%JYEl1zpULV+TlE+)=lc$2foM#=k*{rXoHt~t;^$Yt-r`N8&B$oHosQ7Z= zv{ThNVrdscc;hd$AD2!svFfrn@=N?}v-PPbPpG9-VRihD+_0h@CejmIwYJ6xE!R`l zl-k#sx-H7JX3|u~tLJOh9jK|AnWoyUcw6FpPQb}?#?xa{a}C?BzDh8QUbaKzuv+Db zJef;pe7E0zT>fxoRNC%IM_1mGh+PvH*=1-nby?6E;S25kEz#9S)@}?|dG+nVr>cvg zlBN@uT#Qj&a=K?p_LghG8O_WV%ffHQoSqaBmufm&WnaMaf@Id|>mGfpENDqzk#9DG z^EJ=vx?^tcA6pl%xoS4!Q{={zkEDb--bp@8n=12Tk5&EWX;b6(r5%2K(f+Ty&TWJK zl!}+t`=9vV-+8v${!j5b+ntTxl0tC>OpOmpuJ2fzw;^;+zW>xLt}d~qJAzYU**mLgkt=r4D1}2+MKJxn0qB12-D`WT+QsEkl2skGcDorGcb{v8q`?s5U z*EH6qN)+y#5uvwf=XT%h=M7bQoyVn@Z1~Dh{kkxQkJmM#kAvlVTYvO{^bg|ZIe+fn z4s&C&I{fYag^HV9mO&4mRog##$zFakRs3T$PtGO|KLHMw<(aIH4m_1tl=!eH`)$g{ zS?`Y73mth{@R*n7<1U#KU48mC2Xk!vR3sciMdmabT>hvs`C`FsHfQ4tCd`Llsv0~x z{_u++58H)O*>-b}1J7Nre--8yI{Q@JY;r=GTHE!t$|tSXJ&?F;eA%a`U-&~+!EdG? zwRs^|54`1m^u6*z2(PQ@2Y0oZy~jD(Yclxsl^yMOt$X~XPvFDOi!ypnkAsgWy)|1g ztMTC%K?%+W7rrb`FqA#}P}M-_K&C~2DC=GEM5}ozN{^hwYL;|MhlD+TakxyT(QuhC z=c0)MZL1c&kaJUie8$iHqlHPz)kb}rgDECWmlZ$xakG5y>5s09dzyYd*QfV2&rN&h z$D%VAI!x;R9-mSda`=jU%aRv|_*@hO=IpBo4t>J^W6Mj8uC7&E|7*F&Wp7%PF#XBo zO{+fbvpvqv(zQ%cJF0rh>l;=se>3g{hhCkaBDs6XoF8j7yP9HyHpol<*Lw9^u2_DJ zv-`CE+l%Mtd}e-XA{#l)|BbiZg>C$myYK#-SCwL&v{`$HQt_2pq05f__2??QVkhYt z*uUq2iOSCm`M$o!MH+9DmDcGtKDZb4_*v05*E{LA8QFI&OWJyKVu;}>H31Hmcuo^u zPpi9c1eqEI^5R+L&10Wvih>$v4hlQWTV|_Wis58oYIIN#sCn8tdzIvl7`BNE>coSW zg2gykoOaY|9^`D@a%%tIX;Xcik}qia^*Jc~coo%jqN`}j7H9WKPbdFR{rPy#|5A~q zd!Kp#KVq6F6gFG-_VcX{@xc?1B-J-MaBROUl-HH@pg>~J?mQ+g2jZ0A7?Np@Hv@R?6WBHfbuYI}OU;jz?zx>|Bj(vZloIkg8^tKxE z#Qs>s$>OwQ?l~#*-FN(U{5kym?H~X5k)3T@@4tDvOj=`ASC&Pg#hgbiTr5q&{WG>$ zGpC%Iz2+!$#Mi)WauqX9)o|Rj^vcYhof2?R>-7sh^ zV>_Ox>?#E%GBC&__K5q)h4?KBx!R@y@oP=GDGw-MooOVqr zCogx?9*f>ZJ7>g1E#12FbeiSqj`L?TY)*gsr#JPf#k&I*JAd)9Kj+ub^?ximJ3aq* z!`ipZW!ubVaQ+SmnRqx-LEz9^kx6Ixqj=qzr2fARKfLGPi{&aa!&QHMWeMN^z4+dr zUs`fsA77is!NPR#dAE)x%kt?O)2~OISrer3B;wrjh%@3V*ZU-WKC_{;!XvqM?y-M| zbEX;VtTDZL=6E4%lF01YI>%yeq{xN_7PKTkk&@2Y`fAOYqlP8oleMK|?%Yo(t?lj> z*EbL^7Vy;%I1_%;zJBJ{D=Hsjn(zKn@;mFg=fZ-(uE*bwdMpp0(V@R#@BV`>Cl2Q% z&UQ-_Ygg-D!ve}1^Vb&yhcqkBK4{Lb`tLA*dt~edJIhlcQzZ;0*?j$#E%PiXf?ai^ zK)8ay9II7Ii&>UygnzqvKQ{e{wb!nI#OEJuPABVqxxqDEPiE7!__WN-i7#JziiNEf zdBj+?mTl%Kv!`Dq!ge>kDiP-RVJN~r&tuBhXL_r5Z`dl_vk9t z6W8@VpZLkND@A!zz|)ED`o^z=0&9$O-n^MGvr|A$URi=`;yT%aL}Tv~t+U78iGAGA z7#p_nHRGkFT2pi8Bp5g?+v=?8fg)S~#N z(A760+Y;xloT_#9nbF3Rm0{Pf&xky+IavF_rJSDBSvew;oOW=6N|=3id11SoyG>jF z|N5+0=B?#y_V}{3q;KMlj!lLCn6giDY>I8!$Ia5De}d2Dnq;s3<|$Ig19B|fA3rfJ z-XUu>X^~KeZou6;X^Z!G-FUBVwA*RvttI;|CTW`Xty$sDzd&kM`J9q{2d{k-d%9I5 zZhBV^%S`<%H*e)_oHXaigt+2APp)cPwBoJG$7AlNSI=rw*?x54DlK^*DSZKsmV)0lHFu63wwjtM z8u>S8kuSJY4Juvr3wvk#8o8vbfcCR(1w*x5;GORH9VgwD^EPGG)Y#dB%6SeJCdE7Z zY96X-v#r$ZJ^npqjvw=GB}l1W9Bw(uenR<|@`oA%4^1YWxF0J0wg27zW!-x&G97&H z8nQBJ!i+0F`0clR`lT#1=~Lv<*^6b@s&;p1HadJ@UHo#zu74}Vq*pClxWa1IJBM-$ zL!RUBb#956dRT=oo#Op4&}7Q}N_!KL(BE%e9@@#nzVqKUzxExS1reU##z%F`D-2+ zl!$EIJ3nl8%c55+R(1JK+8`@Ce;e^Q-^Re1&mIRQ~YKlSVF z&M4nDI$ZWxc>cW<&!e(^pTB(n-?#twN$EAd**99kCxVjGgttbGSFE1v+c;>;J5LM| z2|a8-En#UuLY`IAZDXgr&qmYBvweQdWl5gg!*=JytnSX8I@v!{lNi~}o^xCl=Dal1 z#``m84IlH(0;6eBD%0Z=lS~?xym~v)uzmW{W2)=kgmtv;VR2WV5g(IOcBcOgpYirh zUUizC_g5~Ga8yfstfRMf!-P2rCeu=uPEa?LbGW*t%s!{WQ*`^z|Bo0?t~7Z0hwb*# z&`UE@)s!7YJda7vNKgz<$jsw9d?C<8HZt&|@7j+?Hs4<`Z>HN;KE=wU5I*_moquik zeBBEB1maIkJiFvWrOb#Td?>D#-|@{h~nz&(Dlhs718WDh?TP&>$U&{i~b zm2BsBx44J<|J2OrE)|{q<)i1b)X1Zp)2il7y{4-7K2);!r$@N-8WpvUWuJ2Lu0+JHy|^Zg z^Sn+$#Yd*ATbZ`LjWsfU+;c4a#=TpM_QWj(ds~MVy_U`~)$U<+kI=lXxpw->{CEX(^S)(T9$kI~M$VrL=7+6xII+-BD1KR8 zg}wN-=NDz-CfyX;n$_y{dBWE}Ho`Nx;`i_H)eB#;H8S01+JcKKj70+qeN!^8UFY1L zGvDsA5~#eoDwMY?uORP+g5koC|Nj)tNY_6Z@m5~{j>+MK9sAp#-0R-+C4jTtrbTDo z6&9w0nu|Sz)?GB2Z9V&p`m)G;*#Mum4`;+~YN|=dZCYfhRFNvJyi#fD8IeyLns)}Z zzIh~*JykbIQG0Kg_{*zOM~h~I*3JJ$4)&a9mdCsM@^`6}#~-g0}v*@PsY$Mg4@pSj(C`(m&E_p;5ryc>$1 z^2XI~X>ztxZ<+0&V3At#X4B-(lGg6;@&T)_+_0?oD9)YuBByWdFQ%^8W7bmXHZKxN z7J8+oN>$!CShMq#mzC?fJx7bqEQsftu-4?n`n8ud(h4)plwN90y(2Txqvb=ygo`1K zdp}2?`62qIt5N5sWb~Tg)8`gQFn+qKRh*o+C7{b~v)dWVGaKw37Y8QRRrUS(Wy9y0 zYIJ+SCIPpg_Gp zxrC{umyY^Qdp3DWmTHon==n2Rv$rxS`zhXGX{vVH!FyZQ#jWJu-|DcsKTWdj&d2rY zfAQUDKX174r_TOgPtX6X%9L5H!XyGpWw+{AXmwS$^?;p;M` zmt04E=6t-V68-yk&h~99L&H8;hKjt6*l~5mx-G5I>!MU;xf7=Hs7?2N^G>E8m9(@~j>&pQjc6;?hL*`BR_$Tu{l$D`@m!PKtPn{~uiJxOc65tA6U+BeNv?@_Do zx9{6C^Fn6y{s_4GZA-4f##4UU?cs6@YyL65;&z;JLh1I@RGD1|f7DFe+ibhd?DZM{ zenY$M$K1-;X0Ms7mp5@HkKxXswDR)qzs%6YpU9(m0Dz@Sgbvs7KKo?-jp0|l&- z-M#``I|4;T&%R7lF><@``rylt56i43gv#b?c`(jq( z;mhm7ugd^An~K${heyPvlx-dzfBW%anPmX4y4-sChwaj+bGG+Pc zKQA!9{C%(B82jyonI|?iEs=3gd!_#L%HnTxxBPYft*p(pX_f5T_K%H4uLAdO`lNU` z-naTbn`>=-eBb@w2kbI_vEQn#(YaN++N0~&zwaze2W^wsi?00iP|9wCwz=J=AxSIS0^V$+?b{_J*%CkqV`J^H5?i`NiIgJhqKWr8!zK`ht z7P`V+LEz7~L%x$z=lDIJJ|`v4Ok+vtzvubUk7tK(6$EOg<~sI$DwliCw)b_a z+^s;l^N+2j1kcV5C}lqU_VD}fi{!uWomDnP|Lb3~Kg$@__pfzV5U9~S^Jv*>^f5aXX4b>$X>}J0B<);F~|)zRxDKKi9fX$?tys-^4B7 ze_xxd5hm+-mGj(_jBC>hPHJshmGndD%vzC1-6s(zpGC$-D@*b&Sb54_DXo9I_DU;d zl0H2<12$4uJlnsqx~6+A4m znkdS8wBTXU?hD|_pye5?N;i2IeNN@m&)saa{lu@b$)Bo(rmtG?s&DeSP;;3VyO`Tg zH{ZT{&SJqUw`iH4!f)&fX1bXjzEd-6=Mj~-<-(y?CzvwdHRw1p{p6Bm1=b=dR}Vb= zw(ak26WP$>1=cY;?#S^RZp__S;Wgf)K)}j7-Bj?3REwddy zq;hY+IdkTEzeztGXFDEP{`r2L>6x?nCwS_ECRN5B&%4@TF8_S_{vWFE?^QH#PH%~g z=;B~$3YIIB_FlKKK6CokoW`K+?mve_7OxE5b}i^e>eQWEb*G63Puadba^}~^vtyQo z#j2*ML*FEOK2t=WSf#_AMSIS&das z`5rElKH(m`LVBtzkEiOi?2Bjo7i-EryJogxN|>g3))}@Ena7f5Qm)S~X@_`oLpr&# zr7B+5SFiT6tNweqJ8YWJt>qG*tODLTfBAj-&!hSO%J+T0WA&^~dzPZ#DhCCN+K1bU zFR094TlDdgoUt8e`JxkHisu%DD($?bw0Xv&2rWa=D;JbCS4|a4mb0F;X2Gw=Cj3%I zM693vb8K5<#+GXTb8dU(j~d3KR!3eqP5qR_bJW}~`@hiFt*SyREgwx@+;c2^#q>)r z%33efbcW@%C3>oE-FCDntI21lpXqeP=(|e-V^qGaJe14WzQ!>Arn>#xMfE4#6apVy zYIW8+YQuQcXTGu9*05yN?QUCVh=Cg0ht4{L-Cmq~K5o*F^Y*f8_Unx@e)9&#MzwrC zfA>lB`ufS!@9jJ2cBtR?l1sai0Eb`cs*h6M24m8IB(u|=7~>RSn^NhL%AyZPL(A~w#O5{KGp9MiOqrj5cvUly>suX=MyiPXSe9mpFhv95hGrLncN{%dgeuwwd*K9)ju^%>sB3`BU}S2X>68JH59uCwpJlaAR3BASYpy6p^6Fcejl=$q(u zq~OlP^fXz~OgO z$i;Qi?Z3UNR^3Qlnmbd`Gvcj~+3ub-8E-F|u9f9cIQiav?zY-1OO*LdIcG0XIB7Jg zYR-x{=g`ocGEUE{7frsN`0kr^yKjY7S!AyL5iPE=rMX?&r$JNOLYdp0oq|F{zOL9S zKXYfremURk6PK3F_Ini;n)7X2_}n#hJ3uXjQyk{LmoJq54f&xWzr7$JU3ICF=6u&J z&~a{#hix}=j%964+I-WGb@kO>j`J5Qhn#JUEnM)bufGN~WX{y+piq!7T}9~QkKc#Z zu3yi;`DV}2Buh~?cJ__8aw66;9ejS`V{_x#V;3%5SZP}U9!&p`YGh;c=b*~x+S=L( z9kIUn`g=S)JRB^`o%SC+bil#BYtfeV+k^M?v4RZ$vB_Ze+4wmHuiw9SpQMuFD#~GJ zo>OKm*4?^rq2i~XHqXz^wf_1#0yMzWq~EO{w&SGHtamx?ZFL-fHMF+W8t1vEYpyE$ zvd`he$2*#LHr-q!kOwyQuUMW~cdK#wxq|z(-{%%QJ2R7i&-Lrqug}}`%jeM9kD7wQ zM#>8fUbeCdtrYQ_F1=f2e#fr$J*o}2_&)w$v~B5%Td}pzD@si^a+_~r!Thpw?=HWd*Uj4f)Z~@ig8O&8)7`~ur|EzGwd45ukHJ>< zwR`WDlzmP3$@6{X<=t-kX57F2{G+vvtlj&^RtFl6x}>|St8I4W*lztisJ*>?W!UO1 zQMzVkW;gEKdGg>v!{5KPeEj@3Z{I%rupq%`W}W)OwCO2g(~WF?UYTt3?MAZA$0L(% zzFcs2aXY@j`;&T?RAeCd_Cq^y#zk4b)R#T8`e!2`lUS7XY8~s<_SZjk7U^0DDalCw zJt6Y&<9GY4tTo1Ry@Hamzi&KNJbCJ5xk}{0w;zqn8Vuh-pX_t847YPa>vSATnspUXL<#CkI2`G*_lF5bTEeLsEg%m|$sXWxF#eEItD zmGoux5A^zD7UvJ#K>DmAC^0(7XFMrH>`)=9t z>tA+uly5%i;=f+fRwO;Ou4m!Bef}%2_pIFhdE7N$aj*cn%eRmzus)tNu3sGD!csh(RcUc z_-(%!_)Y(DhCZ>UPX^f<9%R$uI- zjozQwTlyDet(f(%aetZTzlIePMSEx7wD{__ICs-e!_>a*<#*B|1N~3Uxl+GnZ@+f^ z9kKrF?mL50RYZC5wxul~H@ zL8qvN#fin`WtT5s_C0=c^V{WL|1thLTU%0IR`4yyJ=$hw^~-mL7w_9U#OIsuRpb6E z_L=<@56_p&<>|K5?mKOnd1gtJc*XB;-z%SARgdV@m{D!_>{;5o#pw>}fz?g3-|suV zJ+69E%@x=6CtFs2|7*6z)k%M@Y`W#`i=O%OTkEvhrvfll|IQoUPUi~+n?>Cup z-n^T{Gv{&qpO5n|B)?i*pU_a(-8nDM{A>IAkMFkU7r(wc+on#nx%NcQ$rLLqzPa+Y ze0TSLi9Yk?+m{5R?YHk1KGW&@l6r6VPlmp8n@eW0Z}{>x$>@8s;nz!*-*jZ>-ko6| zX7exYqV&0Gl~1pg|NIuMALPOQ^5x6FEz(ZTyo5+I-0CihF%I|J~TRb8K%rmgmd=W&Zo+YstmJ zZ#uHEwqIuczIEtU(z4CF`x6qUdeuoqr<>osJ9mz4^|W>K?AUbDs;YPSZM$CGzQg$Y ztPN7$Ha{-$-uwM+woT29vekQ-)cAc((#7ex~8( zm(HiYYQevM?Y|wkXrJ7!_Lw&||8#zPC;H5_mEW7Dn^yJfoMD*7`Pc7j+N1Mrol8|4 zPNpnczkT-R^z)Z4UhRJBv7oH9?9#=Hp5f*Ew(iHbEkA##;ik*=la{X*-8MN9k=lDF zX3EPu&U^kIGP`s$ugd3b_J+lu&)rXwx1HYhh-anIZK!|>~+%eRj^ z)Y~t+x9vwp{AM+uWp-7&`nTP@`0wrvU)%XH`_30lU!0TX^Ndkwt@_T|-?8^kxn#F+%$@a*x0QX~ z`rFE2rtX)SRWA%@O1^l%eEagdamD%kva+(diWyn2o8O(|J6Be6>FV9ylQs=UYwom{ zB$`EUkeNIG`)^C`z02%kPHO4z`zW_PfA5jR+DVL?JNMm_vpP5LX->L%nzwygF#lZl z=j&g;IQa8P`TdKnH}9Nx*gtdLy0ZJX?v_r=vpuZ+K2BYH%FCDUetOh@zRk6GbNYEB zTU+0?VUN$uG*;&i``%M9S*3IS-#6)h-roPGyZ_(U^*hVnO4a{puRn2fbNbI_`yb4F ze0(QTj7rMN{#`qidm}5kI=%hwUfZ0qmnm~+Uw-A(L2L z-QIfC)kaQVd7(kve0g7Uj#g!sCgq;qeq(8W0lxluJx;#9zQ)GV_JXa)7e}wXrZ!Xg z&6?QxcUE?Q&U`1OGkcDQrZ%Qx@k4eaDn z^XzUTN57XW)t+w#Uea|?r`fu*Nimyud>|ZYUo}Bl=RyNJe z`1|KyucsIMzbJ3`pnHPmI%9j&rk(5C?-d_*xpaEXQ}M!V=NT&Ig8Q56ise_Sx7?RF zk|LL8GBb7Wgkx*xE?&G@dUpMn74sC*x_`c#S5|HP@{|6@JH6>Ed|D#+{*f|YZ&tu_ z=lVXyI~V`G<1?PPw7ufddJ!NGYbS&qhr$ZF8TUz?^IMh5tG-u z^^8v2RhRb*&b>Hd!u?W(Z}v>Z+@7glm0lM18V5~LpI1LwoqyGmXU{*JH2YO`_Dgit zi+6pWo|NBvcyMZ@&Em~A|K{cwW(F=_o!;@Hrtj+?8NSqpzIAd-CKiTuy;fN)w~KvE z1+!zxZ-&2Syz7r2^{ARXeZH;2BaXtSSLHvRYF=%@cK*WhDi6_Xk)B5-q~7e`y>j9{ zxpOxT$=G}|+1)81-0EKOd+l+_&2_!+_Vr6HefjP|OhKb~{ipMPzV>QOS~~k)V(-O_ zrjoL`K1NMT?>F6*RJ7afW48ZL$KgYfwx>_8w?DUK)r0vnRi8~YES>q$?edzn>77+; zXIQZt95Q~=>X42`?pOP-v#p(f_ytH(+v}iYktJ) z8SU;be!W)u$)dw2&KZ2%DZ1$=594u#SZ6+^gJqSwALdWLU)>a)e}932UB}5Q<r}3V zb!;N?%6YAJ#rAFLE*IXXzyJCE!!=>uKYfXNlrNvrT|Y5)#v!YeM33*=Pe=EiVrP02 z|69*|{vDMSU+zt<*gWI60sqaL)$h#s(`;{uFvo7bc>n)JyLbEIn%7F-f4EnDR?FPL zc~zgyu19(PdT-q<=eH^Bl<~uN&*OiD{k(SD{6?mTr}|=z=D#;&8JqMv?M_?XIT$$S za4e5hozYL3?#@gnKI^}KYkQ7Nk2t+-CRcv~Px(djCrUG8)%Ob|znC-Aad&rTMOR4@ z)9(QLW%uOHt=w$$^;-Fk8NH8t^*&!YJ3GgBhNbnJ^vtb3dV?_U<7Q}pc2%=K4J+>YhkUjP05KiTW+ z#E&h{4 z)s`=-`0$!PaP2jYAIwv%?z|1ey?YkvDJp0Nk-fP{eGJNW%F8(u@ zlJ0R&ezD7OZJfGDpFz&nt;@}iAG?`hwzKFd&2#-%~P0tdh>=I2OeB7 zkn5kGwYAM&;E0}fPHyhytlUdETMKsGInmX%C~L~8tJOuPzT_?Q+I@Z&$FgsgAD24s zNw>0(+fh1;Q-99$*5}(l^0n^x^htWppC_gFs@`jTUd%T6>ghe-PG#@;b?UXv*9%6C zPr3J0m$DaMuT7D!XwElDpLxz~=dVBAHvcc_%GIyvJT3j`;A{7)^^TGjhJT`UR6@U6^ z^7+qag7rUrlFr{?@=#$%%(GX<=RaRNz5VAiKd$7OX8C`w_dj^HSoc_x=DIzf*w*j= zrj>uMruk4()9LH`PoKZH_uyCa`V-psZydc^-!^ZbTvgSv$|ui0uaOk{x7%KB$=6fg zD>HJZ%siwQKEJ*(+dS{{iKj;E9HzME?>Xu1ANPE1xm>c%yhk6O$1M?(PD&`5ntgrV zvJGL6UJ0|G@q1SJTL1sd`mfJY59KxYs>eN=njZJ)S@rr2GvyE7sWlI_71Q~9IAV9{ zqno<(_J6eM&pB^==k`y-*B8%}lzlbcTy?@(yllsh8|D%HJOyQYj`7!h3XZGzWc9x0 zcdXXy&1-C{Cdc2Y>s~&;w%t5#Ux)srXFJ2?QgaSC|6Tcf#|9x~gV1MB-|suTdi~u; zU&ZAT4=tTwxo5ukysFmQ>+da?Id93=Gr9lX-v8V6+0*>vDQ26$Url4?S6NvHa5zJA{UYD$@>rb6NzxPP?{hz_}_8ax*7PZg+bJKsvuiohu-+#Xkm?4!|_*-ya z;f&;}cMY%o!!~@azFGT5>%2{A@AUk8i#9ztdgr!p_w{MEwv>+*`PpOoTX%OyO2dD~|1{Kv2Q|J&9V|1Mm#(nP=Zclw^6Z@l*uzP=rE zCpIPVJ7-=@%!6#(=QnD9nfbqcUinSE{(OA>_sC~8YE?ev%6EKbu*cf`_~u{ve(CZZ zn}QWh3>@yaFZVvXcg{=GjC}=@#m$0C{vMQHpeIxGcV)NAqhgzyudMSbpM}Ql`6hAj zh>-cc--g@c_ntd@`~Jh%YfXM0US3(KfAYGInO^+vqiM&^pDQ-6_&)jn|NY7}>-J33>i>9p{~yEf??opL|NT-@ zx^TJvr*quDZ|t_VxSV{<(CTD_ir4Fv;T5lcy}ncRTJ82x&r9O*&+`AjiH@m#sFr`X zVopcw@^8K36<=SS-c$KIG-`F?onq6t`scB6yT7UB$66ne@A~}ZwEx6{mp;$FSA4t0 zZS()rZkvAr+<))faifT!z$jY#pGv*vgn_f`8 zC&wiE%yRLFQ#zA9mYsOYJx5w5t3N?^{T!e5dGFs`x^?H!+mG{DWS)FtRhk$$X{BXY z_;m>xDK#@g&!tg^3wBLNXFIWR4;(q7QeFMq=F5e{Z{%f+%Sl|k3tHXnUrYY|%&erWCD{)t}{uiJMQ?B3RU-RNBK_PP_R@9*$f zI#X%IEzhg-AN{^x*?rpjwT|8n&NThc=YnT{DXr^W`dPmyb^VFI>;HD_|8sD5O!eFI zKf2%VaY@UXm4D|C<9fTY#-i+bE6OEK$MWvwzmWg(>Av-)59i%^el(lkIDO9I?Z^LY zd|mR3?aU6fO*TKyY~J(tT=W|~SA$FZpVt3>b-wcH&gnnj`Tw7mZEbjHr_A;B`%k@n z|98^-Jw^5(U8Y{YS0V9z=6^ZO-yHXMZ*+ZMTi+7uE5NzD;>*?Wn_c{u-k$pK>GgFF z%YQ9>_vCh2AGWFbt^Vhc`~7Eo<^TTtfBoJ}yRD_mGUuxZ>$AMIa(7RfI^l-kY84iy zBUxdaZz(u1C2zj5CeAR;{mtr|Z*Ta`@v}NPdx`qoce7^AEMK+yQtZ|G>-lyZ8P(q%yjLcsUT&iT|D>j*V_>(?~_*UJU#2b9`oh8W3$$@)Cin@aY$|Zo?IWj`}_jiPg+*ZTJ`Z> zT-vj?x#j0xp72?(WNkR-nRWTim^;t9@Bg>J8$OepDIt|)3V;EO_S){_ObNcbyYzn|0n+rNtwI1N6g>T8o0wF zar^w4dE%Zwd42l%CkYnvO--og{olXi^>@Du$z+EP8IqsGfscMAuIpj)z|7fI|CbHW*#~`xBtb-ewXQ2 zPkwsFQ2F!v&G=W&_5WmzZl^~`f4Nlh*)I7n@p7+EA5f3cf!Hz)6`p~cn%IpK;6Z)yBeyCxy^GCjAjCnS}FGjy@eIX+{n-G>%G z3%R#b;^=~U>3DbJ+4E~ppMER4ZT|m8@qf`KUu{z!2WtN+ejfOmX{lgm@Apchn~i=K zlsuKXy5CQ}Q_#P6DWi}bhvTysDcQ+wjXzDNvE7ZC&}zKn%Z#$=Q`fyzp102L;?2<3 z-AB%ScqHtmFUj$9dVvl9^%)Xx9v{48%k`$U=UvUga{2ttUw(N1`}$MsX=aqjtj$X; zTmz3}Z4HWu=s5iFz{7$G)2Fvze#zr@r%uFlbHt0+ub*G`w@*z=YwP3F-@CW=%=z=d zk)eMlKWdQ|GGDBz5R{RVwQTwF>3^D>xbC_xKeBe$vT1F{)YiqnU$|mN%ajo9nUOb_ zXS#UD*qjYtH&1B$v14jVN{dgNJ-vAC-{VKtuK6Rx+uPe{xU+K0)~%Osy;`_s&72P% z9&0jRiin6@x>?G*+O(H%{q#qZf+kyu@Uli}%733n+xFb?o^`Efu?fF> zs`5Yn`G!&X%BpwU79VjvJ=e7?oPFn&JBQCr;lJ719V2%)rRK)zI|sefc6WCg9!)y! zr>1zYYqLec+@sI+cif)Pw&LoX&WaAHMwV*Payh<7W||f6V>F^X|5s@_OuFFpFeUt2 z@m7V_&+qqn2i?`>`~K{uWZi+&e=}t|4VOd+8{FpFv3uXy!&Tzvp6y<$HSma|)z&o{pJ?oftV@@YRMMZ>vwCdJG#)m>AwqksL*wv9h4r8c{4*(Me? zO>IT~mkm$$d(H_uId!A$yDQNg!P14hVsChz-nswxoYsFui&&qY56|~vnx&zgy3Xj4 ze%pt-7~Ot;vz5Nr7hL%B;LPPLgS0IlFUtQv@Og3UyuaUy_ubgrult_sw)Wx~sftI! z?xvls?{8dL`ObWakWg02k^Ki7*8j~vlAAPb-m|Ql?bB!OOH+PgtLo_)8IirNc#FAj zWsumt)><{|q7A#EKlt}gSYhKn?>Xb;@6kIA_nb|s)_UI(bKt7&;ZKh&CSRT$vW(MZ z_pOL13H9?bU0zF_rq|3|tN!}RQm>Xd;g9$2J^lG4TT=0!H@dt@6Xq`7P~Lmg&OCCu z%@6szheR|VRPH#o_cUkAiAOtM$3MRILE!b}zb{gs7kpp8`9icun5#ASWakLp|3zw# z)K-Z~Y}Ssn`O~xbu=Bn@hwDGizn>R8Kg+FVty!?sV$qZ9cAx$CO5+&!`%mliTBps6 zQ~P^cr|;ULO7oTzuWrAwm0Gs-v)JCZdRwZrx2K0^7P}>FD&Mr_lC$5z(r;o_6VJ6y zcs4VscE#rzJFW&s+&lj$LV4RN>za=rwOn7S30+!q<5H60i_#UQR&RRCD>qrTSbmXp zQkrw;cJ;BpZq}@Ch1cBGdN!B;kYq%iTl_|k!uwj2b6>`IXe1}sN`*hEyz-6j+BEf- zd+j^-A3tlID9EE{zj(XHk}uD!g!jpqX#KpIb*IEiX_3&16+RAPLQW}XE#lwx38V_# z_qelbTKSCp@O@ApfYmQ&vw{Xch zF$u?>Kat%z@!?P3Huv9=(L4M%8L@aD75FzZG4K3ZgKIN(q}Cb1QFnc}YgvCw+8e=bu)#BXp7S6Ij^u4m-hTUj z-lJ`M_V`3ZNHi%FJUqn8#>Vz9?@`&LsyA<6Ki+)aF1aG5<<+dHs^7m}?5k_uVwfXrAwzCa{8Y6ch*gz<5O4bmXuU%ye(UC>sIF1Ern}$&t}^GdrRBe3$ZQB*UnwC zB;}U%o<_s#yG|DGJfW|#Wcl*xeCzwSedCj{^s~u*YhoUsm{Bp~(IcTvZ~1=x`c)_{ z8vH`<(XX%4TeeiK*b(w^mTUX<*UIOo`iGS8xE@t4iGBU()m5=wyVp;i{`}Cy$4jlU1fdx&Y6aJ+onyNGVAo4 zgJ#^xpWp1Q@N!QzY6|=P`Lf?4uGWi3KZ*Z8SYNyEO!LMv?%tQr$o^?-?oIUazJ24? z9^X}Aty5yo9Qh~rTKja)`*#nsKYz$boY~iuvE)tFH8U|yZysI&b6+`OfAfs(Zbf!B zy`68J*|I-rezSdac(HC;`mq<8MU&^mop^LH`A>4)xB2gbX3uwgyEgJ$`Lu}p|L5F) zYx}4um|c3c^O2LOA@}N!g;#$+x&5X@L{wsK)x5XMqBW*Z%V=WVe?I=>?>E-}5ZuiF>}KsR zk@?G~EUS*L*|-1Xk1u@IvlpjWt&Y4qSLJ%b((Jm{hix^Rx~*>f$(X)$s_eJxYMT11 z4!)01t*x1KHviw$nPu#0(Wch>f3~%M^*d!H|42Uj;H+^wWEpFR5bnzOziAD#aH zKLXcYRuHXqmrZVh^2g%aF=a;<3bVL4cH3D^fB4h6Y}@h~ckK_^ z7xz|Z@^~LKm9xK{URc(dU;kZ~IZt%ky3l=Avlg#eH?j5b{SB5c(;q*uEU(t~IG>;T z`K4WV@#&i1XSaV5*V4W{}a_`d*{g7 zrteri<;)|#ZT5GP3+sB{@B1@n-K&zkGwV0m{%m;K>u)jRQ_!87*1e05`}FsG{`BCam$e%rrRvw~ntm2rXHV$p^j20^@6GslR*cZ z5-`#FvaCXDeaVHJVg6B0EJdLfD}PQcsgPQ^UgP*QiN3HNrR|@z?AEhSHx&$Adu&#G z-}cRuZ%xW^nOm_fzsZX6;FO--i~6Qb+jd}j(=j8V#fR!u8qHsnuDGgn>`PHp?e&ao z9W^~ShlN)JX3sh=8ZX`}>MFrHam9_2SL-S=GFKd!nRztFPwDtXzbz_?8KyIWxideO z28B=Ri|bOl{7k{pOs3YyhOb@Ldx?NR)C-@KrMi_Bvoau9((DUT_mIrS$ z4$hQmUvP24yLCsdKV7^^Lw0SH_YT#`v$S=$n1%$uIiaAZ*eO#jCAi4JXIA&IwyK6n1cw#P~S>Ku=EdWo0+#$}L*9QOHtb(+ieKOkCvi zB-|`Ge2V9eIGfE%Rtvg#)C~{&m93KWthijQuE-IkB%Euqt@Pp7ki_2U6HZT+xO{g@ zY1!q7IgKmCHmIadm?zY|q+jjwJC&m%eme|BtHW%jZDO>uj99$&u=ib6>qTLQ=FIXf zi(*Rima^O?@+C_(kkitnq@-}`wmCaG9+#g`P+YZ@=Db}1Nco}lJ$9TzXn`pt#K*THbk zqcuzRuAY2qkIolCv7(r#SIjCiGc^>|oLts+tFB+gdH<@_sxEF%p6~?i>;>=7Im_+; zqZ_?FtD~Q9`O5En$^S&_et%^24O3n9K}2g^MdtpZnIek?gOk|$)~N8TpR<0^3Rk10 z0kucHmv3iuj}qb9DdXJKysR(J=4z#j7n9m*X7^Q+j$I0eA1bN3^&0B7ufC@j^}4Hr z@4C`;i49XtFWkBIi7M`%>(M;V`9yVs9nLTgb z}K5~8iFth}e@=cJc2X9nAE zHt!ViTNLt>wRKC?Ek9+SpRBD@rc4tSl`WR?wc5zsX*jDc#keTxZeh}G!DN%a8eFAL z7vkQ2`QU6lLAdnI>SVul)kXg&-~V6mXZ4Y9S>D{Bf|d8)>hD!wt<(cgPA;wax-(8S zS$&#{`s1XtVym*VG)lz(cD;3o`<@ZJ`hU6n_Q{4(Q-vZUZfw+C!{{jza3Zzk;_tVNcmymWjuoUElQo;ESsZrVE&Q zrED@tDN=2cc=1##Bjm*4Lld+^Uwo-5S;V$8rp;%a!`h2VT}}^n_Sc^GJI0$7d59F05cW|M!$tM&I5iCR(hC$FJL%-m#t69JJO^q~-F~ z>zSb^o^WkRS`eo8!G`g4tFiZAUdG*wtvWphJDJx0xO`o}WYuG)B4)O|En#w9Mtj@X zw?}ncJjwCbp)E$<+xI!czDq3kYX383^>#Q41+F%E(f4-?Q(d%`iI?Rj14*skj(Y+d z(k7gIq9NjCvWRc*66d8876xQ9Z{v}ASaDv1gM0GA5N-*T*o3qFxvE#Pc&$!;h_bTS zVE<&r6~=0*W=AKBebZwWI;^$bH(h7S_pKYR#7i$(d*aaU_whVu{`WpU`gkX2{dfDB z!u5u|-)=ZPQ?LDYjjrB9!v{~+D_BPy0u-Mxlv(TmH=^BGM?*t`{W_~K+tMYVNJ3)D} z_5|&z8KrD0j?Fe-WEK{>_VATWP7Erx3lY09`sqO;Vd68^N3|~Ct_f3rKBFRseNhTDQ zxRYmYH@|8As=re>JT3f7qFetzLhRBe5Ya zMMbatg^Xt3J$T@Og6mOL``HnDW`)@*Cgd;Px#p&j`?jlfcLu~YnbCHZY`-svyi zTlW0=fBBoXA;>C)fA7kI@_*Y+{>N#zIAQk2|J%hv*Ka>>^)r%d9{c~8BWH!aZ{HSV zFRm_V;$8D+=6|z}c=Mk10^64@Tc%LRt<<5=#G&MIr*7hfJqI09Qc?sQ|7_~$aG0cW z=VEDEaktaqI0|)*5N| zTmP%S?|c9CR>EvGHbdixO*)fPZW^6B0|q+HXGHu?z1_NZcihKWk793YF9~0k{l9g} z!~biZsQAtL=9HJ4UN?W^-rckA%AWju)%f$7Gn=mm&WbC!IM0PsbxPeiv_Li0d&Q4Ab6crT}KTMdgj`733pZ{hbet+NY+qFAK zqCfB2K7HB!xOo-XiLc&1J-Jh=4&AMaCt zKKtDMTzc_Cp?{sp^;JJ_zyI(3ZGHSsWjmu)Ri9o=ocM3)Z~e;|^}nx9kDv4FSG)ZF z%A)@n@1M-~U&ysPwB*Z+i<2fzTD3|`Z~E^e!u~N|UuSQ<_29t-^LsUyH~c$-%;)*};Y$6r zl=_8HPj44}=nRjq{W`bb{x@6J=kWXgo*!jC+4X06{h#wbH5ccu|6~4P-`_9azIELA zbMSb4<e=iHpd5I>;{n=lSA(r^AP~ z-rBhO!WEhN?8cAgt1nHLX1{--(pJ>;^SOU_#8=<@`D^dR?dfmizia=De!Khq-tB6? zyU)gT{+|E))`rjj?B(~pf0usGrn0;;;ozBrio7!)i{1Zl;N<$cKaYM+ob_qbr-$iw zzaA}~>@WN7W$s(+AD6^uWd45fa_W_aEywNcm-D>0t&L7~baZrmy!icrd&m3rWpCMA z#{@*!{J)_sZ&P1B#bL##Q@h@8{T{dT|Gf5j{~jEdudk^2@8IaUvh3Z9`1ik`v&-)< zI)7+yz>$2rig)LZvfumtaPslz&wt;jR^{{X6`w z?fdn1wX4uZ?{^oH;-{_6zS*2_7q+;N&+}#Fx4rz&A1{_({{P=0=EI!#JQsIs@08*` zf97WW-kR)HN}oM7dFs&eeU&?Xw7#65Tk~dV|NZKZ*ZQ7$@wfgzv6kQGx!aE2 zOXO=`J#GKxeJMEY-`{KVPw%N&r7m`S)#D`N()IPflllUl#4U+^zw+hv|K8rppIC3Yv%OT#j`8i0@AiK`y*#?@P|r&7do>Gg?0s}o z{=O`qkL@q6ExhvGf{{C1)l`nK9OaSw`#L1J?9z{!&z@BG`>3{=?b-OOEC23o`DZu3 z8eYq&*t-74{~ISK&%HPCvVU`B&DvX<53hZ{zkjXD_Uw1@AATjd{d(|+xn0eAcFF&S zyXmE-KPx|<-(Qv9xJ>5T{vX#DI-S3@e1Fx>qqbH5yBU5yS1*ZG{8%U#lzKisuHu(N zeB{AIi`OSV&boA{_4q#%QDK9IkNO_xV@z`&Iw! zVwYGwzL{VD=ik!Z-a_1R|9?y^^F8xv^MzTp3-75uyzzSd`}02Qn&0Hu47m7 zKF7E0rQ?P}$F-dff1Vy+{rR8L{~!D7KR;IgUcSR}svYx#ok!oX`^8(ocpCTlQ~z>4 z(Pdxn{QPmh#CPXQ?t~NbB-ZMjiLUtd{_{n@O8uJukIm1^>U-(ge*Cz9R%|l=UXCsH z(N9G-f0AL!H-33Deg5Ci^Z)-j%>VjQasA(3bB1lkf34=`X<4Xzd2;glI*~m;%lU8G zK79N$WXWO9`uD;Y`ECDxuwK9S@15fFw#;kKET8}D&F1sxitm-Rr|H;#oS680C$sHT zS8n~ie-nHQ&KBRVtxTWUzP9|*!{_!@Py57rrv@h^B>Z|Zw_opD=(DqX_CFK)U-@(1 z9}oHRGpi*p*1j&DU-RkUTHTZ9<}u!zck$Nldw<^@pKjf3#Q&c;qkg5b#rt*J?^%U~ z-7x*k(@?&`V14<2?)m$_Z;!Fx>K+lYrN2Jv;J@|z|9(kup3t1$ke}iZQt-R`{+?^{ zvr4}l&9DFS=ISz${Pz%6}H!_{8<$ zW7qs$|M$MHtJ!C&@cM^0!!!G6rpNB2yz7qbN zUvkc`^PUwyubSKc4EleHKYq{0SK90MeO&l&*Zo???FZUaH}vN3`~UBC@bY~>xL%jk z*1jq}%x02q|NF=NWXr%z)AEBq@7I5Qxj(-4>DKS|zg}(D-~apLZ~bup{~vez-?y&( z^p)T4-xujOYWHjZ{FDCw??bT0`IW&{&o6vm9#{W$>g0UMnr&^f*X^~wlvcEE&;NhF zU#EOLFtc(ZyFTxp;xC8$6JE$wJZL;FUoW%b_q*M_FOq+J+3Mbwed^Tb$#dp5O`BgS zA8Ng%cTM+PBR0NB386;8&Ah+;_WgOVboY0CJ-xLyKTH4$*vvK>(qe&ZYczC?lT#?MN z=d-KQL?7QmHML_Ww)bw4Gcq+*73$<+d+hWhcJ+gU>P+&yeEsIGPEqm?3oL&09)CRX zsI|7Tax&M{Qz?ZJIa30n*1Mz|ELe8&WeLl@Ro~v-^SIoo#h*Pw&GM_iT6P|9Q+?e`Wbw>+<*a zHWpu>S6d;}>T=*Mv*g_6wdU{deLQ~k&+W3eZLi<%x_M%Xi{fKnUxn}fpVnu+zgPQV zq0%>jisyTLmK(Z=Wr=SUZFgJ{u(N3D-nBkQTC7%Izge@q{JdpN-aKA*xv5=`PdpKN zrz@en`=*e$p5XCGGd^oB+r91mjg7_6bzK(Dt`7*w$;t6qvU+aonR}BQAGJ;`F-@5FLfU)BGRZ=XD6i>>vMnRlDFcFOq(+stHY z%FmK&&NOHaxxxJMe~^K}OOsQpR`BHXpSzLa>$^u#amB}VH?3xU?6ZG&BiNuWdg*SX z@}zxsC#tUhkNJOGdK;(GuDCznCx4E;Ys(xv^Wwcc!FyscpMO-nO=vvc_xj)SHtGC3 z+iGw3n%~<|eBIal?X7>ir8y_=E#LR;`))U@UB7;1H`m72D#yN1IezZwN)_oxx+Sj_ z?9)H#UeCY1PuB0|Hr`9$Vt1D{74G@hCjF7ahUMPR2M=egd#I}2|L<#ov!1xRN6t&F z{t{8IyWZC9%iY_$mEN9kdA;S*t9kP-{`~mu(4JNEPCi}vPN~|MYwmiFwQrqb7$)oj@h{>?P_nY9Gtl?BivYK zX5%VNrhMHBo&F=6ru|yf^=jd&B@eEwdNwITeC4TydzP(QUHb4w&hFg@HrAyX-H(@@ zVPE$8AESKr{-C=RejUg3w>~}a$D#D?kB7|t2(JY3!Nn@ z4o_Zw@U~u0M(vY}%BmlDW)y^E4V&+{Z@CQ zfA9IP|NrOahI)=)2+?@G9Ry5Ic?(C_Geb9U!t3&#NJt( zT)R>CXX1XjUXE_-PZ#zcm9m@a#m3IFY8l6#;sc+3R^_elo!WKx7TYvFU7qD_JF=8E zsj0Kyy5%-ay!y|PSC6h4x!c8w1lZh~amwhKn%OpSwU#F)x_8X(hX+MQ$4`2ici8Oc zWV4XyV$nSZenlTYU1%Qr|F?b4c^R9ib%ARb^QG;VJbhVjYjykT-K(>dce_q7H=FnN zp-}9l%X8j6nz#SMpZk1a*RPtJhq2u>%-iv>?f(4^{#^TCkDRwV25&Yy-rrvQ⁣t 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 \uicontrol Configure to open the \uicontrol Locator options. - \image qtcreator-locator-customize.png + \image qtcreator-locator-customize.png "Locator options tab" - \li Click \uicontrol Add. + \li Select \uicontrol Add > \uicontrol {Files in Directories} to add + a directory filter or \uicontrol {URL Template} to add a URL + filter. The settings to specify depend on the filter type. - \li In the \uicontrol {Filter Configuration} dialog: + \image qtcreator-locator-generic-directory-filter.png "Filter Configuration dialog" - \image qtcreator-navigate-customfilter.png + \li In the \uicontrol Name field, enter a name for your filter. - \list + \li In the \uicontrol Directories field, select at least one + directory. The locator searches directories recursively. - \li In the \uicontrol Name field, enter a name for your filter. + \li In the \uicontrol {File pattern} field, specify file patterns to + restrict the search to files that match the pattern. + Use a comma separated list. For example, to search for all + \c {.qml} and \c {.ui.qml} files, enter \c{*.qml,*.ui.qml} - \li In the \uicontrol Directories field, select at least one - directory. The locator searches directories recursively. + \li In the \uicontrol {Exclusion pattern} field, specify file + patterns to omit files from the search. - \li In the \uicontrol {File pattern} field, specify file patterns to - restrict the search to files that match the pattern. - Use a comma separated list. For example, to search for all - \c {.qml} and \c {.ui.qml} files, enter \c{*.qml,*.ui.qml} + \li In the \uicontrol Prefix field, specify the prefix string. - \li In the \uicontrol {Exclusion pattern} field, specify file - patterns to omit files from the search. + To implicitly include the filter even when not typing a prefix + as a part of the search string, select + \uicontrol {Include by default}. - \li In the \uicontrol Prefix field, specify the prefix string. - - To implicitly include the filter even when not typing a prefix - as a part of the search string, select - \uicontrol {Include by default}. - - \endlist - - \li Click \uicontrol OK. + \li Select \uicontrol OK. \endlist From 8940522fe2cff731ecc69fdcf8518db73a50e461 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 28 Feb 2020 08:51:44 +0100 Subject: [PATCH 10/96] Core: calculate highlight scrollbar margins at compile time Change-Id: I9ce008c438f888df1c7f97df5ccb1868705e0636 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp index f68739f1e22..4f2657fba87 100644 --- a/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp +++ b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp @@ -122,8 +122,8 @@ void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent) const QRect &gRect = overlayRect(); const QRect &hRect = handleRect(); - const int marginX = 3; - const int marginH = -2 * marginX + 1; + constexpr int marginX = 3; + constexpr int marginH = -2 * marginX + 1; const QRect aboveHandleRect = QRect(gRect.x() + marginX, gRect.y(), gRect.width() + marginH, From 0776340ad8e99cf078a2d24dcb6deb5efc28ec34 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 24 Feb 2020 14:37:56 +0100 Subject: [PATCH 11/96] Dumper: unify Codestyle generated with autopep8 and the introduced setup.cfg Change-Id: I5b55a7937f2cde81be59d2b434e94ada1a4af5ab Reviewed-by: Christian Stenger --- share/qtcreator/debugger/boosttypes.py | 9 +- share/qtcreator/debugger/cdbbridge.py | 44 +- share/qtcreator/debugger/creatortypes.py | 41 ++ share/qtcreator/debugger/dumper.py | 500 ++++++++++--------- share/qtcreator/debugger/gdbbridge.py | 264 +++++----- share/qtcreator/debugger/lldbbridge.py | 257 +++++----- share/qtcreator/debugger/misctypes.py | 110 +++-- share/qtcreator/debugger/opencvtypes.py | 5 +- share/qtcreator/debugger/pdbbridge.py | 30 +- share/qtcreator/debugger/qttypes.py | 581 ++++++++++++++--------- share/qtcreator/debugger/setup.cfg | 15 + share/qtcreator/debugger/stdtypes.py | 159 ++++++- share/qtcreator/debugger/utils.py | 8 +- 13 files changed, 1201 insertions(+), 822 deletions(-) create mode 100644 share/qtcreator/debugger/setup.cfg diff --git a/share/qtcreator/debugger/boosttypes.py b/share/qtcreator/debugger/boosttypes.py index 215ccc6922e..214f3692313 100644 --- a/share/qtcreator/debugger/boosttypes.py +++ b/share/qtcreator/debugger/boosttypes.py @@ -25,6 +25,7 @@ from dumper import Children + def qdump__boost__bimaps__bimap(d, value): #leftType = value.type[0] #rightType = value.type[1] @@ -64,7 +65,7 @@ def qdump__boost__shared_ptr(d, value): (vptr, usecount, weakcount) = d.split('pii', pi) d.check(weakcount >= 0) d.check(weakcount <= usecount) - d.check(usecount <= 10*1000*1000) + d.check(usecount <= 10 * 1000 * 1000) d.putItem(d.createValue(px, value.type[0])) d.putBetterType(value.type) @@ -105,7 +106,7 @@ def qdump__boost__posix_time__time_duration(d, value): def qdump__boost__unordered__unordered_set(d, value): innerType = value.type[0] - if value.type.size() == 6 * d.ptrSize(): # 48 for boost 1.55+, 40 for 1.48 + if value.type.size() == 6 * d.ptrSize(): # 48 for boost 1.55+, 40 for 1.48 # boost 1.58 or 1.55 # bases are 3? bytes, and mlf is actually a float, but since # its followed by size_t maxload, it's # effectively padded to a size_t @@ -125,6 +126,7 @@ def qdump__boost__unordered__unordered_set(d, value): if forward: # boost 1.58 code = 'pp{%s}' % innerType.name + def children(p): while True: p, dummy, val = d.split(code, p) @@ -134,12 +136,13 @@ def qdump__boost__unordered__unordered_set(d, value): code = '{%s}@p' % innerType.name (pp, ssize, fields) = d.describeStruct(code) offset = fields[2].offset() + def children(p): while True: val, pad, p = d.split(code, p - offset) yield val p = d.extractPointer(buckets + bucketCount * d.ptrSize()) - d.putItems(size, children(p), maxNumChild = 10000) + d.putItems(size, children(p), maxNumChild=10000) def qdump__boost__variant(d, value): diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index ec55b183124..cee6ea9c406 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -35,8 +35,9 @@ sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.curre from dumper import DumperBase, SubItem + class FakeVoidType(cdbext.Type): - def __init__(self, name , dumper): + def __init__(self, name, dumper): cdbext.Type.__init__(self) self.typeName = name.strip() self.dumper = dumper @@ -89,6 +90,7 @@ class FakeVoidType(cdbext.Type): def templateArguments(self): return [] + class Dumper(DumperBase): def __init__(self): DumperBase.__init__(self) @@ -114,7 +116,7 @@ class Dumper(DumperBase): elif integerString == 'false': val.ldata = int(0).to_bytes(1, byteorder='little') else: - integerString = integerString.replace('`','') + integerString = integerString.replace('`', '') integerString = integerString.split(' ')[0] if integerString.startswith('0n'): integerString = integerString[2:] @@ -125,8 +127,8 @@ class Dumper(DumperBase): base = 10 signed = not val.type.name.startswith('unsigned') try: - val.ldata = int(integerString, base).to_bytes(val.type.size(), \ - byteorder='little', signed=signed) + val.ldata = int(integerString, base).to_bytes(val.type.size(), + byteorder='little', signed=signed) except: # read raw memory in case the integerString can not be interpreted pass @@ -148,7 +150,8 @@ class Dumper(DumperBase): c = 'u' else: return name - typeId = c + ''.join(['{%s:%s}' % (f.name(), self.nativeTypeId(f.type())) for f in nativeType.fields()]) + typeId = c + ''.join(['{%s:%s}' % (f.name(), self.nativeTypeId(f.type())) + for f in nativeType.fields()]) return typeId def fromNativeType(self, nativeType): @@ -170,7 +173,8 @@ class Dumper(DumperBase): if code == TypeCode.TypeCodeArray: # cdb reports virtual function tables as arrays those ar handled separetly by - # the DumperBase. Declare those types as structs prevents a lookup to a none existing type + # the DumperBase. Declare those types as structs prevents a lookup to a + # none existing type if not nativeType.name().startswith('__fptr()') and not nativeType.name().startswith(' 0: namespace = name[:namespaceIndex + 2] self.qtNamespace = lambda: namespace - self.qtCustomEventFunc = self.parseAndEvaluate('%s!%sQObject::customEvent' - % (self.qtCoreModuleName(), namespace)).address() + self.qtCustomEventFunc = self.parseAndEvaluate( + '%s!%sQObject::customEvent' % + (self.qtCoreModuleName(), namespace)).address() return namespace def qtVersion(self): qtVersion = None try: - qtVersion = self.parseAndEvaluate('((void**)&%s)[2]' % self.qtHookDataSymbolName()).integer() + qtVersion = self.parseAndEvaluate( + '((void**)&%s)[2]' % self.qtHookDataSymbolName()).integer() except: if self.qtCoreModuleName() is not None: try: @@ -391,7 +397,7 @@ class Dumper(DumperBase): else: return typeName - def lookupType(self, typeNameIn, module = 0): + def lookupType(self, typeNameIn, module=0): if len(typeNameIn) == 0: return None typeName = self.stripQintTypedefs(typeNameIn) @@ -405,7 +411,7 @@ class Dumper(DumperBase): return type return self.Type(self, typeName) - def lookupNativeType(self, name, module = 0): + def lookupNativeType(self, name, module=0): if name.startswith('void'): return FakeVoidType(name, self) return cdbext.lookupType(name, module) @@ -447,7 +453,7 @@ class Dumper(DumperBase): variables = [] for val in cdbext.listOfLocals(self.partialVariable): dumperVal = self.fromNativeValue(val) - dumperVal.lIsInScope = not dumperVal.name in self.uninitialized + dumperVal.lIsInScope = dumperVal.name not in self.uninitialized variables.append(dumperVal) self.handleLocals(variables) @@ -472,7 +478,7 @@ class Dumper(DumperBase): return cdbext.parseAndEvaluate(exp) def nativeDynamicTypeName(self, address, baseType): - return None # Does not work with cdb + return None # Does not work with cdb def nativeValueDereferenceReference(self, value): return self.nativeValueDereferencePointer(value) diff --git a/share/qtcreator/debugger/creatortypes.py b/share/qtcreator/debugger/creatortypes.py index 346b53ae7da..0bb0be0699f 100644 --- a/share/qtcreator/debugger/creatortypes.py +++ b/share/qtcreator/debugger/creatortypes.py @@ -23,15 +23,18 @@ # ############################################################################ + def typeTarget(type): target = type.target() if target: return target return type + def stripTypeName(value): return typeTarget(value.type).unqualified().name + def extractPointerType(d, value): postfix = "" while stripTypeName(value) == "CPlusPlus::PointerType": @@ -47,6 +50,7 @@ def extractPointerType(d, value): return "void" + postfix return "" + def readTemplateName(d, value): name = readLiteral(d, value["_identifier"]) + "<" args = value["_templateArguments"] @@ -65,6 +69,7 @@ def readTemplateName(d, value): name += ">" return name + def readLiteral(d, value): if not value.integer(): return "" @@ -78,9 +83,11 @@ def readLiteral(d, value): except: return "" + def dumpLiteral(d, value): d.putValue(d.hexencode(readLiteral(d, value)), "latin1") + def qdump__Core__Id(d, value): val = value.extractPointer() if True: @@ -93,36 +100,44 @@ def qdump__Core__Id(d, value): d.putValue(val) d.putPlainChildren(value) + def qdump__Debugger__Internal__GdbMi(d, value): val = d.encodeString(value["m_name"]) + "3a002000" \ + d.encodeString(value["m_data"]) d.putValue(val, "utf16") d.putPlainChildren(value) + def qdump__Debugger__Internal__DisassemblerLine(d, value): d.putByteArrayValue(value["m_data"]) d.putPlainChildren(value) + def qdump__Debugger__Internal__WatchData(d, value): d.putStringValue(value["iname"]) d.putPlainChildren(value) + def qdump__Debugger__Internal__WatchItem(d, value): d.putStringValue(value["iname"]) d.putPlainChildren(value) + def qdump__Debugger__Internal__BreakpointModelId(d, value): d.putValue("%s.%s" % (value["m_majorPart"].integer(), value["m_minorPart"].integer())) d.putPlainChildren(value) + def qdump__Debugger__Internal__ThreadId(d, value): d.putValue("%s" % value["m_id"]) d.putPlainChildren(value) + def qdump__CPlusPlus__ByteArrayRef(d, value): d.putSimpleCharArray(value["m_start"], value["m_length"]) d.putPlainChildren(value) + def qdump__CPlusPlus__Identifier(d, value): try: d.putSimpleCharArray(value["_chars"], value["_size"]) @@ -130,14 +145,17 @@ def qdump__CPlusPlus__Identifier(d, value): pass d.putPlainChildren(value) + def qdump__CPlusPlus__Symbol(d, value): dumpLiteral(d, value["_name"]) d.putBetterType(value.type) d.putPlainChildren(value) + def qdump__CPlusPlus__Class(d, value): qdump__CPlusPlus__Symbol(d, value) + def kindName(d, value): e = value.integer() if e: @@ -146,10 +164,12 @@ def kindName(d, value): else: return '' + def qdump__CPlusPlus__IntegerType(d, value): d.putValue(kindName(d, value["_kind"])) d.putPlainChildren(value) + def qdump__CPlusPlus__FullySpecifiedType(d, value): type = value["_type"] typeName = stripTypeName(type) @@ -159,36 +179,44 @@ def qdump__CPlusPlus__FullySpecifiedType(d, value): d.putValue(d.hexencode(extractPointerType(d, type)), "latin1") d.putPlainChildren(value) + def qdump__CPlusPlus__NamedType(d, value): dumpLiteral(d, value["_name"]) d.putBetterType(value.type) d.putPlainChildren(value) + def qdump__CPlusPlus__PointerType(d, value): d.putValue(d.hexencode(extractPointerType(d, value)), "latin1") d.putPlainChildren(value) + def qdump__CPlusPlus__TemplateNameId(d, value): dumpLiteral(d, value) d.putBetterType(value.type) d.putPlainChildren(value) + def qdump__CPlusPlus__QualifiedNameId(d, value): dumpLiteral(d, value) d.putPlainChildren(value) + def qdump__CPlusPlus__Literal(d, value): dumpLiteral(d, value) d.putPlainChildren(value) + def qdump__CPlusPlus__StringLiteral(d, value): d.putSimpleCharArray(value["_chars"], value["_size"]) d.putPlainChildren(value) + def qdump__CPlusPlus__Internal__Value(d, value): d.putValue(value["l"]) d.putPlainChildren(value) + def qdump__Utils__FilePath(d, value): try: if not d.extractPointer(value["m_url"]): # there is no valid URL @@ -199,21 +227,26 @@ def qdump__Utils__FilePath(d, value): d.putStringValue(value) # support FileName before 4.10 as well d.putPlainChildren(value) + def qdump__Utils__FileName(d, value): qdump__Utils__FilePath(d, value) + def qdump__Utils__ElfSection(d, value): d.putByteArrayValue(value["name"]) d.putPlainChildren(value) + def qdump__Utils__Port(d, value): d.putValue(d.extractInt(value)) d.putPlainChildren(value) + def qdump__Utf8String(d, value): d.putByteArrayValue(value['byteArray']) d.putPlainChildren(value) + def qdump__CPlusPlus__Token(d, value): k = value["f"]["kind"] e = k.lvalue @@ -228,6 +261,7 @@ def qdump__CPlusPlus__Token(d, value): d.putValue(type) d.putPlainChildren(value) + def qdump__CPlusPlus__Internal__PPToken(d, value): data, size, alloc = d.byteArrayData(value["m_src"]) length = value["f"]["utf16chars"].integer() @@ -237,6 +271,7 @@ def qdump__CPlusPlus__Internal__PPToken(d, value): d.putValue(d.readMemory(data + offset, min(100, length)), "latin1") d.putPlainChildren(value) + def qdump__ProString(d, value): try: s = value["m_string"] @@ -249,10 +284,12 @@ def qdump__ProString(d, value): d.putEmptyValue() d.putPlainChildren(value) + def qdump__ProKey(d, value): qdump__ProString(d, value) d.putBetterType(value.type) + def qdump__Core__GeneratedFile(d, value): d.putStringValue(value["m_d"]["d"]["path"]) d.putPlainChildren(value) @@ -275,14 +312,18 @@ def qdump__Core__GeneratedFile(d, value): # d.putStringValue(value["d"]["m_unexpandedDisplayName"]) # d.putPlainChildren(value) + def qdump__ProjectExplorer__ProjectNode(d, value): qdump__ProjectExplorer__FolderNode(d, value) + def qdump__CMakeProjectManager__Internal__CMakeProjectNode(d, value): qdump__ProjectExplorer__FolderNode(d, value) + def qdump__QmakeProjectManager__QmakePriFileNode(d, value): qdump__ProjectExplorer__FolderNode(d, value) + def qdump__QmakeProjectManager__QmakeProFileNode(d, value): qdump__ProjectExplorer__FolderNode(d, value) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index b292b145df3..7db5c7084dc 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -53,13 +53,14 @@ else: toInteger = long -class ReportItem: +class ReportItem(): """ Helper structure to keep temporary 'best' information about a value or a type scheduled to be reported. This might get overridden be subsequent better guesses during a putItem() run. """ - def __init__(self, value = None, encoding = None, priority = -100, elided = None): + + def __init__(self, value=None, encoding=None, priority=-100, elided=None): self.value = value self.priority = priority self.encoding = encoding @@ -70,7 +71,7 @@ class ReportItem: % (self.value, self.encoding, self.priority, self.elided) -class Timer: +class Timer(): def __init__(self, d, desc): self.d = d self.desc = desc + '-' + d.currentIName @@ -83,9 +84,9 @@ class Timer: self.d.timings.append([self.desc, elapsed]) -class Children: - def __init__(self, d, numChild = 1, childType = None, childNumChild = None, - maxNumChild = None, addrBase = None, addrStep = None): +class Children(): + def __init__(self, d, numChild=1, childType=None, childNumChild=None, + maxNumChild=None, addrBase=None, addrStep=None): self.d = d self.numChild = numChild self.childNumChild = childNumChild @@ -132,7 +133,7 @@ class Children: return True -class SubItem: +class SubItem(): def __init__(self, d, component): self.d = d self.name = component @@ -144,19 +145,22 @@ class SubItem: def __exit__(self, exType, exValue, exTraceBack): return self.d.exitSubItem(self, exType, exValue, exTraceBack) + class TopLevelItem(SubItem): def __init__(self, d, iname): self.d = d self.iname = iname self.name = None + class UnnamedSubItem(SubItem): def __init__(self, d, component): self.d = d self.iname = '%s.%s' % (self.d.currentIName, component) self.name = None -class DumperBase: + +class DumperBase(): @staticmethod def warn(message): print('bridgemessage={msg="%s"},' % message.replace('"', '$').encode('latin1')) @@ -259,7 +263,7 @@ class DumperBase: def resetCaches(self): # This is a cache mapping from 'type name' to 'display alternatives'. - self.qqFormats = { 'QVariant (QVariantMap)' : [DisplayFormat.CompactMapFormat] } + self.qqFormats = {'QVariant (QVariantMap)': [DisplayFormat.CompactMapFormat]} # This is a cache of all known dumpers. self.qqDumpers = {} # Direct type match @@ -326,13 +330,13 @@ class DumperBase: item.savedValue = self.currentValue item.savedType = self.currentType self.currentIName = item.iname - self.currentValue = ReportItem(); - self.currentType = ReportItem(); + self.currentValue = ReportItem() + self.currentType = ReportItem() def exitSubItem(self, item, exType, exValue, exTraceBack): #DumperBase.warn('CURRENT VALUE: %s: %s %s' % # (self.currentIName, self.currentValue, self.currentType)) - if not exType is None: + if exType is not None: if self.passExceptions: self.showException('SUBITEM', exType, exValue, exTraceBack) self.putSpecialValue('notaccessible') @@ -346,7 +350,7 @@ class DumperBase: if self.currentValue.value is None: self.put('value="",encoding="notaccessible",numchild="0",') else: - if not self.currentValue.encoding is None: + if self.currentValue.encoding is not None: self.put('valueencoded="%s",' % self.currentValue.encoding) if self.currentValue.elided: self.put('valueelided="%s",' % self.currentValue.elided) @@ -363,7 +367,7 @@ class DumperBase: typeName = self.currentType.value self.put('<%s> = {' % typeName) - if self.currentValue.value is None: + if self.currentValue.value is None: self.put('') else: value = self.currentValue.value @@ -405,7 +409,7 @@ class DumperBase: inArray -= 1 if inArray and ord(c) >= 48 and ord(c) <= 57: continue - stripped += c + stripped += c self.cachedFormats[typeName] = stripped return stripped @@ -446,13 +450,14 @@ class DumperBase: tdata.typeId = typeId tdata.lbitsize = 16 tdata.code = TypeCode.TypeCodeStruct - tdata.lfields = [self.Field(dumper=self, name='ucs', type='unsigned short', bitsize=16, bitpos=0)] + tdata.lfields = [self.Field(dumper=self, name='ucs', + type='unsigned short', bitsize=16, bitpos=0)] tdata.lalignment = 2 tdata.templateArguments = [] self.registerType(typeId, tdata) def nativeDynamicType(self, address, baseType): - return baseType # Override in backends. + return baseType # Override in backends. def listTemplateParameters(self, typename): return self.listTemplateParametersManually(typename) @@ -467,7 +472,7 @@ class DumperBase: inner = inner.strip()[::-1] p = inner.find(')::') if p > -1: - inner = inner[p+3:].strip() + inner = inner[p + 3:].strip() if inner.startswith('const '): inner = inner[6:].strip() if inner.endswith(' const'): @@ -478,7 +483,7 @@ class DumperBase: #DumperBase.warn("SPLITTING %s" % typename) level = 0 inner = '' - for c in typename[::-1]: # Reversed... + for c in typename[::-1]: # Reversed... #DumperBase.warn("C: %s" % c) if c == '>': if level > 0: @@ -508,7 +513,7 @@ class DumperBase: if len(item) == 0: continue c = ord(item[0]) - if c in (45, 46) or (c >= 48 and c < 58): # '-', '.' or digit. + if c in (45, 46) or (c >= 48 and c < 58): # '-', '.' or digit. if item.find('.') > -1: res.append(float(item)) else: @@ -613,24 +618,26 @@ class DumperBase: return 0, '' data, size, alloc = self.byteArrayDataHelper(addr) if alloc != 0: - self.check(0 <= size and size <= alloc and alloc <= 100*1000*1000) + self.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) elided, shown = self.computeLimit(size, limit) return elided, self.readMemory(data, 2 * shown) def encodeByteArrayHelper(self, addr, limit): data, size, alloc = self.byteArrayDataHelper(addr) if alloc != 0: - self.check(0 <= size and size <= alloc and alloc <= 100*1000*1000) + self.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) elided, shown = self.computeLimit(size, limit) return elided, self.readMemory(data, shown) def putCharArrayValue(self, data, size, charSize, - displayFormat = DisplayFormat.AutomaticFormat): + displayFormat=DisplayFormat.AutomaticFormat): bytelen = size * charSize elided, shown = self.computeLimit(bytelen, self.displayStringLimit) mem = self.readMemory(data, shown) if charSize == 1: - if displayFormat in (DisplayFormat.Latin1StringFormat, DisplayFormat.SeparateLatin1StringFormat): + if displayFormat in ( + DisplayFormat.Latin1StringFormat, + DisplayFormat.SeparateLatin1StringFormat): encodingType = 'latin1' else: encodingType = 'utf8' @@ -644,15 +651,18 @@ class DumperBase: self.putValue(mem, encodingType, elided=elided) - if displayFormat in (DisplayFormat.SeparateLatin1StringFormat, DisplayFormat.SeparateUtf8StringFormat, DisplayFormat.SeparateFormat): + if displayFormat in ( + DisplayFormat.SeparateLatin1StringFormat, + DisplayFormat.SeparateUtf8StringFormat, + DisplayFormat.SeparateFormat): elided, shown = self.computeLimit(bytelen, 100000) self.putDisplay(encodingType + ':separate', self.readMemory(data, shown)) def putCharArrayHelper(self, data, size, charType, - displayFormat = DisplayFormat.AutomaticFormat, - makeExpandable = True): + displayFormat=DisplayFormat.AutomaticFormat, + makeExpandable=True): charSize = charType.size() - self.putCharArrayValue(data, size, charSize, displayFormat = displayFormat) + self.putCharArrayValue(data, size, charSize, displayFormat=displayFormat) if makeExpandable: self.putNumChild(size) @@ -664,7 +674,7 @@ class DumperBase: def readMemory(self, addr, size): return self.hexencode(bytes(self.readRawMemory(addr, size))) - def encodeByteArray(self, value, limit = 0): + def encodeByteArray(self, value, limit=0): elided, data = self.encodeByteArrayHelper(self.extractPointer(value), limit) return data @@ -672,17 +682,18 @@ class DumperBase: return self.byteArrayDataHelper(self.extractPointer(value)) def putByteArrayValue(self, value): - elided, data = self.encodeByteArrayHelper(self.extractPointer(value), self.displayStringLimit) + elided, data = self.encodeByteArrayHelper( + self.extractPointer(value), self.displayStringLimit) self.putValue(data, 'latin1', elided=elided) - def encodeString(self, value, limit = 0): + def encodeString(self, value, limit=0): elided, data = self.encodeStringHelper(self.extractPointer(value), limit) return data def encodedUtf16ToUtf8(self, s): - return ''.join([chr(int(s[i:i+2], 16)) for i in range(0, len(s), 4)]) + return ''.join([chr(int(s[i:i + 2], 16)) for i in range(0, len(s), 4)]) - def encodeStringUtf8(self, value, limit = 0): + def encodeStringUtf8(self, value, limit=0): return self.encodedUtf16ToUtf8(self.encodeString(value, limit)) def stringData(self, value): @@ -692,7 +703,7 @@ class DumperBase: level = 0 skipSpace = False inner = '' - for c in typename[typename.find('<') + 1 : -1]: + for c in typename[typename.find('<') + 1: -1]: if c == '<': inner += c level += 1 @@ -718,7 +729,7 @@ class DumperBase: inner = inner.strip() p = inner.find(')::') if p > -1: - inner = inner[p+3:] + inner = inner[p + 3:] return inner def putStringValue(self, value): @@ -796,7 +807,7 @@ class DumperBase: if address is not None and not self.isCli: self.put('address="0x%x",' % address) - def putPlainChildren(self, value, dumpBase = True): + def putPlainChildren(self, value, dumpBase=True): self.putEmptyValue(-99) self.putNumChild(1) if self.isExpanded(): @@ -829,7 +840,7 @@ class DumperBase: p += self.ptrSize() return itemCount - def putFields(self, value, dumpBase = True): + def putFields(self, value, dumpBase=True): baseIndex = 0 for item in value.members(True): if item.name is not None: @@ -861,8 +872,7 @@ class DumperBase: with SubItem(self, item.name): self.putItem(item) - - def putMembersItem(self, value, sortorder = 10): + def putMembersItem(self, value, sortorder=10): with SubItem(self, '[members]'): self.putField('sortgroup', sortorder) self.putPlainChildren(value) @@ -912,7 +922,7 @@ class DumperBase: elided, shown, blob = self.readToFirstZero(p, tsize, limit) return elided, blob - def putItemCount(self, count, maximum = 1000000000): + def putItemCount(self, count, maximum=1000000000): # This needs to override the default value, so don't use 'put' directly. if count > maximum: self.putSpecialValue('minimumitemcount', maximum) @@ -921,20 +931,20 @@ class DumperBase: self.putNumChild(count) def resultToMi(self, value): - if type(value) is bool: + if isinstance(value, bool): return '"%d"' % int(value) - if type(value) is dict: + if isinstance(value, dict): return '{' + ','.join(['%s=%s' % (k, self.resultToMi(v)) - for (k, v) in list(value.items())]) + '}' - if type(value) is list: + for (k, v) in list(value.items())]) + '}' + if isinstance(value, list): return '[' + ','.join([self.resultToMi(k) - for k in list(value.items())]) + ']' + for k in list(value.items())]) + ']' return '"%s"' % value def variablesToMi(self, value, prefix): - if type(value) is bool: + if isinstance(value, bool): return '"%d"' % int(value) - if type(value) is dict: + if isinstance(value, dict): pairs = [] for (k, v) in list(value.items()): if k == 'iname': @@ -946,7 +956,7 @@ class DumperBase: v = self.variablesToMi(v, prefix) pairs.append('%s=%s' % (k, v)) return '{' + ','.join(pairs) + '}' - if type(value) is list: + if isinstance(value, list): index = 0 pairs = [] for item in value: @@ -957,7 +967,7 @@ class DumperBase: name = str(index) index += 1 pairs.append((name, self.variablesToMi(item, prefix))) - pairs.sort(key = lambda pair: pair[0]) + pairs.sort(key=lambda pair: pair[0]) return '[' + ','.join([pair[1] for pair in pairs]) + ']' return '"%s"' % value @@ -1016,7 +1026,7 @@ class DumperBase: def putField(self, name, value): self.put('%s="%s",' % (name, value)) - def putType(self, typish, priority = 0): + def putType(self, typish, priority=0): # Higher priority values override lower ones. if priority >= self.currentType.priority: types = (str) if sys.version_info[0] >= 3 else (str, unicode) @@ -1026,14 +1036,14 @@ class DumperBase: self.currentType.value = typish.name self.currentType.priority = priority - def putValue(self, value, encoding = None, priority = 0, elided = None): + def putValue(self, value, encoding=None, priority=0, elided=None): # Higher priority values override lower ones. # elided = 0 indicates all data is available in value, # otherwise it's the true length. if priority >= self.currentValue.priority: self.currentValue = ReportItem(value, encoding, priority, elided) - def putSpecialValue(self, encoding, value = '', children = None): + def putSpecialValue(self, encoding, value='', children=None): self.putValue(value, encoding) if children is not None: self.putNumChild(1) @@ -1043,7 +1053,7 @@ class DumperBase: with SubItem(self, name): self.putValue(str(value).replace('"', '$')) - def putEmptyValue(self, priority = -10): + def putEmptyValue(self, priority=-10): if priority >= self.currentValue.priority: self.currentValue = ReportItem('', None, priority, None) @@ -1081,7 +1091,7 @@ class DumperBase: def mangleName(self, typeName): return '_ZN%sE' % ''.join(map(lambda x: '%d%s' % (len(x), x), - typeName.split('::'))) + typeName.split('::'))) def putCStyleArray(self, value): arrayType = value.type.unqualified() @@ -1090,7 +1100,7 @@ class DumperBase: innerType = value.type.target().unqualified() address = value.address() if address: - self.putValue('@0x%x' % address, priority = -1) + self.putValue('@0x%x' % address, priority=-1) else: self.putEmptyValue() self.putType(arrayType) @@ -1102,20 +1112,27 @@ class DumperBase: # GDB/GCC produce sizeof == 0 for QProcess arr[3] # And in the Nim string dumper. s = value.type.name - itemCount = s[s.find('[')+1:s.find(']')] + itemCount = s[s.find('[') + 1:s.find(']')] if not itemCount: itemCount = '100' - arrayByteSize = int(itemCount) * innerType.size(); + arrayByteSize = int(itemCount) * innerType.size() n = arrayByteSize // innerType.size() p = value.address() if displayFormat != DisplayFormat.RawFormat and p: - if innerType.name in ('char', 'wchar_t', 'unsigned char', 'signed char', 'CHAR', 'WCHAR'): + if innerType.name in ( + 'char', + 'wchar_t', + 'unsigned char', + 'signed char', + 'CHAR', + 'WCHAR' + ): self.putCharArrayHelper(p, n, innerType, self.currentItemFormat(), - makeExpandable = False) + makeExpandable=False) else: self.tryPutSimpleFormattedPointer(p, arrayType, innerType, - displayFormat, arrayByteSize) + displayFormat, arrayByteSize) self.putNumChild(n) if self.isExpanded(): @@ -1146,10 +1163,10 @@ class DumperBase: continue elif s == '>': lvl -= 1 - if lvl < 0 : + if lvl < 0: raise RuntimeError("Unbalanced '<' in type, @index %d" % index) if lvl == 0: - stripChunks.append((pos, index+1)) + stripChunks.append((pos, index + 1)) if lvl != 0: raise RuntimeError("unbalanced at end of type name") for (f, l) in reversed(stripChunks): @@ -1190,7 +1207,7 @@ class DumperBase: return False - def putSimpleCharArray(self, base, size = None): + def putSimpleCharArray(self, base, size=None): if size is None: elided, shown, data = self.readToFirstZero(base, 1, self.displayStringLimit) else: @@ -1276,7 +1293,7 @@ class DumperBase: def putDerefedPointer(self, value): derefValue = value.dereference() - innerType = value.type.target() #.unqualified() + innerType = value.type.target() # .unqualified() self.putType(innerType) savedCurrentChildType = self.currentChildType self.currentChildType = innerType.name @@ -1315,7 +1332,7 @@ class DumperBase: return displayFormat = self.currentItemFormat(value.type.name) - innerType = value.type.target() #.unqualified() + innerType = value.type.target() # .unqualified() if innerType.name == 'void': #DumperBase.warn('VOID POINTER: %s' % displayFormat) @@ -1337,7 +1354,9 @@ class DumperBase: return limit = self.displayStringLimit - if displayFormat in (DisplayFormat.SeparateLatin1StringFormat, DisplayFormat.SeparateUtf8StringFormat): + if displayFormat in ( + DisplayFormat.SeparateLatin1StringFormat, + DisplayFormat.SeparateUtf8StringFormat): limit = 1000000 if self.tryPutSimpleFormattedPointer(pointer, typeName, innerType, displayFormat, limit): @@ -1363,7 +1382,14 @@ class DumperBase: #DumperBase.warn('INNER: %s' % innerType.name) if self.autoDerefPointers: # Generic pointer type with AutomaticFormat, but never dereference char types: - if innerType.name not in ('char', 'signed char', 'unsigned char', 'wchar_t', 'CHAR', 'WCHAR'): + if innerType.name not in ( + 'char', + 'signed char', + 'unsigned char', + 'wchar_t', + 'CHAR', + 'WCHAR' + ): self.putDerefedPointer(value) return @@ -1439,7 +1465,7 @@ class DumperBase: return True except: - # warn('NO QOBJECT: %s' % value.type) + # warn('NO QOBJECT: %s' % value.type) return False def couldBePointer(self, p): @@ -1487,7 +1513,7 @@ class DumperBase: offset = int.from_bytes(data[1:5], byteorder='little') return address + 5 + offset if primaryOpcode == jumpCode: - if data[1] != 0x25: # check for known extended opcode + if data[1] != 0x25: # check for known extended opcode return 0 # 0xff25 is a relative jump on 64bit and an absolute jump on 32 bit if self.ptrSize() == 8: @@ -1595,7 +1621,7 @@ class DumperBase: someTypeName = someTypeObj.name self.bump('metaObjectFromType') known = self.knownStaticMetaObjects.get(someTypeName, None) - if known is not None: # Is 0 or the static metaobject. + if known is not None: # Is 0 or the static metaobject. return known result = 0 @@ -1615,7 +1641,6 @@ class DumperBase: self.knownStaticMetaObjects[someTypeName] = result return result - if not self.useFancy: return 0 @@ -1623,7 +1648,7 @@ class DumperBase: typeName = typeobj.name result = self.knownStaticMetaObjects.get(typeName, None) - if result is not None: # Is 0 or the static metaobject. + if result is not None: # Is 0 or the static metaobject. self.bump('typecached') #DumperBase.warn('CACHED RESULT: %s %s 0x%x' % (self.currentIName, typeName, result)) return result @@ -1715,7 +1740,7 @@ class DumperBase: def metaString(self, metaObjectPtr, index, revision): ptrSize = self.ptrSize() stringdata = self.extractPointer(toInteger(metaObjectPtr) + ptrSize) - if revision >= 7: # Qt 5. + if revision >= 7: # Qt 5. byteArrayDataSize = 24 if ptrSize == 8 else 16 literal = stringdata + toInteger(index) * byteArrayDataSize ldata, lsize, lalloc = self.byteArrayDataHelper(literal) @@ -1724,7 +1749,7 @@ class DumperBase: return s if sys.version_info[0] == 2 else s.decode('utf8') except: return '' - else: # Qt 4. + else: # Qt 4. ldata = stringdata + index return self.extractCString(ldata).decode('utf8') @@ -1757,7 +1782,7 @@ class DumperBase: intSize = 4 ptrSize = self.ptrSize() - def putt(name, value, typeName = ' '): + def putt(name, value, typeName=' '): with SubItem(self, name): self.putValue(value) self.putType(typeName) @@ -1797,16 +1822,16 @@ class DumperBase: dd = self.extractPointer(qobjectPtr + ptrSize) if self.qtVersion() >= 0x50000: (dvtablePtr, qptr, parentPtr, childrenDPtr, flags, postedEvents, - dynMetaObjectPtr, # Up to here QObjectData. + dynMetaObjectPtr, # Up to here QObjectData. extraData, threadDataPtr, connectionListsPtr, sendersPtr, currentSenderPtr) \ - = self.split('ppppIIp' + 'ppppp', dd) + = self.split('ppppIIp' + 'ppppp', dd) else: (dvtablePtr, qptr, parentPtr, childrenDPtr, flags, postedEvents, - dynMetaObjectPtr, # Up to here QObjectData + dynMetaObjectPtr, # Up to here QObjectData objectName, extraData, threadDataPtr, connectionListsPtr, sendersPtr, currentSenderPtr) \ - = self.split('ppppIIp' + 'pppppp', dd) + = self.split('ppppIIp' + 'pppppp', dd) if qobjectPtr: qobjectType = self.createType('QObject') @@ -1820,7 +1845,7 @@ class DumperBase: self.putNumChild(0) with SubItem(self, '[children]'): self.putField('sortgroup', 8) - base = self.extractPointer(dd + 3 * ptrSize) # It's a QList + base = self.extractPointer(dd + 3 * ptrSize) # It's a QList begin = self.extractInt(base + 8) end = self.extractInt(base + 12) array = base + 16 @@ -1884,51 +1909,52 @@ class DumperBase: with Children(self): if extraData: self.putTypedPointer('[extraData]', extraData, - ns + 'QObjectPrivate::ExtraData') + ns + 'QObjectPrivate::ExtraData') with SubItem(self, '[metaObject]'): self.putAddress(metaObjectPtr) self.putNumChild(1) if self.isExpanded(): with Children(self): - self.putQObjectGutsHelper(0, 0, -1, metaObjectPtr, 'QMetaObject') + self.putQObjectGutsHelper( + 0, 0, -1, metaObjectPtr, 'QMetaObject') if False: - with SubItem(self, '[connections]'): - if connectionListsPtr: - typeName = '@QObjectConnectionListVector' - self.putItem(self.createValue(connectionListsPtr, typeName)) - else: - self.putItemCount(0) + with SubItem(self, '[connections]'): + if connectionListsPtr: + typeName = '@QObjectConnectionListVector' + self.putItem(self.createValue(connectionListsPtr, typeName)) + else: + self.putItemCount(0) if False: - with SubItem(self, '[signals]'): - self.putItemCount(signalCount) - if self.isExpanded(): - with Children(self): - j = -1 - for i in range(signalCount): - t = self.split('IIIII', dataPtr + 56 + 20 * i) - flags = t[4] - if flags != 0x06: - continue - j += 1 - with SubItem(self, j): - name = self.metaString(metaObjectPtr, t[0], revision) - self.putType(' ') - self.putValue(name) - self.putNumChild(1) - with Children(self): - putt('[nameindex]', t[0]) - #putt('[type]', 'signal') - putt('[argc]', t[1]) - putt('[parameter]', t[2]) - putt('[tag]', t[3]) - putt('[flags]', t[4]) - putt('[localindex]', str(i)) - putt('[globalindex]', str(globalOffset + i)) - #self.putQObjectConnections(dd) - + with SubItem(self, '[signals]'): + self.putItemCount(signalCount) + if self.isExpanded(): + with Children(self): + j = -1 + for i in range(signalCount): + t = self.split('IIIII', dataPtr + 56 + 20 * i) + flags = t[4] + if flags != 0x06: + continue + j += 1 + with SubItem(self, j): + name = self.metaString( + metaObjectPtr, t[0], revision) + self.putType(' ') + self.putValue(name) + self.putNumChild(1) + with Children(self): + putt('[nameindex]', t[0]) + #putt('[type]', 'signal') + putt('[argc]', t[1]) + putt('[parameter]', t[2]) + putt('[tag]', t[3]) + putt('[flags]', t[4]) + putt('[localindex]', str(i)) + putt('[globalindex]', str(globalOffset + i)) + #self.putQObjectConnections(dd) if isQMetaObject or isQObject: with SubItem(self, '[properties]'): @@ -1941,14 +1967,14 @@ class DumperBase: t = self.split('III', dataPtr + properties * 4 + 12 * i) name = self.metaString(metaObjectPtr, t[0], revision) if qobject and self.qtPropertyFunc: - # LLDB doesn't like calling it on a derived class, possibly - # due to type information living in a different shared object. - #base = self.createValue(qobjectPtr, '@QObject') - #DumperBase.warn("CALL FUNC: 0x%x" % self.qtPropertyFunc) + # LLDB doesn't like calling it on a derived class, possibly + # due to type information living in a different shared object. + #base = self.createValue(qobjectPtr, '@QObject') + #DumperBase.warn("CALL FUNC: 0x%x" % self.qtPropertyFunc) cmd = '((QVariant(*)(void*,char*))0x%x)((void*)0x%x,"%s")' \ - % (self.qtPropertyFunc, qobjectPtr, name) + % (self.qtPropertyFunc, qobjectPtr, name) try: - #DumperBase.warn('PROP CMD: %s' % cmd) + #DumperBase.warn('PROP CMD: %s' % cmd) res = self.parseAndEvaluate(cmd) #DumperBase.warn('PROP RES: %s' % res) except: @@ -1979,7 +2005,7 @@ class DumperBase: values = self.listChildrenGenerator( extraData + 2 * ptrSize, variantType.pointer()) names = self.listChildrenGenerator( - extraData + ptrSize, byteArrayType) + extraData + ptrSize, byteArrayType) for (k, v) in zip(names, values): with SubItem(self, propertyCount + dynamicPropertyCount): self.putField('key', self.encodeByteArray(k)) @@ -2000,7 +2026,7 @@ class DumperBase: superDataIterator = superDataPtr while superDataIterator: sdata = extractDataPtr(superDataIterator) - globalOffset += self.extractInt(sdata + 16) # methodCount member + globalOffset += self.extractInt(sdata + 16) # methodCount member superDataIterator = extractSuperDataPtr(superDataIterator) if isQMetaObject or isQObject: @@ -2066,7 +2092,6 @@ class DumperBase: self.putField('sortgroup', 11) self.putValue(globalOffset + localIndex) - def putQObjectConnections(self, dd): with SubItem(self, '[connections]'): ptrSize = self.ptrSize() @@ -2093,14 +2118,14 @@ class DumperBase: first = self.extractPointer(data + i * 2 * ptrSize) while first: self.putSubItem('%s' % pp, - self.createPointerValue(first, connectionType)) + self.createPointerValue(first, connectionType)) first = self.extractPointer(first + 3 * ptrSize) # We need to enforce some upper limit. pp += 1 if pp > 1000: break - def currentItemFormat(self, typeName = None): + def currentItemFormat(self, typeName=None): displayFormat = self.formats.get(self.currentIName, DisplayFormat.AutomaticFormat) if displayFormat == DisplayFormat.AutomaticFormat: if typeName is None: @@ -2109,7 +2134,7 @@ class DumperBase: displayFormat = self.typeformats.get(needle, DisplayFormat.AutomaticFormat) return displayFormat - def putSubItem(self, component, value): # -> ReportItem + def putSubItem(self, component, value): # -> ReportItem if not isinstance(value, self.Value): raise RuntimeError('WRONG VALUE TYPE IN putSubItem: %s' % type(value)) if not isinstance(value.type, self.Type): @@ -2120,7 +2145,7 @@ class DumperBase: res = self.currentValue return res # The 'short' display. - def putArrayData(self, base, n, innerType, childNumChild = None, maxNumChild = 10000): + def putArrayData(self, base, n, innerType, childNumChild=None, maxNumChild=10000): self.checkIntType(base) self.checkIntType(n) addrBase = base @@ -2134,14 +2159,14 @@ class DumperBase: self.put('addrstep="0x%x",' % innerSize) self.put('arrayencoding="%s",' % enc) if n > maxNumChild: - self.put('childrenelided="%s",' % n) # FIXME: Act on that in frontend + self.put('childrenelided="%s",' % n) # FIXME: Act on that in frontend n = maxNumChild self.put('arraydata="') self.put(self.readMemory(addrBase, n * innerSize)) self.put('",') else: with Children(self, n, innerType, childNumChild, maxNumChild, - addrBase=addrBase, addrStep=innerSize): + addrBase=addrBase, addrStep=innerSize): for i in self.childRange(): self.putSubItem(i, self.createValue(addrBase + i * innerSize, innerType)) @@ -2154,9 +2179,9 @@ class DumperBase: self.putArrayData(addr, n, self.lookupType(typeName)) self.putAddress(addr) - def putPlotDataHelper(self, base, n, innerType, maxNumChild = 1000*1000): + def putPlotDataHelper(self, base, n, innerType, maxNumChild=1000 * 1000): if n > maxNumChild: - self.putField('plotelided', n) # FIXME: Act on that in frontend + self.putField('plotelided', n) # FIXME: Act on that in frontend n = maxNumChild if self.currentItemFormat() == DisplayFormat.ArrayPlotFormat and innerType.isSimpleType(): enc = innerType.simpleEncoding() @@ -2165,7 +2190,7 @@ class DumperBase: self.putDisplay('plotdata:separate', self.readMemory(base, n * innerType.size())) - def putPlotData(self, base, n, innerType, maxNumChild = 1000*1000): + def putPlotData(self, base, n, innerType, maxNumChild=1000 * 1000): self.putPlotDataHelper(base, n, innerType, maxNumChild=maxNumChild) if self.isExpanded(): self.putArrayData(base, n, innerType, maxNumChild=maxNumChild) @@ -2262,21 +2287,21 @@ class DumperBase: return i return len(s) - match = re.search('(\.)(\(.+?\))?(\.)', exp) + match = re.search(r'(\.)(\(.+?\))?(\.)', exp) if match: s = match.group(2) left_e = match.start(1) - left_s = 1 + left_e - searchUnbalanced(exp[left_e::-1], False) + left_s = 1 + left_e - searchUnbalanced(exp[left_e::-1], False) right_s = match.end(3) right_e = right_s + searchUnbalanced(exp[right_s:], True) - template = exp[:left_s] + '%s' + exp[right_e:] + template = exp[:left_s] + '%s' + exp[right_e:] a = exp[left_s:left_e] b = exp[right_s:right_e] try: # Allow integral expressions. - ss = self.parseAndEvaluate(s[1:len(s)-1]).integer() if s else 1 + ss = self.parseAndEvaluate(s[1:len(s) - 1]).integer() if s else 1 aa = self.parseAndEvaluate(a).integer() bb = self.parseAndEvaluate(b).integer() if aa < bb and ss > 0: @@ -2403,7 +2428,7 @@ class DumperBase: except: pass - def setupDumpers(self, _ = {}): + def setupDumpers(self, _={}): self.resetCaches() for mod in self.dumpermodules: @@ -2469,14 +2494,14 @@ class DumperBase: def reportInterpreterResult(self, resdict, args): print('interpreterresult=%s,token="%s"' - % (self.resultToMi(resdict), args.get('token', -1))) + % (self.resultToMi(resdict), args.get('token', -1))) def reportInterpreterAsync(self, resdict, asyncclass): print('interpreterasync=%s,asyncclass="%s"' - % (self.resultToMi(resdict), asyncclass)) + % (self.resultToMi(resdict), asyncclass)) def removeInterpreterBreakpoint(self, args): - res = self.sendInterpreterRequest('removebreakpoint', { 'id' : args['id'] }) + res = self.sendInterpreterRequest('removebreakpoint', {'id': args['id']}) return res def insertInterpreterBreakpoint(self, args): @@ -2516,12 +2541,12 @@ class DumperBase: # msg is a sequence of 'servicenamemsglenmsg' items. resdict = {} # Native payload. while len(msg): - pos0 = msg.index(' ') # End of service name - pos1 = msg.index(' ', pos0 + 1) # End of message length + pos0 = msg.index(' ') # End of service name + pos1 = msg.index(' ', pos0 + 1) # End of message length service = msg[0:pos0] - msglen = int(msg[pos0+1:pos1]) - msgend = pos1+1+msglen - payload = msg[pos1+1:msgend] + msglen = int(msg[pos0 + 1:pos1]) + msgend = pos1 + 1 + msglen + payload = msg[pos1 + 1:msgend] msg = msg[msgend:] if service == 'NativeQmlDebugger': try: @@ -2531,7 +2556,7 @@ class DumperBase: self.warn('Cannot parse native payload: %s' % payload) else: print('interpreteralien=%s' - % {'service': service, 'payload': self.hexencode(payload)}) + % {'service': service, 'payload': self.hexencode(payload)}) try: expr = 'qt_qmlDebugClearBuffer()' res = self.parseAndEvaluate(expr) @@ -2540,8 +2565,8 @@ class DumperBase: return resdict - def sendInterpreterRequest(self, command, args = {}): - encoded = json.dumps({ 'command': command, 'arguments': args }) + def sendInterpreterRequest(self, command, args={}): + encoded = json.dumps({'command': command, 'arguments': args}) hexdata = self.hexencode(encoded) expr = 'qt_qmlDebugSendDataToService("NativeQmlDebugger","%s")' % hexdata try: @@ -2586,12 +2611,12 @@ class DumperBase: if wasPending: if not bp: self.reportInterpreterResult({'bpnr': -1, 'pending': 1, - 'error': 'Pending interpreter breakpoint insertion failed.'}, args) + 'error': 'Pending interpreter breakpoint insertion failed.'}, args) return else: if not bp: self.reportInterpreterResult({'bpnr': -1, 'pending': 1, - 'warning': 'Direct interpreter breakpoint insertion failed.'}, args) + 'warning': 'Direct interpreter breakpoint insertion failed.'}, args) self.createResolvePendingBreakpointsHookBreakpoint(args) return self.reportInterpreterResult({'bpnr': bp, 'pending': 0}, args) @@ -2612,7 +2637,7 @@ class DumperBase: return functionName and functionName.find('QV4::Moth::VME::exec') >= 0 def extractInterpreterStack(self): - return self.sendInterpreterRequest('backtrace', {'limit': 10 }) + return self.sendInterpreterRequest('backtrace', {'limit': 10}) def isInt(self, thing): if isinstance(thing, int): @@ -2636,10 +2661,10 @@ class DumperBase: def putItemX(self, value): #DumperBase.warn('PUT ITEM: %s' % value.stringify()) - typeobj = value.type #unqualified() + typeobj = value.type # unqualified() typeName = typeobj.name - self.addToCache(typeobj) # Fill type cache + self.addToCache(typeobj) # Fill type cache if not value.lIsInScope: self.putSpecialValue('optimizedout') @@ -2696,7 +2721,8 @@ class DumperBase: #DumperBase.warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typeName)) self.putNumChild(0) dd = typeobj.ltarget.typeData().enumDisplay - self.putValue(str(value.lvalue) if dd is None else dd(value.lvalue, value.laddress, '%d')) + self.putValue(str(value.lvalue) if dd is None else dd( + value.lvalue, value.laddress, '%d')) self.putType(typeName) return @@ -2810,19 +2836,19 @@ class DumperBase: self.typesReported[typename] = True self.typesToReport[typename] = typeobj - class Value: + class Value(): def __init__(self, dumper): self.dumper = dumper self.name = None self.type = None - self.ldata = None # Target address in case of references and pointers. - self.laddress = None # Own address. + self.ldata = None # Target address in case of references and pointers. + self.laddress = None # Own address. self.lIsInScope = True self.ldisplay = None - self.summary = None # Always hexencoded UTF-8. + self.summary = None # Always hexencoded UTF-8. self.lbitpos = None self.lbitsize = None - self.targetValue = None # For references. + self.targetValue = None # For references. self.isBaseClass = None self.nativeValue = None @@ -2858,8 +2884,8 @@ class DumperBase: def stringify(self): addr = 'None' if self.laddress is None else ('0x%x' % self.laddress) return "Value(name='%s',type=%s,bsize=%s,bpos=%s,data=%s,address=%s)" \ - % (self.name, self.type.name, self.lbitsize, self.lbitpos, - self.dumper.hexencode(self.ldata), addr) + % (self.name, self.type.name, self.lbitsize, self.lbitpos, + self.dumper.hexencode(self.ldata), addr) def displayEnum(self, form='%d', bitsize=None): intval = self.integer(bitsize) @@ -2894,8 +2920,8 @@ class DumperBase: return self.lvalue # Could be something like 'short unsigned int' unsigned = self.type.name == 'unsigned' \ - or self.type.name.startswith('unsigned ') \ - or self.type.name.find(' unsigned ') != -1 + or self.type.name.startswith('unsigned ') \ + or self.type.name.find(' unsigned ') != -1 if bitsize is None: bitsize = self.type.bitsize() return self.extractInteger(bitsize, unsigned) @@ -2970,7 +2996,10 @@ class DumperBase: self.check() if self.type.code == TypeCode.TypeCodeTypedef: return self.findMemberByName(self.detypedef()) - if self.type.code in (TypeCode.TypeCodePointer, TypeCode.TypeCodeReference, TypeCode.TypeCodeRValueReference): + if self.type.code in ( + TypeCode.TypeCodePointer, + TypeCode.TypeCodeReference, + TypeCode.TypeCodeRValueReference): res = self.dereference().findMemberByName(name) if res is not None: return res @@ -2987,7 +3016,7 @@ class DumperBase: for member in members: if member.type.code == TypeCode.TypeCodeTypedef: member = member.detypedef() - if member.name == name: # Could be base class. + if member.name == name: # Could be base class. return member if member.type.code == TypeCode.TypeCodeStruct: res = member.findMemberByName(name) @@ -3008,7 +3037,7 @@ class DumperBase: res = self.findMemberByName(index) if res is None: raise RuntimeError('No member named %s in type %s' - % (index, self.type.name)) + % (index, self.type.name)) return res elif isinstance(index, self.dumper.Field): field = index @@ -3223,7 +3252,7 @@ class DumperBase: self.check() return self.laddress - def data(self, size = None): + def data(self, size=None): self.check() if self.ldata is not None: if len(self.ldata) > 0: @@ -3282,6 +3311,7 @@ class DumperBase: (pp, size, fields) = self.dumper.describeStruct(pattern) #DumperBase.warn('SIZE: %s ' % size) result = struct.unpack_from(self.dumper.packCode + pp, self.data(size)) + def structFixer(field, thing): #DumperBase.warn('STRUCT MEMBER: %s' % type(thing)) if field.isStruct: @@ -3299,7 +3329,7 @@ class DumperBase: raise RuntimeError('STRUCT ERROR: %s %s' % (fields, result)) return tuple(map(structFixer, fields, result)) - def checkPointer(self, p, align = 1): + def checkPointer(self, p, align=1): ptr = p if self.isInt(p) else p.pointer() self.readRawMemory(ptr, 1) @@ -3316,8 +3346,8 @@ class DumperBase: if type_name[pos1 - 1] != ']': break - item_count = type_name[pos1+1:pos2] - return (type_name[0:pos1].strip(), type_name[pos2+1:].strip(), int(item_count)) + item_count = type_name[pos1 + 1:pos2] + return (type_name[0:pos1].strip(), type_name[pos2 + 1:].strip(), int(item_count)) def registerType(self, typeId, tdata): #DumperBase.warn('REGISTER TYPE: %s' % typeId) @@ -3330,13 +3360,13 @@ class DumperBase: #DumperBase.warn('REGISTER ALIAS %s FOR %s' % (aliasId, existingTypeId)) self.typeData[aliasId] = self.typeData[existingTypeId] - class TypeData: + class TypeData(): def __init__(self, dumper): self.dumper = dumper - self.lfields = None # None or Value -> list of member Values - self.lalignment = None # Function returning alignment of this struct + self.lfields = None # None or Value -> list of member Values + self.lalignment = None # Function returning alignment of this struct self.lbitsize = None - self.ltarget = None # Inner type for arrays + self.ltarget = None # Inner type for arrays self.templateArguments = [] self.code = None self.name = None @@ -3359,7 +3389,7 @@ class DumperBase: tdata.moduleName = self.moduleName return tdata - class Type: + class Type(): def __init__(self, dumper, typeId): self.typeId = typeId self.dumper = dumper @@ -3413,7 +3443,7 @@ class DumperBase: if tdata is None: return 'Type(id="%s")' % self.typeId return 'Type(name="%s",bsize=%s,code=%s)' \ - % (tdata.name, tdata.lbitsize, tdata.code) + % (tdata.name, tdata.lbitsize, tdata.code) def __getitem__(self, index): if self.dumper.isInt(index): @@ -3448,7 +3478,8 @@ class DumperBase: def check(self): tdata = self.typeData() if tdata is None: - raise RuntimeError('TYPE WITHOUT DATA: %s ALL: %s' % (self.typeId, self.dumper.typeData.keys())) + raise RuntimeError('TYPE WITHOUT DATA: %s ALL: %s' % + (self.typeId, self.dumper.typeData.keys())) if tdata.name is None: raise RuntimeError('TYPE WITHOUT NAME: %s' % self.typeId) @@ -3485,34 +3516,43 @@ class DumperBase: def simpleEncoding(self): res = { - 'bool' : 'int:1', - 'char' : 'int:1', - 'signed char' : 'int:1', - 'unsigned char' : 'uint:1', - 'short' : 'int:2', - 'unsigned short' : 'uint:2', - 'int' : 'int:4', - 'unsigned int' : 'uint:4', - 'long long' : 'int:8', - 'unsigned long long' : 'uint:8', + 'bool': 'int:1', + 'char': 'int:1', + 'signed char': 'int:1', + 'unsigned char': 'uint:1', + 'short': 'int:2', + 'unsigned short': 'uint:2', + 'int': 'int:4', + 'unsigned int': 'uint:4', + 'long long': 'int:8', + 'unsigned long long': 'uint:8', 'float': 'float:4', 'double': 'float:8' }.get(self.name, None) return res def isSimpleType(self): - return self.code in (TypeCode.TypeCodeIntegral, TypeCode.TypeCodeFloat, TypeCode.TypeCodeEnum) + return self.code in ( + TypeCode.TypeCodeIntegral, + TypeCode.TypeCodeFloat, + TypeCode.TypeCodeEnum) def alignment(self): tdata = self.typeData() if tdata.code == TypeCode.TypeCodeTypedef: return tdata.ltarget.alignment() - if tdata.code in (TypeCode.TypeCodeIntegral, TypeCode.TypeCodeFloat, TypeCode.TypeCodeEnum): + if tdata.code in ( + TypeCode.TypeCodeIntegral, + TypeCode.TypeCodeFloat, + TypeCode.TypeCodeEnum): if tdata.name in ('double', 'long long', 'unsigned long long'): # Crude approximation. return 8 if self.dumper.isWindowsTarget() else self.dumper.ptrSize() return self.size() - if tdata.code in (TypeCode.TypeCodePointer, TypeCode.TypeCodeReference, TypeCode.TypeCodeRValueReference): + if tdata.code in ( + TypeCode.TypeCodePointer, + TypeCode.TypeCodeReference, + TypeCode.TypeCodeRValueReference): return self.dumper.ptrSize() if tdata.lalignment is not None: #if isinstance(tdata.lalignment, function): # Does not work that way. @@ -3545,7 +3585,10 @@ class DumperBase: raise RuntimeError('DONT KNOW SIZE: %s' % self) def isMovableType(self): - if self.code in (TypeCode.TypeCodePointer, TypeCode.TypeCodeIntegral, TypeCode.TypeCodeFloat): + if self.code in ( + TypeCode.TypeCodePointer, + TypeCode.TypeCodeIntegral, + TypeCode.TypeCodeFloat): return True strippedName = self.dumper.stripNamespaceFromType(self.name) if strippedName in ( @@ -3559,7 +3602,7 @@ class DumperBase: 'QUrl', 'QVariant', 'QXmlStreamAttribute', 'QXmlStreamNamespaceDeclaration', 'QXmlStreamNotationDeclaration', 'QXmlStreamEntityDeclaration' - ): + ): return True if strippedName == 'QStringList': return self.dumper.qtVersion() >= 0x050000 @@ -3568,14 +3611,14 @@ class DumperBase: return False class Field(collections.namedtuple('Field', - ['dumper', 'name', 'type', 'bitsize', 'bitpos', - 'extractor', 'isBase', 'isStruct', 'isArtificial' ])): + ['dumper', 'name', 'type', 'bitsize', 'bitpos', + 'extractor', 'isBase', 'isStruct', 'isArtificial'])): def __new__(cls, dumper, name=None, type=None, bitsize=None, bitpos=None, extractor=None, isBase=False, isStruct=False, isArtificial=False): return super(DumperBase.Field, cls).__new__( - cls, dumper, name, type, bitsize, bitpos, - extractor, isBase, isStruct, isArtificial) + cls, dumper, name, type, bitsize, bitpos, + extractor, isBase, isStruct, isArtificial) __slots__ = () @@ -3586,7 +3629,7 @@ class DumperBase: #return 'Field(name="%s")' % self.name typename = None if self.type is None else self.type.stringify() return 'Field(name="%s",type=%s,bitpos=%s,bitsize=%s)' \ - % (self.name, typename, self.bitpos, self.bitsize) + % (self.name, typename, self.bitpos, self.bitsize) def check(self): pass @@ -3617,10 +3660,10 @@ class DumperBase: def createPointerValue(self, targetAddress, targetTypish): if not isinstance(targetTypish, self.Type) and not isinstance(targetTypish, str): raise RuntimeError('Expected type in createPointerValue(), got %s' - % type(targetTypish)) + % type(targetTypish)) if not self.isInt(targetAddress): raise RuntimeError('Expected integral address value in createPointerValue(), got %s' - % type(targetTypish)) + % type(targetTypish)) val = self.Value(self) val.ldata = self.toPointerData(targetAddress) targetType = self.createType(targetTypish).dynamicType(targetAddress) @@ -3630,10 +3673,10 @@ class DumperBase: def createReferenceValue(self, targetAddress, targetType): if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createReferenceValue(), got %s' - % type(targetType)) + % type(targetType)) if not self.isInt(targetAddress): raise RuntimeError('Expected integral address value in createReferenceValue(), got %s' - % type(targetType)) + % type(targetType)) val = self.Value(self) val.ldata = self.toPointerData(targetAddress) targetType = targetType.dynamicType(targetAddress) @@ -3643,7 +3686,7 @@ class DumperBase: def createPointerType(self, targetType): if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createPointerType(), got %s' - % type(targetType)) + % type(targetType)) typeId = targetType.typeId + ' *' tdata = self.TypeData(self) tdata.name = targetType.name + '*' @@ -3657,7 +3700,7 @@ class DumperBase: def createReferenceType(self, targetType): if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createReferenceType(), got %s' - % type(targetType)) + % type(targetType)) typeId = targetType.typeId + ' &' tdata = self.TypeData(self) tdata.name = targetType.name + ' &' @@ -3672,7 +3715,7 @@ class DumperBase: def createRValueReferenceType(self, targetType): if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createRValueReferenceType(), got %s' - % type(targetType)) + % type(targetType)) typeId = targetType.typeId + ' &&' tdata = self.TypeData(self) tdata.name = targetType.name + ' &&' @@ -3686,7 +3729,7 @@ class DumperBase: def createArrayType(self, targetType, count): if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createArrayType(), got %s' - % type(targetType)) + % type(targetType)) targetTypeId = targetType.typeId if targetTypeId.endswith(']'): @@ -3709,7 +3752,7 @@ class DumperBase: def createBitfieldType(self, targetType, bitsize): if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createBitfieldType(), got %s' - % type(targetType)) + % type(targetType)) typeId = '%s:%d' % (targetType.typeId, bitsize) tdata = self.TypeData(self) tdata.name = '%s : %d' % (targetType.typeId, bitsize) @@ -3720,12 +3763,12 @@ class DumperBase: self.registerType(typeId, tdata) return self.Type(self, typeId) - def createTypedefedType(self, targetType, typeName, typeId = None): + def createTypedefedType(self, targetType, typeName, typeId=None): if typeId is None: typeId = typeName if not isinstance(targetType, self.Type): raise RuntimeError('Expected type in createTypedefType(), got %s' - % type(targetType)) + % type(targetType)) # Happens for C-style struct in GDB: typedef { int x; } struct S1; if targetType.typeId == typeId: return targetType @@ -3740,7 +3783,7 @@ class DumperBase: self.registerType(typeId, tdata) return self.Type(self, typeId) - def createType(self, typish, size = None): + def createType(self, typish, size=None): if isinstance(typish, self.Type): #typish.check() return typish @@ -3779,7 +3822,6 @@ class DumperBase: if size is not None: typish = ns + typish - tdata = self.typeData.get(typish, None) if tdata is not None: return self.Type(self, typish) @@ -3840,7 +3882,7 @@ class DumperBase: def createVectorItem(self, data, innerTypish): return self.createContainerItem(data, innerTypish, 'QVector') - class StructBuilder: + class StructBuilder(): def __init__(self, dumper): self.dumper = dumper self.pattern = '' @@ -3849,8 +3891,8 @@ class DumperBase: self.autoPadNext = False self.maxAlign = 1 - def addField(self, fieldSize, fieldCode = None, fieldIsStruct = False, - fieldName = None, fieldType = None, fieldAlign = 1): + def addField(self, fieldSize, fieldCode=None, fieldIsStruct=False, + fieldName=None, fieldType=None, fieldAlign=1): if fieldType is not None: fieldType = self.dumper.createType(fieldType) @@ -3864,7 +3906,7 @@ class DumperBase: padding = (fieldAlign - (self.currentBitsize >> 3)) % fieldAlign #DumperBase.warn('AUTO PADDING AT %s BITS BY %s BYTES' % (self.currentBitsize, padding)) field = self.dumper.Field(self.dumper, bitpos=self.currentBitsize, - bitsize=padding*8) + bitsize=padding * 8) self.pattern += '%ds' % padding self.currentBitsize += padding * 8 self.fields.append(field) @@ -3896,34 +3938,34 @@ class DumperBase: readingTypeName = False fieldType = self.createType(typeName) fieldAlign = fieldType.alignment() - builder.addField(n, fieldIsStruct = True, - fieldType = fieldType, fieldAlign = fieldAlign) + builder.addField(n, fieldIsStruct=True, + fieldType=fieldType, fieldAlign=fieldAlign) typeName = None n = None else: typeName += c - elif c == 't': # size_t - builder.addField(ptrSize, self.ptrCode(), fieldAlign = ptrSize) - elif c == 'p': # Pointer as int - builder.addField(ptrSize, self.ptrCode(), fieldAlign = ptrSize) - elif c == 'P': # Pointer as Value - builder.addField(ptrSize, '%ss' % ptrSize, fieldAlign = ptrSize) + elif c == 't': # size_t + builder.addField(ptrSize, self.ptrCode(), fieldAlign=ptrSize) + elif c == 'p': # Pointer as int + builder.addField(ptrSize, self.ptrCode(), fieldAlign=ptrSize) + elif c == 'P': # Pointer as Value + builder.addField(ptrSize, '%ss' % ptrSize, fieldAlign=ptrSize) elif c in ('d'): - builder.addField(8, c, fieldAlign = ptrSize) # fieldType = 'double' ? + builder.addField(8, c, fieldAlign=ptrSize) # fieldType = 'double' ? elif c in ('q', 'Q'): - builder.addField(8, c, fieldAlign = ptrSize) + builder.addField(8, c, fieldAlign=ptrSize) elif c in ('i', 'I', 'f'): - builder.addField(4, c, fieldAlign = 4) + builder.addField(4, c, fieldAlign=4) elif c in ('h', 'H'): - builder.addField(2, c, fieldAlign = 2) + builder.addField(2, c, fieldAlign=2) elif c in ('b', 'B', 'c'): - builder.addField(1, c, fieldAlign = 1) + builder.addField(1, c, fieldAlign=1) elif c >= '0' and c <= '9': if n is None: n = '' n += c elif c == 's': - builder.addField(int(n), fieldAlign = 1) + builder.addField(int(n), fieldAlign=1) n = None elif c == '{': readingTypeName = True diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 55ad02afcd5..c88811ae927 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -46,6 +46,7 @@ from utils import TypeCode # ####################################################################### + def safePrint(output): try: print(output) @@ -61,18 +62,19 @@ def safePrint(output): out += c print(out) + def registerCommand(name, func): class Command(gdb.Command): def __init__(self): super(Command, self).__init__(name, gdb.COMMAND_OBSCURE) + def invoke(self, args, from_tty): safePrint(func(args)) Command() - ####################################################################### # # Convenience @@ -83,18 +85,24 @@ def registerCommand(name, func): class PPCommand(gdb.Command): def __init__(self): super(PPCommand, self).__init__('pp', gdb.COMMAND_OBSCURE) + def invoke(self, args, from_tty): print(theCliDumper.fetchVariable(args)) + PPCommand() # Just convenience for 'python print gdb.parse_and_eval(...)' + + class PPPCommand(gdb.Command): def __init__(self): super(PPPCommand, self).__init__('ppp', gdb.COMMAND_OBSCURE) + def invoke(self, args, from_tty): print(gdb.parse_and_eval(args)) + PPPCommand() @@ -109,14 +117,17 @@ def scanStack(p, n): p += f.type.sizeof return r + class ScanStackCommand(gdb.Command): def __init__(self): super(ScanStackCommand, self).__init__('scanStack', gdb.COMMAND_OBSCURE) + def invoke(self, args, from_tty): if len(args) == 0: args = 20 safePrint(scanStack(gdb.parse_and_eval('$sp'), int(args))) + ScanStackCommand() @@ -126,7 +137,7 @@ ScanStackCommand() # ####################################################################### -class PlainDumper: +class PlainDumper(): def __init__(self, printer): self.printer = printer self.typeCache = {} @@ -143,7 +154,7 @@ class PlainDumper: d.putValue(d.hexencode(val), 'utf8:1:0') elif sys.version_info[0] <= 2 and isinstance(val, unicode): d.putValue(val) - elif val is not None: # Assuming LazyString + elif val is not None: # Assuming LazyString d.putCharArrayValue(val.address, val.length, val.type.target().sizeof) @@ -162,6 +173,7 @@ class PlainDumper: break d.putNumChild(1) + def importPlainDumpers(args): if args == 'off': try: @@ -172,11 +184,11 @@ def importPlainDumpers(args): else: theDumper.importPlainDumpers() + registerCommand('importPlainDumpers', importPlainDumpers) - -class OutputSaver: +class OutputSaver(): def __init__(self, d): self.d = d @@ -185,7 +197,7 @@ class OutputSaver: self.d.output = '' def __exit__(self, exType, exValue, exTraceBack): - if self.d.passExceptions and not exType is None: + if self.d.passExceptions and exType is not None: self.d.showException('OUTPUTSAVER', exType, exValue, exTraceBack) self.d.output = self.savedOutput else: @@ -194,7 +206,6 @@ class OutputSaver: return False - ####################################################################### # # The Dumper Class @@ -220,9 +231,9 @@ class Dumper(DumperBase): #DumperBase.warn('FROM FRAME VALUE: %s' % nativeValue.address) val = nativeValue try: - val = nativeValue.cast(nativeValue.dynamic_type) + val = nativeValue.cast(nativeValue.dynamic_type) except: - pass + pass return self.fromNativeValue(val) def fromNativeValue(self, nativeValue): @@ -249,7 +260,7 @@ class Dumper(DumperBase): # is surprisingly expensive. val.nativeValue = nativeValue #DumperBase.warn('CREATED PTR 1: %s' % val) - if not nativeValue.address is None: + if nativeValue.address is not None: val.laddress = toInteger(nativeValue.address) #DumperBase.warn('CREATED PTR 2: %s' % val) return val @@ -272,7 +283,7 @@ class Dumper(DumperBase): val = self.Value(self) val.nativeValue = nativeValue - if not nativeValue.address is None: + if nativeValue.address is not None: val.laddress = toInteger(nativeValue.address) else: size = nativeType.sizeof @@ -356,34 +367,34 @@ class Dumper(DumperBase): tdata.lbitsize = nativeType.sizeof * 8 tdata.code = { #gdb.TYPE_CODE_TYPEDEF : TypeCodeTypedef, # Handled above. - gdb.TYPE_CODE_METHOD : TypeCode.TypeCodeFunction, - gdb.TYPE_CODE_VOID : TypeCode.TypeCodeVoid, - gdb.TYPE_CODE_FUNC : TypeCode.TypeCodeFunction, - gdb.TYPE_CODE_METHODPTR : TypeCode.TypeCodeFunction, - gdb.TYPE_CODE_MEMBERPTR : TypeCode.TypeCodeFunction, + gdb.TYPE_CODE_METHOD: TypeCode.TypeCodeFunction, + gdb.TYPE_CODE_VOID: TypeCode.TypeCodeVoid, + gdb.TYPE_CODE_FUNC: TypeCode.TypeCodeFunction, + gdb.TYPE_CODE_METHODPTR: TypeCode.TypeCodeFunction, + gdb.TYPE_CODE_MEMBERPTR: TypeCode.TypeCodeFunction, #gdb.TYPE_CODE_PTR : TypeCode.TypeCodePointer, # Handled above. #gdb.TYPE_CODE_REF : TypeCode.TypeCodeReference, # Handled above. - gdb.TYPE_CODE_BOOL : TypeCode.TypeCodeIntegral, - gdb.TYPE_CODE_CHAR : TypeCode.TypeCodeIntegral, - gdb.TYPE_CODE_INT : TypeCode.TypeCodeIntegral, - gdb.TYPE_CODE_FLT : TypeCode.TypeCodeFloat, - gdb.TYPE_CODE_ENUM : TypeCode.TypeCodeEnum, + gdb.TYPE_CODE_BOOL: TypeCode.TypeCodeIntegral, + gdb.TYPE_CODE_CHAR: TypeCode.TypeCodeIntegral, + gdb.TYPE_CODE_INT: TypeCode.TypeCodeIntegral, + gdb.TYPE_CODE_FLT: TypeCode.TypeCodeFloat, + gdb.TYPE_CODE_ENUM: TypeCode.TypeCodeEnum, #gdb.TYPE_CODE_ARRAY : TypeCode.TypeCodeArray, - gdb.TYPE_CODE_STRUCT : TypeCode.TypeCodeStruct, - gdb.TYPE_CODE_UNION : TypeCode.TypeCodeStruct, - gdb.TYPE_CODE_COMPLEX : TypeCode.TypeCodeComplex, - gdb.TYPE_CODE_STRING : TypeCode.TypeCodeFortranString, + gdb.TYPE_CODE_STRUCT: TypeCode.TypeCodeStruct, + gdb.TYPE_CODE_UNION: TypeCode.TypeCodeStruct, + gdb.TYPE_CODE_COMPLEX: TypeCode.TypeCodeComplex, + gdb.TYPE_CODE_STRING: TypeCode.TypeCodeFortranString, }[code] if tdata.code == TypeCode.TypeCodeEnum: - tdata.enumDisplay = lambda intval, addr, form : \ + tdata.enumDisplay = lambda intval, addr, form: \ self.nativeTypeEnumDisplay(nativeType, intval, form) if tdata.code == TypeCode.TypeCodeStruct: - tdata.lalignment = lambda : \ + tdata.lalignment = lambda: \ self.nativeStructAlignment(nativeType) - tdata.lfields = lambda value : \ + tdata.lfields = lambda value: \ self.listMembers(value, nativeType) tdata.templateArguments = self.listTemplateParameters(nativeType) - self.registerType(typeId, tdata) # Fix up fields and template args + self.registerType(typeId, tdata) # Fix up fields and template args # warn('CREATE TYPE: %s' % typeId) #else: # warn('REUSE TYPE: %s' % typeId) @@ -417,7 +428,7 @@ class Dumper(DumperBase): enumerators.append((field.name, field.enumval)) # No match was found, try to return as flags - enumerators.sort(key = lambda x: x[1]) + enumerators.sort(key=lambda x: x[1]) flags = [] v = intval found = False @@ -460,16 +471,14 @@ class Dumper(DumperBase): align = handleItem(f.type, align) return align - #except: # # Happens in the BoostList dumper for a 'const bool' # # item named 'constant_time_size'. There isn't anything we can do # # in this case. - # pass + # pass #yield value.extractField(field) - def memberFromNativeFieldAndValue(self, nativeField, nativeValue, fieldName, value): nativeMember = self.nativeMemberFromField(nativeValue, nativeField) if nativeMember is None: @@ -554,9 +563,9 @@ class Dumper(DumperBase): extractor = None else: extractor = lambda value, \ - capturedNativeField = nativeField, \ - capturedNativeValue = nativeValue, \ - capturedFieldName = fieldName : \ + capturedNativeField = nativeField, \ + capturedNativeValue = nativeValue, \ + capturedFieldName = fieldName: \ self.memberFromNativeFieldAndValue(capturedNativeField, capturedNativeValue, capturedFieldName, @@ -564,10 +573,8 @@ class Dumper(DumperBase): #DumperBase.warn("FOUND NATIVE FIELD: %s bitpos: %s" % (fieldName, bitpos)) return self.Field(dumper=self, name=fieldName, isBase=nativeField.is_base_class, - bitsize=bitsize, bitpos=bitpos, type=fieldType, - extractor=extractor) - - + bitsize=bitsize, bitpos=bitpos, type=fieldType, + extractor=extractor) def listLocals(self, partialVar): frame = gdb.selected_frame() @@ -590,67 +597,67 @@ class Dumper(DumperBase): break for symbol in block: - # Filter out labels etc. - if symbol.is_variable or symbol.is_argument: - name = symbol.print_name + # Filter out labels etc. + if symbol.is_variable or symbol.is_argument: + name = symbol.print_name - if name in ('__in_chrg', '__PRETTY_FUNCTION__'): - continue + if name in ('__in_chrg', '__PRETTY_FUNCTION__'): + continue - if not partialVar is None and partialVar != name: - continue + if partialVar is not None and partialVar != name: + continue - # 'NotImplementedError: Symbol type not yet supported in - # Python scripts.' - #DumperBase.warn('SYMBOL %s (%s, %s)): ' % (symbol, name, symbol.name)) - if self.passExceptions and not self.isTesting: - nativeValue = frame.read_var(name, block) - value = self.fromFrameValue(nativeValue) - value.name = name - #DumperBase.warn('READ 0: %s' % value.stringify()) - items.append(value) - continue + # 'NotImplementedError: Symbol type not yet supported in + # Python scripts.' + #DumperBase.warn('SYMBOL %s (%s, %s)): ' % (symbol, name, symbol.name)) + if self.passExceptions and not self.isTesting: + nativeValue = frame.read_var(name, block) + value = self.fromFrameValue(nativeValue) + value.name = name + #DumperBase.warn('READ 0: %s' % value.stringify()) + items.append(value) + continue - try: - # Same as above, but for production. - nativeValue = frame.read_var(name, block) - value = self.fromFrameValue(nativeValue) - value.name = name - #DumperBase.warn('READ 1: %s' % value.stringify()) - items.append(value) - continue - except: - pass + try: + # Same as above, but for production. + nativeValue = frame.read_var(name, block) + value = self.fromFrameValue(nativeValue) + value.name = name + #DumperBase.warn('READ 1: %s' % value.stringify()) + items.append(value) + continue + except: + pass - try: - #DumperBase.warn('READ 2: %s' % item.value) - value = self.fromFrameValue(frame.read_var(name)) - value.name = name - items.append(value) - continue - except: - # RuntimeError: happens for - # void foo() { std::string s; std::wstring w; } - # ValueError: happens for (as of 2010/11/4) - # a local struct as found e.g. in - # gcc sources in gcc.c, int execute() - pass + try: + #DumperBase.warn('READ 2: %s' % item.value) + value = self.fromFrameValue(frame.read_var(name)) + value.name = name + items.append(value) + continue + except: + # RuntimeError: happens for + # void foo() { std::string s; std::wstring w; } + # ValueError: happens for (as of 2010/11/4) + # a local struct as found e.g. in + # gcc sources in gcc.c, int execute() + pass - try: - #DumperBase.warn('READ 3: %s %s' % (name, item.value)) - #DumperBase.warn('ITEM 3: %s' % item.value) - value = self.fromFrameValue(gdb.parse_and_eval(name)) - value.name = name - items.append(value) - except: - # Can happen in inlined code (see last line of - # RowPainter::paintChars(): 'RuntimeError: - # No symbol '__val' in current context.\n' - pass + try: + #DumperBase.warn('READ 3: %s %s' % (name, item.value)) + #DumperBase.warn('ITEM 3: %s' % item.value) + value = self.fromFrameValue(gdb.parse_and_eval(name)) + value.name = name + items.append(value) + except: + # Can happen in inlined code (see last line of + # RowPainter::paintChars(): 'RuntimeError: + # No symbol '__val' in current context.\n' + pass # The outermost block in a function has the function member # FIXME: check whether this is guaranteed. - if not block.function is None: + if block.function is not None: break block = block.superblock @@ -670,7 +677,7 @@ class Dumper(DumperBase): self.resetStats() self.prepare(args) - self.isBigEndian = gdb.execute('show endian', to_string = True).find('big endian') > 0 + self.isBigEndian = gdb.execute('show endian', to_string=True).find('big endian') > 0 self.packCode = '>' if self.isBigEndian else '<' (ok, res) = self.tryFetchInterpreterVariables(args) @@ -757,7 +764,7 @@ class Dumper(DumperBase): #exp = '((class %s*)%s)->%s(%s)' % (typeName, value.laddress, function, arg) addr = value.address() if addr is None: - addr = self.pokeValue(value) + addr = self.pokeValue(value) #DumperBase.warn('PTR: %s -> %s(%s)' % (value, function, addr)) exp = '((%s*)0x%x)->%s(%s)' % (typeName, addr, function, arg) #DumperBase.warn('CALL: %s' % exp) @@ -777,9 +784,9 @@ class Dumper(DumperBase): def makeStdString(init): # Works only for small allocators, but they are usually empty. - gdb.execute('set $d=(std::string*)calloc(sizeof(std::string), 2)'); + gdb.execute('set $d=(std::string*)calloc(sizeof(std::string), 2)') gdb.execute('call($d->basic_string("' + init + - '",*(std::allocator*)(1+$d)))') + '",*(std::allocator*)(1+$d)))') value = gdb.parse_and_eval('$d').dereference() return value @@ -791,7 +798,7 @@ class Dumper(DumperBase): data = value.data() h = self.hexencode(data) #DumperBase.warn('DATA: %s' % h) - string = ''.join('\\x' + h[2*i:2*i+2] for i in range(size)) + string = ''.join('\\x' + h[2 * i:2 * i + 2] for i in range(size)) exp = '(%s*)memcpy(calloc(%d, 1), "%s", %d)' \ % (value.type.name, size, string, size) #DumperBase.warn('EXP: %s' % exp) @@ -886,7 +893,7 @@ class Dumper(DumperBase): try: version = self.qtVersionString() - (major, minor, patch) = version[version.find('"')+1:version.rfind('"')].split('.') + (major, minor, patch) = version[version.find('"') + 1:version.rfind('"')].split('.') qtversion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) self.qtVersion = lambda: qtversion return qtversion @@ -896,6 +903,7 @@ class Dumper(DumperBase): def createSpecialBreakpoints(self, args): self.specialBreakpoints = [] + def newSpecial(spec): # GDB < 8.1 does not have the 'qualified' parameter here, # GDB >= 8.1 applies some generous pattern matching, hitting @@ -903,7 +911,7 @@ class Dumper(DumperBase): class Pre81SpecialBreakpoint(gdb.Breakpoint): def __init__(self, spec): super(Pre81SpecialBreakpoint, self).__init__(spec, - gdb.BP_BREAKPOINT, internal=True) + gdb.BP_BREAKPOINT, internal=True) self.spec = spec def stop(self): @@ -913,7 +921,9 @@ class Dumper(DumperBase): class SpecialBreakpoint(gdb.Breakpoint): def __init__(self, spec): super(SpecialBreakpoint, self).__init__(spec, - gdb.BP_BREAKPOINT, internal=True, qualified=True) + gdb.BP_BREAKPOINT, + internal=True, + qualified=True) self.spec = spec def stop(self): @@ -999,7 +1009,6 @@ class Dumper(DumperBase): # oldthread.switch() #return out + ']' - def importPlainDumper(self, printer): name = printer.name.replace('::', '__') self.qqDumpers[name] = PlainDumper(printer) @@ -1024,9 +1033,9 @@ class Dumper(DumperBase): def handleNewObjectFile(self, objfile): name = objfile.filename if self.isWindowsTarget(): - qtCoreMatch = re.match('.*Qt5?Core[^/.]*d?\.dll', name) + qtCoreMatch = re.match(r'.*Qt5?Core[^/.]*d?\.dll', name) else: - qtCoreMatch = re.match('.*/libQt5?Core[^/.]*\.so', name) + qtCoreMatch = re.match(r'.*/libQt5?Core[^/.]*\.so', name) if qtCoreMatch is not None: self.addDebugLibs(objfile) @@ -1043,18 +1052,17 @@ class Dumper(DumperBase): except: pass - def handleQtCoreLoaded(self, objfile): fd, tmppath = tempfile.mkstemp() os.close(fd) cmd = 'maint print msymbols %s "%s"' % (tmppath, objfile.filename) try: - symbols = gdb.execute(cmd, to_string = True) + symbols = gdb.execute(cmd, to_string=True) except: # command syntax depends on gdb version - below is gdb 8+ cmd = 'maint print msymbols -objfile "%s" -- %s' % (objfile.filename, tmppath) try: - symbols = gdb.execute(cmd, to_string = True) + symbols = gdb.execute(cmd, to_string=True) except: pass ns = '' @@ -1063,14 +1071,14 @@ class Dumper(DumperBase): if line.find('msgHandlerGrabbed ') >= 0: # [11] b 0x7ffff683c000 _ZN4MynsL17msgHandlerGrabbedE # section .tbss Myns::msgHandlerGrabbed qlogging.cpp - ns = re.split('_ZN?(\d*)(\w*)L17msgHandlerGrabbedE? ', line)[2] + ns = re.split(r'_ZN?(\d*)(\w*)L17msgHandlerGrabbedE? ', line)[2] if len(ns): ns += '::' break if line.find('currentThreadData ') >= 0: # [ 0] b 0x7ffff67d3000 _ZN2UUL17currentThreadDataE # section .tbss UU::currentThreadData qthread_unix.cpp\\n - ns = re.split('_ZN?(\d*)(\w*)L17currentThreadDataE? ', line)[2] + ns = re.split(r'_ZN?(\d*)(\w*)L17currentThreadDataE? ', line)[2] if len(ns): ns += '::' break @@ -1179,14 +1187,14 @@ class Dumper(DumperBase): def lookupNativeType(self, typeName): nativeType = self.lookupNativeTypeHelper(typeName) - if not nativeType is None: + if nativeType is not None: self.check(isinstance(nativeType, gdb.Type)) return nativeType def lookupNativeTypeHelper(self, typeName): typeobj = self.typeCache.get(typeName) #DumperBase.warn('LOOKUP 1: %s -> %s' % (typeName, typeobj)) - if not typeobj is None: + if typeobj is not None: return typeobj if typeName == 'void': @@ -1212,7 +1220,7 @@ class Dumper(DumperBase): ts = typeName ts = ts.replace('{anonymous}', '(anonymous namespace)') typeobj = self.lookupNativeType(ts) - if not typeobj is None: + if typeobj is not None: self.typeCache[typeName] = typeobj self.typesToReport[typeName] = typeobj return typeobj @@ -1248,7 +1256,7 @@ class Dumper(DumperBase): if ts.endswith('*'): typeobj = self.lookupNativeType(ts[0:-1]) - if not typeobj is None: + if typeobj is not None: typeobj = typeobj.pointer() self.typeCache[typeName] = typeobj self.typesToReport[typeName] = typeobj @@ -1271,7 +1279,7 @@ class Dumper(DumperBase): #DumperBase.warn("LOOKING UP '%s' FAILED" % ts) pass - if not typeobj is None: + if typeobj is not None: #DumperBase.warn('CACHING: %s' % typeobj) self.typeCache[typeName] = typeobj self.typesToReport[typeName] = typeobj @@ -1292,7 +1300,7 @@ class Dumper(DumperBase): extraQml = int(args.get('extraqml', '0')) limit = int(args['limit']) if limit <= 0: - limit = 10000 + limit = 10000 self.prepare(args) self.output = '' @@ -1316,8 +1324,8 @@ class Dumper(DumperBase): value = symbol.value(frame) typeobj = value.type if typeobj.code == gdb.TYPE_CODE_PTR: - dereftype = typeobj.target().unqualified() - if dereftype.name == needle: + dereftype = typeobj.target().unqualified() + if dereftype.name == needle: addr = toInteger(value) expr = pat % (ns, addr) res = str(gdb.parse_and_eval(expr)) @@ -1347,7 +1355,7 @@ class Dumper(DumperBase): if sal: line = sal.line symtab = sal.symtab - if not symtab is None: + if symtab is not None: objfile = fromNativePath(symtab.objfile.filename) fullname = symtab.fullname() if fullname is None: @@ -1366,22 +1374,22 @@ class Dumper(DumperBase): context = interpreterFrame.get('context', 0) self.put(('frame={function="%s",file="%s",' - 'line="%s",language="%s",context="%s"}') - % (function, self.hexencode(fileName), lineNumber, language, context)) + 'line="%s",language="%s",context="%s"}') + % (function, self.hexencode(fileName), lineNumber, language, context)) if False and self.isInternalInterpreterFrame(functionName): frame = frame.older() self.put(('frame={address="0x%x",function="%s",' - 'file="%s",line="%s",' - 'module="%s",language="c",usable="0"}') % - (pc, functionName, fileName, line, objfile)) + 'file="%s",line="%s",' + 'module="%s",language="c",usable="0"}') % + (pc, functionName, fileName, line, objfile)) i += 1 frame = frame.older() continue self.put(('frame={level="%s",address="0x%x",function="%s",' - 'file="%s",line="%s",module="%s",language="c"}') % - (i, pc, functionName, fileName, line, objfile)) + 'file="%s",line="%s",module="%s",language="c"}') % + (i, pc, functionName, fileName, line, objfile)) frame = frame.older() i += 1 @@ -1406,7 +1414,7 @@ class Dumper(DumperBase): def exitGdb(self, _): gdb.execute('quit') - def reportResult(self, result, args = {}): + def reportResult(self, result, args={}): print('result={token="%s",%s}' % (args.get("token", 0), result)) def profile1(self, args): @@ -1420,8 +1428,7 @@ class Dumper(DumperBase): def profile2(self, args): import timeit print(timeit.repeat('theDumper.fetchVariables(%s)' % args, - 'from __main__ import theDumper', number=10)) - + 'from __main__ import theDumper', number=10)) class CliDumper(Dumper): @@ -1473,6 +1480,7 @@ theCliDumper = CliDumper() def threadnames(arg): return theDumper.threadnames(int(arg)) + registerCommand('threadnames', threadnames) ####################################################################### @@ -1481,6 +1489,7 @@ registerCommand('threadnames', threadnames) # ####################################################################### + class InterpreterMessageBreakpoint(gdb.Breakpoint): def __init__(self): spec = 'qt_qmlDebugMessageAvailable' @@ -1501,6 +1510,7 @@ class InterpreterMessageBreakpoint(gdb.Breakpoint): def new_objfile_handler(event): return theDumper.handleNewObjectFile(event.new_objfile) + gdb.events.new_objfile.connect(new_objfile_handler) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 5e049aeb246..8a98b8e5dcd 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -52,6 +52,7 @@ from dumper import DumperBase, SubItem, Children, TopLevelItem qqWatchpointOffset = 10000 + def fileNameAsString(file): return str(file) if file.IsValid() else '' @@ -60,8 +61,9 @@ def check(exp): if not exp: raise RuntimeError('Check failed') + class Dumper(DumperBase): - def __init__(self, debugger = None): + def __init__(self, debugger=None): DumperBase.__init__(self) lldb.theDumper = self @@ -169,14 +171,14 @@ class Dumper(DumperBase): elif code == lldb.eTypeClassTypedef: nativeTargetType = nativeType.GetUnqualifiedType() if hasattr(nativeTargetType, 'GetCanonicalType'): - nativeTargetType = nativeTargetType.GetCanonicalType() + nativeTargetType = nativeTargetType.GetCanonicalType() val = self.fromNativeValue(nativeValue.Cast(nativeTargetType)) val.type = self.fromNativeType(nativeType) #DumperBase.warn('CREATED TYPEDEF: %s' % val) else: val = self.Value(self) address = nativeValue.GetLoadAddress() - if not address is None: + if address is not None: val.laddress = address if True: data = nativeValue.GetData() @@ -270,27 +272,27 @@ class Dumper(DumperBase): fieldBitpos = None isBitfield = False - if isBitfield: # Bit fields + if isBitfield: # Bit fields fieldType = self.createBitfieldType( self.createType(self.typeName(nativeFieldType)), fieldBitsize) yield self.Field(self, name=fieldName, type=fieldType, bitsize=fieldBitsize, bitpos=fieldBitpos) - elif fieldName is None: # Anon members + elif fieldName is None: # Anon members anonNumber += 1 fieldName = '#%s' % anonNumber fakeMember = fakeValue.GetChildAtIndex(i) fakeMemberAddress = fakeMember.GetLoadAddress() offset = fakeMemberAddress - fakeAddress yield self.Field(self, name=fieldName, type=self.fromNativeType(nativeFieldType), - bitsize=fieldBitsize, bitpos=8*offset) + bitsize=fieldBitsize, bitpos=8 * offset) elif fieldName in baseNames: # Simple bases member = self.fromNativeValue(fakeValue.GetChildAtIndex(i)) member.isBaseClass = True yield member - else: # Normal named members + else: # Normal named members member = self.fromNativeValue(fakeValue.GetChildAtIndex(i)) member.name = nativeField.GetName() yield member @@ -389,7 +391,7 @@ class Dumper(DumperBase): #DumperBase.warn('TYPEDEF') nativeTargetType = nativeType.GetUnqualifiedType() if hasattr(nativeTargetType, 'GetCanonicalType'): - nativeTargetType = nativeTargetType.GetCanonicalType() + nativeTargetType = nativeTargetType.GetCanonicalType() targetType = self.fromNativeType(nativeTargetType) return self.createTypedefedType(targetType, nativeType.GetName()) @@ -398,10 +400,10 @@ class Dumper(DumperBase): if code in (lldb.eTypeClassArray, lldb.eTypeClassVector): #DumperBase.warn('ARRAY: %s' % nativeType.GetName()) - if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x + if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x nativeTargetType = nativeType.GetArrayElementType() if not nativeTargetType.IsValid(): - if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x + if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x #DumperBase.warn('BAD: %s ' % nativeTargetType.get_fields_array()) nativeTargetType = nativeType.GetVectorElementType() count = nativeType.GetByteSize() // nativeTargetType.GetByteSize() @@ -414,9 +416,9 @@ class Dumper(DumperBase): targetType = self.fromNativeType(nativeTargetType) tdata = targetType.typeData().copy() tdata.name = targetTypeName - targetType.typeData = lambda : tdata + targetType.typeData = lambda: tdata return self.createArrayType(targetType, count) - if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x + if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x nativeTargetType = nativeType.GetVectorElementType() count = nativeType.GetByteSize() // nativeTargetType.GetByteSize() targetType = self.fromNativeType(nativeTargetType) @@ -445,15 +447,15 @@ class Dumper(DumperBase): self.warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code)) elif code == lldb.eTypeClassEnumeration: tdata.code = TypeCode.TypeCodeEnum - tdata.enumDisplay = lambda intval, addr, form : \ + tdata.enumDisplay = lambda intval, addr, form: \ self.nativeTypeEnumDisplay(nativeType, intval, form) elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat): tdata.code = TypeCode.TypeCodeComplex elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion): tdata.code = TypeCode.TypeCodeStruct - tdata.lalignment = lambda : \ + tdata.lalignment = lambda: \ self.nativeStructAlignment(nativeType) - tdata.lfields = lambda value : \ + tdata.lfields = lambda value: \ self.listMembers(value, nativeType) tdata.templateArguments = self.listTemplateParametersHelper(nativeType) elif code == lldb.eTypeClassFunction: @@ -461,7 +463,7 @@ class Dumper(DumperBase): elif code == lldb.eTypeClassMemberPointer: tdata.code = TypeCode.TypeCodeMemberPointer - self.registerType(typeId, tdata) # Fix up fields and template args + self.registerType(typeId, tdata) # Fix up fields and template args # warn('CREATE TYPE: %s' % typeId) #else: # warn('REUSE TYPE: %s' % typeId) @@ -489,7 +491,8 @@ class Dumper(DumperBase): # eTemplateArgumentKindExpression, # eTemplateArgumentKindPack if kind == lldb.eTemplateArgumentKindType: - innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType() + innerType = nativeType.GetTemplateArgumentType( + i).GetUnqualifiedType().GetCanonicalType() targs.append(self.fromNativeType(innerType)) #elif kind == lldb.eTemplateArgumentKindIntegral: # innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType() @@ -510,7 +513,7 @@ class Dumper(DumperBase): # targs.append(value) else: #DumperBase.warn('UNHANDLED TEMPLATE TYPE : %s' % kind) - targs.append(stringArgs[i]) # Best we can do. + targs.append(stringArgs[i]) # Best we can do. #DumperBase.warn('TARGS: %s %s' % (nativeType.GetName(), [str(x) for x in targs])) return targs @@ -562,7 +565,7 @@ class Dumper(DumperBase): return form % intval def nativeDynamicTypeName(self, address, baseType): - return None # FIXME: Seems sufficient, no idea why. + return None # FIXME: Seems sufficient, no idea why. addr = self.target.ResolveLoadAddress(address) ctx = self.target.ResolveSymbolContextForAddress(addr, 0) sym = ctx.GetSymbol() @@ -573,20 +576,20 @@ class Dumper(DumperBase): # See db.StateType return ( 'invalid', - 'unloaded', # Process is object is valid, but not currently loaded - 'connected', # Process is connected to remote debug services, - # but not launched or attached to anything yet - 'attaching', # Process is currently trying to attach - 'launching', # Process is in the process of launching - 'stopped', # Process or thread is stopped and can be examined. - 'running', # Process or thread is running and can't be examined. - 'stepping', # Process or thread is in the process of stepping - # and can not be examined. - 'crashed', # Process or thread has crashed and can be examined. - 'detached', # Process has been detached and can't be examined. - 'exited', # Process has exited and can't be examined. - 'suspended' # Process or thread is in a suspended state as far - )[s] + 'unloaded', # Process is object is valid, but not currently loaded + 'connected', # Process is connected to remote debug services, + # but not launched or attached to anything yet + 'attaching', # Process is currently trying to attach + 'launching', # Process is in the process of launching + 'stopped', # Process or thread is stopped and can be examined. + 'running', # Process or thread is running and can't be examined. + 'stepping', # Process or thread is in the process of stepping + # and can not be examined. + 'crashed', # Process or thread has crashed and can be examined. + 'detached', # Process has been detached and can't be examined. + 'exited', # Process has exited and can't be examined. + 'suspended' # Process or thread is in a suspended state as far + )[s] except: return 'unknown(%s)' % s @@ -604,7 +607,7 @@ class Dumper(DumperBase): 'plancomplete', 'threadexiting', 'instrumentation', - )[s] + )[s] except: return 'unknown(%s)' % s @@ -708,8 +711,8 @@ class Dumper(DumperBase): if version.count('.') != 2: continue - version.replace("'", '"') # Both seem possible - version = version[version.find('"')+1:version.rfind('"')] + version.replace("'", '"') # Both seem possible + version = version[version.find('"') + 1:version.rfind('"')] (major, minor, patch) = version.split('.') qtVersion = 0x10000 * int(major) + 0x100 * int(minor) + int(patch) @@ -753,7 +756,7 @@ class Dumper(DumperBase): def lookupNativeType(self, name): #DumperBase.warn('LOOKUP TYPE NAME: %s' % name) typeobj = self.typeCache.get(name) - if not typeobj is None: + if typeobj is not None: #DumperBase.warn('CACHED: %s' % name) return typeobj typeobj = self.target.FindFirstType(name) @@ -845,7 +848,7 @@ class Dumper(DumperBase): self.startMode_ = args.get('startmode', 1) self.breakOnMain_ = args.get('breakonmain', 0) self.useTerminal_ = args.get('useterminal', 0) - pargs = self.hexdecode(args.get('processargs', '')) + pargs = self.hexdecode(args.get('processargs', '')) self.processArgs_ = pargs.split('\0') if len(pargs) else [] self.environment_ = args.get('environment', []) self.environment_ = list(map(lambda x: self.hexdecode(x), self.environment_)) @@ -858,7 +861,7 @@ class Dumper(DumperBase): if self.workingDirectory_ == '': try: self.workingDirectory_ = os.getcwd() - except: # Could have been deleted in the mean time. + except: # Could have been deleted in the mean time. pass self.ignoreStops = 0 @@ -884,7 +887,7 @@ class Dumper(DumperBase): state = 1 if self.target.IsValid() else 0 self.reportResult('success="%s",msg="%s",exe="%s"' - % (state, error, self.executable_), args) + % (state, error, self.executable_), args) def runEngine(self, args): if self.runEngineAttempted: @@ -927,7 +930,7 @@ class Dumper(DumperBase): # better to mirror that and wait for the spontaneous stop. self.reportState('enginerunandinferiorrunok') elif self.startMode_ == DebuggerStartMode.AttachCore: - coreFile = args.get('coreFile', ''); + coreFile = args.get('coreFile', '') self.process = self.target.LoadCore(coreFile) if self.process.IsValid(): self.reportState('enginerunokandinferiorunrunnable') @@ -952,8 +955,8 @@ class Dumper(DumperBase): broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) listener.StartListeningForEvents(broadcaster, lldb.SBProcess.eBroadcastBitStateChanged) broadcaster.AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged) - listener.StartListeningForEvents(broadcaster, lldb.SBTarget.eBroadcastBitBreakpointChanged) - + listener.StartListeningForEvents( + broadcaster, lldb.SBTarget.eBroadcastBitBreakpointChanged) def loop(self): event = lldb.SBEvent() @@ -968,7 +971,6 @@ class Dumper(DumperBase): #if listener.WaitForEventForBroadcaster(0, broadcaster, event): # self.handleEvent(event) - def describeError(self, error): desc = lldb.SBStream() error.GetDescription(desc) @@ -1092,8 +1094,8 @@ class Dumper(DumperBase): lineNumber = interpreterFrame.get('line', 0) context = interpreterFrame.get('context', 0) result += ('frame={function="%s",file="%s",' - 'line="%s",language="%s",context="%s"}' - % (function, fileName, lineNumber, language, context)) + 'line="%s",language="%s",context="%s"}' + % (function, fileName, lineNumber, language, context)) fileName = fileNameAsString(lineEntry.file) result += '{pc="0x%x"' % pc @@ -1118,11 +1120,9 @@ class Dumper(DumperBase): # logview pane feature. self.report('token(\"%s\")' % args["token"]) - def reportBreakpointUpdate(self, bp): self.report('breakpointmodified={%s}' % self.describeBreakpoint(bp)) - def readRawMemory(self, address, size): if size == 0: return bytes() @@ -1203,7 +1203,7 @@ class Dumper(DumperBase): #else: if True: values = list(frame.GetVariables(True, True, False, True)) - values.reverse() # To get shadowed vars numbered backwards. + values.reverse() # To get shadowed vars numbered backwards. variables = [] for val in values: @@ -1225,7 +1225,7 @@ class Dumper(DumperBase): self.put('],partial="%d"' % isPartial) self.reportResult(self.output, args) - def fetchRegisters(self, args = None): + def fetchRegisters(self, args=None): if self.process is None: result = 'process="none"' else: @@ -1253,7 +1253,7 @@ class Dumper(DumperBase): self.reportResult('output="%s"' % result.GetOutput(), args) return # Try again with register write xmm0 "{0x00 ... 0x02}" syntax: - vec = ' '.join(["0x" + value[i:i+2] for i in range(2, len(value), 2)]) + vec = ' '.join(["0x" + value[i:i + 2] for i in range(2, len(value), 2)]) success = interp.HandleCommand('register write %s "{%s}"' % (name, vec), result) if success: self.reportResult('output="%s"' % result.GetOutput(), args) @@ -1295,7 +1295,6 @@ class Dumper(DumperBase): self.process.Kill() self.reportResult('', args) - def handleBreakpointEvent(self, event): eventType = lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) # handle only the resolved locations for now.. @@ -1304,7 +1303,6 @@ class Dumper(DumperBase): if bp is not None: self.reportBreakpointUpdate(bp) - def handleEvent(self, event): if lldb.SBBreakpoint.EventIsBreakpointEvent(event): self.handleBreakpointEvent(event) @@ -1321,16 +1319,17 @@ class Dumper(DumperBase): flavor = event.GetDataFlavor() state = lldb.SBProcess.GetStateFromEvent(event) bp = lldb.SBBreakpoint.GetBreakpointFromEvent(event) - skipEventReporting = eventType in (lldb.SBProcess.eBroadcastBitSTDOUT, lldb.SBProcess.eBroadcastBitSTDERR) + skipEventReporting = eventType in ( + lldb.SBProcess.eBroadcastBitSTDOUT, lldb.SBProcess.eBroadcastBitSTDERR) self.report('event={type="%s",data="%s",msg="%s",flavor="%s",state="%s",bp="%s"}' - % (eventType, out.GetData(), msg, flavor, self.stateName(state), bp)) + % (eventType, out.GetData(), msg, flavor, self.stateName(state), bp)) if state == lldb.eStateExited: self.eventState = state if not self.isShuttingDown_: self.reportState("inferiorexited") self.report('exited={status="%s",desc="%s"}' - % (self.process.GetExitStatus(), self.process.GetExitDescription())) + % (self.process.GetExitStatus(), self.process.GetExitDescription())) elif state != self.eventState and not skipEventReporting: self.eventState = state if state == lldb.eStateStopped: @@ -1347,7 +1346,7 @@ class Dumper(DumperBase): resolver() self.report("AUTO-CONTINUE AFTER RESOLVING") self.reportState("inferiorstopok") - self.process.Continue(); + self.process.Continue() return if functionName == "::qt_qmlDebugMessageAvailable()": self.report("ASYNC MESSAGE FROM SERVICE") @@ -1355,7 +1354,7 @@ class Dumper(DumperBase): if not res: self.report("EVENT NEEDS NO STOP") self.reportState("stopped") - self.process.Continue(); + self.process.Continue() return if self.isInterrupting_: self.isInterrupting_ = False @@ -1368,13 +1367,13 @@ class Dumper(DumperBase): else: self.reportState(self.stateName(state)) - if eventType == lldb.SBProcess.eBroadcastBitStateChanged: # 1 + if eventType == lldb.SBProcess.eBroadcastBitStateChanged: # 1 state = self.process.GetState() if state == lldb.eStateStopped: stoppedThread = self.firstStoppedThread() if stoppedThread: self.process.SetSelectedThread(stoppedThread) - elif eventType == lldb.SBProcess.eBroadcastBitInterrupt: # 2 + elif eventType == lldb.SBProcess.eBroadcastBitInterrupt: # 2 pass elif eventType == lldb.SBProcess.eBroadcastBitSTDOUT: # FIXME: Size? @@ -1391,9 +1390,9 @@ class Dumper(DumperBase): def describeBreakpoint(self, bp): isWatch = isinstance(bp, lldb.SBWatchpoint) if isWatch: - result = 'lldbid="%s"' % (qqWatchpointOffset + bp.GetID()) + result = 'lldbid="%s"' % (qqWatchpointOffset + bp.GetID()) else: - result = 'lldbid="%s"' % bp.GetID() + result = 'lldbid="%s"' % bp.GetID() result += ',valid="%s"' % (1 if bp.IsValid() else 0) result += ',hitcount="%s"' % bp.GetHitCount() if bp.IsValid(): @@ -1469,7 +1468,7 @@ class Dumper(DumperBase): value = frame.FindVariable(args['expression']) error = lldb.SBError() bp = self.target.WatchAddress(value.GetLoadAddress(), - value.GetByteSize(), False, True, error) + value.GetByteSize(), False, True, error) except: bp = self.target.BreakpointCreateByName(None) else: @@ -1528,7 +1527,7 @@ class Dumper(DumperBase): enabled = loc.IsEnabled() res = True self.reportResult('success="%s",enabled="%s",locid="%s"' - % (int(res), int(enabled), locId), args) + % (int(res), int(enabled), locId), args) def removeBreakpoint(self, args): lldbId = int(args['lldbid']) @@ -1608,7 +1607,7 @@ class Dumper(DumperBase): self.currentThread().StepInstruction(False) self.reportResult('', args) - def executeStepOut(self, args = {}): + def executeStepOut(self, args={}): self.currentThread().StepOut() self.reportResult('', args) @@ -1622,7 +1621,7 @@ class Dumper(DumperBase): if bp.GetNumLocations() == 0: self.target.BreakpointDelete(bp.GetID()) self.reportResult(self.describeStatus('No target location found.') - + self.describeLocation(frame), args) + + self.describeLocation(frame), args) return bp.SetOneShot(True) self.reportResult('', args) @@ -1647,7 +1646,7 @@ class Dumper(DumperBase): bp = self.target.BreakpointCreateByAddress(addr) else: bp = self.target.BreakpointCreateByLocation( - str(args['file']), int(args['line'])) + str(args['file']), int(args['line'])) if bp.GetNumLocations() == 0: self.target.BreakpointDelete(bp.GetID()) status = 'No target location found.' @@ -1663,7 +1662,7 @@ class Dumper(DumperBase): result = lldb.SBCommandReturnObject() self.debugger.GetCommandInterpreter().HandleCommand('break list', result) self.report('success="%d",output="%s",error="%s"' - % (result.Succeeded(), result.GetOutput(), result.GetError())) + % (result.Succeeded(), result.GetOutput(), result.GetError())) def activateFrame(self, args): self.reportToken(args) @@ -1675,7 +1674,7 @@ class Dumper(DumperBase): self.process.SetSelectedThreadByID(int(args['id'])) self.reportResult('', args) - def fetchFullBacktrace(self, _ = None): + def fetchFullBacktrace(self, _=None): command = 'thread backtrace all' result = lldb.SBCommandReturnObject() self.debugger.GetCommandInterpreter().HandleCommand(command, result) @@ -1748,7 +1747,7 @@ class Dumper(DumperBase): result += ',hunk="%s"}' % hunk result += '{address="%s"' % loadAddr result += ',data="%s %s"' % (insn.GetMnemonic(self.target), - insn.GetOperands(self.target)) + insn.GetOperands(self.target)) result += ',function="%s"' % functionName rawData = insn.GetData(self.target).uint8s result += ',rawdata="%s"' % ' '.join(["%02x" % x for x in rawData]) @@ -1854,7 +1853,7 @@ class Tester(Dumper): error = lldb.SBError() launchInfo = lldb.SBLaunchInfo([]) launchInfo.SetWorkingDirectory(os.getcwd()) - environmentList = [key + '=' + value for key,value in os.environ.items()] + environmentList = [key + '=' + value for key, value in os.environ.items()] launchInfo.SetEnvironmentEntries(environmentList, False) self.process = self.target.Launch(launchInfo, error) @@ -1868,9 +1867,9 @@ class Tester(Dumper): if listener.WaitForEvent(100, event): #DumperBase.warn('EVENT: %s' % event) state = lldb.SBProcess.GetStateFromEvent(event) - if state == lldb.eStateExited: # 10 + if state == lldb.eStateExited: # 10 break - if state == lldb.eStateStopped: # 5 + if state == lldb.eStateStopped: # 5 stoppedThread = None for i in range(0, self.process.GetNumThreads()): thread = self.process.GetThreadAtIndex(i) @@ -1904,14 +1903,16 @@ class Tester(Dumper): # ------------------------------ For use in LLDB ------------------------------ + from pprint import pprint __module__ = sys.modules[__name__] DEBUG = False if not hasattr(__module__, 'DEBUG') else DEBUG -class LogMixin: + +class LogMixin(): @staticmethod - def log(message = '', log_caller = False, frame = 1, args = ''): + def log(message='', log_caller=False, frame=1, args=''): if not DEBUG: return if log_caller: @@ -1925,13 +1926,15 @@ class LogMixin: print(message) @staticmethod - def log_fn(arg_str = ''): - LogMixin.log(log_caller = True, frame = 2, args = arg_str) + def log_fn(arg_str=''): + LogMixin.log(log_caller=True, frame=2, args=arg_str) + class DummyDebugger(object): def __getattr__(self, attr): raise AttributeError("Debugger should not be needed to create summaries") + class SummaryDumper(Dumper, LogMixin): _instance = None _lock = threading.RLock() @@ -1971,9 +1974,9 @@ class SummaryDumper(Dumper, LogMixin): Dumper.__init__(self, DummyDebugger()) self.setVariableFetchingOptions({ - 'fancy' : True, - 'qobjectnames' : True, - 'passexceptions' : True + 'fancy': True, + 'qobjectnames': True, + 'passexceptions': True }) self.dumpermodules = ['qttypes'] @@ -1981,19 +1984,19 @@ class SummaryDumper(Dumper, LogMixin): self.output = '' def report(self, stuff): - return # Don't mess up lldb output + return # Don't mess up lldb output def lookupNativeTypeInAllModules(self, name): self.warn('Failed to resolve type %s' % name) return None - def dump_summary(self, valobj, expanded = False): + def dump_summary(self, valobj, expanded=False): try: from pygdbmi import gdbmiparser except ImportError: print("Qt summary provider requires the pygdbmi module, " - "please install using 'sudo /usr/bin/easy_install pygdbmi', " - "and then restart Xcode.") + "please install using 'sudo /usr/bin/easy_install pygdbmi', " + "and then restart Xcode.") lldb.debugger.HandleCommand('type category delete Qt') return None @@ -2021,14 +2024,15 @@ class SummaryDumper(Dumper, LogMixin): return summary + class SummaryProvider(LogMixin): DEFAULT_SUMMARY = '' VOID_PTR_TYPE = None @staticmethod - def provide_summary(valobj, internal_dict, options = None): - if not __name__ in internal_dict: + def provide_summary(valobj, internal_dict, options=None): + if __name__ not in internal_dict: # When disabling the import of the Qt summary providers, the # summary functions are still registered with LLDB, and we will # get callbacks to provide summaries, but at this point the child @@ -2048,7 +2052,7 @@ class SummaryProvider(LogMixin): return provider.get_summary(options) - def __init__(self, valobj, expand = False): + def __init__(self, valobj, expand=False): # Prevent recursive evaluation during logging, etc valobj.SetPreferSyntheticValue(False) @@ -2088,29 +2092,29 @@ class SummaryProvider(LogMixin): if encoding: special_encodings = { - "empty" : "", - "minimumitemcount" : "" % summaryValue, - "undefined" : "", - "null" : "", - "itemcount" : "<%s items>" % summaryValue, - "notaccessible" : "", - "optimizedout" : "", - "nullreference" : "", - "emptystructure" : "", - "uninitialized" : "", - "invalid" : "", - "notcallable" : "", - "outofscope" : "" + "empty": "", + "minimumitemcount": "" % summaryValue, + "undefined": "", + "null": "", + "itemcount": "<%s items>" % summaryValue, + "notaccessible": "", + "optimizedout": "", + "nullreference": "", + "emptystructure": "", + "uninitialized": "", + "invalid": "", + "notcallable": "", + "outofscope": "" } if encoding in special_encodings: return special_encodings[encoding] text_encodings = [ 'latin1', - # 'local8bit', + # 'local8bit', 'utf8', 'utf16', - # 'ucs4' + # 'ucs4' ] if encoding in text_encodings: @@ -2122,8 +2126,15 @@ class SummaryProvider(LogMixin): return "" % (summaryValue, encoding) # FIXME: Support these - other_encodings = ['int', 'uint', 'float', 'juliandate', 'juliandateandmillisecondssincemidnight', - 'millisecondssincemidnight', 'ipv6addressandhexscopeid', 'datetimeinternal'] + other_encodings = [ + 'int', + 'uint', + 'float', + 'juliandate', + 'juliandateandmillisecondssincemidnight', + 'millisecondssincemidnight', + 'ipv6addressandhexscopeid', + 'datetimeinternal'] summaryValue += " " % encoding @@ -2136,9 +2147,10 @@ class SummaryProvider(LogMixin): return summaryValue.strip() + class SyntheticChildrenProvider(SummaryProvider): def __init__(self, valobj, dict): - SummaryProvider.__init__(self, valobj, expand = True) + SummaryProvider.__init__(self, valobj, expand=True) self.summary = None self.synthetic_children = [] @@ -2147,7 +2159,7 @@ class SyntheticChildrenProvider(SummaryProvider): def num_children(self): self.log("native: %d synthetic: %d" % - (self.num_native_children(), len(self.synthetic_children)), True) + (self.num_native_children(), len(self.synthetic_children)), True) return self._num_children() def _num_children(self): @@ -2181,7 +2193,7 @@ class SyntheticChildrenProvider(SummaryProvider): return value - def create_value(self, child, name = ''): + def create_value(self, child, name=''): child_type = child.get('type', self.summary.get('childtype')) value = None @@ -2196,8 +2208,8 @@ class SyntheticChildrenProvider(SummaryProvider): # Create as void* so that the value is fully initialized before # we trigger our own summary/child providers recursively. - value = self.valobj.synthetic_child_from_address(name, address, - SummaryProvider.VOID_PTR_TYPE).Cast(value_type) + value = self.valobj.synthetic_child_from_address( + name, address, SummaryProvider.VOID_PTR_TYPE).Cast(value_type) else: self.log("Don't know how to create value for child %s" % child) # FIXME: Figure out if we ever will hit this case, and deal with it @@ -2219,7 +2231,7 @@ class SyntheticChildrenProvider(SummaryProvider): dereference_child = None for child in self.summary['children']: - if not child or not type(child) is dict: + if not child or not isinstance(child, dict): continue # Skip base classes, they are built-in children @@ -2254,8 +2266,9 @@ class SyntheticChildrenProvider(SummaryProvider): # the debugger UI, even if dereferencing the pointer works fine. # We fall back to the special child reported by the Qt dumper. if not self.valobj.GetNumChildren() and dereference_child: - self.valobj = self.create_value(dereference_child) - self.update() + self.valobj = self.create_value(dereference_child) + self.update() + def __lldb_init_module(debugger, internal_dict): # Module is being imported in an LLDB session @@ -2266,25 +2279,25 @@ def __lldb_init_module(debugger, internal_dict): # Concrete types summary_function = "%s.%s.%s" % (__name__, 'SummaryProvider', 'provide_summary') types = map(lambda x: x.replace('__', '::'), dumper.qqDumpers) - debugger.HandleCommand("type summary add -F %s -w %s %s" \ - % (summary_function, type_category, ' '.join(types))) + debugger.HandleCommand("type summary add -F %s -w %s %s" + % (summary_function, type_category, ' '.join(types))) regex_types = list(map(lambda x: "'" + x + "'", dumper.qqDumpersEx.keys())) if regex_types: - debugger.HandleCommand("type summary add -x -F %s -w %s %s" \ - % (summary_function, type_category, ' '.join(regex_types))) + debugger.HandleCommand("type summary add -x -F %s -w %s %s" + % (summary_function, type_category, ' '.join(regex_types))) # Global catch-all for Qt classes - debugger.HandleCommand("type summary add -x '^Q.*$' -F %s -w %s" \ - % (summary_function, type_category)) + debugger.HandleCommand("type summary add -x '^Q.*$' -F %s -w %s" + % (summary_function, type_category)) # Named summary ('frame variable foo --summary Qt') - debugger.HandleCommand("type summary add --name Qt -F %s -w %s" \ - % (summary_function, type_category)) + debugger.HandleCommand("type summary add --name Qt -F %s -w %s" + % (summary_function, type_category)) # Synthetic children - debugger.HandleCommand("type synthetic add -x '^Q.*$' -l %s -w %s" \ - % ("lldbbridge.SyntheticChildrenProvider", type_category)) + debugger.HandleCommand("type synthetic add -x '^Q.*$' -l %s -w %s" + % ("lldbbridge.SyntheticChildrenProvider", type_category)) debugger.HandleCommand('type category enable %s' % type_category) diff --git a/share/qtcreator/debugger/misctypes.py b/share/qtcreator/debugger/misctypes.py index 9889e5ca97b..864f280b5e8 100644 --- a/share/qtcreator/debugger/misctypes.py +++ b/share/qtcreator/debugger/misctypes.py @@ -33,39 +33,46 @@ import re # ####################################################################### + def qdump____m128(d, value): d.putEmptyValue() if d.isExpanded(): d.putArrayData(value.address(), 4, d.lookupType('float')) + def qdump____m256(d, value): d.putEmptyValue() if d.isExpanded(): d.putArrayData(value.address(), 8, d.lookupType('float')) + def qdump____m512(d, value): d.putEmptyValue() if d.isExpanded(): d.putArrayData(value.address(), 16, d.lookupType('float')) + def qdump____m128d(d, value): d.putEmptyValue() if d.isExpanded(): d.putArrayData(value.address(), 2, d.lookupType('double')) + def qdump____m256d(d, value): d.putEmptyValue() if d.isExpanded(): d.putArrayData(value.address(), 4, d.lookupType('double')) + def qdump____m512d(d, value): d.putEmptyValue() if d.isExpanded(): d.putArrayData(value.address(), 8, d.lookupType('double')) + def qdump____m128i(d, value): data = d.hexencode(value.data(16)) - d.putValue(':'.join('%04x' % int(data[i:i+4], 16) for i in range(0, 32, 4))) + d.putValue(':'.join('%04x' % int(data[i:i + 4], 16) for i in range(0, 32, 4))) if d.isExpanded(): with Children(d): addr = value.address() @@ -74,9 +81,10 @@ def qdump____m128i(d, value): d.putArrayItem('uint32x4', addr, 4, 'unsigned int') d.putArrayItem('uint64x2', addr, 2, 'unsigned long long') + def qdump____m256i(d, value): data = d.hexencode(value.data(32)) - d.putValue(':'.join('%04x' % int(data[i:i+4], 16) for i in range(0, 64, 4))) + d.putValue(':'.join('%04x' % int(data[i:i + 4], 16) for i in range(0, 64, 4))) if d.isExpanded(): with Children(d): addr = value.address() @@ -85,10 +93,11 @@ def qdump____m256i(d, value): d.putArrayItem('uint32x8', addr, 8, 'unsigned int') d.putArrayItem('uint64x4', addr, 4, 'unsigned long long') + def qdump____m512i(d, value): data = d.hexencode(value.data(64)) - d.putValue(':'.join('%04x' % int(data[i:i+4], 16) for i in range(0, 64, 4)) - + ', ' + ':'.join('%04x' % int(data[i:i+4], 16) for i in range(64, 128, 4))) + d.putValue(':'.join('%04x' % int(data[i:i + 4], 16) for i in range(0, 64, 4)) + + ', ' + ':'.join('%04x' % int(data[i:i + 4], 16) for i in range(64, 128, 4))) if d.isExpanded(): with Children(d): d.putArrayItem('uint32x16', value.address(), 16, 'unsigned int') @@ -100,15 +109,18 @@ def qdump____m512i(d, value): # ####################################################################### + def qform__std__array(): return [DisplayFormat.ArrayPlotFormat] + def qdump__gsl__span(d, value): size, pointer = value.split('pp') d.putItemCount(size) if d.isExpanded(): d.putPlotData(pointer, size, value.type[0]) + def qdump__gsl__byte(d, value): d.putNumChild(0) d.putValue(value.integer()) @@ -122,6 +134,7 @@ def qdump__gsl__byte(d, value): #def qform__Eigen__Matrix(): # return 'Transposed' + def qdump__Eigen__Matrix(d, value): innerType = value.type[0] argRow = value.type[1] @@ -185,7 +198,8 @@ def qdump__NimStringDesc(d, value): d.putBetterType('string') d.putCharArrayHelper(data, size, d.createType('char'), 'utf8') -def qdump__NimGenericSequence__(d, value, regex = '^TY[\d]+$'): + +def qdump__NimGenericSequence__(d, value, regex=r'^TY[\d]+$'): code = value.type.stripTypedefs().code if code == TypeCode.TypeCodeStruct: size, reserved = d.split('pp', value) @@ -198,6 +212,7 @@ def qdump__NimGenericSequence__(d, value, regex = '^TY[\d]+$'): d.putEmptyValue() d.putPlainChildren(value) + def qdump__TNimNode(d, value): name = value['name'].pointer() d.putSimpleCharArray(name) if name != 0 else d.putEmptyValue() @@ -222,6 +237,7 @@ def qdump__TNimNode(d, value): def cleanDType(type): return str(type).replace('uns long long', 'string') + def qdump_Array(d, value): n = value['length'] p = value['ptr'] @@ -251,7 +267,7 @@ def qdump_AArray(d, value): d.putEmptyValue() if d.isExpanded(): with Children(d, 1): - d.putSubItem('ptr', p) + d.putSubItem('ptr', p) ####################################################################### @@ -264,7 +280,7 @@ if False: def qdump__tree_entry(d, value): d.putValue('len: %s, offset: %s, type: %s' % - (value['blocklength'], value['offset'], value['type'])) + (value['blocklength'], value['offset'], value['type'])) d.putNumChild(0) def qdump__tree(d, value): @@ -273,42 +289,42 @@ if False: base = value['base'].pointer() d.putItemCount(count) if d.isExpanded(): - with Children(d): - with SubItem(d, 'tree'): - d.putEmptyValue() - d.putNoType() - if d.isExpanded(): - with Children(d): - for i in range(count): - d.putSubItem(Item(entries[i], iname)) - with SubItem(d, 'data'): - d.putEmptyValue() - d.putNoType() - if d.isExpanded(): - with Children(d): - for i in range(count): - with SubItem(d, i): - entry = entries[i] - mpitype = str(entry['type']) - d.putType(mpitype) - length = int(entry['blocklength']) - offset = int(entry['offset']) - d.putValue('%s items at %s' % (length, offset)) - if mpitype == 'MPI_INT': - innerType = 'int' - elif mpitype == 'MPI_CHAR': - innerType = 'char' - elif mpitype == 'MPI_DOUBLE': - innerType = 'double' - else: - length = 0 - d.putNumChild(length) - if d.isExpanded(): - with Children(d): - t = d.lookupType(innerType).pointer() - p = (base + offset).cast(t) - for j in range(length): - d.putSubItem(j, p.dereference()) + with Children(d): + with SubItem(d, 'tree'): + d.putEmptyValue() + d.putNoType() + if d.isExpanded(): + with Children(d): + for i in range(count): + d.putSubItem(Item(entries[i], iname)) + with SubItem(d, 'data'): + d.putEmptyValue() + d.putNoType() + if d.isExpanded(): + with Children(d): + for i in range(count): + with SubItem(d, i): + entry = entries[i] + mpitype = str(entry['type']) + d.putType(mpitype) + length = int(entry['blocklength']) + offset = int(entry['offset']) + d.putValue('%s items at %s' % (length, offset)) + if mpitype == 'MPI_INT': + innerType = 'int' + elif mpitype == 'MPI_CHAR': + innerType = 'char' + elif mpitype == 'MPI_DOUBLE': + innerType = 'double' + else: + length = 0 + d.putNumChild(length) + if d.isExpanded(): + with Children(d): + t = d.lookupType(innerType).pointer() + p = (base + offset).cast(t) + for j in range(length): + d.putSubItem(j, p.dereference()) ####################################################################### @@ -322,6 +338,7 @@ def qdump__KDSoapValue1(d, value): d.putStringValue(inner['m_name']) d.putPlainChildren(inner) + def qdump__KDSoapValue(d, value): p = (value.cast(d.lookupType('char*')) + 4).dereference().cast(d.lookupType('QString')) d.putStringValue(p) @@ -528,6 +545,7 @@ def qdump__PyVarObject(d, value): def qdump__QtcDumperTest_FieldAccessByIndex(d, value): d.putValue(value["d"][2].integer()) + def qdump__QtcDumperTest_PointerArray(d, value): foos = value["foos"] d.putItemCount(10) @@ -536,6 +554,7 @@ def qdump__QtcDumperTest_PointerArray(d, value): for i in d.childRange(): d.putSubItem(i, foos[i]) + def qdump__QtcDumperTest_BufArray(d, value): maxItems = 1000 buffer = value['buffer'] @@ -549,11 +568,12 @@ def qdump__QtcDumperTest_BufArray(d, value): for i in d.childRange(): d.putSubItem(i, (buffer + (i * objsize)).dereference().cast(valueType)) + def qdump__QtcDumperTest_List__NodeX(d, value): typename = value.type.unqualified().name pos0 = typename.find('<') pos1 = typename.find('>') - tName = typename[pos0+1:pos1] + tName = typename[pos0 + 1:pos1] d.putBetterType('QtcDumperTest_List<' + tName + '>::Node') d.putNumChild(1) if d.isExpanded(): @@ -563,6 +583,7 @@ def qdump__QtcDumperTest_List__NodeX(d, value): d.putFields(value) #d.putPlainChildren(value) + def qdump__QtcDumperTest_List(d, value): innerType = value.type[0] d.putNumChild(1) @@ -574,6 +595,7 @@ def qdump__QtcDumperTest_List(d, value): d.putFields(value) #d.putPlainChildren(value) + def qdump__QtcDumperTest_String(d, value): with Children(d): first = d.hexdecode(d.putSubItem('first', value['first']).value) diff --git a/share/qtcreator/debugger/opencvtypes.py b/share/qtcreator/debugger/opencvtypes.py index 7a62af7041f..1e4a07d1cae 100644 --- a/share/qtcreator/debugger/opencvtypes.py +++ b/share/qtcreator/debugger/opencvtypes.py @@ -26,16 +26,19 @@ from dumper import Children, SubItem from utils import TypeCode, DisplayFormat + def qdump__cv__Size_(d, value): d.putValue('(%s, %s)' % (value[0].display(), value[1].display())) d.putPlainChildren(value) + def qform__cv__Mat(): return [DisplayFormat.SeparateFormat] + def qdump__cv__Mat(d, value): (flag, dims, rows, cols, data, refcount, datastart, dataend, - datalimit, allocator, size, stepp) \ + datalimit, allocator, size, stepp) \ = value.split('iiiipppppppp') steps = d.split('p' * dims, stepp) innerSize = 0 if dims == 0 else steps[dims - 1] diff --git a/share/qtcreator/debugger/pdbbridge.py b/share/qtcreator/debugger/pdbbridge.py index 4c77d41ce5b..463e8a97ff6 100644 --- a/share/qtcreator/debugger/pdbbridge.py +++ b/share/qtcreator/debugger/pdbbridge.py @@ -41,7 +41,7 @@ class QuitException(Exception): pass -class QtcInternalBreakpoint: +class QtcInternalBreakpoint(): """Breakpoint class. Breakpoints are indexed by number through bpbynumber and by the file,line tuple using bplist. The former points to a @@ -52,9 +52,9 @@ class QtcInternalBreakpoint: next = 1 # Next bp to be assigned bplist = {} # indexed by (file, lineno) tuple - bpbynumber = [None] # Each entry is None or an instance of Bpt - # index 0 is unused, except for marking an - # effective break .... see effective() + bpbynumber = [None] # Each entry is None or an instance of Bpt + # index 0 is unused, except for marking an + # effective break .... see effective() def __init__(self, filepath, line, temporary=False, cond=None, funcname=None): self.funcname = funcname @@ -115,7 +115,7 @@ def checkfuncname(b, frame): # The function is entered for the 1st time. b.func_first_executable_line = frame.f_lineno - if b.func_first_executable_line != frame.f_lineno: + if b.func_first_executable_line != frame.f_lineno: # But we are not at the first line number: don't break. return False return True @@ -193,7 +193,7 @@ class _rstr(str): return self -class QtcInternalDumper: +class QtcInternalDumper(): identchars = string.ascii_letters + string.digits + '_' lastcmd = '' use_rawinput = 1 @@ -387,7 +387,7 @@ class QtcInternalDumper: # (CT) stopframe may now also be None, see dispatch_call. # (CT) the former test for None is therefore removed from here. if self.skip and \ - self.is_skipped_module(frame.f_globals.get('__name__')): + self.is_skipped_module(frame.f_globals.get('__name__')): return False if frame is self.stopframe: if self.stoplineno == -1: @@ -696,7 +696,7 @@ class QtcInternalDumper: return None, None, line i, length = 0, len(line) while i < length and line[i] in self.identchars: - i = i+1 + i = i + 1 cmd, arg = line[:i], line[i:].strip() return cmd, arg, line @@ -745,10 +745,10 @@ class QtcInternalDumper: import __main__ # __main__.__dict__.clear() - __main__.__dict__.update({'__name__' : '__main__', - '__file__' : mainpyfile, - # '__builtins__': __builtins__, - }) + __main__.__dict__.update({'__name__': '__main__', + '__file__': mainpyfile, + #'__builtins__': __builtins__, + }) # When bdb sets tracing, a number of call and line events happens # BEFORE debugger even reaches user's code (and the exact sequence of @@ -966,7 +966,7 @@ class QtcInternalDumper: comma = arg.find(',') if comma > 0: # parse stuff after comma: 'condition' - cond = arg[comma+1:].lstrip() + cond = arg[comma + 1:].lstrip() arg = arg[:comma].rstrip() # parse stuff before comma: [filename:]lineno | function colon = arg.rfind(':') @@ -979,7 +979,7 @@ class QtcInternalDumper: return else: filename = f - arg = arg[colon+1:].lstrip() + arg = arg[colon + 1:].lstrip() try: lineno = int(arg) except ValueError: @@ -1212,7 +1212,7 @@ class QtcInternalDumper: # Make sure it works for 'clear C:\foo\bar.py:12' i = arg.rfind(':') filename = arg[:i] - arg = arg[i+1:] + arg = arg[i + 1:] try: lineno = int(arg) except ValueError: diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 34d592ede7a..2407a25b2a9 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -28,6 +28,7 @@ import re from dumper import Children, SubItem, UnnamedSubItem, toInteger from utils import DisplayFormat + def qdump__QAtomicInt(d, value): d.putValue(value.integer()) d.putNumChild(0) @@ -45,13 +46,15 @@ def qdump__QAtomicPointer(d, value): def qform__QByteArray(): return [DisplayFormat.Latin1StringFormat, DisplayFormat.SeparateLatin1StringFormat, - DisplayFormat.Utf8StringFormat, DisplayFormat.SeparateUtf8StringFormat ] + DisplayFormat.Utf8StringFormat, DisplayFormat.SeparateUtf8StringFormat] + def qedit__QByteArray(d, value, data): d.call('void', value, 'resize', str(len(data))) (base, size, alloc) = d.stringData(value) d.setValues(base, 'char', [ord(c) for c in data]) + def qdump__QByteArray(d, value): data, size, alloc = d.byteArrayData(value) d.check(alloc == 0 or (0 <= size and size <= alloc and alloc <= 100000000)) @@ -71,6 +74,7 @@ def qdump__QByteArray(d, value): if d.isExpanded(): d.putArrayData(data, size, d.charType()) + def qdump__QArrayData(d, value): data, size, alloc = d.byteArrayDataHelper(value.address()) d.check(alloc == 0 or (0 <= size and size <= alloc and alloc <= 100000000)) @@ -78,6 +82,7 @@ def qdump__QArrayData(d, value): d.putNumChild(1) d.putPlainChildren(value) + def qdump__QByteArrayData(d, value): qdump__QArrayData(d, value) @@ -105,6 +110,7 @@ def qdump__QChar(d, value): def qform_X_QAbstractItemModel(): return [DisplayFormat.SimpleFormat, DisplayFormat.EnhancedFormat] + def qdump_X_QAbstractItemModel(d, value): displayFormat = d.currentItemFormat() if displayFormat == DisplayFormat.SimpleFormat: @@ -131,14 +137,16 @@ def qdump_X_QAbstractItemModel(d, value): with SubItem(d, i): d.putName('[%s, %s]' % (row, column)) mi = d.parseAndEvaluate('%s.index(%d,%d,%s)' - % (this_, row, column, ri_)) + % (this_, row, column, ri_)) d.putItem(mi) i = i + 1 #gdb.execute('call free($ri)') + def qform_X_QModelIndex(): return [DisplayFormat.SimpleFormat, DisplayFormat.EnhancedFormat] + def qdump_X_QModelIndex(d, value): displayFormat = d.currentItemFormat() if displayFormat == DisplayFormat.SimpleFormat: @@ -187,44 +195,47 @@ def qdump_X_QModelIndex(d, value): with UnnamedSubItem(d, i): d.putName('[%s, %s]' % (row, column)) mi2 = d.parseAndEvaluate('%s.index(%d,%d,%s)' - % (mm_, row, column, mi_)) + % (mm_, row, column, mi_)) d.putItem(mi2) i = i + 1 d.putCallItem('parent', '@QModelIndex', value, 'parent') #gdb.execute('call free($mi)') + def qdump__Qt__ItemDataRole(d, value): d.putEnumValue(value.integer(), { - 0 : "Qt::DisplayRole", - 1 : "Qt::DecorationRole", - 2 : "Qt::EditRole", - 3 : "Qt::ToolTipRole", - 4 : "Qt::StatusTipRole", - 5 : "Qt::WhatsThisRole", - 6 : "Qt::FontRole", - 7 : "Qt::TextAlignmentRole", + 0: "Qt::DisplayRole", + 1: "Qt::DecorationRole", + 2: "Qt::EditRole", + 3: "Qt::ToolTipRole", + 4: "Qt::StatusTipRole", + 5: "Qt::WhatsThisRole", + 6: "Qt::FontRole", + 7: "Qt::TextAlignmentRole", # obsolete: 8 : "Qt::BackgroundColorRole", - 8 : "Qt::BackgroundRole", + 8: "Qt::BackgroundRole", # obsolete: 9 : "Qt::TextColorRole", - 9 : "Qt::ForegroundRole", - 10 : "Qt::CheckStateRole", - 11 : "Qt::AccessibleTextRole", - 12 : "Qt::AccessibleDescriptionRole", - 13 : "Qt::SizeHintRole", - 14 : "Qt::InitialSortOrderRole", + 9: "Qt::ForegroundRole", + 10: "Qt::CheckStateRole", + 11: "Qt::AccessibleTextRole", + 12: "Qt::AccessibleDescriptionRole", + 13: "Qt::SizeHintRole", + 14: "Qt::InitialSortOrderRole", # 27-31 Qt4 ItemDataRoles - 27 : "Qt::DisplayPropertyRole", - 28 : "Qt::DecorationPropertyRole", - 29 : "Qt::ToolTipPropertyRole", - 30 : "Qt::StatusTipPropertyRole", - 31 : "Qt::WhatsThisPropertyRole", - 0x100 : "Qt::UserRole" + 27: "Qt::DisplayPropertyRole", + 28: "Qt::DecorationPropertyRole", + 29: "Qt::ToolTipPropertyRole", + 30: "Qt::StatusTipPropertyRole", + 31: "Qt::WhatsThisPropertyRole", + 0x100: "Qt::UserRole" }) + def qdump__QStandardItemData(d, value): role, pad, val = value.split('{@Qt::ItemDataRole}@{QVariant}') d.putPairContents(role.value(), (role, val), 'role', 'value') + def qdump__QStandardItem(d, value): vtable, dptr = value.split('pp') # There used to be a virtual destructor that got removed in @@ -240,7 +251,7 @@ def qdump__QStandardItem(d, value): d.putSubItem('[model]', d.createValue(model, '@QStandardItemModel')) d.putSubItem('[values]', d.createVectorItem(values, '@QStandardItemData')) d.putSubItem('[children]', d.createVectorItem(children, - d.createPointerType(value.type))) + d.createPointerType(value.type))) def qdump__QDate(d, value): @@ -252,13 +263,13 @@ def qdump__QDate(d, value): with Children(d): if d.canCallLocale(): d.putCallItem('toString', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'TextDate')) + d.enumExpression('DateFormat', 'TextDate')) d.putCallItem('(ISO)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'ISODate')) + d.enumExpression('DateFormat', 'ISODate')) d.putCallItem('(SystemLocale)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'SystemLocaleDate')) + d.enumExpression('DateFormat', 'SystemLocaleDate')) d.putCallItem('(Locale)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'LocaleDate')) + d.enumExpression('DateFormat', 'LocaleDate')) d.putFields(value) else: d.putValue('(invalid)') @@ -275,14 +286,14 @@ def qdump__QTime(d, value): if d.isExpanded(): with Children(d): d.putCallItem('toString', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'TextDate')) + d.enumExpression('DateFormat', 'TextDate')) d.putCallItem('(ISO)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'ISODate')) + d.enumExpression('DateFormat', 'ISODate')) if d.canCallLocale(): d.putCallItem('(SystemLocale)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'SystemLocaleDate')) + d.enumExpression('DateFormat', 'SystemLocaleDate')) d.putCallItem('(Locale)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'LocaleDate')) + d.enumExpression('DateFormat', 'LocaleDate')) d.putFields(value) @@ -292,7 +303,7 @@ def qdump__QTimeZone(d, value): d.putValue('(null)') d.putNumChild(0) return - idAddr = base + 2 * d.ptrSize() # [QSharedData] + [vptr] + idAddr = base + 2 * d.ptrSize() # [QSharedData] + [vptr] d.putByteArrayValue(idAddr) d.putPlainChildren(value['d']) @@ -325,7 +336,14 @@ def qdump__QDateTime(d, value): spec = (status & 0x30) >> 4 isValid = True - d.putValue('%s/%s/%s/%s/%s/%s' % (msecs, spec, offsetFromUtc, timeZone, status, tiVersion), + d.putValue( + '%s/%s/%s/%s/%s/%s' % + (msecs, + spec, + offsetFromUtc, + timeZone, + status, + tiVersion), 'datetimeinternal') else: if d.isWindowsTarget(): @@ -341,7 +359,7 @@ def qdump__QDateTime(d, value): timeZoneOffset = 20 if is32bit else 24 statusOffset = 24 if is32bit else 32 status = d.extractInt(base + statusOffset) - if int(status & 0x0c == 0x0c): # ValidDate and ValidTime + if int(status & 0x0c == 0x0c): # ValidDate and ValidTime isValid = True msecs = d.extractInt64(base + msecsOffset) spec = d.extractInt(base + specOffset) @@ -350,10 +368,10 @@ def qdump__QDateTime(d, value): if tzp == 0: tz = '' else: - idBase = tzp + 2 * d.ptrSize() # [QSharedData] + [vptr] + idBase = tzp + 2 * d.ptrSize() # [QSharedData] + [vptr] elided, tz = d.encodeByteArrayHelper(d.extractPointer(idBase), limit=100) d.putValue('%s/%s/%s/%s/%s/%s' % (msecs, spec, offset, tz, status, 0), - 'datetimeinternal') + 'datetimeinternal') else: # This relies on the Qt4/Qt5 internal structure layout: # {sharedref(4), date(8), time(4+x)} @@ -364,7 +382,7 @@ def qdump__QDateTime(d, value): # - [QTime time;] # - - uint mds; # - Spec spec; - dateSize = 8 if qtVersion >= 0x050000 else 4 # Qt5: qint64, Qt4 uint + dateSize = 8 if qtVersion >= 0x050000 else 4 # Qt5: qint64, Qt4 uint # 4 byte padding after 4 byte QAtomicInt if we are on 64 bit and QDate is 64 bit refPlusPadding = 8 if qtVersion >= 0x050000 and d.ptrSize() == 8 else 4 dateBase = base + refPlusPadding @@ -386,17 +404,17 @@ def qdump__QDateTime(d, value): d.putCallItem('toTime_t', 'unsigned int', value, 'toTime_t') if d.canCallLocale(): d.putCallItem('toString', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'TextDate')) + d.enumExpression('DateFormat', 'TextDate')) d.putCallItem('(ISO)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'ISODate')) + d.enumExpression('DateFormat', 'ISODate')) d.putCallItem('toUTC', '@QDateTime', value, 'toTimeSpec', - d.enumExpression('TimeSpec', 'UTC')) + d.enumExpression('TimeSpec', 'UTC')) d.putCallItem('(SystemLocale)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'SystemLocaleDate')) + d.enumExpression('DateFormat', 'SystemLocaleDate')) d.putCallItem('(Locale)', '@QString', value, 'toString', - d.enumExpression('DateFormat', 'LocaleDate')) + d.enumExpression('DateFormat', 'LocaleDate')) d.putCallItem('toLocalTime', '@QDateTime', value, 'toTimeSpec', - d.enumExpression('TimeSpec', 'LocalTime')) + d.enumExpression('TimeSpec', 'LocalTime')) d.putFields(value) @@ -507,6 +525,7 @@ def qdump__QEvent(d, value): # Show the rest of the class fields as usual. d.putFields(value) + def qdump__QKeyEvent(d, value): # QEvent fields # virtual table pointer @@ -611,7 +630,7 @@ def qdump__QFile(d, value): if d.isMsvcTarget(): offset = 164 if is32bit else 224 else: - offset = 160 if is32bit else 224 + offset = 160 if is32bit else 224 else: offset = 156 if is32bit else 224 elif qtVersion >= 0x050700: @@ -752,13 +771,14 @@ def qdump__QFileInfo(d, value): def qdump__QFixed(d, value): v = value.split('i')[0] - d.putValue('%s/64 = %s' % (v, v/64.0)) + d.putValue('%s/64 = %s' % (v, v / 64.0)) d.putNumChild(0) def qform__QFiniteStack(): return [DisplayFormat.ArrayPlotFormat] + def qdump__QFiniteStack(d, value): array, alloc, size = value.split('pii') d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000) @@ -777,12 +797,15 @@ def qdump__QFlags(d, value): def qform__QHash(): return [DisplayFormat.CompactMapFormat] + def qdump__QHash(d, value): qdumpHelper_QHash(d, value, value.type[0], value.type[1]) + def qdump__QVariantHash(d, value): qdumpHelper_QHash(d, value, d.createType('QString'), d.createType('QVariant')) + def qdumpHelper_QHash(d, value, keyType, valueType): def hashDataFirstNode(): b = buckets @@ -837,9 +860,11 @@ def qdumpHelper_QHash(d, value, keyType, valueType): def qform__QHashNode(): return [DisplayFormat.CompactMapFormat] + def qdump__QHashNode(d, value): d.putPairItem(None, value) + def qHashIteratorHelper(d, value): typeName = value.type.name hashTypeName = typeName[0:typeName.rfind('::')] @@ -861,9 +886,11 @@ def qHashIteratorHelper(d, value): d.putSubItem('key', key) d.putSubItem('value', val) + def qdump__QHash__const_iterator(d, value): qHashIteratorHelper(d, value) + def qdump__QHash__iterator(d, value): qHashIteratorHelper(d, value) @@ -887,19 +914,19 @@ def qdump__QHostAddress(d, value): else: (ipString, scopeId, a4, pad, a6, protocol, isParsed) \ = d.split('{QString}{QString}{quint32}I16sI{bool}', dd) - elif qtVersion >= 0x050600: # 5.6.0 at f3aabb42 + elif qtVersion >= 0x050600: # 5.6.0 at f3aabb42 if d.ptrSize() == 8 or d.isWindowsTarget(): (ipString, scopeId, a4, pad, a6, protocol, isParsed) \ = d.split('{QString}{QString}{quint32}I16sI{bool}', dd) else: (ipString, scopeId, a4, a6, protocol, isParsed) \ = d.split('{QString}{QString}{quint32}16sI{bool}', dd) - elif qtVersion >= 0x050000: # 5.2.0 at 62feb088 + elif qtVersion >= 0x050000: # 5.2.0 at 62feb088 (ipString, scopeId, a4, a6, protocol, isParsed) \ = d.split('{QString}{QString}{quint32}16sI{bool}', dd) - else: # 4.8.7 at b05d05f + else: # 4.8.7 at b05d05f (a4, a6, protocol, pad, ipString, isParsed, pad, scopeId) \ - = d.split('{quint32}16sB@{QString}{bool}@{QString}', dd) + = d.split('{quint32}16sB@{QString}{bool}@{QString}', dd) if mayNeedParse: ipStringData, ipStringSize, ipStringAlloc = d.stringData(ipString) @@ -912,7 +939,7 @@ def qdump__QHostAddress(d, value): if protocol == 1: # value.d.d->a6 data = d.hexencode(a6) - address = ':'.join('%x' % int(data[i:i+4], 16) for i in range(0, 32, 4)) + address = ':'.join('%x' % int(data[i:i + 4], 16) for i in range(0, 32, 4)) d.putValue(address) elif protocol == 0: # value.d.d->a @@ -921,7 +948,7 @@ def qdump__QHostAddress(d, value): a, n3 = divmod(a, 256) a, n2 = divmod(a, 256) a, n1 = divmod(a, 256) - d.putValue('%d.%d.%d.%d' % (n1, n2, n3, n4)); + d.putValue('%d.%d.%d.%d' % (n1, n2, n3, n4)) else: d.putValue('' % protocol) @@ -938,18 +965,22 @@ def qdump__QHostAddress(d, value): def qdump__QIPv6Address(d, value): raw = d.split('16s', value)[0] data = d.hexencode(raw) - d.putValue(':'.join('%x' % int(data[i:i+4], 16) for i in range(0, 32, 4))) + d.putValue(':'.join('%x' % int(data[i:i + 4], 16) for i in range(0, 32, 4))) d.putArrayData(value.address(), 16, d.lookupType('unsigned char')) + def qform__QList(): return [DisplayFormat.DirectQListStorageFormat, DisplayFormat.IndirectQListStorageFormat] + def qdump__QList(d, value): return qdumpHelper_QList(d, value, value.type[0]) + def qdump__QVariantList(d, value): qdumpHelper_QList(d, value, d.createType('QVariant')) + def qdumpHelper_QList(d, value, innerType): base = d.extractPointer(value) (ref, alloc, begin, end) = d.split('IIII', base) @@ -994,14 +1025,16 @@ def qdumpHelper_QList(d, value, innerType): x = d.createValue(p, innerType) d.putSubItem(i, x) + def qform__QImage(): return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + def qdump__QImage(d, value): if d.qtVersion() < 0x050000: - (vtbl, painters, imageData) = value.split('ppp'); + (vtbl, painters, imageData) = value.split('ppp') else: - (vtbl, painters, reserved, imageData) = value.split('pppp'); + (vtbl, painters, reserved, imageData) = value.split('pppp') if imageData == 0: d.putValue('(invalid)') @@ -1026,15 +1059,15 @@ def qdump__QImage(d, value): displayFormat = d.currentItemFormat() if displayFormat == DisplayFormat.SeparateFormat: d.putDisplay('imagedata:separate', '%08x%08x%08x%08x' % (width, height, nbytes, iformat) - + d.readMemory(bits, nbytes)) + + d.readMemory(bits, nbytes)) def qdump__QLinkedList(d, value): dd = d.extractPointer(value) ptrSize = d.ptrSize() - n = d.extractInt(dd + 4 + 2 * ptrSize); - ref = d.extractInt(dd + 2 * ptrSize); - d.check(0 <= n and n <= 100*1000*1000) + n = d.extractInt(dd + 4 + 2 * ptrSize) + ref = d.extractInt(dd + 2 * ptrSize) + d.check(0 <= n and n <= 100 * 1000 * 1000) d.check(-1 <= ref and ref <= 1000) d.putItemCount(n) if d.isExpanded(): @@ -1045,10 +1078,12 @@ def qdump__QLinkedList(d, value): d.putSubItem(i, d.createValue(pp + 2 * ptrSize, innerType)) pp = d.extractPointer(pp) + qqLocalesCount = None + def qdump__QLocale(d, value): - if d.isMsvcTarget(): # as long as this dumper relies on calling functions skip it for cdb + if d.isMsvcTarget(): # as long as this dumper relies on calling functions skip it for cdb return # Check for uninitialized 'index' variable. Retrieve size of @@ -1079,11 +1114,11 @@ def qdump__QLocale(d, value): dd = value.extractPointer() (data, ref, numberOptions) = d.split('pi4s', dd) (languageId, scriptId, countryId, - decimal, group, listt, percent, zero, - minus, plus, exponential) \ + decimal, group, listt, percent, zero, + minus, plus, exponential) \ = d.split('2s{short}2s' - + '{QChar}{QChar}{short}{QChar}{QChar}' - + '{QChar}{QChar}{QChar}', data) + + '{QChar}{QChar}{short}{QChar}{QChar}' + + '{QChar}{QChar}{QChar}', data) d.putStringValue(d.call('const char *', value, 'name')) d.putNumChild(1) if d.isExpanded(): @@ -1100,11 +1135,11 @@ def qdump__QLocale(d, value): d.putSubItem('negativeSign', minus) d.putSubItem('positiveSign', plus) d.putCallItem('measurementSystem', '@QLocale::MeasurementSystem', - value, 'measurementSystem') + value, 'measurementSystem') d.putCallItem('timeFormat_(short)', '@QString', - value, 'timeFormat', ns + 'QLocale::ShortFormat') + value, 'timeFormat', ns + 'QLocale::ShortFormat') d.putCallItem('timeFormat_(long)', '@QString', - value, 'timeFormat', ns + 'QLocale::LongFormat') + value, 'timeFormat', ns + 'QLocale::LongFormat') d.putFields(value) @@ -1121,7 +1156,7 @@ def qdumpHelper_Qt4_QMap(d, value, keyType, valueType): dd = value.extractPointer() (dummy, it, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, ref, toplevel, n) = d.split('p' * 13 + 'iii', dd) - d.check(0 <= n and n <= 100*1000*1000) + d.check(0 <= n and n <= 100 * 1000 * 1000) d.checkRef(ref) d.putItemCount(n) if d.isExpanded(): @@ -1141,7 +1176,7 @@ def qdumpHelper_Qt4_QMap(d, value, keyType, valueType): def qdumpHelper_Qt5_QMap(d, value, keyType, valueType): dptr = d.extractPointer(value) (ref, n) = d.split('ii', dptr) - d.check(0 <= n and n <= 100*1000*1000) + d.check(0 <= n and n <= 100 * 1000 * 1000) d.check(-1 <= ref and ref < 100000) d.putItemCount(n) @@ -1169,39 +1204,50 @@ def qdumpHelper_Qt5_QMap(d, value, keyType, valueType): def qform__QMap(): return [DisplayFormat.CompactMapFormat] + def qdump__QMap(d, value): qdumpHelper_QMap(d, value, value.type[0], value.type[1]) + def qdumpHelper_QMap(d, value, keyType, valueType): if d.qtVersion() < 0x50000: qdumpHelper_Qt4_QMap(d, value, keyType, valueType) else: qdumpHelper_Qt5_QMap(d, value, keyType, valueType) + def qform__QMultiMap(): return [DisplayFormat.CompactMapFormat] + def qdump__QMultiMap(d, value): qdump__QMap(d, value) + def qform__QVariantMap(): return [DisplayFormat.CompactMapFormat] + def qdump__QVariantMap(d, value): qdumpHelper_QMap(d, value, d.createType('QString'), d.createType('QVariant')) + def qdump__QMetaMethod(d, value): d.putQMetaStuff(value, 'QMetaMethod') + def qdump__QMetaEnum(d, value): d.putQMetaStuff(value, 'QMetaEnum') + def qdump__QMetaProperty(d, value): d.putQMetaStuff(value, 'QMetaProperty') + def qdump__QMetaClassInfo(d, value): d.putQMetaStuff(value, 'QMetaClassInfo') + def qdump__QMetaObject(d, value): d.putEmptyValue() d.putNumChild(1) @@ -1212,35 +1258,36 @@ def qdump__QMetaObject(d, value): if False: - def qdump__QObjectPrivate__ConnectionList(d, value): - d.putNumChild(1) - if d.isExpanded(): - i = 0 - with Children(d): - first, last = value.split('pp') - currentConnection = first - connectionType = d.createType('@QObjectPrivate::Connection') - while currentConnection and currentConnection != last: - sender, receiver, slotObj, nextConnectionList, nextp, prev = \ - d.split('pppppp', currentConnection) - d.putSubItem(i, d.createValue(currentConnection, connectionType)) - currentConnection = nextp - i += 1 - d.putFields(value) - d.putItemCount(i) - else: - d.putSpecialValue('minimumitemcount', 0) + def qdump__QObjectPrivate__ConnectionList(d, value): + d.putNumChild(1) + if d.isExpanded(): + i = 0 + with Children(d): + first, last = value.split('pp') + currentConnection = first + connectionType = d.createType('@QObjectPrivate::Connection') + while currentConnection and currentConnection != last: + sender, receiver, slotObj, nextConnectionList, nextp, prev = \ + d.split('pppppp', currentConnection) + d.putSubItem(i, d.createValue(currentConnection, connectionType)) + currentConnection = nextp + i += 1 + d.putFields(value) + d.putItemCount(i) + else: + d.putSpecialValue('minimumitemcount', 0) def qdump__QProcEnvKey(d, value): d.putByteArrayValue(value) d.putPlainChildren(value) + def qdump__QPixmap(d, value): if d.qtVersion() < 0x050000: - (vtbl, painters, dataPtr) = value.split('ppp'); + (vtbl, painters, dataPtr) = value.split('ppp') else: - (vtbl, painters, reserved, dataPtr) = s = d.split('pppp', value); + (vtbl, painters, reserved, dataPtr) = s = d.split('pppp', value) if dataPtr == 0: d.putValue('(invalid)') else: @@ -1265,14 +1312,14 @@ def qdump__QPointF(d, value): def qdump__QRect(d, value): - pp = lambda l: ('+' if l >= 0 else '') + str(l) + def pp(l): return ('+' if l >= 0 else '') + str(l) (x1, y1, x2, y2) = d.split('iiii', value) d.putValue('%sx%s%s%s' % (x2 - x1 + 1, y2 - y1 + 1, pp(x1), pp(y1))) d.putPlainChildren(value) def qdump__QRectF(d, value): - pp = lambda l: ('+' if l >= 0 else '') + str(l) + def pp(l): return ('+' if l >= 0 else '') + str(l) (x, y, w, h) = value.split('dddd') d.putValue('%sx%s%s%s' % (w, h, pp(x), pp(y))) d.putPlainChildren(value) @@ -1287,7 +1334,7 @@ def qdump__QRegExp(d, value): if d.isExpanded(): with Children(d): try: - d.call('void', value, 'capturedTexts') # Warm up internal cache. + d.call('void', value, 'capturedTexts') # Warm up internal cache. except: # Might fail (LLDB, Core files, ...), still cache might be warm. pass @@ -1303,7 +1350,7 @@ def qdump__QRegion(d, value): d.putSpecialValue('empty') d.putNumChild(0) else: - if d.qtVersion() >= 0x050400: # Padding removed in ee324e4ed + if d.qtVersion() >= 0x050400: # Padding removed in ee324e4ed (ref, pad, rgn) = d.split('i@p', regionDataPtr) (numRects, innerArea, rects, extents, innerRect) = \ d.split('iiP{QRect}{QRect}', rgn) @@ -1422,11 +1469,11 @@ def qdump__QSharedDataPointer(d, value): d.putItem(d_ptr.dereference()) - def qdump__QSize(d, value): d.putValue('(%s, %s)' % value.split('ii')) d.putPlainChildren(value) + def qdump__QSizeF(d, value): d.putValue('(%s, %s)' % value.split('dd')) d.putPlainChildren(value) @@ -1434,17 +1481,18 @@ def qdump__QSizeF(d, value): def qdump__QSizePolicy__Policy(d, value): d.putEnumValue(value.integer(), { - 0 : 'QSizePolicy::Fixed', - 1 : 'QSizePolicy::GrowFlag', - 2 : 'QSizePolicy::ExpandFlag', - 3 : 'QSizePolicy::MinimumExpanding (GrowFlag|ExpandFlag)', - 4 : 'QSizePolicy::ShrinkFlag', - 5 : 'QSizePolicy::Preferred (GrowFlag|ShrinkFlag)', - 7 : 'QSizePolicy::Expanding (GrowFlag|ShrinkFlag|ExpandFlag)', - 8 : 'QSizePolicy::IgnoreFlag', - 13 : 'QSizePolicy::Ignored (ShrinkFlag|GrowFlag|IgnoreFlag)', + 0: 'QSizePolicy::Fixed', + 1: 'QSizePolicy::GrowFlag', + 2: 'QSizePolicy::ExpandFlag', + 3: 'QSizePolicy::MinimumExpanding (GrowFlag|ExpandFlag)', + 4: 'QSizePolicy::ShrinkFlag', + 5: 'QSizePolicy::Preferred (GrowFlag|ShrinkFlag)', + 7: 'QSizePolicy::Expanding (GrowFlag|ShrinkFlag|ExpandFlag)', + 8: 'QSizePolicy::IgnoreFlag', + 13: 'QSizePolicy::Ignored (ShrinkFlag|GrowFlag|IgnoreFlag)', }) + def qdump__QSizePolicy(d, value): bits = value.integer() d.putEmptyValue(-99) @@ -1460,19 +1508,23 @@ def qdump__QSizePolicy(d, value): def qform__QStack(): return [DisplayFormat.ArrayPlotFormat] + def qdump__QStack(d, value): qdump__QVector(d, value) + def qdump__QPolygonF(d, value): data, size, alloc = d.vectorDataHelper(d.extractPointer(value)) d.putItemCount(size) d.putPlotData(data, size, d.createType('QPointF')) + def qdump__QPolygon(d, value): data, size, alloc = d.vectorDataHelper(d.extractPointer(value)) d.putItemCount(size) d.putPlotData(data, size, d.createType('QPoint')) + def qdump__QGraphicsPolygonItem(d, value): (vtbl, dptr) = value.split('pp') # Assume sizeof(QGraphicsPolygonItemPrivate) == 400 @@ -1486,14 +1538,17 @@ def qdump__QGraphicsPolygonItem(d, value): d.putItemCount(size) d.putPlotData(data, size, d.createType('QPointF')) + def qedit__QString(d, value, data): d.call('void', value, 'resize', str(len(data))) (base, size, alloc) = d.stringData(value) d.setValues(base, 'short', [ord(c) for c in data]) + def qform__QString(): return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + def qdump__QString(d, value): d.putStringValue(value) (data, size, alloc) = d.stringData(value) @@ -1504,18 +1559,21 @@ def qdump__QString(d, value): if d.isExpanded(): d.putArrayData(data, size, d.createType('QChar')) + def qdump__QStaticStringData(d, value): size = value.type[0] (ref, size, alloc, pad, offset, data) = value.split('iii@p%ss' % (2 * size)) d.putValue(d.hexencode(data), 'utf16') d.putPlainChildren(value) + def qdump__QTypedArrayData(d, value): if value.type[0].name == 'unsigned short': qdump__QStringData(d, value) else: qdump__QArrayData(d, value) + def qdump__QStringData(d, value): (ref, size, alloc, pad, offset) = value.split('III@p') elided, shown = d.computeLimit(size, d.displayStringLimit) @@ -1524,10 +1582,12 @@ def qdump__QStringData(d, value): d.putNumChild(1) d.putPlainChildren(value) + def qdump__QHashedString(d, value): qdump__QString(d, value) d.putBetterType(value.type) + def qdump__QQmlRefCount(d, value): d.putItem(value['refCount']) d.putBetterType(value.type) @@ -1536,7 +1596,7 @@ def qdump__QQmlRefCount(d, value): def qdump__QStringRef(d, value): (stringptr, pos, size) = value.split('pii') if stringptr == 0: - d.putValue('(null)'); + d.putValue('(null)') d.putNumChild(0) return (data, ssize, alloc) = d.stringData(d.createValue(stringptr, 'QString')) @@ -1598,6 +1658,7 @@ def qdump__QTextDocument(d, value): def qform__QUrl(): return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + def qdump__QUrl(d, value): privAddress = d.extractPointer(value) if not privAddress: @@ -1607,18 +1668,18 @@ def qdump__QUrl(d, value): return if d.qtVersion() < 0x050000: - d.call('void', value, 'port') # Warm up internal cache. + d.call('void', value, 'port') # Warm up internal cache. d.call('void', value, 'path') st = '{QString}' ba = '{QByteArray}' (ref, dummy, - scheme, userName, password, host, path, # QString - query, # QByteArray - fragment, # QString - encodedOriginal, encodedUserName, encodedPassword, - encodedPath, encodedFragment, # QByteArray - port) \ - = d.split('i@' + st*5 + ba + st + ba*5 + 'i', privAddress) + scheme, userName, password, host, path, # QString + query, # QByteArray + fragment, # QString + encodedOriginal, encodedUserName, encodedPassword, + encodedPath, encodedFragment, # QByteArray + port) \ + = d.split('i@' + st * 5 + ba + st + ba * 5 + 'i', privAddress) else: (ref, port, scheme, userName, password, host, path, query, fragment) \ = d.split('ii' + '{QString}' * 7, privAddress) @@ -1629,7 +1690,7 @@ def qdump__QUrl(d, value): url = d.encodeString(scheme) url += '3a002f002f00' # '://' if len(userNameEnc): - url += userNameEnc + '4000' # '@' + url += userNameEnc + '4000' # '@' url += hostEnc if port >= 0: url += '3a00' + ''.join(['%02x00' % ord(c) for c in str(port)]) @@ -1666,36 +1727,43 @@ def qdumpHelper_QVariant_0(d, value): d.putBetterType('%sQVariant (invalid)' % d.qtNamespace()) d.putValue('(invalid)') + def qdumpHelper_QVariant_1(d, value): # QVariant::Bool d.putBetterType('%sQVariant (bool)' % d.qtNamespace()) d.putValue('true' if value.to('b') else 'false') + def qdumpHelper_QVariant_2(d, value): # QVariant::Int d.putBetterType('%sQVariant (int)' % d.qtNamespace()) d.putValue(value.to('i')) + def qdumpHelper_QVariant_3(d, value): # uint d.putBetterType('%sQVariant (uint)' % d.qtNamespace()) d.putValue(value.to('I')) + def qdumpHelper_QVariant_4(d, value): # qlonglong d.putBetterType('%sQVariant (qlonglong)' % d.qtNamespace()) d.putValue(value.to('q')) + def qdumpHelper_QVariant_5(d, value): # qulonglong d.putBetterType('%sQVariant (qulonglong)' % d.qtNamespace()) d.putValue(value.to('Q')) + def qdumpHelper_QVariant_6(d, value): # QVariant::Double d.putBetterType('%sQVariant (double)' % d.qtNamespace()) d.putValue(value.to('d')) + qdumpHelper_QVariants_A = [ qdumpHelper_QVariant_0, qdumpHelper_QVariant_1, @@ -1708,35 +1776,37 @@ qdumpHelper_QVariants_A = [ qdumpHelper_QVariants_B = [ - 'QChar', # 7 - 'QVariantMap', # 8 - 'QVariantList',# 9 - 'QString', # 10 - 'QStringList', # 11 - 'QByteArray', # 12 - 'QBitArray', # 13 - 'QDate', # 14 - 'QTime', # 15 - 'QDateTime', # 16 - 'QUrl', # 17 - 'QLocale', # 18 - 'QRect', # 19 - 'QRectF', # 20 - 'QSize', # 21 - 'QSizeF', # 22 - 'QLine', # 23 - 'QLineF', # 24 - 'QPoint', # 25 - 'QPointF', # 26 - 'QRegExp', # 27 - 'QVariantHash',# 28 + 'QChar', # 7 + 'QVariantMap', # 8 + 'QVariantList', # 9 + 'QString', # 10 + 'QStringList', # 11 + 'QByteArray', # 12 + 'QBitArray', # 13 + 'QDate', # 14 + 'QTime', # 15 + 'QDateTime', # 16 + 'QUrl', # 17 + 'QLocale', # 18 + 'QRect', # 19 + 'QRectF', # 20 + 'QSize', # 21 + 'QSizeF', # 22 + 'QLine', # 23 + 'QLineF', # 24 + 'QPoint', # 25 + 'QPointF', # 26 + 'QRegExp', # 27 + 'QVariantHash', # 28 ] + def qdumpHelper_QVariant_31(d, value): # QVariant::VoidStar d.putBetterType('%sQVariant (void *)' % d.qtNamespace()) d.putValue('0x%x' % d.extractPointer(value)) + def qdumpHelper_QVariant_32(d, value): # QVariant::Long d.putBetterType('%sQVariant (long)' % d.qtNamespace()) @@ -1745,16 +1815,19 @@ def qdumpHelper_QVariant_32(d, value): else: d.putValue('%s' % d.extractInt64(value)) # sic! + def qdumpHelper_QVariant_33(d, value): # QVariant::Short d.putBetterType('%sQVariant (short)' % d.qtNamespace()) d.putValue('%s' % d.extractShort(value)) + def qdumpHelper_QVariant_34(d, value): # QVariant::Char d.putBetterType('%sQVariant (char)' % d.qtNamespace()) d.putValue('%s' % d.extractByte(value)) + def qdumpHelper_QVariant_35(d, value): # QVariant::ULong d.putBetterType('%sQVariant (unsigned long)' % d.qtNamespace()) @@ -1763,21 +1836,25 @@ def qdumpHelper_QVariant_35(d, value): else: d.putValue('%s' % d.extractUInt64(value)) # sic! + def qdumpHelper_QVariant_36(d, value): # QVariant::UShort d.putBetterType('%sQVariant (unsigned short)' % d.qtNamespace()) d.putValue('%s' % d.extractUShort(value)) + def qdumpHelper_QVariant_37(d, value): # QVariant::UChar d.putBetterType('%sQVariant (unsigned char)' % d.qtNamespace()) d.putValue('%s' % d.extractByte(value)) + def qdumpHelper_QVariant_38(d, value): # QVariant::Float d.putBetterType('%sQVariant (float)' % d.qtNamespace()) d.putValue(value.to('f')) + qdumpHelper_QVariants_D = [ qdumpHelper_QVariant_31, qdumpHelper_QVariant_32, @@ -1805,20 +1882,21 @@ qdumpHelper_QVariants_E = [ qdumpHelper_QVariants_F = [ # Qt 5. In Qt 4 add one. - 'QKeySequence',# 75 - 'QPen', # 76 - 'QTextLength', # 77 - 'QTextFormat', # 78 + 'QKeySequence', # 75 + 'QPen', # 76 + 'QTextLength', # 77 + 'QTextFormat', # 78 'X', - 'QTransform', # 80 - 'QMatrix4x4', # 81 - 'QVector2D', # 82 - 'QVector3D', # 83 - 'QVector4D', # 84 - 'QQuaternion', # 85 - 'QPolygonF' # 86 + 'QTransform', # 80 + 'QMatrix4x4', # 81 + 'QVector2D', # 82 + 'QVector3D', # 83 + 'QVector4D', # 84 + 'QQuaternion', # 85 + 'QPolygonF' # 86 ] + def qdump__QVariant(d, value): (data, typeStuff) = d.split('8sI', value) variantType = typeStuff & 0x3fffffff @@ -1842,7 +1920,7 @@ def qdump__QVariant(d, value): d.putBetterType('%sQVariant (void *)' % d.qtNamespace()) d.putValue('0x%x' % value.extractPointer()) else: - if variantType == 135: # Float + if variantType == 135: # Float blob = value else: p = d.extractPointer(value) @@ -1885,7 +1963,6 @@ def qdump__QVariant(d, value): return innert - # User types. ns = d.qtNamespace() d.putEmptyValue(-99) @@ -1926,7 +2003,7 @@ def qdump__QVariant(d, value): val.laddress = value.laddress d.putSubItem('data', val) - if not innerType is None: + if innerType is not None: d.putBetterType('%sQVariant (%s)' % (ns, innerType)) return None @@ -1949,13 +2026,14 @@ def qdump__QVector(d, value): d.putItemCount(size) d.putPlotData(data, size, value.type[0]) + if False: - def qdump__QObjectConnectionList(d, value): - dd = d.extractPointer(value) - data, size, alloc = d.vectorDataHelper(dd) - d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000) - d.putItemCount(size) - d.putPlotData(data, size, d.createType('@QObjectPrivate::ConnectionList')) + def qdump__QObjectConnectionList(d, value): + dd = d.extractPointer(value) + data, size, alloc = d.vectorDataHelper(dd) + d.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000) + d.putItemCount(size) + d.putPlotData(data, size, d.createType('@QObjectPrivate::ConnectionList')) def qdump__QVarLengthArray(d, value): @@ -1968,16 +2046,19 @@ def qdump__QVarLengthArray(d, value): def qdump__QSharedPointer(d, value): qdump_QWeakPointerHelper(d, value, False) + def qdump__QWeakPointer(d, value): qdump_QWeakPointerHelper(d, value, True) + def qdump__QPointer(d, value): # actually, we'd use value['wp'] instead of value, but since we # only split() on the result and the (sub-)object address is the # same it does not matter but saves some cycles. qdump_QWeakPointerHelper(d, value, True, value.type[0]) -def qdump_QWeakPointerHelper(d, value, isWeak, innerType = None): + +def qdump_QWeakPointerHelper(d, value, isWeak, innerType=None): if isWeak: (d_ptr, val) = value.split('pp') else: @@ -1997,7 +2078,7 @@ def qdump_QWeakPointerHelper(d, value, isWeak, innerType = None): (vptr, weakref, strongref) = d.split('pii', d_ptr) d.check(strongref >= -1) d.check(strongref <= weakref) - d.check(weakref <= 10*1000*1000) + d.check(weakref <= 10 * 1000 * 1000) if innerType is None: innerType = value.type[0] @@ -2019,6 +2100,7 @@ def qdump__QXmlAttributes__Attribute(d, value): d.putSubItem('localname', localname) d.putSubItem('value', val) + def qdump__QXmlAttributes(d, value): (vptr, atts) = value.split('pP') innerType = d.createType(d.qtNamespace() + 'QXmlAttributes::Attribute', 4 * d.ptrSize()) @@ -2066,6 +2148,7 @@ def extractQmlData(d, value): #DumperBase.warn('TYOE DATA: %s' % typeName) return d.createValue(base, typeName) + def qdump__QV4__Heap__Base(d, value): mm_data = value.extractPointer() d.putValue('[%s]' % mm_data) @@ -2078,6 +2161,7 @@ def qdump__QV4__Heap__Base(d, value): with SubItem(d, 'nextFree'): d.putItem(d.createValue(mm_data & (~3), value.type)) + def qdump__QV4__Heap__String(d, value): # Note: There's also the 'Identifier' case. And the largestSubLength != 0 case. (baseClass, textOrLeft, idOrRight, subtype, stringHash, largestSub, length, mm) \ @@ -2088,6 +2172,7 @@ def qdump__QV4__Heap__String(d, value): with Children(d): d.putFields(value) + def qmlPutHeapChildren(d, value): d.putItem(extractQmlData(d, value)) @@ -2095,6 +2180,7 @@ def qmlPutHeapChildren(d, value): def qdump__QV4__Object(d, value): qmlPutHeapChildren(d, value) + def qdump__QV4__FunctionObject(d, value): #qmlPutHeapChildren(d, value) d.putEmptyValue() @@ -2105,21 +2191,27 @@ def qdump__QV4__FunctionObject(d, value): d.putCallItem('sourceLocation', '@QQmlSourceLocation', value, 'sourceLocation') + def qdump__QV4__CompilationUnit(d, value): qmlPutHeapChildren(d, value) + def qdump__QV4__CallContext(d, value): qmlPutHeapChildren(d, value) + def qdump__QV4__ScriptFunction(d, value): qmlPutHeapChildren(d, value) + def qdump__QV4__SimpleScriptFunction(d, value): qdump__QV4__FunctionObject(d, value) + def qdump__QV4__ExecutionContext(d, value): qmlPutHeapChildren(d, value) + def qdump__QQmlSourceLocation(d, value): (sourceFile, line, col) = value.split('pHH') (data, size, alloc) = d.stringData(value) @@ -2141,10 +2233,12 @@ def qdump__QQmlSourceLocation(d, value): def qdump__QV4__String(d, value): qmlPutHeapChildren(d, value) + def qdump__QV4__Identifier(d, value): d.putStringValue(value) d.putPlainChildren(value) + def qdump__QV4__PropertyHash(d, value): data = value.extractPointer() (ref, alloc, size, numBits, entries) = d.split('iiiip', data) @@ -2161,14 +2255,17 @@ def qdump__QV4__PropertyHash(d, value): d.putItemCount(n) d.putPlainChildren(value) + def qdump__QV4__InternalClass__Transition(d, value): identifier = d.createValue(value.extractPointer(), d.qtNamespace() + 'QV4::Identifier') d.putStringValue(identifier) d.putPlainChildren(value) + def qdump__QV4__InternalClassTransition(d, value): qdump__QV4__InternalClass__Transition(d, value) + def qdump__QV4__SharedInternalClassData(d, value): (ref, alloc, size, pad, data) = value.split('iIIip') val = d.createValue(data, value.type[0]) @@ -2181,6 +2278,7 @@ def qdump__QV4__SharedInternalClassData(d, value): d.putIntItem('refcount', ref) d.putValue(short.value, short.encoding) + def qdump__QV4__IdentifierTable(d, value): (engine, alloc, size, numBits, pad, entries) = value.split('piiiip') n = 0 @@ -2198,24 +2296,24 @@ def qdump__QV4__IdentifierTable(d, value): if False: # 32 bit. - QV4_Masks_SilentNaNBit = 0x00040000 - QV4_Masks_NaN_Mask = 0x7ff80000 - QV4_Masks_NotDouble_Mask = 0x7ffa0000 - QV4_Masks_Type_Mask = 0xffffc000 - QV4_Masks_Immediate_Mask = QV4_Masks_NotDouble_Mask | 0x00004000 | QV4_Masks_SilentNaNBit - QV4_Masks_IsNullOrUndefined_Mask = QV4_Masks_Immediate_Mask | 0x08000 + QV4_Masks_SilentNaNBit = 0x00040000 + QV4_Masks_NaN_Mask = 0x7ff80000 + QV4_Masks_NotDouble_Mask = 0x7ffa0000 + QV4_Masks_Type_Mask = 0xffffc000 + QV4_Masks_Immediate_Mask = QV4_Masks_NotDouble_Mask | 0x00004000 | QV4_Masks_SilentNaNBit + QV4_Masks_IsNullOrUndefined_Mask = QV4_Masks_Immediate_Mask | 0x08000 QV4_Masks_Tag_Shift = 32 - QV4_ValueType_Undefined_Type = QV4_Masks_Immediate_Mask | 0x00000 - QV4_ValueType_Null_Type = QV4_Masks_Immediate_Mask | 0x10000 - QV4_ValueType_Boolean_Type = QV4_Masks_Immediate_Mask | 0x08000 - QV4_ValueType_Integer_Type = QV4_Masks_Immediate_Mask | 0x18000 - QV4_ValueType_Managed_Type = QV4_Masks_NotDouble_Mask | 0x00000 | QV4_Masks_SilentNaNBit - QV4_ValueType_Empty_Type = QV4_Masks_NotDouble_Mask | 0x18000 | QV4_Masks_SilentNaNBit + QV4_ValueType_Undefined_Type = QV4_Masks_Immediate_Mask | 0x00000 + QV4_ValueType_Null_Type = QV4_Masks_Immediate_Mask | 0x10000 + QV4_ValueType_Boolean_Type = QV4_Masks_Immediate_Mask | 0x08000 + QV4_ValueType_Integer_Type = QV4_Masks_Immediate_Mask | 0x18000 + QV4_ValueType_Managed_Type = QV4_Masks_NotDouble_Mask | 0x00000 | QV4_Masks_SilentNaNBit + QV4_ValueType_Empty_Type = QV4_Masks_NotDouble_Mask | 0x18000 | QV4_Masks_SilentNaNBit - QV4_ConvertibleToInt = QV4_Masks_Immediate_Mask | 0x1 + QV4_ConvertibleToInt = QV4_Masks_Immediate_Mask | 0x1 - QV4_ValueTypeInternal_Null_Type_Internal = QV4_ValueType_Null_Type | QV4_ConvertibleToInt + QV4_ValueTypeInternal_Null_Type_Internal = QV4_ValueType_Null_Type | QV4_ConvertibleToInt QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ValueType_Boolean_Type | QV4_ConvertibleToInt QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ValueType_Integer_Type | QV4_ConvertibleToInt @@ -2226,19 +2324,22 @@ def QV4_getValue(d, jsval): # (Dumper, QJSValue *jsval) -> QV4::Value * return 0 return dd + def QV4_getVariant(d, jsval): # (Dumper, QJSValue *jsval) -> QVariant * dd = d.split('Q', jsval)[0] if dd & 1: return dd & ~3 return 0 -def QV4_valueForData(d, jsval): # (Dumper, QJSValue *jsval) -> QV4::Value * + +def QV4_valueForData(d, jsval): # (Dumper, QJSValue *jsval) -> QV4::Value * v = QV4_getValue(d, jsval) if v: return v d.warn('Not implemented: VARIANT') return 0 + def QV4_putObjectValue(d, objectPtr): ns = d.qtNamespace() base = d.extractPointer(objectPtr) @@ -2249,7 +2350,7 @@ def QV4_putObjectValue(d, objectPtr): with Children(d): with SubItem(d, '[raw]'): d.putValue('[0x%x]' % objectPtr) - d.putType(' '); + d.putType(' ') d.putNumChild(0) d.putIntItem('inlineMemberOffset', inlineMemberOffset) d.putIntItem('inlineMemberSize', inlineMemberSize) @@ -2260,6 +2361,7 @@ def QV4_putObjectValue(d, objectPtr): d.putSubItem('OBJ', d.createValue(objectPtr, ns + 'QV4::Object')) #d.putFields(value) + def qdump__QV4_Object(d, value): ns = d.qtNamespace() d.putEmptyValue() @@ -2271,12 +2373,14 @@ def qdump__QV4_Object(d, value): memberData, arrayData) = d.split('IIpppp', base) d.putValue('PTR: 0x%x' % objectPtr) + def qdump__QV4__Value(d, value): - if d.ptrSize() == 4: + if d.ptrSize() == 4: qdump_32__QV4__Value(d, value) else: qdump_64__QV4__Value(d, value) + def qdump_32__QV4__Value(d, value): # QV4_Masks_SilentNaNBit = 0x00040000 # QV4_Masks_NaN_Mask = 0x7ff80000 @@ -2286,16 +2390,16 @@ def qdump_32__QV4__Value(d, value): v = value.split('Q')[0] tag = v >> 32 val = v & 0xffffffff - if (tag & 0x7fff2000) == 0x7fff2000: # Int + if (tag & 0x7fff2000) == 0x7fff2000: # Int d.putValue(val) d.putBetterType('%sQV4::Value (int32)' % ns) - elif (tag & 0x7fff4000) == 0x7fff4000: # Bool + elif (tag & 0x7fff4000) == 0x7fff4000: # Bool d.putValue(val) d.putBetterType('%sQV4::Value (bool)' % ns) - elif (tag & 0x7fff0000) == 0x7fff0000: # Null + elif (tag & 0x7fff0000) == 0x7fff0000: # Null d.putValue(val) d.putBetterType('%sQV4::Value (null)' % ns) - elif (tag & 0x7ffa0000) != 0x7ffa0000: # Double + elif (tag & 0x7ffa0000) != 0x7ffa0000: # Double d.putValue(value.split('d')[0]) d.putBetterType('%sQV4::Value (double)' % ns) elif tag == 0x7ffa0000: @@ -2311,15 +2415,15 @@ def qdump_32__QV4__Value(d, value): with Children(d): with SubItem(d, '[raw]'): d.putValue('[0x%x]' % v) - d.putType(' '); + d.putType(' ') d.putNumChild(0) with SubItem(d, '[val]'): d.putValue('[0x%x]' % val) - d.putType(' '); + d.putType(' ') d.putNumChild(0) with SubItem(d, '[tag]'): d.putValue('[0x%x]' % tag) - d.putType(' '); + d.putType(' ') d.putNumChild(0) #with SubItem(d, '[vtable]'): # d.putItem(d.createValue(vtable, ns + 'QV4::VTable')) @@ -2327,56 +2431,57 @@ def qdump_32__QV4__Value(d, value): # d.putNumChild(0) d.putFields(value) + def qdump_64__QV4__Value(d, value): dti = d.qtDeclarativeTypeInfoVersion() new = dti is not None and dti >= 2 if new: - QV4_NaNEncodeMask = 0xfffc000000000000 - QV4_Masks_Immediate_Mask = 0x00020000 # bit 49 + QV4_NaNEncodeMask = 0xfffc000000000000 + QV4_Masks_Immediate_Mask = 0x00020000 # bit 49 - QV4_ValueTypeInternal_Empty_Type_Internal = QV4_Masks_Immediate_Mask | 0 - QV4_ConvertibleToInt = QV4_Masks_Immediate_Mask | 0x10000 # bit 48 - QV4_ValueTypeInternal_Null_Type_Internal = QV4_ConvertibleToInt | 0x08000 - QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ConvertibleToInt | 0x04000 - QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ConvertibleToInt | 0x02000 + QV4_ValueTypeInternal_Empty_Type_Internal = QV4_Masks_Immediate_Mask | 0 + QV4_ConvertibleToInt = QV4_Masks_Immediate_Mask | 0x10000 # bit 48 + QV4_ValueTypeInternal_Null_Type_Internal = QV4_ConvertibleToInt | 0x08000 + QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ConvertibleToInt | 0x04000 + QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ConvertibleToInt | 0x02000 - QV4_ValueType_Undefined_Type = 0 # Dummy to make generic code below pass. + QV4_ValueType_Undefined_Type = 0 # Dummy to make generic code below pass. else: - QV4_NaNEncodeMask = 0xffff800000000000 - QV4_Masks_Immediate_Mask = 0x00018000 + QV4_NaNEncodeMask = 0xffff800000000000 + QV4_Masks_Immediate_Mask = 0x00018000 - QV4_IsInt32Mask = 0x0002000000000000 - QV4_IsDoubleMask = 0xfffc000000000000 - QV4_IsNumberMask = QV4_IsInt32Mask | QV4_IsDoubleMask - QV4_IsNullOrUndefinedMask = 0x0000800000000000 - QV4_IsNullOrBooleanMask = 0x0001000000000000 + QV4_IsInt32Mask = 0x0002000000000000 + QV4_IsDoubleMask = 0xfffc000000000000 + QV4_IsNumberMask = QV4_IsInt32Mask | QV4_IsDoubleMask + QV4_IsNullOrUndefinedMask = 0x0000800000000000 + QV4_IsNullOrBooleanMask = 0x0001000000000000 - QV4_Masks_NaN_Mask = 0x7ff80000 - QV4_Masks_Type_Mask = 0xffff8000 - QV4_Masks_IsDouble_Mask = 0xfffc0000 - QV4_Masks_IsNullOrUndefined_Mask = 0x00008000 - QV4_Masks_IsNullOrBoolean_Mask = 0x00010000 + QV4_Masks_NaN_Mask = 0x7ff80000 + QV4_Masks_Type_Mask = 0xffff8000 + QV4_Masks_IsDouble_Mask = 0xfffc0000 + QV4_Masks_IsNullOrUndefined_Mask = 0x00008000 + QV4_Masks_IsNullOrBoolean_Mask = 0x00010000 - QV4_ValueType_Undefined_Type = QV4_Masks_IsNullOrUndefined_Mask - QV4_ValueType_Null_Type = QV4_Masks_IsNullOrUndefined_Mask \ - | QV4_Masks_IsNullOrBoolean_Mask - QV4_ValueType_Boolean_Type = QV4_Masks_IsNullOrBoolean_Mask - QV4_ValueType_Integer_Type = 0x20000 | QV4_Masks_IsNullOrBoolean_Mask - QV4_ValueType_Managed_Type = 0 - QV4_ValueType_Empty_Type = QV4_ValueType_Undefined_Type | 0x4000 + QV4_ValueType_Undefined_Type = QV4_Masks_IsNullOrUndefined_Mask + QV4_ValueType_Null_Type = QV4_Masks_IsNullOrUndefined_Mask \ + | QV4_Masks_IsNullOrBoolean_Mask + QV4_ValueType_Boolean_Type = QV4_Masks_IsNullOrBoolean_Mask + QV4_ValueType_Integer_Type = 0x20000 | QV4_Masks_IsNullOrBoolean_Mask + QV4_ValueType_Managed_Type = 0 + QV4_ValueType_Empty_Type = QV4_ValueType_Undefined_Type | 0x4000 - QV4_ValueTypeInternal_Null_Type_Internal = QV4_ValueType_Null_Type - QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ValueType_Boolean_Type - QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ValueType_Integer_Type + QV4_ValueTypeInternal_Null_Type_Internal = QV4_ValueType_Null_Type + QV4_ValueTypeInternal_Boolean_Type_Internal = QV4_ValueType_Boolean_Type + QV4_ValueTypeInternal_Integer_Type_Internal = QV4_ValueType_Integer_Type - QV4_PointerMask = 0xfffffffffffffffd + QV4_PointerMask = 0xfffffffffffffffd - QV4_Masks_Tag_Shift = 32 - QV4_IsDouble_Shift = 64-14 - QV4_IsNumber_Shift = 64-15 - QV4_IsConvertibleToInt_Shift = 64-16 - QV4_IsManaged_Shift = 64-17 + QV4_Masks_Tag_Shift = 32 + QV4_IsDouble_Shift = 64 - 14 + QV4_IsNumber_Shift = 64 - 15 + QV4_IsConvertibleToInt_Shift = 64 - 16 + QV4_IsManaged_Shift = 64 - 17 v = value.split('Q')[0] tag = v >> QV4_Masks_Tag_Shift @@ -2414,13 +2519,13 @@ def qdump_64__QV4__Value(d, value): else: (parentv, flags, pad, className) = d.split('pIIp', vtable) #vtable = value['m']['vtable'] - if flags & 2: # isString' + if flags & 2: # isString' d.putBetterType('%sQV4::Value (string)' % ns) qdump__QV4__Heap__String(d, d.createValue(v, ns + 'QV4::Heap::String')) #d.putStringValue(d.extractPointer(value) + 2 * d.ptrSize()) #d.putValue('ptr: 0x%x' % d.extractPointer(value)) return - elif flags & 4: # isObject + elif flags & 4: # isObject d.putBetterType('%sQV4::Value (object)' % ns) #QV4_putObjectValue(d, d.extractPointer(value) + 2 * d.ptrSize()) arrayVTable = d.symbolAddress(ns + 'QV4::ArrayObject::static_vtbl') @@ -2428,7 +2533,7 @@ def qdump_64__QV4__Value(d, value): d.putNumChild(1) d.putItem(d.createValue(d.extractPointer(value) + 2 * d.ptrSize(), ns + 'QV4::Object')) return - elif flags & 8: # isFunction + elif flags & 8: # isFunction d.putBetterType('%sQV4::Value (function)' % ns) d.putEmptyValue() else: @@ -2439,14 +2544,15 @@ def qdump_64__QV4__Value(d, value): with Children(d): with SubItem(d, '[raw]'): d.putValue('[0x%x]' % v) - d.putType(' '); + d.putType(' ') d.putNumChild(0) with SubItem(d, '[vtable]'): d.putItem(d.createValue(vtable, ns + 'QV4::VTable')) - d.putType(' '); + d.putType(' ') d.putNumChild(0) d.putFields(value) + def qdump__QV__PropertyHashData(d, value): (ref, alloc, size, numBits, entries) = value.split('IIIIp') d.putItemCount(size) @@ -2454,6 +2560,7 @@ def qdump__QV__PropertyHashData(d, value): with Children(d): d.putFields(value) + def qdump__QV__PropertyHash(d, value): qdump__QV__PropertyHashData(d, d.createValue(d.extractPointer(), value.type.name + 'Data')) @@ -2467,6 +2574,7 @@ def qdump__QV4__Scoped(d, value): # d.putSubItem('[]', d.createValue(value.extractPointer(), innerType)) # d.putFields(value) + def qdump__QV4__ScopedString(d, value): innerType = value.type[0] qdump__QV4__String(d, d.createValue(value.extractPointer(), innerType)) @@ -2478,6 +2586,7 @@ def qdump__QJSValue(d, value): else: qdump_64__QJSValue(d, value) + def qdump_32__QJSValue(d, value): ns = d.qtNamespace() dd = value.split('I')[0] @@ -2498,10 +2607,11 @@ def qdump_32__QJSValue(d, value): with Children(d): with SubItem(d, '[raw]'): d.putValue('[0x%x]' % dd) - d.putType(' '); + d.putType(' ') d.putNumChild(0) d.putFields(value) + def qdump_64__QJSValue(d, value): ns = d.qtNamespace() dd = value.split('Q')[0] @@ -2520,10 +2630,11 @@ def qdump_64__QJSValue(d, value): with Children(d): with SubItem(d, '[raw]'): d.putValue('[0x%x]' % dd) - d.putType(' '); + d.putType(' ') d.putNumChild(0) d.putFields(value) + def qdump__QQmlBinding(d, value): d.putEmptyValue() if d.isExpanded(): @@ -2566,7 +2677,6 @@ def jstagAsString(tag): return 'Unknown' - def qdump__QTJSC__JSValue(d, value): d.putEmptyValue() d.putNumChild(1) @@ -2597,6 +2707,7 @@ def qdump__QTJSC__JSValue(d, value): except: pass + def qdump__QScriptValue(d, value): # structure: # engine QScriptEnginePrivate @@ -2614,12 +2725,12 @@ def qdump__QScriptValue(d, value): d.putValue('(invalid)') d.putNumChild(0) return - if int(dd['type']) == 1: # Number + if int(dd['type']) == 1: # Number d.putValue(dd['numberValue']) d.putType('%sQScriptValue (Number)' % ns) d.putNumChild(0) return - if int(dd['type']) == 2: # String + if int(dd['type']) == 2: # String d.putStringValue(dd['stringValue']) d.putType('%sQScriptValue (String)' % ns) return @@ -2681,7 +2792,7 @@ def qdump__QScriptValue(d, value): d.putNumChild(1) if d.isExpanded(): with Children(d): - d.putSubItem('jscValue', dd['jscValue']) + d.putSubItem('jscValue', dd['jscValue']) def qdump__QQmlAccessorProperties__Properties(d, value): @@ -2698,6 +2809,7 @@ def qdump__QQmlAccessorProperties__Properties(d, value): def qdumpHelper_qle_cutBits(value, offset, length): return (value >> offset) & ((1 << length) - 1) + def qdump__QJsonPrivate__qle_bitfield(d, value): offset = value.type[0] length = value.type[1] @@ -2705,6 +2817,7 @@ def qdump__QJsonPrivate__qle_bitfield(d, value): d.putValue('%s' % qdumpHelper_qle_cutBits(val, offset, length)) d.putNumChild(0) + def qdumpHelper_qle_signedbitfield_value(d, value): offset = value.type[0] length = value.type[1] @@ -2714,10 +2827,12 @@ def qdumpHelper_qle_signedbitfield_value(d, value): val -= (1 << (length - 1)) return val + def qdump__QJsonPrivate__qle_signedbitfield(d, value): d.putValue('%s' % qdumpHelper_qle_signedbitfield_value(d, value)) d.putNumChild(0) + def qdump__QJsonPrivate__q_littleendian(d, value): d.putValue('%s' % value['val'].integer()) d.putNumChild(0) @@ -2767,7 +2882,7 @@ def qdumpHelper_QJsonValue(d, data, base, pv): return if t == 3: d.putType('QJsonValue (String)') - data = base + v; + data = base + v if latinOrIntValue: length = d.extractUShort(data) d.putValue(d.readMemory(data + 2, length), 'latin1') @@ -2831,9 +2946,9 @@ def qdumpHelper_QJsonObject(d, data, obj): table = obj + d.extractUInt(obj + 8) for i in range(n): with SubItem(d, i): - entryPtr = table + 4 * i # entryAt(i) - entryStart = obj + d.extractUInt(entryPtr) # Entry::value - keyStart = entryStart + 4 # sizeof(QJsonPrivate::Entry) == 4 + entryPtr = table + 4 * i # entryAt(i) + entryStart = obj + d.extractUInt(entryPtr) # Entry::value + keyStart = entryStart + 4 # sizeof(QJsonPrivate::Entry) == 4 val = d.extractInt(entryStart) key = d.extractInt(keyStart) isLatinKey = qdumpHelper_qle_cutBits(val, 4, 1) diff --git a/share/qtcreator/debugger/setup.cfg b/share/qtcreator/debugger/setup.cfg new file mode 100644 index 00000000000..7b75dd8860a --- /dev/null +++ b/share/qtcreator/debugger/setup.cfg @@ -0,0 +1,15 @@ +[pycodestyle] +max-line-length = 100 +ignore = + # E222 - multiple spaces after operator: Used for alignments + E222, + # E241 - multiple spaces after ',': Used for alignments + E241, + # E265 - block comment should start with '# ': We have a bunch of #warn(foo) lines + # a space after # would leave an incorrect indentation after uncommenting + E265, + # E402 - module level import not at top of file: Sometimes we need to adjust the sys.path before + # we can import + E402, + # E722 - do not use bare except, specify exception instead: TODO + E722 diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index e9f99fc3f60..069f54190bf 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -26,9 +26,11 @@ from utils import DisplayFormat from dumper import Children, SubItem + def qform__std__array(): return [DisplayFormat.ArrayPlotFormat] + def qdump__std__array(d, value): size = value.type[1] d.putItemCount(size) @@ -39,6 +41,7 @@ def qdump__std__array(d, value): def qform__std____1__array(): return [DisplayFormat.ArrayPlotFormat] + def qdump__std____1__array(d, value): qdump__std__array(d, value) @@ -66,6 +69,7 @@ def qdump__std__complex(d, value): d.putSubItem("real", real) d.putSubItem("imag", imag) + def qdump__std____1__complex(d, value): qdump__std__complex(d, value) @@ -85,7 +89,7 @@ def qdump__std__deque(d, value): bufsize = 512 // innerSize (mapptr, mapsize, startCur, startFirst, startLast, startNode, - finishCur, finishFirst, finishLast, finishNode) = value.split("pppppppppp") + finishCur, finishFirst, finishLast, finishNode) = value.split("pppppppppp") size = bufsize * ((finishNode - startNode) // d.ptrSize() - 1) size += (finishCur - finishFirst) // innerSize @@ -108,6 +112,7 @@ def qdump__std__deque(d, value): pcur = pfirst pnode = newnode + def qdump__std____1__deque(d, value): mptr, mfirst, mbegin, mend, start, size = value.split("pppptt") d.check(0 <= size and size <= 1000 * 1000 * 1000) @@ -123,6 +128,7 @@ def qdump__std____1__deque(d, value): base = d.extractPointer(mfirst + k * ptrSize) d.putSubItem(i, d.createValue(base + j * innerSize, innerType)) + def qdump__std__deque__QNX(d, value): innerType = value.type[0] innerSize = innerType.size() @@ -157,7 +163,8 @@ def qdump__std__deque__QNX(d, value): if mapsize <= block: block -= mapsize d.putSubItem(i, map[block][offset]) - myoff += 1; + myoff += 1 + def qdump__std__deque__MSVC(d, value): innerType = value.type[0] @@ -187,6 +194,7 @@ def qdump__std__deque__MSVC(d, value): d.putSubItem(i, d.createValue(address, innerType)) myoff += 1 + def qdump__std____debug__deque(d, value): qdump__std__deque(d, value) @@ -218,6 +226,7 @@ def qdump__std__list(d, value): d.putSubItem(i, d.createValue(p + 2 * d.ptrSize(), innerType)) p = d.extractPointer(p) + def qdump__std__list__QNX(d, value): (proxy, head, size) = value.split("ppp") d.putItemCount(size, 1000) @@ -230,12 +239,15 @@ def qdump__std__list__QNX(d, value): d.putSubItem(i, d.createValue(p + 2 * d.ptrSize(), innerType)) p = d.extractPointer(p) + def qdump__std____debug__list(d, value): qdump__std__list(d, value) + def qdump__std____cxx11__list(d, value): qdump__std__list(d, value) + def qdump__std____1__list(d, value): if value.type.size() == 3 * d.ptrSize(): # C++11 only. @@ -260,9 +272,11 @@ def qdump__std____1__list(d, value): (prev, p, val) = d.split(typeCode, p) d.putSubItem(i, val) + def qform__std__map(): return [DisplayFormat.CompactMapFormat] + def qdump__std__map(d, value): if d.isQnxTarget() or d.isMsvcTarget(): qdump_std__map__helper(d, value) @@ -270,7 +284,7 @@ def qdump__std__map(d, value): # stuff is actually (color, pad) with 'I@', but we can save cycles/ (compare, stuff, parent, left, right, size) = value.split('pppppp') - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) d.putItemCount(size) if d.isExpanded(): @@ -299,16 +313,19 @@ def qdump__std__map(d, value): break node = node["_M_left"] + def qdump_std__map__helper(d, value): (proxy, head, size) = value.split("ppp") - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) d.putItemCount(size) if d.isExpanded(): keyType = value.type[0] valueType = value.type[1] pairType = value.type[3][0] + def helper(node): - (left, parent, right, color, isnil, pad, pair) = d.split("pppcc@{%s}" % (pairType.name), node) + (left, parent, right, color, isnil, pad, pair) = d.split( + "pppcc@{%s}" % (pairType.name), node) if left != head: for res in helper(left): yield res @@ -322,24 +339,31 @@ def qdump_std__map__helper(d, value): for (pair, i) in zip(helper(root), d.childRange()): d.putPairItem(i, pair) + def qdump__std____debug__map(d, value): qdump__std__map(d, value) + def qdump__std____debug__set(d, value): qdump__std__set(d, value) + def qdump__std__multiset(d, value): qdump__std__set(d, value) + def qdump__std____cxx1998__map(d, value): qdump__std__map(d, value) + def qform__std__multimap(): return [DisplayFormat.CompactMapFormat] + def qdump__std__multimap(d, value): return qdump__std__map(d, value) + def qdumpHelper__std__tree__iterator(d, value, isSet=False): treeTypeName = None if value.type.name.endswith("::iterator"): @@ -375,30 +399,39 @@ def qdumpHelper__std__tree__iterator(d, value, isSet=False): d.putSubItem("right", d.createValue(right, nodeType)) d.putSubItem("parent", d.createValue(parent, nodeType)) + def qdump__std___Rb_tree_iterator(d, value): qdumpHelper__std__tree__iterator(d, value) + def qdump__std___Rb_tree_const_iterator(d, value): qdumpHelper__std__tree__iterator(d, value) + def qdump__std__map__iterator(d, value): qdumpHelper__std__tree__iterator(d, value) + def qdump____gnu_debug___Safe_iterator(d, value): d.putItem(value["_M_current"]) + def qdump__std__map__const_iterator(d, value): qdumpHelper__std__tree__iterator(d, value) + def qdump__std__set__iterator(d, value): qdumpHelper__std__tree__iterator(d, value, True) + def qdump__std__set__const_iterator(d, value): qdumpHelper__std__tree__iterator(d, value, True) + def qdump__std____cxx1998__set(d, value): qdump__std__set(d, value) + def qdumpHelper__std__tree__iterator_MSVC(d, value): d.putNumChild(1) d.putEmptyValue() @@ -416,9 +449,11 @@ def qdumpHelper__std__tree__iterator_MSVC(d, value): else: d.putSubItem("value", child) + def qdump__std___Tree_const_iterator(d, value): qdumpHelper__std__tree__iterator_MSVC(d, value) + def qdump__std___Tree_iterator(d, value): qdumpHelper__std__tree__iterator_MSVC(d, value) @@ -430,7 +465,7 @@ def qdump__std__set(d, value): impl = value["_M_t"]["_M_impl"] size = impl["_M_node_count"].integer() - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) d.putItemCount(size) if d.isExpanded(): valueType = value.type[0] @@ -453,14 +488,17 @@ def qdump__std__set(d, value): while node["_M_left"].pointer() != 0: node = node["_M_left"] + def qdump__std__set__QNX(d, value): (proxy, head, size) = value.split("ppp") - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) d.putItemCount(size) if d.isExpanded(): - childType=value.type[0] + childType = value.type[0] + def helper(node): - (left, parent, right, color, isnil, pad, value) = d.split("pppcc@{%s}" % childType.name, node) + (left, parent, right, color, isnil, pad, value) = d.split( + "pppcc@{%s}" % childType.name, node) if left != head: for res in helper(left): yield res @@ -474,6 +512,7 @@ def qdump__std__set__QNX(d, value): for (item, i) in zip(helper(root), d.childRange()): d.putSubItem(i, item) + def std1TreeMin(d, node): #_NodePtr __tree_min(_NodePtr __x): # while (__x->__left_ != nullptr) @@ -485,6 +524,7 @@ def std1TreeMin(d, node): node = left return node + def std1TreeIsLeftChild(d, node): # bool __tree_is_left_child(_NodePtr __x): # return __x == __x->__parent_->__left_; @@ -508,10 +548,11 @@ def std1TreeNext(d, node): node = node['__parent_'] return node['__parent_'] + def qdump__std____1__set(d, value): (proxy, head, size) = value.split("ppp") - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) d.putItemCount(size) if d.isExpanded(): @@ -534,21 +575,24 @@ def qdump__std____1__set(d, value): for (i, data) in zip(d.childRange(), in_order_traversal(head)): d.putSubItem(i, data) + def qdump__std____1__multiset(d, value): qdump__std____1__set(d, value) + def qform__std____1__map(): return [DisplayFormat.CompactMapFormat] + def qdump__std____1__map(d, value): try: (proxy, head, size) = value.split("ppp") - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) # Sometimes there is extra data at the front. Don't know why at the moment. except RuntimeError: (junk, proxy, head, size) = value.split("pppp") - d.check(0 <= size and size <= 100*1000*1000) + d.check(0 <= size and size <= 100 * 1000 * 1000) d.putItemCount(size) @@ -574,12 +618,15 @@ def qdump__std____1__map(d, value): for (i, pair) in zip(d.childRange(), in_order_traversal(head)): d.putPairItem(i, pair, 'key', 'value') + def qform__std____1__multimap(): return [DisplayFormat.CompactMapFormat] + def qdump__std____1__multimap(d, value): qdump__std____1__map(d, value) + def qdump__std____1__map__iterator(d, value): d.putEmptyValue() if d.isExpanded(): @@ -588,9 +635,11 @@ def qdump__std____1__map__iterator(d, value): d.putSubItem('first', node['first']) d.putSubItem('second', node['second']) + def qdump__std____1__map__const_iterator(d, value): qdump__std____1__map__iterator(d, value) + def qdump__std____1__set__iterator(d, value): d.putEmptyValue() d.putNumChild(1) @@ -606,27 +655,34 @@ def qdump__std____1__set__iterator(d, value): node = node.cast(keyType) d.putSubItem('value', node) + def qdump__std____1__set_const_iterator(d, value): qdump__std____1__set__iterator(d, value) + def qdump__std__stack(d, value): d.putItem(value["c"]) d.putBetterType(value.type) + def qdump__std____debug__stack(d, value): qdump__std__stack(d, value) + def qdump__std____1__stack(d, value): d.putItem(value["c"]) d.putBetterType(value.type) + def qform__std__string(): return [DisplayFormat.Latin1StringFormat, DisplayFormat.SeparateLatin1StringFormat, - DisplayFormat.Utf8StringFormat, DisplayFormat.SeparateUtf8StringFormat ] + DisplayFormat.Utf8StringFormat, DisplayFormat.SeparateUtf8StringFormat] + def qdump__std__string(d, value): qdumpHelper_std__string(d, value, d.createType("char"), d.currentItemFormat()) + def qdumpHelper_std__string(d, value, charType, format): if d.isQnxTarget(): qdumpHelper__std__string__QNX(d, value, charType, format) @@ -650,34 +706,37 @@ def qdumpHelper_std__string(d, value, charType, format): # struct { size_type _M_length, size_type _M_capacity, int _M_refcount; } (size, alloc, refcount) = d.split("ppp", data - 3 * d.ptrSize()) refcount = refcount & 0xffffffff - d.check(refcount >= -1) # Can be -1 according to docs. - d.check(0 <= size and size <= alloc and alloc <= 100*1000*1000) + d.check(refcount >= -1) # Can be -1 according to docs. + d.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) d.putCharArrayHelper(data, size, charType, format) + def qdumpHelper__std__string__QNX(d, value, charType, format): size = value['_Mysize'] alloc = value['_Myres'] _BUF_SIZE = int(16 / charType.size()) - if _BUF_SIZE <= alloc: #(_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf); + if _BUF_SIZE <= alloc: # (_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf); data = value['_Bx']['_Ptr'] else: data = value['_Bx']['_Buf'] sizePtr = data.cast(d.charType().pointer()) refcount = int(sizePtr[-1]) - d.check(refcount >= -1) # Can be -1 accoring to docs. - d.check(0 <= size and size <= alloc and alloc <= 100*1000*1000) + d.check(refcount >= -1) # Can be -1 accoring to docs. + d.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) d.putCharArrayHelper(sizePtr, size, charType, format) + def qdumpHelper__std__string__MSVC(d, value, charType, format): - (proxy, buffer, size, alloc) = value.split("p16spp"); - _BUF_SIZE = int(16 / charType.size()); - d.check(0 <= size and size <= alloc and alloc <= 100*1000*1000) + (proxy, buffer, size, alloc) = value.split("p16spp") + _BUF_SIZE = int(16 / charType.size()) + d.check(0 <= size and size <= alloc and alloc <= 100 * 1000 * 1000) if _BUF_SIZE <= alloc: - (proxy, data) = value.split("pp"); + (proxy, data) = value.split("pp") else: data = value.address() + d.ptrSize() d.putCharArrayHelper(data, size, charType, format) + def qdump__std____1__string(d, value): firstByte = value.split('b')[0] if int(firstByte & 1) == 0: @@ -707,9 +766,11 @@ def qdump__std____1__wstring(d, value): def qdump__std____weak_ptr(d, value): return qdump__std__shared_ptr(d, value) + def qdump__std__weak_ptr(d, value): return qdump__std__shared_ptr(d, value) + def qdump__std____1__weak_ptr(d, value): return qdump__std____1__shared_ptr(d, value) @@ -727,6 +788,7 @@ def qdump__std__shared_ptr(d, value): d.putItem(i.dereference()) d.putBetterType(value.type) + def qdump__std____1__shared_ptr(d, value): i = value["__ptr_"] if i.pointer() == 0: @@ -736,6 +798,7 @@ def qdump__std____1__shared_ptr(d, value): d.putItem(i.dereference()) d.putBetterType(value.type) + def qdump__std__unique_ptr(d, value): p = d.extractPointer(value) if p == 0: @@ -745,6 +808,7 @@ def qdump__std__unique_ptr(d, value): d.putItem(d.createValue(p, value.type[0])) d.putBetterType(value.type) + def qdump__std____1__unique_ptr(d, value): qdump__std__unique_ptr(d, value) @@ -760,12 +824,15 @@ def qdump__std__pair(d, value): d.putField('keyencoded', key.encoding) d.putValue(value.value, value.encoding) + def qform__std__unordered_map(): return [DisplayFormat.CompactMapFormat] + def qform__std____debug__unordered_map(): return [DisplayFormat.CompactMapFormat] + def qdump__std__unordered_map(d, value): if d.isQnxTarget() or d.isMsvcTarget(): qdump__std__list__QNX(d, value["_List"]) @@ -806,6 +873,7 @@ def qdump__std__unordered_map(d, value): p, pad, key, pad, val = d.split(typeCode, p) d.putPairItem(i, (key, val)) + def qdump__std____debug__unordered_map(d, value): qdump__std__unordered_map(d, value) @@ -813,12 +881,15 @@ def qdump__std____debug__unordered_map(d, value): def qform__std__unordered_multimap(): return qform__std__unordered_map() + def qform__std____debug__unordered_multimap(): return qform__std____debug__unordered_map() + def qdump__std__unordered_multimap(d, value): qdump__std__unordered_map(d, value) + def qdump__std____debug__unordered_multimap(d, value): qdump__std__unordered_multimap(d, value) @@ -861,9 +932,11 @@ def qdump__std__unordered_set(d, value): d.putSubItem(i, d.createValue(p + ptrSize - offset, valueType)) p = d.extractPointer(p + offset) + def qform__std____1__unordered_map(): return [DisplayFormat.CompactMapFormat] + def qdump__std____1__unordered_map(d, value): (size, _) = value["__table_"]["__p2_"].split("pp") d.putItemCount(size) @@ -909,9 +982,11 @@ def qdump__std____1__unordered_set(d, value): def qdump__std____debug__unordered_set(d, value): qdump__std__unordered_set(d, value) + def qdump__std__unordered_multiset(d, value): qdump__std__unordered_set(d, value) + def qdump__std____debug__unordered_multiset(d, value): qdump__std__unordered_multiset(d, value) @@ -919,6 +994,7 @@ def qdump__std____debug__unordered_multiset(d, value): def qform__std__valarray(): return [DisplayFormat.ArrayPlotFormat] + def qdump__std__valarray(d, value): if d.isMsvcTarget(): (data, size) = value.split('pp') @@ -931,6 +1007,7 @@ def qdump__std__valarray(d, value): def qform__std____1__valarray(): return [DisplayFormat.ArrayPlotFormat] + def qdump__std____1__valarray(d, value): innerType = value.type[0] (begin, end) = value.split('pp') @@ -942,6 +1019,7 @@ def qdump__std____1__valarray(d, value): def qform__std__vector(): return [DisplayFormat.ArrayPlotFormat] + def qedit__std__vector(d, value, data): import gdb values = data.split(',') @@ -954,12 +1032,14 @@ def qedit__std__vector(d, value, data): cmd = "set (%s[%d])*$d={%s}" % (innerType, n, data) gdb.execute(cmd) + def qdump__std__vector(d, value): if d.isQnxTarget() or d.isMsvcTarget(): qdumpHelper__std__vector__QNX(d, value) else: qdumpHelper__std__vector(d, value, False) + def qdumpHelper__std__vector(d, value, isLibCpp): innerType = value.type[0] isBool = innerType.name == 'bool' @@ -975,7 +1055,7 @@ def qdumpHelper__std__vector(d, value, isLibCpp): finish = value["_M_finish"]["_M_p"].pointer() foffset = value["_M_finish"]["_M_offset"].integer() alloc = value["_M_end_of_storage"].pointer() - size = (finish - start) * 8 + foffset - soffset # 8 is CHAR_BIT. + size = (finish - start) * 8 + foffset - soffset # 8 is CHAR_BIT. else: if isLibCpp: start = value["__begin_"].pointer() @@ -1007,6 +1087,7 @@ def qdumpHelper__std__vector(d, value, isLibCpp): else: d.putPlotData(start, size, innerType) + def qdumpHelper__std__vector__QNX(d, value): innerType = value.type[0] isBool = innerType.name == 'bool' @@ -1036,15 +1117,19 @@ def qdumpHelper__std__vector__QNX(d, value): else: d.putPlotData(start, size, innerType) + def qform__std____1__vector(): return [DisplayFormat.ArrayPlotFormat] + def qdump__std____1__vector(d, value): qdumpHelper__std__vector(d, value, True) + def qform__std____debug__vector(): return [DisplayFormat.ArrayPlotFormat] + def qdump__std____debug__vector(d, value): qdump__std__vector(d, value) @@ -1067,37 +1152,48 @@ def qdump__std__initializer_list(d, value): if d.isExpanded(): d.putPlotData(start, size, innerType) + def qedit__std__string(d, value, data): d.call('void', value, 'assign', '"%s"' % data.replace('"', '\\"')) + def qedit__string(d, expr, value): qedit__std__string(d, expr, value) + def qedit__std____cxx11__string(d, expr, value): qedit__std__string(d, expr, value) + def qedit__std__wstring(d, value, data): d.call('void', value, 'assign', 'L"%s"' % data.replace('"', '\\"')) + def qedit__wstring(d, expr, value): qedit__std__wstring(d, expr, value) + def qedit__std____cxx11__wstring(d, expr, value): qedit__std__wstring(d, expr, value) + def qdump__string(d, value): qdump__std__string(d, value) + def qform__std__wstring(): return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + def qdump__std__wstring(d, value): qdumpHelper_std__string(d, value, d.createType('wchar_t'), d.currentItemFormat()) + def qdump__std__basic_string(d, value): innerType = value.type[0] qdumpHelper_std__string(d, value, innerType, d.currentItemFormat()) + def qdump__std____cxx11__basic_string(d, value): innerType = value.type[0] try: @@ -1107,24 +1203,30 @@ def qdump__std____cxx11__basic_string(d, value): d.putEmptyValue() d.putPlainChildren(value) return - d.check(0 <= size) #and size <= alloc and alloc <= 100*1000*1000) + d.check(0 <= size) # and size <= alloc and alloc <= 100*1000*1000) d.putCharArrayHelper(data, size, innerType, d.currentItemFormat()) + def qform__std____cxx11__string(d, value): qform__std__string(d, value) + def qdump__std____cxx11__string(d, value): (data, size) = value.split("pI") - d.check(0 <= size) #and size <= alloc and alloc <= 100*1000*1000) + d.check(0 <= size) # and size <= alloc and alloc <= 100*1000*1000) d.putCharArrayHelper(data, size, d.charType(), d.currentItemFormat()) # Needed only to trigger the form report above. + + def qform__std____cxx11__string(): return qform__std__string() + def qform__std____cxx11__wstring(): return qform__std__wstring() + def qdump__std____1__basic_string(d, value): innerType = value.type[0].name if innerType == "char": @@ -1134,12 +1236,15 @@ def qdump__std____1__basic_string(d, value): else: d.warn("UNKNOWN INNER TYPE %s" % innerType) + def qdump__wstring(d, value): qdump__std__wstring(d, value) + def qdump__std____1__once_flag(d, value): qdump__std__once_flag(d, value) + def qdump__std__once_flag(d, value): d.putValue(value.split("i")[0]) d.putBetterType(value.type) @@ -1174,14 +1279,17 @@ def qdump__uint8_t(d, value): d.putNumChild(0) d.putValue(value.integer()) + def qdump__int8_t(d, value): d.putNumChild(0) d.putValue(value.integer()) + def qdump__std__byte(d, value): d.putNumChild(0) d.putValue(value.integer()) + def qdump__std__optional(d, value): innerType = value.type[0] (payload, pad, initialized) = d.split('{%s}@b' % innerType.name, value) @@ -1192,5 +1300,6 @@ def qdump__std__optional(d, value): d.putSpecialValue("uninitialized") d.putNumChild(0) + def qdump__std__experimental__optional(d, value): qdump__std__optional(d, value) diff --git a/share/qtcreator/debugger/utils.py b/share/qtcreator/debugger/utils.py index f67b9311199..72dc0fbcb80 100644 --- a/share/qtcreator/debugger/utils.py +++ b/share/qtcreator/debugger/utils.py @@ -26,7 +26,7 @@ # Debugger start modes. Keep in sync with DebuggerStartMode in debuggerconstants.h -class DebuggerStartMode: +class DebuggerStartMode(): ( NoStartMode, StartInternal, @@ -41,7 +41,7 @@ class DebuggerStartMode: # Known special formats. Keep in sync with DisplayFormat in debuggerprotocol.h -class DisplayFormat: +class DisplayFormat(): ( AutomaticFormat, RawFormat, @@ -67,7 +67,7 @@ class DisplayFormat: # Breakpoints. Keep synchronized with BreakpointType in breakpoint.h -class BreakpointType: +class BreakpointType(): ( UnknownType, BreakpointByFileAndLine, @@ -87,7 +87,7 @@ class BreakpointType: # Internal codes for types keep in sync with cdbextensions pytype.cpp -class TypeCode: +class TypeCode(): ( TypeCodeTypedef, TypeCodeStruct, From d119258c9d9a732492b0bfb38faa1f0c21675b0f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 27 Feb 2020 17:05:51 +0100 Subject: [PATCH 12/96] Doc: Describe new help options - Only latest docs are registered by default - Users can change the settings for displaying help in the detached help window Change-Id: Id7efb98e11eb8a27b7d01422e65ac63b860c868e Reviewed-by: Eike Ziller --- .../images/qtcreator-help-options.png | Bin 14951 -> 13552 bytes doc/qtcreator/src/howto/creator-help.qdoc | 9 +++++++++ 2 files changed, 9 insertions(+) diff --git a/doc/qtcreator/images/qtcreator-help-options.png b/doc/qtcreator/images/qtcreator-help-options.png index 63c34700b51b3098e5350d811793bb1034f05d7d..c08bc176409bffc16605bef72b805f6f596f89bb 100644 GIT binary patch literal 13552 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 YZh6#q?6TZ$1_lNOPgg&ebxsLQ0BGqUvj6}9 literal 14951 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

*K38 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 \uicontrol Options > + \uicontrol Kits > \uicontrol {Qt Versions} > + \uicontrol {Register documentation}. + To find information in the documentation, select: \list @@ -210,6 +216,9 @@ in the \uicontrol {On context help} field. To detach the help window, select \uicontrol {Always Show in External Window}. + To change this setting in a help view, select the \inlineimage linkicon.png + toolbar button. + \section1 Selecting the Start Page You can select the page to display when you open the \uicontrol Help mode in the From a8c9d394fd3cf76ef728390e7463c5241de680c5 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 28 Feb 2020 10:24:14 +0100 Subject: [PATCH 13/96] Doc: Replace "Qt Bug Tracker" with "Qt Project Bug Tracker" Add links where they were missing. Change-Id: I218c1160226ec5223e6bd055d73e82092f254792 Reviewed-by: Eike Ziller --- doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc | 8 ++++---- doc/qtcreator/src/editors/creator-locator.qdoc | 2 +- .../src/editors/creator-only/creator-language-server.qdoc | 5 +++-- doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc | 2 +- .../src/overview/creator-only/creator-issues.qdoc | 2 +- doc/qtcreator/src/qtcreator.qdoc | 5 +++-- doc/qtdesignstudio/src/qtdesignstudio.qdoc | 5 +++-- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc index 7c458a7d4c5..b9d636fed8f 100644 --- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc @@ -265,10 +265,10 @@ \section1 Inspecting the Code Model - When you report a bug that is related to the C++ code model, the \QC - developers might ask you to write information about the internal state of - the code model into a log file and to deliver the file to them for - inspection. + When you \l{https://bugreports.qt.io/}{report a bug} that is related to the + C++ code model, the \QC developers might ask you to write information about + the internal state of the code model into a log file and to deliver the fil + to them for inspection. To view information about the C++ code model in the \uicontrol {C++ Code Model Inspector} dialog and write it to a log file, diff --git a/doc/qtcreator/src/editors/creator-locator.qdoc b/doc/qtcreator/src/editors/creator-locator.qdoc index 2894be1744a..951e61f4905 100644 --- a/doc/qtcreator/src/editors/creator-locator.qdoc +++ b/doc/qtcreator/src/editors/creator-locator.qdoc @@ -149,7 +149,7 @@ \li Triggering menu items from the main menu (\c {t}) \li Searching for issues from the \l{https://bugreports.qt.io/} - {Qt Bug Tracker} (\c bug). + {Qt Project Bug Tracker} (\c bug). \if defined(qtcreator) \li Running external tools (\c x) diff --git a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc index b354f762b43..df6335e9c01 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc @@ -123,7 +123,8 @@ The language service client has been mostly tested with Python. If problems arise when you try it or some other language, please select - \uicontrol Help > \uicontrol {Report Bug} to report them in the Qt Bug - Tracker. The reports should include \QC console output with the environment + \uicontrol Help > \uicontrol {Report Bug} to report them in the + \l{https://bugreports.qt.io/}{Qt Project Bug Tracker}. The reports + should include \QC console output with the environment variable \c {QT_LOGGING_RULES=qtc.languageclient.*=true} set. */ diff --git a/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc b/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc index 5690fe6201e..6928e6ed939 100644 --- a/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc +++ b/doc/qtcreator/src/howto/creator-only/qtcreator-faq.qdoc @@ -73,7 +73,7 @@ \b {Has a reported issue been addressed?} You can look up any issue in the - \l{https://bugreports.qt.io/}{Qt bug tracker}. + \l{https://bugreports.qt.io/}{Qt Project Bug Tracker}. \include widgets/creator-faq-qtdesigner.qdocinc qt designer faq diff --git a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc index fd1171ba36f..453718b219d 100644 --- a/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc +++ b/doc/qtcreator/src/overview/creator-only/creator-issues.qdoc @@ -43,7 +43,7 @@ For a list of fixed issues and added features, see the changelog file in the \c{qtcreator\dist} folder or the \l{https://bugreports.qt.io} - {Qt Bug Tracker}. + {Qt Project Bug Tracker}. \section1 General Issues diff --git a/doc/qtcreator/src/qtcreator.qdoc b/doc/qtcreator/src/qtcreator.qdoc index 58db763d760..8a17cf193b5 100644 --- a/doc/qtcreator/src/qtcreator.qdoc +++ b/doc/qtcreator/src/qtcreator.qdoc @@ -130,8 +130,9 @@ \row \li {4,1} \l{All Topics} \row - \li {4,1} \note To report bugs and suggestions to the Qt Bug - Tracker, select \uicontrol {Help > Report Bug}. + \li {4,1} \note To report bugs and suggestions to the + \l{https://bugreports.qt.io/}{Qt Project Bug Tracker}, + select \uicontrol {Help > Report Bug}. To copy and paste detailed information about your system to the bug report, select \uicontrol Help > \uicontrol {System Information}. diff --git a/doc/qtdesignstudio/src/qtdesignstudio.qdoc b/doc/qtdesignstudio/src/qtdesignstudio.qdoc index f69cd066c69..6195330faeb 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio.qdoc @@ -107,8 +107,9 @@ \row \li {4,1} \l{All Topics} \row - \li {4,1} \note To report bugs and suggestions to the Qt Bug - Tracker, select \uicontrol {Help > Report Bug}. + \li {4,1} \note To report bugs and suggestions to the + \l{https://bugreports.qt.io/}{Qt Project Bug Tracker}, + select \uicontrol {Help > Report Bug}. To copy and paste detailed information about your system to the bug report, select \uicontrol Help > \uicontrol {System Information}. From a01035fefb6a9f877ac86c332c102e397bf93ba3 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 28 Feb 2020 10:03:11 +0200 Subject: [PATCH 14/96] VcsBaseEditor: Highlight default actions on context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Idc493658dbc829394bd2898a59ba5686036bc3fe Reviewed-by: André Hartmann --- src/plugins/vcsbase/vcsbaseeditor.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 5338580354c..5dc03df32eb 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -255,7 +255,7 @@ private slots: void slotCopyRevision(); private: - QAction *createDescribeAction(const QString &change) const; + void addDescribeAction(QMenu *menu, const QString &change) const; QAction *createAnnotateAction(const QString &change, bool previous) const; QAction *createCopyRevisionAction(const QString &change) const; @@ -299,7 +299,7 @@ void ChangeTextCursorHandler::fillContextMenu(QMenu *menu, EditorContentType typ menu->addSeparator(); menu->addAction(createCopyRevisionAction(m_currentChange)); if (currentValid) - menu->addAction(createDescribeAction(m_currentChange)); + addDescribeAction(menu, m_currentChange); menu->addSeparator(); if (currentValid) menu->addAction(createAnnotateAction(widget->decorateVersion(m_currentChange), false)); @@ -313,7 +313,7 @@ void ChangeTextCursorHandler::fillContextMenu(QMenu *menu, EditorContentType typ default: // Describe current / Annotate file of current menu->addSeparator(); menu->addAction(createCopyRevisionAction(m_currentChange)); - menu->addAction(createDescribeAction(m_currentChange)); + addDescribeAction(menu, m_currentChange); if (widget->isFileLogAnnotateEnabled()) menu->addAction(createAnnotateAction(m_currentChange, false)); break; @@ -336,11 +336,12 @@ void ChangeTextCursorHandler::slotCopyRevision() QApplication::clipboard()->setText(m_currentChange); } -QAction *ChangeTextCursorHandler::createDescribeAction(const QString &change) const +void ChangeTextCursorHandler::addDescribeAction(QMenu *menu, const QString &change) const { auto a = new QAction(VcsBaseEditorWidget::tr("&Describe Change %1").arg(change), nullptr); connect(a, &QAction::triggered, this, &ChangeTextCursorHandler::slotDescribe); - return a; + menu->addAction(a); + menu->setDefaultAction(a); } QAction *ChangeTextCursorHandler::createAnnotateAction(const QString &change, bool previous) const From ab3e2ac0fcb33d6b145cff08463437100171330a Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Fri, 28 Feb 2020 11:42:07 +0200 Subject: [PATCH 15/96] VcsBaseEditor: Fix tr context for Copy action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This amends commit 7677e3e197368bd206dc565368cb3f33d951d092. Change-Id: Ib07dc2a8110a8e09f43c035989d9ffa84e0427d3 Reviewed-by: André Hartmann --- src/plugins/vcsbase/vcsbaseeditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index 5dc03df32eb..0f334b7f137 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -359,7 +359,7 @@ QAction *ChangeTextCursorHandler::createAnnotateAction(const QString &change, bo QAction *ChangeTextCursorHandler::createCopyRevisionAction(const QString &change) const { - auto a = new QAction(tr("Copy \"%1\"").arg(change), nullptr); + auto a = new QAction(VcsBaseEditorWidget::tr("Copy \"%1\"").arg(change), nullptr); a->setData(change); connect(a, &QAction::triggered, this, &ChangeTextCursorHandler::slotCopyRevision); return a; From ba87fb20831dc00ae18484b0994fa553cfdc2194 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 25 Feb 2020 21:13:39 +0200 Subject: [PATCH 16/96] Git: Add actions for changes in output window context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5aa46f87b82670286ac225d71a3a045133976e86 Reviewed-by: Eike Ziller Reviewed-by: André Hartmann --- src/plugins/coreplugin/iversioncontrol.cpp | 4 ++++ src/plugins/coreplugin/iversioncontrol.h | 6 ++++++ src/plugins/git/gitclient.cpp | 5 ++++- src/plugins/git/giteditor.cpp | 1 - src/plugins/git/gitplugin.cpp | 13 +++++++++++++ src/plugins/vcsbase/vcsoutputformatter.cpp | 18 ++++++++++++++++++ src/plugins/vcsbase/vcsoutputformatter.h | 3 +++ src/plugins/vcsbase/vcsoutputwindow.cpp | 18 ++++++++++++++---- 8 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/plugins/coreplugin/iversioncontrol.cpp b/src/plugins/coreplugin/iversioncontrol.cpp index 34c9adb1ae6..fcc861b5ee4 100644 --- a/src/plugins/coreplugin/iversioncontrol.cpp +++ b/src/plugins/coreplugin/iversioncontrol.cpp @@ -194,6 +194,10 @@ QString IVersionControl::TopicCache::topic(const QString &topLevel) return data.topic = refreshTopic(topLevel); } +void IVersionControl::fillLinkContextMenu(QMenu *, const QString &, const QString &) +{ +} + } // namespace Core #if defined(WITH_TESTS) diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h index 113dcf84b2d..17e471e0281 100644 --- a/src/plugins/coreplugin/iversioncontrol.h +++ b/src/plugins/coreplugin/iversioncontrol.h @@ -36,6 +36,8 @@ #include #include +QT_FORWARD_DECLARE_CLASS(QMenu); + namespace Core { class ShellCommand; @@ -226,6 +228,10 @@ public: const QString &localName, const QStringList &extraArgs); + virtual void fillLinkContextMenu(QMenu *menu, + const QString &workingDirectory, + const QString &reference); + class CORE_EXPORT RepoUrl { public: RepoUrl(const QString &location); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 8608d947e1c..377abba60f7 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -3598,6 +3598,7 @@ GitRemote::GitRemote(const QString &location) : Core::IVersionControl::RepoUrl(l void GitClient::addChangeActions(QMenu *menu, const QString &workingDir, const QString &change) { + QTC_ASSERT(!change.isEmpty(), return); menu->addAction(tr("Cherr&y-Pick Change %1").arg(change), [workingDir, change] { m_instance->synchronousCherryPick(workingDir, change); }); @@ -3611,9 +3612,11 @@ void GitClient::addChangeActions(QMenu *menu, const QString &workingDir, const Q &QAction::triggered, [workingDir, change] { GitPlugin::startRebaseFromCommit(workingDir, change); }); - menu->addAction(tr("&Log for Change %1").arg(change), [workingDir, change] { + QAction *logAction = menu->addAction(tr("&Log for Change %1").arg(change), [workingDir, change] { m_instance->log(workingDir, QString(), false, {change}); }); + if (change.contains("..")) + menu->setDefaultAction(logAction); menu->addAction(tr("Add &Tag for Change %1...").arg(change), [workingDir, change] { QString output; QString errorMessage; diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp index 36463955963..d243c53f90b 100644 --- a/src/plugins/git/giteditor.cpp +++ b/src/plugins/git/giteditor.cpp @@ -27,7 +27,6 @@ #include "annotationhighlighter.h" #include "branchadddialog.h" -#include "gitplugin.h" #include "gitclient.h" #include "gitsettings.h" #include "gitsubmiteditorwidget.h" diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index be99e377d26..d3d93267b36 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -83,6 +83,7 @@ #include #include +#include #include #include #include @@ -256,6 +257,18 @@ public: const QString &localName, const QStringList &extraArgs) final; + void fillLinkContextMenu(QMenu *menu, + const QString &workingDirectory, + const QString &reference) final + { + menu->addAction(tr("&Copy \"%1\"").arg(reference), + [reference] { QApplication::clipboard()->setText(reference); }); + QAction *action = menu->addAction(tr("&Describe Change %1").arg(reference), + [=] { describe(workingDirectory, reference); }); + menu->setDefaultAction(action); + GitClient::addChangeActions(menu, workingDirectory, reference); + } + RepoUrl getRepoUrl(const QString &location) const override; QStringList additionalToolsPath() const final; diff --git a/src/plugins/vcsbase/vcsoutputformatter.cpp b/src/plugins/vcsbase/vcsoutputformatter.cpp index 4b09ed06eb7..9e454da544c 100644 --- a/src/plugins/vcsbase/vcsoutputformatter.cpp +++ b/src/plugins/vcsbase/vcsoutputformatter.cpp @@ -23,7 +23,11 @@ ****************************************************************************/ #include "vcsoutputformatter.h" +#include +#include + #include +#include #include #include #include @@ -68,4 +72,18 @@ void VcsOutputFormatter::handleLink(const QString &href) emit referenceClicked(href); } +void VcsOutputFormatter::fillLinkContextMenu( + QMenu *menu, const QString &workingDirectory, const QString &href) +{ + if (href.isEmpty() || href.startsWith("http://") || href.startsWith("https://")) { + QAction *action = menu->addAction( + tr("&Open \"%1\"").arg(href), + [href] { QDesktopServices::openUrl(QUrl(href)); }); + menu->setDefaultAction(action); + return; + } + if (Core::IVersionControl *vcs = Core::VcsManager::findVersionControlForDirectory(workingDirectory)) + vcs->fillLinkContextMenu(menu, workingDirectory, href); +} + } diff --git a/src/plugins/vcsbase/vcsoutputformatter.h b/src/plugins/vcsbase/vcsoutputformatter.h index d1d508b895f..b9fd8c6c7e4 100644 --- a/src/plugins/vcsbase/vcsoutputformatter.h +++ b/src/plugins/vcsbase/vcsoutputformatter.h @@ -27,6 +27,8 @@ #include +QT_FORWARD_DECLARE_CLASS(QMenu) + namespace VcsBase { class VcsOutputFormatter : public Utils::OutputFormatter @@ -37,6 +39,7 @@ public: ~VcsOutputFormatter() override = default; void appendMessage(const QString &text, Utils::OutputFormat format) override; void handleLink(const QString &href) override; + void fillLinkContextMenu(QMenu *menu, const QString &workingDirectory, const QString &href); signals: void referenceClicked(const QString &reference); diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index e468adcc305..1cff2dc4b72 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -175,10 +175,17 @@ QString OutputWindowPlainTextEdit::identifierUnderCursor(const QPoint &widgetPos void OutputWindowPlainTextEdit::contextMenuEvent(QContextMenuEvent *event) { - QMenu *menu = createStandardContextMenu(); + const QString href = anchorAt(event->pos()); + QMenu *menu = href.isEmpty() ? createStandardContextMenu(event->pos()) : new QMenu; // Add 'open file' QString repository; const QString token = identifierUnderCursor(event->pos(), &repository); + if (!repository.isEmpty()) { + if (VcsOutputFormatter *f = formatter()) { + if (!href.isEmpty()) + f->fillLinkContextMenu(menu, repository, href); + } + } QAction *openAction = nullptr; if (!token.isEmpty()) { // Check for a file, expand via repository if relative @@ -192,9 +199,12 @@ void OutputWindowPlainTextEdit::contextMenuEvent(QContextMenuEvent *event) openAction->setData(fi.absoluteFilePath()); } } - // Add 'clear' - menu->addSeparator(); - QAction *clearAction = menu->addAction(VcsOutputWindow::tr("Clear")); + QAction *clearAction = nullptr; + if (href.isEmpty()) { + // Add 'clear' + menu->addSeparator(); + clearAction = menu->addAction(VcsOutputWindow::tr("Clear")); + } // Run QAction *action = menu->exec(event->globalPos()); From 351f39fb3b84a97479aea339d2ecf71b5d079c75 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Wed, 26 Feb 2020 09:54:06 +0200 Subject: [PATCH 17/96] Android: fix sdkmanager duplicating packages list It seems that forcing sdkmanager reloadPackages is causing a duplication in all packages and ndk listings. Change-Id: I7e92d1c6dcec2a09db088d9596aca31a3d8b437f Reviewed-by: Alessandro Portale --- src/plugins/android/androidsettingswidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 5cb44faeb5d..3eeb0150160 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -342,7 +342,7 @@ void AndroidSettingsWidget::showEvent(QShowEvent *event) // Reloading SDK packages (force) is still synchronous. Use zero timer // to let settings dialog open first. QTimer::singleShot(0, std::bind(&AndroidSdkManager::reloadPackages, - m_sdkManager.get(), true)); + m_sdkManager.get(), false)); m_isInitialReloadDone = true; } } From 94a952815600d500bda42644491fa18b1ba8afbd Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 25 Feb 2020 12:31:25 +0200 Subject: [PATCH 18/96] Android: deduce the NDK path of saved toolchains from compilerCommand() The change 290840, made AndroidToolchain tied to an NDK location, but when restoring a toolchain the NDK wasn't being assigned. This deduces the NDK location from the toolchain compilerCommand(). Change-Id: I3cd936ac48570fadbec15ac1e13496706718c0ea Reviewed-by: Alessandro Portale --- src/plugins/android/androidtoolchain.cpp | 14 +++++++++++--- src/plugins/android/androidtoolchain.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 42ea48ee97c..4f879d92491 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -93,14 +93,22 @@ AndroidToolChain::~AndroidToolChain() = default; bool AndroidToolChain::isValid() const { + if (m_ndkLocation.isEmpty()) { + QStringList ndkParts(compilerCommand().toString().split("toolchains/llvm/prebuilt/")); + if (ndkParts.size() > 1) { + QString ndkLocation(ndkParts.first()); + if (ndkLocation.endsWith('/')) + ndkLocation.chop(1); + m_ndkLocation = FilePath::fromString(ndkLocation); + } + } + const bool isChildofNdk = compilerCommand().isChildOf(m_ndkLocation); - // If we're restoring a toolchain we set NDK path ourselves so it's enough to check against SDK const bool isChildofSdk = compilerCommand().isChildOf( AndroidConfigurations::currentConfig().sdkLocation()); return ClangToolChain::isValid() && typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID - && targetAbi().isValid() - && (isChildofNdk || isChildofSdk) + && targetAbi().isValid() && (isChildofNdk || isChildofSdk) && !originalTargetTriple().isEmpty(); } diff --git a/src/plugins/android/androidtoolchain.h b/src/plugins/android/androidtoolchain.h index 26c55f20a13..14ef9231be1 100644 --- a/src/plugins/android/androidtoolchain.h +++ b/src/plugins/android/androidtoolchain.h @@ -57,7 +57,7 @@ private: friend class AndroidToolChainFactory; - Utils::FilePath m_ndkLocation; + mutable Utils::FilePath m_ndkLocation; }; class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory From fb185eef11f24f5f72e4c7e6d09e7e2e56a5e7f2 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 28 Feb 2020 10:33:28 +0100 Subject: [PATCH 19/96] Doc: Update screen shot to show the list of locator filters Change-Id: If6b4068676e994ce5ec684432983df3f173dfab5 Reviewed-by: Eike Ziller --- .../images/qtcreator-locator-customize.png | Bin 6396 -> 22905 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/qtcreator/images/qtcreator-locator-customize.png b/doc/qtcreator/images/qtcreator-locator-customize.png index 707712e41a37be24d10d02531dd07bbd624fd6c0..8b28fa80fe5715ef4e68b5264f1ab6360f32b977 100644 GIT binary patch literal 22905 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%0ALLL!Ge-gUf&Lvs-?wam+Bz9SjwO#-|o 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 OFnGH9xvX Date: Fri, 28 Feb 2020 13:03:53 +0100 Subject: [PATCH 20/96] Doc: Fix typo "fil" > "file" Change-Id: Iaa0f25c9ef0c76f2923f91354304e3b0c6bb78b1 Reviewed-by: Leena Miettinen --- doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc index b9d636fed8f..ee2fbf7dc9c 100644 --- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc @@ -267,7 +267,7 @@ When you \l{https://bugreports.qt.io/}{report a bug} that is related to the C++ code model, the \QC developers might ask you to write information about - the internal state of the code model into a log file and to deliver the fil + the internal state of the code model into a log file and to deliver the file to them for inspection. To view information about the C++ code model in the From bafa0d94957b96d92d0e821a66fd02d75b6cb91a Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Fri, 28 Feb 2020 12:44:00 +0100 Subject: [PATCH 21/96] CMakeProjectManager: Add elapsed timer Change-Id: I1e7bcd60cae0193b4d16f20175b76550aaefbf9c Reviewed-by: Eike Ziller --- src/plugins/cmakeprojectmanager/cmakeprocess.cpp | 8 ++++++++ src/plugins/cmakeprojectmanager/cmakeprocess.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp index 0effbb97db7..8fce28e1ea6 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp @@ -38,6 +38,7 @@ #include #include +#include #include namespace CMakeProjectManager { @@ -149,6 +150,7 @@ void CMakeProcess::run(const BuildDirParameters ¶meters, const QStringList & process->setCommand(commandLine); emit started(); + m_elapsed.start(); process->start(); m_process = std::move(process); @@ -234,6 +236,12 @@ void CMakeProcess::handleProcessFinished(int code, QProcess::ExitStatus status) m_future->reportFinished(); emit finished(code, status); + + const QTime format = QTime(0, 0, 0, 0).addMSecs(m_elapsed.elapsed() + 500); + QString time = format.toString("h:mm:ss"); + if (time.startsWith("0:")) + time.remove(0, 2); // Don't display zero hours + Core::MessageManager::write(tr("Elapsed time: %1.") .arg(time)); } void CMakeProcess::checkForCancelled() diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.h b/src/plugins/cmakeprojectmanager/cmakeprocess.h index 6d03d1ab832..d71a56629f5 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprocess.h +++ b/src/plugins/cmakeprojectmanager/cmakeprocess.h @@ -31,6 +31,7 @@ #include +#include #include #include @@ -73,6 +74,7 @@ private: std::unique_ptr> m_future; bool m_processWasCanceled = false; QTimer m_cancelTimer; + QElapsedTimer m_elapsed; }; } // namespace Internal From a75cb044424f7d29b6841a32d325c0c5c1288f4c Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 25 Feb 2020 00:19:28 +0200 Subject: [PATCH 22/96] Android: keep the debuggers list updated with auto detected toolchains Current autoDetected Android debuggers list is never cleaned, if one sets up many NDKs it could get really big and messy. This change tries to keep it clean from old or duplicate entries, as well as keep it chained to the autodection mechanism of Android toolchains and kits. Relies on 291807 to allow autoDection for kits, toolchains, debuggers to work out-of-box. Change-Id: I320a021f0435d80fd3d56c060caa316def533afa Reviewed-by: Alessandro Portale --- src/plugins/android/androidconfigurations.cpp | 68 +++++++++++++++++-- src/plugins/android/androidconfigurations.h | 1 + src/plugins/android/androidplugin.cpp | 2 +- 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 0e794dd6d7e..90d6f875399 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -1090,22 +1090,73 @@ void AndroidConfigurations::removeOldToolChains() } } -static QVariant findOrRegisterDebugger(ToolChain *tc, const BaseQtVersion *qtVersion) +void AndroidConfigurations::removeUnusedDebuggers() { - const FilePath command = AndroidConfigurations::currentConfig().gdbPath(tc->targetAbi(), qtVersion); + QList uniqueNdks; + const QList qtVersions + = QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) { + return v->type() == Constants::ANDROIDQT; + }); + + for (const QtSupport::BaseQtVersion *qt : qtVersions) { + FilePath ndkLocation = currentConfig().ndkLocation(qt); + if (!uniqueNdks.contains(ndkLocation)) + uniqueNdks.append(ndkLocation); + } + + const QList allDebuggers = Debugger::DebuggerItemManager::debuggers(); + for (const Debugger::DebuggerItem &debugger : allDebuggers) { + if (!debugger.displayName().contains("Android")) + continue; + + bool isChildOfNdk = false; + for (const FilePath &path : uniqueNdks) { + if (debugger.command().isChildOf(path)) { + isChildOfNdk = true; + break; + } + } + + if (!isChildOfNdk && debugger.isAutoDetected()) + Debugger::DebuggerItemManager::deregisterDebugger(debugger.id()); + } +} + +static QVariant findOrRegisterDebugger(ToolChain *tc, + const QStringList &abisList, + const BaseQtVersion *qtVersion) +{ + const FilePath command = AndroidConfigurations::currentConfig().gdbPath(tc->targetAbi(), + qtVersion); // check if the debugger is already registered, but ignoring the display name const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(command); + + QList abis = Utils::transform(abisList, Abi::abiFromTargetTriplet); + + auto containsAbis = [abis](const Abis &secondAbis) { + for (const Abi &abi : secondAbis) { + if (!abis.contains(abi)) + return false; + } + return true; + }; + if (existing && existing->engineType() == Debugger::GdbEngineType && existing->isAutoDetected() - && existing->abis() == Abis{tc->targetAbi()}) + && containsAbis(existing->abis())) { + // update debugger info with new return existing->id(); + } + // debugger not found, register a new one Debugger::DebuggerItem debugger; debugger.setCommand(command); debugger.setEngineType(Debugger::GdbEngineType); debugger.setUnexpandedDisplayName( - AndroidConfigurations::tr("Android Debugger for %1").arg(tc->displayName())); + AndroidConfigurations::tr("Android Debugger (%1, NDK %2)") + .arg(abisList.join(", "), + AndroidConfigurations::currentConfig().ndkVersion(qtVersion).toString())); debugger.setAutoDetected(true); - debugger.setAbi(tc->targetAbi()); + debugger.setAbis(abis.toVector()); debugger.reinitializeFromFile(); return Debugger::DebuggerItemManager::registerDebugger(debugger); } @@ -1136,6 +1187,8 @@ void AndroidConfigurations::updateAutomaticKitList() return false; }); + removeUnusedDebuggers(); + QHash > qtVersionsForArch; const QList qtVersions = QtSupport::QtVersionManager::versions([](const QtSupport::BaseQtVersion *v) { @@ -1199,10 +1252,11 @@ void AndroidConfigurations::updateAutomaticKitList() ToolChainKitAspect::setToolChain(k, tc); QtSupport::QtKitAspect::setQtVersion(k, qt); DeviceKitAspect::setDevice(k, device); - Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc, QtKitAspect::qtVersion(k))); + QStringList abis = static_cast(qt)->androidAbis(); + Debugger::DebuggerKitAspect::setDebugger(k, findOrRegisterDebugger(tc, abis, QtKitAspect::qtVersion(k))); k->makeSticky(); k->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)") - .arg(static_cast(qt)->androidAbis().join(",")) + .arg(abis.join(",")) .arg(qt->displayName())); k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation(qt).toString()); k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString()); diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 4a4217e3a2c..b2f9ec02015 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -237,6 +237,7 @@ public: static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name static void clearDefaultDevices(ProjectExplorer::Project *project); static void registerNewToolChains(); + static void removeUnusedDebuggers(); static void removeOldToolChains(); static void updateAutomaticKitList(); static bool force32bitEmulator(); diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp index 1fcdd9bd720..2e02d516492 100644 --- a/src/plugins/android/androidplugin.cpp +++ b/src/plugins/android/androidplugin.cpp @@ -177,8 +177,8 @@ void AndroidPlugin::kitsRestored() &AndroidPlugin::askUserAboutAndroidSetup, Qt::QueuedConnection); } - AndroidConfigurations::updateAutomaticKitList(); AndroidConfigurations::registerNewToolChains(); + AndroidConfigurations::updateAutomaticKitList(); connect(QtSupport::QtVersionManager::instance(), &QtSupport::QtVersionManager::qtVersionsChanged, AndroidConfigurations::instance(), &AndroidConfigurations::updateAutomaticKitList); disconnect(KitManager::instance(), &KitManager::kitsLoaded, From 55b3d53213d7f7c0e5eefdfa8e94badd41c32d4c Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Wed, 26 Feb 2020 15:03:02 +0200 Subject: [PATCH 23/96] Handle the case when there is no 3D Nodes in the qml doc When there is no 3D node in the qml doc, the view 3D will still be enabled and manipulate-able. Also few relevant tweaks. Task-number: QDS-1693 Change-Id: I758f783108b317a6971703bee8e3fb564400ed8b Reviewed-by: Miikka Heikkinen Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 43 ++++++----- .../qt5informationnodeinstanceserver.cpp | 74 ++++++++++--------- .../components/edit3d/edit3dcanvas.cpp | 4 +- .../components/edit3d/edit3dcanvas.h | 2 +- .../designercore/include/qmlvisualnode.h | 4 +- .../instances/nodeinstanceview.cpp | 2 +- .../designercore/model/qmlvisualnode.cpp | 18 ++--- 7 files changed, 78 insertions(+), 69 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 9ee23e48a4e..d60ee38c4a7 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -62,33 +62,42 @@ Item { onUsePerspectiveChanged: _generalHelper.storeToolState(sceneId, "usePerspective", usePerspective) onShowEditLightChanged: _generalHelper.storeToolState(sceneId,"showEditLight", showEditLight) onGlobalOrientationChanged: _generalHelper.storeToolState(sceneId, "globalOrientation", globalOrientation) + onActiveSceneChanged: updateActiveScene(); - onActiveSceneChanged: { + function updateActiveScene() + { if (editView) { // Destroy is async, so make sure we don't get any more updates for the old editView _generalHelper.enableItemUpdate(editView, false); editView.destroy(); } - if (activeScene) { - // importScene cannot be updated after initial set, so we need to reconstruct entire View3D - var component = Qt.createComponent("SceneView3D.qml"); - if (component.status === Component.Ready) { - editView = component.createObject(viewRect, - {"usePerspective": usePerspective, - "showSceneLight": showEditLight, - "importScene": activeScene, - "cameraZoomFactor": cameraControl._zoomFactor, - "z": 1}); - editView.usePerspective = Qt.binding(function() {return usePerspective;}); - editView.showSceneLight = Qt.binding(function() {return showEditLight;}); - editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;}); - selectionBoxes.length = 0; - updateToolStates(_generalHelper.getToolStates(sceneId), true); - } + // importScene cannot be updated after initial set, so we need to reconstruct entire View3D + var component = Qt.createComponent("SceneView3D.qml"); + if (component.status === Component.Ready) { + editView = component.createObject(viewRect, + {"usePerspective": usePerspective, + "showSceneLight": showEditLight, + "importScene": activeScene, + "cameraZoomFactor": cameraControl._zoomFactor, + "z": 1}); + editView.usePerspective = Qt.binding(function() {return usePerspective;}); + editView.showSceneLight = Qt.binding(function() {return showEditLight;}); + editView.cameraZoomFactor = Qt.binding(function() {return cameraControl._zoomFactor;}); + + selectionBoxes.length = 0; + updateToolStates(_generalHelper.getToolStates(sceneId), true); } } + function clearActiveScene() + { + activeScene = null; + sceneId = ""; + + updateActiveScene(); + } + // Disables edit view update if scene doesn't match current activeScene. // If it matches, updates are enabled. function enableEditViewUpdate(scene) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 3b8cb04a909..b525da8248b 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -420,14 +420,22 @@ void Qt5InformationNodeInstanceServer::updateActiveSceneToEditView3D() sceneIdVar = QVariant::fromValue(sceneId); sceneIdProperty.write(sceneIdVar); - QQmlProperty sceneProperty(m_editView3DRootItem, "activeScene", context()); - sceneProperty.write(activeSceneVar); - - auto helper = qobject_cast(m_3dHelper); QVariantMap toolStates; - if (helper) - toolStates = helper->getToolStates(sceneId); - toolStates.insert("sceneInstanceId", QVariant::fromValue(sceneInstance.instanceId())); + + // if m_active3DScene is null, QQmlProperty::write() doesn't work so invoke the updateActiveScene + // qml method directly + if (!m_active3DScene) { + QMetaObject::invokeMethod(m_editView3DRootItem, "clearActiveScene", Qt::QueuedConnection); + toolStates.insert("sceneInstanceId", QVariant::fromValue(-1)); + } else { + QQmlProperty sceneProperty(m_editView3DRootItem, "activeScene", context()); + sceneProperty.write(activeSceneVar); + + auto helper = qobject_cast(m_3dHelper); + if (helper) + toolStates = helper->getToolStates(sceneId); + toolStates.insert("sceneInstanceId", QVariant::fromValue(sceneInstance.instanceId())); + } nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::ActiveSceneChanged, toolStates}); @@ -514,7 +522,6 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView() { static bool showEditView = qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_SHOW_EDIT_WINDOW"); if (m_editView3DRootItem && !showEditView) { - auto t = std::chrono::steady_clock::now(); if (!m_editView3DContentItem) { m_editView3DContentItem = QQmlProperty::read(m_editView3DRootItem, "contentItem").value(); if (m_editView3DContentItem) { @@ -544,10 +551,6 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView() // send the rendered image to creator process nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Render3DView, QVariant::fromValue(imgContainer)}); - qDebug() << "\x1b[42m \x1b[1m" << __FUNCTION__ - << ", t=" << std::chrono::duration_cast(std::chrono::steady_clock::now()-t).count() - << "\x1b[m"; - if (m_needRender) { m_renderTimer.start(0); m_needRender = false; @@ -880,32 +883,31 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList(m_3dHelper); - if (helper) { - auto it = toolStates.constBegin(); - while (it != toolStates.constEnd()) { - helper->initToolStates(it.key(), it.value()); - ++it; - } - helper->restoreWindowState(); - if (toolStates.contains(helper->globalStateId()) - && toolStates[helper->globalStateId()].contains("rootSize")) { - m_editView3DRootItem->setSize(toolStates[helper->globalStateId()]["rootSize"].value()); - } - } - - updateActiveSceneToEditView3D(); - - createCameraAndLightGizmos(instanceList); + createEditView3D(); + if (!m_editView3DRootItem) { + m_active3DScene = nullptr; + m_active3DView = nullptr; + return; } + + auto helper = qobject_cast(m_3dHelper); + if (helper) { + auto it = toolStates.constBegin(); + while (it != toolStates.constEnd()) { + helper->initToolStates(it.key(), it.value()); + ++it; + } + helper->restoreWindowState(); + if (toolStates.contains(helper->globalStateId()) + && toolStates[helper->globalStateId()].contains("rootSize")) { + m_editView3DRootItem->setSize(toolStates[helper->globalStateId()]["rootSize"].value()); + } + } + + updateActiveSceneToEditView3D(); + + createCameraAndLightGizmos(instanceList); #else Q_UNUSED(instanceList) Q_UNUSED(toolStates) diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp index 8a1c049907b..37c80246a51 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.cpp @@ -117,9 +117,7 @@ void Edit3DCanvas::dropEvent(QDropEvent *e) { Q_UNUSED(e) - QmlVisualNode::createQmlVisualNode(m_parent->view(), m_itemLibraryEntry, m_activeScene, {}); + QmlVisualNode::createQml3DNode(m_parent->view(), m_itemLibraryEntry, m_activeScene); } } - - diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h index 48b05789476..2243a466dd4 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dcanvas.h @@ -59,7 +59,7 @@ protected: private: QPointer m_parent; QImage m_image; - qint32 m_activeScene; + qint32 m_activeScene = -1; ItemLibraryEntry m_itemLibraryEntry; }; diff --git a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h index e573ec1bc99..d2169b52ff7 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlvisualnode.h @@ -102,9 +102,9 @@ public: const Position &position, NodeAbstractProperty parentproperty); - static QmlVisualNode createQmlVisualNode(AbstractView *view, + static QmlVisualNode createQml3DNode(AbstractView *view, const ItemLibraryEntry &itemLibraryEntry, - qint32 sceneRootId, const QVector3D &position); + qint32 sceneRootId = -1, const QVector3D &position = {}); static NodeListProperty findSceneNodeProperty(AbstractView *view, qint32 sceneRootId); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index e361b742058..66572534261 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1452,7 +1452,7 @@ void NodeInstanceView::library3DItemDropped(const Drop3DLibraryItemCommand &comm QDataStream stream(command.itemData()); ItemLibraryEntry itemLibraryEntry; stream >> itemLibraryEntry; - QmlVisualNode::createQmlVisualNode(this, itemLibraryEntry, command.sceneRootId(), {}); + QmlVisualNode::createQml3DNode(this, itemLibraryEntry, command.sceneRootId(), {}); } void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index ada504908f9..16caa385e67 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -294,15 +294,16 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view, return newQmlObjectNode; } -QmlVisualNode QmlVisualNode::createQmlVisualNode(AbstractView *view, - const ItemLibraryEntry &itemLibraryEntry, - qint32 sceneRootId, const QVector3D &position) +QmlVisualNode QmlVisualNode::createQml3DNode(AbstractView *view, + const ItemLibraryEntry &itemLibraryEntry, + qint32 sceneRootId, const QVector3D &position) { - NodeAbstractProperty sceneNodeProperty = findSceneNodeProperty(view, sceneRootId); - QTC_ASSERT(sceneNodeProperty.isValid(), return {}); - ModelNode node = createQmlObjectNode(view, itemLibraryEntry, position, sceneNodeProperty).modelNode(); + NodeAbstractProperty sceneNodeProperty = sceneRootId != -1 ? findSceneNodeProperty(view, sceneRootId) + : view->rootModelNode().defaultNodeAbstractProperty(); - return node; + QTC_ASSERT(sceneNodeProperty.isValid(), return {}); + + return createQmlObjectNode(view, itemLibraryEntry, position, sceneNodeProperty).modelNode(); } NodeListProperty QmlVisualNode::findSceneNodeProperty(AbstractView *view, qint32 sceneRootId) @@ -318,8 +319,7 @@ NodeListProperty QmlVisualNode::findSceneNodeProperty(AbstractView *view, qint32 bool QmlVisualNode::isFlowTransition(const ModelNode &node) { - return node.metaInfo().isValid() - && node.metaInfo().isSubclassOf("FlowView.FlowTransition"); + return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowTransition"); } bool QmlVisualNode::isFlowTransition() const From d07d118b447b40a9a53ea15eee4f5c68fda3b25f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 28 Feb 2020 14:34:20 +0100 Subject: [PATCH 24/96] Doc: Add missing separators to menu paths Change-Id: I58fe828d204ebc636fd529be9759bdeb5a8fe76a Reviewed-by: Leena Miettinen --- doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc index ee2fbf7dc9c..72f7bdecf64 100644 --- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc @@ -187,10 +187,10 @@ the bookmark. To go to the previous bookmark in the current session, select - \uicontrol Tools \uicontrol Bookmarks > \uicontrol {Previous Bookmark} + \uicontrol Tools > \uicontrol Bookmarks > \uicontrol {Previous Bookmark} or press \key {Ctrl+,}. - To go to the next bookmark in the current session, select \uicontrol Tools + To go to the next bookmark in the current session, select \uicontrol Tools > \uicontrol Bookmarks > \uicontrol {Previous Bookmark} or press \key {Ctrl+.}. From 0750af7049c9af0bec174e32d8be0284ffe26dea Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 28 Feb 2020 14:29:22 +0100 Subject: [PATCH 25/96] Doc: Describe the "Go to Last Edit" function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Returns to the last location where you made a change. Change-Id: I35cda32d28b51b0fcfe31fd17e03ce103a87b447 Reviewed-by: André Hartmann --- .../src/editors/creator-coding-edit-mode.qdoc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc index 72f7bdecf64..bd5d5e2b565 100644 --- a/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc +++ b/doc/qtcreator/src/editors/creator-coding-edit-mode.qdoc @@ -54,12 +54,18 @@ \section2 Navigating Between Open Files and Symbols - Use the toolbar to navigate between open files and symbols in use. To browse - backward or forward through your location history, click - \inlineimage prev.png + Use the toolbar, \uicontrol Window menu items, or + \l{General Keyboard Shortcuts}{keyboard shortcuts} + to navigate between open files and symbols in use. + + To browse backward or forward through your + location history, click \inlineimage prev.png (\uicontrol {Go Back}) and \inlineimage next.png (\uicontrol {Go Forward}). + To return to the last location where you made a change, select + \uicontrol Window > \uicontrol {Go to Last Edit}. + To go to any open file, select it from the \uicontrol {Open files} drop-down menu (1). To open a context menu that contains commands for managing open files, right-click the file name or icon on the toolbar. In addition to the @@ -80,8 +86,7 @@ number in the locator, separated by a colon (:). \note Other convenient ways of navigating in \QC are provided - by the \l{Keyboard Shortcuts} {keyboard shortcuts} and the - \l{Browsing Project Contents}{sidebar}. + by the \l{Browsing Project Contents}{sidebars}. \if defined(qtcreator) \section2 Selecting Parse Context From 87d18ec0dc0d1e637c6c6bb21394da7115ef351c Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 24 Feb 2020 16:52:43 +0100 Subject: [PATCH 26/96] QmlDesigner: Add import filtering for QtForMCUs This implements basic import filtering for QtForMCUs. Change-Id: I3b8bfbee11b26f1512cd5864057a347afe09c93f Reviewed-by: Tim Jenssen --- .../importmanager/importswidget.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/importmanager/importswidget.cpp b/src/plugins/qmldesigner/components/importmanager/importswidget.cpp index 07ada7c8588..5f10c36bc96 100644 --- a/src/plugins/qmldesigner/components/importmanager/importswidget.cpp +++ b/src/plugins/qmldesigner/components/importmanager/importswidget.cpp @@ -27,6 +27,9 @@ #include "importlabel.h" #include "importmanagercombobox.h" +#include +#include + #include #include @@ -90,7 +93,22 @@ void ImportsWidget::setPossibleImports(QList possibleImports) { Utils::sort(possibleImports, importLess); m_addImportComboBox->clear(); - foreach (const Import &possibleImport, possibleImports) { + + const DesignDocument *designDocument = QmlDesignerPlugin::instance()->currentDesignDocument(); + const bool isQtForMCUs = designDocument && designDocument->isQtForMCUsProject(); + + QList filteredImports; + + const QStringList mcuWhiteList = {"QtQuick", "QtQuick.Controls"}; + + if (isQtForMCUs) + filteredImports = Utils::filtered(possibleImports, [mcuWhiteList](const Import &import) { + return mcuWhiteList.contains(import.url()) || !import.url().startsWith("Qt"); + }); + else + filteredImports = possibleImports; + + for (const Import &possibleImport : filteredImports) { if (!isImportAlreadyUsed(possibleImport, m_importLabels)) m_addImportComboBox->addItem(possibleImport.toString(true), QVariant::fromValue(possibleImport)); } From ea7457410b57fdd0935f198cb71034c96550ef19 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 24 Feb 2020 16:27:56 +0100 Subject: [PATCH 27/96] QmlDesigner: Fix potential crash Change-Id: I99cbddfed3d343638d707d2915e77bd962200498 Reviewed-by: Tim Jenssen --- .../components/propertyeditor/qmlanchorbindingproxy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp index 7a38f74f34e..b4ec89d3687 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/qmlanchorbindingproxy.cpp @@ -894,6 +894,7 @@ QmlItemNode QmlAnchorBindingProxy::targetIdToNode(const QString &id) const QString QmlAnchorBindingProxy::idForNode(const QmlItemNode &qmlItemNode) const { + QTC_ASSERT(qmlItemNode.isValid(), return {}); if (m_qmlItemNode.instanceParent().modelNode() == qmlItemNode) return QStringLiteral("parent"); From 620e17cf7b5f31f37d81de76f18cb837f4fb9de4 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 24 Feb 2020 16:27:45 +0100 Subject: [PATCH 28/96] QmlDesigner: Implement usage of qtForMCUs property If qtForMCUs is set in the qmlproject file we disable unsupported properties like roation, transformOrigin or layer. Change-Id: I75d9677beca3d4ce71f975b4f0ae75e63967d143 Reviewed-by: Thomas Hartmann --- .../QtQuick/AdvancedSection.qml | 10 +++++++ .../QtQuick/LayerSection.qml | 1 + .../QtQuick/RectangleSpecifics.qml | 2 ++ .../imports/HelperWidgets/Label.qml | 23 ++++++++++++-- .../imports/HelperWidgets/OriginControl.qml | 6 +++- .../imports/StudioTheme/Values.qml | 1 + .../components/integration/designdocument.cpp | 8 +++++ .../components/integration/designdocument.h | 2 ++ .../propertyeditor/propertyeditorvalue.cpp | 30 +++++++++++++++---- .../propertyeditor/propertyeditorvalue.h | 4 +++ 10 files changed, 78 insertions(+), 9 deletions(-) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml index ab6b17dd12b..276284cfc99 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/AdvancedSection.qml @@ -37,14 +37,17 @@ Section { Label { text: qsTr("Origin") + disabledState: !backendValues.transformOrigin.isAvailable } OriginControl { backendValue: backendValues.transformOrigin + enabled: backendValues.transformOrigin.isAvailable } Label { text: qsTr("Scale") + disabledState: !backendValues.scale.isAvailable } SecondColumnLayout { @@ -57,12 +60,14 @@ Section { minimumValue: -10 maximumValue: 10 Layout.preferredWidth: 140 + enabled: backendValues.scale.isAvailable } ExpandingSpacer { } } Label { text: qsTr("Rotation") + disabledState: !backendValues.rotation.isAvailable } SecondColumnLayout { SpinBox { @@ -73,6 +78,7 @@ Section { minimumValue: -360 maximumValue: 360 Layout.preferredWidth: 140 + enabled: backendValues.rotation.isAvailable } ExpandingSpacer { } @@ -110,12 +116,14 @@ Section { Label { visible: majorQtQuickVersion > 1 text: qsTr("Smooth") + disabledState: !backendValues.smooth.isAvailable } SecondColumnLayout { visible: majorQtQuickVersion > 1 CheckBox { backendValue: backendValues.smooth text: qsTr("Smooth sampling active") + enabled: backendValues.smooth.isAvailable } ExpandingSpacer { } @@ -124,12 +132,14 @@ Section { Label { visible: majorQtQuickVersion > 1 text: qsTr("Antialiasing") + disabledState: !backendValues.antialiasing.isAvailable } SecondColumnLayout { visible: majorQtQuickVersion > 1 CheckBox { backendValue: backendValues.antialiasing text: qsTr("Anti-aliasing active") + enabled: backendValues.antialiasing.isAvailable } ExpandingSpacer { } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml index 4db19fe275f..b95312f1484 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LayerSection.qml @@ -31,6 +31,7 @@ Section { anchors.left: parent.left anchors.right: parent.right caption: qsTr("Layer") + visible: backendValues.layer_effect.isAvailable SectionLayout { columns: 2 diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml index 65704972975..0fa2b331a8c 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/RectangleSpecifics.qml @@ -50,6 +50,7 @@ Column { anchors.left: parent.left anchors.right: parent.right caption: qsTr("Border Color") + visible: backendValues.border_color.isAvailable ColorEditor { caption: qsTr("Border Color") @@ -63,6 +64,7 @@ Column { anchors.left: parent.left anchors.right: parent.right caption: "Rectangle" + visible: backendValues.border_color.isAvailable SectionLayout { rows: 2 diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml index 127ffa6ac9d..6a14e7f68cc 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/Label.qml @@ -37,7 +37,8 @@ Label { property alias toolTip: toolTipArea.tooltip width: Math.max(Math.min(240, parent.width - 280), 50) - color: StudioTheme.Values.themeTextColor + color: label.disabledState ? StudioTheme.Values.themeDisabledTextColor : StudioTheme.Values.themeTextColor + elide: Text.ElideRight font.pixelSize: StudioTheme.Values.myFontSize @@ -46,9 +47,27 @@ Label { Layout.minimumWidth: width Layout.maximumWidth: width + leftPadding: label.disabledState ? 10 : 0 + rightPadding: label.disabledState ? 10 : 0 + + property bool disabledState: false + + Text { + text: "[" + color: StudioTheme.Values.themeTextColor//StudioTheme.Values.themeDisabledTextColor + visible: label.disabledState + } + + Text { + text: "]" + color: StudioTheme.Values.themeTextColor//StudioTheme.Values.themeDisabledTextColor// + visible: label.disabledState + x: label.contentWidth + 10 + contentWidth + } + ToolTipArea { id: toolTipArea anchors.fill: parent - tooltip: label.text + tooltip: label.disabledState ? qsTr("This property is not available in this configuration.") : label.text } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml index da2f2cac88d..a6db34f4f16 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/OriginControl.qml @@ -42,6 +42,8 @@ Item { readonly property color selectedColor: Theme.qmlDesignerBackgroundColorDarkAlternate() readonly property color unselectedColor: Theme.qmlDesignerBackgroundColorDarker() + property bool enabled: true + ExtendedFunctionLogic { id: extFuncLogic backendValue: originControl.backendValue @@ -69,6 +71,7 @@ Item { } Grid { + opacity: originControl.enabled ? 1 : 0.5 rows: 3 columns: 3 spacing: 5 @@ -76,7 +79,8 @@ Item { id: grid function setValue(myValue) { - originControl.backendValue.setEnumeration("Item", myValue) + if (originControl.enabled) + originControl.backendValue.setEnumeration("Item", myValue) } function select(myValue) { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml index ff10e1e79f5..3f432d40808 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/Values.qml @@ -84,6 +84,7 @@ QtObject { property string themeControlBackground: "#242424" property string themeControlOutline: "#404040" property string themeTextColor: "#ffffff" + property string themeDisabledTextColor: "#909090" property string themePanelBackground: "#2a2a2a" property string themeHoverHighlight: "#313131" diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index 9d3809727ed..75b45fedb86 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -269,6 +269,14 @@ void DesignDocument::changeToDocumentModel() viewManager().attachViewsExceptRewriterAndComponetView(); } +bool DesignDocument::isQtForMCUsProject() const +{ + if (m_currentTarget) + return m_currentTarget->additionalData("CustomQtForMCUs").toBool(); + + return true; +} + void DesignDocument::changeToInFileComponentModel(ComponentTextModifier *textModifer) { m_inFileComponentTextModifier.reset(textModifer); diff --git a/src/plugins/qmldesigner/components/integration/designdocument.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 7e8509eb4d4..60a0f3f11a1 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -97,6 +97,8 @@ public: void changeToDocumentModel(); + bool isQtForMCUsProject() const; + signals: void displayNameChanged(const QString &newFileName); void dirtyStateChanged(bool newState); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp index b1efd1af0e2..3ec61f9cabb 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.cpp @@ -25,16 +25,18 @@ #include "propertyeditorvalue.h" +#include #include +#include +#include +#include +#include +#include + +#include #include #include -#include -#include -#include -#include -#include -#include //using namespace QmlDesigner; @@ -261,6 +263,22 @@ bool PropertyEditorValue::isTranslated() const return false; } +bool PropertyEditorValue::isAvailable() const +{ + const QList mcuProperties = {"layer", "opacity", "rotation", "scale", "transformOrigin", "smooth", "antialiasing", "border"}; + const QList list = name().split('.'); + const QByteArray pureName = list.first(); + + QmlDesigner::DesignDocument *designDocument = + QmlDesigner::QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); + + + if (designDocument && designDocument->isQtForMCUsProject()) + return !mcuProperties.contains(pureName); + + return true; +} + QmlDesigner::ModelNode PropertyEditorValue::modelNode() const { return m_modelNode; diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h index a69bca8a739..52de9cbb707 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorvalue.h @@ -89,6 +89,8 @@ class PropertyEditorValue : public QObject Q_PROPERTY(QString name READ nameAsQString FINAL) Q_PROPERTY(PropertyEditorNodeWrapper* complexNode READ complexNode NOTIFY complexNodeChanged FINAL) + Q_PROPERTY(bool isAvailable READ isAvailable NOTIFY isBoundChanged) + public: PropertyEditorValue(QObject *parent=nullptr); @@ -115,6 +117,8 @@ public: bool isTranslated() const; + bool isAvailable() const; + QmlDesigner::PropertyName name() const; QString nameAsQString() const; void setName(const QmlDesigner::PropertyName &name); From fb447f9999421e28ef169ba5c8328c270a1929b8 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 28 Feb 2020 13:45:48 +0100 Subject: [PATCH 29/96] ProjectExplorer: Trigger updates more directly Changes of active run and build config impact some visible state, but instead of connecting and disconnecting signals to the target, make the call explicit. Also, triggering only updateAction is sufficient, as this will already run updateRunAction. This makes the number of doUpdateRunAction calls when opening a normal QMake project with one target, three build configs drops from 17 to 15. There was some mechanism on the receiver side originally meant to prevent excessive updates, which broke with 7ae3589 when remembering the previous configurations was accidentally removed. This here drops the mechanism completely, as active changed signals would not trigger twice in succession for the same config anyway. Change-Id: Id9f87e542d8871733966ab79118734b7e9ad1e8a Reviewed-by: Christian Kandeler --- .../projectexplorer/projectexplorer.cpp | 44 ------------------- src/plugins/projectexplorer/target.cpp | 2 + 2 files changed, 2 insertions(+), 44 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index b99c4384f57..9e21e88fb6d 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -450,8 +450,6 @@ public: void projectDisplayNameChanged(ProjectExplorer::Project *pro); void startupProjectChanged(); // Calls updateRunAction void activeTargetChanged(); - void activeRunConfigurationChanged(); - void activeBuildConfigurationChanged(); void doUpdateRunActions(); @@ -2957,50 +2955,8 @@ void ProjectExplorerPluginPrivate::activeTargetChanged() if (target == previousTarget) return; - if (previousTarget) { - disconnect(previousTarget.data(), &Target::activeRunConfigurationChanged, - this, &ProjectExplorerPluginPrivate::activeRunConfigurationChanged); - disconnect(previousTarget.data(), &Target::activeBuildConfigurationChanged, - this, &ProjectExplorerPluginPrivate::activeBuildConfigurationChanged); - } previousTarget = target; - if (target) { - connect(target, &Target::activeRunConfigurationChanged, - this, &ProjectExplorerPluginPrivate::activeRunConfigurationChanged); - connect(previousTarget.data(), &Target::activeBuildConfigurationChanged, - this, &ProjectExplorerPluginPrivate::activeBuildConfigurationChanged); - } - - activeBuildConfigurationChanged(); - activeRunConfigurationChanged(); - updateDeployActions(); -} - -void ProjectExplorerPluginPrivate::activeRunConfigurationChanged() -{ - static QPointer previousRunConfiguration = nullptr; - RunConfiguration *rc = nullptr; - Project *startupProject = SessionManager::startupProject(); - if (startupProject && startupProject->activeTarget()) - rc = startupProject->activeTarget()->activeRunConfiguration(); - if (rc == previousRunConfiguration) - return; updateActions(); - doUpdateRunActions(); -} - -void ProjectExplorerPluginPrivate::activeBuildConfigurationChanged() -{ - static QPointer previousBuildConfiguration = nullptr; - - BuildConfiguration *bc = nullptr; - if (Target *target = SessionManager::startupTarget()) - bc = target->activeBuildConfiguration(); - if (bc == previousBuildConfiguration) - return; - - updateActions(); - doUpdateRunActions(); } void ProjectExplorerPluginPrivate::updateDeployActions() diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index aa20d94aa82..fc0b87e7271 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -331,6 +331,7 @@ void Target::setActiveBuildConfiguration(BuildConfiguration *bc) bc != d->m_activeBuildConfiguration)) { d->m_activeBuildConfiguration = bc; emit activeBuildConfigurationChanged(d->m_activeBuildConfiguration); + ProjectExplorerPlugin::updateActions(); } } @@ -467,6 +468,7 @@ void Target::setActiveRunConfiguration(RunConfiguration *rc) rc != d->m_activeRunConfiguration)) { d->m_activeRunConfiguration = rc; emit activeRunConfigurationChanged(d->m_activeRunConfiguration); + ProjectExplorerPlugin::updateActions(); } updateDeviceState(); } From 33904afa73357932ee44a64f9c1976ad1eaeb3f0 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 28 Feb 2020 16:40:09 +0100 Subject: [PATCH 30/96] QmlProjectManager: Fix setting of QmlProjectItem.qtForMCUs Change-Id: I0f98d21b7d343685f6e696526486ef17dc7b632e Reviewed-by: Thomas Hartmann --- .../qmlprojectmanager/fileformat/qmlprojectfileformat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp index 1ad4bb0590c..d70a2a7707c 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp @@ -103,7 +103,7 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi const QVariant qtForMCUProperty = rootNode->property("qtForMCUs"); if (qtForMCUProperty.isValid() && qtForMCUProperty.toBool()) - projectItem->setQtForMCUs(targetDirectoryPropery.toBool()); + projectItem->setQtForMCUs(qtForMCUProperty.toBool()); if (debug) qDebug() << "importPath:" << importPathsProperty << "mainFile:" << mainFileProperty; From b4dfda5814ca8c5be4d106ce485cb409bafdad28 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 28 Feb 2020 16:08:18 +0100 Subject: [PATCH 31/96] McuSupport: Let application wizard generate a .qmlproject in addition It sets the qtForMCUs flag to true, so the the QmlDesigner plugin can filter out the unsupported imports and properties. Change-Id: Ic5728ff334b410742518c564d88d72957d6c979d Reviewed-by: Thomas Hartmann --- src/plugins/mcusupport/mcusupport.qrc | 1 + .../application/project.qmlproject.tpl | 19 +++++++++++++++++++ .../wizards/application/wizard.json | 5 +++++ 3 files changed, 25 insertions(+) create mode 100644 src/plugins/mcusupport/wizards/application/project.qmlproject.tpl diff --git a/src/plugins/mcusupport/mcusupport.qrc b/src/plugins/mcusupport/mcusupport.qrc index c38ede5929c..b45fb8ccc31 100644 --- a/src/plugins/mcusupport/mcusupport.qrc +++ b/src/plugins/mcusupport/mcusupport.qrc @@ -7,6 +7,7 @@ wizards/icon.png wizards/icon@2x.png wizards/application/CMakeLists.txt + wizards/application/project.qmlproject.tpl wizards/application/main.qml.tpl wizards/application/wizard.json diff --git a/src/plugins/mcusupport/wizards/application/project.qmlproject.tpl b/src/plugins/mcusupport/wizards/application/project.qmlproject.tpl new file mode 100644 index 00000000000..0b5d6d58631 --- /dev/null +++ b/src/plugins/mcusupport/wizards/application/project.qmlproject.tpl @@ -0,0 +1,19 @@ +/* File generated by Qt Creator */ + +import QmlProject 1.1 + +Project { + mainFile: "%{MainQmlFile}" + qtForMCUs: true + + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } +} diff --git a/src/plugins/mcusupport/wizards/application/wizard.json b/src/plugins/mcusupport/wizards/application/wizard.json index 4e16d17e937..1c598507e13 100644 --- a/src/plugins/mcusupport/wizards/application/wizard.json +++ b/src/plugins/mcusupport/wizards/application/wizard.json @@ -47,6 +47,11 @@ "source": "CMakeLists.txt", "openAsProject": true }, + { + "source": "project.qmlproject.tpl", + "target": "%{ProjectDirectory}/%{ProjectName}.qmlproject", + "openInEditor": false + }, { "source": "main.qml.tpl", "target": "%{ProjectDirectory}/%{MainQmlFile}", From 3f61e9a3912054fdc9c5b6de41113dcb6dcaeab5 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Mon, 24 Feb 2020 11:19:02 +0200 Subject: [PATCH 32/96] Android: Allow adding custom NDKs and auto detect their toolchains This adds the option for the user to add a custom NDK out of the predefined list installed from SDK manager. Once an NDK is added and settings saved, both the toolchains and debuggers will be detected automatically. The user then can create a custom kit with those added toolchains and debuggers. Task-number: QTCREATORBUG-23286 Change-Id: I46200accca6fc956b73f211213bfe2a495093934 Reviewed-by: Alessandro Portale --- src/plugins/android/androidconfigurations.cpp | 114 ++++++++++++++++-- src/plugins/android/androidconfigurations.h | 10 ++ src/plugins/android/androidsettingswidget.cpp | 36 +++++- src/plugins/android/androidsettingswidget.ui | 90 +++++++++++--- src/plugins/android/androidtoolchain.cpp | 51 ++++---- src/plugins/android/androidtoolchain.h | 5 +- 6 files changed, 251 insertions(+), 55 deletions(-) diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 90d6f875399..5879c0e0073 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -100,6 +100,7 @@ namespace { const QLatin1String SettingsGroup("AndroidConfigurations"); const QLatin1String SDKLocationKey("SDKLocation"); + const QLatin1String CustomNdkLocationsKey("CustomNdkLocations"); const QLatin1String SdkFullyConfiguredKey("AllEssentialsInstalled"); const QLatin1String SDKManagerToolArgsKey("SDKManagerToolArgs"); const QLatin1String OpenJDKLocationKey("OpenJDKLocation"); @@ -235,6 +236,7 @@ void AndroidConfig::load(const QSettings &settings) // user settings m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt(); m_sdkLocation = FilePath::fromString(settings.value(SDKLocationKey).toString()); + m_customNdkList = settings.value(CustomNdkLocationsKey).toStringList(); m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList(); m_openJDKLocation = FilePath::fromString(settings.value(OpenJDKLocationKey).toString()); m_keystoreLocation = FilePath::fromString(settings.value(KeystoreLocationKey).toString()); @@ -246,12 +248,14 @@ void AndroidConfig::load(const QSettings &settings) && settings.value(changeTimeStamp).toInt() != QFileInfo(sdkSettingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) { // persisten settings m_sdkLocation = FilePath::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString()); + m_customNdkList = reader.restoreValue(CustomNdkLocationsKey).toStringList(); m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList(); m_openJDKLocation = FilePath::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString()); m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool(); m_sdkFullyConfigured = reader.restoreValue(SdkFullyConfiguredKey, m_sdkFullyConfigured).toBool(); // persistent settings } + m_customNdkList.removeAll(""); parseDependenciesJson(); } @@ -263,6 +267,7 @@ void AndroidConfig::save(QSettings &settings) const // user settings settings.setValue(SDKLocationKey, m_sdkLocation.toString()); + settings.setValue(CustomNdkLocationsKey, m_customNdkList); settings.setValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs); settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString()); settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString()); @@ -353,6 +358,22 @@ QVector AndroidConfig::availableNdkPlatforms(const BaseQtVersion *qtVersion return availableNdkPlatforms; } +QStringList AndroidConfig::getCustomNdkList() const +{ + return m_customNdkList; +} + +void AndroidConfig::addCustomNdk(const QString &customNdk) +{ + if (!m_customNdkList.contains(customNdk)) + m_customNdkList.append(customNdk); +} + +void AndroidConfig::removeCustomNdk(const QString &customNdk) +{ + m_customNdkList.removeAll(customNdk); +} + QStringList AndroidConfig::apiLevelNamesFor(const SdkPlatformList &platforms) { return Utils::transform(platforms, AndroidConfig::apiLevelNameFor); @@ -415,9 +436,9 @@ FilePath AndroidConfig::aaptToolPath() const return aaptToolPath.pathAppended(toolPath); } -FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const +FilePath AndroidConfig::toolchainPathFromNdk(const Utils::FilePath &ndkLocation) const { - const FilePath toolchainPath = ndkLocation(qtVersion).pathAppended("toolchains/llvm/prebuilt/"); + const FilePath toolchainPath = ndkLocation.pathAppended("toolchains/llvm/prebuilt/"); // detect toolchain host QStringList hostPatterns; @@ -443,23 +464,41 @@ FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const return {}; } -FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const +FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const { - const FilePath path = toolchainPath(qtVersion); + return toolchainPathFromNdk(ndkLocation(qtVersion)); +} + +FilePath AndroidConfig::clangPathFromNdk(const Utils::FilePath &ndkLocation) const +{ + const FilePath path = toolchainPathFromNdk(ndkLocation); if (path.isEmpty()) return {}; return path.pathAppended(HostOsInfo::withExecutableSuffix("bin/clang")); } +FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const +{ + return clangPathFromNdk(ndkLocation(qtVersion)); +} + FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi, const BaseQtVersion *qtVersion) const { - const FilePath path = ndkLocation(qtVersion).pathAppended( - QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(qtVersion), QTC_HOST_EXE_SUFFIX)); + return gdbPathFromNdk(abi, ndkLocation(qtVersion)); +} + +FilePath AndroidConfig::gdbPathFromNdk(const Abi &abi, const FilePath &ndkLocation) const +{ + const FilePath path = ndkLocation.pathAppended( + QString("prebuilt/%1/bin/gdb%2").arg(toolchainHostFromNdk(ndkLocation), QTC_HOST_EXE_SUFFIX)); if (path.exists()) return path; // fallback for old NDKs (e.g. 10e) - return ndkLocation(qtVersion).pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4") - .arg(toolchainPrefix(abi), toolchainHost(qtVersion), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX)); + return ndkLocation.pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4") + .arg(toolchainPrefix(abi), + toolchainHostFromNdk(ndkLocation), + toolsPrefix(abi), + QTC_HOST_EXE_SUFFIX)); } FilePath AndroidConfig::makePath(const BaseQtVersion *qtVersion) const @@ -733,6 +772,16 @@ bool AndroidConfig::useNativeUiTools() const return !version.isNull() && version <= QVersionNumber(25, 3 ,0); } +bool AndroidConfig::isValidNdk(const QString &ndkLocation) const +{ + auto ndkPath = Utils::FilePath::fromUserInput(ndkLocation); + const Utils::FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms"); + + return ndkPath.exists() && ndkPath.pathAppended("toolchains").exists() + && ndkPlatformsDir.exists() && !ndkPlatformsDir.toString().contains(' ') + && !ndkVersion(ndkPath).isNull(); +} + QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const { target = std::max(AndroidManager::apiLevelRange().first, target); @@ -1076,10 +1125,53 @@ void AndroidConfigurations::registerNewToolChains() const QList existingAndroidToolChains = ToolChainManager::toolChains(Utils::equal(&ToolChain::typeId, Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID))); - const QList newToolchains - = AndroidToolChainFactory::autodetectToolChainsForNdk(existingAndroidToolChains); + QList newToolchains = AndroidToolChainFactory::autodetectToolChains( + existingAndroidToolChains); + foreach (ToolChain *tc, newToolchains) ToolChainManager::registerToolChain(tc); + + registerCustomToolChainsAndDebuggers(); +} + +void AndroidConfigurations::registerCustomToolChainsAndDebuggers() +{ + const QList existingAndroidToolChains = ToolChainManager::toolChains( + Utils::equal(&ToolChain::typeId, Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID))); + QList customNdks = Utils::transform(currentConfig().getCustomNdkList(), + FilePath::fromString); + QList customToolchains + = AndroidToolChainFactory::autodetectToolChainsFromNdks(existingAndroidToolChains, + customNdks, + true); + for (ToolChain *tc : customToolchains) { + ToolChainManager::registerToolChain(tc); + + const FilePath ndk = static_cast(tc)->ndkLocation(); + const FilePath command = AndroidConfigurations::currentConfig() + .gdbPathFromNdk(tc->targetAbi(), ndk); + + const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand( + command); + QString abiStr + = static_cast(tc)->platformLinkerFlags().at(1).split('-').first(); + Abi abi = Abi::abiFromTargetTriplet(abiStr); + if (existing && existing->abis().contains(abi)) + continue; + + Debugger::DebuggerItem debugger; + debugger.setCommand(command); + debugger.setEngineType(Debugger::GdbEngineType); + debugger.setUnexpandedDisplayName( + AndroidConfigurations::tr("Custom Android Debugger (%1, NDK %2)") + .arg(abiStr, + AndroidConfigurations::currentConfig().ndkVersion(ndk).toString())); + debugger.setAutoDetected(true); + debugger.setAbi(abi); + debugger.reinitializeFromFile(); + + Debugger::DebuggerItemManager::registerDebugger(debugger); + } } void AndroidConfigurations::removeOldToolChains() @@ -1104,6 +1196,8 @@ void AndroidConfigurations::removeUnusedDebuggers() uniqueNdks.append(ndkLocation); } + uniqueNdks.append(Utils::transform(currentConfig().getCustomNdkList(), FilePath::fromString)); + const QList allDebuggers = Debugger::DebuggerItemManager::debuggers(); for (const Debugger::DebuggerItem &debugger : allDebuggers) { if (!debugger.displayName().contains("Android")) diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index b2f9ec02015..f793ed78c3f 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -160,9 +160,12 @@ public: Utils::FilePath aaptToolPath() const; Utils::FilePath toolchainPath(const QtSupport::BaseQtVersion *qtVersion) const; + Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation) const; Utils::FilePath clangPath(const QtSupport::BaseQtVersion *qtVersion) const; + Utils::FilePath clangPathFromNdk(const Utils::FilePath &ndkLocation) const; Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::BaseQtVersion *qtVersion) const; + Utils::FilePath gdbPathFromNdk(const ProjectExplorer::Abi &abi, const Utils::FilePath &ndkLocation) const; Utils::FilePath makePath(const QtSupport::BaseQtVersion *qtVersion) const; Utils::FilePath makePathFromNdk(const Utils::FilePath &ndkLocation) const; @@ -188,6 +191,11 @@ public: bool sdkFullyConfigured() const { return m_sdkFullyConfigured; }; void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; }; + bool isValidNdk(const QString &ndkLocation) const; + QStringList getCustomNdkList() const; + void addCustomNdk(const QString &customNdk); + void removeCustomNdk(const QString &customNdk); + private: static QString getDeviceProperty(const Utils::FilePath &adbToolPath, const QString &device, const QString &property); @@ -216,6 +224,7 @@ private: QStringList m_commonEssentialPkgs; SdkForQtVersions m_defaultSdkDepends; QList m_specificQtVersions; + QStringList m_customNdkList; bool m_sdkFullyConfigured = false; //caches @@ -237,6 +246,7 @@ public: static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name static void clearDefaultDevices(ProjectExplorer::Project *project); static void registerNewToolChains(); + static void registerCustomToolChainsAndDebuggers(); static void removeUnusedDebuggers(); static void removeOldToolChains(); static void updateAutomaticKitList(); diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 3eeb0150160..42511b893c3 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -133,6 +133,7 @@ private: bool sdkToolsOk() const; Utils::FilePath getDefaultSdkPath(); void showEvent(QShowEvent *event) override; + void addCustomNdkItem(); Ui_AndroidSettingsWidget *m_ui; AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr; @@ -352,6 +353,22 @@ void AndroidSettingsWidget::updateNdkList() m_ui->ndkListComboBox->clear(); for (const Ndk *ndk : m_sdkManager->installedNdkPackages()) m_ui->ndkListComboBox->addItem(ndk->installedLocation().toString()); + + for (const QString &ndk : m_androidConfig.getCustomNdkList()) { + if (m_androidConfig.isValidNdk(ndk)) + m_ui->ndkListComboBox->addItem(ndk); + else + m_androidConfig.removeCustomNdk(ndk); + } +} + +void AndroidSettingsWidget::addCustomNdkItem() +{ + const QString ndkPath = QDir::toNativeSeparators(m_ui->customNdkPathChooser->rawPath()); + m_androidConfig.addCustomNdk(ndkPath); + if (m_ui->ndkListComboBox->findData(ndkPath) == -1) + m_ui->ndkListComboBox->addItem(ndkPath); + m_ui->ndkListComboBox->setCurrentText(ndkPath); } AndroidSettingsWidget::AndroidSettingsWidget() @@ -435,8 +452,23 @@ AndroidSettingsWidget::AndroidSettingsWidget() connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged, this, &AndroidSettingsWidget::onSdkPathChanged); - connect(m_ui->ndkListComboBox, QOverload::of(&QComboBox::currentIndexChanged), - [this](const QString) { validateNdk(); }); + connect(m_ui->ndkListComboBox, + QOverload::of(&QComboBox::currentIndexChanged), + [this](const QString &ndk) { + validateNdk(); + m_ui->removeCustomNdkButton->setEnabled(m_androidConfig.getCustomNdkList().contains(ndk)); + }); + connect(m_ui->customNdkPathChooser, &Utils::PathChooser::rawPathChanged, this, [this]() { + const QString ndkPath = m_ui->customNdkPathChooser->rawPath(); + m_ui->addCustomNdkButton->setEnabled(m_androidConfig.isValidNdk(ndkPath)); + }); + connect(m_ui->addCustomNdkButton, &QPushButton::clicked, this, + &AndroidSettingsWidget::addCustomNdkItem); + connect(m_ui->removeCustomNdkButton, &QPushButton::clicked, this, [this]() { + m_androidConfig.removeCustomNdk(m_ui->ndkListComboBox->currentText()); + m_ui->ndkListComboBox->removeItem(m_ui->ndkListComboBox->currentIndex()); + }); + connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished, this, &AndroidSettingsWidget::updateAvds); connect(m_ui->AVDRefreshPushButton, &QAbstractButton::clicked, diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui index 5d149dddcf5..6d8272b7dfa 100644 --- a/src/plugins/android/androidsettingswidget.ui +++ b/src/plugins/android/androidsettingswidget.ui @@ -93,7 +93,7 @@ - + 0 0 @@ -106,21 +106,24 @@ - - - - Download Android SDK - - - - + - Android NDK list: + Add custom NDK: - + + + + + + + + + + + Automatically download Android SDK Tools to selected location. @@ -130,29 +133,74 @@ - + - - + + - + Android NDK list: - - + + + + Download Android SDK + + + + + + + + 20 + 0 + + + + + + + + false + - + 0 0 + + Add the selected custom NDK. The toolchains and debuggers will be created automatically. + + + Add + - + + + + + false + + + + 0 + 0 + + + + Remove the selected custom NDK. + + + Remove + + + @@ -351,6 +399,10 @@ QWidget

utils/pathchooser.h
1 + + editingFinished() + browsingFinished() + Utils::DetailsWidget diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 4f879d92491..2c45eba1e59 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -171,7 +171,7 @@ AndroidToolChainFactory::AndroidToolChainFactory() ToolChainList AndroidToolChainFactory::autoDetect(const ToolChainList &alreadyKnown) { - return autodetectToolChainsForNdk(alreadyKnown); + return autodetectToolChains(alreadyKnown); } static FilePath clangPlusPlusPath(const FilePath &clangPath) @@ -181,7 +181,7 @@ static FilePath clangPlusPlusPath(const FilePath &clangPath) QFileInfo(clangPath.toString()).baseName() + "++")); } -static QList androidQtVersionsWithUniqueNdk() +static QList uniqueNdksForCurrentQtVersions() { AndroidConfig config = AndroidConfigurations::currentConfig(); @@ -190,36 +190,40 @@ static QList androidQtVersionsWithUniqueNdk() return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE); }); - auto shouldRemove = [config](const QtSupport::BaseQtVersion *first, - const QtSupport::BaseQtVersion *second) { - return config.ndkLocation(first) == config.ndkLocation(second); - }; + QList uniqueNdks; + for (const QtSupport::BaseQtVersion *version : androidQtVersions) { + FilePath ndk = config.ndkLocation(version); + if (!uniqueNdks.contains(ndk)) + uniqueNdks.append(ndk); + } - QList::iterator it = std::unique(androidQtVersions.begin(), - androidQtVersions.end(), - shouldRemove); - androidQtVersions.erase(it, androidQtVersions.end()); - - return androidQtVersions; + return uniqueNdks; } -ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChainList &alreadyKnown) +ToolChainList AndroidToolChainFactory::autodetectToolChains(const ToolChainList &alreadyKnown) +{ + const QList uniqueNdks = uniqueNdksForCurrentQtVersions(); + return autodetectToolChainsFromNdks(alreadyKnown, uniqueNdks); +} + +ToolChainList AndroidToolChainFactory::autodetectToolChainsFromNdks( + const ToolChainList &alreadyKnown, + const QList &ndkLocations, + const bool isCustom) { QList result; - const QList androidQtVersions = androidQtVersionsWithUniqueNdk(); const AndroidConfig config = AndroidConfigurations::currentConfig(); - for (const QtSupport::BaseQtVersion *qtVersion : androidQtVersions) { - FilePath clangPath = config.clangPath(qtVersion); + for (const Utils::FilePath &ndkLocation : ndkLocations) { + qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:" << ndkLocation; + + FilePath clangPath = config.clangPathFromNdk(ndkLocation); if (!clangPath.exists()) { qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang" << clangPath; - return result; + continue; } - qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:" - << config.ndkLocation(qtVersion); - for (const Core::Id &lang : LanguageIds) { FilePath compilerCommand = clangPath; if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID) @@ -237,10 +241,11 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai const QString target = targetItr.key(); ToolChain *tc = findToolChain(compilerCommand, lang, target, alreadyKnown); - const QString displayName(QString("Android Clang (%1, %2, NDK %3)") + QLatin1String customStr = isCustom ? QLatin1String("Custom ") : QLatin1String(); + const QString displayName(customStr + QString("Android Clang (%1, %2, NDK %3)") .arg(ToolChainManager::displayNameOfLanguageId(lang), AndroidConfig::displayName(abi), - config.ndkVersion(qtVersion).toString())); + config.ndkVersion(ndkLocation).toString())); if (tc) { qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang; // make sure to update the toolchain with current name format @@ -249,7 +254,7 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai } else { qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang; auto atc = new AndroidToolChain(); - atc->setNdkLocation(config.ndkLocation(qtVersion)); + atc->setNdkLocation(ndkLocation); atc->setOriginalTargetTriple(target); atc->setLanguage(lang); atc->setTargetAbi(ClangTargets[target]); diff --git a/src/plugins/android/androidtoolchain.h b/src/plugins/android/androidtoolchain.h index 14ef9231be1..4002cef75fa 100644 --- a/src/plugins/android/androidtoolchain.h +++ b/src/plugins/android/androidtoolchain.h @@ -78,7 +78,10 @@ public: QString version; }; - static ToolChainList autodetectToolChainsForNdk(const ToolChainList &alreadyKnown); + static ToolChainList autodetectToolChains(const ToolChainList &alreadyKnown); + static ToolChainList autodetectToolChainsFromNdks(const ToolChainList &alreadyKnown, + const QList &ndkLocations, + const bool isCustom = false); }; } // namespace Internal From 41cb713370f81531effb72a3d3b1f19b90a2ca7d Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Fri, 28 Feb 2020 11:40:26 +0100 Subject: [PATCH 33/96] SubmitEditorWidget: Inline two small functions Change-Id: Ia9b2c451a587d418ccf39707c25d8aff062f6ed8 Reviewed-by: Orgad Shaneh --- src/plugins/vcsbase/submiteditorwidget.cpp | 14 ++------------ src/plugins/vcsbase/submiteditorwidget.h | 2 -- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/plugins/vcsbase/submiteditorwidget.cpp b/src/plugins/vcsbase/submiteditorwidget.cpp index e87a317719c..ad15a8ca9b0 100644 --- a/src/plugins/vcsbase/submiteditorwidget.cpp +++ b/src/plugins/vcsbase/submiteditorwidget.cpp @@ -622,16 +622,6 @@ void SubmitEditorWidget::checkAllToggled() d->m_ui.checkAllCheckBox->setTristate(false); } -void SubmitEditorWidget::checkAll() -{ - fileModel()->setAllChecked(true); -} - -void SubmitEditorWidget::uncheckAll() -{ - fileModel()->setAllChecked(false); -} - void SubmitEditorWidget::fileListCustomContextMenuRequested(const QPoint & pos) { // Execute menu offering to check/uncheck all @@ -642,11 +632,11 @@ void SubmitEditorWidget::fileListCustomContextMenuRequested(const QPoint & pos) QAction *uncheckAllAction = menu.addAction(tr("Unselect All")); QAction *action = menu.exec(d->m_ui.fileView->mapToGlobal(pos)); if (action == checkAllAction) { - checkAll(); + fileModel()->setAllChecked(true);; return; } if (action == uncheckAllAction) { - uncheckAll(); + fileModel()->setAllChecked(false); return; } } diff --git a/src/plugins/vcsbase/submiteditorwidget.h b/src/plugins/vcsbase/submiteditorwidget.h index 651775fe1b4..e19ab65c4de 100644 --- a/src/plugins/vcsbase/submiteditorwidget.h +++ b/src/plugins/vcsbase/submiteditorwidget.h @@ -124,8 +124,6 @@ protected slots: private: void updateCheckAllComboBox(); void checkAllToggled(); - void checkAll(); - void uncheckAll(); void triggerDiffSelected(); void diffActivated(const QModelIndex &index); From d76a2f4fcd44ff4371795163c458e80640f867cf Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Fri, 28 Feb 2020 15:09:35 +0100 Subject: [PATCH 34/96] Deduplicate elapsed time formatting While it's nice to see my code spreading, I still prefer to have it at one place. Change-Id: I7bdb13c47ed7e96227deeb14b0a8070aa40148de Reviewed-by: Orgad Shaneh --- src/libs/utils/stringutils.cpp | 10 ++++++++++ src/libs/utils/stringutils.h | 2 +- src/plugins/clangtools/clangtoolruncontrol.cpp | 8 +++----- src/plugins/cmakeprojectmanager/cmakeprocess.cpp | 8 +++----- src/plugins/cpptools/builtinindexingsupport.cpp | 6 +++--- src/plugins/projectexplorer/buildmanager.cpp | 8 +++----- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp index f73e9d81444..070abd79a1f 100644 --- a/src/libs/utils/stringutils.cpp +++ b/src/libs/utils/stringutils.cpp @@ -30,11 +30,13 @@ #include #include +#include #include #include #include #include #include +#include #include @@ -383,4 +385,12 @@ QString quoteAmpersands(const QString &text) return result.replace("&", "&&"); } +QString formatElapsedTime(qint64 elapsed) +{ + elapsed += 500; // round up + const QString format = QString::fromLatin1(elapsed >= 3600000 ? "h:mm:ss" : "mm:ss"); + const QString time = QTime(0, 0).addMSecs(elapsed).toString(format); + return QCoreApplication::translate("StringUtils", "Elapsed time: %1.").arg(time); +} + } // namespace Utils diff --git a/src/libs/utils/stringutils.h b/src/libs/utils/stringutils.h index d07a734a9b3..430b2a3fd80 100644 --- a/src/libs/utils/stringutils.h +++ b/src/libs/utils/stringutils.h @@ -100,6 +100,6 @@ T makeUniquelyNumbered(const T &preferred, const Container &reserved) return tryName; } - +QTCREATOR_UTILS_EXPORT QString formatElapsedTime(qint64 elapsed); } // namespace Utils diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index 2221f9a34b4..49bef96a7c5 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -345,11 +346,8 @@ void ClangToolRunWorker::stop() reportStopped(); // Print elapsed time since start - const QTime format = QTime(0, 0, 0, 0).addMSecs(m_elapsed.elapsed() + 500); - QString time = format.toString("h:mm:ss"); - if (time.startsWith("0:")) - time.remove(0, 2); // Don't display zero hours - appendMessage(tr("Elapsed time: %1.") .arg(time), NormalMessageFormat); + const QString elapsedTime = Utils::formatElapsedTime(m_elapsed.elapsed()); + appendMessage(elapsedTime, NormalMessageFormat); } void ClangToolRunWorker::analyzeNextFile() diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp index 8fce28e1ea6..2c603d7331d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -237,11 +238,8 @@ void CMakeProcess::handleProcessFinished(int code, QProcess::ExitStatus status) emit finished(code, status); - const QTime format = QTime(0, 0, 0, 0).addMSecs(m_elapsed.elapsed() + 500); - QString time = format.toString("h:mm:ss"); - if (time.startsWith("0:")) - time.remove(0, 2); // Don't display zero hours - Core::MessageManager::write(tr("Elapsed time: %1.") .arg(time)); + const QString elapsedTime = Utils::formatElapsedTime(m_elapsed.elapsed()); + Core::MessageManager::write(elapsedTime); } void CMakeProcess::checkForCancelled() diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index 484c3adcd58..9673a995f3f 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -173,9 +174,8 @@ void indexFindErrors(QFutureInterface &indexingFuture, indexingFuture.setProgressValue(files.size() - (files.size() - (i + 1))); } - const QTime format = QTime(0, 0, 0, 0).addMSecs(timer.elapsed() + 500); - const QString time = format.toString(QLatin1String("hh:mm:ss")); - qDebug("FindErrorsIndexing: Finished after %s.", qPrintable(time)); + const QString elapsedTime = Utils::formatElapsedTime(timer.elapsed()); + qDebug("FindErrorsIndexing: %s", qPrintable(elapsedTime)); } void index(QFutureInterface &indexingFuture, diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index 27c46a54a61..41bcc17ccc8 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -458,11 +459,8 @@ void BuildManager::updateTaskCount() void BuildManager::finish() { - const QTime format = QTime(0, 0, 0, 0).addMSecs(d->m_elapsed.elapsed() + 500); - QString time = format.toString("h:mm:ss"); - if (time.startsWith("0:")) - time.remove(0, 2); // Don't display zero hours - m_instance->addToOutputWindow(tr("Elapsed time: %1.") .arg(time), BuildStep::OutputFormat::NormalMessage); + const QString elapsedTime = Utils::formatElapsedTime(d->m_elapsed.elapsed()); + m_instance->addToOutputWindow(elapsedTime, BuildStep::OutputFormat::NormalMessage); QApplication::alert(ICore::mainWindow(), 3000); } From 6f35a662018b47737d4f0289df7d34f7bd3e54bb Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 28 Feb 2020 14:45:13 +0100 Subject: [PATCH 35/96] LanguageClient: clear compressed uri after requesting symbols Change-Id: I1247959d657c5449a37a9e2ac16380eb9b14afe0 Reviewed-by: Christian Stenger --- src/plugins/languageclient/documentsymbolcache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/languageclient/documentsymbolcache.cpp b/src/plugins/languageclient/documentsymbolcache.cpp index 21494a66936..4727c501e3d 100644 --- a/src/plugins/languageclient/documentsymbolcache.cpp +++ b/src/plugins/languageclient/documentsymbolcache.cpp @@ -78,6 +78,7 @@ void DocumentSymbolCache::requestSymbolsImpl() }); m_client->sendContent(request); } + m_compressedUris.clear(); } void DocumentSymbolCache::handleResponse(const DocumentUri &uri, From df2525a54e80e5bba840ba701063763332a5432c Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 28 Feb 2020 14:45:40 +0100 Subject: [PATCH 36/96] LanguageClient: request symbols for all compressed uris Change-Id: Ib6d08f7d4f1efaaa2b484af312599b8b338fbcf5 Reviewed-by: Christian Stenger --- src/plugins/languageclient/documentsymbolcache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/languageclient/documentsymbolcache.cpp b/src/plugins/languageclient/documentsymbolcache.cpp index 4727c501e3d..218758b66f7 100644 --- a/src/plugins/languageclient/documentsymbolcache.cpp +++ b/src/plugins/languageclient/documentsymbolcache.cpp @@ -66,7 +66,7 @@ void DocumentSymbolCache::requestSymbolsImpl() auto entry = m_cache.find(uri); if (entry != m_cache.end()) { emit gotSymbols(uri, entry.value()); - return; + continue; } const DocumentSymbolParams params((TextDocumentIdentifier(uri))); From 8a8c49eb2ebfbb4fc94207b304f8b785c28cf510 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 28 Feb 2020 15:54:54 +0100 Subject: [PATCH 37/96] ProjectExplorer: Simplify update logic after active target change Change-Id: Ia1d9366b1f2ff2b7ae02604bc43b38ca4b914c17 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/project.cpp | 1 + .../projectexplorer/projectexplorer.cpp | 41 ------------------- 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index af07fa7e5d6..5aa448b03b9 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -340,6 +340,7 @@ void Project::setActiveTarget(Target *target) (target && Utils::contains(d->m_targets, target))) { d->m_activeTarget = target; emit activeTargetChanged(d->m_activeTarget); + ProjectExplorerPlugin::updateActions(); } } diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 9e21e88fb6d..862ea2864a5 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -448,8 +448,6 @@ public: void projectAdded(ProjectExplorer::Project *pro); void projectRemoved(ProjectExplorer::Project *pro); void projectDisplayNameChanged(ProjectExplorer::Project *pro); - void startupProjectChanged(); // Calls updateRunAction - void activeTargetChanged(); void doUpdateRunActions(); @@ -727,8 +725,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er dd, &ProjectExplorerPluginPrivate::projectAdded); connect(sessionManager, &SessionManager::projectRemoved, dd, &ProjectExplorerPluginPrivate::projectRemoved); - connect(sessionManager, &SessionManager::startupProjectChanged, - dd, &ProjectExplorerPluginPrivate::startupProjectChanged); connect(sessionManager, &SessionManager::projectDisplayNameChanged, dd, &ProjectExplorerPluginPrivate::projectDisplayNameChanged); connect(sessionManager, &SessionManager::dependencyChanged, @@ -2922,43 +2918,6 @@ void ProjectExplorerPluginPrivate::projectDisplayNameChanged(Project *pro) updateActions(); } -void ProjectExplorerPluginPrivate::startupProjectChanged() -{ - static QPointer previousStartupProject = nullptr; - Project *project = SessionManager::startupProject(); - if (project == previousStartupProject) - return; - - if (previousStartupProject) { - disconnect(previousStartupProject.data(), &Project::activeTargetChanged, - this, &ProjectExplorerPluginPrivate::activeTargetChanged); - } - - previousStartupProject = project; - - if (project) { - connect(project, &Project::activeTargetChanged, - this, &ProjectExplorerPluginPrivate::activeTargetChanged); - } - - activeTargetChanged(); - updateActions(); -} - -void ProjectExplorerPluginPrivate::activeTargetChanged() -{ - static QPointer previousTarget = nullptr; - Target *target = nullptr; - Project *startupProject = SessionManager::startupProject(); - if (startupProject) - target = startupProject->activeTarget(); - if (target == previousTarget) - return; - - previousTarget = target; - updateActions(); -} - void ProjectExplorerPluginPrivate::updateDeployActions() { Project *project = SessionManager::startupProject(); From b718f47893a7aa3c4d2daec8488cdf3c3c773ea1 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 28 Feb 2020 14:46:11 +0100 Subject: [PATCH 38/96] LanguageClient: Request symbols in outline combo box constructor Change-Id: Ib7bc4f828b6e3abc4344ff96b7561015ac0cf66f Reviewed-by: Christian Stenger --- src/plugins/languageclient/languageclientoutline.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/languageclient/languageclientoutline.cpp b/src/plugins/languageclient/languageclientoutline.cpp index 550e391dda4..96555092294 100644 --- a/src/plugins/languageclient/languageclientoutline.cpp +++ b/src/plugins/languageclient/languageclientoutline.cpp @@ -299,6 +299,8 @@ OutlineComboBox::OutlineComboBox(Client *client, TextEditor::BaseTextEditor *edi connect(m_editorWidget, &TextEditor::TextEditorWidget::cursorPositionChanged, this, &OutlineComboBox::updateEntry); connect(this, QOverload::of(&QComboBox::activated), this, &OutlineComboBox::activateEntry); + + requestSymbols(); } void OutlineComboBox::updateModel(const DocumentUri &resultUri, const DocumentSymbolsResult &result) From 26e4a2a7582da1f272b79940bca81b10639de0b9 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 2 Mar 2020 09:41:58 +0100 Subject: [PATCH 39/96] Qbs: Fix build target key of project part The build target key is the basic mapping of project part to run configuration and this went out of sync with the latest refactorings of the Qbs project manager. This fixes execution of tests inside the AutoTest plugin for qbs based projects. Change-Id: I7d7a703a341df98a015f9c83d3c2a320d46779c3 Reviewed-by: Christian Kandeler --- src/plugins/qbsprojectmanager/qbsproject.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 3bbf4501283..090bfae0afd 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -170,6 +170,12 @@ static bool supportsNodeAction(ProjectAction action, const Node *node) return false; } +static QString buildKeyValue(const QJsonObject &product) +{ + return product.value("name").toString() + '.' + + product.value("multiplex-configuration-id").toString(); +} + QbsBuildSystem::QbsBuildSystem(QbsBuildConfiguration *bc) : BuildSystem(bc->target()), m_session(new QbsSession(this)), @@ -907,7 +913,7 @@ static RawProjectParts generateProjectParts( rpp.setProjectFileLocation(location.value("file-path").toString(), location.value("line").toInt(), location.value("column").toInt()); - rpp.setBuildSystemTarget(productName); + rpp.setBuildSystemTarget(buildKeyValue(prd)); rpp.setBuildTargetType(prd.value("is-runnable").toBool() ? BuildTargetType::Executable : BuildTargetType::Library); @@ -1069,8 +1075,7 @@ void QbsBuildSystem::updateApplicationTargets() } } BuildTargetInfo bti; - bti.buildKey = productData.value("name").toString() + '.' - + productData.value("multiplex-configuration-id").toString(); + bti.buildKey = buildKeyValue(productData); bti.targetFilePath = FilePath::fromString(targetFile); bti.projectFilePath = FilePath::fromString(projectFile); bti.isQtcRunnable = isQtcRunnable; // Fixed up below. From 7dd8858fa2cdb66cf8ccfb13d26110b5b77472f6 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 28 Feb 2020 12:42:53 +0100 Subject: [PATCH 40/96] CMake: Remove unused CMakeBuildConfiguration::emitBuildTypeChanged() Change-Id: I4cb93a7f89ff4bcada2083bebd8e9e96770f4818 Reviewed-by: Tobias Hunger --- src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp | 5 ----- src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index df0892eb26c..9c9d60cdba2 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -305,11 +305,6 @@ void CMakeBuildConfiguration::clearError(ForceEnabledChanged fec) } } -void CMakeBuildConfiguration::emitBuildTypeChanged() -{ - emit buildTypeChanged(); -} - static CMakeConfig removeDuplicates(const CMakeConfig &config) { CMakeConfig result; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index 9592fa41694..082b74c580e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -56,8 +56,6 @@ class CMakeBuildConfiguration final : public ProjectExplorer::BuildConfiguration ~CMakeBuildConfiguration() final; public: - void emitBuildTypeChanged(); - CMakeConfig configurationForCMake() const; CMakeConfig configurationFromCMake() const; From 2ce03eae18e9432bffd612a33f2b8be46041f87c Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 2 Mar 2020 11:19:47 +0100 Subject: [PATCH 41/96] QtSupport: Relax ABI matching when fixing a Qt kit E.g. consider MSVC 2019 a candidate when filling in the toolchain in a Qt kit that doesn't have one yet. Task-number: QTCREATORBUG-23653 Change-Id: I90aeb6f80c8f95faafa1e345f51fde77ddd0d2bd Reviewed-by: Kai Koehne --- src/plugins/qtsupport/qtkitinformation.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index 1e4037c4477..6c5a8b90cb4 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -222,13 +222,25 @@ void QtKitAspect::fix(ProjectExplorer::Kit *k) if (ToolChainKitAspect::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID)) return; const QString spec = version->mkspec(); - const QList possibleTcs = ToolChainManager::toolChains( + QList possibleTcs = ToolChainManager::toolChains( [version](const ToolChain *t) { return t->isValid() && t->language() == Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID) - && version->qtAbis().contains(t->targetAbi()); + && contains(version->qtAbis(), [t](const Abi &qtAbi) { + return qtAbi.isFullyCompatibleWith(t->targetAbi()); + }); }); if (!possibleTcs.isEmpty()) { + // Prefer exact matches. + // TODO: We should probably prefer the compiler with the highest version number instead, + // but this information is currently not exposed by the ToolChain class. + sort(possibleTcs, [version](const ToolChain *tc1, const ToolChain *tc2) { + const QVector &qtAbis = version->qtAbis(); + const bool tc1ExactMatch = qtAbis.contains(tc1->targetAbi()); + const bool tc2ExactMatch = qtAbis.contains(tc2->targetAbi()); + return tc1ExactMatch && !tc2ExactMatch; + }); + const QList goodTcs = Utils::filtered(possibleTcs, [&spec](const ToolChain *t) { return t->suggestedMkspecList().contains(spec); From 3c4acafdb60bb6497b3867ef1d4238e1de29cae0 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 27 Feb 2020 14:43:35 +0100 Subject: [PATCH 42/96] Editor: Fix crash on exit Make sure no FontSettingsPageWidget is created when changing the font zoom level in the editor. Otherwise it will crash in the font combo box when closing Qt Creator. Since we can't use the save and emit mechanism from the widget anymore move it to TextEditorSettings Change-Id: I1eb87bbae3cf2b802fb15981e7fc2203106d5565 Reviewed-by: Christian Stenger --- src/plugins/texteditor/fontsettingspage.cpp | 5 ++--- src/plugins/texteditor/texteditorsettings.cpp | 17 +++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp index c192192bdb8..f0e1bca968f 100644 --- a/src/plugins/texteditor/fontsettingspage.cpp +++ b/src/plugins/texteditor/fontsettingspage.cpp @@ -642,9 +642,8 @@ FontSettingsPage::FontSettingsPage(FontSettings *fontSettings, const FormatDescr void FontSettingsPage::setFontZoom(int zoom) { - auto w = static_cast(widget()); - w->m_ui.zoomSpinBox->setValue(zoom); - w->saveSettings(); + if (m_widget) + static_cast(m_widget.data())->m_ui.zoomSpinBox->setValue(zoom); } } // TextEditor diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index ed822f20801..eb75f8aeb9c 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -514,21 +514,26 @@ Core::Id TextEditorSettings::languageId(const QString &mimeType) return d->m_mimeTypeToLanguage.value(mimeType); } +static void setFontZoom(int zoom) +{ + d->m_fontSettingsPage.setFontZoom(zoom); + d->m_fontSettings.setFontZoom(zoom); + d->m_fontSettings.toSettings(Core::ICore::settings()); + emit m_instance->fontSettingsChanged(d->m_fontSettings); +} + int TextEditorSettings::increaseFontZoom(int step) { const int previousZoom = d->m_fontSettings.fontZoom(); const int newZoom = qMax(10, previousZoom + step); - if (newZoom != previousZoom) { - d->m_fontSettings.setFontZoom(newZoom); - d->m_fontSettingsPage.setFontZoom(newZoom); - } + if (newZoom != previousZoom) + setFontZoom(newZoom); return newZoom; } void TextEditorSettings::resetFontZoom() { - d->m_fontSettings.setFontZoom(100); - d->m_fontSettingsPage.setFontZoom(100); + setFontZoom(100); } } // TextEditor From 6d169ae7aa6907066c23871d52316ac6d83226e9 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Fri, 28 Feb 2020 13:31:40 +0100 Subject: [PATCH 43/96] CMake Build: Less file creating during configure Change-Id: I263853f0a903d81a8d869bc4f5683e1a1b0078e2 Reviewed-by: Tobias Hunger --- cmake/QtCreatorAPI.cmake | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/cmake/QtCreatorAPI.cmake b/cmake/QtCreatorAPI.cmake index 751f2d4f6f0..7dd104caf00 100644 --- a/cmake/QtCreatorAPI.cmake +++ b/cmake/QtCreatorAPI.cmake @@ -382,14 +382,12 @@ function(enable_pch target) endfunction() if (NOT TARGET QtCreatorPchGui AND NOT TARGET QtCreatorPchConsole) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c_cpp.in "/*empty file*/") - configure_file( - ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c_cpp.in - ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.cpp) - configure_file( - ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c_cpp.in - ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c) - + file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.c + CONTENT "/*empty file*/") + file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.cpp + CONTENT "/*empty file*/") _add_pch_target(QtCreatorPchGui "${PROJECT_SOURCE_DIR}/src/shared/qtcreator_gui_pch.h" Qt5::Widgets) _add_pch_target(QtCreatorPchConsole @@ -728,9 +726,10 @@ function(add_qtc_plugin target_name) string(REGEX REPLACE "^.*=" "" json_value ${_arg_PLUGIN_JSON_IN}) string(REPLACE "$$${json_key}" "${json_value}" plugin_json_in ${plugin_json_in}) endif() - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${name}.json.cmakein" ${plugin_json_in}) - - configure_file("${CMAKE_CURRENT_BINARY_DIR}/${name}.json.cmakein" "${name}.json") + string(CONFIGURE "${plugin_json_in}" plugin_json) + file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.json" + CONTENT "${plugin_json}") endif() add_library(${target_name} SHARED ${_arg_SOURCES}) From 6164378372527db9f4c22f03f5ec18b5818de03a Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 28 Feb 2020 16:58:37 +0100 Subject: [PATCH 44/96] ProjectExplorer: Replace a few foreach() Change-Id: I445cdfaac13ac894be3cd6fc8c20b4a09f460a01 Reviewed-by: Christian Kandeler --- .../buildsettingspropertiespage.cpp | 2 +- .../miniprojecttargetselector.cpp | 18 +++++++++--------- src/plugins/projectexplorer/project.cpp | 6 +++--- src/plugins/projectexplorer/session.cpp | 4 ++-- src/plugins/projectexplorer/target.cpp | 6 +++--- src/plugins/projectexplorer/target.h | 6 +++--- src/plugins/valgrind/memchecktool.cpp | 2 +- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp index 924adfa6784..b0f4ce758a8 100644 --- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp @@ -244,7 +244,7 @@ QString BuildSettingsWidget::uniqueName(const QString & name) QString result = name.trimmed(); if (!result.isEmpty()) { QStringList bcNames; - foreach (BuildConfiguration *bc, m_target->buildConfigurations()) { + for (BuildConfiguration *bc : m_target->buildConfigurations()) { if (bc == m_buildConfiguration) continue; bcNames.append(bc->displayName()); diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp index 4d47ff01914..342c877526f 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp +++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp @@ -1160,11 +1160,11 @@ void MiniProjectTargetSelector::addedTarget(Target *target) m_listWidgets[TARGET]->addProjectConfiguration(target); - foreach (BuildConfiguration *bc, target->buildConfigurations()) + for (BuildConfiguration *bc : target->buildConfigurations()) addedBuildConfiguration(bc); - foreach (DeployConfiguration *dc, target->deployConfigurations()) + for (DeployConfiguration *dc : target->deployConfigurations()) addedDeployConfiguration(dc); - foreach (RunConfiguration *rc, target->runConfigurations()) + for (RunConfiguration *rc : target->runConfigurations()) addedRunConfiguration(rc); } @@ -1175,11 +1175,11 @@ void MiniProjectTargetSelector::removedTarget(Target *target) m_listWidgets[TARGET]->removeProjectConfiguration(target); - foreach (BuildConfiguration *bc, target->buildConfigurations()) + for (BuildConfiguration *bc : target->buildConfigurations()) removedBuildConfiguration(bc); - foreach (DeployConfiguration *dc, target->deployConfigurations()) + for (DeployConfiguration *dc : target->deployConfigurations()) removedDeployConfiguration(dc); - foreach (RunConfiguration *rc, target->runConfigurations()) + for (RunConfiguration *rc : target->runConfigurations()) removedRunConfiguration(rc); } @@ -1364,17 +1364,17 @@ void MiniProjectTargetSelector::activeTargetChanged(Target *target) if (m_target) { QList bl; - foreach (BuildConfiguration *bc, target->buildConfigurations()) + for (BuildConfiguration *bc : target->buildConfigurations()) bl.append(bc); m_listWidgets[BUILD]->setProjectConfigurations(bl, target->activeBuildConfiguration()); QList dl; - foreach (DeployConfiguration *dc, target->deployConfigurations()) + for (DeployConfiguration *dc : target->deployConfigurations()) dl.append(dc); m_listWidgets[DEPLOY]->setProjectConfigurations(dl, target->activeDeployConfiguration()); QList rl; - foreach (RunConfiguration *rc, target->runConfigurations()) + for (RunConfiguration *rc : target->runConfigurations()) rl.append(rc); m_listWidgets[RUN]->setProjectConfigurations(rl, target->activeRunConfiguration()); diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 5aa448b03b9..292f81a4cd4 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -401,7 +401,7 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget) QStringList runconfigurationError; const Project * const project = newTarget->project(); - foreach (BuildConfiguration *sourceBc, sourceTarget->buildConfigurations()) { + for (BuildConfiguration *sourceBc : sourceTarget->buildConfigurations()) { ProjectMacroExpander expander(project->projectFilePath(), project->displayName(), newTarget->kit(), sourceBc->displayName(), sourceBc->buildType()); @@ -423,7 +423,7 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget) SessionManager::setActiveBuildConfiguration(newTarget, bcs.first(), SetActive::NoCascade); } - foreach (DeployConfiguration *sourceDc, sourceTarget->deployConfigurations()) { + for (DeployConfiguration *sourceDc : sourceTarget->deployConfigurations()) { DeployConfiguration *newDc = DeployConfigurationFactory::clone(newTarget, sourceDc); if (!newDc) { deployconfigurationError << sourceDc->displayName(); @@ -440,7 +440,7 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget) SessionManager::setActiveDeployConfiguration(newTarget, dcs.first(), SetActive::NoCascade); } - foreach (RunConfiguration *sourceRc, sourceTarget->runConfigurations()) { + for (RunConfiguration *sourceRc : sourceTarget->runConfigurations()) { RunConfiguration *newRc = RunConfigurationFactory::clone(newTarget, sourceRc); if (!newRc) { runconfigurationError << sourceRc->displayName(); diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index bb3bc8b8dca..f76d15531e8 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -323,7 +323,7 @@ void SessionManager::setActiveBuildConfiguration(Target *target, BuildConfigurat if (!otherTarget || otherTarget->kit()->id() != kitId) continue; - foreach (BuildConfiguration *otherBc, otherTarget->buildConfigurations()) { + for (BuildConfiguration *otherBc : otherTarget->buildConfigurations()) { if (otherBc->displayName() == name) { otherTarget->setActiveBuildConfiguration(otherBc); break; @@ -351,7 +351,7 @@ void SessionManager::setActiveDeployConfiguration(Target *target, DeployConfigur if (!otherTarget || otherTarget->kit()->id() != kitId) continue; - foreach (DeployConfiguration *otherDc, otherTarget->deployConfigurations()) { + for (DeployConfiguration *otherDc : otherTarget->deployConfigurations()) { if (otherDc->displayName() == name) { otherTarget->setActiveDeployConfiguration(otherDc); break; diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index fc0b87e7271..b3f04c646f0 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -314,7 +314,7 @@ bool Target::removeBuildConfiguration(BuildConfiguration *bc) return true; } -QList Target::buildConfigurations() const +const QList Target::buildConfigurations() const { return d->m_buildConfigurations; } @@ -385,7 +385,7 @@ bool Target::removeDeployConfiguration(DeployConfiguration *dc) return true; } -QList Target::deployConfigurations() const +const QList Target::deployConfigurations() const { return d->m_deployConfigurations; } @@ -406,7 +406,7 @@ void Target::setActiveDeployConfiguration(DeployConfiguration *dc) updateDeviceState(); } -QList Target::runConfigurations() const +const QList Target::runConfigurations() const { return d->m_runConfigurations; } diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h index 2e452fac22c..1e31c47bda6 100644 --- a/src/plugins/projectexplorer/target.h +++ b/src/plugins/projectexplorer/target.h @@ -71,18 +71,18 @@ public: void addBuildConfiguration(BuildConfiguration *bc); bool removeBuildConfiguration(BuildConfiguration *bc); - QList buildConfigurations() const; + const QList buildConfigurations() const; BuildConfiguration *activeBuildConfiguration() const; // DeployConfiguration void addDeployConfiguration(DeployConfiguration *dc); bool removeDeployConfiguration(DeployConfiguration *dc); - QList deployConfigurations() const; + const QList deployConfigurations() const; DeployConfiguration *activeDeployConfiguration() const; // Running - QList runConfigurations() const; + const QList runConfigurations() const; void addRunConfiguration(RunConfiguration *rc); void removeRunConfiguration(RunConfiguration *rc); diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index fd8025fc8b1..c5073bd40f1 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -350,7 +350,7 @@ bool MemcheckErrorFilterProxyModel::filterAcceptsRow(int sourceRow, const QModel if (file.isExecutable()) validFolders << file.remoteDirectory(); } - foreach (BuildConfiguration *config, target->buildConfigurations()) + for (BuildConfiguration *config : target->buildConfigurations()) validFolders << config->buildDirectory().toString(); } } From 1e8f2623224bee60043b1eb33562c25e1d9d0215 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 2 Mar 2020 12:57:48 +0100 Subject: [PATCH 45/96] CMake: Compile fix Amend 7dd8858fa2c. Was not unusused after all. Change-Id: I18c5f5033ebd8b3e19ebdf4718465d6b4ba6acf4 Reviewed-by: Christian Kandeler --- src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index fa8396e92d8..2045a84cd28 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -497,7 +497,7 @@ void CMakeBuildSystem::updateProjectData() updateQmlJSCodeModel(); } - emit m_buildConfiguration->emitBuildTypeChanged(); + emit m_buildConfiguration->buildTypeChanged(); m_buildDirManager.resetData(); From d91d4aa75904d8da2c32714f08e07771bb331a43 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 25 Feb 2020 14:28:14 +0100 Subject: [PATCH 46/96] Dumper: remove unused imports Change-Id: I447c9697dbd631ab26358c193c274484e70a908d Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 2 -- share/qtcreator/debugger/gdbbridge.py | 1 - 2 files changed, 3 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 7db5c7084dc..0a3253a758b 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -25,7 +25,6 @@ import os import codecs -import copy import collections import struct import sys @@ -33,7 +32,6 @@ import base64 import re import time import inspect -import threading from utils import DisplayFormat, TypeCode try: diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index c88811ae927..a79e9edb180 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -35,7 +35,6 @@ import re import sys import struct import tempfile -import types from dumper import DumperBase, Children, toInteger, TopLevelItem from utils import TypeCode From 472797a1d1c2d0e8c9a5159fb7c123b2a6f41b97 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 24 Feb 2020 15:10:47 +0100 Subject: [PATCH 47/96] Dumper: avoid redundant labeling Change-Id: I85581cfe34a60e7f8a3e3590358443a15b7d2d4c Reviewed-by: hjk Reviewed-by: Cristian Maureira-Fredes Reviewed-by: David Schulz --- share/qtcreator/debugger/cdbbridge.py | 26 ++-- share/qtcreator/debugger/dumper.py | 198 +++++++++++------------- share/qtcreator/debugger/gdbbridge.py | 40 ++--- share/qtcreator/debugger/lldbbridge.py | 18 +-- share/qtcreator/debugger/misctypes.py | 4 +- share/qtcreator/debugger/opencvtypes.py | 6 +- share/qtcreator/debugger/qttypes.py | 58 +++---- share/qtcreator/debugger/stdtypes.py | 34 ++-- share/qtcreator/debugger/utils.py | 72 ++++----- 9 files changed, 220 insertions(+), 236 deletions(-) diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index cee6ea9c406..f73140dc0fb 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -50,19 +50,19 @@ class FakeVoidType(cdbext.Type): def code(self): if self.typeName.endswith('*'): - return TypeCode.TypeCodePointer + return TypeCode.Pointer if self.typeName.endswith(']'): - return TypeCode.TypeCodeArray - return TypeCode.TypeCodeVoid + return TypeCode.Array + return TypeCode.Void def unqualified(self): return self def target(self): code = self.code() - if code == TypeCode.TypeCodePointer: + if code == TypeCode.Pointer: return FakeVoidType(self.typeName[:-1], self.dumper) - if code == TypeCode.TypeCodeVoid: + if code == TypeCode.Void: return self try: return FakeVoidType(self.typeName[:self.typeName.rindex('[')], self.dumper) @@ -109,7 +109,7 @@ class Dumper(DumperBase): val.type = self.fromNativeType(nativeValue.type()) # There is no cdb api for the size of bitfields. # Workaround this issue by parsing the native debugger text for integral types. - if val.type.code == TypeCode.TypeCodeIntegral: + if val.type.code == TypeCode.Integral: integerString = nativeValue.nativeDebuggerValue() if integerString == 'true': val.ldata = int(1).to_bytes(1, byteorder='little') @@ -132,7 +132,7 @@ class Dumper(DumperBase): except: # read raw memory in case the integerString can not be interpreted pass - if val.type.code == TypeCode.TypeCodeEnum: + if val.type.code == TypeCode.Enum: val.ldisplay = self.enumValue(nativeValue) val.isBaseClass = val.name == val.type.name val.nativeValue = nativeValue @@ -164,14 +164,14 @@ class Dumper(DumperBase): nativeType = FakeVoidType(nativeType.name(), self) code = nativeType.code() - if code == TypeCode.TypeCodePointer: + if code == TypeCode.Pointer: if not nativeType.name().startswith(''): targetType = self.lookupType(nativeType.targetName(), nativeType.moduleId()) if targetType is not None: return self.createPointerType(targetType) - code = TypeCode.TypeCodeFunction + code = TypeCode.Function - if code == TypeCode.TypeCodeArray: + if code == TypeCode.Array: # cdb reports virtual function tables as arrays those ar handled separetly by # the DumperBase. Declare those types as structs prevents a lookup to a # none existing type @@ -179,7 +179,7 @@ class Dumper(DumperBase): targetType = self.lookupType(nativeType.targetName(), nativeType.moduleId()) if targetType is not None: return self.createArrayType(targetType, nativeType.arrayElements()) - code = TypeCode.TypeCodeStruct + code = TypeCode.Struct tdata = self.TypeData(self) tdata.name = nativeType.name() @@ -188,12 +188,12 @@ class Dumper(DumperBase): tdata.code = code tdata.moduleName = nativeType.module() self.registerType(typeId, tdata) # Prevent recursion in fields. - if code == TypeCode.TypeCodeStruct: + if code == TypeCode.Struct: tdata.lfields = lambda value: \ self.listFields(nativeType, value) tdata.lalignment = lambda: \ self.nativeStructAlignment(nativeType) - if code == TypeCode.TypeCodeEnum: + if code == TypeCode.Enum: tdata.enumDisplay = lambda intval, addr, form: \ self.nativeTypeEnumDisplay(nativeType, intval, form) tdata.templateArguments = self.listTemplateParameters(nativeType.name()) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 0a3253a758b..90ce78887ce 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -261,7 +261,7 @@ class DumperBase(): def resetCaches(self): # This is a cache mapping from 'type name' to 'display alternatives'. - self.qqFormats = {'QVariant (QVariantMap)': [DisplayFormat.CompactMapFormat]} + self.qqFormats = {'QVariant (QVariantMap)': [DisplayFormat.CompactMap]} # This is a cache of all known dumpers. self.qqDumpers = {} # Direct type match @@ -439,7 +439,7 @@ class DumperBase(): tdata.name = typeId tdata.typeId = typeId tdata.lbitsize = 16 - tdata.code = TypeCode.TypeCodeIntegral + tdata.code = TypeCode.Integral self.registerType(typeId, tdata) typeId = 'QChar' @@ -447,7 +447,7 @@ class DumperBase(): tdata.name = typeId tdata.typeId = typeId tdata.lbitsize = 16 - tdata.code = TypeCode.TypeCodeStruct + tdata.code = TypeCode.Struct tdata.lfields = [self.Field(dumper=self, name='ucs', type='unsigned short', bitsize=16, bitpos=0)] tdata.lalignment = 2 @@ -628,14 +628,12 @@ class DumperBase(): return elided, self.readMemory(data, shown) def putCharArrayValue(self, data, size, charSize, - displayFormat=DisplayFormat.AutomaticFormat): + displayFormat=DisplayFormat.Automatic): bytelen = size * charSize elided, shown = self.computeLimit(bytelen, self.displayStringLimit) mem = self.readMemory(data, shown) if charSize == 1: - if displayFormat in ( - DisplayFormat.Latin1StringFormat, - DisplayFormat.SeparateLatin1StringFormat): + if displayFormat in (DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String): encodingType = 'latin1' else: encodingType = 'utf8' @@ -650,14 +648,14 @@ class DumperBase(): self.putValue(mem, encodingType, elided=elided) if displayFormat in ( - DisplayFormat.SeparateLatin1StringFormat, - DisplayFormat.SeparateUtf8StringFormat, - DisplayFormat.SeparateFormat): + DisplayFormat.SeparateLatin1String, + DisplayFormat.SeparateUtf8String, + DisplayFormat.Separate): elided, shown = self.computeLimit(bytelen, 100000) self.putDisplay(encodingType + ':separate', self.readMemory(data, shown)) def putCharArrayHelper(self, data, size, charType, - displayFormat=DisplayFormat.AutomaticFormat, + displayFormat=DisplayFormat.Automatic, makeExpandable=True): charSize = charType.size() self.putCharArrayValue(data, size, charSize, displayFormat=displayFormat) @@ -1117,7 +1115,7 @@ class DumperBase(): n = arrayByteSize // innerType.size() p = value.address() - if displayFormat != DisplayFormat.RawFormat and p: + if displayFormat != DisplayFormat.Raw and p: if innerType.name in ( 'char', 'wchar_t', @@ -1173,7 +1171,7 @@ class DumperBase(): def tryPutPrettyItem(self, typeName, value): value.check() - if self.useFancy and self.currentItemFormat() != DisplayFormat.RawFormat: + if self.useFancy and self.currentItemFormat() != DisplayFormat.Raw: self.putType(typeName) nsStrippedType = self.stripNamespaceFromType(typeName)\ @@ -1219,7 +1217,7 @@ class DumperBase(): # This is shared by pointer and array formatting. def tryPutSimpleFormattedPointer(self, ptr, typeName, innerType, displayFormat, limit): - if displayFormat == DisplayFormat.AutomaticFormat: + if displayFormat == DisplayFormat.Automatic: if innerType.name in ('char', 'signed char', 'unsigned char', 'CHAR'): # Use UTF-8 as default for char *. self.putType(typeName) @@ -1239,45 +1237,45 @@ class DumperBase(): self.putValue(data, 'ucs4', elided=elided) return True - if displayFormat == DisplayFormat.Latin1StringFormat: + if displayFormat == DisplayFormat.Latin1String: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 1, limit) self.putValue(data, 'latin1', elided=elided) return True - if displayFormat == DisplayFormat.SeparateLatin1StringFormat: + if displayFormat == DisplayFormat.SeparateLatin1String: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 1, limit) self.putValue(data, 'latin1', elided=elided) self.putDisplay('latin1:separate', data) return True - if displayFormat == DisplayFormat.Utf8StringFormat: + if displayFormat == DisplayFormat.Utf8String: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 1, limit) self.putValue(data, 'utf8', elided=elided) return True - if displayFormat == DisplayFormat.SeparateUtf8StringFormat: + if displayFormat == DisplayFormat.SeparateUtf8String: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 1, limit) self.putValue(data, 'utf8', elided=elided) self.putDisplay('utf8:separate', data) return True - if displayFormat == DisplayFormat.Local8BitStringFormat: + if displayFormat == DisplayFormat.Local8BitString: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 1, limit) self.putValue(data, 'local8bit', elided=elided) return True - if displayFormat == DisplayFormat.Utf16StringFormat: + if displayFormat == DisplayFormat.Utf16String: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 2, limit) self.putValue(data, 'utf16', elided=elided) return True - if displayFormat == DisplayFormat.Ucs4StringFormat: + if displayFormat == DisplayFormat.Ucs4String: self.putType(typeName) (elided, data) = self.encodeCArray(ptr, 4, limit) self.putValue(data, 'ucs4', elided=elided) @@ -1339,7 +1337,7 @@ class DumperBase(): self.putNumChild(0) return - if displayFormat == DisplayFormat.RawFormat: + if displayFormat == DisplayFormat.Raw: # Explicitly requested bald pointer. #DumperBase.warn('RAW') self.putType(typeName) @@ -1352,23 +1350,21 @@ class DumperBase(): return limit = self.displayStringLimit - if displayFormat in ( - DisplayFormat.SeparateLatin1StringFormat, - DisplayFormat.SeparateUtf8StringFormat): + if displayFormat in (DisplayFormat.SeparateLatin1String, DisplayFormat.SeparateUtf8String): limit = 1000000 if self.tryPutSimpleFormattedPointer(pointer, typeName, innerType, displayFormat, limit): self.putNumChild(1) return - if DisplayFormat.Array10Format <= displayFormat and displayFormat <= DisplayFormat.Array1000Format: - n = (10, 100, 1000, 10000)[displayFormat - DisplayFormat.Array10Format] + if DisplayFormat.Array10 <= displayFormat and displayFormat <= DisplayFormat.Array1000: + n = (10, 100, 1000, 10000)[displayFormat - DisplayFormat.Array10] self.putType(typeName) self.putItemCount(n) self.putArrayData(value.pointer(), n, innerType) return - if innerType.code == TypeCode.TypeCodeFunction: + if innerType.code == TypeCode.Function: # A function pointer. self.putSymbolValue(pointer) self.putType(typeName) @@ -2124,12 +2120,12 @@ class DumperBase(): break def currentItemFormat(self, typeName=None): - displayFormat = self.formats.get(self.currentIName, DisplayFormat.AutomaticFormat) - if displayFormat == DisplayFormat.AutomaticFormat: + displayFormat = self.formats.get(self.currentIName, DisplayFormat.Automatic) + if displayFormat == DisplayFormat.Automatic: if typeName is None: typeName = self.currentType.value needle = None if typeName is None else self.stripForFormat(typeName) - displayFormat = self.typeformats.get(needle, DisplayFormat.AutomaticFormat) + displayFormat = self.typeformats.get(needle, DisplayFormat.Automatic) return displayFormat def putSubItem(self, component, value): # -> ReportItem @@ -2181,7 +2177,7 @@ class DumperBase(): if n > maxNumChild: self.putField('plotelided', n) # FIXME: Act on that in frontend n = maxNumChild - if self.currentItemFormat() == DisplayFormat.ArrayPlotFormat and innerType.isSimpleType(): + if self.currentItemFormat() == DisplayFormat.ArrayPlot and innerType.isSimpleType(): enc = innerType.simpleEncoding() if enc: self.putField('editencoding', enc) @@ -2221,7 +2217,7 @@ class DumperBase(): def extractPointer(self, value): try: - if value.type.code == TypeCode.TypeCodeArray: + if value.type.code == TypeCode.Array: return value.address() except: pass @@ -2318,8 +2314,8 @@ class DumperBase(): shadowed = {} for value in variables: if value.name == 'argv': - if value.type.code == TypeCode.TypeCodePointer: - if value.type.ltarget.code == TypeCode.TypeCodePointer: + if value.type.code == TypeCode.Pointer: + if value.type.ltarget.code == TypeCode.Pointer: if value.type.ltarget.ltarget.name == 'char': self.putSpecialArgv(value) continue @@ -2676,19 +2672,19 @@ class DumperBase(): # Try on possibly typedefed type first. if self.tryPutPrettyItem(typeName, value): - if typeobj.code == TypeCode.TypeCodePointer: + if typeobj.code == TypeCode.Pointer: self.putOriginalAddress(value.address()) else: self.putAddress(value.address()) return - if typeobj.code == TypeCode.TypeCodeTypedef: + if typeobj.code == TypeCode.Typedef: #DumperBase.warn('TYPEDEF VALUE: %s' % value.stringify()) self.putItem(value.detypedef()) self.putBetterType(typeName) return - if typeobj.code == TypeCode.TypeCodePointer: + if typeobj.code == TypeCode.Pointer: self.putFormattedPointer(value) if value.summary and self.useFancy: self.putValue(self.hexencode(value.summary), 'utf8:1:0') @@ -2696,26 +2692,26 @@ class DumperBase(): self.putAddress(value.address()) - if typeobj.code == TypeCode.TypeCodeFunction: + if typeobj.code == TypeCode.Function: #DumperBase.warn('FUNCTION VALUE: %s' % value) self.putType(typeobj) self.putSymbolValue(value.pointer()) self.putNumChild(0) return - if typeobj.code == TypeCode.TypeCodeEnum: + if typeobj.code == TypeCode.Enum: #DumperBase.warn('ENUM VALUE: %s' % value.stringify()) self.putType(typeobj.name) self.putValue(value.display()) self.putNumChild(0) return - if typeobj.code == TypeCode.TypeCodeArray: + if typeobj.code == TypeCode.Array: #DumperBase.warn('ARRAY VALUE: %s' % value) self.putCStyleArray(value) return - if typeobj.code == TypeCode.TypeCodeBitfield: + if typeobj.code == TypeCode.Bitfield: #DumperBase.warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typeName)) self.putNumChild(0) dd = typeobj.ltarget.typeData().enumDisplay @@ -2724,7 +2720,7 @@ class DumperBase(): self.putType(typeName) return - if typeobj.code == TypeCode.TypeCodeIntegral: + if typeobj.code == TypeCode.Integral: #DumperBase.warn('INTEGER: %s %s' % (value.name, value)) val = value.value() self.putNumChild(0) @@ -2732,14 +2728,14 @@ class DumperBase(): self.putType(typeName) return - if typeobj.code == TypeCode.TypeCodeFloat: + if typeobj.code == TypeCode.Float: #DumperBase.warn('FLOAT VALUE: %s' % value) self.putValue(value.value()) self.putNumChild(0) self.putType(typeobj.name) return - if typeobj.code in (TypeCode.TypeCodeReference, TypeCode.TypeCodeRValueReference): + if typeobj.code in (TypeCode.Reference, TypeCode.RValueReference): #DumperBase.warn('REFERENCE VALUE: %s' % value) val = value.dereference() if val.laddress != 0: @@ -2749,13 +2745,13 @@ class DumperBase(): self.putBetterType(typeName) return - if typeobj.code == TypeCode.TypeCodeComplex: + if typeobj.code == TypeCode.Complex: self.putType(typeobj) self.putValue(value.display()) self.putNumChild(0) return - if typeobj.code == TypeCode.TypeCodeFortranString: + if typeobj.code == TypeCode.FortranString: self.putValue(self.hexencode(value.data()), 'latin1') self.putNumChild(0) self.putType(typeobj) @@ -2907,14 +2903,14 @@ class DumperBase(): return '' def pointer(self): - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.detypedef().pointer() return self.extractInteger(self.dumper.ptrSize() * 8, True) def integer(self, bitsize=None): - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.detypedef().integer() - elif self.type.code == TypeCode.TypeCodeBitfield: + elif self.type.code == TypeCode.Bitfield: return self.lvalue # Could be something like 'short unsigned int' unsigned = self.type.name == 'unsigned' \ @@ -2927,7 +2923,7 @@ class DumperBase(): def floatingPoint(self): if self.nativeValue is not None and not self.dumper.isCdb: return str(self.nativeValue) - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.detypedef().floatingPoint() if self.type.size() == 8: return self.extractSomething('d', 64) @@ -2973,17 +2969,17 @@ class DumperBase(): def value(self): if self.type is not None: - if self.type.code == TypeCode.TypeCodeEnum: + if self.type.code == TypeCode.Enum: return self.displayEnum() - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.detypedef().value() - if self.type.code == TypeCode.TypeCodeIntegral: + if self.type.code == TypeCode.Integral: return self.integer() - if self.type.code == TypeCode.TypeCodeBitfield: + if self.type.code == TypeCode.Bitfield: return self.integer() - if self.type.code == TypeCode.TypeCodeFloat: + if self.type.code == TypeCode.Float: return self.floatingPoint() - if self.type.code == TypeCode.TypeCodePointer: + if self.type.code == TypeCode.Pointer: return self.pointer() return None @@ -2992,31 +2988,31 @@ class DumperBase(): def findMemberByName(self, name): self.check() - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.findMemberByName(self.detypedef()) if self.type.code in ( - TypeCode.TypeCodePointer, - TypeCode.TypeCodeReference, - TypeCode.TypeCodeRValueReference): + TypeCode.Pointer, + TypeCode.Reference, + TypeCode.RValueReference): res = self.dereference().findMemberByName(name) if res is not None: return res - if self.type.code == TypeCode.TypeCodeStruct: + if self.type.code == TypeCode.Struct: #DumperBase.warn('SEARCHING FOR MEMBER: %s IN %s' % (name, self.type.name)) members = self.members(True) #DumperBase.warn('MEMBERS: %s' % members) for member in members: #DumperBase.warn('CHECKING FIELD %s' % member.name) - if member.type.code == TypeCode.TypeCodeTypedef: + if member.type.code == TypeCode.Typedef: member = member.detypedef() if member.name == name: return member for member in members: - if member.type.code == TypeCode.TypeCodeTypedef: + if member.type.code == TypeCode.Typedef: member = member.detypedef() if member.name == name: # Could be base class. return member - if member.type.code == TypeCode.TypeCodeStruct: + if member.type.code == TypeCode.Struct: res = member.findMemberByName(name) if res is not None: return res @@ -3025,11 +3021,11 @@ class DumperBase(): def __getitem__(self, index): #DumperBase.warn('GET ITEM %s %s' % (self, index)) self.check() - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: #DumperBase.warn('GET ITEM STRIP TYPEDEFS TO %s' % self.type.ltarget) return self.cast(self.type.ltarget).__getitem__(index) if isinstance(index, str): - if self.type.code == TypeCode.TypeCodePointer: + if self.type.code == TypeCode.Pointer: #DumperBase.warn('GET ITEM %s DEREFERENCE TO %s' % (self, self.dereference())) return self.dereference().__getitem__(index) res = self.findMemberByName(index) @@ -3040,10 +3036,10 @@ class DumperBase(): elif isinstance(index, self.dumper.Field): field = index elif self.dumper.isInt(index): - if self.type.code == TypeCode.TypeCodeArray: + if self.type.code == TypeCode.Array: addr = self.laddress + int(index) * self.type.ltarget.size() return self.dumper.createValue(addr, self.type.ltarget) - if self.type.code == TypeCode.TypeCodePointer: + if self.type.code == TypeCode.Pointer: addr = self.pointer() + int(index) * self.type.ltarget.size() return self.dumper.createValue(addr, self.type.ltarget) return self.members(False)[index] @@ -3052,7 +3048,7 @@ class DumperBase(): field.check() #DumperBase.warn('EXTRACT FIELD: %s, BASE 0x%x' % (field, self.address())) - if self.type.code == TypeCode.TypeCodePointer: + if self.type.code == TypeCode.Pointer: #DumperBase.warn('IS TYPEDEFED POINTER!') res = self.dereference() #DumperBase.warn('WAS POINTER: %s' % res) @@ -3069,9 +3065,9 @@ class DumperBase(): #DumperBase.warn('EXTRACTOR SUCCEEDED: %s ' % val) return val - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.cast(self.type.ltarget).extractField(field) - if self.type.code in (TypeCode.TypeCodeReference, TypeCode.TypeCodeRValueReference): + if self.type.code in (TypeCode.Reference, TypeCode.RValueReference): return self.dereference().extractField(field) #DumperBase.warn('FIELD: %s ' % field) val = self.dumper.Value(self.dumper) @@ -3092,7 +3088,7 @@ class DumperBase(): fieldOffset = fieldBitpos // 8 fieldType = field.fieldType() - if fieldType.code == TypeCode.TypeCodeBitfield: + if fieldType.code == TypeCode.Bitfield: fieldBitpos -= fieldOffset * 8 ldata = self.data() data = 0 @@ -3116,7 +3112,7 @@ class DumperBase(): else: self.dumper.check(False) - if fieldType.code in (TypeCode.TypeCodeReference, TypeCode.TypeCodeRValueReference): + if fieldType.code in (TypeCode.Reference, TypeCode.RValueReference): if val.laddress is not None: val = self.dumper.createReferenceValue(val.laddress, fieldType.ltarget) val.name = field.name @@ -3131,7 +3127,7 @@ class DumperBase(): # implementations. def members(self, includeBases): #DumperBase.warn("LISTING MEMBERS OF %s" % self) - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.detypedef().members(includeBases) tdata = self.type.typeData() @@ -3163,7 +3159,7 @@ class DumperBase(): self.check() if self.dumper.isInt(other): stripped = self.type.stripTypedefs() - if stripped.code == TypeCode.TypeCodePointer: + if stripped.code == TypeCode.Pointer: address = self.pointer() + stripped.dereference().size() * other val = self.dumper.Value(self.dumper) val.laddress = None @@ -3176,16 +3172,16 @@ class DumperBase(): self.check() if self.type.name == other.type.name: stripped = self.type.stripTypedefs() - if stripped.code == TypeCode.TypeCodePointer: + if stripped.code == TypeCode.Pointer: return (self.pointer() - other.pointer()) // stripped.dereference().size() raise RuntimeError('BAD DATA TO SUB TO: %s %s' % (self.type, other)) def dereference(self): self.check() - if self.type.code == TypeCode.TypeCodeTypedef: + if self.type.code == TypeCode.Typedef: return self.detypedef().dereference() val = self.dumper.Value(self.dumper) - if self.type.code in (TypeCode.TypeCodeReference, TypeCode.TypeCodeRValueReference): + if self.type.code in (TypeCode.Reference, TypeCode.RValueReference): val.summary = self.summary if self.nativeValue is None: val.laddress = self.pointer() @@ -3194,7 +3190,7 @@ class DumperBase(): val.type = self.dumper.nativeDynamicType(val.laddress, self.type.dereference()) else: val = self.dumper.nativeValueDereferenceReference(self) - elif self.type.code == TypeCode.TypeCodePointer: + elif self.type.code == TypeCode.Pointer: if self.nativeValue is None: val.laddress = self.pointer() val.type = self.dumper.nativeDynamicType(val.laddress, self.type.dereference()) @@ -3211,7 +3207,7 @@ class DumperBase(): def detypedef(self): self.check() - if self.type.code != TypeCode.TypeCodeTypedef: + if self.type.code != TypeCode.Typedef: raise RuntimeError("WRONG") val = self.copy() val.type = self.type.ltarget @@ -3452,7 +3448,7 @@ class DumperBase(): tdata = self.typeData() if tdata is None: return None - if tdata.code != TypeCode.TypeCodeStruct: + if tdata.code != TypeCode.Struct: return None try: vtbl = self.dumper.extractPointer(address) @@ -3482,7 +3478,7 @@ class DumperBase(): raise RuntimeError('TYPE WITHOUT NAME: %s' % self.typeId) def dereference(self): - if self.code == TypeCode.TypeCodeTypedef: + if self.code == TypeCode.Typedef: return self.ltarget.dereference() self.check() return self.ltarget @@ -3530,27 +3526,18 @@ class DumperBase(): return res def isSimpleType(self): - return self.code in ( - TypeCode.TypeCodeIntegral, - TypeCode.TypeCodeFloat, - TypeCode.TypeCodeEnum) + return self.code in (TypeCode.Integral, TypeCode.Float, TypeCode.Enum) def alignment(self): tdata = self.typeData() - if tdata.code == TypeCode.TypeCodeTypedef: + if tdata.code == TypeCode.Typedef: return tdata.ltarget.alignment() - if tdata.code in ( - TypeCode.TypeCodeIntegral, - TypeCode.TypeCodeFloat, - TypeCode.TypeCodeEnum): + if tdata.code in (TypeCode.Integral, TypeCode.Float, TypeCode.Enum): if tdata.name in ('double', 'long long', 'unsigned long long'): # Crude approximation. return 8 if self.dumper.isWindowsTarget() else self.dumper.ptrSize() return self.size() - if tdata.code in ( - TypeCode.TypeCodePointer, - TypeCode.TypeCodeReference, - TypeCode.TypeCodeRValueReference): + if tdata.code in (TypeCode.Pointer, TypeCode.Reference, TypeCode.RValueReference): return self.dumper.ptrSize() if tdata.lalignment is not None: #if isinstance(tdata.lalignment, function): # Does not work that way. @@ -3566,7 +3553,7 @@ class DumperBase(): return self.typeData().ltarget def stripTypedefs(self): - if isinstance(self, self.dumper.Type) and self.code != TypeCode.TypeCodeTypedef: + if isinstance(self, self.dumper.Type) and self.code != TypeCode.Typedef: #DumperBase.warn('NO TYPEDEF: %s' % self) return self return self.ltarget @@ -3583,10 +3570,7 @@ class DumperBase(): raise RuntimeError('DONT KNOW SIZE: %s' % self) def isMovableType(self): - if self.code in ( - TypeCode.TypeCodePointer, - TypeCode.TypeCodeIntegral, - TypeCode.TypeCodeFloat): + if self.code in (TypeCode.Pointer, TypeCode.Integral, TypeCode.Float): return True strippedName = self.dumper.stripNamespaceFromType(self.name) if strippedName in ( @@ -3690,7 +3674,7 @@ class DumperBase(): tdata.name = targetType.name + '*' tdata.typeId = typeId tdata.lbitsize = 8 * self.ptrSize() - tdata.code = TypeCode.TypeCodePointer + tdata.code = TypeCode.Pointer tdata.ltarget = targetType self.registerType(typeId, tdata) return self.Type(self, typeId) @@ -3703,7 +3687,7 @@ class DumperBase(): tdata = self.TypeData(self) tdata.name = targetType.name + ' &' tdata.typeId = typeId - tdata.code = TypeCode.TypeCodeReference + tdata.code = TypeCode.Reference tdata.ltarget = targetType tdata.lbitsize = 8 * self.ptrSize() # Needed for Gdb13393 test. #tdata.lbitsize = None @@ -3718,7 +3702,7 @@ class DumperBase(): tdata = self.TypeData(self) tdata.name = targetType.name + ' &&' tdata.typeId = typeId - tdata.code = TypeCode.TypeCodeRValueReference + tdata.code = TypeCode.RValueReference tdata.ltarget = targetType tdata.lbitsize = None self.registerType(typeId, tdata) @@ -3741,7 +3725,7 @@ class DumperBase(): tdata = self.TypeData(self) tdata.name = type_name tdata.typeId = type_id - tdata.code = TypeCode.TypeCodeArray + tdata.code = TypeCode.Array tdata.ltarget = targetType tdata.lbitsize = targetType.lbitsize * count self.registerType(type_id, tdata) @@ -3755,7 +3739,7 @@ class DumperBase(): tdata = self.TypeData(self) tdata.name = '%s : %d' % (targetType.typeId, bitsize) tdata.typeId = typeId - tdata.code = TypeCode.TypeCodeBitfield + tdata.code = TypeCode.Bitfield tdata.ltarget = targetType tdata.lbitsize = bitsize self.registerType(typeId, tdata) @@ -3773,7 +3757,7 @@ class DumperBase(): tdata = self.TypeData(self) tdata.name = typeName tdata.typeId = typeId - tdata.code = TypeCode.TypeCodeTypedef + tdata.code = TypeCode.Typedef tdata.ltarget = targetType tdata.lbitsize = targetType.lbitsize #tdata.lfields = targetType.lfields diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index a79e9edb180..4d2e9680cce 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -365,29 +365,29 @@ class Dumper(DumperBase): tdata.typeId = typeId tdata.lbitsize = nativeType.sizeof * 8 tdata.code = { - #gdb.TYPE_CODE_TYPEDEF : TypeCodeTypedef, # Handled above. - gdb.TYPE_CODE_METHOD: TypeCode.TypeCodeFunction, - gdb.TYPE_CODE_VOID: TypeCode.TypeCodeVoid, - gdb.TYPE_CODE_FUNC: TypeCode.TypeCodeFunction, - gdb.TYPE_CODE_METHODPTR: TypeCode.TypeCodeFunction, - gdb.TYPE_CODE_MEMBERPTR: TypeCode.TypeCodeFunction, - #gdb.TYPE_CODE_PTR : TypeCode.TypeCodePointer, # Handled above. - #gdb.TYPE_CODE_REF : TypeCode.TypeCodeReference, # Handled above. - gdb.TYPE_CODE_BOOL: TypeCode.TypeCodeIntegral, - gdb.TYPE_CODE_CHAR: TypeCode.TypeCodeIntegral, - gdb.TYPE_CODE_INT: TypeCode.TypeCodeIntegral, - gdb.TYPE_CODE_FLT: TypeCode.TypeCodeFloat, - gdb.TYPE_CODE_ENUM: TypeCode.TypeCodeEnum, - #gdb.TYPE_CODE_ARRAY : TypeCode.TypeCodeArray, - gdb.TYPE_CODE_STRUCT: TypeCode.TypeCodeStruct, - gdb.TYPE_CODE_UNION: TypeCode.TypeCodeStruct, - gdb.TYPE_CODE_COMPLEX: TypeCode.TypeCodeComplex, - gdb.TYPE_CODE_STRING: TypeCode.TypeCodeFortranString, + #gdb.TYPE_CODE_TYPEDEF : TypeCode.Typedef, # Handled above. + gdb.TYPE_CODE_METHOD: TypeCode.Function, + gdb.TYPE_CODE_VOID: TypeCode.Void, + gdb.TYPE_CODE_FUNC: TypeCode.Function, + gdb.TYPE_CODE_METHODPTR: TypeCode.Function, + gdb.TYPE_CODE_MEMBERPTR: TypeCode.Function, + #gdb.TYPE_CODE_PTR : TypeCode.Pointer, # Handled above. + #gdb.TYPE_CODE_REF : TypeCode.Reference, # Handled above. + gdb.TYPE_CODE_BOOL: TypeCode.Integral, + gdb.TYPE_CODE_CHAR: TypeCode.Integral, + gdb.TYPE_CODE_INT: TypeCode.Integral, + gdb.TYPE_CODE_FLT: TypeCode.Float, + gdb.TYPE_CODE_ENUM: TypeCode.Enum, + #gdb.TYPE_CODE_ARRAY : TypeCode.Array, + gdb.TYPE_CODE_STRUCT: TypeCode.Struct, + gdb.TYPE_CODE_UNION: TypeCode.Struct, + gdb.TYPE_CODE_COMPLEX: TypeCode.Complex, + gdb.TYPE_CODE_STRING: TypeCode.FortranString, }[code] - if tdata.code == TypeCode.TypeCodeEnum: + if tdata.code == TypeCode.Enum: tdata.enumDisplay = lambda intval, addr, form: \ self.nativeTypeEnumDisplay(nativeType, intval, form) - if tdata.code == TypeCode.TypeCodeStruct: + if tdata.code == TypeCode.Struct: tdata.lalignment = lambda: \ self.nativeStructAlignment(nativeType) tdata.lfields = lambda value: \ diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 8a98b8e5dcd..b9806054516 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -436,32 +436,32 @@ class Dumper(DumperBase): tdata.lbitsize = nativeType.GetByteSize() * 8 if code == lldb.eTypeClassBuiltin: if utils.isFloatingPointTypeName(typeName): - tdata.code = TypeCode.TypeCodeFloat + tdata.code = TypeCode.Float elif utils.isIntegralTypeName(typeName): - tdata.code = TypeCode.TypeCodeIntegral + tdata.code = TypeCode.Integral elif typeName in ('__int128', 'unsigned __int128'): - tdata.code = TypeCode.TypeCodeIntegral + tdata.code = TypeCode.Integral elif typeName == 'void': - tdata.code = TypeCode.TypeCodeVoid + tdata.code = TypeCode.Void else: self.warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code)) elif code == lldb.eTypeClassEnumeration: - tdata.code = TypeCode.TypeCodeEnum + tdata.code = TypeCode.Enum tdata.enumDisplay = lambda intval, addr, form: \ self.nativeTypeEnumDisplay(nativeType, intval, form) elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat): - tdata.code = TypeCode.TypeCodeComplex + tdata.code = TypeCode.Complex elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion): - tdata.code = TypeCode.TypeCodeStruct + tdata.code = TypeCode.Struct tdata.lalignment = lambda: \ self.nativeStructAlignment(nativeType) tdata.lfields = lambda value: \ self.listMembers(value, nativeType) tdata.templateArguments = self.listTemplateParametersHelper(nativeType) elif code == lldb.eTypeClassFunction: - tdata.code = TypeCode.TypeCodeFunction + tdata.code = TypeCode.Function elif code == lldb.eTypeClassMemberPointer: - tdata.code = TypeCode.TypeCodeMemberPointer + tdata.code = TypeCode.MemberPointer self.registerType(typeId, tdata) # Fix up fields and template args # warn('CREATE TYPE: %s' % typeId) diff --git a/share/qtcreator/debugger/misctypes.py b/share/qtcreator/debugger/misctypes.py index 864f280b5e8..7ce5739cc43 100644 --- a/share/qtcreator/debugger/misctypes.py +++ b/share/qtcreator/debugger/misctypes.py @@ -111,7 +111,7 @@ def qdump____m512i(d, value): def qform__std__array(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__gsl__span(d, value): @@ -201,7 +201,7 @@ def qdump__NimStringDesc(d, value): def qdump__NimGenericSequence__(d, value, regex=r'^TY[\d]+$'): code = value.type.stripTypedefs().code - if code == TypeCode.TypeCodeStruct: + if code == TypeCode.Struct: size, reserved = d.split('pp', value) data = value.address() + 2 * d.ptrSize() typeobj = value['data'].type.dereference() diff --git a/share/qtcreator/debugger/opencvtypes.py b/share/qtcreator/debugger/opencvtypes.py index 1e4a07d1cae..1f74476a742 100644 --- a/share/qtcreator/debugger/opencvtypes.py +++ b/share/qtcreator/debugger/opencvtypes.py @@ -33,7 +33,7 @@ def qdump__cv__Size_(d, value): def qform__cv__Mat(): - return [DisplayFormat.SeparateFormat] + return [DisplayFormat.Separate] def qdump__cv__Mat(d, value): @@ -47,7 +47,7 @@ def qdump__cv__Mat(d, value): d.putPlainChildren(value) return - if d.currentItemFormat() == DisplayFormat.SeparateFormat: + if d.currentItemFormat() == DisplayFormat.Separate: rs = steps[0] * innerSize cs = cols * innerSize dform = 'arraydata:separate:int:%d::2:%d:%d' % (innerSize, cols, rows) @@ -57,7 +57,7 @@ def qdump__cv__Mat(d, value): d.putValue('(%s x %s)' % (rows, cols)) if d.isExpanded(): with Children(d): - innerType = d.createType(TypeCode.TypeCodeIntegral, innerSize) + innerType = d.createType(TypeCode.Integral, innerSize) for i in range(rows): for j in range(cols): with SubItem(d, None): diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 2407a25b2a9..f28abcd8edb 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -45,8 +45,8 @@ def qdump__QAtomicPointer(d, value): def qform__QByteArray(): - return [DisplayFormat.Latin1StringFormat, DisplayFormat.SeparateLatin1StringFormat, - DisplayFormat.Utf8StringFormat, DisplayFormat.SeparateUtf8StringFormat] + return [DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String, + DisplayFormat.Utf8String, DisplayFormat.SeparateUtf8String] def qedit__QByteArray(d, value, data): @@ -61,14 +61,14 @@ def qdump__QByteArray(d, value): d.putNumChild(size) elided, p = d.encodeByteArrayHelper(d.extractPointer(value), d.displayStringLimit) displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.AutomaticFormat or displayFormat == DisplayFormat.Latin1StringFormat: + if displayFormat == DisplayFormat.Automatic or displayFormat == DisplayFormat.Latin1String: d.putValue(p, 'latin1', elided=elided) - elif displayFormat == DisplayFormat.SeparateLatin1StringFormat: + elif displayFormat == DisplayFormat.SeparateLatin1String: d.putValue(p, 'latin1', elided=elided) d.putDisplay('latin1:separate', d.encodeByteArray(value, limit=100000)) - elif displayFormat == DisplayFormat.Utf8StringFormat: + elif displayFormat == DisplayFormat.Utf8String: d.putValue(p, 'utf8', elided=elided) - elif displayFormat == DisplayFormat.SeparateUtf8StringFormat: + elif displayFormat == DisplayFormat.SeparateUtf8String: d.putValue(p, 'utf8', elided=elided) d.putDisplay('utf8:separate', d.encodeByteArray(value, limit=100000)) if d.isExpanded(): @@ -108,15 +108,15 @@ def qdump__QChar(d, value): def qform_X_QAbstractItemModel(): - return [DisplayFormat.SimpleFormat, DisplayFormat.EnhancedFormat] + return [DisplayFormat.Simple, DisplayFormat.Enhanced] def qdump_X_QAbstractItemModel(d, value): displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.SimpleFormat: + if displayFormat == DisplayFormat.Simple: d.putPlainChildren(value) return - #displayFormat == EnhancedFormat: + #displayFormat == Enhanced: # Create a default-constructed QModelIndex on the stack. try: ri = d.pokeValue(d.qtNamespace() + 'QModelIndex', '-1, -1, 0, 0') @@ -144,12 +144,12 @@ def qdump_X_QAbstractItemModel(d, value): def qform_X_QModelIndex(): - return [DisplayFormat.SimpleFormat, DisplayFormat.EnhancedFormat] + return [DisplayFormat.Simple, DisplayFormat.Enhanced] def qdump_X_QModelIndex(d, value): displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.SimpleFormat: + if displayFormat == DisplayFormat.Simple: d.putPlainChildren(value) return r = value['r'] @@ -776,7 +776,7 @@ def qdump__QFixed(d, value): def qform__QFiniteStack(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__QFiniteStack(d, value): @@ -795,7 +795,7 @@ def qdump__QFlags(d, value): def qform__QHash(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__QHash(d, value): @@ -858,7 +858,7 @@ def qdumpHelper_QHash(d, value, keyType, valueType): def qform__QHashNode(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__QHashNode(d, value): @@ -970,7 +970,7 @@ def qdump__QIPv6Address(d, value): def qform__QList(): - return [DisplayFormat.DirectQListStorageFormat, DisplayFormat.IndirectQListStorageFormat] + return [DisplayFormat.DirectQListStorage, DisplayFormat.IndirectQListStorage] def qdump__QList(d, value): @@ -1003,9 +1003,9 @@ def qdumpHelper_QList(d, value, innerType): # in the frontend. # So as first approximation only do the 'isLarge' check: displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.DirectQListStorageFormat: + if displayFormat == DisplayFormat.DirectQListStorage: isInternal = True - elif displayFormat == DisplayFormat.IndirectQListStorageFormat: + elif displayFormat == DisplayFormat.IndirectQListStorage: isInternal = False else: isInternal = innerSize <= stepSize and innerType.isMovableType() @@ -1027,7 +1027,7 @@ def qdumpHelper_QList(d, value, innerType): def qform__QImage(): - return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + return [DisplayFormat.Simple, DisplayFormat.Separate] def qdump__QImage(d, value): @@ -1057,7 +1057,7 @@ def qdump__QImage(d, value): d.putType('void *') displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.SeparateFormat: + if displayFormat == DisplayFormat.Separate: d.putDisplay('imagedata:separate', '%08x%08x%08x%08x' % (width, height, nbytes, iformat) + d.readMemory(bits, nbytes)) @@ -1202,7 +1202,7 @@ def qdumpHelper_Qt5_QMap(d, value, keyType, valueType): def qform__QMap(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__QMap(d, value): @@ -1217,7 +1217,7 @@ def qdumpHelper_QMap(d, value, keyType, valueType): def qform__QMultiMap(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__QMultiMap(d, value): @@ -1225,7 +1225,7 @@ def qdump__QMultiMap(d, value): def qform__QVariantMap(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__QVariantMap(d, value): @@ -1506,7 +1506,7 @@ def qdump__QSizePolicy(d, value): def qform__QStack(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__QStack(d, value): @@ -1546,7 +1546,7 @@ def qedit__QString(d, value, data): def qform__QString(): - return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + return [DisplayFormat.Simple, DisplayFormat.Separate] def qdump__QString(d, value): @@ -1554,7 +1554,7 @@ def qdump__QString(d, value): (data, size, alloc) = d.stringData(value) d.putNumChild(size) displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.SeparateFormat: + if displayFormat == DisplayFormat.Separate: d.putDisplay('utf16:separate', d.encodeString(value, limit=100000)) if d.isExpanded(): d.putArrayData(data, size, d.createType('QChar')) @@ -1656,7 +1656,7 @@ def qdump__QTextDocument(d, value): def qform__QUrl(): - return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + return [DisplayFormat.Simple, DisplayFormat.Separate] def qdump__QUrl(d, value): @@ -1698,7 +1698,7 @@ def qdump__QUrl(d, value): d.putValue(url, 'utf16') displayFormat = d.currentItemFormat() - if displayFormat == DisplayFormat.SeparateFormat: + if displayFormat == DisplayFormat.Separate: d.putDisplay('utf16:separate', url) d.putNumChild(1) @@ -2016,7 +2016,7 @@ def qedit__QVector(d, value, data): def qform__QVector(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__QVector(d, value): @@ -2135,7 +2135,7 @@ def qdump__QXmlStreamAttribute(d, value): ####################################################################### def extractQmlData(d, value): - #if value.type.code == TypeCode.TypeCodePointer: + #if value.type.code == TypeCode.Pointer: # value = value.dereference() base = value.split('p')[0] #mmdata = d.split('Q', base)[0] diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index 069f54190bf..c6693f70b69 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -28,7 +28,7 @@ from dumper import Children, SubItem def qform__std__array(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__std__array(d, value): @@ -39,7 +39,7 @@ def qdump__std__array(d, value): def qform__std____1__array(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__std____1__array(d, value): @@ -274,7 +274,7 @@ def qdump__std____1__list(d, value): def qform__std__map(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__std__map(d, value): @@ -357,7 +357,7 @@ def qdump__std____cxx1998__map(d, value): def qform__std__multimap(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__std__multimap(d, value): @@ -581,7 +581,7 @@ def qdump__std____1__multiset(d, value): def qform__std____1__map(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__std____1__map(d, value): @@ -620,7 +620,7 @@ def qdump__std____1__map(d, value): def qform__std____1__multimap(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__std____1__multimap(d, value): @@ -675,8 +675,8 @@ def qdump__std____1__stack(d, value): def qform__std__string(): - return [DisplayFormat.Latin1StringFormat, DisplayFormat.SeparateLatin1StringFormat, - DisplayFormat.Utf8StringFormat, DisplayFormat.SeparateUtf8StringFormat] + return [DisplayFormat.Latin1String, DisplayFormat.SeparateLatin1String, + DisplayFormat.Utf8String, DisplayFormat.SeparateUtf8String] def qdump__std__string(d, value): @@ -826,11 +826,11 @@ def qdump__std__pair(d, value): def qform__std__unordered_map(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qform__std____debug__unordered_map(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__std__unordered_map(d, value): @@ -934,7 +934,7 @@ def qdump__std__unordered_set(d, value): def qform__std____1__unordered_map(): - return [DisplayFormat.CompactMapFormat] + return [DisplayFormat.CompactMap] def qdump__std____1__unordered_map(d, value): @@ -992,7 +992,7 @@ def qdump__std____debug__unordered_multiset(d, value): def qform__std__valarray(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__std__valarray(d, value): @@ -1005,7 +1005,7 @@ def qdump__std__valarray(d, value): def qform__std____1__valarray(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__std____1__valarray(d, value): @@ -1017,7 +1017,7 @@ def qdump__std____1__valarray(d, value): def qform__std__vector(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qedit__std__vector(d, value, data): @@ -1119,7 +1119,7 @@ def qdumpHelper__std__vector__QNX(d, value): def qform__std____1__vector(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__std____1__vector(d, value): @@ -1127,7 +1127,7 @@ def qdump__std____1__vector(d, value): def qform__std____debug__vector(): - return [DisplayFormat.ArrayPlotFormat] + return [DisplayFormat.ArrayPlot] def qdump__std____debug__vector(d, value): @@ -1182,7 +1182,7 @@ def qdump__string(d, value): def qform__std__wstring(): - return [DisplayFormat.SimpleFormat, DisplayFormat.SeparateFormat] + return [DisplayFormat.Simple, DisplayFormat.Separate] def qdump__std__wstring(d, value): diff --git a/share/qtcreator/debugger/utils.py b/share/qtcreator/debugger/utils.py index 72dc0fbcb80..feec4379cde 100644 --- a/share/qtcreator/debugger/utils.py +++ b/share/qtcreator/debugger/utils.py @@ -43,26 +43,26 @@ class DebuggerStartMode(): # Known special formats. Keep in sync with DisplayFormat in debuggerprotocol.h class DisplayFormat(): ( - AutomaticFormat, - RawFormat, - SimpleFormat, - EnhancedFormat, - SeparateFormat, - Latin1StringFormat, - SeparateLatin1StringFormat, - Utf8StringFormat, - SeparateUtf8StringFormat, - Local8BitStringFormat, - Utf16StringFormat, - Ucs4StringFormat, - Array10Format, - Array100Format, - Array1000Format, - Array10000Format, - ArrayPlotFormat, - CompactMapFormat, - DirectQListStorageFormat, - IndirectQListStorageFormat, + Automatic, + Raw, + Simple, + Enhanced, + Separate, + Latin1String, + SeparateLatin1String, + Utf8String, + SeparateUtf8String, + Local8BitString, + Utf16String, + Ucs4String, + Array10, + Array100, + Array1000, + Array10000, + ArrayPlot, + CompactMap, + DirectQListStorage, + IndirectQListStorage, ) = range(0, 20) @@ -89,22 +89,22 @@ class BreakpointType(): # Internal codes for types keep in sync with cdbextensions pytype.cpp class TypeCode(): ( - TypeCodeTypedef, - TypeCodeStruct, - TypeCodeVoid, - TypeCodeIntegral, - TypeCodeFloat, - TypeCodeEnum, - TypeCodePointer, - TypeCodeArray, - TypeCodeComplex, - TypeCodeReference, - TypeCodeFunction, - TypeCodeMemberPointer, - TypeCodeFortranString, - TypeCodeUnresolvable, - TypeCodeBitfield, - TypeCodeRValueReference, + Typedef, + Struct, + Void, + Integral, + Float, + Enum, + Pointer, + Array, + Complex, + Reference, + Function, + MemberPointer, + FortranString, + Unresolvable, + Bitfield, + RValueReference, ) = range(0, 16) From 821f073f159c9dc6089b26acb70438e8ce188e59 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 20 Feb 2020 10:13:14 +0100 Subject: [PATCH 48/96] LanguageClient: Add logging window Change-Id: Ib86b70381b69df55d62a97abdf52b747f7f1c75e Reviewed-by: Christian Stenger --- src/plugins/languageclient/CMakeLists.txt | 1 + src/plugins/languageclient/client.cpp | 7 + src/plugins/languageclient/languageclient.pro | 2 + src/plugins/languageclient/languageclient.qbs | 2 + .../languageclient/languageclientmanager.cpp | 14 + .../languageclient/languageclientmanager.h | 7 + .../languageclient/languageclientutils.cpp | 3 + src/plugins/languageclient/lsplogger.cpp | 364 ++++++++++++++++++ src/plugins/languageclient/lsplogger.h | 69 ++++ 9 files changed, 469 insertions(+) create mode 100644 src/plugins/languageclient/lsplogger.cpp create mode 100644 src/plugins/languageclient/lsplogger.h diff --git a/src/plugins/languageclient/CMakeLists.txt b/src/plugins/languageclient/CMakeLists.txt index abddb9cd968..9d04e7df1b7 100644 --- a/src/plugins/languageclient/CMakeLists.txt +++ b/src/plugins/languageclient/CMakeLists.txt @@ -19,5 +19,6 @@ add_qtc_plugin(LanguageClient languageclientutils.cpp languageclientutils.h languageclient_global.h locatorfilter.cpp locatorfilter.h + lsplogger.cpp lsplogger.h semantichighlightsupport.cpp semantichighlightsupport.h ) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index bb74a7bcab3..80b156216d5 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -262,6 +262,9 @@ void Client::initialize() }); // directly send data otherwise the state check would fail; initRequest.registerResponseHandler(&m_responseHandlers); + LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, + name(), + initRequest.toBaseMessage()); m_clientInterface->sendMessage(initRequest.toBaseMessage()); m_state = InitializeRequested; } @@ -334,6 +337,9 @@ void Client::sendContent(const IContent &content) QString error; if (!QTC_GUARD(content.isValid(&error))) Core::MessageManager::write(error); + LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, + name(), + content.toBaseMessage()); m_clientInterface->sendMessage(content.toBaseMessage()); } @@ -931,6 +937,7 @@ void Client::setError(const QString &message) void Client::handleMessage(const BaseMessage &message) { + LanguageClientManager::logBaseMessage(LspLogMessage::ServerMessage, name(), message); if (auto handler = m_contentHandler[message.mimeType]) { QString parseError; handler(message.content, message.codec, parseError, diff --git a/src/plugins/languageclient/languageclient.pro b/src/plugins/languageclient/languageclient.pro index 5db41008d1c..f6a2930d71a 100644 --- a/src/plugins/languageclient/languageclient.pro +++ b/src/plugins/languageclient/languageclient.pro @@ -19,6 +19,7 @@ HEADERS += \ languageclientsettings.h \ languageclientutils.h \ locatorfilter.h \ + lsplogger.h \ semantichighlightsupport.h @@ -38,6 +39,7 @@ SOURCES += \ languageclientsettings.cpp \ languageclientutils.cpp \ locatorfilter.cpp \ + lsplogger.cpp \ semantichighlightsupport.cpp RESOURCES += \ diff --git a/src/plugins/languageclient/languageclient.qbs b/src/plugins/languageclient/languageclient.qbs index ce1583381de..0502921b9ef 100644 --- a/src/plugins/languageclient/languageclient.qbs +++ b/src/plugins/languageclient/languageclient.qbs @@ -46,6 +46,8 @@ QtcPlugin { "languageclientutils.h", "locatorfilter.cpp", "locatorfilter.h", + "lsplogger.cpp", + "lsplogger.h", "semantichighlightsupport.cpp", "semantichighlightsupport.h", ] diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index 27e74683132..b2c65f511b7 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -340,6 +340,20 @@ void LanguageClientManager::reOpenDocumentWithClient(TextEditor::TextDocument *d client->activateDocument(document); } +void LanguageClientManager::logBaseMessage(const LspLogMessage::MessageSender sender, + const QString &clientName, + const BaseMessage &message) +{ + instance()->m_logger.log(sender, clientName, message); +} + +void LanguageClientManager::showLogger() +{ + QWidget *loggerWidget = instance()->m_logger.createWidget(); + loggerWidget->setAttribute(Qt::WA_DeleteOnClose); + loggerWidget->show(); +} + QVector LanguageClientManager::reachableClients() { return Utils::filtered(m_clients, &Client::reachable); diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h index fbf5322f1cc..ae30540f44b 100644 --- a/src/plugins/languageclient/languageclientmanager.h +++ b/src/plugins/languageclient/languageclientmanager.h @@ -29,6 +29,7 @@ #include "languageclient_global.h" #include "languageclientsettings.h" #include "locatorfilter.h" +#include "lsplogger.h" #include @@ -84,6 +85,11 @@ public: static Client *clientForUri(const LanguageServerProtocol::DocumentUri &uri); static void reOpenDocumentWithClient(TextEditor::TextDocument *document, Client *client); + static void logBaseMessage(const LspLogMessage::MessageSender sender, + const QString &clientName, + const LanguageServerProtocol::BaseMessage &message); + static void showLogger(); + signals: void shutdownFinished(); @@ -118,5 +124,6 @@ private: WorkspaceLocatorFilter m_workspaceLocatorFilter; WorkspaceClassLocatorFilter m_workspaceClassLocatorFilter; WorkspaceMethodLocatorFilter m_workspaceMethodLocatorFilter; + LspLogger m_logger; }; } // namespace LanguageClient diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 9cc1ad488fa..72bb0157576 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -239,6 +239,9 @@ void updateEditorToolBar(Core::IEditor *editor) QObject::connect(action, &QAction::triggered, reopen); } menu->addActions(clientsGroup->actions()); + menu->addAction("Language Client Logs", []() { + LanguageClientManager::showLogger(); + }); menu->addAction("Manage...", []() { Core::ICore::showOptionsDialog(Constants::LANGUAGECLIENT_SETTINGS_PAGE); }); diff --git a/src/plugins/languageclient/lsplogger.cpp b/src/plugins/languageclient/lsplogger.cpp new file mode 100644 index 00000000000..76a50a138fe --- /dev/null +++ b/src/plugins/languageclient/lsplogger.cpp @@ -0,0 +1,364 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "lsplogger.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace LanguageServerProtocol; + +namespace LanguageClient { + +class MessageDetailWidget : public QGroupBox +{ +public: + MessageDetailWidget(); + + void setMessage(const BaseMessage &message); + void clear(); + +private: + QLabel *m_contentLength = nullptr; + QLabel *m_mimeType = nullptr; +}; + +class LspLoggerWidget : public QDialog +{ + Q_DECLARE_TR_FUNCTIONS(LspLoggerWidget) +public: + explicit LspLoggerWidget(LspLogger *logger); + +private: + void addMessage(const QString &clientName, const LspLogMessage &message); + void setCurrentClient(const QString &clientName); + void currentMessageChanged(const QModelIndex &index); + void selectMatchingMessage(LspLogMessage::MessageSender sender, const QJsonValue &id); + void saveLog(); + + LspLogger *m_logger = nullptr; + QListWidget *m_clients = nullptr; + MessageDetailWidget *m_clientDetails = nullptr; + QListView *m_messages = nullptr; + MessageDetailWidget *m_serverDetails = nullptr; + Utils::ListModel m_model; +}; + +QWidget *LspLogger::createWidget() +{ + return new LspLoggerWidget(this); +} + +void LspLogger::log(const LspLogMessage::MessageSender sender, + const QString &clientName, + const BaseMessage &message) +{ + QLinkedList &clientLog = m_logs[clientName]; + auto delta = clientLog.size() - m_logSize + 1; + if (delta > 0) + clientLog.erase(clientLog.begin(), clientLog.begin() + delta); + m_logs[clientName].append({sender, QTime::currentTime(), message}); + emit newMessage(clientName, m_logs[clientName].last()); +} + +QLinkedList LspLogger::messages(const QString &clientName) const +{ + return m_logs[clientName]; +} + +QList LspLogger::clients() const +{ + return m_logs.keys(); +} + +static QVariant messageData(const LspLogMessage &message, int, int role) +{ + if (role == Qt::DisplayRole) { + QString result = message.time.toString("hh:mm:ss.zzz") + '\n'; + if (message.message.mimeType == JsonRpcMessageHandler::jsonRpcMimeType()) { + QString error; + auto json = JsonRpcMessageHandler::toJsonObject(message.message.content, + message.message.codec, + error); + result += json.value(QString{methodKey}).toString(json.value(QString{idKey}).toString()); + } else { + result += message.message.codec->toUnicode(message.message.content); + } + return result; + } + if (role == Qt::TextAlignmentRole) + return message.sender == LspLogMessage::ClientMessage ? Qt::AlignLeft : Qt::AlignRight; + return {}; +} + +LspLoggerWidget::LspLoggerWidget(LspLogger *logger) + : m_logger(logger) +{ + setWindowTitle(tr("Language Client Log")); + + connect(logger, &LspLogger::newMessage, this, &LspLoggerWidget::addMessage); + connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close); + + m_clients = new QListWidget; + m_clients->addItems(logger->clients()); + connect(m_clients, &QListWidget::currentTextChanged, this, &LspLoggerWidget::setCurrentClient); + m_clients->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); + + m_clientDetails = new MessageDetailWidget; + m_clientDetails->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_clientDetails->setTitle(tr("Client Message")); + m_serverDetails = new MessageDetailWidget; + m_serverDetails->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + m_serverDetails->setTitle(tr("Server Message")); + + m_model.setDataAccessor(&messageData); + m_messages = new QListView; + m_messages->setModel(&m_model); + m_messages->setAlternatingRowColors(true); + m_model.setHeader({tr("Messages")}); + connect(m_messages->selectionModel(), + &QItemSelectionModel::currentChanged, + this, + &LspLoggerWidget::currentMessageChanged); + m_messages->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + m_messages->setSelectionMode(QAbstractItemView::MultiSelection); + + auto layout = new QVBoxLayout; + setLayout(layout); + auto splitter = new Core::MiniSplitter; + splitter->setOrientation(Qt::Horizontal); + splitter->addWidget(m_clients); + splitter->addWidget(m_clientDetails); + splitter->addWidget(m_messages); + splitter->addWidget(m_serverDetails); + splitter->setStretchFactor(0, 0); + splitter->setStretchFactor(1, 1); + splitter->setStretchFactor(2, 1); + splitter->setStretchFactor(3, 1); + layout->addWidget(splitter); + + auto buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Close); + layout->addWidget(buttonBox); + + // save + connect(buttonBox, &QDialogButtonBox::accepted, this, &LspLoggerWidget::saveLog); + + // close + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + resize(1024, 768); +} + +void LspLoggerWidget::addMessage(const QString &clientName, const LspLogMessage &message) +{ + if (m_clients->findItems(clientName, Qt::MatchExactly).isEmpty()) + m_clients->addItem(clientName); + if (clientName != m_clients->currentItem()->text()) + return; + m_model.appendItem(message); +} + +void LspLoggerWidget::setCurrentClient(const QString &clientName) +{ + m_model.clear(); + for (const LspLogMessage &message : m_logger->messages(clientName)) + m_model.appendItem(message); +} + +void LspLoggerWidget::currentMessageChanged(const QModelIndex &index) +{ + m_messages->clearSelection(); + if (!index.isValid()) + return; + LspLogMessage selectedMessage = m_model.itemAt(index.row())->itemData; + BaseMessage message = selectedMessage.message; + if (selectedMessage.sender == LspLogMessage::ClientMessage) + m_clientDetails->setMessage(message); + else + m_serverDetails->setMessage(message); + if (message.mimeType == JsonRpcMessageHandler::jsonRpcMimeType()) { + QString error; + QJsonValue id = JsonRpcMessageHandler::toJsonObject(message.content, message.codec, error) + .value(idKey); + if (!id.isUndefined()) { + selectMatchingMessage(selectedMessage.sender == LspLogMessage::ClientMessage + ? LspLogMessage::ServerMessage + : LspLogMessage::ClientMessage, + id); + } + } +} + +static bool matches(LspLogMessage::MessageSender sender, + const QJsonValue &id, + const LspLogMessage &message) +{ + if (message.sender != sender) + return false; + if (message.message.mimeType != JsonRpcMessageHandler::jsonRpcMimeType()) + return false; + QString error; + auto json = JsonRpcMessageHandler::toJsonObject(message.message.content, + message.message.codec, + error); + return json.value(QString{idKey}) == id; +} + +void LspLoggerWidget::selectMatchingMessage(LspLogMessage::MessageSender sender, + const QJsonValue &id) +{ + LspLogMessage *matchingMessage = m_model.findData( + [&](const LspLogMessage &message) { return matches(sender, id, message); }); + if (!matchingMessage) + return; + auto item = m_model.findItemByData( + [&](const LspLogMessage &message) { return &message == matchingMessage; }); + + m_messages->selectionModel()->select(m_model.indexForItem(item), QItemSelectionModel::Select); + if (matchingMessage->sender == LspLogMessage::ServerMessage) + m_serverDetails->setMessage(matchingMessage->message); + else + m_clientDetails->setMessage(matchingMessage->message); +} + +void LspLoggerWidget::saveLog() +{ + QString contents; + QTextStream stream(&contents); + m_model.forItems([&](const LspLogMessage &message) { + stream << message.time.toString("hh:mm:ss.zzz") << ' '; + stream << (message.sender == LspLogMessage::ClientMessage ? QString{"Client"} + : QString{"Server"}); + stream << '\n'; + stream << message.message.codec->toUnicode(message.message.content); + stream << "\n\n"; + }); + + const QString fileName = QFileDialog::getSaveFileName(this, tr("Log File")); + if (fileName.isEmpty()) + return; + Utils::FileSaver saver(fileName, QIODevice::Text); + saver.write(contents.toUtf8()); + if (!saver.finalize(this)) + saveLog(); +} + +MessageDetailWidget::MessageDetailWidget() +{ + auto layout = new QFormLayout; + setLayout(layout); + + m_contentLength = new QLabel; + m_mimeType = new QLabel; + + layout->addRow("Content Length:", m_contentLength); + layout->addRow("MIME Type:", m_mimeType); +} + +class JsonTreeItemDelegate : public QStyledItemDelegate +{ +public: + QString displayText(const QVariant &value, const QLocale &) const override + { + QString result = value.toString(); + if (result.size() == 1) { + switch (result.at(0).toLatin1()) { + case '\n': + return QString("\\n"); + case '\t': + return QString("\\t"); + case '\r': + return QString("\\r"); + } + } + return result; + } +}; + +void MessageDetailWidget::setMessage(const BaseMessage &message) +{ + m_contentLength->setText(QString::number(message.contentLength)); + m_mimeType->setText(QString::fromLatin1(message.mimeType)); + + QWidget *newContentWidget = nullptr; + if (message.mimeType == JsonRpcMessageHandler::jsonRpcMimeType()) { + QString error; + auto json = JsonRpcMessageHandler::toJsonObject(message.content, message.codec, error); + if (json.isEmpty()) { + newContentWidget = new QLabel(error); + } else { + auto root = new Utils::JsonTreeItem("content", json); + if (root->canFetchMore()) + root->fetchMore(); + + auto model = new Utils::TreeModel(root); + model->setHeader({{"Name"}, {"Value"}, {"Type"}}); + auto view = new QTreeView; + view->setModel(model); + view->setAlternatingRowColors(true); + view->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + view->setItemDelegate(new JsonTreeItemDelegate); + newContentWidget = view; + } + } else { + auto edit = new QPlainTextEdit(); + edit->setReadOnly(true); + edit->setPlainText(message.codec->toUnicode(message.content)); + newContentWidget = edit; + } + auto formLayout = static_cast(layout()); + if (formLayout->rowCount() > 2) + formLayout->removeRow(2); + formLayout->setWidget(2, QFormLayout::SpanningRole, newContentWidget); +} + +void MessageDetailWidget::clear() +{ + m_contentLength->setText({}); + m_mimeType->setText({}); + auto formLayout = static_cast(layout()); + if (formLayout->rowCount() > 2) + formLayout->removeRow(2); +} + +} // namespace LanguageClient diff --git a/src/plugins/languageclient/lsplogger.h b/src/plugins/languageclient/lsplogger.h new file mode 100644 index 00000000000..c07a161737d --- /dev/null +++ b/src/plugins/languageclient/lsplogger.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +#include + +class QWidget; + +namespace LanguageClient { + +struct LspLogMessage +{ + enum MessageSender { ClientMessage, ServerMessage } sender; + QTime time; + LanguageServerProtocol::BaseMessage message; +}; + +class LspLogger : public QObject +{ + Q_OBJECT +public: + LspLogger() {} + + QWidget *createWidget(); + + + void log(const LspLogMessage::MessageSender sender, + const QString &clientName, + const LanguageServerProtocol::BaseMessage &message); + + QLinkedList messages(const QString &clientName) const; + QList clients() const; + +signals: + void newMessage(const QString &clientName, const LspLogMessage &message); + +private: + QMap> m_logs; + int m_logSize = 100; // default log size if no widget is currently visible +}; + +} // namespace LanguageClient From 015d09a9e7c50e85ccd8b719e055aefb2356b06f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 28 Feb 2020 16:22:41 +0100 Subject: [PATCH 49/96] Doc: Describe new supported LSP services Change-Id: I3e0e9b92945b48ffa2f349924762f6bb0fef3c87 Reviewed-by: David Schulz --- .../editors/creator-only/creator-language-server.qdoc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc index df6335e9c01..b6c09ff1f4a 100644 --- a/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc +++ b/doc/qtcreator/src/editors/creator-only/creator-language-server.qdoc @@ -38,15 +38,22 @@ \list \li \l{Completing Code}{Code completion} + \li Sending document formatting requests to the language server to + automatically format documents using the settings specified in + \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} + > \uicontrol Behavior \li Highlighting the symbol under cursor + \li \l{Viewing Function Tooltips}{Viewing function tooltips} \li \l{Semantic Highlighting}{Semantic highlighting}, as defined in \l{https://github.com/microsoft/vscode-languageserver-node/pull/367} {Proposal of the semantic highlighting protocol extension} \li Navigating in the code by using the \l{Searching with the Locator} {locator} or \l{Moving to Symbol Definition or Declaration} {moving to the symbol definition} - \li Inspecting code by viewing the document - \l{Viewing Defined Types and Symbols}{outline} + \li Inspecting code by viewing the document outline in the + \l{Viewing Defined Types and Symbols}{Outline} view or + in the \uicontrol Symbols list on the \l{Using the Editor Toolbar} + {editor toolbar} \li \l{Finding Symbols}{Finding references to symbols} \li Code actions \li Integrating diagnostics from the language server From c7e2ba9c14174044375cb62b0f750284620a32d5 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 2 Mar 2020 14:19:44 +0100 Subject: [PATCH 50/96] LanguageClient: Fix passing proposals Pass the real proposals around instead of a copied nullptr. Change-Id: I1a8678bcbd5838113f6416b6f63d92d6cceceb3f Reviewed-by: David Schulz --- .../languageclientcompletionassist.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/plugins/languageclient/languageclientcompletionassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp index 54b9740809c..8b5aa94dba1 100644 --- a/src/plugins/languageclient/languageclientcompletionassist.cpp +++ b/src/plugins/languageclient/languageclientcompletionassist.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -362,19 +361,18 @@ void LanguageClientCompletionAssistProcessor::cancel() void LanguageClientCompletionAssistProcessor::handleCompletionResponse( const CompletionRequest::Response &response) { - LanguageClientCompletionProposal *proposal = nullptr; // We must report back to the code assistant under all circumstances - Utils::ExecuteOnDestruction eod([this, proposal]() { setAsyncProposalAvailable(proposal); }); qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : got completions"; m_currentRequest = MessageId(); - QTC_ASSERT(m_client, return); - if (auto error = response.error()) { + QTC_ASSERT(m_client, setAsyncProposalAvailable(nullptr); return); + if (auto error = response.error()) m_client->log(error.value()); + + const Utils::optional &result = response.result(); + if (!result || Utils::holds_alternative(*result)) { + setAsyncProposalAvailable(nullptr); return; } - const Utils::optional &result = response.result(); - if (!result || Utils::holds_alternative(*result)) - return; QList items; if (Utils::holds_alternative(*result)) { @@ -387,11 +385,12 @@ void LanguageClientCompletionAssistProcessor::handleCompletionResponse( model->loadContent(Utils::transform(items, [](const CompletionItem &item){ return static_cast(new LanguageClientCompletionItem(item)); })); - proposal = new LanguageClientCompletionProposal(m_pos, model); + LanguageClientCompletionProposal *proposal = new LanguageClientCompletionProposal(m_pos, model); proposal->m_document = m_document; proposal->m_pos = m_pos; proposal->setFragile(true); proposal->setSupportsPrefix(false); + setAsyncProposalAvailable(proposal); qCDebug(LOGLSPCOMPLETION) << QTime::currentTime() << " : " << items.count() << " completions handled"; } From 757628bf4a4a323d580f05e2362ebeed3415603b Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 2 Mar 2020 15:13:25 +0100 Subject: [PATCH 51/96] ProjectExplorer: Fix Project::setExtraProjectFiles() This function was buggy and could erroneously un-watch all the project files after the first update. Change-Id: I528fd8da7f873598e08f4c0177757a052fbb97ef Reviewed-by: hjk --- src/plugins/projectexplorer/project.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 292f81a4cd4..5e511fcedaf 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -362,8 +362,8 @@ void Project::setExtraProjectFiles(const QVector &projectDocume QSet existingWatches = Utils::transform(d->m_extraProjectDocuments, &Core::IDocument::filePath); - QSet toAdd = uniqueNewFiles.subtract(existingWatches); - QSet toRemove = existingWatches.subtract(uniqueNewFiles); + const QSet toAdd = uniqueNewFiles - existingWatches; + const QSet toRemove = existingWatches - uniqueNewFiles; Utils::erase(d->m_extraProjectDocuments, [&toRemove](const std::unique_ptr &d) { return toRemove.contains(d->filePath()); From b0b50257ecbac450d74982e600f0586e507c8fd2 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 2 Mar 2020 18:34:12 +0100 Subject: [PATCH 52/96] ProjectExplorer: Pass extra project files as QSet They are available in some cases as such, and consumed as such. Change-Id: I9866c7d7bd817fb19a8b11a0efbe583ed55fe393 Reviewed-by: Christian Kandeler --- .../autotoolsprojectmanager/autotoolsbuildsystem.cpp | 6 +++--- src/plugins/cmakeprojectmanager/builddirmanager.cpp | 4 ++-- src/plugins/cmakeprojectmanager/builddirmanager.h | 2 +- src/plugins/cmakeprojectmanager/builddirreader.h | 2 +- src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp | 2 +- src/plugins/cmakeprojectmanager/fileapireader.cpp | 4 ++-- src/plugins/cmakeprojectmanager/fileapireader.h | 2 +- src/plugins/cmakeprojectmanager/servermodereader.h | 2 +- src/plugins/cmakeprojectmanager/tealeafreader.cpp | 4 ++-- src/plugins/cmakeprojectmanager/tealeafreader.h | 2 +- src/plugins/projectexplorer/project.cpp | 4 ++-- src/plugins/projectexplorer/project.h | 2 +- src/plugins/qbsprojectmanager/qbsproject.cpp | 4 ++-- src/plugins/qmakeprojectmanager/qmakeproject.cpp | 4 ++-- 14 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp index 2345a890768..a6cacabaa26 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsbuildsystem.cpp @@ -110,7 +110,7 @@ void AutotoolsBuildSystem::makefileParsingFinished() m_files.clear(); - QVector filesToWatch; + QSet filesToWatch; // Apply sources to m_files, which are returned at AutotoolsBuildSystem::files() const QFileInfo fileInfo = projectFilePath().toFileInfo(); @@ -127,7 +127,7 @@ void AutotoolsBuildSystem::makefileParsingFinished() m_files.append(absMakefile); - filesToWatch.append(Utils::FilePath::fromString(absMakefile)); + filesToWatch.insert(Utils::FilePath::fromString(absMakefile)); } // Add configure.ac file to project and watch for changes. @@ -137,7 +137,7 @@ void AutotoolsBuildSystem::makefileParsingFinished() const QString absConfigureAc = dir.absoluteFilePath(configureAc); m_files.append(absConfigureAc); - filesToWatch.append(Utils::FilePath::fromString(absConfigureAc)); + filesToWatch.insert(Utils::FilePath::fromString(absConfigureAc)); } auto newRoot = std::make_unique(project()->projectDirectory()); diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index d4d90a7a941..75790bee87e 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -390,7 +390,7 @@ void BuildDirManager::parse() reparseParameters & REPARSE_FORCE_CONFIGURATION); } -QVector BuildDirManager::takeProjectFilesToWatch() +QSet BuildDirManager::projectFilesToWatch() const { QTC_ASSERT(!m_isHandlingError, return {}); QTC_ASSERT(m_reader, return {}); @@ -398,7 +398,7 @@ QVector BuildDirManager::takeProjectFilesToWatch() Utils::FilePath sourceDir = m_parameters.sourceDirectory; Utils::FilePath buildDir = m_parameters.workDirectory; - return Utils::filtered(m_reader->takeProjectFilesToWatch(), + return Utils::filtered(m_reader->projectFilesToWatch(), [&sourceDir, &buildDir](const Utils::FilePath &p) { return p.isChildOf(sourceDir) diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h index 00085952a33..3138b24a813 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.h +++ b/src/plugins/cmakeprojectmanager/builddirmanager.h @@ -89,7 +89,7 @@ public: bool isFilesystemScanRequested() const; void parse(); - QVector takeProjectFilesToWatch(); + QSet projectFilesToWatch() const; std::unique_ptr generateProjectTree(const QList &allFiles, QString &errorMessage) const; ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage) const; diff --git a/src/plugins/cmakeprojectmanager/builddirreader.h b/src/plugins/cmakeprojectmanager/builddirreader.h index bd04f5676d2..71b5edb974f 100644 --- a/src/plugins/cmakeprojectmanager/builddirreader.h +++ b/src/plugins/cmakeprojectmanager/builddirreader.h @@ -63,7 +63,7 @@ public: virtual bool isParsing() const = 0; - virtual QVector takeProjectFilesToWatch() = 0; + virtual QSet projectFilesToWatch() const = 0; virtual QList takeBuildTargets(QString &errorMessage) = 0; virtual CMakeConfig takeParsedConfiguration(QString &errorMessage) = 0; virtual std::unique_ptr generateProjectTree( diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 2045a84cd28..c346e368ef0 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -409,7 +409,7 @@ void CMakeBuildSystem::updateProjectData() QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return); - m_buildConfiguration->project()->setExtraProjectFiles(m_buildDirManager.takeProjectFilesToWatch()); + m_buildConfiguration->project()->setExtraProjectFiles(m_buildDirManager.projectFilesToWatch()); CMakeConfig patchedConfig = m_buildConfiguration->configurationFromCMake(); { diff --git a/src/plugins/cmakeprojectmanager/fileapireader.cpp b/src/plugins/cmakeprojectmanager/fileapireader.cpp index 83a81f2a70e..089354dc805 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.cpp +++ b/src/plugins/cmakeprojectmanager/fileapireader.cpp @@ -164,9 +164,9 @@ bool FileApiReader::isParsing() const return m_isParsing; } -QVector FileApiReader::takeProjectFilesToWatch() +QSet FileApiReader::projectFilesToWatch() const { - return QVector::fromList(Utils::toList(m_cmakeFiles)); + return m_cmakeFiles; } QList FileApiReader::takeBuildTargets(QString &errorMessage){ diff --git a/src/plugins/cmakeprojectmanager/fileapireader.h b/src/plugins/cmakeprojectmanager/fileapireader.h index 2d0c1a5809a..560aafc779a 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.h +++ b/src/plugins/cmakeprojectmanager/fileapireader.h @@ -62,7 +62,7 @@ public: bool isParsing() const final; - QVector takeProjectFilesToWatch() final; + QSet projectFilesToWatch() const final; QList takeBuildTargets(QString &errorMessage) final; CMakeConfig takeParsedConfiguration(QString &errorMessage) final; std::unique_ptr generateProjectTree( diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h index dbf91b25296..3910df1778f 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.h +++ b/src/plugins/cmakeprojectmanager/servermodereader.h @@ -55,7 +55,7 @@ public: bool isParsing() const final; - QVector takeProjectFilesToWatch() final { return {}; }; + QSet projectFilesToWatch() const final { return {}; }; QList takeBuildTargets(QString &errorMessage) final; CMakeConfig takeParsedConfiguration(QString &errorMessage) final; std::unique_ptr generateProjectTree( diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 31f13234a6e..8b03b33f608 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -160,9 +160,9 @@ bool TeaLeafReader::isParsing() const return m_cmakeProcess && m_cmakeProcess->state() != QProcess::NotRunning; } -QVector TeaLeafReader::takeProjectFilesToWatch() +QSet TeaLeafReader::projectFilesToWatch() const { - return transform(m_cmakeFiles, [](const FilePath &p) { return p; }); + return m_cmakeFiles; } QList TeaLeafReader::takeBuildTargets(QString &errorMessage) diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.h b/src/plugins/cmakeprojectmanager/tealeafreader.h index b8dd9996359..ae77afc47ca 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.h +++ b/src/plugins/cmakeprojectmanager/tealeafreader.h @@ -54,7 +54,7 @@ public: bool isParsing() const final; - QVector takeProjectFilesToWatch() final; + QSet projectFilesToWatch() const final; QList takeBuildTargets(QString &errorMessage) final; CMakeConfig takeParsedConfiguration(QString &errorMessage) final; std::unique_ptr generateProjectTree( diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 5e511fcedaf..f338b3bfafc 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -354,9 +354,9 @@ void Project::setNeedsInitialExpansion(bool needsExpansion) d->m_needsInitialExpansion = needsExpansion; } -void Project::setExtraProjectFiles(const QVector &projectDocumentPaths) +void Project::setExtraProjectFiles(const QSet &projectDocumentPaths) { - QSet uniqueNewFiles = Utils::toSet(projectDocumentPaths); + QSet uniqueNewFiles = projectDocumentPaths; uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file! QSet existingWatches = Utils::transform(d->m_extraProjectDocuments, diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 5fb9c3ad8e7..b93e273a068 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -164,7 +164,7 @@ public: // Set project files that will be watched and trigger the same callback // as the main project file. - void setExtraProjectFiles(const QVector &projectDocumentPaths); + void setExtraProjectFiles(const QSet &projectDocumentPaths); void setDisplayName(const QString &name); void setProjectLanguage(Core::Id id, bool enabled); diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 090bfae0afd..f0de5fe9522 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -700,13 +700,13 @@ void QbsBuildSystem::updateDocuments() OpTimer opTimer("updateDocuments"); const FilePath buildDir = FilePath::fromString( m_projectData.value("build-directory").toString()); - const auto filePaths = transform>( + const auto filePaths = transform>( m_projectData.value("build-system-files").toArray(), [](const QJsonValue &v) { return FilePath::fromString(v.toString()); }); // A changed qbs file (project, module etc) should trigger a re-parse, but not if // the file was generated by qbs itself, in which case that might cause an infinite loop. - const QVector nonBuildDirFilePaths = filtered(filePaths, + const QSet nonBuildDirFilePaths = filtered(filePaths, [buildDir](const FilePath &p) { return !p.isChildOf(buildDir); }); diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index e337f84ed53..58e7b48d872 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -263,9 +263,9 @@ void QmakeBuildSystem::updateCodeModels() void QmakeBuildSystem::updateDocuments() { - QVector projectDocuments; + QSet projectDocuments; project()->rootProjectNode()->forEachProjectNode([&projectDocuments](const ProjectNode *n) { - projectDocuments << n->filePath(); + projectDocuments.insert(n->filePath()); }); project()->setExtraProjectFiles(projectDocuments); } From fb252248be81674f08f9122438b72dc11a0ef8ea Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 26 Feb 2020 15:05:29 +0200 Subject: [PATCH 53/96] Improve simpleprojectwizard - add Qt modules - add support for cmake build-system Change-Id: I80ea5ef78bbffedf8f2c140365ee31718e7ee4a4 Reviewed-by: Alessandro Portale --- .../wizards/simpleprojectwizard.cpp | 148 ++++++++++++++++-- 1 file changed, 139 insertions(+), 9 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp index f601b4c5a12..a169e3d4484 100644 --- a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -43,9 +44,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -72,10 +75,14 @@ public: void cleanupPage() override { m_filesWidget->cancelParsing(); } FilePaths selectedFiles() const { return m_filesWidget->selectedFiles(); } FilePaths selectedPaths() const { return m_filesWidget->selectedPaths(); } + QString qtModules() const { return m_qtModules; } + QString buildSystem() const { return m_buildSystem; } private: SimpleProjectWizardDialog *m_simpleProjectWizardDialog; SelectableFilesWidget *m_filesWidget; + QString m_qtModules; + QString m_buildSystem; }; FilesSelectionWizardPage::FilesSelectionWizardPage(SimpleProjectWizardDialog *simpleProjectWizard) @@ -83,6 +90,31 @@ FilesSelectionWizardPage::FilesSelectionWizardPage(SimpleProjectWizardDialog *si m_filesWidget(new SelectableFilesWidget(this)) { auto layout = new QVBoxLayout(this); + { + auto hlayout = new QHBoxLayout; + hlayout->addWidget(new QLabel("Qt modules", this)); + auto lineEdit = new QLineEdit("core gui widgets", this); + connect(lineEdit, &QLineEdit::editingFinished, this, [this, lineEdit]{ + m_qtModules = lineEdit->text(); + }); + m_qtModules = lineEdit->text(); + hlayout->addWidget(lineEdit); + layout->addLayout(hlayout); + } + + { + auto hlayout = new QHBoxLayout; + hlayout->addWidget(new QLabel("Build system", this)); + auto comboBox = new QComboBox(this); + connect(comboBox, &QComboBox::currentTextChanged, this, [this](const QString &bs){ + m_buildSystem = bs; + }); + comboBox->addItems(QStringList() << "qmake" << "cmake"); + comboBox->setEditable(false); + comboBox->setCurrentText("qmake"); + hlayout->addWidget(comboBox); + layout->addLayout(hlayout); + } layout->addWidget(m_filesWidget); m_filesWidget->setBaseDirEditable(false); @@ -119,6 +151,8 @@ public: void setPath(const QString &path) { m_firstPage->setPath(path); } FilePaths selectedFiles() const { return m_secondPage->selectedFiles(); } FilePaths selectedPaths() const { return m_secondPage->selectedPaths(); } + QString qtModules() const { return m_secondPage->qtModules(); } + QString buildSystem() const { return m_secondPage->buildSystem(); } QString projectName() const { return m_firstPage->fileName(); } FileWizardPage *m_firstPage; @@ -133,14 +167,15 @@ void FilesSelectionWizardPage::initializePage() SimpleProjectWizard::SimpleProjectWizard() { - setSupportedProjectTypes({Constants::QMAKEPROJECT_ID}); + setSupportedProjectTypes({QmakeProjectManager::Constants::QMAKEPROJECT_ID, + CMakeProjectManager::Constants::CMAKEPROJECT_ID}); setIcon(QIcon(QLatin1String(":/qmakeprojectmanager/images/qmakeprojectmanager.png"))); - setDisplayName(tr("Import as qmake Project (Limited Functionality)")); + setDisplayName(tr("Import as qmake or cmake Project (Limited Functionality)")); setId("Z.DummyProFile"); setDescription(tr("Imports existing projects that do not use qmake, CMake or Autotools.

" - "This creates a qmake .pro file that allows you to use %1 as a code editor " + "This creates a project file that allows you to use %1 as a code editor " "and as a launcher for debugging and analyzing tools. " - "If you want to build the project, you might need to edit the generated .pro file.") + "If you want to build the project, you might need to edit the generated project file.") .arg(Core::Constants::IDE_DISPLAY_NAME)); setCategory(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY); setDisplayCategory(ProjectExplorer::Constants::IMPORT_WIZARD_CATEGORY_DISPLAY); @@ -159,12 +194,10 @@ BaseFileWizard *SimpleProjectWizard::create(QWidget *parent, return wizard; } -GeneratedFiles SimpleProjectWizard::generateFiles(const QWizard *w, - QString *errorMessage) const +GeneratedFiles generateQmakeFiles(const SimpleProjectWizardDialog *wizard, + QString *errorMessage) { Q_UNUSED(errorMessage) - - auto wizard = qobject_cast(w); const QString projectPath = wizard->path(); const QDir dir(projectPath); const QString projectName = wizard->projectName(); @@ -209,15 +242,112 @@ GeneratedFiles SimpleProjectWizard::generateFiles(const QWizard *w, + " This file was created for editing the project sources only.\n" "# You may attempt to use it for building too, by modifying this file here.\n\n" "#TARGET = " + projectName + "\n\n" + "QT = " + wizard->qtModules() + "\n\n" + proHeaders + "\n\n" + proSources + "\n\n" + proIncludes + "\n\n" "#DEFINES = \n\n" - ); + ); return GeneratedFiles{generatedProFile}; } +GeneratedFiles generateCmakeFiles(const SimpleProjectWizardDialog *wizard, + QString *errorMessage) +{ + Q_UNUSED(errorMessage) + const QString projectPath = wizard->path(); + const QDir dir(projectPath); + const QString projectName = wizard->projectName(); + const QString projectFileName = QFileInfo(dir, "CMakeLists.txt").absoluteFilePath(); + const QStringList paths = Utils::transform(wizard->selectedPaths(), &FilePath::toString); + + MimeType headerType = Utils::mimeTypeForName("text/x-chdr"); + + QStringList nameFilters = headerType.globPatterns(); + + QString includes = "include_directories(\n"; + bool haveIncludes = false; + for (const QString &path : paths) { + QFileInfo fileInfo(path); + QDir thisDir(fileInfo.absoluteFilePath()); + if (!thisDir.entryList(nameFilters, QDir::Files).isEmpty()) { + QString relative = dir.relativeFilePath(path); + if (!relative.isEmpty()) { + includes.append(" " + relative + "\n"); + haveIncludes = true; + } + } + } + if (haveIncludes) + includes += ")"; + else + includes.clear(); + + QString srcs = "set (SRCS\n"; + for (const FilePath &fileName : wizard->selectedFiles()) + srcs += " " + dir.relativeFilePath(fileName.toString()) + "\n"; + srcs += ")\n"; + + QString components = "find_package(Qt5 COMPONENTS"; + QString libs = "target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE"; + bool haveQtModules = false; + for (QString c : wizard->qtModules().split(' ')) { + if (c.isEmpty()) + continue; + c[0] = c[0].toUpper(); + libs += " Qt5::" + c; + components += " " + c; + haveQtModules = true; + } + if (haveQtModules) { + libs += ")\n"; + components += " REQUIRED)"; + } else { + libs.clear(); + components.clear(); + } + + + GeneratedFile generatedProFile(projectFileName); + generatedProFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute); + generatedProFile.setContents( + "# Created by and for " + QLatin1String(Core::Constants::IDE_DISPLAY_NAME) + + " This file was created for editing the project sources only.\n" + "# You may attempt to use it for building too, by modifying this file here.\n\n" + "cmake_minimum_required(VERSION 3.5)\n" + "project("+ projectName +")\n\n" + "set(CMAKE_INCLUDE_CURRENT_DIR ON)\n" + "set(CMAKE_AUTOUIC ON)\n" + "set(CMAKE_AUTOMOC ON)\n" + "set(CMAKE_AUTORCC ON)\n" + "set(CMAKE_CXX_STANDARD 11)\n" + "set(CMAKE_CXX_STANDARD_REQUIRED ON)\n" + + components + "\n\n" + + includes + "\n\n" + + srcs + "\n\n" + "add_executable(${CMAKE_PROJECT_NAME} ${SRCS})\n\n" + + libs + ); + return GeneratedFiles{generatedProFile}; +} + +GeneratedFiles SimpleProjectWizard::generateFiles(const QWizard *w, + QString *errorMessage) const +{ + Q_UNUSED(errorMessage) + + auto wizard = qobject_cast(w); + if (wizard->buildSystem() == "qmake") + return generateQmakeFiles(wizard, errorMessage); + else if (wizard->buildSystem() == "cmake") + return generateCmakeFiles(wizard, errorMessage); + + if (errorMessage) + *errorMessage = tr("Unknown build system \"%1\"").arg(wizard->buildSystem()); + return {}; +} + bool SimpleProjectWizard::postGenerateFiles(const QWizard *w, const GeneratedFiles &l, QString *errorMessage) const { From 42b595d86556e532dbbb07c337c4884745aafda6 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 27 Feb 2020 09:22:36 +0200 Subject: [PATCH 54/96] Move SimpleProjectWizard to ProjectExplorer plugin Now SimpleProjectWizard supports also cmake buildsystem therefore qmakeprojectmanager it's not the best place to keeping it. Change-Id: I383ee89ea22e8df157cd98f644d3fd971e3c2382 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/CMakeLists.txt | 1 + .../images/importasproject.png} | Bin .../images/importasproject@2x.png} | Bin src/plugins/projectexplorer/projectexplorer.cpp | 2 ++ src/plugins/projectexplorer/projectexplorer.pro | 6 ++++-- src/plugins/projectexplorer/projectexplorer.qbs | 1 + src/plugins/projectexplorer/projectexplorer.qrc | 2 ++ .../simpleprojectwizard.cpp | 10 +++++----- .../simpleprojectwizard.h | 4 ++-- src/plugins/qmakeprojectmanager/CMakeLists.txt | 1 - .../qmakeprojectmanager/qmakeprojectmanager.pro | 2 -- .../qmakeprojectmanager/qmakeprojectmanager.qbs | 1 - .../qmakeprojectmanager/qmakeprojectmanager.qrc | 2 -- .../qmakeprojectmanagerplugin.cpp | 4 +--- 14 files changed, 18 insertions(+), 18 deletions(-) rename src/plugins/{qmakeprojectmanager/images/qmakeprojectmanager.png => projectexplorer/images/importasproject.png} (100%) rename src/plugins/{qmakeprojectmanager/images/qmakeprojectmanager@2x.png => projectexplorer/images/importasproject@2x.png} (100%) rename src/plugins/{qmakeprojectmanager/wizards => projectexplorer}/simpleprojectwizard.cpp (98%) rename src/plugins/{qmakeprojectmanager/wizards => projectexplorer}/simpleprojectwizard.h (96%) diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt index 60176adceed..a7aa76ae502 100644 --- a/src/plugins/projectexplorer/CMakeLists.txt +++ b/src/plugins/projectexplorer/CMakeLists.txt @@ -163,6 +163,7 @@ add_qtc_plugin(ProjectExplorer sessionview.cpp sessionview.h showineditortaskhandler.cpp showineditortaskhandler.h showoutputtaskhandler.cpp showoutputtaskhandler.h + simpleprojectwizard.cpp simpleprojectwizard.h target.cpp target.h targetsettingspanel.cpp targetsettingspanel.h targetsetuppage.cpp targetsetuppage.h diff --git a/src/plugins/qmakeprojectmanager/images/qmakeprojectmanager.png b/src/plugins/projectexplorer/images/importasproject.png similarity index 100% rename from src/plugins/qmakeprojectmanager/images/qmakeprojectmanager.png rename to src/plugins/projectexplorer/images/importasproject.png diff --git a/src/plugins/qmakeprojectmanager/images/qmakeprojectmanager@2x.png b/src/plugins/projectexplorer/images/importasproject@2x.png similarity index 100% rename from src/plugins/qmakeprojectmanager/images/qmakeprojectmanager@2x.png rename to src/plugins/projectexplorer/images/importasproject@2x.png diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 862ea2864a5..71a0ec5468c 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -98,6 +98,7 @@ #include "targetsettingspanel.h" #include "projectpanelfactory.h" #include "projectexplorericons.h" +#include "simpleprojectwizard.h" #include "windebuginterface.h" #include "msvctoolchain.h" @@ -708,6 +709,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er QList result; result << CustomWizard::createWizards(); result << JsonWizardFactory::createWizardFactories(); + result << new SimpleProjectWizard; return result; }); diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index aa3fc2eb546..e9357a8e651 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -166,7 +166,8 @@ HEADERS += projectexplorer.h \ parseissuesdialog.h \ projectconfigurationaspects.h \ treescanner.h \ - rawprojectpart.h + rawprojectpart.h \ + simpleprojectwizard.h SOURCES += projectexplorer.cpp \ abi.cpp \ @@ -313,7 +314,8 @@ SOURCES += projectexplorer.cpp \ parseissuesdialog.cpp \ projectconfigurationaspects.cpp \ treescanner.cpp \ - rawprojectpart.cpp + rawprojectpart.cpp \ + simpleprojectwizard.cpp FORMS += \ editorsettingspropertiespage.ui \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 4b8bb4b8941..a3d53a22627 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -143,6 +143,7 @@ Project { "sessiondialog.cpp", "sessiondialog.h", "sessiondialog.ui", "showineditortaskhandler.cpp", "showineditortaskhandler.h", "showoutputtaskhandler.cpp", "showoutputtaskhandler.h", + "simpleprojectwizard.cpp", "simpleprojectwizard.h", "target.cpp", "target.h", "targetsettingspanel.cpp", "targetsettingspanel.h", "targetsetuppage.cpp", "targetsetuppage.h", diff --git a/src/plugins/projectexplorer/projectexplorer.qrc b/src/plugins/projectexplorer/projectexplorer.qrc index 36b149e2538..0f5e0dc3069 100644 --- a/src/plugins/projectexplorer/projectexplorer.qrc +++ b/src/plugins/projectexplorer/projectexplorer.qrc @@ -86,5 +86,7 @@ images/settingscategory_kits@2x.png images/settingscategory_cpp.png images/settingscategory_cpp@2x.png + images/importasproject.png + images/importasproject@2x.png diff --git a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp b/src/plugins/projectexplorer/simpleprojectwizard.cpp similarity index 98% rename from src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp rename to src/plugins/projectexplorer/simpleprojectwizard.cpp index a169e3d4484..d9d88aa3158 100644 --- a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.cpp +++ b/src/plugins/projectexplorer/simpleprojectwizard.cpp @@ -25,7 +25,7 @@ #include "simpleprojectwizard.h" -#include +#include "projectexplorerconstants.h" #include @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -56,10 +57,9 @@ #include using namespace Core; -using namespace ProjectExplorer; using namespace Utils; -namespace QmakeProjectManager { +namespace ProjectExplorer { namespace Internal { class SimpleProjectWizardDialog; @@ -169,7 +169,7 @@ SimpleProjectWizard::SimpleProjectWizard() { setSupportedProjectTypes({QmakeProjectManager::Constants::QMAKEPROJECT_ID, CMakeProjectManager::Constants::CMAKEPROJECT_ID}); - setIcon(QIcon(QLatin1String(":/qmakeprojectmanager/images/qmakeprojectmanager.png"))); + setIcon(QIcon(QLatin1String(":/projectexplorer/images/importasproject.png"))); setDisplayName(tr("Import as qmake or cmake Project (Limited Functionality)")); setId("Z.DummyProFile"); setDescription(tr("Imports existing projects that do not use qmake, CMake or Autotools.

" @@ -356,6 +356,6 @@ bool SimpleProjectWizard::postGenerateFiles(const QWizard *w, const GeneratedFil } } // namespace Internal -} // namespace QmakeProjectManager +} // namespace GenericProjectManager #include "simpleprojectwizard.moc" diff --git a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.h b/src/plugins/projectexplorer/simpleprojectwizard.h similarity index 96% rename from src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.h rename to src/plugins/projectexplorer/simpleprojectwizard.h index ee1f794c3e0..d4bcce5616f 100644 --- a/src/plugins/qmakeprojectmanager/wizards/simpleprojectwizard.h +++ b/src/plugins/projectexplorer/simpleprojectwizard.h @@ -27,7 +27,7 @@ #include -namespace QmakeProjectManager { +namespace ProjectExplorer { namespace Internal { class SimpleProjectWizard : public Core::BaseFileWizardFactory @@ -45,4 +45,4 @@ private: }; } // namespace Internal -} // namespace QmakeProjectManager +} // namespace ProjectExplorer diff --git a/src/plugins/qmakeprojectmanager/CMakeLists.txt b/src/plugins/qmakeprojectmanager/CMakeLists.txt index 835913cac3a..90d48c0347e 100644 --- a/src/plugins/qmakeprojectmanager/CMakeLists.txt +++ b/src/plugins/qmakeprojectmanager/CMakeLists.txt @@ -41,7 +41,6 @@ add_qtc_plugin(QmakeProjectManager qmakestep.cpp qmakestep.h wizards/qtprojectparameters.cpp wizards/qtprojectparameters.h wizards/qtwizard.cpp wizards/qtwizard.h - wizards/simpleprojectwizard.cpp wizards/simpleprojectwizard.h wizards/subdirsprojectwizard.cpp wizards/subdirsprojectwizard.h wizards/subdirsprojectwizarddialog.cpp wizards/subdirsprojectwizarddialog.h wizards/wizards.qrc diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro index ee5e931c9ad..aa56251ada3 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro @@ -22,7 +22,6 @@ HEADERS += \ wizards/qtwizard.h \ wizards/subdirsprojectwizard.h \ wizards/subdirsprojectwizarddialog.h \ - wizards/simpleprojectwizard.h \ qmakeprojectmanagerconstants.h \ qmakestep.h \ externaleditors.h \ @@ -52,7 +51,6 @@ SOURCES += \ wizards/qtwizard.cpp \ wizards/subdirsprojectwizard.cpp \ wizards/subdirsprojectwizarddialog.cpp \ - wizards/simpleprojectwizard.cpp \ qmakestep.cpp \ externaleditors.cpp \ qmakebuildconfiguration.cpp \ diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs index 7b23de4e178..24a4fce4315 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs @@ -78,7 +78,6 @@ Project { "qtwizard.cpp", "qtwizard.h", "subdirsprojectwizard.cpp", "subdirsprojectwizard.h", "subdirsprojectwizarddialog.cpp", "subdirsprojectwizarddialog.h", - "simpleprojectwizard.cpp", "simpleprojectwizard.h", "wizards.qrc" ] } diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc index 87248770da4..8e13ebeeb5d 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qrc @@ -3,7 +3,5 @@ images/dark_headers.png images/dark_sources.png images/dark_unknown.png - images/qmakeprojectmanager.png - images/qmakeprojectmanager@2x.png diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index 21978b33c24..6ca690f6f06 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -32,7 +32,6 @@ #include "qmakestep.h" #include "qmakemakestep.h" #include "qmakebuildconfiguration.h" -#include "wizards/simpleprojectwizard.h" #include "wizards/subdirsprojectwizard.h" #include "customwidgetwizard/customwidgetwizard.h" #include "qmakeprojectmanagerconstants.h" @@ -145,8 +144,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString IWizardFactory::registerFactoryCreator([] { return QList { new SubdirsProjectWizard, - new CustomWidgetWizard, - new SimpleProjectWizard + new CustomWidgetWizard }; }); From daa9804699711aa71479e3fcb590fc806f46ce1c Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 26 Feb 2020 16:41:52 +0100 Subject: [PATCH 55/96] McuSupport: Prepare support for more toolchains than GNU Arm Embedded Move all hardcoded arm-specific strings and code into the new McuToolChainPackage class (which will later support IAR and KEIL). In the same change: Adjust paths in CMake options to latest Qul path changes in the master branch. Change-Id: Iefa205729588a3efa783eb9eaaa339ed9f8e2813 Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/mcusupportoptions.cpp | 218 ++++++++++-------- src/plugins/mcusupport/mcusupportoptions.h | 36 ++- .../mcusupport/mcusupportoptionspage.cpp | 1 - 3 files changed, 154 insertions(+), 101 deletions(-) diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 8b514534c82..d13e2e018d8 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -195,12 +195,101 @@ void McuPackage::updateStatus() m_infoLabel->setText(statusText); } +McuToolChainPackage::McuToolChainPackage(const QString &label, const QString &defaultPath, + const QString &detectionPath, const QString &settingsKey, + McuToolChainPackage::Type type) + : McuPackage(label, defaultPath, detectionPath, settingsKey) + , m_type(type) +{ +} + +McuToolChainPackage::Type McuToolChainPackage::type() const +{ + return m_type; +} + +static ProjectExplorer::ToolChain* armGccToolChain(const Utils::FilePath &path, Core::Id language) +{ + using namespace ProjectExplorer; + + ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){ + return t->compilerCommand() == path && t->language() == language; + }); + if (!toolChain) { + ToolChainFactory *gccFactory = + Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){ + return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; + }); + if (gccFactory) { + const QList detected = gccFactory->detectForImport({path, language}); + if (!detected.isEmpty()) { + toolChain = detected.first(); + toolChain->setDetection(ToolChain::ManualDetection); + toolChain->setDisplayName("Arm GCC"); + ToolChainManager::registerToolChain(toolChain); + } + } + } + + return toolChain; +} + +ProjectExplorer::ToolChain *McuToolChainPackage::toolChain(Core::Id language) const +{ + const QLatin1String compilerName( + language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++"); + const Utils::FilePath compiler = Utils::FilePath::fromUserInput( + Utils::HostOsInfo::withExecutableSuffix( + path() + ( + m_type == TypeArmGcc + ? "/bin/arm-none-eabi-%1" : m_type == TypeIAR + ? "/foo/bar-iar-%1" : "/bar/foo-keil-%1")).arg(compilerName)); + + ProjectExplorer::ToolChain *tc = armGccToolChain(compiler, language); + return tc; +} + +QString McuToolChainPackage::cmakeToolChainFileName() const +{ + return QLatin1String(m_type == TypeArmGcc + ? "armgcc.cmake" : m_type == McuToolChainPackage::TypeIAR + ? "iar.cmake" : "keil.cmake"); +} + +QVariant McuToolChainPackage::debuggerId() const +{ + using namespace Debugger; + + const Utils::FilePath command = Utils::FilePath::fromUserInput( + Utils::HostOsInfo::withExecutableSuffix(path() + ( + m_type == TypeArmGcc + ? "/bin/arm-none-eabi-gdb-py" : m_type == TypeIAR + ? "/foo/bar-iar-gdb" : "/bar/foo-keil-gdb"))); + const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command); + QVariant debuggerId; + if (!debugger) { + DebuggerItem newDebugger; + newDebugger.setCommand(command); + const QString displayName = + m_type == TypeArmGcc + ? tr("Arm GDB at %1") : m_type == TypeIAR + ? QLatin1String("/foo/bar-iar-gdb") : QLatin1String("/bar/foo-keil-gdb"); + newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput())); + debuggerId = DebuggerItemManager::registerDebugger(newDebugger); + } else { + debuggerId = debugger->id(); + } + return debuggerId; +} + McuTarget::McuTarget(const QString &vendor, const QString &platform, - const QVector &packages) + const QVector &packages, McuToolChainPackage *toolChainPackage) : m_vendor(vendor) , m_qulPlatform(platform) , m_packages(packages) + , m_toolChainPackage(toolChainPackage) { + QTC_CHECK(m_toolChainPackage == nullptr || m_packages.contains(m_toolChainPackage)); } QString McuTarget::vendor() const @@ -213,14 +302,9 @@ QVector McuTarget::packages() const return m_packages; } -void McuTarget::setToolChainFile(const QString &toolChainFile) +McuToolChainPackage *McuTarget::toolChainPackage() const { - m_toolChainFile = toolChainFile; -} - -QString McuTarget::toolChainFile() const -{ - return m_toolChainFile; + return m_toolChainPackage; } QString McuTarget::qulPlatform() const @@ -269,7 +353,7 @@ static McuPackage *createQtForMCUsPackage() return result; } -static McuPackage *createArmGccPackage() +static McuToolChainPackage *createArmGccPackage() { const char envVar[] = "ARMGCC_DIR"; @@ -290,11 +374,12 @@ static McuPackage *createArmGccPackage() if (defaultPath.isEmpty()) defaultPath = QDir::homePath(); - auto result = new McuPackage( + auto result = new McuToolChainPackage( McuPackage::tr("GNU Arm Embedded Toolchain"), defaultPath, Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"), - "GNUArmEmbeddedToolchain"); + "GNUArmEmbeddedToolchain", + McuToolChainPackage::TypeArmGcc); result->setDownloadUrl( "https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads"); result->setEnvironmentVariableName(envVar); @@ -368,19 +453,19 @@ static McuPackage *createSeggerJLinkPackage() McuSupportOptions::McuSupportOptions(QObject *parent) : QObject(parent) + , qtForMCUsSdkPackage(createQtForMCUsPackage()) { - qtForMCUsSdkPackage = createQtForMCUsPackage(); - armGccPackage = createArmGccPackage(); + McuToolChainPackage* armGccPackage = createArmGccPackage(); McuPackage* stm32CubeFwF7SdkPackage = createStm32CubeFwF7SdkPackage(); McuPackage* stm32CubeProgrammerPackage = createStm32CubeProgrammerPackage(); McuPackage* evkbImxrt1050SdkPackage = createEvkbImxrt1050SdkPackage(); McuPackage* seggerJLinkPackage = createSeggerJLinkPackage(); - auto stmEvalPackages = { + QVector stmEvalPackages = { armGccPackage, stm32CubeProgrammerPackage, qtForMCUsSdkPackage}; - auto nxpEvalPackages = { + QVector nxpEvalPackages = { armGccPackage, seggerJLinkPackage, qtForMCUsSdkPackage}; - auto desktopPackages = { + QVector desktopPackages = { qtForMCUsSdkPackage}; packages = { armGccPackage, stm32CubeFwF7SdkPackage, stm32CubeProgrammerPackage, evkbImxrt1050SdkPackage, @@ -390,30 +475,25 @@ McuSupportOptions::McuSupportOptions(QObject *parent) const QString vendorNxp = "NXP"; const QString vendorQt = "Qt"; - const QString armGccToochainFile = "CMake/toolchain/armgcc.cmake"; - // STM - auto mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages); - mcuTarget->setToolChainFile(armGccToochainFile); + auto mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages, + armGccPackage); mcuTarget->setColorDepth(32); mcuTargets.append(mcuTarget); - mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages); - mcuTarget->setToolChainFile(armGccToochainFile); + mcuTarget = new McuTarget(vendorStm, "STM32F7508-DISCOVERY", stmEvalPackages, armGccPackage); mcuTarget->setColorDepth(16); mcuTargets.append(mcuTarget); - mcuTarget = new McuTarget(vendorStm, "STM32F769I-DISCOVERY", stmEvalPackages); - mcuTarget->setToolChainFile(armGccToochainFile); + mcuTarget = new McuTarget(vendorStm, "STM32F769I-DISCOVERY", stmEvalPackages, armGccPackage); mcuTargets.append(mcuTarget); // NXP - mcuTarget = new McuTarget(vendorNxp, "MIMXRT1050-EVK", nxpEvalPackages); - mcuTarget->setToolChainFile(armGccToochainFile); + mcuTarget = new McuTarget(vendorNxp, "MIMXRT1050-EVK", nxpEvalPackages, armGccPackage); mcuTargets.append(mcuTarget); // Desktop (Qt) - mcuTarget = new McuTarget(vendorQt, "Qt", desktopPackages); + mcuTarget = new McuTarget(vendorQt, "Qt", desktopPackages, nullptr); mcuTarget->setColorDepth(32); mcuTargets.append(mcuTarget); @@ -431,32 +511,6 @@ McuSupportOptions::~McuSupportOptions() mcuTargets.clear(); } -static ProjectExplorer::ToolChain* armGccToolchain(const Utils::FilePath &path, Core::Id language) -{ - using namespace ProjectExplorer; - - ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){ - return t->compilerCommand() == path && t->language() == language; - }); - if (!toolChain) { - ToolChainFactory *gccFactory = - Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){ - return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; - }); - if (gccFactory) { - const QList detected = gccFactory->detectForImport({path, language}); - if (!detected.isEmpty()) { - toolChain = detected.first(); - toolChain->setDetection(ToolChain::ManualDetection); - toolChain->setDisplayName("Arm GCC"); - ToolChainManager::registerToolChain(toolChain); - } - } - } - - return toolChain; -} - static bool mcuTargetIsDesktop(const McuTarget* mcuTarget) { return mcuTarget->qulPlatform() == "Qt"; @@ -492,48 +546,22 @@ static void setKitProperties(const QString &kitName, ProjectExplorer::Kit *k, } } -static void setKitToolchains(ProjectExplorer::Kit *k, const QString &armGccPath) +static void setKitToolchains(ProjectExplorer::Kit *k, const McuToolChainPackage *tcPackage) { - using namespace ProjectExplorer; - - const QString compileNameScheme = Utils::HostOsInfo::withExecutableSuffix( - armGccPath + "/bin/arm-none-eabi-%1"); - ToolChain *cTc = armGccToolchain( - Utils::FilePath::fromUserInput(compileNameScheme.arg("gcc")), - ProjectExplorer::Constants::C_LANGUAGE_ID); - ToolChain *cxxTc = armGccToolchain( - Utils::FilePath::fromUserInput(compileNameScheme.arg("g++")), - ProjectExplorer::Constants::CXX_LANGUAGE_ID); - ToolChainKitAspect::setToolChain(k, cTc); - ToolChainKitAspect::setToolChain(k, cxxTc); + ProjectExplorer::ToolChainKitAspect::setToolChain(k, tcPackage->toolChain( + ProjectExplorer::Constants::C_LANGUAGE_ID)); + ProjectExplorer::ToolChainKitAspect::setToolChain(k, tcPackage->toolChain( + ProjectExplorer::Constants::CXX_LANGUAGE_ID)); } -static void setKitDebugger(ProjectExplorer::Kit *k, const QString &armGccPath) +static void setKitDebugger(ProjectExplorer::Kit *k, const McuToolChainPackage *tcPackage) { - using namespace Debugger; - - const Utils::FilePath command = Utils::FilePath::fromUserInput( - Utils::HostOsInfo::withExecutableSuffix(armGccPath + "/bin/arm-none-eabi-gdb-py")); - const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command); - QVariant debuggerId; - if (!debugger) { - DebuggerItem newDebugger; - newDebugger.setCommand(command); - newDebugger.setUnexpandedDisplayName( - McuPackage::tr("Arm GDB at %1").arg(command.toUserOutput())); - debuggerId = DebuggerItemManager::registerDebugger(newDebugger); - } else { - debuggerId = debugger->id(); - } - - DebuggerKitAspect::setDebugger(k, debuggerId); + Debugger::DebuggerKitAspect::setDebugger(k, tcPackage->debuggerId()); } static void setKitDevice(ProjectExplorer::Kit *k) { - using namespace ProjectExplorer; - - DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE); + ProjectExplorer::DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE); } static void setKitEnvironment(ProjectExplorer::Kit *k, const McuTarget* mcuTarget) @@ -564,11 +592,13 @@ static void setKitCMakeOptions(ProjectExplorer::Kit *k, const McuTarget* mcuTarg CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}")); config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}")); - if (!mcuTarget->toolChainFile().isEmpty()) - config.append(CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", - (qulDir + "/" + mcuTarget->toolChainFile()).toUtf8())); + if (mcuTarget->toolChainPackage()) + config.append(CMakeConfigItem( + "CMAKE_TOOLCHAIN_FILE", + (qulDir + "/lib/cmake/Qul/toolchain/" + + mcuTarget->toolChainPackage()->cmakeToolChainFileName()).toUtf8())); config.append(CMakeConfigItem("QUL_GENERATORS", - (qulDir + "/CMake/QulGenerators.cmake").toUtf8())); + (qulDir + "/lib/cmake/Qul/QulGenerators.cmake").toUtf8())); config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->qulPlatform().toUtf8())); if (mcuTargetIsDesktop(mcuTarget)) @@ -607,15 +637,13 @@ ProjectExplorer::Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget) { using namespace ProjectExplorer; - const QString armGccPath = armGccPackage->path(); - const QString qulDir = qtForMCUsSdkPackage->path(); const auto init = [this, mcuTarget](Kit *k) { KitGuard kitGuard(k); setKitProperties(kitName(mcuTarget), k, mcuTarget); if (!mcuTargetIsDesktop(mcuTarget)) { - setKitToolchains(k, armGccPackage->path()); - setKitDebugger(k, armGccPackage->path()); + setKitToolchains(k, mcuTarget->toolChainPackage()); + setKitDebugger(k, mcuTarget->toolChainPackage()); setKitDevice(k); } setKitEnvironment(k, mcuTarget); diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index 55e75d2bfb0..deb7010f9da 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -30,6 +30,10 @@ QT_FORWARD_DECLARE_CLASS(QWidget) +namespace Core { +class Id; +} + namespace Utils { class PathChooser; class InfoLabel; @@ -37,6 +41,7 @@ class InfoLabel; namespace ProjectExplorer { class Kit; +class ToolChain; } namespace McuSupport { @@ -55,6 +60,7 @@ public: McuPackage(const QString &label, const QString &defaultPath, const QString &detectionPath, const QString &settingsKey); + virtual ~McuPackage() = default; QString path() const; QString label() const; @@ -95,17 +101,38 @@ private: Status m_status = InvalidPath; }; +class McuToolChainPackage : public McuPackage +{ +public: + enum Type { + TypeArmGcc, + TypeIAR, + TypeKEIL + }; + + McuToolChainPackage(const QString &label, const QString &defaultPath, + const QString &detectionPath, const QString &settingsKey, Type type); + + Type type() const; + ProjectExplorer::ToolChain *toolChain(Core::Id language) const; + QString cmakeToolChainFileName() const; + QVariant debuggerId() const; + +private: + const Type m_type; +}; + class McuTarget : public QObject { Q_OBJECT public: - McuTarget(const QString &vendor, const QString &platform, const QVector &packages); + McuTarget(const QString &vendor, const QString &platform, const QVector &packages, + McuToolChainPackage *toolChainPackage); QString vendor() const; QVector packages() const; - void setToolChainFile(const QString &toolChainFile); - QString toolChainFile() const; + McuToolChainPackage *toolChainPackage() const; QString qulPlatform() const; void setColorDepth(int colorDepth); int colorDepth() const; @@ -115,7 +142,7 @@ private: const QString m_vendor; const QString m_qulPlatform; const QVector m_packages; - QString m_toolChainFile; + McuToolChainPackage *m_toolChainPackage; int m_colorDepth = -1; }; @@ -129,7 +156,6 @@ public: QVector packages; QVector mcuTargets; - McuPackage *armGccPackage = nullptr; McuPackage *qtForMCUsSdkPackage = nullptr; QString kitName(const McuTarget* mcuTarget) const; diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index b63db28c656..5d72fd819df 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -183,7 +183,6 @@ void McuSupportOptionsWidget::apply() for (auto package : m_options.packages) package->writeToSettings(); - QTC_ASSERT(m_options.armGccPackage, return); QTC_ASSERT(m_options.qtForMCUsSdkPackage, return); if (!isVisible() || !cMakeAvailable()) From b081d7dc8f60d921d581112aaf67adb85ab3a345 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Fri, 28 Feb 2020 00:16:03 +0200 Subject: [PATCH 56/96] Android: allow style extraction method selection to the manifest editor Make a bit more easier to choose the method of style extraction to the manifest editor UI. Task-number: QTCREATORBUG-23283 Change-Id: I65ad52f07d31913cf091ef4ef1693617ac82d4ad Reviewed-by: Alessandro Portale --- .../android/androidmanifesteditorwidget.cpp | 48 ++++++++++++++++--- .../android/androidmanifesteditorwidget.h | 1 + 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index bc80a84ba75..18bb2d1b486 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -240,6 +240,18 @@ void AndroidManifestEditorWidget::initializePage() m_targetLineEdit->installEventFilter(this); formLayout->addRow(tr("Run:"), m_targetLineEdit); + m_styleExtractMethod = new QComboBox(applicationGroupBox); + formLayout->addRow(tr("Style extraction:"), m_styleExtractMethod); + QList styleMethodsMap = { + {"default", "In most cases this will be the same as \"full\", but it can also be something else if needed, e.g. for compatibility reasons."}, + {"full", "Useful for Qt Widgets & Qt Quick Controls 1 apps."}, + {"minimal", "Useful for Qt Quick Controls 2 apps, it is much faster than \"full\"."}, + {"none", "Useful for apps that don't use Qt Widgets, Qt Quick Controls 1 or Qt Quick Controls 2."}}; + for (int i = 0; i addItem(styleMethodsMap.at(i).at(0)); + m_styleExtractMethod->setItemData(i, styleMethodsMap.at(i).at(1), Qt::ToolTipRole); + } + auto iconLayout = new QHBoxLayout(); createDPIButton(iconLayout, @@ -297,6 +309,9 @@ void AndroidManifestEditorWidget::initializePage() this, setDirtyFunc); connect(m_targetLineEdit, &QComboBox::currentTextChanged, this, setDirtyFunc); + connect(m_styleExtractMethod, + QOverload::of(&QComboBox::currentIndexChanged), + this, setDirtyFunc); connect(m_masterIconButton, &QAbstractButton::clicked, this, &AndroidManifestEditorWidget::setMasterIcon); @@ -804,11 +819,21 @@ void AndroidManifestEditorWidget::syncToWidgets(const QDomDocument &doc) QDomElement metadataElem = activityElem.firstChildElement(QLatin1String("meta-data")); + const int parseItemsCount = 2; + int counter = 0; while (!metadataElem.isNull()) { if (metadataElem.attribute(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) { m_targetLineEdit->setEditText(metadataElem.attribute(QLatin1String("android:value"))); - break; + ++counter; + } else if (metadataElem.attribute(QLatin1String("android:name")) + == QLatin1String("android.app.extract_android_style")) { + m_styleExtractMethod->setCurrentText( + metadataElem.attribute(QLatin1String("android:value"))); + ++counter; } + + if (counter == parseItemsCount) + break; metadataElem = metadataElem.nextSiblingElement(QLatin1String("meta-data")); } @@ -1093,15 +1118,24 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt { Q_ASSERT(reader.isStartElement()); - bool found = false; + const int parseItemsCount = 2; + int counter = 0; QXmlStreamAttributes attributes = reader.attributes(); QXmlStreamAttributes result; + QStringList keys; + QStringList values; if (attributes.value(QLatin1String("android:name")) == QLatin1String("android.app.lib_name")) { - QStringList keys = QStringList("android:value"); - QStringList values = QStringList(m_targetLineEdit->currentText()); + keys = QStringList("android:value"); + values = QStringList(m_targetLineEdit->currentText()); result = modifyXmlStreamAttributes(attributes, keys, values); - found = true; + ++counter; + } else if (attributes.value(QLatin1String("android:name")) + == QLatin1String("android.app.extract_android_style")) { + keys = QStringList("android:value"); + values = QStringList(m_styleExtractMethod->currentText()); + result = modifyXmlStreamAttributes(attributes, keys, values); + ++counter; } else { result = attributes; } @@ -1114,7 +1148,7 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt while (!reader.atEnd()) { if (reader.isEndElement()) { writer.writeCurrentToken(reader); - return found; + return counter == parseItemsCount; } else if (reader.isStartElement()) { parseUnknownElement(reader, writer); } else { @@ -1122,7 +1156,7 @@ bool AndroidManifestEditorWidget::parseMetaData(QXmlStreamReader &reader, QXmlSt } reader.readNext(); } - return found; // should never be reached + return counter == parseItemsCount; // should never be reached } void AndroidManifestEditorWidget::parseUsesSdk(QXmlStreamReader &reader, QXmlStreamWriter & writer) diff --git a/src/plugins/android/androidmanifesteditorwidget.h b/src/plugins/android/androidmanifesteditorwidget.h index efbc2b529a4..8e38773cd69 100644 --- a/src/plugins/android/androidmanifesteditorwidget.h +++ b/src/plugins/android/androidmanifesteditorwidget.h @@ -189,6 +189,7 @@ private: QLineEdit *m_appNameLineEdit; QLineEdit *m_activityNameLineEdit; QComboBox *m_targetLineEdit; + QComboBox *m_styleExtractMethod; QToolButton *m_masterIconButton; QToolButton *m_lIconButton; QToolButton *m_lIconClearButton; From 75a895a7a38e2bb0abe7e88fe7b34e859bd5db62 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Fri, 28 Feb 2020 00:55:35 +0200 Subject: [PATCH 57/96] Android: place add permissions combobox on top of the list view It's more convenient to have the add permissions combobox on top of the list view, so that it would be directly visible without needing to scroll down, especially if on non-fullscreen mode or small screen. Task-number: QTCREATORBUG-23283 Change-Id: If3ef29fc91dd38f00d03ec63ce56103728c4b5f9 Reviewed-by: Alessandro Portale --- .../android/androidmanifesteditorwidget.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index 18bb2d1b486..ca14e5453c6 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -346,17 +346,6 @@ void AndroidManifestEditorWidget::initializePage() m_defaultFeaturesCheckBox->setText(tr("Include default features for Qt modules.")); layout->addWidget(m_defaultFeaturesCheckBox, 1, 0); - m_permissionsModel = new PermissionsModel(this); - - m_permissionsListView = new QListView(permissionsGroupBox); - m_permissionsListView->setModel(m_permissionsModel); - m_permissionsListView->setMinimumSize(QSize(0, 200)); - layout->addWidget(m_permissionsListView, 2, 0, 3, 1); - - m_removePermissionButton = new QPushButton(permissionsGroupBox); - m_removePermissionButton->setText(tr("Remove")); - layout->addWidget(m_removePermissionButton, 2, 1); - m_permissionsComboBox = new QComboBox(permissionsGroupBox); m_permissionsComboBox->insertItems(0, QStringList() << QLatin1String("android.permission.ACCESS_CHECKIN_PROPERTIES") @@ -491,11 +480,22 @@ void AndroidManifestEditorWidget::initializePage() << QLatin1String("android.permission.WRITE_USER_DICTIONARY") ); m_permissionsComboBox->setEditable(true); - layout->addWidget(m_permissionsComboBox, 6, 0); + layout->addWidget(m_permissionsComboBox, 2, 0); m_addPermissionButton = new QPushButton(permissionsGroupBox); m_addPermissionButton->setText(tr("Add")); - layout->addWidget(m_addPermissionButton, 6, 1); + layout->addWidget(m_addPermissionButton, 2, 1); + + m_permissionsModel = new PermissionsModel(this); + + m_permissionsListView = new QListView(permissionsGroupBox); + m_permissionsListView->setModel(m_permissionsModel); + m_permissionsListView->setMinimumSize(QSize(0, 200)); + layout->addWidget(m_permissionsListView, 3, 0, 3, 1); + + m_removePermissionButton = new QPushButton(permissionsGroupBox); + m_removePermissionButton->setText(tr("Remove")); + layout->addWidget(m_removePermissionButton, 3, 1); permissionsGroupBox->setLayout(layout); From d2bb3b0358e814e055dfd06c74ea1a7be1d61bca Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 3 Mar 2020 13:23:55 +0200 Subject: [PATCH 58/96] QmlDesigner: Update 3D Edit view icons Task-number: QDS-1691 Change-Id: I2f41a912217ba4494cf622e0ad11fac60dbd6b1b Reviewed-by: Mahmoud Badri --- .../qmldesigner/components/edit3d/edit3d.qrc | 52 +++++++++--------- .../edit3d/images/edit_light_off.png | Bin 1189 -> 174 bytes .../edit3d/images/edit_light_off@2x.png | Bin 1430 -> 325 bytes .../edit3d/images/edit_light_on.png | Bin 1355 -> 162 bytes .../edit3d/images/edit_light_on@2x.png | Bin 1766 -> 271 bytes .../components/edit3d/images/fit_active.png | Bin 266 -> 0 bytes .../edit3d/images/fit_active@2x.png | Bin 386 -> 0 bytes .../components/edit3d/images/fit_selected.png | Bin 0 -> 165 bytes .../edit3d/images/fit_selected@2x.png | Bin 0 -> 235 bytes .../components/edit3d/images/global.png | Bin 433 -> 193 bytes .../components/edit3d/images/global@2x.png | Bin 561 -> 267 bytes .../images/group_selection_selected.png | Bin 438 -> 0 bytes .../images/group_selection_selected@2x.png | Bin 904 -> 0 bytes .../edit3d/images/item_selection_selected.png | Bin 355 -> 0 bytes .../images/item_selection_selected@2x.png | Bin 661 -> 0 bytes .../components/edit3d/images/local.png | Bin 1309 -> 212 bytes .../components/edit3d/images/local@2x.png | Bin 1960 -> 371 bytes .../components/edit3d/images/move_active.png | Bin 294 -> 0 bytes .../edit3d/images/move_active@2x.png | Bin 303 -> 0 bytes .../components/edit3d/images/move_off.png | Bin 0 -> 190 bytes .../components/edit3d/images/move_off@2x.png | Bin 0 -> 250 bytes .../components/edit3d/images/move_on.png | Bin 0 -> 155 bytes .../components/edit3d/images/move_on@2x.png | Bin 0 -> 234 bytes .../edit3d/images/move_selected.png | Bin 191 -> 0 bytes .../edit3d/images/move_selected@2x.png | Bin 272 -> 0 bytes .../components/edit3d/images/ortho.png | Bin 1310 -> 0 bytes .../components/edit3d/images/ortho@2x.png | Bin 1727 -> 0 bytes .../edit3d/images/orthographic_camera.png | Bin 0 -> 190 bytes .../edit3d/images/orthographic_camera@2x.png | Bin 0 -> 295 bytes .../components/edit3d/images/persp.png | Bin 1391 -> 0 bytes .../components/edit3d/images/persp@2x.png | Bin 1971 -> 0 bytes .../edit3d/images/perspective_camera.png | Bin 0 -> 195 bytes .../edit3d/images/perspective_camera@2x.png | Bin 0 -> 355 bytes .../edit3d/images/rotate_active.png | Bin 451 -> 0 bytes .../edit3d/images/rotate_active@2x.png | Bin 869 -> 0 bytes .../components/edit3d/images/rotate_off.png | Bin 0 -> 161 bytes .../edit3d/images/rotate_off@2x.png | Bin 0 -> 287 bytes .../components/edit3d/images/rotate_on.png | Bin 0 -> 170 bytes .../components/edit3d/images/rotate_on@2x.png | Bin 0 -> 310 bytes .../edit3d/images/rotate_selected.png | Bin 478 -> 0 bytes .../edit3d/images/rotate_selected@2x.png | Bin 906 -> 0 bytes .../components/edit3d/images/scale_active.png | Bin 242 -> 0 bytes .../edit3d/images/scale_active@2x.png | Bin 338 -> 0 bytes .../components/edit3d/images/scale_off.png | Bin 0 -> 211 bytes .../components/edit3d/images/scale_off@2x.png | Bin 0 -> 301 bytes .../components/edit3d/images/scale_on.png | Bin 0 -> 198 bytes .../components/edit3d/images/scale_on@2x.png | Bin 0 -> 245 bytes .../edit3d/images/scale_selected.png | Bin 277 -> 0 bytes .../edit3d/images/scale_selected@2x.png | Bin 364 -> 0 bytes .../components/edit3d/images/select_group.png | Bin 0 -> 166 bytes .../edit3d/images/select_group@2x.png | Bin 0 -> 275 bytes .../components/edit3d/images/select_item.png | Bin 0 -> 175 bytes .../edit3d/images/select_item@2x.png | Bin 0 -> 317 bytes src/plugins/qmldesigner/qmldesignericons.h | 22 ++++---- 54 files changed, 37 insertions(+), 37 deletions(-) delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/fit_active.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/fit_active@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/fit_selected.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/fit_selected@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/group_selection_selected.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/group_selection_selected@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/item_selection_selected.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/item_selection_selected@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_active.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_active@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_off.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_off@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_on.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_on@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_selected.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/move_selected@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/ortho.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/ortho@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/orthographic_camera.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/orthographic_camera@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/persp.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/persp@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/perspective_camera.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/perspective_camera@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_active.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_active@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_off.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_off@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_on.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_on@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_selected.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/rotate_selected@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_active.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_active@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_off.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_off@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_on.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_on@2x.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_selected.png delete mode 100644 src/plugins/qmldesigner/components/edit3d/images/scale_selected@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/select_group.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/select_group@2x.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/select_item.png create mode 100644 src/plugins/qmldesigner/components/edit3d/images/select_item@2x.png diff --git a/src/plugins/qmldesigner/components/edit3d/edit3d.qrc b/src/plugins/qmldesigner/components/edit3d/edit3d.qrc index 1719b8ed63a..c0456890cd5 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3d.qrc +++ b/src/plugins/qmldesigner/components/edit3d/edit3d.qrc @@ -1,34 +1,34 @@ + images/global.png + images/global@2x.png + images/local.png + images/local@2x.png images/edit_light_off.png images/edit_light_off@2x.png images/edit_light_on.png images/edit_light_on@2x.png - images/fit_active.png - images/fit_active@2x.png - images/global.png - images/global@2x.png - images/group_selection_selected.png - images/group_selection_selected@2x.png - images/item_selection_selected.png - images/item_selection_selected@2x.png - images/local.png - images/local@2x.png - images/move_active.png - images/move_active@2x.png - images/move_selected.png - images/move_selected@2x.png - images/ortho.png - images/ortho@2x.png - images/persp.png - images/persp@2x.png - images/rotate_active.png - images/rotate_active@2x.png - images/rotate_selected.png - images/rotate_selected@2x.png - images/scale_active.png - images/scale_active@2x.png - images/scale_selected.png - images/scale_selected@2x.png + images/fit_selected.png + images/fit_selected@2x.png + images/move_off.png + images/move_off@2x.png + images/move_on.png + images/move_on@2x.png + images/perspective_camera.png + images/perspective_camera@2x.png + images/rotate_off.png + images/rotate_off@2x.png + images/rotate_on.png + images/rotate_on@2x.png + images/scale_off.png + images/scale_off@2x.png + images/scale_on.png + images/scale_on@2x.png + images/select_group.png + images/select_group@2x.png + images/select_item.png + images/select_item@2x.png + images/orthographic_camera.png + images/orthographic_camera@2x.png diff --git a/src/plugins/qmldesigner/components/edit3d/images/edit_light_off.png b/src/plugins/qmldesigner/components/edit3d/images/edit_light_off.png index 73e6e92374b15f4b693ef5804309327c65a06253..81ff3ba1e61dc4e0f5d350f47e7b09c512d12fc8 100644 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqlzO^2hDc0J{?X4Sp>Sp8 zv}>0=nErb$+gD?_^Obx|!Y4+7oz+q?3haxlr1b(=1y?k2KXGR1dcf5B-r>o1nH>k3 zqXcdivOetllmGw!|5L6-H#S=S|F3_)`OPIA@6RpuCzyoKo>5!$<7w08&#WSi|Fy#w b{Ssqjxb@_fe_KhJ9mpY`u6{1-oD!M{(JaZG%Q-e|yQz{EjrrIztF!N`IM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyje1YYl>zP+vl9-pA3e%g3(Cds>ua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zE!ZY(y^2>`s;R+5kE0@%w%(B!Jx1#)91#rMv zWg=N_>0)GIZt7xcWM*k@Xlia@VPxoLY-wR`W?|s$Y+!7t1l5y*zXjWXkDm^&28sGc4pMq_I}YbleZpRcAi@Q*y#B{v+%Q1nW68zBR5&6%Teo zEn!U)n|kNAg~%T*u{BmdUq0TL^zW7Z4Us>eN-MY$ZB4%aZ+3O;eH$+Ed9^3^vZm@k z{DRN!J*)3oxIl^jX68y>2`(OfMeQ5ejSCz8a&KztkCEV#C}`oIqxgd<@}I4F8&iAf z39fIF$r>}B^{!D^D(8IAymK+f&)+rY4epxVm0GB?HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|bol2!OE0x2x;^|f-zPcF?(%`5SAu~n+bEznEJOtCUB zH#c=La5XhFFt#)_bak{eG_-WIa58kXG_y1{G&X_h^~@_SNz6-5h3U;i=rzHs*UGsl zHL)bWC?r2W2Nrt)8Tlpo#Toep3eL_7;hA|U`Q^o+a0LgNl}l<-W?5>ATTyF?VaXfv- zhRq)|`dd}rPq69MbnUpH^CU1V$jnU4OsplyEGOs94FO*@Gdb?0!x~~|E-bj>(~*+; zN#=j>{8`JaC(pcn#&Y|){dKjM=M+Di_y11u`JekF_a1+IF*7pIs@Gd;0^1VCOa~~{ z%9CY(AjeF5Z!Fs_2fiOnX4gb-)LPH-QQOB>GletEai!C3l^d*gA4DEey~3ZD@riqZ z%#x;(0PpezayE@(iPHo!17rhrc&Yv^Bob=~sETQK~Cju_ty} z#*>{bTpCtR64joDvzIsKcU{z4_xJGS1CmGo2pkg&-15<+z+t0#%f{L%X>SUR8}2sC z26!(Je!^g!QW=-4N@0JEmh0o{z6+UQI(99{wx2gI9%cVW@IP1GuuYcKfC|mf! zyfe9tdI3Don7(Wd_!Yo<&h@lg_yINvCQYulR~HESG%E*cZ`yBq_p$ojv{|A%muv|N zIrTldQP`#{PWXOM*W1-81q)jj{o_6IGqadG{EBwRQnuEFDcd~DZm9*_o+`$}(`?o1 z+?6{!Im+O{66apgFKePM1s{7EG`rI66vJip9hY4lJ}p1W5XHj(pw;jGh7$sA%sJMz stcDM4W5h3>w%@fB5=B>Dgf}oUJf4u1AFtuD6jV}ry85}Sb4q9e06~TX5dZ)H diff --git a/src/plugins/qmldesigner/components/edit3d/images/edit_light_on.png b/src/plugins/qmldesigner/components/edit3d/images/edit_light_on.png index 7660c285460512ed0025dd1d64014fb5b661adaf..e0bde1c5f74a391cfd7d9b3358d484a522a05e23 100644 GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqWO}+dhDc0J{?X4Sp>XBm zv}>0=nCgWj8x)@M$1Ir4$W!%@X_Ek>>JA2Gkprwp6l)xJIIy}XFzbDYlQ{CcuC2h` z)I)*)WFr5J2Bzy1V|Ur;R0wrl_HS#M<04owandIy*9ZUmWLNBSWnl2XzW4BJ{R<~R OmV3JTxvX{(JaZG%Q-e|yQz{EjrrIztF!N`IM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyjezP+vl9-pA3e%g3&})EKua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zE!ZY(y^2>`s;R+5kE0@%w%(B!Jx1#)91#rMv zWg=N_>0)GIZt7xcWM*k@Xlia@VPxoLY-wR`W?|s$Y+!7t1l5y*2l`<&6)ovDqo6U@tD!eqQcsZl(7} zQ);%Kdy&7(`2U~a%|)+Y->H6Q`FvjW`=9Ug`;R7V%Q0)$J$?2P)5C%r+{R%wMY?Js zxuxtoXX#8`C#ZKP@4Neq#g>j)+RdarXleunL_JyfB9e3YYD_l@o z#GZBHQ*4Q9hjfJN_DO{^g;q#EWDK|2ap$t~B4M_TAD4u>N>~Z{MSgK*+IE2RueGn? zoX5r9+nKi=-5>Gph3UKrh3tn5c)~BJ?^ov5@{c*>#O&Y|eq!@d@?^H@)Ml`7DRF6-PIr7h{d$P1 zXky+WgYuRg&gN6z71y#=bM6XUSv>XP=4XOACtj@dxN&n$)w+{crk|BRw_KF{_y1on e(=XMrN-#uRHRzxA|JX-R@#g93=d#Wzp$P!*$nT2) diff --git a/src/plugins/qmldesigner/components/edit3d/images/edit_light_on@2x.png b/src/plugins/qmldesigner/components/edit3d/images/edit_light_on@2x.png index 836bd2a0d594e7a283a3f755ce6bb6817cad5562..37e5047cd77158689cafc0d2d0aaea8ae6259c5f 100644 GIT binary patch literal 271 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=Yo0ESAr_~TfA}*P1cV>l zsZyCHwzOxpg-DHeas$J$Kk_$3YPKdeFdv^EA(CRK(5U3YI(@=Z$r*V`8YdhA8w{A% zIq-%y>a{V6g|OyGa7hG;8YE~;aGEN9FhHPl)d6PbgMJ~b#Rkl$1S8{~nlEcIK5_0& zlkTP@fluEel0WM>9ZY-k@}P*?`VZo}n=B1jWi5iPh$nW~y!MXq%$slIF>k4S`J%g_ z!E@qwi2ASk=D?Y%!}U)5>2vYB#}_BCo@f#MVRUZsyLavt#n;&N*75(?e6L?VHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|bol2!OE0x2x;^|f-zPcF?(%`5SAu~n+bEznEJOtCUB zHZ*s1b96K`Ft#)_baiwzH8pf`HE?pYbTv0Ma5aJH^~@_SNz6-5h3U;i=(WVF*UGsl zHL)bWC?r2W2Nrt)8Tlpo#Toep3eL_7;hA|U`Q^o+a0LgNl}l<-W?5>ATTyS zSEjm5xai^9z3Ju6@)zQK(?7qtTYbOwyGoe`-$>3Y9-mbC8;K`HfJhh6WNT})1T*J>eUTD0u&tcCLv?QXCA z{lR|GWt%;FHsrpuxp^^X?b#-)XX|>e^?qyB`Mb`eFe(0p@1z&Rk^K*mC`dd4j4>!{NO)*EL=qHmQ)=vM4Sz zJ3LXC$8gJPqe8hi?bVKdwJsJf3zxp-LQ$%>Yt ze|QoOonDdtBF6bMx97&UMiE^#moL6bSo3O!!~vJDK|NP)-d}cNyGLMf%yP{IE5(D3 z-3Z+mmf};uww3LhV1rhUYO04fZ%E5s&AcGdugpu{u2ht$3-vm-&SCk-+uLSbXXdG4 z*eaSeGogE-+PjGhKLng|kDYRR4o|EZ^Beczx9_Uz>;+#dmx!0W=YZo7ja|%z;`Y1&@|pJ!sdw(%=dr7wO{4sm>X-NREcSn9 s9r60R*gDnWRKpZTP3Ao(;u+Z(QtxvvdltR#G^pnBboFyt=akR{0OLWj0{{R3 diff --git a/src/plugins/qmldesigner/components/edit3d/images/fit_active.png b/src/plugins/qmldesigner/components/edit3d/images/fit_active.png deleted file mode 100644 index 056e9ec3c8b690fa708232ff38f26bd477ca91ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 266 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|7G?$p2BAoW(+ms@iUB?$t_%ze|M7zJim!h% zFfeeH1o;IsFmegVD|Aes_kFM4?BUDd zmXO#X6v5&Uq!g)e&d7a()wWQDbE{Yk)VU8uvQ2C#I1qH^*fF=c##4HGc@>rwuZgMG6~mKvvKSfy(?M7(iWEXms7Cf;x-jCEtW<&E4&0)C1Sve}{?n{61*6pFAH q3b`JbC!C{3i~y?LMUs zGOi@ZFPMRmTR>hxrLtrC<(t3GybI`HU|{&=>Eak-(R+6CM&3gP0t~sD3#RB@N@3#i z67w)iU`boxeu_!Y$ib|kZ651{6&o4fH`&+yek&ke^7GNxQ!oF_pMLg6(Bj6BUAvk? z6jmsBhHHE1GUZLZwBuI9Qh^?kmyJq{Q!Z5`SP89B;?xjYz|45r)!~@KQl>_aiJAeO z0*wn!Xnr`A$Ft4ye*eC{CFc4tA zo7T17nAzJK34Hx Qj04&4>FVdQ&MBb@0DgTq*8l(j literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/fit_selected@2x.png b/src/plugins/qmldesigner/components/edit3d/images/fit_selected@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..278e832f1efc58b6f07407f9750236ad1ac22a4d GIT binary patch literal 235 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=O`a}}Ar_~%PCm1 zzG6nq9&fkI;_sHXE0)jUxyaSHqA=BbT(wJYl zAMF>F*jsaD#fpkK3`U84-h8KD6|(XzV$o~h`N3we=DHT&e_e*thZ#1TJ17?1iayZ6 z({eE-%-2xu>Q0SA_ezSYtq%A`Z@`V*{l4Ylx@4gAX2y&aJtDnm{r-UW|aQjW< literal 433 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoD?D8sLp(a)PTsH2;wW<5 z-o<6nf(aKiT@+P>IISkl%>2Vq{&s3tca-z;PwW~VB8!|?PMhiZ#ATggiItV0iwT!t z%6XY;>)pjoP7f#N82#RtfA9A9r7 zNT%AW=>pHXhCSB(yY4+tuIes-ygMVg_|}bCZ!aGEw(BidP(GXDuSVtEobm(D-8q$h zHEc2~I}u!`>F6RJaO&2YS-M4j?Ot8&Gjh-UJsRlEm-J5dT-Z}q4J}PGXHg#J-?wg< ziPtbhu;(>iK2kh!NA=?`QkSlk98sOgxUEsxK~r;{@YQDxncu7Ud^9xm_D@j_T= zE8FCQ!c!U|RgdmnzGRDrpLzlBoyt?{yVvcy^5CnG%ak7$GWf@PVN@2h%!85kHCJYD@<);T3K0RZmQyXgP` diff --git a/src/plugins/qmldesigner/components/edit3d/images/global@2x.png b/src/plugins/qmldesigner/components/edit3d/images/global@2x.png index a2a857fb10cb935e127fe65d0263ed0fcb7ef423..1a2fc06ee334026552a4c01979d18aac5f718005 100644 GIT binary patch literal 267 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=OP(%{Ar`0CUN+=wGLT?> zu-)L+42wsMb0#=LSYd!S-!0lNzng91K z)974~zTx5B1pXtj4<0c1UEgTe~DWM4f6w78k literal 561 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4rT@hhJ-tuTNxM_<_GwMxH2#>?Ag0-&>~aQ zg-00}7)(ln{DK)6nV31b1Vlt7l~r|g^$kretZW^eeEkE1^9o9;8~P?pn?7^R+TBNw zoj8B(`mNiqzy19C@8g?KS_}+~yq+$OAs)xyPVo#r6qbfg%qJToP9PQ`M&n)esHw+6ZM9gTf4y}z{R)#Uvr9Be+N-)GQ2_cMXj;oqAX z?{zgUY|lH?BYShHcikEJmkX@zPkm>(HurUhsj1an|9nwa=bsAX{lh% ztxqbw$25D*XMESbcY2S>`DuqLTGns4W;fxs9g~CD-1MCMDT*1d?KRpqHiai2*v1*k zw86%(Wy@3XDL?14C%3MRUN_G>M0nCQ>qA*QxA!xYIa_k{xz+bO$Xc50&${huDF4)- Rmw|zS!PC{xWt~$(69AmUAF==d diff --git a/src/plugins/qmldesigner/components/edit3d/images/group_selection_selected.png b/src/plugins/qmldesigner/components/edit3d/images/group_selection_selected.png deleted file mode 100644 index bfb848aa384d7aa0694c22c281eff34094c0aaaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 438 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoYdu{YLp(a)UfJKz8z^z? zBY#+v%i_xxy&Pd%d9_-dRtip<8al^q(WNdo5seN3m06$pUvze~xG26TyWZcm{gUQ{ zjtwW??B%RJe`fE&DZhP}&G=q>uJY5r85>XS4}7#uNcz`{d$+WV64?5u+=xo8GKx6D zXA_>Z?9{iE4+7yIBRZ3(KC+`7WK~F#X^HSJi8$U&?)ZZ1GNG zB^UB0T=w5{aGiaUd;y35N1x8xt2@PR@z!n6 zJm2xr+;Z-rN}GVBbylW_ESe84xP9WK7~kVrLer;2TwfHGwyJB5$&6S*O~c-^8T&r< z?r7+q5tbC@H~-(U1V-zrGbUXwSLJ)8ckkip51C>Q?WPq7O?TISdGEE5?{7Q)dg*+_ ze(9oJahb<2*f!6pd+@b@Fa5%l`puVo6Jok~%vVZ26O@^7IcVt&hjLctSzLZ5ypu0? wYu#>k3_e&rXRVQ~)SPLTk85rA(tjY{cr!s&i*3U*1_lNOPgg&ebxsLQ0A8ERr~m)} diff --git a/src/plugins/qmldesigner/components/edit3d/images/group_selection_selected@2x.png b/src/plugins/qmldesigner/components/edit3d/images/group_selection_selected@2x.png deleted file mode 100644 index f18895dc4400ab6fd4265573925cece156414df2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FS zPc~Sg8Kkml#*vg`&6?L;IzKf`Vi(c()|fd(T;*e$&5DIjg03|yeN(8bk6-0+ zUGzr>xjXBP_0|^ed;BKzY}z-w-*b!?|6P6gUiI4ixqJV;{=KjC=8`2#mV6QDv2ED+ zcUN?Jb*1V<69#dEvWOL~k{wD5L}xI?9KXS~ep@?70S~)g;v1p!i+EfF3)Bnl%UiT< zyluGc&}JRQLYoH`O4oA_aQ4VPh@9S`!KCxS^IbXf>jwD)Nt`Pu#&ru_C}oWL%k=Ja zux!*@)@O|Q4V?!}d*;5{s%;c#GaZLKt_t$o*gLvbw!N z`sZc`(E^F&*#_G#Wyi8S;#%=KVAa*=gnduil9daDl2`Ao_n46pykMj0f#k|nZmav} z-dMx(jj^`j_5r6YRj+QUx`goCFz-82yEfeWm~?xC<$>%4abfRf&Wnv?$@nU~L*4)J z-d}s}x+ZL@NHDn2v~jiVZkCQ$j7-LXI~vw-JYW0rfF`H<_Sw09Ry!Ya{MgQ3l<}1@ zg5}MWNna00_Q<}td2ERQ|CMUfxepKdt@b@o^g!A`d`Hv9$ES1?LYCN02+R9#!d=1H zBP>{Kv%BMn;0G7CO-dzdT+XXkA5eL~_TbP9nPX;c5#^mPn6~^9Jkh+aHSqX1{RYVc zg_Zy1dhYgbthK$ZCvcpZ<&efK_D@Q7%-)S}gEp~Q^lxmoyFdMg2U;(M|J->vX!eb5 zmH9l1>l)lYO|qNBZq8h~x*_w@!Jipl4`k0(_&6zI^|u2)Q}~sW+ZlX6ZCQL{?(&An z4nKbL4crnc3ok#}s=?&RaiZ$LjhmZd3)Z}yAbvOGK<>_KNjXzxl4RVUu89%i5}fec z$&l>^R}br*i$%@pkuF?<4}`YFE<3Fov`untT;;U8K@DNKN=ogwSIB;O)8(Tmr!e6} zUSX83`#CvPh3)B?ZmXl?aydPm4ix`95iK@}W1-uYUr(-r()XYL4Eq^F-(S-xlw^I+ Qz`(%Z>FVdQ&MBb@0IqweK>z>% diff --git a/src/plugins/qmldesigner/components/edit3d/images/item_selection_selected.png b/src/plugins/qmldesigner/components/edit3d/images/item_selection_selected.png deleted file mode 100644 index 2b685d3d00a8d06631fbe3678b9997f258c77d1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 355 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJowLD!MLp(a)PO@}b#-f0!6I!P2 z^K8yNW+%Y$zWT&r+n7T$9vavmui4i3*4Jy&C6+vc_$kZO9JwP{-x=n6MNd{pw|I+GqHmNMTKFnx;~~5R+)9ewN`B3tx=~*Xx_7rY+T67$I<2|AS8D zDXxO{pR-I@MYw}*O)7~zvF_tClUg2aj~R@52KI+)yl(XbvRGChFn#v<62s+5C6$v{ z_BDz>Fs|O$P`-dUhxzz_!6))rUs84-DNvfstPvl`V_$3jQqW@RPOej|nm=a=-4rt{ zNmeAmF@af9)W^OqGXBUo#gOswkinbs*=HNKDvj#N~% zzHqYg0o$V4y}^QZj3P6PwPXr)w_dgoy-?j?@r!kjK~?wN1IjMnrI)AFlr`uv3TVLxT?t7cb6vZNka9;gZjj(<`_OHQqZZGTvjf?|J2a$!)u! z?bP&%8v-M~aBevL;-Qb}d3PDzAL|4*F^gPrn>&Z$oq|=)93Cg;FIGW63NF}wIkt); z;0xat$->9ScN7Li?B6uUbN%*9*YmdTV>o>v{rg{0k6(YK4c^R1!)r2!U%EjLz z8@8|Bmd|WIAR2sqJ7d(A z+Zj78&u@vd)K<-J_~ubK(V{Br4wr_~0rrGL7R*8m9zOdK`S{9}D_8#fXV}lEFlVAl U^4&;v1_lNOPgg&ebxsLQ07c>=(f|Me diff --git a/src/plugins/qmldesigner/components/edit3d/images/local.png b/src/plugins/qmldesigner/components/edit3d/images/local.png index 0a608f6816e62e1942a668cbe66f2745db13e623..94b2f97c4ce6eec20f90ae01354f68e6f20365a8 100644 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rq%=UC~43P*={?X4SQNS&; zg1xC$ppk!l;}LOXHnuj&gvR!$?+%CjD8q-QU`xj+r%1%c$U)IE$D1|9}7MwQo#&&6M^3|NpOhe*FJ`PFx`S`%R|K`5XP8 zZ@kyO>#1O^Uc~9B;@8?$2*!v%<__!GA{+vs=Wp$zw O{(JaZG%Q-e|yQz{EjrrIztFe_$;M3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyjezP+vl9-pA3e%g3(Cds>ua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zEG{Q6UQu51-H9;W@4mK;7)S}F?)D*X({9FZa z&{$<+vEJ0k*wNI`%)-FU!W`suM{`FQL22%>BK2jvr}%8i$qcrm;Yg&!g^C9Xi<#UNvBh7lVXI#PAt`lxUn)aqDM_< z=@joG$@{_kS6*(pC;47y&M%Ynb927iyx(ctt1iKF?C7Q=$B*tfV&jlharoiI!WFZ6 zm|`9(PjZxgwYM)Vf$jd0hNhkSTuL>LZb-Y>>|@TnCGu;H&tpdC`diFXl`7W0f2MPP zrtTrhppT2btzeq5-T&b3Uq1p{mtU|;l3D$zzoc{4gUbuvYB+BE`kQl-L7R8&d$*-= zZ>}@EeBs>MwC1r?aM*nFFRSM@M4d@E;@RNNo3nm>E{JUY_+MAC`Q*DR?21d|eX?#G zu*tf^@gR8Bw%=11hE_lEGK<~zihG5d-nP3ZmMwd;n0xoGlt9t*`~Qc3R6W43TsinZ Tf0y}6P=V#?>gTe~DWM4fMkwDG diff --git a/src/plugins/qmldesigner/components/edit3d/images/local@2x.png b/src/plugins/qmldesigner/components/edit3d/images/local@2x.png index a5c931e750fa19f3baaae1fd47679c4683d1ddd6..f4f95e4e3a77e3c97d443d717e166dcc1eadf2a0 100644 GIT binary patch literal 371 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2AD^C~45R22vKl~XCc>GxN zuSzUvc&lF~oX71fnz3L;!7qh5l`XQ14sb^vR6Dnq!+4sr$P*>a8OM$k$Sr)ZoipMf z%Z{e{rw;Fwcl=Q=XH%QdN0iK+N5)t2S|Nr}kr|o>h8umv<8yaqLZ3|F2dpu;8>zesf4>Bj+)a0-5 z@MG1S@G5H8^IN+u*xIhx2keehXxhcG;(+v-U)t-x2rK=4$Qu;%hch9eqqXDz25*+j z{Uzs=-LHiUx7Ad{Y-KpfeThed>!1Df{FchkeJ?isxBe+{LFCW=T^xepHB;B{NN`PX z)UZe>(E2fzqw}=2g-A_Fv)c6EH$-hNrXN`Sz`spPyH2)rdAfkG>em(CB^^xr&V alN^K5I{Wm`UMD_+LetaL&t;ucLK6V6*`DbD literal 1960 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|bol2!OE0x2x;^|f-zPcF?(%`5SAu~n+bEznEJOtCVx zFn2aIH*zvGFg7(bbaiwzHg$0_H8wYJHgIw=uyBIu^~@_SNz6-5h3U;i=yk-a*UGsl zHL)bWC?r2W2Nrt)8Tlpo#Toep3eL_78sV9FDf#8anxK#c2b+~kYEfocYKmJ?ey##I zXsj}^S#MhftcVV2}+)J3W#){nwMg$RHS5YSEA}C&cMJT>*?YcQgQ3etef5;g(An( z?{pnG<#pJr>7v*Q9qn5Sx7c40oRcUl+TohZ`<8^pbPVxFH z8+0z1ZN5|_o4)LQm&24>lfPK!+({qZ?fBOATZzK7D|osNYJa$V!tSFggXYYadVR~ALpCtl zur6I7wWZyO(=&4o%g4NP(uWm39W2~%dWG9}Gv*+rZd;r0+7-N6j>a2Utr<>UtJ&c2 ze8-DVaUXb18rXFfZqKQC%2@N@ep;OH28LrR)q2XbTrWzl{CasoUt>h*bJymW35{Y4599^dGj?*VkDZ8}Mu4}if-n*-()ZUdpzMh|U zP@j9IwdRNEpB8rBJXKh%pZP$}oZsivR+S0Tv(oG~G8**H^4J)Wwc_am0crD#NB5?v z%zyCW>u#}2#)W(4EDn>})F7O06u}g>vGVx`Yhh{IW1R+j4k{*cr!c7f%Mks}z4J_0 zYv1{xx#5T1&a*_$aZw8mxRh_-6STN0?OFfnQ&t>m4azYLN3A68lzwR86Em>(T=m;S z@}6ms-|I-FZ0qo+B}~i1BzGKR*cEy`q*zOn@lWF8Z*0m8+~sMRfBx{quuhMe;%qH` zbm^4{-8=Kx{%q}{!@MaF*%P9w| z52k&X$bBhf)d|K|RoNQ*W(uqBnrf}}^lyOB{5qNHrE@3y+VQvFn!PjaR6@G&i8ZfS zZ_brvogLz=U?yUeko@+0fSQG|=K8mHBA*t%)?BrzcW)AZ8ru}z#7_3-M}seP2JAl3 zu(&za>C_(k)t|39THo%T(VEg1mc7B-Lw9EC^Q}&wYwe9gPR0e^Z&A4f5R&!!DVYzo)sFBg$8V?9{I`#{#>SlkPfq+Jy{&C36^1vwws^FNr+z|3Iw Wi<>>uV)AcL-RbG-=d#Wzp$Py!UjHrt diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_active.png b/src/plugins/qmldesigner/components/edit3d/images/move_active.png deleted file mode 100644 index d21d290349ce216e263c91151198bb31c15e4e57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 294 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo-g>$?hIn+oonp(^fSUemd)ob!$x;$9)X;e$#QQ-d8`IXSZFLTXW30NK0vX!xpDA y;x<>hR@!~%Ke@Vd#v#M{;KTP$@{}+gked?W%m?%TPH zfq{XiB*-tAfl*D}!6RV7juYqa*d!kO#lXO@+SA1`#Nu>vg2bB!UB>p7D^4;(md7`A z8?UoeZMfTIoW3Disq`67nRn5-IS2DPJKejD%WmJ~mSCI8l5FI3h(|Ltwab~A#_k)v3g%fFGp=TNJ=2)+hVIN_q4w2DeUBzQnA70gWSVecIvc~+ YM~-u+nVXa`FfcH9y85}Sb4q9e02|zdS^xk5 diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_off.png b/src/plugins/qmldesigner/components/edit3d/images/move_off.png new file mode 100644 index 0000000000000000000000000000000000000000..1c07c7cf6d8d6ab35e845250d33aed0b6afa5cd0 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdsSyd_r6~I5@bux%2b$3kwTN zOH0ek%lrHLmoHzwfB*hx&z?Ph{`~dp*I&PW{r~^JX-#M<0|SGJilql rGbL@eOMK=ZjLvl3E?&rEz`&4fn5g$U`HThw0|SGntDnm{r-UW|DHTj? literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_off@2x.png b/src/plugins/qmldesigner/components/edit3d/images/move_off@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ac943afe1a7c6af37eaf9988f30cc6dc3a92825f GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;|vT81_3@Ht{~dLz{JGF+}u1M zARs$CyT8AG{rdGAHf-3udGq$|+xPF^f8)lDn>TO%`}gnv|Np#YUZD&O46U9njv*T7 zlYjKHNpy()2<=z<5XtA8z+}DZfIZ`}?;1?^B_&=3vi!^Gwd>D1w*Ak45zapr{DMDr z%PD<0onY_s!2EO7gai7_Z5y_15!t?FO9G@oGjT8;vzjpNIg^2|gWZh_&jXzQ zUkSXp^v0fkK?e!PANv_}C;Ydcq%0En|Gu#7O@{L?&&)ahi2E}G0|SGntDnm{r-UW| D#x7}# literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_on.png b/src/plugins/qmldesigner/components/edit3d/images/move_on.png new file mode 100644 index 0000000000000000000000000000000000000000..c23b711b3ffda352841b3da1294c2d7f403bc42e GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqBzd|xhDc1!?c2zEK!JxP zc9T4_LDOQLr+T_ew;N7e5nDe?pz*NzG{0Tng`HmPy~~sk*SIu=yFf5r^s1*}`?R2k zYz-GII>i>PnRLV9#dDT-3$M&szc9zEJiq>MLCeb*x()jLB0>*8>%=qc1lj88>gTe~ HDWM4fp#V4{ literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_on@2x.png b/src/plugins/qmldesigner/components/edit3d/images/move_on@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e0065301727c44c13c1278f47ddda8f5ee78226e GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;|vT8>H$6>t_%ze1_lPk#>Qr5 zX4%=<{r&yx*RS8WapU&w+xPF^f8)lDfB*jd|Noz7`_(cA28KFM7sn8d^T`&?Y!U@r zZybd!CN`^W2$b?wXygrju!Z5VoJeCb509k=)AD5%>l{rVXPlAjV%fIVvbdqK@%fpR zIUNVg8Z8AHC->Y`XiR3}S+|gphiA<~MIHyiHe+?32`pI~G7p+e(b7BmthR^Y5QkHb mgWYD&SphDBf;SBq7<%2(g{uG8E@EI{VDNPHb6Mw<&;$U_C{&&R literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_selected.png b/src/plugins/qmldesigner/components/edit3d/images/move_selected.png deleted file mode 100644 index 5c8ce42a7588ce13303070ea892765582c05b951..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 191 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|7G?$p2BAoW(+ms@iUB?$t_%ze4D%l1LGKf8 zyk}rw;4TUB3ua*S2*@jH-*@8tAFu4k{0s~XPM$7~Are!Q6BHN?G!+Uhq$XHIbx*K( zr|Kb-#(YTTA%j5sRRJBV)i-YF+`LhmdKI;Vst07ij69smFU diff --git a/src/plugins/qmldesigner/components/edit3d/images/move_selected@2x.png b/src/plugins/qmldesigner/components/edit3d/images/move_selected@2x.png deleted file mode 100644 index fad362a3e6a5b51b12c94e97374f7e4bb1e1be2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-7G?$phNU`BwlFX-=mz+NxH2#>FwA>MBr<7B z$z)();42C83ua(cQ+MzPSg_;7`8%J#99t3ig@J*g#nZ(x#Nu>vg2bB!Q-*ey=PWWp zh5m&eXR137cWwW^A^OnIXEJ5pkM8X~oY&dq-Ys0_eS=$qZ7NH$k<%d`22Y#UoKA=G zXEHebk==B}dWX-o-PZc28W&Vqcf7IwohPZtImhkc7MbnE?3phf`SVyz=0C^MZru6E l=gN-FjOTiqjaT!^F)*m@b)6~t`d}8wYo4xtF6*2UngCeBY6AcO diff --git a/src/plugins/qmldesigner/components/edit3d/images/ortho.png b/src/plugins/qmldesigner/components/edit3d/images/ortho.png deleted file mode 100644 index 35b36203fa20ad34b5b48264723aa966b33786e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1310 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFe_$;M3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9ucqbpIn-onpfiKVyjegWv9>zP+vl9-pA3e%g3&})oWua$FA zYGO%#QAmD%4lMQpGV)9Ei!<^I6r7zEG{Q6UQu51-H9;W@4mK;7)S}F?)D*X({9FZa z&{$<+vEJFp$jH&i$;80T(iG%$CqpAwH#ZXt0~a?Vb5~1OC8*vMEZ&CdHN~k{-%i0s z9~7@h@eC6Ra&ZGO!ATO7Jna+^={_|t#a5|E$=)t9*6J4n1LI^*7srr_TW_v~%`l6+{QK3Ic**cs1JZtJgoe4`@Rl+9aJTdf`#mjv@>9OF` ztut674X*#cW?m}({oEYMw1qWaqwf@_pZh-d{k-aRv6oGvRg_POJ^b;TbJ1D0?c46A z9sXRfP@X+ZI4m@*WlvLu%pw;5h=UVVivDeJt*khzUUadkMrQ%%^Baz(7M!OF+FYkd z9h-01m~_Q+_p}F&bF!M`R<03@W$gNJA}eVr$MUQu$C`zVhds9bxGUkew1Zb=wb~AM zTfK{I+-pwHus6Hd&XhS(drJBO{hz##KP{O3@aPnuJ#8jS9v=zVx$KLafSroOy7Jb2 zsp=PbcR$>BH|LWB=bA^dmo-c@PkfJdZ@nkg{-HfQ>`j2LK=W;d&K_MUCpNhdVU@&l zOGN*5e!W(A;;WHcK%ezhmbDd)(Pf_N6PMeZa`CIY{8h;)RanEmx%SE;j@2)Y7^Xet zIC*HQ%Bf?eJKFE^vOP(C<)Gv?Q8{-d=j-YO!Rke_nll1_PX7CUvAoVcRtbjJt|6yA SzI_%2l~|sxelF{r5}E)fYu0}N diff --git a/src/plugins/qmldesigner/components/edit3d/images/ortho@2x.png b/src/plugins/qmldesigner/components/edit3d/images/ortho@2x.png deleted file mode 100644 index 443c73e444b195ca8aaf90f77707a87405bd379a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1727 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|VL96y)LtVuF(-D0$i`AkuwmUW%AQ z^ZOjD{l7})7r)y+wM&<7*-tOeT z_q2nxM)@O-7?$e}k`+v5P5b-=3;5SC`93g~U_RI2Rv>(4>*|J*4{T==l9xCAOJLq{ zzFLgYzJhmK^Taa24NblN>CEhn&;PvDnZY?p^O@=ihT{jhKTJ@*W*o<4)~u~Fy{U4+ z;>o{fX{3qFVD%FP*sm0t#xQ4DdVMy% z_SIU7aqofL4b9gteORRNYGR-zZ(HH5w-3K7AK*1`aF(?fF0l()c7XXp|2Zp37T*tx z{TH;q+VwmB`Z05(2)^pLH-gXCORCw%@?JV%eL-3!^5K!}&{X*w{Kq77YQ(}fnCPuv zta)rws7BFy?Qa+2KFlco$s)04^T)~uE7zzzFp}WgSNwlN$N{wp9DEI77uZFbzJKYL z;VqR-S$veQxhdiub6nlK#S?C7-Jfx;$k;tKL;b&g@LG%A2i{e@KO!2lJy=7_!(Hcz zl>WjaMFuP^2b?aji8UyfaXs5t5S3b>Yky308t=NM?FoF!Av2$Ee>3Mo$Kv-(Ha{=A z8G7T##s|@7glB22Z8p3V&Q|3(`L%yhmDkJST@7K&xiboOHI(h<^kAJS$XB2J-`21+;`&l8cm-4n|D|* zH}dNB)KS@6H}B_1mA12Ib6VyE{b88COJXXUYE530>&K})|6V;7J#)1oH$lNU%l_}8 zhNt}r-9mOrBGGGG&ig9=blDcj{wbr@d*$Pjs6LOdrmu69Vr2zb-bndfFV^y0@Bd`g z*Y5qMK_Lg$v`6lpc=giBS|9nP&*#tl$$^Q9jhaFm<>z(HQ tE8nTd-2Cp-evf&-wtc@ zr5|AU)cx;}=n>-t){pg_W)Jns%KTnm;rMb+h8`m=TaL(XT;yA5`2DfrDkMdkb2c&W&!UH_%s7X7u1l~h}6^H=>^ x%Kz$#Y93L=7xU*xK7TL8+-zE(IosTjkwJ{ne{xUp?(?7!@O1TaS?83{1OSbtbbbH; literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/persp.png b/src/plugins/qmldesigner/components/edit3d/images/persp.png deleted file mode 100644 index 9a48e7639969d799e64927acc1fddc34c5db1ccb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1391 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFe_$;M3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gu2HtFf>sx zx70H)KM@pFf`UTFxEFT)-^P;GO)BVG*y5CB|8P1qLehNAQv~NT}3Hrwn`Z# zB?VUc`sL;2dgaD?`9IbD3=a&{Grv{~_DTCZpVC7ttnpl!w6q28x0}I7~jQo=P;*9(P z1!rdkjquF8l>G8yO|WubUn|eN;*!L?-46f0LFa}x_oXJZ35OH)Hb zS4T@jOLIqOV{>O`S3@^5V{@2Zm;B_?+|;}hnBEkGUK5;pK`8+g8dff;MVV!(DQ-pi zxe8z(TV>*Qiy=<)pn6kqyTu5nUVS?S8+}l`BE>UID9FVP!~`cvQ1Y}>K&1QBycAod zA|-pfImchkWnf@@;_2cTQgQ3eRd0`wK$+toXD;j&n3cq}GQq=W+XNxOC=NTbCh6!@ zmmPv4g$q}o@Lhc%Hd9T zJ~(`)_RP<@)$jh#;dE1)cp!A!gHne>4gA5EJKvo=RBYoYRri?VzCpYGkH`NO>{?~? z>u;O;@|PKhlb@_?Hr(T`=@rnIzN1q%=aInVA1_1$+Tui#W#(>h|MT>Y@yi;2M>Q_P zrjW0ayc`Qp{B+!D^*{SEd$psw-R1JGTHDN3hwkq%k8s#loU=GC`~*wfLx%ewrOF?* z+}OIiqTTjS5ATf9zU?ND*h-Xp*d?xNm~UtjySsnI`KUYnFSVrvZm%)Qnv*OY+HSRB zx^;hT-?)CMOWOq2hi0kjuQ+x$E%dWz^^~a}CdD6Ebv|bQ6|eQdo^7S~yuP%GrEI?M zC+U@R{O$$sx7WREyZ-O`7Ixd~P?7hto3CV#800HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRu#Dg zxv3?I3Kh9IdBs*0wn|`gt@4VkK*IV;3ScEA*|tg$M@9GsC^+XAr7D=}nd&AR7@8=U zTk08_8k$%b>L?f)7#iyv80#Av>lzwa8CY5wnkqnnlAVH0QA(Oskc%7CuA-DQTcwPW zk^(Dz{qpj1y>er{{GxPyLrY6beFGzXBO~3Slr-Jq%Dj@q3f;V7Wta&rsl~}fnFS@8 z`FRQ;6BCp2OG|8(l%U2|nxvQgrxrvdbvxSqTvk6SEOMY@`Zfaf$Om7N8uMVL96y)LtVuF(-D0$i`AkuwmUW%CXkZS{dRWhl#59&+XS}c z`@1@Qec-*i^{O-f+K_}05jT--`O_k&-7uONqB6tTB&~W{s^wq)Kl(CykME?uTXLx8 z!{g8Qs^881Y=63ZUvWu=joebbXxpWI(E$z+cs8o}wRzsHzi0Cjq&gV)JK9xnavfw3 z$o$s)_|dU2{R7Lq+?zQQCjGFLf4VQYLs+C?_MUYc?l9MdRIzAV%YM0Rvzx)M*-XS- zz@Io%lx-Tedivz1J}w6*3G%hy*Rg2sVgUmXFJ1NCK1u~jZfF? zIiy(W?BB5dl+5Dtq8VG*q7MiMaFrEz+)ON&5b?77*7~#|$(HeKt&RWkd?q0a#$XB6 zBR67s*EL*E5SK_Z6nbW`%F;3=+S7KyZlUQvD)gd$>8j7*sC7*+c780eVe)4upF^e( z^fZ_=6IL8NCBA9R55IW5l8HG>f|Qx;UQMy|w+}A1=T7VO<^u}F!e`{K= z+~qBOfu|XY9W*?c(ku51YwHJ1$PfA%cUJb#ak_mcf7+ZoIkcO@BKJAEzoRCfyZ^F^;F)}6j4dsFe3iaqNJ z&cvC|_F4V=>=3HJGUsB+=Fsj1*O%S-{KA-dtNOn~R|A*qIjkENr;;hV=SxEbPx^=V zmmBX~S$#O8&y_KeXQgNi{}#(|EAhPzoF^8{=bjZQAmH>r@D{uOQ@{0H+zAf-p)qG{ zoL{QXsri?D^7gwOM!b z-hd-p6PVYF8!huU{E(Nd8Nzj2qxSHplXFf#+P%`o^F(rvc=h$>1rr-xeOxx5ytGX9 zx;*2*oO9eeE=Hbzt@>u+jjU7U%fuIc;rJi-;QXSb>o;GNEj!9TBlDTpqLggU`Nvpu z<;@*U^&Diynk~18nAJN~-BeXXKxk?pstG zlkqL!W&MmBSMrnGX6HU{mp%CZ3Og$cD+}wD6@P^j7*3pj_UTl#RwAex^>p=fS?83{ F1OV(@6C(fs diff --git a/src/plugins/qmldesigner/components/edit3d/images/perspective_camera.png b/src/plugins/qmldesigner/components/edit3d/images/perspective_camera.png new file mode 100644 index 0000000000000000000000000000000000000000..2461d8be5e7c142a924ffd4ba089c45049aa5a78 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rqba}cshDc0J{?X4SA#kR? zpz%HXv#{3L9J~HBa@KrKWN40=(ePVTx8sCP$AMI~y{DZL7_T)aGzzh`HSE<%5S;ki zq0wH*A?$34neY5Poze4{ShqDl6}x}SZs&pXFN{4JIvM$#4yK)P_%{?DiH8-!^pf4?#5_KJCjKj^YBFtpE_aX;yF&1{hCJYD@<);T3K0RYrAOX&ar literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/perspective_camera@2x.png b/src/plugins/qmldesigner/components/edit3d/images/perspective_camera@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..321dcfb5ea8f95f598523df46fe83c1e8c2713aa GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2AEl(H65R22vKl~XCF1Q`E zpTl);PSmwI3F^8ZIf4&%TTWGU`@<8E@I%!3puaU+ioiF1--FlZuNMsnFuTKj+NTy6NA^3k*5AElxAek$y^u!pLtz`WpImdK II;Vst0CRGaApigX literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/rotate_active.png b/src/plugins/qmldesigner/components/edit3d/images/rotate_active.png deleted file mode 100644 index bdabaf30285f9a7468f9fb7f6c14e78359a42f1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 451 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoyF6VSLp(a)PBruhOB89F z@1x>kgPw#zRbN{JCuEoV8t0y1GeZXeG&BJ`Zar=Sd2dOT9 zypGB7EcM#{Q#V0)2bT@YvxdwB!5=&}OxLb%K6!_&)b(zlxOY%#OzoPy)yAFyO}iHS z3pp>Y^4D?ot7TTxPDp+1*tJwobrZwaCBOXk2Cx5N|6tj!g=T#FkC`w37vTT3_^)#u z!#uYm@2@On6x_&H!}{zt(<1d*y%NwTKlL6x2T8;!@+IvPNuPu!HHE(jIZYa57`u2fbfxXf<;m_jDGF#-{2b`YvS6J@VDhUqT>36>_{-#y;`dsN> zh93+z%w`S#f*WTa;nn!Zuk?u1fOQYsG;8THRnGoG6^43-t*7>wJZ(E9#K6G7;OXk; Jvd$@?2>{-k$P)kn diff --git a/src/plugins/qmldesigner/components/edit3d/images/rotate_active@2x.png b/src/plugins/qmldesigner/components/edit3d/images/rotate_active@2x.png deleted file mode 100644 index 8c81f409d326592bf944d13e7fea01ca58ef479a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 869 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4rT@hhJ-tuTNxM_-2;3=Tp1V`K8^y4L*USc zGFt`)hMbZhzhDMNCT12^Hg+CfegP3taS0hYMI~hwH4QBTV>3%DYa2&r?|{&-@TmBN zl+?7$yn@1_vdY@J=9bpBt_c&TO`p49$eDv6flNYYvxOwZ& z-TM!oK6~-(AeR>f-00GcYhFdb&77p=^J^c-w5XV?{5rMgZHoHywDNZ@lUDuU-u0Y6c>a@18$TrU zwwBd5#ouY0BYNw0l7o@ayVrru54|6_nZD)Ub2u-4852_D7i3y(YMnC!1`GnvV z63w>L+a`xAD7}#Xk#v0F^5+ScHr)SuVCCT#2c>4}Dc4PXu6EemQfQ9Eg?BoK7x_Mu zxU@NOUCZSgPa=+=%xpSTSpMwu+9=0j_G$M|Vl0cF z$?HxRVQ0`>{&nLjhRbDQ<&5j~tgmq#*d+Vev&iUn&hdMbOg1K#G`byWvg+^E)@m|f zX%RTm!`ahxM&{RwH7vdo(GG_1Y^SOIvtS6^y?@P$kfZesjoED~**nPXgSnd4ah@;D@X z;NLEKU!{TT+T-FB`y&i@?y*R1l*@Pc`<`98!FWZZo6G_6$QPV!wz~``%VaejoTfH$ ol1yJnt?;A_PPN~R=c;ZnGFY-r`8h3fxh2Twp00i_>zopr03Hr+tN;K2 literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/rotate_on.png b/src/plugins/qmldesigner/components/edit3d/images/rotate_on.png new file mode 100644 index 0000000000000000000000000000000000000000..7e680b5a85ef2b8e542723b14a839605235c95b3 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rq6neTihDcma{?X4Sv4Km5 z-)xfsj~%CYM#)YV6@82C4yVkW%e?iQ{j9?m=Gd|Ce?Ebc Y;r+!2D^_gsT?=xAr>mdKI;Vst0J}&+?*IS* literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/rotate_on@2x.png b/src/plugins/qmldesigner/components/edit3d/images/rotate_on@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ee93a691381094e8379c2ed1d8a885ccfa86095f GIT binary patch literal 310 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=zn(6RAr_~TfA}*PTnIh5 zH7c8tjm`1)F6ju-J0DULjLxrEf8HQ5>BIisl?iIr`G1W$K4?%VGW?C~vNHG39tP@gkL=4AXrnOgN7OpQJ(BIZ1q#QI1xz;6IL%|Ie7j(-1cZTOTfV@9`|F4GB^1R8Md1@x~(}b9q|A6 zLAD1xSqlW&Ke&ojH97X@ol$9@m9Sx{=Mt56tkKBWFnfLtX+?k)x$Z+!{Uv#j2I@O}7`9?!v&B5e5hiVP~ ztb0`@u~NzStojG8-G!2mBijE~bZXC-^l8?rZSCJgm(*}QwbW{>o_gv9$;fYvI+eWlQpQvp^SosL?M2*XU!xDQugTilv2aeep`p!slT$199p|3& zRy0j|O8?f)TJsHm1|FUDLwS$ePq%V5Nt**LQ(iM$%=z?8{K$vm363{Ui(1&QH}BpN z<*I!ubmFIQ&HOc6{=4mb6ZB8#Df8#toAv8wzy75(?*ZGqq$r;ItM4#=`7eK@fH(W& mhT@;5!rNA#icW}opdVk9erb(qzY_xk1B0ilpUXO@geCy0@8To? diff --git a/src/plugins/qmldesigner/components/edit3d/images/rotate_selected@2x.png b/src/plugins/qmldesigner/components/edit3d/images/rotate_selected@2x.png deleted file mode 100644 index b6cc48c053351c5ec94b98bcfd108b13af604cff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 906 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4rT@hhJ-tuTNxM_V*-3aTp1V`80I}3MYITk z#zZ3y+qx!9oHl*t+y#r5u3EQo^VV(KckbG|Z~x&VM~|I2 zdExqvo40P?xqJV?!>7+)ynOra^SAFme*XIN_uuq{R5=C)#w<@4#}JR>Z>NR_A94_B z4L=}sv}>=nR>FH$?r--tCcAD-di?vpv7JG4;>lw!@wWNj-`LK)TkPHP<9L36@g~9A z$I9EpbIxv>@Xq>y^z*;#WdN)k}qegQXS2;`nthv`d9B!HWOt{Zu&k4V3?u*vh z=?yIcmU7a{tD4G|MlgAqNUxU^E;+m^&3ocbt@@@dJ-P~8-`P%6-DkkiT~;62{Ybw4 Zpm^W9xOb+qd4ix!<>~6@vd$@?2>|Cjq#*zR diff --git a/src/plugins/qmldesigner/components/edit3d/images/scale_active.png b/src/plugins/qmldesigner/components/edit3d/images/scale_active.png deleted file mode 100644 index cd63c1d03bca5b4993cf2c2e3e18a233c3b6aa4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoc6z!vhIn+ooxGR#kb!{P zc|lbJ*3=al677>%Z#1%LGN*`3G&FG?t31)geOp|{S&3y*eDeMNzjN(XgDSWmu)TS! z75nGoKJf<^rvKM$I5vOzr{*W0l^B?F8ifnCZG1grb(+7zZKVXxn3oo-+BPy|KX~Y3 zHm~6Gr&lrE4N^O-C%T4YUu9fBBUNz2rs=B>nRn>Ua-D2w(rkEaMT*ArB5tHl6!>JezSriPWON%h z9%M^Cz=G_v_RC?NAN%-K6j&((n_TSGN{> UfY6dV3=9kmp00i_>zopr0EsrR`Tzg` diff --git a/src/plugins/qmldesigner/components/edit3d/images/scale_off.png b/src/plugins/qmldesigner/components/edit3d/images/scale_off.png new file mode 100644 index 0000000000000000000000000000000000000000..664cb20434b5c7282de104efd3fbb2676ffd1af8 GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rq%<^<`43P*={?X4S@o&EE zpAT=ATC2ys|Fi4g^=bSLjki9ZUw^-@=I7s!?|;|J|Kky<;0XWw^ZvbRhsFwx?}Zay z{$IVmfytoYp5JR<^RxbkVnD*Z8iR`8vKm#tbpsS0+Hjc6W7oW0C#^Ao z|C*t^&WCT(vkqMH&S0|tzkrj$GobP0l+XkK_fA^w literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/scale_off@2x.png b/src/plugins/qmldesigner/components/edit3d/images/scale_off@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..52777e1672472484e97911ac69313fbdb65557ac GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=FP<)rAr_~TfA}*P1UMf& zGWYdk^?&se^8dfq7yfzpUqfaC)Bk^ezn=bYzkdDyfBX0U`%^E%7jbY7^OIePzjHg9 zgv&R0-23tU|Ng%b$wST~$Fw6bA=bizc}eGq~}tHD()(LL(8a>JWHKfhi5pMU#y z{Xh9U{@yjde@{Gk_3@wY|M;)p|NpSx{$DH9NS`6=URR0V2CrG5aPV~Xb6Mw<&;$S) CSTB0>B|rI0T}j>aa2 y8&N5Z{GuLA1hea literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/scale_on@2x.png b/src/plugins/qmldesigner/components/edit3d/images/scale_on@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6dac35fb32e3ff53dffde30ff63dc922946ddf5d GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4h9AWhA=@@4F(2=J)SO(Ar_~TfA}*P1h_ID zuB~kQ`Tw=#pa1jI89oJC1hDqMumAV|-@nuU?cd-3|6jh9IjrEH`pmqFJpRxJ|An02 z-JYfT|NnjW9gLyh-p?w?Ycu`-zy3|T)`|M=W&7tgHolj(GhZ_`z2j$p%Ar5!SA6o0 znC^4?kNkG&hED>=f@@bW{XDM0Wi?$uns5Jm;edt$W+Mex#yeawTmml{+nFj-Ccb5> x2$=kqtw~LwgxO}3M=5jKCimcmnS~j1Dj5&`lu98N@DA_^ab;j&V3_xiD(H%I z_cM?kB|(0{42-;d0`e+4y2cg>8KoV)6XxtcaOT3b>r)puvNA9*Bzn3yhG!CByd_ZC4WgT(?)Ju!crdU%>#~L!-=i2+ zMrH%f8G%A;bP^OA*9AARdL>J=>M3@3H;K6&{CiNB$2EkN;mQp*8-XAjeUSe=UHx3v IIVCg!0QH4pLI3~& diff --git a/src/plugins/qmldesigner/components/edit3d/images/scale_selected@2x.png b/src/plugins/qmldesigner/components/edit3d/images/scale_selected@2x.png deleted file mode 100644 index 690cf5f924fc3dbb2146954f62f93b43fdc1bb67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4rT@hhJ-tuTNxM_LIQk3Tp1V`80I~sE_(G; zse*xlLAoT!FPMRmSwLP#-`K*^!K0#~qj$pec}ox6ef073mmiiHIujTe7}j{YIEHu} ze>?Rw*C7J|*Y{hp9xIy}W?lXL|Nl#;31$=1lDO}F(PLvPN_Zw9l+bHcqQIH*ilN{f z<4h|CvGWJTn5LbQJ+dV{kU8m=btPNF;!~H_DW6=HQ1n?LpY{3C{qyE`mP|Wh{ARaX zuBVN2>)N>2tqXsdNqH~7SNZf@_r0YmlN)acnU~sY3fMEPSzKo%5P6FE{ rkJJ6j`e(bP0l+XkKa`l^( diff --git a/src/plugins/qmldesigner/components/edit3d/images/select_group.png b/src/plugins/qmldesigner/components/edit3d/images/select_group.png new file mode 100644 index 0000000000000000000000000000000000000000..228d8d4d9ac98acb257904cb39f8882791484cac GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)Rq)y;$wg02mk5eT*4(GCzr+oc) cQR6cc!~bHpz$V)-t3bZ>boFyt=akR{0LejXRR910 literal 0 HcmV?d00001 diff --git a/src/plugins/qmldesigner/components/edit3d/images/select_item.png b/src/plugins/qmldesigner/components/edit3d/images/select_item.png new file mode 100644 index 0000000000000000000000000000000000000000..922a4d4f251e60028e821c3261a629abe903372e GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4h9AW2CEqh_A)RqlzF;1hDc0J{?X4S(eOiQ zSHnFvlg2ma^g?+=k2li&M0_e=LT?cVeMfBY2hU!B1RGFI%bF%=dOXv6KDTe-0z2+wzyAF@`PVXM zXZ;0{H5=F`PG{XIAt7P$W9iectNtz2+M&U>>F%ySAAjfHn0&|o+4lec&xii%v-Vvj z`{#dH1^Yag*Y=<5y*T!T#7?d6`Oay_+AaI#*N11_n|Z4Cf7JSMs-(x^T-M^;dq;Q~ Xx}>)TO-fnw85Ay_u6{1-oD!M Date: Tue, 3 Mar 2020 11:46:39 +0100 Subject: [PATCH 59/96] Doc: Describe changes in the diff editor - Describe the context menu commands in the diff editor when used with Git - Make the description of colors less specific, because they depend on the theme - Use "chunk" consistently instead of "hunk" - Update the screenshot Change-Id: I6c9ec4eee8ff80f171558c930e5e448ac493f927 Reviewed-by: Jarek Kobus --- doc/qtcreator/images/creator-diff-editor.png | Bin 36172 -> 21098 bytes .../src/editors/creator-diff-editor.qdoc | 12 +++++------ .../src/vcs/creator-only/creator-vcs.qdoc | 3 ++- doc/qtcreator/src/vcs/creator-vcs-git.qdoc | 20 ++++++++++++------ 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/doc/qtcreator/images/creator-diff-editor.png b/doc/qtcreator/images/creator-diff-editor.png index 70ae71f7e9ce3389f98190d079162e24208af74f..3d2ce4bb4315894c9944da549aa5c3e6796dc8dc 100644 GIT binary patch literal 21098 zcmeAS@N?(olHy`uVBq!ia0y~yUS^k3K8&zEZF)mbk; zzw`N>>UU?BzmEQPb#C!)|NV8pe}B1r*Z%uy7N$lA1py8grp67qhtA)ve!us+5QqmB zJoJsjLjkJ5srZNg`O|KmVu?&TXBliQ_~-|cwJ zcT18{ti_j;g{kqNJm(Yd1^Q1JMNL{4q;9kI-SuDX*m5~B!7qP*xZL#d_pqHi@A1aA_qFe<*G2@C&WX<7 zdo|vow|4%iWhc)r54DzF@r;v&De<23?Su7g4=;+>mp%P)_p?UhK9xgvRxDW9T|Hw# z%fWWLFAFa(_uv2Nl=l6<@5;~5w_pG7_s{e7cF$%>TrvJ1*mA?%ROrR-T&KlcLHs2@ zayPRC32*&VqWHl1(_MYbZp|N4psbV{ay8X+Yt+=)3 zexCcjCcUsQ@SD`v$lAsG!s}f@F@5OASO41w?fJ{)_kS{$4O)KkW`0~v$)uO%KT}tC zxG6O5d(s*ux}+$w#qrY%l_i%?oVp@X5qYjomM506_Qibre~<0&-MRDUL%aPS?fsv$ z`R#rz2;}y+`3#Ri*?GG>ZU3yzuYIlm|C9dwibtJJ-`1>MyRv?j{`{&}nolFI zYc$q<6tDki|KwneMpM-6ppSe0zRlPFw`5+;<=OW_=4*a!=(*q${r@%_=aN%N=ilc4 zykB2?xqM&EVblC~>*_-Sa$`Hs9ha}KdH0?5q-28K{cX#duf{hUyMA5zYu%50%j46X z4$O}Xi%&a$swDPks;%80ldYj#?dL)^8BFMu;uM*CD0^bM{RGVe#((|)>`!lZ5et#^ z|GJ)ATu(xD$-mV(jIU<@ez#lyhVDcM7N$l6r@xo8KInh#pUGtZD`^qiD_vo^Ibx~BbwtJ$Nf+=U^gGTl#{{p4lDoa;Zo)F*v!*yp` z(VH8F^{d{$o?ra@ob8tj&a2qg?|!$dnVnxu=*9QC_usGBU!Bg*ClkQ0aeh}7XULhR zE>@Y%VT*&}V`F0@BP&18zMr$jcM(gGT=Bjy)0?GKF08d)_cQ+f?w9TQd*1Ha{wHXW zd7N*+A-|Kq+~sS(gx7x!-`>HpYT3-A|5qKIzW?9*`n!9Wgy$^sni`;698%@@?@Dao zM!D_FRyyUpWI5tBQ84Aceetv3sU@j*l=d0lGjCra@iX(u{i|MK7Q*+cm-s(?%YG{5 z*SsI~`XWIQ0bf&0kNo+T|Nq<3Ztb_5?QRi#d7AuEO{<#;t2RyX zp8QjNf7ZIMb>V+p!gf5q)XAbGz;Qe9{}TRx6FE0TifjF!a&~@v&Bv~vUTdVE`p?+P zXL?#})~bl!ibqEu2uoz~m!F5f2P zArkX1wszg>Af0(1Pg%uGp4n&nFDW$TS9+M}wD(^p&YJbb`%eFossmBwlkOjh+hMn& z@^T#XB#DdtxkmOitobCO|x&131;suQZ**8bO+_?dhE2kxWmo8+g+{5q3v z_qgK7Pa%)J{j>O1o`1E!^;7_Na2BV>-|ZE>`&1?YcxVpZCmIW4}syLh+|G_Z?oAC!ehD-0>^qXO(T0O(c`#o7n%e=kNW} zZXC<{$y;SY_WCbtORd(gspVbrZ~edUbcp;iA!b^eukN?+B#9*F;YHGU<(sn7}mdn1iR zwdoDFycRgQ&kQ&sFA{ZD=!O0M*HWsD|DK!Q|JOJB-j(YOO)Oc{9Lj>KoMtOE9(nxm zNU>+4rkb}(WO1ssu##Q1(wiJBEw4w*-$nT!n659gyYt-V{Ok`?iti;)cOYQgk{r1M~J8hsu*|JT@<4kC+zLsVA z_iK!AzDj1_o2SzFX6L3mi@q4IU3tm;DhF@z{mtwDy-8oc?*F-*cdSM`x1T9$|y zi@W>ciqy9%AsP#U?00De)qPT(Aig{Lk)Wyi^@($Kt*d>wYXM8cq>qj(KWFd%mVN)v zGxMqH(YsiFeYXE!9M3e@s#GhMX=Uo7q~m?R*8i&ceAfK5>Vj=T8WJ@Nr>Zng;kf;C zp1GF$j?>cl^}l)Z=hZB^!PZysR%OC#aj{vyeo3dliQG6x*1F%^V}Vy#Md8*d4vjHl zT`to*MA8=en23e0S&}rb<#9oavCxVe|3ACee{nC0zfhub;ro1>CpDU@*f?Dj1UQ&^ z{`H;Rx0vPAvTe1V3mWces$D(nq_Ks|B-(vPok~D&&x!DuFJEsBX$#JQ@u|5C(^!Q|3B-WvwmIr zYjTx?<)N$I3!H99OiV6gJb83Zn2<(=Oq2eWNh$#go8IktJN;@Q$Nj&rZr`i=>$0yP z`maTco{&b3Op~f_&f3(I;_oe3epYA{7E8_j?EUipHJ!#MeoB9LJ>#8sM&{wU9l~k1 zO|>UJn>={F}e8O^j1xp7MH+?)S_fA7EH&U()Ae9kVx@|MlF zCNGWb`hPn#*!98bL=}NXha2w_n-1C+$T(dP)YEHB;VGB5*9%vOvN~ib7d-WL=);b$ zFS^e$ua$ZDX{*9s{S33dfFff6?|G_zI#pW!%W#O0RjI)&L>CTP1~{b*&6xT z^KZRf`LH$nOaCQ_B3qZatpOa0PofFrnD^&_mqMja%jbor zg10W!i#=7S>r=OZS|K=K|o9#)}$NR58x7yKptk7ol z)y?*w&mH@w8n8!Ae(yEi!jIw68KTQocKj>3*B|FI-QkpI{M?RQmNqNF-*?~FegF6O z_tYgnkEq)T-d^!W=1tg-owdI%&ktLdcdGoI|Gy{xT%1e%j)(mZiU0R<{=b*J=64?G zFdkKzFeUw{(1fm2GUqQ$XW^=1P>bzdRk#2BJ@eJ81NVPh61 z_r)EKv%6J!OM3Up(ixv;v8x|aU_BP`Vek9e^+DENtTPjr1~|6r1=Z&sUKY$%9Ig*) zF>E_n&&^(}G-qZ*c{J0kH*pJgypVYwYt!457xjJhD$kBtm+XJP+5F5cq}2Oi`2Js^ zTmJ=b4z#S$UuE^}?fvJDwHhiDKKnl2>u~AeSsg~r_nRL~WYZMVD3ft|6YeRr;?DWn z2eay{-#+`l>%y)hGEArtG;Z)m*jdBBQUZK+lGM+gA#C zWVtgn8VGPJHFB^pF>-FPRh_`~V*bmP?N1axK2%h>AmL;Ub}Oi7b7Nj&2B(WeB63f~ zLjk3$;>4r~>Z?F|IZTZPhbDL~*nNM$f%cmlmD~&r4Qp94SQ!`&tSNZhYyPi~PhR9< zoV7wD0|Nt?$dTpz691{7o5Q;F#zb}%0R{#JC=tWTz`(%C0wPQ_!uS50yql4M;f(bH zQ3eKv%}xPKw%=Z~Pjp~lV3+_RwzabSx)pA>@&kK+4F^OQ3j;$!xAy|4{~n?(EKCdx z4IpBJsp^C)_HL}bVN7r1uHM(Nt6l!@)4BBbm;LW;f8E|Z^%np9eWk}A-p%WJYTo?XG_MZ=!TI*T3E@erwO4m$z3<3Y@=oZsPV_zIzW=MMc}*4W1Jj7?M9P^y~-T z1hWmrQtK{fI+irf+Wz*6%Wbug+ZSKWp7|D$CJ^!l7{?0wZ69Hg?MOMcxK=Cxj1 zuP-S}3tZ5pURe@gZ!%|!YtTP~*Xm*Xfvo|;%fE&njlTR&`Y(TXm}|N*o8$jYtt*qG()t`s9RU{rPsu^_B|Ps=QXkfna;4#D_8IIbpP-~YW@tBG^fvhp*~ut z`}Bf~kjF7GcU^soJU z$C6#xW5Jg&Q)AAM+cMn?wQSz)7OoZSG&Wu*?K8J9OWQ-CTl4Ln+iw@PvSi(!@UG_D zhAzu9HzVK5>|1M?xjM1M(!x%C#y*y;i$!T>P0P<~O>l_zWcuo(ee*zF^vBd|)8Fqd z-4wbYj%`k&O2FIOV%jPfGfP4<{NmmOuFex!_xE9q*8-{LWbSKzCM~Y>_xn!GQu()L zLb&wgZBlL(2Rirv|8o48*xt-Ep$s_=5l)ldP=)q&YB8)`e3uUuEc&nIW3+4WsiQL| z*xr+H%8RwVy6h>NHQ#x=q-V$G?(5l` z8LkS1W~{CJT5yEhRi`7>Naz2vn~QSWUxi%jc)|2=)~DHFDV*9SP3}Tl_r#Z^J>|$N zFZft6DXFLGB%9|VEw}%P=F2zP-frvpbxr!ad_-;3_L*z$uH$Z>*j)B2&z(8#om6l025XNt)qsCen~EcAFZ5boEB~~`%-6lFNOp=tqo&Jl#TCZc{u+&s zgqAMZDaIXeamAifMn_BM8_Bc8G9EpZ_0PxhMdjnH1$`;epQ3Xba+$XX&0p;PU9;tx z`n=c6V*dC1F5z)qu<+nQ?Z#v27jITXxCD8#9gl&&KC} zPtMngo4MP=&$qfvs?7N{uh08GR#*4UwaUC7(Z?b+DXhzHis_8l)j!)e^|hQ|n{z2I z`{T2Zrjsu|3p}daw5tD#>aAuLFH?!5Dgl?7y3IFlXHT#GyJU-YB-7%mcCA$r_cz`V zd^=I`$E0fsK~J||6}U2O>r%l}8`Iz3xLI|0^Zi$6%ym@*nkxPJK3uw}ccbd;;a!`) z{Eqmlbj)q_nm=n<4z`I@-abI~pbL!Rt!&$p-tm!d-+8{b3x+CsF&X?RclVWYvSs6=A#rPwx z#d{xMe_nP^`)XL@^|^D)&Hnd1-I8(s+>Fats$O%Sy0Y>`K;_2kD|J)?{%;A|CbPFa zczaN~z_tHhw(tM0*|;aOFlmvq*Mb9Iwl}kUQomN(S5UeAlb27_mopQD-dKOldAB#E zWZ|;20#~jUybQhEYTfKMIV_lC=2J5vjUV&!{F1N8=j~mlH)q~c6P5oH`j51Qye@hc z=4Em*BKu7H{mcK@_TOFok#%n)hsidZ8=VfX+1V{$U%veKz?ytJl?%M)cM5`?X7oQ6 zICT2vyP}=>dPROx9Hz(XR07OrWxlvtX5G!Vta0MHw2}|szu*3?wshq(cFrp=OxC|V zD|vh_U)XkyD_0L&@02$837d3GDl;l?Lr&`^G0kJ&gif4n-P|;NL(u(9mVU1Va}t#J zGp>g3f4ytlx5=sjI?G#=Lh8G|>2*wC4!GGYJz``=Da&@Q$0Sm0JW$%bWX`rCcmbSuwPobKDe?&565tpD<u$HeNw54b>ITVu<#%1M)qT|#l?!iG8uRx3e0Fm^)7SEn z{-a`zE2qAmIJI~4`CFg8k56=vj!pUh{tZWXy;95*ixvahD|2;)ElW&Q(^g-Pe7*VH zt-MoO6H0$=o4V`&q;DHDt7MPqh4z~@wH^4;STd4+?Q|8P#u=;&+7Ee z;P&08ht{S0-@lviJ-4jI*m7#+mhk_NY92&xQZBuv(3n;sbokpOhsKwsCj`&sTJE(z zbkeTq;W_z#DykRd{93wusv8~GKXln~f^Ytm8GB{t6-jLTc1q1-!2SyQ1Gz4?l;(8hzZ87H4l*%j;j>{j+(Lr#&eo|~&y*gxkpUBa-| zg(YZ~@*V#&``=&YHeQT7W4kD9)kBUe>lVw~?altIF3V|hVZtG(8x2WU~>}bjh^~+;j>k)(^-K z;Ik@WdC&SOtU6}CiLIQOm%?7wdiN(iMc@5D#Z3O)bu#t0;tJht_A|x1&1>uTOGS0Q zD_@&A;h)WsXwyw85l7x1xN9Y!xi^qg#B%0=na?cGJr8_uF+J>$@j9t<2?fvWmzV#p zo_h9Qy6b`>u7?pf*i`~vTd+*MyxUqZV}s&JD^vFv6ORP}AC(%HJ>xJ>-Llhl;b%vV z*xD`2%42?9;bGV+cjoh3*(*N_p0AWSXtQ{77Q1DB$(@}ys>*+#Tg-BcD?_od%DUE~ z@@nk`=|5E^KVN5a%;J8(pi(9${lbK8Dvf1#gv{2@Nax&A%p-omEtjp&v|W_#>M=!)-mNpawugx) zZ?8Vrnk*rd5vL-sU_0{$*G876umffrv>6*%oS3#g&|+X#8#P|D|33+y6pe{$};=x=-JZws-6E z>%P0SbAx^q%TNDzl^G|3!q!(EzvtY1{psQF_a8p1y=D2fulD<$px>WB=51kG>!8iR zpfbUH#mbN8K1`F^ar!)O%+%t05<9f2&l~ku%a!cExZ-5Tv1aax59_!r-!5MBK#O65 z!v(G_Oluh!wyi>HV-`#`a&OgG*tmL`(Lb}I&~KBTNlu-3fLmKl&vK1&_*qsIjbF4T zIEM?*dfla3UG6YFCRE};(d5vr`|^L(+KDxlPqoa3+{4uPyQGjO+Hv> z_+2$xu1-pQwn=g9yxp%@Psyb6b2!g^oGMo~y?l<6Omfzn8bu@rF{lJch1-7G@I~H$ zdG-0kt^XKi=DwN7ntwel&FOZr|A#h~jrpa|WwX>*?Ed_r`FmPF)#>mL^Xyj5M|i5 zlf|m+*VXImo>cri;`sOJ!N<=}>#v_vpJpFp8oSOban{M5TF;wZ)&;#O%BsEiRBLYc zpW^i~SJy3Aq|eDPqm!j6Y=LM7D}zB6=M=%KFBdbv zyG8#8eVkEs@+_|<%k1}iOAh-4KRKb_7~t1zC{oE&=@K$eDD+Qi5tFN8y6T3yPgAOV z{$_oCvgv`=N8y>uUyV{1bv-%qyZgJLp1{@^(XD*z@)FiDCme%?(SaMP7bY5?3JbSX zm)JeGBzeao&uoo#TJ2i>eq9UCN>2(iXKIeBVbPy)K>CoHuSvI=w|2LBcTDf9qw$;7 zzkZm-yEQfB=IfX9pRbQv`!)Q1g3`;B9PX!E?Anf|o<271>Crts$-jao{+8p;Uj0g4 z`t;4op&>@g7nzhe&OD@_eX5TA>z*|S4Z@GU;_GK+a8qam1$Y!A! z_^0LXeI^$p^>{0Eb|i0?%lf+FRnN;uhO;N1QoIqdVV&EXXlJY3-7!ml-kZ&SWap_5 z>pD-JTlsVOS*xkXn@j|LiR~`wZxxG^VQ6TCXVQ(rvrL^#|^|WLt_J*`c*7KlGm0 z#(jeKw*RVn_FwkHQUBBW?%x>5-}Yu6?U&pYAbdDbM!~ z;|y78QV?o!v0%FVzSylZf3UGlo&hZ?zz%q~#fTNP!1%auk;YHSbyDo%Ti^IaPgvcy zd);o{@Ytxh>-lzPW=!(;y0l7J`od?y<24uZx2`#U;oo}8^=zqEb9UY8U#z@4v#W0Q znfBjLnEH#aK5<(Uuugi%sec~wz|-j7|S z>R!j5c&E7AytgWv;<=mq<0_%g@416}_4KlR1XcBYQ)f$8e$CYp=bZW6b?dE}x{p6f z1sN>Y&TcbXGsAq^mkXI!cTdl_`s5Igh|iWS;gx5%Y9-EGoMdsXy79+knVV~+!Y7KK zoXPL!{^8fk>j^$le$7)#bElqs+Pihpnd{vutM(}@T6Kx{`-_@)p{fhL)#hX@csSGY z_|=B=iGMsVJe&URZlGCIe_`_Bx$%OI$YCUW>C^)ukC~7BmSLU;n zemxhukuTEZdw?~E=GTa)y18+@z2(VXCRaX6ohj|>m@X!@-IjI7@psbu6p#ErCUs%0 zV9a{8@W%^MtBrr%lX^Ml&QT+2?Ry=S`T^zJk~c~mdHhVw*LC8PRg<>2X9g;J&%SCs zBgrs-($-!bv$ro}tXExoqGEn_`@ux!{~i@pBmx6j!*tIzBX<6p^$9j~IN zb=rSw>AaBjCr-bEr+g)}6$YwJp3t=#%0=)~HRUz?3CX8OOotbXOW;!dtD z-y;gH8+wcJNIneO?e*p72G_Hu!867CBs|`HJoK(n_m1(Rww65ZHJLH0j|5%Qi>9~> zN$x*$LG!fx|5Zo}f&Qd_slBWnMKE$?@US>H5bW;+q^>TqG`a-+>86VdK$7Jo)niKOrW@+r1?k!54S@JwnC*IMGyCwVD*Ci}RcE_rOFPS~3=k7RV z)UN*J=Evfx_Kd!>G?uJoa@2-7<5bHQqd$cl>@Avpb#_&6JTj8CV@&+4-9oLa5&;?ScctT2*Fu8W=#MO`P%&E4IJ|}VML1Czc z)$Muvw#Gb_I~ysM|GRcIZ%nHGVt1jlQpZx?PMq{pQ6;j_hHcg7h>n@B#crLAih3X2 zYx={aI5tjjk)p27JD#GT|IcKC(eGpba(OB4@;k3japX}6w-aM zHzqZAqwfoz+`e}kzpY)jUdQx%(9Fp64K z9o5%u%2b|{@$cEO!zvSboO}fCZjU-2dh(^(?zO*XZmo7#3ctC|;+4AgQ=2odV{D73 z&Ruth=fZtke(mhP@?E^(RuQC<%!n=7TR!Ky`mP%XcYP_?SoL|<=IrFo zt`%wJ*IV|b=HEEn2X5tnny4A6eJU3YK7Jm5xx8Zc^fGzN#rtiFdDcluhCem`UADh+ z`?nA7g?qo4><(T%arJWRH+yF9l;%DzUHLTh&gSP@wX9n+q>~@7+LQB^`>3@-+^yVQ zZo%(Xg-GqtnzN#`y(+f;&7{BEE}vR>TYU?tR|yWtGjFvnTzt-}`_{hjWQ4<0Z)%>pR`X)gWkvUU9&gKc z9W=PJDmf<9r#2|UY;)*zec@$?CA}d%GO!P4Dsz@Rm^t0lQZ&sbdHd%7CM@Buvoe=_ z;#&F2ys0MfTz>k|MGNnrJ2oX_-@m-=OFjq$pZs#+^Dlp^yPrOpHX6PB7PHirWtCIF z{hT$qV%iJUudgXt?HcquHDrsL+}xImOMUy-RctQe=x1u&#jWem{l?<(uD?c=my$9z zu-!@ebLnVmFYBTwU#CaT%+Gsrb^FE`6_vA2VO@TGf7(ROygU^px$tMe>Cn)V(eHR) zv3?4BwZ~`b;;p_XLzR|?YDM0TSY?ztwP2$7=Y^$ysp1^JZ^vwne}Cy#THLMK>UVc@ zFt0Vac3F9?`8D~y)6YEa|K@&CO_+_ndffsoZ?UMHC!HlT7ed>c;85?0VbYu(*}zSQ{3m0xSrCAS|+)!r*r z!n;d(ZbrzjxnI)*nU<|NVtnm`l*ajM_kJ$?Ct++?Ihk$s&RMH?wg=5_i1p&zes6`L z&MmLoGY1PtgdM2M-ZI5~MSy%AKw04>vNXJ<~eQ_k2x@-w{YHa%S&V^>ta# zpWL<3Q$eXkBsQ+PetEsr<5efuL>7dauk$K7WF{#o8NPMf`*SIxkd7wU0yn)zChK6) z>W%rObvsVoI{xy@VTbK&o@)L7nX`3!Rb64>!oJmeE*p!BOYdCuHS9zRf5`3R#KKBQ z1+i!26TRZuGAB)|vJH%0|1ex|WeY!hE~x!PiH$+DQI`RBU7@Ls*V=J{MV z&9L*@t9^W*Jga>9F2=SdvvTXS)pJDj=li^PTjU+@bU(YeqIDt&edVU%>^g21sk(k?COQ0{<^1z2)2`R)^%bNcp5!T>pA)-VNV}Qu!II;3fjoTF~gh zhSq>$9iamvToW7^K*FHz3}~Xf2{d%4(0C}O^wstEYz#at@^5b%YiJ}U7|2CczPPfU znSt$4dR@u&KTWT09|HAcCO9x~vM@M+*8+GbFiddpPykgO3XKdxpxJm30h*>)5dbN1 zYhsTJEMKI1{qNVW;&xV^Pd>$M-v9p&^Q+&N=l|ZbPvZ59mlLO-{}lY`to7ri;%X<} z{B{5TFDul26||$1WH%)$^?Uv+x$m>%a|29w%U`bjyz#E5&N_KIXnC9f8LYrzrU{Z=vZFTAWHMM74r=2=?Th6<3O_e17{eNq}cb1ek*F0MC<3jz;n^P@3gKJ`s zEMB!>o#7Fov-`^z%`!Vhhc#pj#m&*$IlXOWuA@++fk zUfLp-Amh^Vyj4p5{tvFOWWN&f@Lllw*)pNDq zZdW<|qEoMy$HR5%_iwu~-RzwAYK^+`T0LD2y@Xx_|6gMD#D0#=^9!$%)&Gaq{x_drwBy^I?faI^ zdTC#K@9Bg0|9e;MS^xKk;q%}9e}2ec`Ck9AcKYVyQ(ip(@8tS#{rz7ak41cUe6e6l zetCOYdhAi7R+m(!e9cC!|MGvsUd_-{L z-G1PYX-xT|6rX)AWk-(O{mQR%opDq9Qrr|5iY~o`Nd`yd{I2}F_eA?r!kYO%WOa== zj$DaKD7f%*R?5v>E1?XrEsG=zzrGK#{Qo%J{~WmH$PN$-oJz0=f2DTI%vP@{r(@N)7y?ud7&L2GV%ZEsr*Z4w8*~SIw61dyxko8 zrEVWyyO-tD-r7x)SA}n~#GXBT&OUKz^ttnh{&oX*z!FeP$75N+-OfpdKZR}zes;QU zzhO>N8vp5+3uehayDzTIuxrPfm8&3uBVHFE@t7al>HZpY?6I#~v!(5K7s-YH0`wb; z-fvx`zOVfM_Sq@{@0Nzy_e)?<6{`+x9*Uz7>ANcbXQ{UEbm`hoOidECMA5tN&$)hXxiMc@Bv?Cs z=@VhTdMVpwF5I=L=QC!@mOjZjx#^&F@#2Oh8<*#ui~sxFc(ADTPL@piQ5Ys~Q32k!M03D=(K=X9uRM&x{HE)XH*6Uq9=~;_0iIOpYeqQ<*K9 zzVYRfx2rw-_l(M5^# zw-qNo;BKp#_Lzh1@ZWu2Cqvuqd*y-`weH)buEe|Ap)dD_#6RZGM?wCI*;jk_|FKJ) z(+n>7c}-ojXm7lv7Yh7$DWE;uz^ z+*E0K|FVcPvr{HNgN`L!`|hFrwclC5>iDfEi}%&vpZs1px?zd*Z2iWVw;}=_eJr;s zyZho@UfEn7I*Vn~_X#id&ysmM(ZW=TTem(s((YII(vmfio-;nU?D(N|A@-

V#V^U+&%B|Mu_Z=eqw+3VCcd-zau{%Nz}@r5&g8iW;x5Pj*;a`%S8Baqp9W zmX8;>`10q|Z zEu1P7p04Xg$)`y`Bs1sa-heyz%W`hku{?%GxJ$rR%8%BncZWwf!%Y@n^Mz@gmVBe)&Qt zBJWN7{LfQ0;E8XNkcQdaH=ayeZ(Cp4v0gKfX{N|iuIQ1bR}5=kbNFDEYJkPg zM%93=Mwj#SCw!|B*7nd<4fuEaU|3_@B!_ES*-rE4)^nO%3src!?!%|fW{(9wr#f8w z$k4~ZnK3Df^ND@Fyg<#bf9$VRCRE#fVqX3}e~QC9`(U;1%taHnAEy^hdGBPnJIUqS*4xn`Oro!&LQhUPdi$S6%ZI%V6NMk{tC}70|Kz-l+n6oe zHA;$GviHV`e`WBAV&&Q%6#weWelC&Mt8)9CU#K-6+bf#j&f z{P}r?MQ>T>`L`=4JG}F}T-|4PU86DT{O3c}jY>x~)EB3pH$BJwc+z|J-!by`la+T` z-@g=l>#eR<;~nAoryu3k%Q#7MK9NiQ`!Rq2dCP}q#VohK7v)k{NVv6z$#qhOW@D6m zyFm7b%+(H+t{rV#p1)YR;L6K-QH^E$qGZ}H_%iht>rZ&Uaqs^luD?SrKkrv)T&CCf zXLYsGW>r<=HP7dA&io*_%IAUU#M#fE>dkuf(AzzJ)l>(+uKNEw`^~%*vi)lg9a(p_ zv*21G$9kRmEuKs_XKtOoYE9>+smk8jCoe0+X?+v>Z#KaoC^0w)kU#~owj!OBwv1oaAZeB>n z;&|3sqH7gOZ^hjep6K9}7IEI%xZ>fI(6`|nb)EO)33s3i4I5lzU)+d<)>E2t#raHXS6hF0m-A9X-PSpvU zeP7hR`qK2_A^T3BU*CS)>G|7zxO?N4_kvG+O5R>ur#ZZQ6fkYWU27rL32z^+tSeeK z<$K)oSCLFNU!Jl}TX~&*XWtsnRgY{j=6H%;L~|m-{(1 z>2ph^rO52nfd}U-SYF*26~E5t_Uw8qj|D$nCsp5`aJ@V)A2c_yVEtO<@aQ;I%bz`) zUuT^uo9e)vSG?%se!E%C0uvk(x*hbd`1nu0@>boE$v2+qYk8sA2mL>?ZxmQm1Q?pT z=G*aS-If#5cw3UcA+&*oX~Ewm1v^ehOmxUq4fynRYr+&zSK!za4)$dn&zJRSGIO#V zC_5ll-ohO0vR}reUWkK%;eZ%u+Jqq?45X9+N+`mY1A{sx;OP%Au_H?*B4U3@S@F_$ z>(}S&_zLaZbM4iqlWXF{{O4T?@6gll+fx&E?aA!&W3P^}%#4i*E03RrXs^#)xySE% zn6v&JHt*Tt{%iI9V)i^^-L>B{>h`;Prf=>g#@SUT#`fq6i3a+9@d|c{GnI{#08K=Q zg1eCd&(ALeb~_ZR`}MonlU1E=yOvGzf40i|^y^<|+aIo~3GrIZXKZvz zF{t+5oru%%I;XEc^$s?@e)RE2<(!F^71P-!-pYTl%51IGvCyMe)LT=dH^naBG|L5f z1Xsp$0rUAiHUDP*RV=$%|LDW`RdI6=OI66mj2F{?&k#EMb<5p( zhhjo4MO)@wuiq55VrkHI&+X5(7XCQBJ?MVUnx|>a!LLE%P^XhV#=)Ad%+FdpK0b5) z;FXlmuj}B=?Dlof>l1-$b8U522la10`eSMLX(>UMldttR8{NNiVs(DQKQSGP6uwXS{58;ts8AKFU+Ww-~Jda=P)D^r2~H>)Vd)HdKw;ma{$l zdSuv~Z|Q4$SB0d6FuvQ!p898B|(~l|~57^GOc8#lVu#siH=+bE7%j;IyA3GMGe<{H;oY{dv~e z6=H?IVy*8?_!Y?tnWYDLb86vwrlYx~U5Bf-Tz$Cl!t~=!x6Q?3gI$Efw;Eh;)y-Nr z^VFUVZv(S#YUxzZtN1VWPV%iyzcjBjVn*Z9l@1*fU;bq^U)Fosaopsn&hmH~o$4GU zmTMgD`ua*;+>}+*FURfFI=FRL=jv5fLiRmdF3r#`i+wFSZMD5H0Hw>?50fa=XQ{C;iTj#YCfmp|Sy;Y6sK zYbMuPP&47AY2vZfasC&aC#?SUseN6(`qJ37>Fccf+CI zd+e6q-LdNHzN-;uGN0|b5_W6<&UJZ4(^KRo&yD>(?MjY#;T|s`>nQ$e$Q(Ch$ooxo zqfLMAe^70DAT;>7R()~YlKd6((rn*<5!kpa#!}$AOWr*GcP=5>-&b#qdAg+HXNpt) z^tu(gyR*9|g-Dx+Pn*RaJTvn4vKP5GO)NLLG450>+PmbcM)=O#@>4%MKfcz~xzkJJ z$E{Tx9j_IJP7~bUgs!!qNYF z#rB&zH=c6TU&zujFfWhIPb}Gc45p|-E|Zm$<$y=k`-a`#jLR-mvTtEx*uu27A(G@p zGN3~RK=lxV5XU+xp0C#{o_}9iY9D7%(;izo`PKyUAK#ki`RQ+cUzFGR$3s5Y-Ppe7 z*b~df z#^uQmD`HgFKbmJ7{&M!JyW1w#{C4S&N!4STuW{&y>jO($pOS->qR@(iw|u7Ey2jOc z5B&O89liRJ*%LYJ*M}}xd_LZ?*hl#4(Z}qk-uKU`^sVO)?`>Hf6*YC6LO5^vTqo&u zySD6EcfUqr-6?g|%&UoP_Yb5NTzOVJo!KE`dE%*{XTT7C8H&Q(UzFSeiBb>voB;m+G9O^+`Uh~U=KxO`;s zWC8zqU#~|iADunbIbi|k^|>07ll3RceneCd{OLzOEbKllwE?w)IANo|>gu^1$^PpT znk-`@wUtfevvz9jIH9-ls7T$ns!g6dk~0=O@?ots-MU3`pTLFJQk(ixd{2hO+Rhg| z{LC$I)#=&aez$a+UwCP9FvPQESI}K=v5&v|looxM{QAm5hxVA{Sml7<##4~1<|57| zIYoMkn%_>@h-vM<8xSM9de0)+ipS4hxm}3fE|alGQRfmU5N=LivvB#rnCDxPPdhCR zni$Bsek7i>yTU^C*ojLMoeb{oNV@|8Jt#)>&nuYBVjP_pe?u}^ierfg` zX~yPWpLJS4i%#gp$6YybDeWsCxF4GfnVLwwWmLXos+we7&i6K1YhA6b88_FQ^bM7Y z-14k??s`s}2Zv*o(`q)oxnNcL*K1iwc6az>ucZCZk zvR;=zn~!hdf~>y+&wxFi<`5Vio4Ky~=MhI6F}J51AC&cPTHXHi_v^`(IxUbIqTona zVtH)7hL7yCq_WE?`MuFr1yeiRMdqFil`FbbBJhP0~f>W{83ww>3V@##i6}>4iym-HLwNk#&<5dyjZ*k3WLuV)S;tn+z zg&Lk|owL^4ctMNWL|LMJ}muq!C2cMG2rXO+C})BA{y68@v?*FK+{pcr;u zoBh$O6K6kPy1TRL$E8nMy5W|Zs~Fc!T)n2Yk@Hxanfv#M-(lCor_IWhHrm`bJ16J& zGT*ME+wZD8R|l>u+ODkqy#3f(R^j5%Q~N^C2U?V*<)z%uN-kB2PIs2xbh{vQM}@e! z*wXA?d4K+x)TP<}g_mBHxGuf=FRtU_8bmR8;groBj^nar33V4Pv-0hg3G&=n-jQCR z-kaOKQMQYBEd#hLSs)6Us;+uHp*H5R?ZTtkx2IO>n^&KC)HdO5!_BzIsLHkpWc9h; ziZgDuTTvy~;|ZF5096QYQ--|knZ z)_#=NyLtKL(r>+wbtlTdOn#N|?7H=gJrOe}O=n&&UmW=DLl++UvvS`Hak`;Q~W zRBs(u?24GnhIbxDxXRgg7mGcAy?w9D+U2LOKxVGxBaeV)u2=2xoWY;>c6qS3ok4HY z>N9ii2ygYQEv%`>?rjJ<-5olzx|!d$r&}BZ#tgGy7w8qe3KYCbyu>u z@>a-ts`dNNoT@2aykQpRf~wS(XU)btB21%udX6OoFVXf^_@P$T`E=s?S<|P#7mhrB zKW62m4_d$0R0q%N+TU@xCS!yBPu^vlJZ^q$FP;_p=vY+Xv)8UdVVys7)$S}-w(J#M zfBnOmIghgrZ1(u4lJS|ly4)fr^}Ml+TMut}ovR6S#b=rj&lN)6V`p^)cLpP>M7InF9ksh zsQ#qiymuxdlXtz}JIFlt9`O~{nUgoLe_XLsHDT9;lcB2d-@bi%>e{Q58}>e->*yZO zYi65nlw2wcT_!nAX|2hBUc{|N&Vtw{5cQj37V>u zL?`$@))MU3u$sKsX3~itscn9s5zwj)95*-tvjSPzvJ!Z zSx0V&`8qQ@cHb(o(Y9H4sqg)+O=r&NBm{nrN~`r-ejxOu@7^4V$cOQKKa5Sz)cpxZ z>Hx`QrbY>!D7+r_zvk-A^Hm>zFz(1Y67!TtpvY(D6i8iiW5)&I@U6w4@=6^1pJ+{9 zWa1KPdFu4%C$kJ5Tb}-68gq5Ka;a`Kw^iox(7uo7%_6EMrYrCMxij@RZ_fkg>bma- zL(O>2zu)}%VAT%BP4iL8@K1XkPQ^ZaD$K6@rfFv$A7mE1_sTk<`g>AUd66+OD;{fo z_qfn{^r+jqth+WYA zdN65U=*3LMOYF`(cf_>Aw>ey|Uv{!XG|zz3PCED7+G9qu)7BZMt^M>=T&$d}_{#pB zdTx_-zpZtfwX5Q!+3&E)-;oM%uk@&y^H_@bbX!*+I}kciH`^|J<-1(l_dHvZzTUY% zPom?FjsD%atJ|-J9R;n5+EY`sa^mVkx0QZd?mB*J`>uVPuGD<#I%YM38z~;a~D|BD*?v2y3+4xvrVy-v;jH3Q#(7N8W4%!J}wtSo{ z2OM;+e($tO2wJqr>KJPVE2ySo+>BhwWE>HC@v(m`0|Ud1a?r|thBQ{_ieK<97v$<_ z9c&YN1IsMVaN8~J^_yS+bN@2E|IOZ5`^w*s4j-M~E>`|F=7zX#(;xNkHYO>WtHbvu zzh8Lp^{0ow-xqwgdpoD>_`d4Am9>?i>J8L&7iC}&Iw5`KN=15wH}9RN&)L?UvdsS$ zqZ$#m?@V*pz3(WFn=j()w&k|G`guro!LP)R zmUCCH;ZQxhMC#!q*uECa_Rdc_`?vS>{eCBTf>(AO69aUqDgy)Om9Et_>`$8(6$J-h zczIL);8FXt47rv|y}M4AO0VNG*mXnTO~e~7>3bLW z-l1;o_!gtu_NK}2%JY=sSnhRQ0?z8|PEA_znZ@JFv3V0#OV!@ldf(}iTGS3Mh7GQu z%^Yh%hY~11(W;)XwkP`2?+X@k5y!8KY2G$oD0TCw@wtf$`fX}X{7hVQ+$l}vvs?Yl z<7#T&H$a^t5Hs(Vbis7d771K1aOZIxe8vemC*j3&t2$ z&=wI!&{i+bD<7rucVxvKG`$B-Ck$Xee~mGHuz)k1k>S9%$qpc83XR9KK!dwEj7WK- zAy>EY-_PaYqALVJ>)??`e?f~x7@!1nUki977%58y+!uOrYV~@}fa#!>Dz99b9JN6V zsjVzp9bCJZ7#LIn^o2O07#SE;F04?UprZAH3ltr~UJ9UdC?+^8p5|Z|crXH_=ao() z=r{=nrn9SA76mbaQq5wPMVlBH7&u#$Wf&M3WFCU|+F0;0GB6yN16ra7GD@b4mw_Rn z8r0tgabtS9AY62p3Ls~GP+K&i59$wO38Yd1=hhzNQ45d{1-5{WLgWNDY9W3Ft+ruk zU}=IZ+yT29IVz!=QI%)r1Pb$yjG0|PTdfKQ0)|Ns9#eE6{b z|9S@}m;3+k|G$5K{q^Vn|1<2o^Ga1i^XK2+uiw1QD=hr~@%^VypP#>Y@&Et9|Nm?M z|NI^l9J1=i%73q)J^TOc!~YN0|KCc8PgwGC+3jD~jl4`Q{=9hQ;$>qi%e8CQzyI}5 z%U1jU`t?C&A>VG@j_*#WuV<*JsOdi2H+j;usjpT#yZbKvvpzE`=gEyruTN|^c<{)n z<0s2ERz3dk`^JkerRV3*U$7`@Ro{;*N6tQYd-Uw>wci#tKUi`7#Nq7==cj~tcsbb} zIKWVqnc3df*|4L|!Prp}d)rZ7KL1MP z{9{k|9lF#oeWz1=(94H+PH$S9zIXbRomXf6ULRl9d24Bvy=RI?q*Z@mN<&U?&79Z? zJF_4D|8Jj{ShC{kc;*4Wcj#sy>Nz(K8v~yxwzVTRbPw3qv z^BN*-!)q6R{K_zC`5}83?a8y&{(E}3a!=pd)7OHnG}gT6nckKYlvCY4%PS;j+W-G| zBce+7?3;09Ui-GLnzrqa*8g8H?{Hd2RNU%kwHGF*m?(%oInL1Wciokp-JAMi)of$t zWCkQAw|zW3>%{8m4YjGNx?cC+F&zDW^xoG46*<#ZOq)>EZojFQare4)^$QmJ>a(rf zzjVU7G#_I}_vDLzRqpBetrfZ^BKOzNU;D3j zZ;f|h4x?`x!;EvM&Rw48FsWnK?(K%9C1x3OX4VJIE@e3O@BiN$t8Q#!Fi|qty>!o; zha2bSmG0QmG;IpQ?%((4tew903d72W*DgNTvH9x3&TyW}GULuo45c#}3Y;agyc+s0 zJuXkKQt&K4bYj)oYel>N@45Ya(XlTKQ%?T=vUXa`fmI($0-G5ay4XEk978H@y_w~o zaXCQZz|@8XyjpuM?^dyG`@m7g!7q|?im6JVRUk*yTW6g{kTdt9r5}y9^fX;CloGYk z^sC;uBPgWBkX7)A;YT$Q8xAcV5q>4xUwgM?21ox7S#5E)e^PDb+e>@D*ZutTH1)L^ z8_OT%HMdW&vhXx6zt2*^K>z3;Zy_MA!CpqTI? zqsRT3udLIdc)jAD=;{Xt+ZyCfq<@Y`xwmKE+4qxY_P9Q~@tFT#@*~rUkC|rv-*IN* z-2K66YkD2i3VxQwXSvyD8b36ARM?ZS=GVEN8xtxlSbB9fJKf1u`0Rhu=Yxh(`?9X1 zwhJ%xpX#~b@#=($;6;z{G>^+U%4I2h!P5(7wC&9gzm=PJXR_tDhYuU|mq?xEc3HV5 zDl{nK!Yl67yIQ{Sn|Y#&d(XKC&N-zveNIb7=+~sxe)BhdpKSD-arc|cM;}kQbaGQ2#_Zr_g2Yo{=6iu8?6 zoa=l0rM1lVO#zQ9zgjOhNL4r=yD0O4k<_G_C;!h}p~{sp@65?%XHVP4KQ22X-+V@b zclyt)U0+{D?mrXVVy001`$YWYogWui6x!WSG7`=)4SDxlz^s+y#fdYX8xjRLZW(PB zZ(Osq!e}?+WXY=AQ-40tF8Db;=h$h(Aaj}I`|D2Zi+w5)Tru_QmKQ5hJnPmMrD&EW z{dcXmx$m*jFHK{LYTp0PeR-x{rg1y#AKj`+E{d}Fr@86#k4K7{Mq8iv*&p8|Eb;r! z)fGNfD|Z=eeEzJh`=sQ;uO|(af`u(JX75%HNX+Vwoh8(_`i_0y3Rk6&FDd6XeDS<= zXt(xK*M}B%Rd152oKA?XQ%k=mV_U|aVwRCzc-~WDz4Oj38??iBtSmp(^LK6Z@?R-_ zZ(b|xFq&L-ZI&RPyKr~)x?P9wMr<(-KD3E%=F2~mK5nX5DR;BdqbTp~jitWaeLI!* z7`Jdfe0pa}f#A|sXU!Rjo7Fd8`S)qvTl&y4q~p8E-JBv}mfu&g8#S zcjl+$UpaxsGv2Dt>zu!yJ8XGPbKRt-NzO$j0y}ta?$BR1T}EKHz`}=Xw2iIjzh4r) zB`r)$+(&4+;Lg_BH?4A4{`}7W%Wtm1H}#~>th$-gpPxHxUDf86)wgktxWeBJt6Ar0 z{VeB>TwOW+_jSS4nI)%ruGQ<^59;>&vCg%)(7ImVs#bKZ&XnZ0XL2rZs01cA>ABs% z9Wi(9F)O3|%U-vCr;1tmR2ZG#d$rqS(rNQN%PPfLCnEJ1JuKJy9aQ-*(`xoM&)Bq} zCHx0d?rCd(-2Q7$aeUsq-CI{pVltUlTVGnOC+eS8XCB6&Qf9o_!*xla-OP?wM!iyq4&k&dHOdZoGW6_nPV_pLj+3 zy;LPSLW@1ydj9^idCvY*Twg^pQ|hJJk<-Qb+I+uDUrD6i=rx?U^G~$Jsk1Vk|9=}D zX84x%%tA%M+y4@sYNn)DGajv;nW)|U=IO~dH*I#E{x|Dp#N6+vebOS%@}#<5 z?AvH{Gw``ontq<6O!+(W^=I0a28o?XH{Hzo%89?QW^2mv>`NxOr|-;)*|k!=w1q>i zi2236-jigQMb}1L{Te|*6%`(%-9Ui%wIYs}u_s;rxx%Ja2)mNuvT4x-e%J$?~ z#g#XwYPe0-T=@~SEjsPa%tAZ6-$j{u&)(b=zIRDRM$+qO$rQ^P?TNECN^3<%KAS4B zr}UuO^7V`Q&YU%GJFNZrw2iK1%`Ug#kJpx`Nt#R$nV%Y^bZ}Enex~2VrFZ8nQRJ{T zHEvh^wxD`LTHE$Nug|c{%l&!TBg69rg zn9Xsn)O*zjgC9aCFWgF*bE|6m84GpKezt2fze_HipkCa1EntqG-tOXg3;hMp>`^@| zzVW4j=Q1ym$r@g!X4;;iMhj?e?Dj@&*wL0v;J8-L_WHB{rb$6OEQgadlZGI zZCm{_%-Duc=EeTLe(u#LPsJ87<#GRhlz8NA;@bd~o`(xLV=^sI_}r;K@Ctw%^u>B{`}dfc$9(=jyOB+rsc!L^*Uq`y{=EG^TTsBj z<=Mm4l8t8=vpW)v+IQvr(@qte%J`$9(77q_pRb19wS`~fH&wVPS{LwcxHNt|3pnn_JN3>XZCGf?ZE4Dv55QNarqm(H-54k-FV8b^Jm7&XY6l$ z=VvMSOf@+y!mJsrlB%G2iTJ8qb!mx3~SD zU!Nvlr}ymn^#9+&-=0-A+<*Sj)BS&E?){KP;^GLecv19W)t&N-3|MS^dx^<4rgFlNmRQ-)zfA4?ejP{Dtne!HePZO_dkH6?3~F8a>daC_|+ z<`nkkmlNj(|E}R@(i3b`o-TaI;+NCmyyTz=iytfGb>ue3)Lm|S-@NYV{0_^_n|@o= zp8v$V=YnUHbJ)4=b>xS{*8%O?+}itPz1wiacNQ@1N;o$$#+=c3(eVr;(;?o_THQrR$eX*{5>coiZ~>IA3|zZ-spmUn$&m zTzT*Pfp3>5T$QVeJ14dDl!@Q7)Ytau!7rv{aZR4el^_0X>8mc6MawuJa_eth#=Fo> zds*?5OL@!J?0<3o#e(vpZIjEFtSeo5YTr|iaNG256Z!BfnokZN5RY58LZ{cOMMdqO7vzf%<+6nr;v)rrMb^1FJ}Wj^Xi|INPM^N@Q{KIcbU zn`hb^W4L!F?vPM=TIaiLspv14Q@VR}T`!1wT)WTLm>1D2Z@;bdreE~s34v^3m%n*& z&i!=YgMn#W*3PNT$(A{K+!N-0+OT}?oq$lk%7AFOtS1NgZ%+DTkYi~sqrrXfu&TwI z+SoMVW83abc~Y?5IRBfo;c*quy@ICSr1%%vnPh4y7L6U#B+&eMoDKQJ==atpDm9bLWaE->k=Nk)8`H zuY`oFyf}HG#a8C$X`avt6T0H}8)q~95s;gSn}syDXYu@NXWo z3&XW7mp}D2*xTKh(>S5iKa z99Ott<-Nv>pSbs$X6t_FDb_B@;u1af)QMl%Q}3r=O`zP1x@z_I#jQKC+tWNP`9($7 zC#}1_^Zl#~k@LzQI2_l#&`^1|EBzF+|3jU*ES`M(wVyS7*=ZMRoFUhjGj*AI*axi} zp1X{_pY*-+ujJpLGQsHb6??C!rFzjbBRlyIn4D60mw5DG^Wh`bXTBGn)P8Lh|I;y2 zQZ+++?G?)lyX3Z~lx&})C2{{MSBsRHXu6Fl zXnE$Vov|t%EP6M8?&`kvMI|Qq(nibmn>aRVA3Jr8DUqQv>QQRR+v(j0H589evQZB3 z)N_COx>9w~vwa0?b*At9d2;T}(CgW5e>vm~3>3VzR!KVFUAQ66K+>lUW~mrY5NNA#=g~&rUN_&wVOfvYy-MOystxx%+YqPi0AM&1w?bImLKy1s)-1?m+saVcEGspItJmtAQ(}R^#C35mFRPx;_&WP>yT$M2U(ZUoPq`6Z zbWJx#{o=v6InSFkii)I6A1%4@;E1&0MW4@8`h0ul&WW&SczOGJ?`OuvCjCZ+i!^;D z8r0msd_8daxKdU6`6E7mZ8oowKbXAlMw?Ey&c%rlZuL?JeyG|Ce-hZ)`BqFWI3ysk zcca90TYlkB3mWIlW>623Tefpy;EHC|3ZKJ8>g;?bGtD&lZ%GSKF z<@VYuJ9)pQH-G-5ZT(&Nl9|YH#y=+)WQ1IB;*XQLR~6O0ggshd=>l7psuf$5_+(2< zdbq?~4ptS{`zb)B`HnVY68 zGf>>$ENDOV$?s3y`=+hd<@hh1ZP_9CONwJ@gU22<+YcvR zGOHTBc^o2QH7$6$-9a^dO@5J+SHJUbTHTSVp=LS3sB&)6lt^Q1wnb^`?pldODvM95 zJ~Fwr@Wqpuf0=F@R&Tznoc-+RahW~;emdVd{f>XvO3UMCC2Ho#EnP0N^rdg|m*6Fu z6YFkHC`(P5zw7>jWyMQeI~Qpw^*mwkGP&)zGQ54#&qt*^LUW&Z$V~e9WM|sCBY|mW zZN#2O7TtBc=-n6c>q!rn-E)tpuPR)(HJ>wC?0xM_(|z|7*LKv~3aaLRvs-7ecVV@) z^ljxi)i#zhPcZPh6g}|>&dOMIYi5j;(t3%|PLYLQ{M-t?uD;Awm=`Fs!hYZGcly&W zYXr=i_*Zw*1DB%y<>Eq;3*#5 zsOD}o;g4UCwk2Oz)s)jWDY4XVPI`w3a)z15A^B1#xYzR5oxa5hJk*4M1 z9bwi9pR}gQc&b|lxv9)vm=@Rb;ltN2-_B^5e2d(n#60~$V1=CCI`OwFnRgiM(^&Dg zOV1^0@fEF$n|xLNbv1Flnm(C1qeGxvYmbcRN#_&W%e=0puQe{>@-AU0sd9Z=6vet} z{=G#ebFvniREzBU5ah)uIB`~xuBhaa%JmZc!7A=rHkOm7{8{H_yj#4Y$hI?^xer+X+{PO!3^aL+PaSdIOXci$49bIT;F&i>Kp5?=Ez?N|N=yBi$R z?fxGQCUP@Q4_Dz|DiLHGbmIA^qFEvgLc7{EcTQL}RU{xFK&4Ued6#MT6^KZgY;s@ohCoW&;JmhsZhH)yuB(DmA(xQE^Bg`i*1 zjwzEJx|&UdxPmSzHO2Z)<6Cy&)dPj5rU%y+HrKcC{o`-qxHtEEoNbbH?tSUF3OnaE zos+fi51;;Q_rBj`mt)Ulgr~kZ-+;RQELG>ItPT84jw`Fd9Y`57m%hEK$ z@VMP>vXl9?0FoQ&=>)qcxvG{2rZ`}I-p29CFB6;nPMCFj>$--!&W+0NK;VV0%4q`vX5x>E<| z&H8%R*TKb)VQS-9KedLImiY}w=S0jDJ-cqc4}+(O@iLvTXLB60#SZ7OsV_A;yx>gI zjk6v*&s@lx@^(|7QSqgTH@Sn}X=xaLo4J(r_ZgWfkyQcDSaz5@rv*HdkeQjvp89OT znM=(^$4>;O?THCy^o)Mi{7~89oXkwq-8rA_iXS-%_#IrZteE%QBKwfXN2G;0P8dz9 z5&mZ@_mgq$CYj9bAsw1N-o3t}Varc<>z(93*1Pz_rCGZr>s}OJU0}EMpRjmZX3(jo z`$3cMUzHX8$NhhPpsmM&$NabM#|vm~7GL&;xpQ?u$b%H#Rp&i_Ca6!_xoP*u>r?jE z{b5@0v(V6JM{M(qH*qUBE@s*jf6j*^WB%bOpKp~tGwcl7=Tv*6Fq3I>#FSYKmG937 zgrA#PWL|Mht^UH}>+5bXuk|skn7?zUX;y7~!>MaK$|Ig{>(!5s&HB?)pZe;!Vf6*w z-`#UJa|bGQJ^HaWdZTr%QQ}7Zt9v{>B40G?O-Tv~$l0JQ5x6EP%!7~XQP(dat*IhM zGiD30&0HrP!Y_J??V`XY7S~`MCqZe?NRclhwE`S-tu3vVZe{)ES?`hj?#&t7|DSiK zpIhO>XXYPuCE47GCp)m9$oQTAj8`e&Z$(d(+jvja%sqImgmCw9vvo#0(_~%?Y&*zQ zZ0#g@rRu2J`YN5$P#1fZt8Z`Id|g%f&1KEvZiD92v!C;s+oiKjmyfBaXOZOV+2Qx) zM5Wxu72$V17QYXDCVb}93CC|iEOX?8`eV1gj94GNk*~sDdiCNXbrZKv2|TDJFg?5W z-L%uSV#W6Z?(l!yuIU)F?^sUh7Y!}8!k=!Ee|~a4eL0zK%1vTD~xxB_@5Z)XK9b9`4BB zKjW#dlzErj+oQ9r*KP{*ei?YlupuJ9W8r4Oqg?GdHo}UQy$Adn9lxdLwN5R(wsA9q z!D{w$*~aWP$>Xz6FPV~dVaeNr7w9dYGZ%!^- z5clo*p_l^8UN_$v*ViiReHNJa>_KItyoTWP%c~~2Wf^-}ytCCyd!**e5IS{Yv(W0Q zfKNBm8fIO;c(m|nlB(YHiRu?3)>%IKbkf>udg#Nt9XjdXXIq$W>gP$?x6{XuO=3yt ze(?t}im`{E9^&fiV>;v7qs)0<@8K?iHz#Gc&)8Wv<-^1?>NP(l`c5o4At|j|xB2*i zr&Bt%2~OV~In!}<_?EhilFQS285)mH-B-0)-p=FS46P+%0dn(J&e08y)Ly!GL300F zx04d#%Mzy8l=pmNTk&Y8(W*Vh>$Y_)xuR8HWl$N@zUt$#_kuQ#OD@FeAJIAZChx$R zsG`$5l{cN$Yp|?JICf-8-F)A057~&vvnREGIx>sbt@+js8}Z$jJkB{iclz-D!HZr~ z_xm=*+5K)BZ$r~AcA2(H_XmExBcm18*5`HH>ep0*^=T`Dr210ii-Kmp+a`J8?ABX7 z7yr6mnqIl)UdiT?T`KvDYMHM{&O522A1o)$d|j*h2ZPtMg1I|ll;=iSxb)g+D$lsr zv(QK?%!TjLx=YN{g0?9tz1!TTBQq(+?WhBD+O>(%>ns&+KVzD)wS8vig2IYM={Ln))|j=IrOQ>Nmz0SxPTo;l565pV|_CxtPCIb1r^+Iazy~IKyYHvY?Gt zYl8M_?UB|@h+DgO6XT;#n(9}dnlZD8J1~7V&wuyk^>5WnT8tl#Dy}-@_m*w$pFK7% z34VL#I?Ane5Bqn`Ffh+p#GqNbj^!6q+FDjWg@ZL`G!M%>{u{b4bkD*?lLL#+JPO?! z^>$L?K5eCx8R;Q$Ig_QIdE|>fNS$kXO8x!5if3~3*sVierH8FN&X890qSGi-r6FDQ z%!a^K(N{mN+a_sr?*1>U-D-E;FSIV7#5$AX!DG>vli$sXQnyzYWIS_(`_Zl^;p_gS z&R*#IGIjd?2FpZ6*Q>&TA!*+NFT|e?_I-TluZNUuS;xGi4>oNzJkoS}!X>%X*@^pK z{Co0=sUi5U0>8hzO=ZFQrR^mGfdw-U%wczay~Kr4(`!azvRjemy{~4;w{JB{9=^Vh z&v?OYez9rXdR!U_T8{QzO&=#K>Z?R^Zod24WwDg%nYQgor_&m4)?NDga+$jEx(My? zxo1>jZmg|a;mkWD^TtDM1NYp3hq;@U&fGEo+)fFPmtiw)t0u9}*LzW1TC^^U`I)2o zl;4c{TkLgbT$B`Ywm#!}U1)~qlxD;8dgbN`(_;Uzoq4laxr5jGVAP``wwP;i2?_}Y zUyWzH3}VPU>ovpk$tIrFJtz2%c!{1kym;B7L$zr_*WR=KS87_uV*JTxA_oZzKZWmt*I9s2YCs4T4 z%!6-(#oeR+#%20{*v@!lAF^;z^_D1BTJ`48lDmy;$uf6D4X&}QsBM;bY>{*5;O?h^ z#T%A4J@(m@@~ljIQt2z+%#()OUOxEmcT~4qGC6|j^X4a0^$tyJvicxWd{!hhv46t- z=4NJLizc@-U5Zsnr>Fh!W0T5!$1v$>W9PJsN{r7;axTSKZT)|(x80EU+7eHd>Xtvd z6yIn$d2TnXFtQU9j)1qnGA7 zkGZA7)64_I=f5zvKh_&-yUzV`X2jh@`HqFP+v<-!KQq%o`M315l9HW0`xaf?vtM+x zV5z6@od~WCbNrq(-O&qs=l5@izVEkKJMl{sckS6|e#vY`GuOEV>rd=kV`);}@G8vb zHQO6&v*63`#9lwW^=ZC{S>DS4!GA0>uFKv{QP!J(>xT6`vxq|$Uu^ZxznFE}qiCk% zWzFli>n^Y9c_>~#*Vljb&(G5NAJ$FT^YQ$Z_p|cSXROTJTJkdJCGVBOH@~;0tWkk}Xd~s^%m;TKXXB|sc&)NEFy84UHTc4kOKJ9VI;$mMlksprF z{r^tpT6;`goAb;E-RB8nJW~@d1j*&tNX=||$hD2hz&dNvi?onGzwW&3Jh>+`)K|jt zRMn0PWgMcp*LMlC&RdqIdR+Y3+TQQWo+gCd%W05*xF`C%sDb+T*Dc8w$$4iE?$2D9 zuaUqOt-X)y;)T@?#_^Bxnsem zneI;&CS@E3?X}eldiX_iGs745+*otrrNsq*b!{>$Sf;@~4v4M3!ABFg@7#=k2xY*2`54 z4sSnmcurNqo_G8S*Z0&-U)afR^sQm5y}YwTraZUaqK{X$pJBDF>5yLa^0&eA<;5%0 zqgm|_pP8$)#_|oL$xY9OpWCB%-80^2_ISsdg;vYY1jzkou-S8SkLB?*TV)qqS+8f* zoK#pII)9nFeqL_HvimXGVOI>pHtq;+Gfwle*=?V?*D5k*KUcx-s_)!qHrG7LlWcZ6 zyL#Tw1=qh?X>X0S5eziHz?`G}O`vg0DBl_XX%_Eea<5)_CAD_4=&yM@duPeTb^2C) z{8qd+O(HYtT-1#(=P#x&)i+Lv=k+;%a1M8?Nz$t2vbtL$&qgGEyjyBvtRv>%uDtp^ zMrGk|?;SY&$1~lDV@AvLR7=e%=@C*3 zKmMLux~)!fUFIn*)En2A9#NH{NCTG3qKv4C;I-?ollMY<`q-dPB~RjTwc1*=&)w+;<(U?`5tGb zMOlo+o914Svb{6prWul}S>~|5z1P@&#MhwL zBaCat!ITh7bDxukWC|q(nT}omS8y(9TWW*igXiykmP~IkJUexb(d0s<9oM4GxV{-} z(mSYKd`jR4Q?W0@<}FV(jW4VgwRm&!YWg$%8GD7N{9JOqxk}f!=yHjIRP(f3+;chi zmoKQk|J5iv;Ya43*`bk-gZL$XJM;yn9bc?sW#JsbVtF@$;q;+1?Ln6erbRv9IERnz ztN%t58A}V}W4|7#E!p39kHzQ>V}Y2*<;O`TVeBl&E~oiqu9&^K+IwP_+cnqtI>zhk zLbsJKSYdN!o4a;PY|*VP&3b9Z4+`zhXx+TN^VI7V<`-O?PyFrpPe>TlA*QzuqFO15S6Xa^u|B$}d;G?01h0{X+vxon@V$GX& zK(y>S%S`i^lQfKfO$!%WnU)e;Qll5M``&VE$L*CfE(eKcf1f6)ntC+n*xZc<%pM;K z4t0KgZQf|~S*}%@MZrD6e#OnO&l0w*|W~GR0!Tcu~?fZ>L zg%X`JEZf-+TTM%CH^}3EZ#XG6{yf)b1O2ZDlrB!4qNaE`)a>5X9?jxaT?fzX5V!O- z6@Ne7dTyHT;+(i(OP%F2r@1<1?%q_q&U5{W&7Q62toN?|;MjRtEAz*#v$ZB<-5z7{rJC!IIoxPSLqeq68hXk@ahiL;v}iNbI+LyylN82(=EUEB5S?K z+Jd-uN8W#bZ)RsOw;#<+9i3PJfVRc2m|4%*^w04V>Y5 znAuE^*S#t5+IrQ;XPq_AYBEX|Z@lEN#O~B9Ya7j%*=BaOopGIUispLXQ+;-(v_ z{$?)6_N=+0D)BBMGU>&EiK*QE@1EqgIZu7^&^@@!{mXKL_GdvgpQ_I&mPH15{n6@~ zy~#aNRHOKhko0Shgq62HNJ^XL+1sc%DDHQfVERlmY-vN)F^z5~KG8RcVK;V6N&P$B zsG5U=ZOfbN>Pa%a-`(3!oG6J{aV>e`1~x6u%?qyf6q_#IRpq?Vs(7iRN>H;&w~KOV zt-9+jX{8P93#UyKw_rYh?QMMPZ3PwQe@;tIZ^o0Tu`7czP;-s8ZW_cHz zF>~5a&pa13MO0MHw731%%;?n$59PuOR+KDG@KDLhTuHjf8cLY*#8Lx0>9 zyLcjISCKtW`?H4jT|OD++g)UNI3$gJ>{%=rw)lxqf%&P3#Uj0H3cIfu$vjMc6-KFeZLR~YwnPfN^K zH9TJD-c=hj@Ud(~9Id@F!p9#$Ssdvce z-_+@9Pog(S{=C`~lUN<{!8mm%-zJYMAKO(wmE=G2KlR4=|Fr8j!#=uv%`e^JsK}}x zTHLLE>f+z{MoTweo`m`jYzF(LT}oP-rInQ=ao3yc^OgT^jjOLSUA`jP_F7jbEY?RS zZ%5eaQ@4BqDsvWXb;{Jy?Gko%5SVgx>U9x;nMyyTx)?fLnva?gZ}-&w)4 zw6@&3BCn*pn{U$Z6FrN2Zuq$W)SvPA`clJxClVh%<6P@lCOBj1Cxt1x>`UFwJl#<6 zo;N{lBrUw!4I#ss2aDmS3Ntaaq3NRTG@q^H%+o82NO=(JUck)CZn>} zdDGNa5^dX4El$Y%Ney`#;-B!0`c zFul?gQ0_RW9=fyh%%rvn*Ns$pL(WdB6ySKZ?$^FmoB`#sKJ!>V&RP+-``+9XIg_&y zbFbv7f1cOiQ{Dwbo{)EM`fiX&jX@Y>Dlw1bE5J?5|fkX3c#Zqj_qk}du+%9mo^9xV~7*tsZsw?l%t zX>N&{u^DeayX`t-&xv&mZ{+5mV~dZmYK)k!F1B{A@0`7CIobwXhxKr z*N=H8r0p|nnX_`$)pN5GufJbqwM2KZPeZNB%(YRu3}p-_b#f;KYoFX!d3%di=k})! zVXK|rE&qC}E1@}K(l!3ejBgh+oicf+5~{II>o42S=T}}GY~fp(yM6M`dkGh!7UrBY zyu0xh51aF}vs*51IJ;!)tao<|bv8w1+-<2%(e6H*Vvw`>*2)!Ek2%j=KX1vUhpR5R zt=)EH_P$TGYcrbLjs~y^pVBv5uz6zg_gm5a++Rh7xMQyKWVP2EXZ78%=;BG$MLpdI z<{jzD3^%OqikHcXVo70}su!@=>V9((r(?PQ`O;Z;1H!j%eXf*yDCOPNZ-07ZC%m+} z`^qlu_0MUaA2j;dKH#6ce|L41+>`ES3jSOHH!m}#&RX&8xmV28ZQMWQUDF?Pe~!G! z*1PCQ&LS(z-3o=%L!|zl-m<7^gUHKYukLPe6w!^;o?7P;k}mT0#>TXd%eL-bdXwcN z-;~{(Ys)+o&wkMKxSK$Va`3d9N)p|GRJ(nGKJU7V=)kv#&-eIO;Wye^^+?o_+UFN@gvAN9m_4dKh z_r)L7zgzjwYxY;K`3qlVx__Q(yt67;TFp31^k&}9O&<4;hCYa&WML6z_$SVdZO**L z{;RWA2eecLhx={S+SuK>pk>uGo7o}mM&i>}iLhs>Tsx80+IhZ*VUfn;IX{0Nd$QK! zVn*22{y4uBzdKoe%*T`#@~l{6C|+RLyUf0N&vl+dZYNq!>YT_ooPT_-rP10$Yd1KB ze}B668MA4eKGT`I?Fn2j^OAdiCI*}DKbmtrYR%*O=FjunZ$1p@{Ql*^f!5y}3b*Vz zCiC;i>l<;KZ~lu8-%w+g!gM-V?rujH*B{lQv`4+NrmrUpFS0wqq5td8A@n-OeemWbdy{WVL^x{RIUc9UMsL8wH%7?>_ z!irfZi;|u{TjBdCyL<9;{gz`UGv}Y(nI9L@qg=Y?SWUg_Q-#AfSLdJSO)5&`oT~3| zlA$GD<%#@l?dT25k_y_RYGs6brnEX<2)}W1&gJE7t~$q@{j>Ib$)8%x5s|RUW_ieJ z>BSSBmnF|)l+9o{dGF z=P%MJaZz4{ySZSx;^)A{9xA7n+HUX+;QAD?qfbb_>XNj&R{kD#zSZw6mr6E$_6%6k z74unJ(=ATSTpi9L#QvQ5HY2CS%yo>xQ8&)c`ry?vo2#v74l>RRV49iQR%Q{z;rEU=tp2ua{p^)z z1uAb}d-y#5{>)Oo$vbb}538E3WPJBj(ESJbuLB-@ZeG1f#;a6u^HR&HyNYJ6WQn?a zOmSxjQ~AQwjx*{CrOO;ASw?VYm35c2D~e6~_ukmQhxcfToPY=8iOw?$&n<1=URFHu zCy6gbAWhxqy5sl1FO<}b<)4^*lFw^dvuv`;W_{PRfHMca*QRcmKdV|VrB0xLf8x(m z)0X{N{r8JQ@Q*|nuOhRgJG-`S=6^S<-XQEV)Q~G>J_2z*OfBRDO8f^AhDF;Zo)%@f*QPXQNsr_V4`PGv3_qE=XFWrCG z^7qbVk`ZjWo_13fUEH{8Mr7(Hy||5E&zP%LEuCn-`p|Fw-bvhZh0p2sN~P{H&o$Ca zcG44mcBTJ(UZHuRRtkj!!rFg2-J-C8kJu;&mW5SaUtM{} z)XMFy)5*EwF{ixGTTWiRIZShE?u`^<$NN9`z3rcI>(`89&-AuN<@BuSy7^;9{H^V8 z3+4a#ZjkAF{kSl^l6~@8o&L%!(|0o)XL_k-oPD~YQmJnD--xANc@B!TPY=poIF)y* zGgxWuG2zftk=s>g{0=qzu*Kz?SDfW7#p(C+MPoWX2`CvX(2+3a{!(92UA@|5ewnuZ z=NR_+IQwF-*t*8<^IXpYg(Vb=Zr8@ z{_MQ28DaVtw8AFHPyg&9c_3ohrl*dY>vz06V;(NAa_Cn04*l<%CxpAM{}PB_*}CZO z=JQ#H=6&AO*;KT!pg7@E>cW62ANcMtaJ9~wdD4*6x>x*Ac~{G#o&$?q3VVJyU0gYX z+t~hki|A9%))=d^6>;Z&JM6WoynZGnV~($krg+!US${RBw=O!LZ=<8zFSzdK!j~#B zOJhGh+bMO;TH5}{qG`hIHRp5~17@=Sa?fX!v61o7TiLZ_Kl`%7za6*8AJ{5doN~Q6 zu=R805B@$GXR#?_?VGm;EW2(gc7RQ?H}U;~=id1~#a*8SY&SDFO#3kZ&H;NFo0_@4 ze{Ex;Cwj%);GaE5SmwHIBLAz3KDDH~sUO#+oG`4ZsacUO@`RruazU=plDW5h8votc z$>$|i;=JozqWV52mg&LFJ(~m_Iy+Z4y-7@A^WAl2`ldV98A+j@YodO>kZ0U;k~P+< zyy?co2b&-7EqIj5=x-c$X8zlIf(HUs&bJaIpZwGH z;ill$`fb14H{aa;tc~^ewL2ST7&IlsGs^n@ke^gplE9>W-c%>Ts9%uhl5zUHZ=XL; z-mGLG$7q}}i8b(=Z;4o=X0mI-9j|96R|+3Ldq6m9`m{Hl_21akcewn|WY)g$^c?3} zfu{>HzI65!y)QqnWw~k6;g^w*Ep_h9N;`6E>$7F|LOvIX7fhS>$z-d1QN#}8vmLz$ zqKbo~Pgm~DF9@6VEpywZLy~#(m}f|4&7WJF7y7zvN2iV0g#Y~QthOkKJM?6ER|;MWjyjhW+wO3H@puxmPoFCzA5F{2br1S`UxlB{G4YQcFu0r zXMts3`;C5Q^j$qGaXMkXv2~NIiR9sglR50Sjr&VCq#T2`^!d!rO1w@uc_zW7>RIQ^ zm6Iin`lHPl|8~4J|MxvDKmF+oNxquR>vBcrp52g=w&+g$rEk7gr-UW1Ywn#J?tZ@D z!HZw#;^&=dRa8_w-Bxii!|U)I&qDFUw@nP8zgkvui7xmXdrE|7{^R5OZ#KL-wP3AR zY3z5sDXY46@_u}L+|*gMbLm;FP^&EqedbI(yQ*smYxRjR@7daR(QCW<=P_ApMk)j= z^6&bt)F1j$vfb#d^YN}{H8mCIPM%YrW60EY#!=&x^BObLqgLrc@@9cK$7+4twzQZ{ za$Gsb;b=F{udlb?vrS%jXYs0UsR*vh+r6^8$$R86iyV^8D(oA@ z1*KiK?tSB%Q+@Mu#q)m-Zu;Brcfaj>Keyg)|N8yExn5mXPJ6(gcEo4W%+kVnD|H)v z4=>Wcmy<2E|9ouV+pVKbzOK`i#enyF8~;^*%D2-w0z{lNwoOYb+ccQ*Z0~ zF`w^uG5>wf8L_)(YBDhd23?sM{`vm&AB}?BOs(U#xVD#<|GMs#^V-#+BP61DTX*GG z#nWPo9j3e}=vbl9w6TMce1a4E-xVpgc`hh(Se1ZE+t&`(R_FoU)Xx@J8)88p2!i!sPuCy!p zqphRKo&4s{_Z5D&E$4znaxT6+)b}`g+TH!KM>WnyP5z?w$X?+Tr-GN3-tVhxww6`Z z)vXi$Z$FcrUENP?>z!>k`Ai#rl-~R{jUj02+^XRDm*yxnY?@HkR~%e({fwL*Z*gJo z0@HZgBr(1x9K2T9i90*3FLZDnOupVK#Blx4Jf2?FHU{oF)3@E(uz@F{@SmBIsYuH@ z#hL2o-_%LHVo!L?Y88;-5E0L`P^hH#i`Hp7-hDG;WM=7|VORI}eRidb8pG4B{=zMj?CZU!Of_YjHCH58vhz-Y*f%-vDc|>;*f0I6 z#X+huWOn}1Z3&($1b#4i`}eu*GgA1H;N5rStWZk~!xgRDovTDkfA@(8UrRnUJ5r}~ z-I>*eOyB?5?C*TFb=k=mFJ~I(-0YpP(l;z~pM5Ndo^|F?!g79@!y;y%eZPNZS+T7# z$?j#Q>Ra`2^Mx!9XD*#9SIIOw-lh?-+aOzHm4EQGq+|DA3#qfupBtj?n(y8yv^z>` z&)OC4FHdqF>6RVS{d%JQr#^GvuCE+-=vw%W?zl~Q-nYC;EF&%z z1nOQkjo{cmYoR5__nDHvFaA=W+*Z!MOkUP2EsW>d^9S1Ax9hgFs<_(m{uNtaF)gS1 z+^%0HjB=>~(wQDsgsrN7JTq{SjP@Ic zy}K>%O)Rjm+{98B<)#obP1Gn%Zta4|Ijs{uuX?5}@Xqz&w)S_H9g+lVq}+L-!<~ zm?+A8zjkxp^ACcVUGF_IzCY19F>z&fsJ=nH%E>8i?vEyQ8#;#`wayKA=W$47pFVGu zjA%jPtA3S<&XPrfHtz!BxcE~O&atxb>P$J-SB&qZ_2x;fKYYyK0mF+~ip(A}O*|QXXWxFbvNf+cA^C^`f2!B=&8<5c zI8I$LXJQs^a%2j8ZrBkWpV9EIbLOXjXRU3YCP+S6=$$0?=qOW!B15D`#V%uxn#T`R z8F=O#Trhcdc?#1Tb*au|MjauEgtM8V20IiT8UB1@THRf(X_(X?G4puw!F2%=tXpj6 zb!Uo9U|Mq0#v*X$we(GrCmv3gy43LF$e->f#&>F#a;(^J@k*-HI)(%HwjSFi()Mu0 zm*Y;4+J9Y)@_KQ7MPHeFklzJwzS&b3CAoD!)5$rSopw_VvlCt9 z#B<*>%_j9PL+cs!cJ6ehebqld&#auD9XV@TcF*H|D(`+jI=rg>YFpaPv^CL8X5J~& zT^Hp$T`c=~D)TjWVZ}E6lY4~Hd&P5>3Kgw$c(%Uy<;*XMkIQe*=Vb43{_AEm z$8Em+zSQ8_^@{IjO|8~w3t2xw`>Dmr-~ag2pWT}E=jg^iXXUQmPmDA&{%aPhdD@{S z<4sn~){wnL<%@DcLo6r!J9$EGj=_1h=2nd_N1m@15!}M^_Mnqf%|V5VMBZEJEVV|? zwJp3xP5t~5HkU62pY3j2{B0qZK%g+EXQIwb$s^+T8_pSRdF&Z7hqw7OAJ4Mr6KqFk zGM4tZb{i;2z1?wYXRx*0(x|+5VRGm9 zw2fyMH?r%xHYYW^F{=vpGGzXFv_o)Lhar1QTGTC*udPPi}$F^s5r`v>AZ)WIj z=a4?`cv4Y#)t0sk+>^riFLv{9jVp*NIH#)3JZE!M+q z{@t`GNA|SMx_5Z1D4TO@?)2R|4hgiK;JB67QS9q6d1jf&g0qv=kM6n0l`;LmLereM z=5r5EuG*J!bDJcynBJB1(@)O%5-F*;ewi_^i-?}{>Xnryv-172E!Us;c)_;w>!;JR zt>sl?T#s5`wZ64Le_LqN4S~92sV%w1JN?e2KR&8={fiN&li#)rLbK9sy;I-Hz334! zO*;|(R{UuYqi4##Yh0XDgninciPTJB^sITlv5fm}+Lk9@%eTt0dh5GSU82SLE`m9F zq5a8iPj|+wt-dVqG@kodXqD}*g!fTZPeM|;R%cFUpQ!YImB7?8&MnnPKA35wJd>4H zw3||5AvE7Mb>?W~Da}$vj zA`;cbNvFj)+%!|>{eJPRd$#`WQ##k)%@yFSzI@zpcni72OP|%b336h2$P9dF#N-7jSC!4;EyzL_X z^v(3d*VCQ|ytuj4H2L-F=wjK~4C_xmSQ*V@q|cP>_-sSu;?Ef@MNMafA3U6RqGmr;=ZQO)u1Qbph1Ycrxk$sMuFuzIial)RzI?fUrRlyp&#rQ@ z5B*oeS6BY)jk`I~>67WIX$zJGG?#HX@7lnfG2M33-H2oN5^i7o>B}pvlgs?GqHw0^ zk&m5PrS2=ruT05&SsyZE&4#7_*}i3cT^iDGY(m?;f;&QCFIr#l`uNI+syrRyPi&_)}bBq?VirudC&N|WY0UU+4mDn zs=TlF%-CC1oI7!Q#hs>`tGROwn+0b#7nR@3IkDi^Ubn@&OI+s`M&Ed08Io*r?_N&# zkvo;gj%r=}voY7a=iY`&(?8y4RSm7y?UdOo=F`xS@^{wl?j zEUtRGm|4htY3_kpt63b_nq_%zKP<3Od(rB>v}s|QqNclIz}~Bj$roCJ zUP`;H4VcU5I7ReaCcjD9GOM?;e8;-Xd9G~yyz#+$@#>|;#;eLI&Mz-MdHO_)QFWxi zob|0j;<82`|7{8->3J% zxs*e_lI0BnOhUF{E3%G8S=KC@Rk}s#^{c55C*_pFAw4S;XoYmkMt5=OS#{RCu($Jxv9G)v<9f$M{O>&*smH(nDzWc1-+!n2-Qu5L{`eL3 zeOzpiU;kHdVbRZ%(<(o=#ndgT;Y!n*F7vG3e;;$&;{VxsTdnS!y>s~gFm=uD`;Ql0 zxbQ2=T)F*cIalM)qAworepr5*VcAys$-w34Uyg*!Gr!LLz_aD(Zu?!f_PfeghfLRq zKN0Wx+~S(l{k|#ey+_Lrui-p;wQ%}ZyWRS0CWY!;`h0ZJjOb_k0~tO~Eq>nj=*5AJ zYmYy^)AROq>0_t4%e6|~^FMhmSRA0u@$rB6zr9AWX+AL`DUEw()qdTvQf%&py-W6m zXINS1b^Y8B@Zt4??SJy}A2*3+KFvE8uW9W(n`g#(IrWz@hG&|y9+#Y6(!(ZX5H`K| z(Z_|XkDan}3+CL@4`b>RE__qqWowllq}={k;6TT$6=rp>jJ4m%_&K~Sl94n!wES@4 zxk;-mB*d4>2|O)3@Riw^jeD=RMD~F~nfVzHm&EnBNijX!vOI1%8{hKJY~l{9-xoE$ zOW5SNLrSMEzoDw3j$dcZ2ATIqx{mv%bnV?0XX|ih`IK9)ITMZvIqS|kv(-H0S!Vdb zDK}IiS4zCKDL1a$zr;Y<{No$dn1%~yXUq#r=c)U=`7`U()|u}to=oa9=bB`-`JHCa zN>x6S{YOq7uIMa#5_I*s@C@!vDbrUbdTTB0`jBb%WnGnY;Dl8% zEv|Q#Ov#yeN#x~}ct4&;n#J!+8|Q0GdK|e?tjO#8!lG!^<=dMoUre2|^TIU?%?~`K zVPEIgzPocdtubbeQ0l~YG3lZ$H94`D-rb9uE_LLrK?x`0cb+p-w_5F!^1HuPlqGqS z!Fun|OVziurat3Z{8C8W*e$(5VIX;MysOSIAwjlzlPfoHRyzJr{L106@517_CL50zE(#3q zxXUAMaD1oal9FKYvRww#T(f!@AF8`Ytzh`PE4c3ZSqnv>=Z7mg4tJ+rkiTECW&PbO z_NKzaJ2+G8^}lk&8mMNd{Fb(CsATC+vfI4Lz?|busBx)r(2Rxa#2@c`QP|san)%;{ z#VeCe*L+!Mb29PY-ARY`q+Xx-q}T1{a!L92N{z?YR$s~MFt}QJOH**hZ6W6M6}ArZ z)Al#1arx>g-CA44wAm*?F7&9t3J&>j{k~=I587lroIUZ7O^~gyW~GwpKZa*^rn|N` zMH+9Mwdr8wku7Ys$}KYs8H~laZpZg0mf5mg^bTYBobp(A#uuJ53^CgT`X4eH-_@-b zc_z-Z?YjB3ik8PSCDIo6m#lEz^7;AB*&lDS8pvC0Pe1QC<7x5pa}QS@Q%{^H=Hc{g zQL=c}8uzWMbxzN6eUiLMx6sBu_F7i=xjhFq)vn6jtP?bI@v^V0Ev832Yux2oFtNN;U_4W|HC13w!)=vfMX?1DDfpHYHi=EEBnA`e%b@ zMmw`nXXY`9y194QH^qJONW#Ocq8Oz&SjSkP+|NT{F@ea!kBpjAPY`KPqQRR03uHdK?Y?CGNURGwgKV#9XJTr>t$Q8Z57RPkp)O6Z_-Ee>zf@ zo%wP)chR#<<9;4{Zzm8=l$t2&+@0rJlh{uWd1n%seF6orf<@pUR`JY?5(Ms zom4U*`dNK6!{?i^-}@iE`1G;3J@BZ3^h@Qd`QECtYMtMQ>oR?|@)x<9bIWaZ-@Frl zV`h9@@%G)?l8t+PohDxCm3j8x=|u4}=jWamo}60xS$oFq+Q&}IdoHvu-hIDpVSH`% zweu1G3}RR8R6F+6f2vQ4N*}|rNxLQg?^vVMFhS(m*XmZOAmv-PYA*N0N19HXs{0^o z^X9o?rfvd{7P>NtFuC6U{C%Fw-PA~xV!xc0;D9PKzlldY_pA2FXs9di+;-eP$kxt_ zvGn=u3-SipZ@Qiv>{u9ab}QQ=tt%Xivslk9`^dB2N78K8vNgHIwom7+UuRk~*{Etw z{IMRpLt^3muB@P!k51SH=2X3czUaXn;u&*lZ~^Hf%9&oWH7Y&QE_+_AY^O)D*o zznNAa>RwviymOrgpF{PMU#ZJ1?r9h~KZ%*}p=yS2$@$H8c{8=uT|`zLC^750EB5Tr z?hG!q#rqB(SFqfDG|hi{lS-u49l1$ULMC6VF}zo~#rD^|ph;ETCpCkkOZuM}fc+(3 z-Y%WJCaA>oRK%2w7Vh1`uI`#`@2eN?Rx31iyL(Nl^8K~d(grz7wMs1sCmzK<_A(OL zr@WonSTS2?xuu8vF3I4fL0cEBUK}kEDLO3;EA6|ZW=G|= zh-8~MP4v>0$T_Lhz3fux(ukLvmUcYy66x9@=n`}GkSnXJ%ki6?+y{@oNhw(PTrJaR z>$w*{g4gbAR+)U~d)z%~|NG_Y-@n{jemm;ynQya<{{F0g(i9N-Q^aX;pVS1)DLlH< zma<2!%yW8H)%}m3O3d>rg*57$bai*tlNtNZy*UB6dMdg>+u3mS-CUC=7t!a*28J3@lCM^z9D5sc z+IGnz!(|s2+-z9to>`^xOpN_JeCZ#-+V?t zfyuGDLX3^4@oRGBCz;hIFC@NkO*{T_i-K*i?3d#2#zygi*8k>J9#1sA{U-O=e$JjV z^#V1$DjVL|eg<xUoR#fw;6UH=(nToYYA>CC;H|EH$t&AIsJmONK)vd=%RZVS`RJ!ftoS!TxUq&$a@ zpFi+&c5KEK&la~S22LSAmz?kmHb`BkzWkrm6gI!9^RAx$e@-c^xVrfa@8j9m^=1BF zwl}*RxvO;Qnb^fTeYP`qO8#eA7d-8w`e7A=3sSD{XXoMZUZ4 zteMpNUwmfJcCBn-7G41>&VA2q%1%{t^yr*g_GEuqQvkDG!Yk>SY5N+FNUH6B^@hLs zz>yCPKCh$GE@&%#-XX^`${rCUsw6-vtzS}pK+yxa|!%hi3z4}S&pcGH*ou15afp(4pD-M-a zj(xoMmp$b?`DxYUB)&dLTdN;S4a}2g-%$CS?0?TYX5WWgw*Q&ZhU>fRxsKRnr(9$6 zeHbO`a^k66$f6j{&)GX;)(Nb(v*)W)HC--r=ECWptTWHA_}tMyMdWeX469>jewMGD zJagVu%2$}ox5T`#z1q0|n^&(Uw@ z8a=W;yZcyyglD9&X%kGeslRZ`F$?4AKJ2*AD$xp z$m7%Ml|knNRVAb6-aUNonY_n(hqaNdn-`|-eYbUDi&pwFm6zInrYv8qJYAPvxoD|> zp#0+LGgX%kOg-RUvikPTUAm>MUDuqaSrl}TSoc760biuHvH_I9q-u|k{KAX>BXJPq5j8} zd6&AMwqE8_W)iqp^=I|7HI`a?LZ(We>#$#YYV$Ic(iq9lZ;qax{VM-kTyXG3sU5Al zS7%)s)rJ@>@3_j2i;iht|rR-s^m*a&+Mb;D>|+To|&ij?4w3-_-2z68W{>9 zmRtDavUn1*AA1M|*t}in&>!y;v*d({@PuvN3d)SkUAyic`@zH}x!6-%TF0NS?}tN# zMQ7-GXXB8Xg<3BoKI<4{p8V91xB5zBM?8buL;cpBlHo`D*nD?{U%7I>(|CGBSyj{H z&;w0s)_wJAOedE9b8}#tmG`%C$%~#dyZOY<*|9G>dn4DtX#Ih*XLFCoyQHn%bbIE* zAWgStciAWY-1yi1rFq?V+uxlRR){>)-J-Ssv%emT{I=$Ky37B?P5E=}nDWfo8@V}F z`A)p>V%cxL@AF-r{o!tLo38w*&bjwq@X~)#XU_3vT%E#uIi6d0-4ElkODE*+Wl5Y$ z)8_MZdh=juN>Tr&;uZ5x<)r^>FPJ;2N14fEx%9ifRyU{Tda_Q+;p?v@Z>xB2GGFS* zv|#T?ww~LTaIp*P+&eN=;PD2()g_iw3m92dCwRPlA$LxKbMJ-udYLhNTNVh*hTW}* zC^)-x&t+kr8CR+num$SpJ1!GaGjnC{t#Vc4X`QJ$pV9MLf#jA4I98?m=_`D` zloRr@G=PJta>*Escs_w)8~Lndl?S%pUKo7UF!7^4^%E zH)whF`nf97VV5(sKK|Qr=INJ3M$*e>H=QcyEi&G3jLWAVKOUi zO`8D=^QE?R$|m1^>LwM=ayosPci~E>or)Z1FD|J$`_ekCtnr*${S-@qU#p(&7vhn4 z*t{>1qv!(nGDV-C$F%eETAr|WKbWYx*K^s)dCFfN>wev`;!L~xy#osh#l83ao+Oq3 z?#0ry^a~EAZ`Y(svKR%JS{bRN36oo*+ z%x6`G!q54%ChYM$89X7M!|}l?pM`Hrer-12`b%!s{4?uM?z*-1oZ`vTB2y==OFENr zXU3W1d(1X8$K@AJd>OL#?*-H6>la?1cS$!r;n8tF)vXc!M<(XS9Jgm_yVP(fZ{mcX z3cXpu5|f>Oao>L?WbVAW;Y{4pknoc(qTX@U#_O&MuLyj~HjUv(3fr>lf*0RyDERhm z;snWfV^6Q;f4QW}pL#dXIFqhdwqZU~>RG9o-cxlZ-dx=?TXf#`l#06=e>B#s@MziZ zXEQq7T+nf5t;6iYhoc)=IF_H>RIi*f3ds-FG$!4OwQ+8Eo=b`}4 z>cWYcRw4ZlUX-vHO=S{(pPsXN+7s(J(gI~}%O)vu&DT{9Ua8h~c+n*ZyWY-iRZQ#d zNv-`>Y^&V!pfRL!hR%!<<4r7|OI0?+3OwrBk=z`$r9Z~!vG=pI9O2F^z8x>yW;ZJr z1a4g^7cx`8*6qc~ie|&3d*@7f%C#^_c)G=+woJa91HLnk?VNMx^xAKmg>+a;4!>;t zGo>o=@YaH9h6=nFPkV+P)DHQ<yTPG@{#YAh}fe+O-F1H_z=+=4f&AXAwN$ey=vkHEr#sid{;|G8Z@Q?KWSw`0@Rz4z1i4 zj=BG@T({rhX>latOuOkSJ;{~nC$20`{wJptJ# z=J8#PPt-YhEdE9q9xHY2>MwcQ=iy}-FLH1lhiZ(YdS<6Vrd`wu7uAoK8IK8^JezSv z@YRXnw)F?j9tiNt(z~@N){}MbBwumm-cOp@3b!gJOk(q~vzFcHdUZ8ROO(`ClVcyO zlue#A#aV9IzQ{yAv4X!b`_9JO9sfixq}pt#4SZN7p~AH6;^w6XFNhXzY&zwBTEx~e zr>sQi%0i*S@~&rE?Ju8kEy}&!9K*i(yOqJw;3Z3YHp%Gr@07gl=9K2)@P4nQn(@Ay zG0~qCTz_qzv0*`>pSt5YBldZ}^YSJ{-rT{u?wiPI$L>|v?yi0&qiVY1nV6(X*vFMk z&08aawm7|hxh2wXmgN?S>)qQTa;LjkhueGZ>z?&_qR_IuXIATSBqc8NoQyfLqjGKY za*xRT3+@dq@ik#f#jbSkn|N1OzWu1t(*?{iQtQ+B&KwMqy44o7{@3*ydITuOPv&beIKQLaFb*2Gum6g z|KzzZpJnv30_H7WCj~JqO>peh>YK!{)pMKTiI8_oB-nqfxNtJaPMiIypIWtr?)hrd zQdY(%#d*gBZKC|n2e03^$BSWItLhCC_k)E+G1bDVRerwdopWQZUoO16!tke3_v2D? z<&Yx(%u2blyuHfi&e1NLXA0jwtYxzzyk(J^+VPJqR~(kcM{d}|v^sNBsY(i)oOju? zc*n=B+rr`}MmEnju;{+qti+L6K_N- zQgS`-l}(t!!P;QB;Ew3e5Y6qLX}Z(ZjUL;c6#N(ET(@q)^j$^9X?oLld`b6SIInHb z;{5%OlA`TT>~)gl*j3PF;*%W3e_~DPNn^38GtMxp{@CGa!#>m7@}~LDD-~P(()I}~ zljXj+@{#hS$MX+wYt&%6x=Oc5=VeyOXukYPrdrH`K8GbcfL~_XQ}M+G5?%CUvz5K z&mA9w)aJ^m?n>@)*=;&^3nQC}vNyB8t(JbOFaN5AeX>#?INq+9c14bDin6)$>kAo2 z3axzOIZZsSH5PF_`t7~GjK`?nfio$Cm;LySBK}Kxtko8!Z4NuslsUJ+luL(w*+sHb~Lv5_;wpRl^zN{1aM9xzZmxL2rh;!Ekw5xu%AZ3Ip7^t# zwb*!F*V{=y-|%z3dhTTXwccThRoaAf>(AdN*5qc*pL8I=_J{hp(Am4>0xoRd{QSfn z9~Eau)r#*yvi--8?_I}p?r}lPm+Nu`KR25NOgdZ~WdE|qgt9@hcWjm(ywYnL^_5@s6@>2I%T8{K=L5DYI{9A$oChXjDVnLhmy_(u>+ow#f z3GrU_e#@HRki`!JwraA-T(T(Y-WTHCoq2rYTrJh(FSc(GUc~6(u$PHZy=rR7_IY-m zlh!NfbJxzi?dklUpMiJq|<(j8Fr#mj6r~TM3RPK7js>ZjrZAy_xk~ zWQN@JzMrf=USAcR*ZidM`zu|o`eh&f9C|C~(ZB!S&RB)QiOaV)c^sZm^;M?x`}7sn z%RVhEP`Y)rs)=V|Afwab#%PTzNvF(Mr0%X-7;wtaJkt28@6DnpF}62)KYtoXOt22E zl-v8JDK59#bn5%KYS~GF^UkZSe7MT!eB`-~_dyp|U%zAXHFi#krkU@IN4m1BHW#=* zuh#w5mHK4oyy%4r=Pz;|%~gxgscH%42;^r%(Vx_PT*H>()jc6UlUlssLv zu`@($p_#Hy7UxNUw{B@-R;-t5Zhc;U@mRi;+sCgr&K{V%<5q~q?T)Qwx|h-#F0>_2 zd)1dH@oL%Z!jx%WOoJn2R(;guJFoFrt=&g|;%vjKv)djg*-x)Od)8oc;Ck_?1%8j0 zT@PG%B;x0lw#I-jZLIraR6&Blp3oUJ~$CKw9e?x;52zSk}7(a(qp^}S~{FTcHX z)~w#D+zFDwoj#N6q~{-evxN2fBGH|aDPA>iHZ$+OmVT?}?PDv;(-r+6HD30fNZ+^P zR!DEk%zG-#|1B=h;x!JjOz8{W>U+G$^0dqoxlP&Y`lXgTf0Aui>Eo#iUDoXL%t7y>J_mGQA^lCSpUZH2E{u3g)8a@FIBpSCnt>;Cwb$H*KcJ6S8E zccNU-&Nk<%;empaQx*!UsoX!~Upplx)KbQ9wrkqWgFP3Gv_xi?@omVwo?)h#CLvY) zU^%yzzVu8r3E6!=nx@U^y3?~UAX1c#$;5f)&ijT&@uE5zn@S(dU&t zpWCywi@yhLyp{IwO}(nb%=H{W%|^M$_6zr%d7W^pN0v?bv;KjQ;@#a3W~-fNwdR;~ zOD*4ci&s}e01LD7=RSoCX%jARJXhzNe|L@9(O16>&6C3&W`3UEbV0-Ol55JgGxsjr zt@52IyL<5xi5utk2zwm5`Tec^*Ni`{*F1OjWCh<5fBK1YdQw8lJ2>p7z+G4nrjLQ3C(J3V*Vl|OUkq~ELjvo%F8 zG>E6?%x!n4XUD(EAJwnG(+$7GJVMy&SP)ufl%q$5(w^XWdz?U~#AUr#YmJ~O*f z;X$wkyOZ+5;^}+~C$0{Ey>q zGEB~{F*E3S=((!B`fSaW&ehK^ZWNmNtSxcJ+mP#qv)0f2!^C@bZklni@wWb!Ga(C2 z!_M}qcH6LddvSfsVpcR~5Z>!_&f=e_QF(OWTd7mKu1z@hexa3Tq^q0AI(3$-o?W_Y z_qA86zfR%v(YmT3DHgAPcarJi`Jc3v#2oj&YBNMbz+`rTT{l0m2y6w-*zc8*LlzOXgzHVoDp81rGg{)b9aYg#erxZAbR#sc2Uf1r*Sjef%#d_t7>r|nX$&U+*m+w4N_DuWneKC`t z+zFm{m;dM1UoAOveb;}5nWfDCzSlFHIlDvaUvmoIhi|gh{n0l;U8wMrHOG6c`)^Ck zT;CC^@c9S-m4Ll}kL~Bazpv)E>azWl&YU@W!)l$oq_M}Gk4N@;zJ2p?dE%sNy-X_t zQfGuGJ&!D0eCx`cm)f`Q&b+_lU+R~`v+w6h+^_t)Znxd8xjtWv|NfBv@$r}X^oaet z{@L7~xxLpVyW_~aYK!~GfHn$Bm_CT7V9x7t+=4H zPjeaf<*>}ASdOGEW=o^ww@UE1c&+W)yrLr^WQ9dgPmsGgt7Bq@bVfMm%9|Z6e8!<4 zLSH!jpMAzhDA${nckQ|L_f(4C%`N%(wPMG2ga6xREj#u#W6cWAUp~Q`yw>M_E#Gsi z*w({Bd1myte`kLkig&L5d)$kycuLdpC8d96NapFrOpZ9lvGEYIf$jDgjpCbYu4hX1 z#%)N@+u0>=+F*CVm+egW^(#eN3uIR2zH3?Dl)2(@vwiBj8Trwx%a1%|ey2E{+fQKa zx>*yli`(^Idb7Y89G>{#DkXi7U3|tNHETEf1@^w*RpT4T@Yy+X zWkgo$vrDUfC>m5xn>lmm8NPmlDE9ewZXLi`KrSq>_z2vV zmsyTaNZPK+wetCgS+n-?n!RF4I>2*zHs6moBCF-!dfZ;V->Ah>{<>SJQNcNlko--y zAAMw{pIY4JW%p#ek+^x6?1B0>^7{qOo-Sl8J8-P>21z79V4*V`+H|G2G> zfb&eNJMC>gGmdKUNttY_j&I^vyk(j|eRxv!EO+KYtJy1Ba^2aUDMXz0E zs7##6IyK{8%Z4zeq%O^dNDs@dglh~5U*5(Td|&!OE%nfxq(zKjF?xYB`c(oN_Y3^h zGWw{J;5Wf(#>P{P6Eh=|rb?=cC$yavsaf_RD8DNG{E1I>=YQ2jr-vK=@v_|_S5UU@ z_65O0tNuK9p0c%5uYd1f^ZH&bPuOz5Gh5@I&vDOw!+Y+pf$PzlTNf+Ewk<0t;j+x# zkiTfR)MJy&{k_k(yC;N}y|0k`y=%^MW}(Z$XUmHV_fFZs>h#^}-ch~sPpj`AWh~!0 zafaZVXFr!ezSMr#CjR)PP}Yq;miH|*duoF(Z`<%J|K9zZ=hDg^ep72<7L=~{72T|u zxk@WZn_pmU*ZK1aZL5F2y83+4wr}b4<<#D-dosJ+)`#<|O?~j(b(;!n&iq;TMDO2| zluf_ml&YS0O`YkjcVJHsSAOy1H`g+!PW>`}?G+Gj#p{|xMlruezkNB-HApf~qf z+t2vdzh<_tF-rcJZ8vjf#3rN9NdgIW8(w-|Td=$?^dHNHH7k{N$Ch2(p7`#J&bES> z8K!)Xl->%r_=LZe`yqa;+Ap&2+Nqz(xTIL= zTR%@B;8@d5En}~>N!v9K#H_#V@aAp*8~5qYuC^K8K2ar`rq)%=vtd@`$^0JSSV0F{>h!WsrPp#PgTTXt92_@uq{1wtZS-al840910Rz2Sj+1-MgHkB4=#OC zzdHBGoI9)jdxXslOcFiZbEjuk<+Zy#yUo>aoNn%0a%NIvf#I1)d{aBJg^$ks`A^)$ z^vH}etJCj3o}}ij^7)#UvCfSD%NRb-3|;-g?$}KAuhE5xeP?=(E&Svnlsiq`SApH4 zFFRzWk7>AEu}|gBt1;G+>&|WS_bV@!$$GQ0;Y-bhiLs`cQzgaDY(9M}J#NFMQ$6>m zl``!JFr9y9&!J25SNXr4)7z4%(e*f-Wo75aNdX)6FE;Qi6$Pt0UUQo3vn3&OfuQKi zh^4Ei8f|6Wcm(z zYwIJoy0-k0FS~tr_Uz)i@B3$OR!g=wG5)$TOnchxU%6Kk)1rH?^`FUE&A4cb(P6XC zHJi@mOp>lgtcrlBzflCa1cJ#>9;&Dt*qqZ4R^_n+r{(i(}MG6 z&78P=`;?YtTXt8o-OTbh>(l+(St|9YiE)75GuD=()yv-W?sQCbyLu*R`QJ>pV3)Eq z`;}9_&Yii<{%ppzb8A|@u{eEUn%JMiaU(6S>%f`c;@Sbs@$VSux%TF$N;EnoW2@VxvRIQ>EbgF)iwr5EZ`(ps*RI6mgKE@z3x|c z^yU=@m0o5RZS~P5XQuu7A~WN&?IHOolK<{Laa2CKzk2(ggn8_} ziyq&e-zQthTP#z)NNgMX_m``aRz@V-?CqAc50sYNd@{T2YWL49{#DNFzB(N~YqKJq z*)l~j_p$mOJz0ybSyQi@Y~C^N{$Xa4wm{OazR{;PTJ%w-Sx7F>%+`&M#yZiQXb zyOO1P%XQP7pBp{23z6Wt_&_J@Nu}h(WBa%FhgRg~2UgfAZS4GPTjS7RzU9Q}Dfg!C zKInY9!)W${))n@1pD+Aj&{s53FN~+7hGVAJhg%H|9I>}{GcTJtwc&t+yrq_sbfUy1 zb(4N0)k7goW&uu}0!t56%uqP!&Y~L^WxYR@sja7Zz2HTk{Ig1zZ6kB?SB8ee*t&w-`zoCPunN|IcuX; z^Woy*%V||2CU;Lt#R)$6kumGJCzs!Yw196p9|fmKrFM#5F0}QG;1M#|lEZYPBD>-s z!`$f$0{11)x+ywwkyxtj=~dHDW_(_8i*+*3sSPfAacTi`1QxL!@MJW*wN?BH z>-kJ4-aaxtrQ|O?g|Wd&WAeu>u936e-{c9ndM2af_6_3&pYxtZl)9h!qP5|oh}twa z_v(N`fya9KQbmuiRo7k&`t?93w?{-u9{mO^)(xsTxtBMx3cES?B>N$dgpd39+_rx zZ1(0u7IU=qW*)v>aD3(ASH&G^4sO9Jwx`d$&3j|l#aa_Y@WP zdcQn&;i**n9=@5MfQ*B0#&zoRUjy>9vP**8nL zf_@(^WE8z*u*f^f)H>kcznxc`z0?K`W4kWTgE&f zu;0Jv&ZCM%r)#HsQr~kv6FKhdbndaThj!quhFKS$miRy?$vonLos3 zz6}!j6Hr;`+otzAN&4BgZyZ_C@>=qRxi4318cY0;{Pt$jjCTg+GfU>S8)VHXkWzEW zdL^OtJ>nThaeJTFt9F5+y?)!)d{h!TyeYb$wPl^0;Dvb(i8->{D=($bl)QIlk$AI_ z)xSvZ{0&)Y>`wv|w~DjA*Yiw@R^|G7K&GPlrms=rm#iL@{49~UO-tjrI+vt{{h8}G z+33WAH;WrKz2AMv)plQ>bis?4si7Rqr+DUyC+)I4A(Ljm$ldgzL15F&WDj4Ehc2cc zaWWB`a;J|~<3^Zf%;!mZ#>xw7oC1O?O|BgFQO!QhkFRBh~K-G&gWm4SkSfa8S5mu zZD-CL?FjC<_4-iDk|pUT))~TTs!o+H3)U8=&kJwmUwCIhc<$$mTO_pR2rx{{OjC2Z z{P?mIhpLNf`=^krXJQL(dWJG=_BJ=3J;BF#{}O@AVU>oBtJ3Pe-dk95ob|^1gtJ$4 z#ZJNHkx9l&3TmNm$TP4{)Me- zCaM~_nc3beHnvV`*`lDxYq)i(_qHwENelmrD;x<{G$0!LB2xaAl}Sz1*u^ z`#9>-^VEEA_eQV%x}AMa;j=S)zt`OV`|VueJHzVBmuEUld{a((m!opj$XO-oaK?j1 z(-bL5q0NF;?mkn#>i%)G*7E3Dh9w^Yv-D4w-wr|XAz;YWG`8y6}(lRI~J zr)>PD?{zbuNO~NI`CZa$ukx&Ks>Fl9!hP~RvVz5#pZ|QBvGmf!cJpV#8v`_w(oT4u zIbyW^lCoUK&pPWLJOAZ1UA~);^lqzWlAmJF^mYAzPiQ8&&Gzjrv(>7Sl6i1?PT_;4 zVLH!#{JrhgV=8ONufFxxy<^Hra_`iR%57M)SFq}V`i2;8!_~c)3k-wO4m9oT+!V}g z#D45k$rXWr9%naNs#nZ&ns;bWW+Ya9OUrs%3Q8a#8WqtH~sL2J}yjss9HTg4Fd_4^Vr&h}A9qwBl zFV#_$JbO~HQr2bO_?&`1 z;b!swcWJoF@f!(8>|*7+;w#o4EIleGSGHF-H+Yfg6_FWHlD!^=b?=pwSWed-682X} zSDW@eHX~(@cJ>Xn(}isL$JBk_E#oz^5q0+SHfpLbSo$|pGcEN5ukF(@ab5y^!|w58pj~4$C#sk&YSNiOX0NkC~^x>_}DBE-98RSs#7nGADn`DK5h` zN9z=yosZnPYR!cchSTM24=w%7-M307=4arA+-qWDMQwHmmmO}N-lEng>9+IA^2}p< zC7hNXTh!FkD=LM{K2VvVC zKFsJ(lvu>~agV#eo4Ul9_tTkOw>LQm&GhSFUG_le*iXJL0qxJhMyGq;RCinYe7tIL zM5;@`v9ZDCbQSB*t7|4aw)$gqnrG)Ur6mSg2aM7{9j)1RZR4XO=@UQS>akCHzE$#nigoS$ta@2GS5)9qTN#1GGZT$0dYw#d0VE%Mkp zk+ur+ph;dub6fY$kYOs$n+euW z7W*~`OB`m1-gi>`?p*x|+kA}7jtSQoF6W)KNc+~3L~HBgZ{0k+w@Th^D>&D-Kljvv zKSg#C_oA~mH9mbg?|y=0Y_mZYf6U0h;IG(p=f=&4 zy*7$eZ!}%3_iwS)A+@jf_RnryKR>iJ-egz3K}YHJqJ{6gQtdt&u8i6>#q-mh$&*@? zw<|4u=DforGP6FxzG?QZHB*E&mP6}m=}D)W7gvLzj{<| zzHEG-y|mD9&cvWDgKFcQJyTNrGcxLbob6HZkaQ7th+X#NL1E6@&t>YB` zA*H$Wn&_R{tGSb|oR}FNbU$@Tt|aqT(N#;AnCdLexOs4b{2iAC9RlH7gR&w7iz^f~ zJhSpF1Gy(CI63jpd-$u4%`+~_UAg4*&Fw})&u-71xauu?>Qv!OPMz?ZA#Lh8QAv@4 zn}1IYzjyFZ%F3MjT|sN7>5j~zfr9(43id8oEC`X)ARu30E zeX?hXUDy*&zLmM*=;=S=A7o0g&XGN?rl2QaEJZLF#`*h(+ax} zY}&s|SJ_g5J!{Rx$YnEDb*7q2uhLRZy%ct5igN74hbNb59DTH!)kBS4CNt@%Q=rF$ zynVmJbRTSV@V=fV!B?04?rCdS)Y7~eY0g}{*4&dt-{;ol?F`W6Y1{F#E^)EVk)7ES z(=Mc_waDCmIDg5cV^6u)bFO{4a7XxzH-dK$`-gM)7Vs{AIBT~8$6LlJA1hW*-`2mU zb4Bz%v!S=G(8LViX+*VU;~$u+Mht|-Vfv5>6EFZQ@@enDAD zde!H|*9VM~y*T;oY7A9Nz7^DZA3D?GRDAaJ#E@sp)$ZOoVjOo+Y`+47^YJ^@^S5qg zarquTB`w4Z?H#4 z3bn;cG_siQHt;%|5OreVvk%O-dbV%buh!$%CUCZ(M5F)Ci5Q-Fm9D7^2KU+k+dw6YeQ@~2M?@tpdC!DoZyJmi*^u%VJS;lHk@5-8bDDRmHhGh<%=Una<067x#s%n zBTk`R-y7xS|Gs#AE01sXpZm_49>yAxZ8Hqzb)tJF&oEyX=v=pV%^6n4#TqLDc2#d( z$hpd~bmsJYISZf77cT{UW6C<;dpXW#|DNcuFu5Epm7Eo9bN}Qm+OsA{@mTC%qXWrr zp2#g~eIcL-K|*R_k^V=(>6 z#IzaWD+`m(EVrMMrobR`IqZRn-u3Bw3!WE?q{(<27d%5+pw4&%KzCD^u6_0 z-I5ATan*VKrD~(Wm0Qg6wSS*(5804ZlR0Nq&;?V2)u~EOJzha?d^*&pJ&!qHb!5Wf zfD)z(zM!+;)|%wU?5R_!U$0%fR_K=LhMMecd)Cw}3~Zd>mU#5Q_voh!>^f`zF7aU1 z;1@WZlQfmfsO?Xr(ks8>v^^GQcNF$MxAW@?j}K~odP|>y_fy3FZ91F(2h0XgEGclequR1Vk~?ebqKq%av!jo3 zoqXl}&A|Mbca`gz7inug8!l(-4pvs17Pj)`jeGt4;@vlIJbz%g^x2x)qut;0)-aot z*Ayu{%eLWanUQC`tXRe%!m@jEm)}dZi#k%zm3GZkiLvBA#=b|%aCfVsOylKdt=T`8 z>7>QZ-|KPa$FT!lOtyX=7w(t1oC%#SwRLaQuUO?{^_)9Nt;tUM%6mOKI((nJ$;_y{#cOVSnUlS+@M1~)(U8TJ$z@kXME}11`hDi2Inw?! zn9g>epCNaX_oG})X}Kkn}q7?Lt>eEB3kTNycV9v1OJxoi@*<#n$78 z@A<3xPd+96TX-nt)%K&W)8;$Ad>3b(xWLJ~%297t+WeiDUbx-@3+oq+W6sxQ$pUiWqa4RGU?Vlnh|^8dQaMw zng_*h`Wyd9+n;C6+IO?6+Thb)hC>_+b7%bvYo{&u-tsUs>Svc<)h>5+ zKX!3_`K=C(&wn;~yXwVsXvG|j&03f6hO@-OeV0?T>ltMe4k>w_CT0JNFFya3dU@j5 zA=d5*#}3W>y6;A4hR!M5lX5@5o-+uD=JIL`zcS-%cFT2-^lvhEgI6TYz0k3U?+3%9 z1F1{i>1*h$mN>oPlFsTcRcjAzdZlq%tBvt&=_lK}jwX8^C4E?-ZM$fr4-4Ps9?L1! zi=KBg)tar^;1jE%^ZNZcqumTsb)0G+s=91mzF|#x#I@;3k)=JUd~uHiYYh}-QfH>e zxwZeBznNLWEvk&^wQTR4D(waNhnD}m+xyRQw%YQItEPN)d1~E#aLLyx&Og;Jc}(+9 z`G5WX*#pwMes4)yxA45+{?q@Alk64-o_(Gf$=CcexZ`Kew#}|*>(5`Awg2KfrDydL zr?bAD*Lpp=enFp_<3t3 z`!BWH=)d)wgx8*Vd@^N$w{4}Rig~5-4`~r!y_Qe^)pqJlzi+-s&j0HE&=3Dkt^3)$ zjn}2H!ocR$rL&WlYcF-?Y~Ma9RP7-9+i3?&1Q&Ib2)IsoYSFboLTl0iR_VtLWxAhU zWd$w}*~QB0yqT+1wbH894zdi5$S{u1ZDGq=3?3lk!{F#x_ z>6H7M6x7Z+J)4|=qQ+BYqZpP-D6}`9Z_5!AdrW&Oa*0>#QI2>xUkRd;2a^W z?rLis!%oZG68kdsOw%pPRQ`nQ3yZ#mWa&@b#JO25bk7pEx9#4?+L^hpAI>&9-SB9J zVzh_l(Y3N(6N?sI6weFQoGxYjtA&HxkiTumDVK@2Z2Z@rG5cNW{;k#I(#a){PqZmF zf1GsYw%(d4k|}B*l#~1JJlrJhd++*=nkRldfuUzokM+!$V5zU+T(sy)_3WtGyF}-^ z8;L!W3(B(&a(21w0Qj}?W_~hiCRZ~u%xZ}LTk?TX-Qp=UX zE>m8}6+Pd0%Wzq)?B?n@dcBeomHq3dNNzr$^I?{aN<{Zr)y!8V5us;PQ{KI0{=({% zdgzR1@zs_>&N(>=kN#~*R9+dLxXUI@r(Qp4YI2?)^k2QVKgEA&54VuDW-g`Rm$sI&b&JCPZfZaA zT->zXHth7ChqFIK_DbeGh&x&HWW~1$S8Zmz3=>e?5#Ci45j|<=%c&D0rDPJS#hLiu zt+uz8gw#sodi$3`Mtus)dU^tn$vO$d_;4)z z%%s(H{OJq>vofx|w{oy+XS`kBH;d#1#?{fTwh`#0uUUftX`3#4Xv zpQu@(QJnI^CVgAF#;M?&wZ0wMX&xMsUb^<}K7rrXuAX=^)VtSENVKXvbmP=5k#jrC z*}VO&?WVu|(=p*wgzV{ik9>C3>3zN^vuc8TZN?;%y<7Lk|G6zcOC;93I`Zm4h4b;% z89^?qf1lV{e&pJluxIn9-mG|4d^Pj+H{GZ4S7yFn(=lb!j~!=uHwQi2y?si(Rsa8) z;SSf;{~wGlj=#M#S-2rlfuref`CAWmK3R!9Y0KK4?sQn8`JLqp`;nUO7v*~eJ_{$E z6aG9yvNTC<`cA(y?K3_fu}O2AJL7ojI^oZX&uk3)X9lW2tNdsbuNf}P@hU$qhk=2C N!PC{xWt~$(69CCM0uTTI diff --git a/doc/qtcreator/src/editors/creator-diff-editor.qdoc b/doc/qtcreator/src/editors/creator-diff-editor.qdoc index a49d1028448..11608e0ce53 100644 --- a/doc/qtcreator/src/editors/creator-diff-editor.qdoc +++ b/doc/qtcreator/src/editors/creator-diff-editor.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -80,11 +80,11 @@ \image creator-diff-editor.png "Diff editor output in the Edit mode" - The changes are displayed in the \uicontrol Edit mode. Color coding is used - to mark changed lines. By default, light red indicates lines that contain - removed text (painted a darker red) in the left pane and light green - indicates lines that contain added text (painted a darker green) in the - right pane. + The changes are displayed in the \uicontrol Edit mode. Color coding is + used to mark changed lines. By default, red indicates lines that contain + removed text (painted another shade of red) in the left pane and green + indicates lines that contain added text (painted another shade of green) + in the right pane. To revert the changes, right-click added text and then select \uicontrol {Revert Chunk} in the context menu. To apply the changes, select diff --git a/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc b/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc index 852eebdbf58..9c253adcda8 100644 --- a/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc +++ b/doc/qtcreator/src/vcs/creator-only/creator-vcs.qdoc @@ -151,7 +151,8 @@ instead, select the \uicontrol {Switch to Text Diff Editor} (1) option from the toolbar. In the inline diff view, you can use context menu commands to apply, revert, stage, and - unstage hunks, as well as send them to a code pasting service. + unstage chunks or selected lines, as well as send chunks to a code pasting + service. \section2 Viewing Versioning History and Change Details diff --git a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc index ca1512bb9eb..5d87adabedb 100644 --- a/doc/qtcreator/src/vcs/creator-vcs-git.qdoc +++ b/doc/qtcreator/src/vcs/creator-vcs-git.qdoc @@ -89,7 +89,8 @@ by default. To use the unified diff view instead, select the \uicontrol {Switch to Unified Diff Editor} (1) option from the toolbar. In both views, you can use context menu commands to apply, revert, stage, - and unstage hunks, as well as send them to a code pasting service. + and unstage chunks or selected lines, as well as send chunks to a code + pasting service. \section2 Viewing Git Log @@ -186,11 +187,18 @@ When you have finished filling out the commit page information, click on \uicontrol Commit to start committing. - The \uicontrol {Diff Selected Files} button brings up a diff view of the - files selected in the file list. Since the commit page is just another - editor, you can go back to it by closing the diff view. You can also switch - to an open diff view by selecting it in the \uicontrol {Open Documents} view - in the sidebar. + The \uicontrol {Diff Selected Files} button opens a \l{Viewing Git Diff} + {diff view} of the files selected in the file list. Select + \uicontrol {Stage Chunk} in the context menu to stage a chunk or + \uicontrol {Stage Selection} to stage the selected lines. + + To unstage chunks or selected lines, select \uicontrol {Unstage Chunk} or + \uicontrol {Unstage Selection} in the context menu. To revert the changes + in a chunk, select \uicontrol {Revert Chunk}. + + The commit page is just another editor, and therefore you return to it when + you close the diff view. You can also switch to an open diff view by + selecting it in the \uicontrol {Open Documents} view in the sidebar. \section2 Amending Commits From 07cbc49d33bdb2308639972013d358d0c112e5a5 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Tue, 3 Mar 2020 12:30:28 +0100 Subject: [PATCH 60/96] Allow blocking auto files refresh While importing assets, qml files are generated under the import path and this triggers files update every time a file is added. This results into high CPU usage. Task-number: QDS-1675 Change-Id: Ia0775ef78bbffedfaf2c140365ee31718e7ee3a4 Reviewed-by: Tim Jenssen --- src/plugins/qmlprojectmanager/qmlproject.cpp | 9 +++++++++ src/plugins/qmlprojectmanager/qmlproject.h | 21 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index fc622179cae..fe7542e8cbe 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -57,11 +57,16 @@ #include #include #include +#include using namespace Core; using namespace ProjectExplorer; using namespace QmlProjectManager::Internal; +namespace { +Q_LOGGING_CATEGORY(infoLogger, "QmlProjectManager.QmlBuildSystem", QtInfoMsg) +} + namespace QmlProjectManager { QmlProject::QmlProject(const Utils::FilePath &fileName) @@ -276,6 +281,10 @@ QStringList QmlBuildSystem::makeAbsolute(const Utils::FilePath &path, const QStr void QmlBuildSystem::refreshFiles(const QSet &/*added*/, const QSet &removed) { + if (m_blockFilesUpdate) { + qCDebug(infoLogger) << "Auto files refresh blocked."; + return; + } refresh(Files); if (!removed.isEmpty()) { if (auto modelManager = QmlJS::ModelManagerInterface::instance()) diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index 0cff1528984..acd8bc1094e 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -104,6 +104,27 @@ public: QPointer m_projectItem; Utils::FilePath m_canonicalProjectDir; + +private: + bool m_blockFilesUpdate = false; + friend class FilesUpdateBlocker; +}; + +class FilesUpdateBlocker { +public: + FilesUpdateBlocker(QmlBuildSystem* bs): m_bs(bs) { + if (m_bs) + m_bs->m_blockFilesUpdate = true; + } + + ~FilesUpdateBlocker() { + if (m_bs) { + m_bs->m_blockFilesUpdate = false; + m_bs->refresh(QmlBuildSystem::Everything); + } + } +private: + QPointer m_bs; }; class QMLPROJECTMANAGER_EXPORT QmlProject : public ProjectExplorer::Project From fc3f5033e2c1bb393b5579dc424b1372e7392103 Mon Sep 17 00:00:00 2001 From: Assam Boudjelthia Date: Tue, 3 Mar 2020 14:34:08 +0200 Subject: [PATCH 61/96] Android: fix minor syntax issues This fixes minor things missed in previous commit b081d7dc8f60d921d581112aaf67adb85ab3a345. Change-Id: I47c0703a81726d7c0c2bf01d844e39096424ea5e Reviewed-by: Alessandro Portale --- src/plugins/android/androidmanifesteditorwidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/android/androidmanifesteditorwidget.cpp b/src/plugins/android/androidmanifesteditorwidget.cpp index ca14e5453c6..2eee4515e07 100644 --- a/src/plugins/android/androidmanifesteditorwidget.cpp +++ b/src/plugins/android/androidmanifesteditorwidget.cpp @@ -242,13 +242,13 @@ void AndroidManifestEditorWidget::initializePage() m_styleExtractMethod = new QComboBox(applicationGroupBox); formLayout->addRow(tr("Style extraction:"), m_styleExtractMethod); - QList styleMethodsMap = { + const QList styleMethodsMap = { {"default", "In most cases this will be the same as \"full\", but it can also be something else if needed, e.g. for compatibility reasons."}, {"full", "Useful for Qt Widgets & Qt Quick Controls 1 apps."}, {"minimal", "Useful for Qt Quick Controls 2 apps, it is much faster than \"full\"."}, {"none", "Useful for apps that don't use Qt Widgets, Qt Quick Controls 1 or Qt Quick Controls 2."}}; for (int i = 0; i addItem(styleMethodsMap.at(i).at(0)); + m_styleExtractMethod->addItem(styleMethodsMap.at(i).first()); m_styleExtractMethod->setItemData(i, styleMethodsMap.at(i).at(1), Qt::ToolTipRole); } From f33d56a53d14730fddf0d705dbc83dee6f266d41 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 3 Mar 2020 06:42:24 +0100 Subject: [PATCH 62/96] LanguageClient: Fix build with namespaced Qt Change-Id: Id3daafa070aa2159f02cdac2cc8ed4348183b9aa Reviewed-by: David Schulz --- src/plugins/languageclient/lsplogger.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/languageclient/lsplogger.h b/src/plugins/languageclient/lsplogger.h index c07a161737d..0cb85967c48 100644 --- a/src/plugins/languageclient/lsplogger.h +++ b/src/plugins/languageclient/lsplogger.h @@ -31,8 +31,6 @@ #include -class QWidget; - namespace LanguageClient { struct LspLogMessage From 79efcb76f618a0a6cebaf63228c0f4370782c0d2 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 2 Mar 2020 10:21:25 +0100 Subject: [PATCH 63/96] ADS: No more structs in DockWidget We do not use struct in QtCreator. Change-Id: I97988dfc5d549d89fe78bfd710b922c11d6fb8fe Reviewed-by: Tim Jenssen --- src/libs/advanceddockingsystem/dockareawidget.h | 2 +- src/libs/advanceddockingsystem/dockwidget.cpp | 6 +++--- src/libs/advanceddockingsystem/dockwidget.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libs/advanceddockingsystem/dockareawidget.h b/src/libs/advanceddockingsystem/dockareawidget.h index fab47e94769..4653f144672 100644 --- a/src/libs/advanceddockingsystem/dockareawidget.h +++ b/src/libs/advanceddockingsystem/dockareawidget.h @@ -67,7 +67,7 @@ private: friend class DockContainerWidget; friend class DockContainerWidgetPrivate; friend class DockWidgetTab; - friend struct DockWidgetPrivate; + friend class DockWidgetPrivate; friend class DockWidget; friend struct DockManagerPrivate; friend class DockManager; diff --git a/src/libs/advanceddockingsystem/dockwidget.cpp b/src/libs/advanceddockingsystem/dockwidget.cpp index 5b4ff87265d..900a74bc266 100644 --- a/src/libs/advanceddockingsystem/dockwidget.cpp +++ b/src/libs/advanceddockingsystem/dockwidget.cpp @@ -63,8 +63,9 @@ namespace ADS /** * Private data class of DockWidget class (pimpl) */ - struct DockWidgetPrivate + class DockWidgetPrivate { + public: DockWidget *q = nullptr; QBoxLayout *m_layout = nullptr; QWidget *m_widget = nullptr; @@ -114,8 +115,7 @@ namespace ADS * Setup the main scroll area */ void setupScrollArea(); - }; - // struct DockWidgetPrivate + }; // class DockWidgetPrivate DockWidgetPrivate::DockWidgetPrivate(DockWidget *parent) : q(parent) diff --git a/src/libs/advanceddockingsystem/dockwidget.h b/src/libs/advanceddockingsystem/dockwidget.h index 56fbe4431f0..a55b8ee0ded 100644 --- a/src/libs/advanceddockingsystem/dockwidget.h +++ b/src/libs/advanceddockingsystem/dockwidget.h @@ -46,7 +46,7 @@ QT_END_NAMESPACE namespace ADS { -struct DockWidgetPrivate; +class DockWidgetPrivate; class DockWidgetTab; class DockManager; class DockContainerWidget; @@ -63,7 +63,7 @@ class ADS_EXPORT DockWidget : public QFrame Q_OBJECT private: DockWidgetPrivate *d; ///< private data (pimpl) - friend struct DockWidgetPrivate; + friend class DockWidgetPrivate; /** * Adjusts the toolbar icon sizes according to the floating state From 3efa2a6af0969730034a631ad9f4f0fc39bef85b Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 2 Mar 2020 10:25:30 +0100 Subject: [PATCH 64/96] ADS: Prevent nullptr access in DockWidget Change-Id: I071fd6a86d8e6951305d4e2d82d2025afafd4fc6 Reviewed-by: Tim Jenssen --- src/libs/advanceddockingsystem/dockwidget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/advanceddockingsystem/dockwidget.cpp b/src/libs/advanceddockingsystem/dockwidget.cpp index 900a74bc266..72a59c5b1f4 100644 --- a/src/libs/advanceddockingsystem/dockwidget.cpp +++ b/src/libs/advanceddockingsystem/dockwidget.cpp @@ -364,7 +364,9 @@ namespace ADS ? dockContainerWidget->topLevelDockWidget() : nullptr; DockWidget::emitTopLevelEventForWidget(topLevelDockWidgetAfter, true); - FloatingDockContainer *floatingContainer = dockContainerWidget->floatingWidget(); + FloatingDockContainer *floatingContainer = dockContainerWidget + ? dockContainerWidget->floatingWidget() + : nullptr; if (floatingContainer) floatingContainer->updateWindowTitle(); From 45d42d45188e504a4ba23d697d944874d3729fd4 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 3 Mar 2020 13:35:52 +0100 Subject: [PATCH 65/96] CompilationDbManager: Do not create an extra target The hidden extra target creates all kinds of inconsistencies, e.g. between mini project target selector and target model. Besides, there is no reason why this project manager should behave differently from the others in this respect. Fixes: QTCREATORBUG-23518 Change-Id: I11022f63bed33191f6349681356b4dd9537de50c Reviewed-by: hjk --- .../compilationdatabaseproject.cpp | 7 ------- .../compilationdatabaseproject.h | 7 ------- 2 files changed, 14 deletions(-) diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index 1f60fd0fe36..c373e5d58a6 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -38,12 +38,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include @@ -439,12 +437,7 @@ CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FilePath &pr setId(Constants::COMPILATIONDATABASEPROJECT_ID); setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); setDisplayName(projectDirectory().fileName()); - setBuildSystemCreator([](Target *t) { return new CompilationDatabaseBuildSystem(t); }); - - m_kit.reset(KitManager::defaultKit()->clone()); - addTargetForKit(m_kit.get()); - setExtraProjectFiles( {projectFile.stringAppended(Constants::COMPILATIONDATABASEPROJECT_FILES_SUFFIX)}); } diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h index 40ed930366d..14adde037cb 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h @@ -55,14 +55,7 @@ class CompilationDatabaseProject : public ProjectExplorer::Project public: explicit CompilationDatabaseProject(const Utils::FilePath &filename); - - bool needsConfiguration() const override { return false; } - Utils::FilePath rootPathFromSettings() const; - ProjectExplorer::Kit *kit() const { return m_kit.get(); } - -private: - std::unique_ptr m_kit; }; class CompilationDatabaseBuildSystem : public ProjectExplorer::BuildSystem From b329b7220bce33f10e2a28fc8ceb6b4868232dcc Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 2 Mar 2020 10:26:56 +0100 Subject: [PATCH 66/96] ADS: Do not re-use variables Change-Id: I2aee3d6684d40077acfe652638292901bd660ea6 Reviewed-by: Tim Jenssen --- src/libs/advanceddockingsystem/dockwidget.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/advanceddockingsystem/dockwidget.cpp b/src/libs/advanceddockingsystem/dockwidget.cpp index 72a59c5b1f4..760f425ae78 100644 --- a/src/libs/advanceddockingsystem/dockwidget.cpp +++ b/src/libs/advanceddockingsystem/dockwidget.cpp @@ -336,9 +336,9 @@ namespace ADS void DockWidget::toggleViewInternal(bool open) { - DockContainerWidget *dockContainerWidget = dockContainer(); - DockWidget *topLevelDockWidgetBefore = dockContainerWidget - ? dockContainerWidget->topLevelDockWidget() + const DockContainerWidget *const beforeDockContainerWidget = dockContainer(); + DockWidget *topLevelDockWidgetBefore = beforeDockContainerWidget + ? beforeDockContainerWidget->topLevelDockWidget() : nullptr; if (open) { @@ -359,7 +359,7 @@ namespace ADS // Here we need to call the dockContainer() function again, because if // this dock widget was unassigned before the call to showDockWidget() then // it has a dock container now - dockContainerWidget = dockContainer(); + const DockContainerWidget *const dockContainerWidget = dockContainer(); DockWidget *topLevelDockWidgetAfter = dockContainerWidget ? dockContainerWidget->topLevelDockWidget() : nullptr; From bc64318e311e07ec6b07c12dcd2c68c2e591a949 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 2 Mar 2020 10:28:09 +0100 Subject: [PATCH 67/96] QmlDesigner: Remove dead code Change-Id: Ia9db826ff5237755b2794a1ebee8df2a7bedace6 Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/designmodewidget.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 091f1d5e459..db8e819869f 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -182,21 +182,11 @@ QWidget *DesignModeWidget::createProjectExplorerWidget(QWidget *parent) void DesignModeWidget::readSettings() // readPerspectives { return; - - QSettings *settings = Core::ICore::settings(); - - settings->beginGroup("Bauhaus"); - settings->endGroup(); } void DesignModeWidget::saveSettings() // savePerspectives { return; - - QSettings *settings = Core::ICore::settings(); - - settings->beginGroup("Bauhaus"); - settings->endGroup(); } void DesignModeWidget::enableWidgets() From a24dead5f63d7eb0b209539daebf5b2ce558b1c0 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 2 Mar 2020 10:29:53 +0100 Subject: [PATCH 68/96] ADS: Remove struct from FloatingDockContainer We do not use structs in Qt Creator. Change-Id: I179013eb40f6fd2a836b49f40c6ee17b5f0ce6d7 Reviewed-by: Tim Jenssen --- src/libs/advanceddockingsystem/dockcontainerwidget.h | 4 ++-- src/libs/advanceddockingsystem/dockmanager.h | 4 ++-- src/libs/advanceddockingsystem/floatingdockcontainer.cpp | 6 +++--- src/libs/advanceddockingsystem/floatingdockcontainer.h | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libs/advanceddockingsystem/dockcontainerwidget.h b/src/libs/advanceddockingsystem/dockcontainerwidget.h index 497b4caa194..b4b78b29e5f 100644 --- a/src/libs/advanceddockingsystem/dockcontainerwidget.h +++ b/src/libs/advanceddockingsystem/dockcontainerwidget.h @@ -52,7 +52,7 @@ class DockWidget; class DockManager; struct DockManagerPrivate; class FloatingDockContainer; -struct FloatingDockContainerPrivate; +class FloatingDockContainerPrivate; class FloatingDragPreview; struct FloatingDragPreviewPrivate; class DockingStateReader; @@ -75,7 +75,7 @@ private: friend class DockAreaWidget; friend struct DockAreaWidgetPrivate; friend class FloatingDockContainer; - friend struct FloatingDockContainerPrivate; + friend class FloatingDockContainerPrivate; friend class DockWidget; friend class FloatingDragPreview; friend struct FloatingDragPreviewPrivate; diff --git a/src/libs/advanceddockingsystem/dockmanager.h b/src/libs/advanceddockingsystem/dockmanager.h index a788e82d6a1..76f1d032d0b 100644 --- a/src/libs/advanceddockingsystem/dockmanager.h +++ b/src/libs/advanceddockingsystem/dockmanager.h @@ -68,7 +68,7 @@ const char AUTO_RESTORE_WORKSPACE_SETTINGS_KEY[] = "QML/Designer/AutoRestoreLast struct DockManagerPrivate; class FloatingDockContainer; -struct FloatingDockContainerPrivate; +class FloatingDockContainerPrivate; class DockComponentsFactory; class DockContainerWidget; class DockContainerWidgetPrivate; @@ -98,7 +98,7 @@ private: DockManagerPrivate *d; ///< private data (pimpl) friend struct DockManagerPrivate; friend class FloatingDockContainer; - friend struct FloatingDockContainerPrivate; + friend class FloatingDockContainerPrivate; friend class DockContainerWidget; friend class DockContainerWidgetPrivate; friend class DockAreaTabBar; diff --git a/src/libs/advanceddockingsystem/floatingdockcontainer.cpp b/src/libs/advanceddockingsystem/floatingdockcontainer.cpp index 6bf2d9efbdc..892ab023024 100644 --- a/src/libs/advanceddockingsystem/floatingdockcontainer.cpp +++ b/src/libs/advanceddockingsystem/floatingdockcontainer.cpp @@ -62,8 +62,9 @@ namespace ADS /** * Private data class of FloatingDockContainer class (pimpl) */ - struct FloatingDockContainerPrivate + class FloatingDockContainerPrivate { + public: FloatingDockContainer *q; DockContainerWidget *m_dockContainer; unsigned int m_zOrderIndex = ++zOrderCounter; @@ -125,8 +126,7 @@ namespace ADS q->setWindowIcon(QApplication::windowIcon()); } } - }; - // struct FloatingDockContainerPrivate + }; // class FloatingDockContainerPrivate FloatingDockContainerPrivate::FloatingDockContainerPrivate(FloatingDockContainer *parent) : q(parent) diff --git a/src/libs/advanceddockingsystem/floatingdockcontainer.h b/src/libs/advanceddockingsystem/floatingdockcontainer.h index 83be9c2662f..de7c2d0ed41 100644 --- a/src/libs/advanceddockingsystem/floatingdockcontainer.h +++ b/src/libs/advanceddockingsystem/floatingdockcontainer.h @@ -48,7 +48,7 @@ using FloatingWidgetBaseType = QWidget; namespace ADS { -struct FloatingDockContainerPrivate; +class FloatingDockContainerPrivate; class DockManager; struct DockManagerPrivate; class DockAreaWidget; @@ -111,7 +111,7 @@ class ADS_EXPORT FloatingDockContainer : public FloatingWidgetBaseType, Q_OBJECT private: FloatingDockContainerPrivate *d; ///< private data (pimpl) - friend struct FloatingDockContainerPrivate; + friend class FloatingDockContainerPrivate; friend class DockManager; friend struct DockManagerPrivate; friend class DockAreaTabBar; From b09a48599e7e5db5447189136353b79aca3898cf Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Fri, 28 Feb 2020 17:51:32 +0100 Subject: [PATCH 69/96] Update qmljs parser to Qt 5.15 parser * parser side support for annotations, inline components, new UiVersion and all the things included in QT 5.15 parser * SourceLocation moved from QmlJS:AST to QmlJS * Visitors now need to handle throwRecursionDepthError * BaseVisitor for visitors that want to override all visit Task-number: QTCREATORBUG-23591 Change-Id: I682a30d0b08b6c929739fd0e339ef6fbde3eb630 Reviewed-by: Fabian Kosmale Reviewed-by: Simon Hausmann --- .../src/editors/creator-code-syntax.qdoc | 8 + src/libs/qmljs/CMakeLists.txt | 2 +- src/libs/qmljs/jsoncheck.cpp | 8 + src/libs/qmljs/jsoncheck.h | 6 +- src/libs/qmljs/parser/cmd.sed | 21 +- src/libs/qmljs/parser/gen-parser.sh | 32 +- src/libs/qmljs/parser/grammar.patch | 21 + src/libs/qmljs/parser/parser.patch | 216 +- src/libs/qmljs/parser/parser.pri | 15 +- src/libs/qmljs/parser/qmldirparser.cpp | 73 +- src/libs/qmljs/parser/qmldirparser_p.h | 68 +- src/libs/qmljs/parser/qmlerror.cpp | 351 -- src/libs/qmljs/parser/qmljs.g | 349 +- src/libs/qmljs/parser/qmljsast.cpp | 270 +- src/libs/qmljs/parser/qmljsast_p.h | 353 +- src/libs/qmljs/parser/qmljsastfwd_p.h | 33 +- src/libs/qmljs/parser/qmljsastvisitor.cpp | 6 +- src/libs/qmljs/parser/qmljsastvisitor_p.h | 800 +++- .../qmljs/parser/qmljsdiagnosticmessage_p.h | 98 + src/libs/qmljs/parser/qmljsengine_p.cpp | 4 +- src/libs/qmljs/parser/qmljsengine_p.h | 48 +- src/libs/qmljs/parser/qmljsgrammar.cpp | 4078 +++++++++-------- src/libs/qmljs/parser/qmljsgrammar_p.h | 129 +- src/libs/qmljs/parser/qmljskeywords_p.h | 19 + src/libs/qmljs/parser/qmljslexer.cpp | 19 +- src/libs/qmljs/parser/qmljslexer_p.h | 4 +- src/libs/qmljs/parser/qmljsmemorypool_p.h | 22 +- src/libs/qmljs/parser/qmljsparser.cpp | 2005 ++++---- src/libs/qmljs/parser/qmljsparser_p.h | 80 +- .../{qmlerror.h => qmljssourcelocation_p.h} | 62 +- src/libs/qmljs/qmljs.qbs | 2 +- src/libs/qmljs/qmljsbind.cpp | 15 +- src/libs/qmljs/qmljsbind.h | 2 + src/libs/qmljs/qmljscheck.cpp | 21 + src/libs/qmljs/qmljscheck.h | 7 +- src/libs/qmljs/qmljsdocument.h | 4 +- src/libs/qmljs/qmljsevaluate.cpp | 7 + src/libs/qmljs/qmljsevaluate.h | 2 + src/libs/qmljs/qmljsinterpreter.cpp | 11 +- src/libs/qmljs/qmljslink.cpp | 8 +- src/libs/qmljs/qmljsreformatter.cpp | 10 +- src/libs/qmljs/qmljsscopeastpath.cpp | 6 + src/libs/qmljs/qmljsscopeastpath.h | 3 +- src/libs/qmljs/qmljsscopechain.cpp | 2 +- src/libs/qmljs/qmljssimplereader.cpp | 12 +- src/libs/qmljs/qmljssimplereader.h | 10 +- src/libs/qmljs/qmljsstaticanalysismessage.cpp | 5 +- src/libs/qmljs/qmljsstaticanalysismessage.h | 5 +- src/libs/qmljs/qmljstypedescriptionreader.cpp | 15 +- src/libs/qmljs/qmljstypedescriptionreader.h | 6 +- src/libs/qmljs/qmljsutils.cpp | 2 +- src/libs/qmljs/qmljsutils.h | 11 +- .../autotest/quick/quicktestvisitors.cpp | 7 + .../autotest/quick/quicktestvisitors.h | 2 + .../componentcore/findimplementation.cpp | 19 +- .../filemanager/addpropertyvisitor.cpp | 4 +- .../filemanager/astobjecttextextractor.cpp | 7 + .../filemanager/astobjecttextextractor.h | 2 + .../filemanager/firstdefinitionfinder.cpp | 5 + .../filemanager/firstdefinitionfinder.h | 2 + .../moveobjectbeforeobjectvisitor.cpp | 6 +- .../moveobjectbeforeobjectvisitor.h | 2 +- .../filemanager/objectlengthcalculator.cpp | 5 + .../filemanager/objectlengthcalculator.h | 2 + .../designercore/filemanager/qmlrewriter.cpp | 17 +- .../designercore/filemanager/qmlrewriter.h | 8 +- .../model/basetexteditmodifier.cpp | 2 +- .../designercore/model/documentmessage.cpp | 1 + .../designercore/model/texttomodelmerger.cpp | 14 +- .../designercore/model/texttomodelmerger.h | 6 +- .../qmljscomponentfromobjectdef.cpp | 1 + src/plugins/qmljseditor/qmljseditor.cpp | 12 +- .../qmljseditor/qmljseditordocument.cpp | 18 +- .../qmljseditor/qmljsfindreferences.cpp | 25 +- src/plugins/qmljseditor/qmljshoverhandler.cpp | 4 +- src/plugins/qmljseditor/qmljsoutline.cpp | 2 +- .../qmljseditor/qmljssemantichighlighter.cpp | 11 + .../qmljseditor/qmljssemantichighlighter.h | 2 +- src/plugins/qmljseditor/qmljswrapinloader.cpp | 6 + src/plugins/qmljseditor/qmloutlinemodel.cpp | 32 +- src/plugins/qmljseditor/qmloutlinemodel.h | 10 +- src/plugins/qmljstools/qmljslocatordata.cpp | 6 + .../qmljstools/qmljsrefactoringchanges.cpp | 4 +- .../qmljstools/qmljsrefactoringchanges.h | 4 +- src/plugins/qmljstools/qmljssemanticinfo.cpp | 14 +- src/plugins/qmljstools/qmljssemanticinfo.h | 2 +- .../qmlprofilerdetailsrewriter.cpp | 8 +- src/plugins/todo/qmljstodoitemsscanner.cpp | 2 +- 88 files changed, 5290 insertions(+), 4350 deletions(-) create mode 100644 src/libs/qmljs/parser/grammar.patch delete mode 100644 src/libs/qmljs/parser/qmlerror.cpp create mode 100644 src/libs/qmljs/parser/qmljsdiagnosticmessage_p.h rename src/libs/qmljs/parser/{qmlerror.h => qmljssourcelocation_p.h} (58%) diff --git a/doc/qtcreator/src/editors/creator-code-syntax.qdoc b/doc/qtcreator/src/editors/creator-code-syntax.qdoc index 3f542df9d1f..4d05f3f288e 100644 --- a/doc/qtcreator/src/editors/creator-code-syntax.qdoc +++ b/doc/qtcreator/src/editors/creator-code-syntax.qdoc @@ -669,10 +669,18 @@ \l{http://linterrors.com/js/the-array-literal-notation-is-preferrable} {The array literal notation [] is preferable}. + \row + \li M324 + \li Error + \li Hit maximum recursion limit visiting AST, the code model will be unreliable + and most likely invalid + \li + \row \li M400 \li Warning \li Duplicate import + \li \endtable diff --git a/src/libs/qmljs/CMakeLists.txt b/src/libs/qmljs/CMakeLists.txt index 5ccb629cb23..3357b0da66e 100644 --- a/src/libs/qmljs/CMakeLists.txt +++ b/src/libs/qmljs/CMakeLists.txt @@ -4,7 +4,6 @@ add_qtc_library(QmlJS SOURCES jsoncheck.cpp jsoncheck.h parser/qmldirparser.cpp parser/qmldirparser_p.h - parser/qmlerror.cpp parser/qmlerror.h parser/qmljsast.cpp parser/qmljsast_p.h parser/qmljsastfwd_p.h parser/qmljsastvisitor.cpp parser/qmljsastvisitor_p.h @@ -15,6 +14,7 @@ add_qtc_library(QmlJS parser/qmljslexer.cpp parser/qmljslexer_p.h parser/qmljsmemorypool_p.h parser/qmljsparser.cpp parser/qmljsparser_p.h + parser/qmljssourcelocation.cpp parser/qmljssourcelocation_p.h persistenttrie.cpp persistenttrie.h qmljs_global.h qmljsbind.cpp qmljsbind.h diff --git a/src/libs/qmljs/jsoncheck.cpp b/src/libs/qmljs/jsoncheck.cpp index 15d0edb1a78..d2beb507cc9 100644 --- a/src/libs/qmljs/jsoncheck.cpp +++ b/src/libs/qmljs/jsoncheck.cpp @@ -310,6 +310,14 @@ bool JsonCheck::visit(StringLiteral *ast) return false; } +void JsonCheck::throwRecursionDepthError() +{ + analysis()->m_messages.append(Message(ErrHitMaximumRecursion, + SourceLocation(), + QString(), QString(), false)); + +} + static QString formatExpectedTypes(QStringList all) { all.removeDuplicates(); diff --git a/src/libs/qmljs/jsoncheck.h b/src/libs/qmljs/jsoncheck.h index e8efc8db190..9885ad2353d 100644 --- a/src/libs/qmljs/jsoncheck.h +++ b/src/libs/qmljs/jsoncheck.h @@ -59,6 +59,8 @@ private: bool visit(AST::NumericLiteral *ast) override; bool visit(AST::StringLiteral *ast) override; + void throwRecursionDepthError() override; + struct AnalysisData { AnalysisData() : m_ranking(0), m_hasMatch(false) {} @@ -71,12 +73,12 @@ private: }; void processSchema(AST::Node *ast); - bool proceedCheck(Utils::JsonValue::Kind kind, const AST::SourceLocation &location); + bool proceedCheck(Utils::JsonValue::Kind kind, const SourceLocation &location); AnalysisData *analysis(); Document::Ptr m_doc; - AST::SourceLocation m_firstLoc; + SourceLocation m_firstLoc; Utils::JsonSchema *m_schema; QStack m_analysis; }; diff --git a/src/libs/qmljs/parser/cmd.sed b/src/libs/qmljs/parser/cmd.sed index a9b8ac0a6e5..0e6fc698281 100644 --- a/src/libs/qmljs/parser/cmd.sed +++ b/src/libs/qmljs/parser/cmd.sed @@ -1,16 +1,25 @@ -s/private\/qdeclarative/qml/g +s/include */include "qmljs\/parser\/\1"/g +s/qtqmlcompilerglobal_p.h/qmljsglobal_p.h/g +s//"qmljsglobal_p.h"/g +s/Q_QMLCOMPILER_PRIVATE_EXPORT/QML_PARSER_EXPORT/g s/qqml/qml/g s/QDECLARATIVE/QML/g s/QQml/Qml/g s/QQMLJS/QMLJS/g s/Q_QML_EXPORT //g -s/Q_QML_PRIVATE_EXPORT/QML_PARSER_EXPORT/ +s/Q_QML_PRIVATE_EXPORT/QML_PARSER_EXPORT/g +s/QT_BEGIN_NAMESPACE/QT_QML_BEGIN_NAMESPACE/g +s/QT_END_NAMESPACE/QT_QML_END_NAMESPACE/g # adjust pri file s/ \$\$PWD\/qmljsglobal_p.h/ $$PWD\/qmljsglobal_p.h \\\ + $$PWD\/qmljssourcelocation_p.h \\\ + $$PWD\/qmljsmemorypool_p.h \\\ $$PWD\/qmldirparser_p.h \\\ - $$PWD\/qmlerror.h/ -s/ \$\$PWD\/qmljsparser.cpp/ $$PWD\/qmljsparser.cpp \\\ + $$PWD\/qmljsgrammar_p.h \\\ + $$PWD\/qmljsparser_p.h/ + +s/ \$\$PWD\/qmljslexer.cpp/ $$PWD\/qmljslexer.cpp \\\ $$PWD\/qmldirparser.cpp \\\ - $$PWD\/qmlerror.cpp/ -s/OTHER_FILES/DISTFILES/ + $$PWD\/qmljsgrammar.cpp \\\ + $$PWD\/qmljsparser.cpp/ diff --git a/src/libs/qmljs/parser/gen-parser.sh b/src/libs/qmljs/parser/gen-parser.sh index acd30d0906a..c78c307adcf 100755 --- a/src/libs/qmljs/parser/gen-parser.sh +++ b/src/libs/qmljs/parser/gen-parser.sh @@ -10,11 +10,12 @@ # cd src/libs/qmljs/parser # QTDIR=~/path/to/qtdeclarative-checkout ./gen-parser.sh -if [ -z "$QTDIR" ]; then - echo "Usage: QTDIR=~/path/to/qtdeclarative-checkout $0" 1>&2 +if [ -z "$QTDIR" -o -z "$QLALR" ]; then + echo "Usage: QTDIR=~/path/to/qtdeclarative-checkout QLALR=~/path/to/qlalr $0" 1>&2 exit 1 fi + me=$(dirname $0) for i in $QTDIR/src/qml/parser/*.{g,h,cpp,pri}; do @@ -23,22 +24,23 @@ for i in $QTDIR/src/qml/parser/*.{g,h,cpp,pri}; do fi done -for i in $QTDIR/src/qml/qml/qqml{error.{h,cpp},dirparser{_p.h,.cpp}}; do - sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qqml/qml/) +for i in $QTDIR/src/qml/qmldirparser/*.{h,cpp}; do + if ! echo $i | grep -q qmljsglobal; then + sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qqml/qml/) + fi done -# export QmlDirParser -perl -p -0777 -i -e 's/QT_BEGIN_NAMESPACE\n\nclass QmlError;\nclass QmlEngine;\nclass Q_AUTOTEST_EXPORT QmlDirParser/#include "qmljsglobal_p.h"\n\nQT_BEGIN_NAMESPACE\n\nclass QmlError;\nclass QmlEngine;\nclass QML_PARSER_EXPORT QmlDirParser/' qmldirparser_p.h -# export QmlJSGrammar -perl -p -0777 -i -e 's/#include \n\nQT_BEGIN_NAMESPACE\n\nclass QmlJSGrammar\n/#include "qmljsglobal_p.h"\n#include \n\nQT_BEGIN_NAMESPACE\n\nclass QML_PARSER_EXPORT QmlJSGrammar\n/' qmljsgrammar_p.h +for i in $QTDIR/src/qml/common/qqmljs{sourcelocation,memorypool}_p.h; do + sed -f $me/cmd.sed $i > $me/$(echo $(basename $i) | sed s/qqmljs/qmljs/) +done + +# remove qmlapiversion_p.h include +#include "qmlapiversion_p.h" +perl -p -0777 -i -e 's/#include \"qmlapiversion_p.h\"//' qmljsdiagnosticmessage_p.h # remove qmlglobal_p.h include perl -p -0777 -i -e 's/#include \"qmlglobal_p.h\"//' qmldirparser.cpp # remove qmlglobal_p.h include -perl -p -0777 -i -e 's/#include \"qmlglobal_p.h\"//' qmlerror.cpp -# remove qmlglobal_p.h include perl -p -0777 -i -e 's/#include \//' qmldirparser.cpp -# remove QtQml/qtqmlglobal.h include -perl -p -0777 -i -e 's/#include \//' qmlerror.h # replace private/qhashedstring_p.h include and QHashedStringRef perl -p -0777 -i -e 's/#include \//' qmldirparser_p.h perl -p -0777 -i -e 's/QHashedStringRef/QString/g' qmldirparser_p.h qmldirparser.cpp @@ -51,11 +53,15 @@ sed -i -e 's/chars.length()/chars.size()/' $me/qmljslexer.cpp sed -i -e 's/DiagnosticMessage::Error/Severity::Error/g' $me/qmljsparser.cpp sed -i -e 's/DiagnosticMessage::Warning/Severity::Warning/g' $me/qmljsparser.cpp sed -i -e 's/DiagnosticMessage::Warning/Severity::Warning/g' $me/qmljsparser_p.h -sed -i -e 's|#include ||g' $me/qmlerror.cpp sed -i -e 's|#include |#include |g' $me/qmljsengine_p.h sed -i -e 's|#include |#include |g' $me/qmljsengine_p.h sed -i -e 's/qt_qnan/qQNaN/' $me/qmljsengine_p.cpp sed -i -e 's|#include |#include |' $me/qmljsengine_p.cpp perl -p -0777 -i -e 's/QT_QML_BEGIN_NAMESPACE/#include \nQT_QML_BEGIN_NAMESPACE/' qmljsengine_p.h +patch -p1 < grammar.patch +$QLALR qmljs.g + ./changeLicense.py $me/../qmljs_global.h qml*.{cpp,h} + +patch -p1 < parser.patch diff --git a/src/libs/qmljs/parser/grammar.patch b/src/libs/qmljs/parser/grammar.patch new file mode 100644 index 00000000000..6189b89a905 --- /dev/null +++ b/src/libs/qmljs/parser/grammar.patch @@ -0,0 +1,21 @@ +diff -u parser-genOut/qmljs.g parser/qmljs.g +--- parser-genOut/qmljs.g 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljs.g 2020-03-02 13:55:50.000000000 +0100 +@@ -379,7 +379,7 @@ + inline DiagnosticMessage diagnosticMessage() const + { + for (const DiagnosticMessage &d : diagnostic_messages) { +- if (d.type != QtWarningMsg) ++ if (d.kind != Severity::Warning) + return d; + } + +@@ -423,7 +423,7 @@ + DiagnosticMessage error; + error.loc = location; + error.message = message; +- error.type = kind; ++ error.kind = DiagnosticMessage::qtMsgTypeToKind(kind); + return error; + } + diff --git a/src/libs/qmljs/parser/parser.patch b/src/libs/qmljs/parser/parser.patch index c1bef1860c3..d8e530133e0 100644 --- a/src/libs/qmljs/parser/parser.patch +++ b/src/libs/qmljs/parser/parser.patch @@ -1,157 +1,83 @@ -diff --git a/src/libs/qmljs/parser/qmlerror.cpp b/src/libs/qmljs/parser/qmlerror.cpp -index d090a19..5ec311d 100644 ---- a/src/libs/qmljs/parser/qmlerror.cpp -+++ b/src/libs/qmljs/parser/qmlerror.cpp -@@ -65,6 +65,12 @@ QT_BEGIN_NAMESPACE +diff -u parser-genOut/qmljsgrammar.cpp parser/qmljsgrammar.cpp +--- parser-genOut/qmljsgrammar.cpp 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljsgrammar.cpp 2020-03-02 14:16:26.000000000 +0100 +@@ -21,7 +21,8 @@ + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** +-***************************************************************************// This file was generated by qlalr - DO NOT EDIT! ++***************************************************************************/ ++// This file was generated by qlalr - DO NOT EDIT! + #include "qmljsgrammar_p.h" - \sa QQuickView::errors(), QmlComponent::errors() - */ -+ -+static quint16 qmlSourceCoordinate(int n) -+{ -+ return (n > 0 && n <= static_cast(USHRT_MAX)) ? static_cast(n) : 0; -+} -+ - class QmlErrorPrivate + const char *const QmlJSGrammar::spell [] = { +diff -u parser-genOut/qmljsgrammar_p.h parser/qmljsgrammar_p.h +--- parser/qmljsgrammar_p.h 2020-03-03 13:51:43.000000000 +0100 ++++ parser-fixed2/qmljsgrammar_p.h 2020-03-02 17:20:56.000000000 +0100 +@@ -21,11 +21,13 @@ + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** +-***************************************************************************// This file was generated by qlalr - DO NOT EDIT! ++***************************************************************************/ ++// This file was generated by qlalr - DO NOT EDIT! + #ifndef QMLJSGRAMMAR_P_H + #define QMLJSGRAMMAR_P_H ++#include "qmljsglobal_p.h" + +-class QmlJSGrammar ++class QML_PARSER_EXPORT QmlJSGrammar { public: -diff --git a/src/libs/qmljs/parser/qmljsengine_p.cpp b/src/libs/qmljs/parser/qmljsengine_p.cpp -index 1e22fa5..10fc3d1 100644 ---- a/src/libs/qmljs/parser/qmljsengine_p.cpp -+++ b/src/libs/qmljs/parser/qmljsengine_p.cpp -@@ -110,7 +110,7 @@ double integerFromString(const QString &str, int radix) - - - Engine::Engine() -- : _lexer(0) -+ : _lexer(0), _directives(0) - { } - - Engine::~Engine() -@@ -131,6 +131,12 @@ Lexer *Engine::lexer() const - void Engine::setLexer(Lexer *lexer) - { _lexer = lexer; } - -+void Engine::setDirectives(Directives *directives) -+{ _directives = directives; } -+ -+Directives *Engine::directives() const -+{ return _directives; } -+ - MemoryPool *Engine::pool() - { return &_pool; } - -diff --git a/src/libs/qmljs/parser/qmljsengine_p.h b/src/libs/qmljs/parser/qmljsengine_p.h -index b1f7e1a..29b69d1 100644 ---- a/src/libs/qmljs/parser/qmljsengine_p.h -+++ b/src/libs/qmljs/parser/qmljsengine_p.h -@@ -44,36 +44,35 @@ - #include "qmljsglobal_p.h" - #include "qmljsastfwd_p.h" - #include "qmljsmemorypool_p.h" -+#include - - #include - #include - --#include - QT_QML_BEGIN_NAMESPACE - + enum VariousConstants { +diff -u parser-genOut/qmljslexer_p.h parser/qmljslexer_p.h +--- parser-genOut/qmljslexer_p.h 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljslexer_p.h 2020-03-02 13:55:13.000000000 +0100 +@@ -47,7 +47,7 @@ namespace QmlJS { - class Lexer; -+class Directives; - class MemoryPool; + class Engine; +-struct DiagnosticMessage; ++class DiagnosticMessage; + class Directives; - class QML_PARSER_EXPORT DiagnosticMessage - { - public: -- enum Kind { Warning, Error }; -- - DiagnosticMessage() -- : kind(Error) {} -+ : kind(Severity::Error) {} + class QML_PARSER_EXPORT Lexer: public QmlJSGrammar +diff -u parser-genOut/qmljsparser.cpp parser/qmljsparser.cpp +--- parser-genOut/qmljsparser.cpp 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljsparser.cpp 2020-03-02 14:16:01.000000000 +0100 +@@ -22,5 +22,6 @@ + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ****************************************************************************/ ++#line 172 "qmljs.g" -- DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) -+ DiagnosticMessage(Severity::Enum kind, const AST::SourceLocation &loc, const QString &message) - : kind(kind), loc(loc), message(message) {} + #include "qmljs/parser/qmljsengine_p.h" +diff -u parser-genOut/qmljsparser_p.h parser/qmljsparser_p.h +--- parser-genOut/qmljsparser_p.h 2020-03-02 13:53:50.000000000 +0100 ++++ parser/qmljsparser_p.h 2020-03-02 14:13:25.000000000 +0100 +@@ -22,6 +22,7 @@ + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ****************************************************************************/ ++#line 223 "qmljs.g" - bool isWarning() const -- { return kind == Warning; } -+ { return kind == Severity::Warning; } - bool isError() const -- { return kind == Error; } -+ { return kind == Severity::Error; } + // + +diff -u parser-genOut/parser.pri parser/parser.pri +--- parser-genOut/parser.pri 2020-03-02 15:40:09.000000000 +0100 ++++ parser/parser.pri 2020-03-02 15:41:11.000000000 +0100 +@@ -22,10 +22,10 @@ + $$PWD/qmljsparser.cpp \ -- Kind kind; -+ Severity::Enum kind; - AST::SourceLocation loc; - QString message; - }; -@@ -81,6 +80,7 @@ public: - class QML_PARSER_EXPORT Engine - { - Lexer *_lexer; -+ Directives *_directives; - MemoryPool _pool; - QList _comments; - QString _extraCode; -@@ -99,6 +99,9 @@ public: - Lexer *lexer() const; - void setLexer(Lexer *lexer); +-CONFIG += qlalr ++#CONFIG += qlalr + QLALRSOURCES = $$PWD/qmljs.g +-QMAKE_QLALRFLAGS = --no-debug --qt ++#QMAKE_QLALRFLAGS = --no-debug --qt -+ void setDirectives(Directives *directives); -+ Directives *directives() const; -+ - MemoryPool *pool(); + OTHER_FILES += $$QLALRSOURCES - inline QStringRef midRef(int position, int size) { return _code.midRef(position, size); } -diff --git a/src/libs/qmljs/parser/qmljslexer.cpp b/src/libs/qmljs/parser/qmljslexer.cpp -index 9698e9d..036be75 100644 ---- a/src/libs/qmljs/parser/qmljslexer.cpp -+++ b/src/libs/qmljs/parser/qmljslexer.cpp -@@ -345,7 +345,7 @@ static inline bool isIdentifierStart(QChar ch) - // fast path for ascii - if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || - (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || -- ch == '$' || ch == '_') -+ ch == QLatin1Char('$') || ch == QLatin1Char('_')) - return true; - - switch (ch.category()) { -@@ -368,7 +368,7 @@ static bool isIdentifierPart(QChar ch) - if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') || - (ch.unicode() >= 'A' && ch.unicode() <= 'Z') || - (ch.unicode() >= '0' && ch.unicode() <= '9') || -- ch == '$' || ch == '_' || -+ ch == QLatin1Char('$') || ch == QLatin1Char('_') || - ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */) - return true; - -diff --git a/src/libs/qmljs/parser/qmljsparser.cpp b/src/libs/qmljs/parser/qmljsparser.cpp -index 6e61637..e016b91 100644 ---- a/src/libs/qmljs/parser/qmljsparser.cpp -+++ b/src/libs/qmljs/parser/qmljsparser.cpp -@@ -157,7 +157,20 @@ bool Parser::parse(int startToken) - - token_buffer[0].token = startToken; - first_token = &token_buffer[0]; -- last_token = &token_buffer[1]; -+ if (startToken == T_FEED_JS_PROGRAM) { -+ Directives ignoreDirectives; -+ Directives *directives = driver->directives(); -+ if (!directives) -+ directives = &ignoreDirectives; -+ lexer->scanDirectives(directives); -+ token_buffer[1].token = lexer->tokenKind(); -+ token_buffer[1].dval = lexer->tokenValue(); -+ token_buffer[1].loc = location(lexer); -+ token_buffer[1].spell = lexer->tokenSpell(); -+ last_token = &token_buffer[2]; -+ } else { -+ last_token = &token_buffer[1]; -+ } - - tos = -1; - program = 0; + # make sure we install the headers generated by qlalr +-private_headers.CONFIG += no_check_exist ++#private_headers.CONFIG += no_check_exist diff --git a/src/libs/qmljs/parser/parser.pri b/src/libs/qmljs/parser/parser.pri index 7418ea56be2..0694a5188bd 100644 --- a/src/libs/qmljs/parser/parser.pri +++ b/src/libs/qmljs/parser/parser.pri @@ -3,30 +3,29 @@ HEADERS += \ $$PWD/qmljsastfwd_p.h \ $$PWD/qmljsastvisitor_p.h \ $$PWD/qmljsengine_p.h \ - $$PWD/qmljsgrammar_p.h \ $$PWD/qmljslexer_p.h \ - $$PWD/qmljsmemorypool_p.h \ - $$PWD/qmljsparser_p.h \ $$PWD/qmljsglobal_p.h \ + $$PWD/qmljssourcelocation_p.h \ + $$PWD/qmljsmemorypool_p.h \ $$PWD/qmldirparser_p.h \ - $$PWD/qmlerror.h \ + $$PWD/qmljsgrammar_p.h \ + $$PWD/qmljsparser_p.h \ $$PWD/qmljskeywords_p.h SOURCES += \ $$PWD/qmljsast.cpp \ $$PWD/qmljsastvisitor.cpp \ $$PWD/qmljsengine_p.cpp \ - $$PWD/qmljsgrammar.cpp \ $$PWD/qmljslexer.cpp \ - $$PWD/qmljsparser.cpp \ $$PWD/qmldirparser.cpp \ - $$PWD/qmlerror.cpp + $$PWD/qmljsgrammar.cpp \ + $$PWD/qmljsparser.cpp \ #CONFIG += qlalr QLALRSOURCES = $$PWD/qmljs.g #QMAKE_QLALRFLAGS = --no-debug --qt -DISTFILES += $$QLALRSOURCES +OTHER_FILES += $$QLALRSOURCES # make sure we install the headers generated by qlalr #private_headers.CONFIG += no_check_exist diff --git a/src/libs/qmljs/parser/qmldirparser.cpp b/src/libs/qmljs/parser/qmldirparser.cpp index d56affdbe12..003f4aa97bb 100644 --- a/src/libs/qmljs/parser/qmldirparser.cpp +++ b/src/libs/qmljs/parser/qmldirparser.cpp @@ -24,11 +24,10 @@ ****************************************************************************/ #include "qmldirparser_p.h" -#include "qmlerror.h" #include -QT_BEGIN_NAMESPACE +QT_QML_BEGIN_NAMESPACE static int parseInt(const QStringRef &str, bool *ok) { @@ -60,12 +59,18 @@ static bool parseVersion(const QString &str, int *major, int *minor) return false; } -QmlDirParser::QmlDirParser() : _designerSupported(false) -{ -} - -QmlDirParser::~QmlDirParser() +void QmlDirParser::clear() { + _errors.clear(); + _typeNamespace.clear(); + _components.clear(); + _dependencies.clear(); + _imports.clear(); + _scripts.clear(); + _plugins.clear(); + _designerSupported = false; + _typeInfos.clear(); + _className.clear(); } inline static void scanSpace(const QChar *&ch) { @@ -88,13 +93,6 @@ inline static void scanWord(const QChar *&ch) { */ bool QmlDirParser::parse(const QString &source) { - _errors.clear(); - _plugins.clear(); - _components.clear(); - _scripts.clear(); - _designerSupported = false; - _className.clear(); - quint16 lineNumber = 0; bool firstLine = true; @@ -193,7 +191,7 @@ bool QmlDirParser::parse(const QString &source) } Component entry(sections[1], sections[2], -1, -1); entry.internal = true; - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else if (sections[0] == QLatin1String("singleton")) { if (sectionCount < 3 || sectionCount > 4) { reportError(lineNumber, 0, @@ -204,7 +202,7 @@ bool QmlDirParser::parse(const QString &source) // singleton TestSingletonType TestSingletonType.qml Component entry(sections[1], sections[2], -1, -1); entry.singleton = true; - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else { // handle qmldir module listing case where singleton is defined in the following pattern: // singleton TestSingletonType 2.0 TestSingletonType20.qml @@ -213,7 +211,7 @@ bool QmlDirParser::parse(const QString &source) const QString &fileName = sections[3]; Component entry(sections[1], fileName, major, minor); entry.singleton = true; - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[2])); } @@ -249,10 +247,17 @@ bool QmlDirParser::parse(const QString &source) } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[2])); } + } else if (sections[0] == QLatin1String("import")) { + if (sectionCount != 2) { + reportError(lineNumber, 0, + QStringLiteral("import requires 2 arguments, but %1 were provided").arg(sectionCount - 1)); + continue; + } + _imports << sections[1]; } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) const Component entry(sections[0], sections[1], -1, -1); - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } else if (sectionCount == 3) { int major, minor; if (parseVersion(sections[1], &major, &minor)) { @@ -264,7 +269,7 @@ bool QmlDirParser::parse(const QString &source) _scripts.append(entry); } else { const Component entry(sections[0], fileName, major, minor); - _components.insertMulti(entry.typeName, entry); + _components.insert(entry.typeName, entry); } } else { reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected .").arg(sections[1])); @@ -297,27 +302,20 @@ bool QmlDirParser::hasError() const return false; } -void QmlDirParser::setError(const QmlError &e) +void QmlDirParser::setError(const QmlJS::DiagnosticMessage &e) { _errors.clear(); - reportError(e.line(), e.column(), e.description()); + reportError(e.loc.startLine, e.loc.startColumn, e.message); } -QList QmlDirParser::errors(const QString &uri) const +QList QmlDirParser::errors(const QString &uri) const { - QUrl url(uri); - QList errors; + QList errors; const int numErrors = _errors.size(); errors.reserve(numErrors); for (int i = 0; i < numErrors; ++i) { - const QmlJS::DiagnosticMessage &msg = _errors.at(i); - QmlError e; - QString description = msg.message; - description.replace(QLatin1String("$$URI$$"), uri); - e.setDescription(description); - e.setUrl(url); - e.setLine(msg.loc.startLine); - e.setColumn(msg.loc.startColumn); + QmlJS::DiagnosticMessage e = _errors.at(i); + e.message.replace(QLatin1String("$$URI$$"), uri); errors << e; } return errors; @@ -338,7 +336,7 @@ QList QmlDirParser::plugins() const return _plugins; } -QHash QmlDirParser::components() const +QMultiHash QmlDirParser::components() const { return _components; } @@ -348,17 +346,20 @@ QHash QmlDirParser::dependencies() const return _dependencies; } +QStringList QmlDirParser::imports() const +{ + return _imports; +} + QList QmlDirParser::scripts() const { return _scripts; } -#ifdef QT_CREATOR QList QmlDirParser::typeInfos() const { return _typeInfos; } -#endif bool QmlDirParser::designerSupported() const { @@ -384,4 +385,4 @@ QDebug &operator<< (QDebug &debug, const QmlDirParser::Script &script) return debug << qPrintable(output); } -QT_END_NAMESPACE +QT_QML_END_NAMESPACE diff --git a/src/libs/qmljs/parser/qmldirparser_p.h b/src/libs/qmljs/parser/qmldirparser_p.h index a39bfff0d27..9b26d023510 100644 --- a/src/libs/qmljs/parser/qmldirparser_p.h +++ b/src/libs/qmljs/parser/qmldirparser_p.h @@ -39,34 +39,44 @@ #include #include #include -#include "qmljsengine_p.h" -#include "qmljsglobal_p.h" +#include "qmljs/parser/qmljsglobal_p.h" +#include "qmljs/parser/qmljsengine_p.h" +#include "qmljs/parser/qmljsdiagnosticmessage_p.h" -QT_BEGIN_NAMESPACE +QT_QML_BEGIN_NAMESPACE -class QmlError; class QmlEngine; class QML_PARSER_EXPORT QmlDirParser { public: - QmlDirParser(); - ~QmlDirParser(); - + void clear(); bool parse(const QString &source); bool hasError() const; - void setError(const QmlError &); - QList errors(const QString &uri) const; + void setError(const QmlJS::DiagnosticMessage &); + QList errors(const QString &uri) const; QString typeNamespace() const; void setTypeNamespace(const QString &s); + static void checkNonRelative(const char *item, const QString &typeName, const QString &fileName) + { + if (fileName.startsWith(QLatin1Char('/'))) { + qWarning() << item << typeName + << "is specified with non-relative URL" << fileName << "in a qmldir file." + << "URLs in qmldir files should be relative to the qmldir file's directory."; + } + } + struct Plugin { - Plugin() {} + Plugin() = default; Plugin(const QString &name, const QString &path) - : name(name), path(path) {} + : name(name), path(path) + { + checkNonRelative("Plugin", name, path); + } QString name; QString path; @@ -74,11 +84,14 @@ public: struct Component { - Component() {} + Component() = default; Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion) : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion), - internal(false), singleton(false) {} + internal(false), singleton(false) + { + checkNonRelative("Component", typeName, fileName); + } QString typeName; QString fileName; @@ -90,10 +103,13 @@ public: struct Script { - Script() {} + Script() = default; Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion) - : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) {} + : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) + { + checkNonRelative("Script", nameSpace, fileName); + } QString nameSpace; QString fileName; @@ -101,16 +117,16 @@ public: int minorVersion = 0; }; - QHash components() const; + QMultiHash components() const; QHash dependencies() const; + QStringList imports() const; QList