From 8e0d6a0d94f2485a8d2f01ec2e88a2ec20bc0255 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 7 Jun 2010 15:16:36 +0200 Subject: [PATCH 01/32] Doc - Add information about installing Qt Mobility API libraries on Nokia N900. Reviewed-by: Niels Weber Reviewed-by: Tim Jenssen --- doc/qtcreator.qdoc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 790a07d48e2..34627cf5c67 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -5872,6 +5872,32 @@ \image qtcreator-mad-developer-screenshot.png \endlist + \section1 Installing Qt Mobility APIs + + To develop applications that use the Qt Mobility APIs, you must install the + APIs on the devices. The APIs are not available in the Nokia N900 package + manager, and therefore, you must install them from the command line as the + root user. To become the root user you must first install \c rootsh from the + application manager. + + \list 1 + + \o On the device, install \c rootsh from the \gui {Application Manager}. + + \o In \gui Programs, select \c {X Terminal} to open a terminal window + + \o To switch to the root user, enter the following command: + \c{sudo gainroot} + + \o To install Qt Mobility libraries, enter the following command: + \c{apt-get install libqtm-*} + + \o To confirm the installation, enter: \c Y. + + \o Close the terminal. + + \endlist + \section1 Setting Up Network Connectivity on Development PC Use the network configuration tools on your platform to specify the @@ -6282,6 +6308,8 @@ your device \o The \e{qt_installer.sis} package installed on the device, that is delivered with the Qt SDK. + \o Qt Mobility APIs installed on the device, if you use them in + applications. \endlist To run your applications in the Symbian emulator, you also need From 383d9ab9e706b1ea152029320ba99e6b83aa9f76 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 7 Jun 2010 15:17:15 +0200 Subject: [PATCH 02/32] Doc - Add workaround for installing files on Symbian devices. --- doc/qtcreator.qdoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 34627cf5c67..bbc92516eb8 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -6345,6 +6345,10 @@ \endlist + \note If errors occur during the installation, copy the .sis files from + \c {\Symbian\sis} to the device using USB storage + mode. Then install them from the file manager on the device. + \section1 Adding Symbian Platform SDKs Nokia Qt SDK contains all the tools you need for developing Qt applications for From 060888208054fb5593bca89b6fc83f44bd12a97d Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 10 Jun 2010 14:26:33 +0200 Subject: [PATCH 03/32] Doc - Replace S60 with Symbian. --- doc/qtcreator.qdoc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index bbc92516eb8..599f6fa26c3 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -1840,7 +1840,7 @@ \image qtcreator-qt4-qtversions-win-msvc.png \endlist - If you are using \bold{Qt for Symbian} and your S60 SDK is registered + If you are using \bold{Qt for Symbian} and your Symbian SDK is registered with devices.exe, Qt Creator automatically detects the Qt version. To add a Qt for Symbian version: \list 1 @@ -2196,7 +2196,7 @@ \list \o You selected the Symbian Device target for building the application. \o The settings for the Qt version you use to build your project are - correct. The path to the S60 SDK must point to the S60 SDK + correct. The path to the Symbian SDK must point to the Symbian SDK installation directory. Select \gui Tools > \gui Options... > \gui Debugger > \gui{Symbian TRK} and check if it points to the debugger toolchain. @@ -6358,33 +6358,33 @@ \list \o \l{http://www.forum.nokia.com/main/resources/tools_and_sdks/S60SDK/} {S60 Platform SDK 3rd Edition FP1 or higher}. - \o Either the GCCE ARM Toolchain that is included in the S60 Platform + \o Either the GCCE ARM Toolchain that is included in the Symbian SDKs, or RVCT 2.2 [build 686] or later (which is not available free of charge)(Your environment needs to find the compiler in the PATH). - \o Qt for Symbian 4.6.2 or later, installed into the S60 SDKs you want + \o Qt for Symbian 4.6.2 or later, installed into the Symbian SDKs you want to use. \endlist \section2 Setting Up Qt Creator - When you run Qt Creator after installing the S60 Platform SDK and Qt for + When you run Qt Creator after installing the Symbian SDK and Qt for Symbian, the installed SDKs and their corresponding Qt versions are - automatically detected. For each detected S60 SDK with Qt, a special entry + automatically detected. For each detected Symbian SDK with Qt, a special entry is made in the Qt version management settings in \gui{Tools} > \gui{Options...} > \gui{Qt4} > \gui{Qt Versions}. \note If you manually add a Qt version for Symbian, you must - also manually specify the S60 SDK to use for this version. + also manually specify the Symbian SDK to use for this version. \image qtcreator-qt4-qtversions-win-symbian.png If you want to run your applications in the Symbian emulator, you need to point Qt Creator to the Metrowerks Compiler that you want to use, by - setting the \gui{Carbide Directory} of the Qt version to the corresponding + setting the \gui{Carbide directory} of the Qt version to the corresponding Carbide.c++ installation directory. - You can check what S60 SDKs and corresponding Qt versions are found in the + You can check which Symbian SDKs and corresponding Qt versions are found in the \gui{Tools} > \gui{Options...} > \gui{Qt4} > \gui{S60 SDKs} preference page. From dc6303c05067f9472e6bcb537de0572a59f22365 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 10 Jun 2010 14:27:40 +0200 Subject: [PATCH 04/32] Doc - Update screen shots and related text. --- .../qtcreator-gs-build-example-targets.png | Bin 39564 -> 34502 bytes .../qtcreator-qt4-qtversions-win-symbian.png | Bin 27927 -> 26937 bytes doc/images/qtcreator-qt4-s60sdks.png | Bin 8028 -> 8193 bytes doc/qtcreator.qdoc | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/images/qtcreator-gs-build-example-targets.png b/doc/images/qtcreator-gs-build-example-targets.png index c039bd03cc11f892c0000e5ed832a7c78bad99b0..4e5fcce53935fee6117319a850fb7b5c5dc7351d 100644 GIT binary patch literal 34502 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 DPuKQS literal 39564 zcmeAS@N?(olHy`uVBq!ia0y~yV0_KMz_^fuiGhLPToCsk1_lPs0*}aI1_r((Aj~*b zn@^g7fq}im)7O>#7ONDGtU&S?jXJQ9Yeb1-X-P(Y5yQ%LXFM1f7i4 zFfed}WP|2#zs~-1QDV^z9kQlh~r z&T1dOf305{guRpAY9yv5y%4@^a_i)&TW4>0bc>}Joj?DMXV2sM|L@P&elwmM)cyGL z`~SDM*KRs&bo4hvo`Q} zpPqWieNWI#=a@4=%{QGgg3{U-|5~{yMX;emtLexssTE(eoK{VdNcD7>Z=$`pRzFN7 zHGQfCZ|}@VHfA=SzW9q@zf{y-cd4z}l-IHC3qvS>*^bE*zLvRuEXjTTzJCAn?Y9{e z4!g|iS@T(kfx(4AkikKQaRXcbJvA$q4n_v0uhNXK7#MWK0vk9=TmCKX?|uC1p5~9& z*W)(i{bjwcQ~$W@v_5k~_PU*F+zj)7pE5Vg`Ef$~+Ma*st0$e#7ktahBx}+(!(Yl+ z@`BegPQ8gqXA9y3loYFkB${lWyq=m?R3-KMx6tdfC%*5sulH=MH(hY+%8hMr)5Tny z-iYiqVwauIM4QL`0xG-~FYala?B%sK8bee+0i9hRNP83dan z?p5;$Y`r0y^x6E>@&hlW4JV247p{%#XJk;zGT6u-xAWQ8h94iZ?JCcjPT2colJ_Q_ z>pbxvZpam6t(V<$@Q|!ZUiaMGhc6P#tW`Rbgin7||5ldmG^>S2y3l;aW3H%Avmd-$ z@@3mR-y-v?Dm#y=MDIB^HO=2+ZK1G|c=9^ibAqmc-YWMt*eso$=%Z+GEGSO-QjgKe zeJLSZT~$6=^p{%PN^pAaXdJ9C%jL8~^c@d(?)Kx76&AN7Vtb@brmEZcX|;ziy*icV zvu~TytB-EHij$6HUX4`I)8>-gaB+SAzbDsjhkS_N_k#6se#HCGsi(WMFBi&OU$%@v z;qXZlCbod*(|H&b9!>9=Y~eP63pe8JnT z*ZFvPQ{V4++y}~}{{AY{?{Hb2JSwXdCtRZZ)J7y{)9ziLzHd=+%`wWooBOC`^0!x0 zW}La3ne6lY&ATluYkN9m-DfSltE403pZNM&h0MxuXU+6Ix=U|7R_kw;5M}AtE?ig3 z+tkhaH1bN$6sI{_$Nnyew0fy*#rbQByM3qfTBbAsZ6>d?qSccP*%jQ@Tun|r`r1g+ zAYryy-@R}5?eA{+ct51l`SpE4X0bSX9=j{b4YxvKR$pDFrli>(eSf0J9M%p-BZkrg z9#M}NK3uJS|NrCP+m*A#<;!olE|+`W*05#k)blPAD|iGJ_qcX2W^Ij%F_&?%R)0|Y z{{Mmfe^0A#-mSK9!@nl?rT>qtxqQvw`VGP_9}!?zu$Yacx%lv-_lBcts}*! z_c?lKCag-|H%Z`jyoy^w(V2@Xd<+aetM_^GRQ zZ01?M?D4IV+9IZ@$D0{Fs%@A9g#8M7S~fXNmcPG0cB<)?f3gwl?|*v0CslON)4iau zWw)e<-}E?<%&E)?xmN2krDYh@vI8RO52~;Gnfh0hDnKdH`_5NNr%=&V|Q^VzCNF9NnFsom~>8a`3XDv)jKmJ+$?(|bPe zm?5uPwk0*YIlF)H!kt04O^$Uwx~C;<(ytNKeJy8K*!&rDmT2mhpE`1cg(2q0v+oQC zdgFg?;hD3&;9}H&*x0TDr#l0E2P^$AsID@6<0^X1;UlzeDMIvQhu} z{BG9FS@7lWp>(~qZ}0Zj7<{^U*KmUbLvq;jFT59wEd%Ep-bxiO@amw8`4Vt1nx=Os5nvc`OB7r zJPPit#V1);{hyih#M5S7PvJ!W83ztYTwD6vLP~S;jGDO)kD~N_|8nRUEe>rx;U{$b z>&vLv>&#!58d!XuV{BPIzw%sU`Mr&$-{0M}30)huIc(8~?y5PhRlJX@Y)nN@o2q~1 zQ0hoNI9uT4{+T}=+WYM!9?zI$!7m^6zi)qy+y4(2*^ghoym61HA-W>epXgz3>0r_xCD~Uwge?`|6V5MS9D2^D56_JYslk zYv!8kuY-dXjw^OBD5lLRn>q1bRbOkm?n9M-t>^y=^H;vU{r};e!&ThpqlEl@8>4hq zgw1Y9D|qN?C~@ao^XgBVA56Jx^K9Zi>1w|_3)DPfwv|shV|r$C$33(5;Jx>H@2I^k z+#bJ1Kjx^^w~4B{jGdelj#%dJD`v|o)D|i~`yuU#$xGqo8?+Y)hHB^en8=y@ymh{7 z!q&5owWcj|IlTVS!n9Mr<{S^6qZMTG*=?cFY8ky}ygzKUTJD@YD|u|kgTiH6?lzt3 z^Y4BB-Tu$#dCOHJr+;50n|IgMT`#>Jce3-}Uilrbmejoa*ZxmuXT-A<9)@{aKP|A` zzxG|#i-YX-RoQKZ#}t?+Fm^C(7EEE-ERZf~z!urCCQf3V;muMO7wsLd-CF+q^tYC) z>$xL!Mb-T}Ll%djlk6g^4OKj*PgUI$PV?RTdgAZ{XJ%;|&d(?AUXZIT{^4QM`G`YTxS9VivB$UawB{C-EZH3__3WwrtS_Cx5i zE|mEkdimLL`$hYvh|Sq&|AAjVa;mh&U)JZ>k|w!YCP-|~DNu7&Q0Qi0Q0_=(>shI) z%C_%%^^>_5yI!x`TU1pwt39Ut?bP>w4}?k_T|cKH!dAhmR8raez+#CA+cvAjg7v)T zCT^;`=)ipHwaJ7(8yC;guzP!U%F?^s%&}Uh+E(6@S*$fNEz>VMbN%*ohJuP|-+iV! z{CBW+QT@EcWam7s2P++>9$RyNO4V1pj<&+gowJxHXXtNMb&qumOi|0xvDfu25}7=0 zvqRAAJfnG@kA*MRoO{;bD{qy2LgLi+np+iH-fePUa5X9QG|PqHgL$isXRn^+r^Xvp z-*hBIau@5RDc5>$Y)SrVd^}oXP8d(%-Km?7xT?-EF!<0||AS-s`>XmD3neTY8CP9w z@D|`QKBgpQ__2MXMw14UnBg&nt{H!rpUr>&Rkk$!dgA;aH`5 zTwW&oZSTIt8A;04-3^8b6UFqp{BqLH8tqthf9Jyd?J*y#(~jPL@>)$n_r_Od1zzV< z*Q|v9-(M8+fmKQ3?3Gv2CP(Inw>dji2$j#?e`j@z&e|hqeXTv)U*z{x&aP8gC~PjJ zb?MTFpqfCX?k%>gQlSCO6?reTxJow9_`=mPaqX161xFum(XFhEQAzG$be?keP>=&> z;N;CNb~AFXW-T@IULGp^n0eAyeg*@PD?fhc-nQHJuvz~0hl9UY-FEnqEa5B6Sa8ZE zVa7=(GwH8o&h_P2uJi7_yJo%h<@>^4zdFRrzkb_3ukPC2{=I)M+-9$>y>R{X|2s2d ze_mYue_z<@t65w5>s}R!BUfA??2^7&uC zZr*42;&tb*YNOh_YqndzdfoQ#-3n{&z+< z-lPBO>%v8Xufy_-w=3VtuDy`rwttJR;BFD^z1!zq_^j<%6-OtPc3}SUHh?3!^$vo$1+c)w|UdLuf^`~`WndJ5K-^M?X)uHl8XAP zTW%LiYqUdGFuPChn5R1FLH{B>`Ik4@8Q21+bVh{jD)%XT;#9j*+I7}nrN_O!$K7U} z+_Wwy?PSogmf69s$kK3eboJvFvE!OGit!RmN%UV-C} zx@+155~p+?z3mWId-CR0@2yKCB6#Mdz1zxn)TQhl%c3vKCk0L67wk>=x=@1QhS)|? zrjvKxKCI0*GEVi{Vcz(Dxw>uBeA7$CW(t32PW-WFa(;T^mG-l*|13ZI_`zzYt06P~ zEf?%R?dDM_;}f?{#CYFp#rP-cmd8UoeY{QGn6ld@_qe??S#~^G@07XEzS?XZYjlo^E9*2&yyaGFoL~dR6niq|&sLX}cG{d-rD3QXjvNG-U?1 z$Oa9e7P(XghRp)ZmnY9$-*_wgfo74scRcgf&kr>h{SRVU!JNXFC6UUQbwYuSEr9t! zcfY_wF=rNrn>kyS*bA37^3P5FFs1F9*E_MtvnFLqOzjKJUb^w!;TP}q9K9cXnRWi< zHshBzy3c(*-}pZGJ#&uT$*7zu*Ev^5czc6RZe{#qiQK4_-wJ)L4CG|x2^QcZ#zPoE=EndDVV#9{ejK76|VX|O2-5ydcM3RVII5h z*R?si8(*x|i!KY;YqoXC`tnU-(?6BUYT3^JKk0Mahe`VtH|{d%KC*eHPRZAl-PP56 zRxZ~BQY8P+VPC|tSyGHKMImkCk9F)4KWt?`x&3JtW@2zDdYd5PEOXj3B86eX%V??Z zvLz=DdhboLKJp-Q@BXcK&bn^VnQ&?2`s$yH_MHCVW0#V#BUmTM%#Bs4Ua@$)tZM#} zr7@ek%-&=?>~yoe5u_D-FZXNR-3iB~dDMMBTl{#FT6DHv?UTiftq-3TDs#^aN$L8f zyPqqvex*@Vcjz72O+L%J*2u-R=tX?q;gNYxM&jtsV>^1(Ock!&4?o=aN7Me-#rnO! zwjQ=Fdp~D!yaSHj=bHf%G_Nn4STe|87=Zd>cOvu8&0UaIhJKW4+nkg;LO(Z`b# zg)3u37gpFLKDF4siP6C_bcS~0MUD-NU(`yjXH$8$a_`pgJ#UU4O)9La`ZaZZ#nFey zWh9T6ot->Oq2$~h582z-FV|j}cwFY^p8Y)xGw#&-)HF&mGNc%#`i$=(?6#91OuQTMd)uQo z9@Au0nSy--SHD$X`{+Xb>0^!8?jOnZOg)y+o>8>?sa50Kg6$tyC*L`HNh#W0-DA#T z-tzXi_s=Fz*rJ&0<(O%u;<9vgZg~GEsU;!xO%Bg~yZ^alC$QM%myxG#t$IsGlGQ2C zPLr9ZQc~C_$cZOkT^2p9T3c(Gde`*t2lxMfa6Ebcp646gs;?IjSGH=}0;V5$QtDa!8famYI|C_fkumluOdNS$0#iEEO%@WEC$Nq>b z9b@>=lj`kPc}_Ch{^QP%RomFwwEygIzPWPw{G0oD{cIWj>CH@1Ki|YSLn6=3;De#E z)N~VG-!m0UCz-vwwdd7pzo~62TeW@t!+*8U`MG)b+4p_o0=GV|*fIZBu>Fqk1TV+j z84q8^Nr`6d3_Ib)zuzT%L6$U6hjdfBbe~G>oGqKLnremWYR|ShE?KdUVbj^NnKzA& z&8#_`@WA+(XQWlYG0jgidluV%Ju~Zb{LZ?wt9AO!UUgoXp+2ESy=O7!rkSNzAMX2f zg~jLkU#HuD)h-_wKl{02lkMddccvW@*6K924%^P$ptJ;@ig`|# zec%6loEJW`_1NRL6Mo#0|LA;bQ_<4M?=~|l=N@^y;?yTjm$OxB{l$%^)boCZo;m64 zbHg)cIeYT%D1l>I{t8yTU-s@e&3m<>^+8QXzK&u@m@=2pbE$XpR=l6Lf_su`vd~$M zCy9ocMwd-WPTF6dyzq>G(leXPhH{Y?276>T@Lu;_RJ@+iUE%NctA8>j_XftLcPy7_ z_jHUDUh=RiSNflopN_bLO6}>NSA1W;tjj&f+?n~Ftt#*4p5l7jB_XjsStc;BCEXd>syIeYP!;!|3CIoJ(Y3H z$dqeQiq+x?oq6vs#2$#;-prZ5(WF@tmDNOx!3N(A_5NQDKE`lFN+hb$(+NcC}cP}D^tN@{aPEzSo4N60@+hr^%lUo!bp z_mdqc9Y-HesJW@BvGDA#gR{e(Ra5pIIC4eT{a4cLk8>6j&U_$zUDwyZ=wtci zH!tty%D$*NcJan}pQS!YDWB!;tlo0qN=Mto%*b!d^DR8~1wWhjTDU#z&LiWGoxh8J zD!h*Wb!6^y$GLAb`MtNg)vC-^3Yy83>ggr+wLg0D94*EPUlJ^j_nuVSr4?9p>nq2S zXYOCw=Ufq6CeNj+BQd>rm6-Cvn4>HB_FQLA=9tLyM93*=hoXYN^Ygx!GV7O5I{R|k zxkVd!?`?bTVz_vE*4O(hZ_e(WdUVH8Nkz58O*eaTel6Sn;GIxk(@n-Nzl5hRt6XqP zyVq!|_JzHvxgHAyAMJIo?^ShM@+@jg#$ok!M%!v{I&M+9S=V$Z?na#odUE2q3=P8;~ z`zGlN6+5spC1wfs$lZ;ZUM^I=+hfgYw>z>4j&DRxJvkKDzIAOY*XAc;`OcgEI?QGF zS-SM2MSzvL@NPN#&HknZeW#CDEsa>Y$j@_erb%b>&D0g?GG~I$L^Dikdt!X|(XVqH zg11%H{eSp>)kW|2roOG&$=d`QciFQSTTGbobeqW23)|HVZ*lhA-*hp;ZR5o}2V=wB zBU)R{jxD`@=Y;p|U70{#0Q+ zQLW#)bFWR_msuvyEzbJ==#xzA&Fon`JCJMX_6aFHv+sJG4&S+@YQ@W_oA=_jTkLES z5n8_W;odhKLb)IK#IEdF^5tB%dnEty*%DuyznogA+t|)6v`uAp$m-~+S<8%=0`=Xt zM9n*QqNm_l$6Jf?^Ja$Uw4eUEsQKC=b=BsXdpaYpd`W0e__*WjzLml+$*6 zZL0=f|834Wl76bf9^wze{fDsA_1;OVR3=|s zbXEV~)7*#<-|NMRyhAO`rFoI zlX_G1boh#lJl3~W3vK*bqy0p)dX#;Wg>AV!Kg~%q=AET#B`10zY9+Vrx(h5?tZ}WMYZ_l3sXb8i{mj7#ZudV9!a27SEM}(4E!Q=EIs5&T zw&gQA*;d7~Wk&5iHs{e|BMn(@4QFXjCf5xo?mpXNwdMPrcW2Z(BUSwVmu5OX4=T}B zv+NBx`1n?O-V(;kXN_)O@C~?Dnr>D1S?Q8*oxhJ(ZFl_~6Tjxm{ukF&p4_80bJY^3 zzFX%H&MIb~yi9UpTG6fv>FeDyue3_FpOY>uuQ+p{&pU^GlAew5Y~zVH1ug3yX3gEf z+wKUseubZ6HiJZ@uD;(QwjfZ{_t*Qk7j& z(~AzvElxdgD?~5<((Dk&TW8FFOVu*W`yF%O&e{upmuJ?Nv>ew>_YiT-^(j5qtKTa3 z__eMFch08RlQ+Y=k4q*;EigXmx!cXycutp;=EcP#s-7|V?s-DBN}aDAW*<3ux^XhM z=fqb`r5$^wt9jgcROny2y)|v$i_C2so=tVquYD~v_eRREu=Dq3v-P?>ioE>1CC$j| zActEt%Otm_PU%sXq&UA=30EKOylQ@?sB`mC4&PmWTf10S#8tm$`WjT|&X>Fz0aYHt3 zWx?6Ivt9|FjZM6mP%N4>_0g>7yHXxoCr5`~ipu>xE0EJqKlz^3ro0ah4xc2h$=zCV z=*rjncT!W!Oq747PuV-Q>5Sd|S!)%3oO$AVYx#mu#=7wvl73aIbcgmKTb68I>$7Ut67FZn-f~ zV;Psr(b+5R{Ql#1)Gqsv`HTIoc8~rh6a{uYy}Y4&^4TkvuaB%#P-zXEIngTj{Kuxt zDcw_ci?6wrJL}=IrBB)Ow=Q7wJ}SJa|*U`l;kOVc8wQ9?yQueq*16 z%R1h(A5Mub4-8{k+2A z_+nASr@DOOC-2gpRJ^?1^`VFHl}(acJ`Y2KXSusbcU6euuREcYoC@b<423_u>I`*k z+0n?jXwET~WZf>W1x#!I9l65SG11m;$0b%i(L7%LJXC6zjv& zel1*->@Q|}GsAslQ&ezVQPL!-ko=X?{%>4(Ds|_fz;7nAdhR#c-HTHZ%#99HUNyxk z?2F#RxdG-2bQDGAhQw;l-I<~`HSl}mlMaij{!f!wx^;P`+Wk3_=5VZB!{ykMx2vKA z76qEZ`vx@qn6a_vf^}CNw8r_0?&`e%RQTIHr8yZ)I0CIm2F1Po%3Ni=^a+nx0i`o zuiegEb$+gdz$K0?f$Ns&ygP8=Sir?4Qkxa0IrHx_TlxD^gkoQ?E5B^Z@s*4%=NiAa zSsr~Kvgz*P2^p}p0H#~F&v>_Xm$4+<%t||%87k}EUz7-xNDf-`q|omX!+{Bk9DUPt z8^33W2&sHDzVts-%1G)%K`#52t~CNaERuZ8E9ZYTh&tf&;3jsV6{V?@s-=Ix8ti4b&I~&|M~O( z-nZZS_OEB0Y_6KWG3n(;?dtyMjZa#pdiTd)``feRTEd@eM;Bh5qQrLK$R=sm&Z^f! zHygf)7(EP|Iw}66$ty!`uhcUh>wB0c@T{Jt&wQzDsY#Xi3NEIbOE`QN|2fPtRa*YF zevXQCv9a)V!_Kvhvkr(ks(&o)x;iHGr~Za=woiXwH_}n31+nW!REk zqt9>6UF0!m|LTC~3nsJnnwhkITV(P6mt4f2nQA*+f4MdE-zoWdf6n}yrYFmM|Gj)T zw|w=AcW*9D{d;_UMA4s9NlreeajhAB$@j}^~*o>utU$6+X|n-Y2C@v5!8FMBs1b$KMid+U770@;3+ z!kXQ7g{3<$^!*UrIjK^nW^3Yy9oHqo*;Y#SBv^!&Tw_U=QR%O?ecY8DSQ+9oZM%g3 zOp7xcR@)x4kd4*oe4VhAO-kjQYLtpzRx{t;cY^kl;;+ozY#ZT67}6Yqrap26kEQe@nK+MP=|N=*@}=CFPyG2y!2!Idd+X|O(R#OPUZ%g zf+so}A3JX!4qe>o$MkrP&nu@5cQ~(2_Hd5=vUWrMo_}|q=KnnK^Zmc4&igAKXR=SP ztGIYj_`Gdm==-um)wlW4xLce-BKSW0s!~R_ z?9cMkb{9`uW^S#$lehX#_TtZueLpW{{9_F`W}$pFb)!M;(xvwbrYy5k{>D3TS;W2K z4{4k83X44gLOPRPFibykmErsnEsh$kD=LM1Z@BSF@ha?7+RPEyQ&5!5FY78+{i)qc z%&y5q{OW$*2fp7<%>OVc{LkC|y7;>9*Y%sC-mhfe|LyDf+Rr!L_r1BW?{J3ODqUWe z;;;$!^2Z{MJa{R4`@H4Pj?mMKL$wzL_s4|&JbI0%nWx!@C6eu?$NvTO+x{lK-nmnG z)&4uHoQ(dkU*2hC!u?oL=Wv8sQl#3y6eFF}5z~FHi8_Y6{dsZDp`2~kmH8aIl>g5D zKlkj0oFhhpr(Gr_*7yk3|Ja=Lpkz8Lf6lIzTh#LQxf@^o_@X~7eZ{3q+qY&Y2G02D zbVI1;)VHg9zGo%`NjaH!EXqIa9iq8(zt?SZrFqXxlb(8SlacF~+Y-X4D%s(6ZGRY3 zQD@519SW{fUMZbQeef!Fc3SxKNA|HZK7LD%E4pwuRrkBpq=g(OZB-8JyUJz|F+*hU zrvH)NRnu&C{r;DFdeQwqFaIs(xBd8FpYyAT?iqL7E|%MeXZlWN>3|^6&d| zN)K&|&pXQ@r~c<$%MHEN9XxMtZTy>>KJUZp_`I`TLg&*KSYP^bcWPr^tjXz=2sNQE zzOjEc{IG~g*r$2D+04S+)9<#?)Rj+qC+AO@>!@C7W6Q{2c%s8gfoJvN5V6@-qMeub zT=|gl=-U>PQ&%R{a%`NTC3twsvjFF&lfP%Rs76W$s>q}oEj1M4>?}=Z*WPZLrSkI7WuaTTl8-^YwZE_Vvr!H!t6QxBanGdNIeeu_*Gx?26CP|I3aG->%=DtCMts!I($+0MB8cmYE#JJjQ<}{p&o^ucKI- zRa+d!$|krx-}80kzwMJ-x!8|z7@RgZZ6KUzb||MMR!~Z19%GQnX@Os9-P3l9Tikm7 zG38O-`;PfXOitR|Tj|*0>{6O7WS6GynhCKif#qW^eNEo#!J>zja$1^BjA3bC&(51%!yuPIi8L z`1xGrw^J`}YA=?rNe@q~#FI%ONZS@6xBjen1(&k5N1{JC|x&A&@m)pP!QN<0V$B_ot zN&7<0GZ+11e#X|*`Iaa0$<2S8dzI^?mdwTHwj>u&I$pI-3$p1XRsaJ#;3R*lU3t$!r@-|UhXklaueyX4;ACyTe*|DTn* z>#Oksb8q+j%^Xtyrk<})`+4f{JlhHEEw#Uo`A64Y(|=z*g)zqF&#c#WzmK|?UEN=P zS~mR8-`#bk=jTq`kpFR|`u6>wb;Wz?zPt0=#_oSL>vjI0N9pR{diOsx)vx_{I{s(- z@<;Y>I`pevTmS$3Enc?rOkwoD*XjTNwDz7d+4r^m|37he+2Z??KfW(NvcBf+g+6up z`s>m9H-6lmEnl;$?yLH`|KIa-cm3>(mo5FW@&4bB=j}c(U2ptzmw@Y`_VuiN(V^!%IOPOqK#W=8kj)wSH`_U+^I zbFCiEJYM&!@4w9bo1dpm-}m+4^7`w?r@gQJVt(Fg$Loha-xi3rH%A`*BfoWuz|$0y zMG;0E9FHGYpRfN|%$V>rvHkyx^!=~izP`V^Jiq?`r0IM9h;n?m(9Hkk>sR~tcf=VF zyj*?0>fTQMsuu_Ct{X8SCQJQMq@spzAHz}KE5YR#v){C{wDwEebX4gMbxz9*_Y zv&%^T8z+fg-kB z(_g)KJZ;x{%M<5U^tkXI;ZfRGBGq_QK>5pe{hx>W>&kAu+RV_Pcr44x>E8w^mH=k? z#HWev_0ON(p1$6qC;jKqyU|BwCzl&4v@smlTt2t-z4Pw%|Cdh`p634l)6KB;tPYpoX3fqa>*3-@e&*{r>Gp~GWKEh#mrMVh=dD(g1AwtW_KU5aUGnnRxW zO4i3+n^^q=g|2^1UnAzPSU4fM@n7bR?M+7*-^|_6ve|vo4%>B^GEHOKh6E`%dpFy*>>l5>nZ1{=Ii&#F#P+};T^a0&!elydGw+$?a#lz z@8ie9HLsZBJZ1ipIuo^&HL&0|0VUb*epIi`SVG%z4q(>KiND2lgl;Y zy8baYaJ>JO@bT_+vHIO>KZ(1`o7?UC-lktOEq&$b&1ydiE?vG}|DtOuzwM9X5)Z%4 zzw_(Jx8s(Z`}^PTecJxNlVkty($wRVZ=bKY*PWvLW%AZf4|TFs?%uUo^sr@~efMMG z>%o=X-#X+oZY^#8GTqtri=gpNx0{m>L^vpMc$d|y6wN5=);9LJ9kHoh%I5XQ?Kjqy z<*Lo{s=lpWYNp*^Hkmu*NN*A6rP6ipZ>`+Y5f{;{yO%dASZibL%Z1tJ_exIZJUOpa zM0#iH->LRH9z?Rwtt+~osm*7(B5wWrTU)sW10nRHuct`u@(3-18&1+E^93e%YI!Z&mR#arvCG zYoPk;-v9SsSKWDEySnDmsTW74Ui6LsafUU&^7+Bj{J-y9-~T!P|DVps)6)B*=l$Hh zJ*MD9*I|F#ziY1V`!c6|-_xdd^Zsq$`}+O=Z;!sZ%TN0G>AC&pM;i|R)cx{Zf9Lmk zYt`5Fw8j6s^F8+GM(1hrZ5%C7#h&DQ+WA|8L>a z<9GIL`rk6u+dt-F`JFD+)nQ-c?_V!{vF`revLg?*%irF*djGz?q2b2^!otVr{bGvR zd@cXs&n^WghMfv6jPbU*e@@$oPL@9;;g>FXRQ9sc zBzK2=T=H#fI`3!^4!IzR61Soz;W%GJ|n<#V2UCcQ!L zTb^DlK4)?I$Er9HufKP{R0nM8o#x@(z3^&YOLUth^YkzQfd|gwHD?6WHmB~YDt~w9 z=GCiPtG~Z5BuMxvoJSLDc)g=_RDwi@o7+OE+TxcUw+12AEysTB_!=Ve^uruZOetDhX^2({j{hbLdE3@o{>m z#H)^Je76=K>iLy=?r>y@f!u2+r$zR=Ug}J%wmKO-7v%Xf`{yQB^ZlKYyJ1#IcehEJ z*y`M|mn2wA~lZXyo{RRSC%Xqar8dB-`LRN#^Or>{)IzRZ0Zr zKPh07-<|$?cKmlCh99T4=biiZ<$BVgyQkQu>$_yUULU0;^`-Zc7{lS02OX9tZmhF> z@WA!@PWJh`z6OdM5lu+BvmvX}{y|~G5kI5;jPy1GCGU!pr}f^JY}lWZK7-|x#?ysi z|032Z#=0@K6wFLvc(x``@z{2SBEi?^a!*w|7v}|^eBQ&I^(SNEk;eYzE8YJzNTf-W z-fQ^YA)my^rGF}4ZvL{;B@5dMQ$OE+&r`L>=Z8`7wGB&5zTf+@lxHi)#ZM)x#hz?D z;&^3QQnByMzV}U@kFLySHTtM`_=$7qRLz&szt*Sh)b#C-foG)ElR!qtdJnyv zLbpe4a-u~m?}|JUQsMOWDyUIAC1Gx3tRg1TIs56asSCX$4iqjA;GH>XZPx`kQBOWM zDYl%eTu)scEwco>@0Vor@onF&X?5L zyy;!1YMzGj@7>p?X_iizm$}?Iqo0d;!R!U6!&x5QWMp{idhwm$PqD_TD?xk;Z@DLZ zcgl{|%+gn1?tLhB{*GPs+PA##PkYWHvYn}+WFCY4Uj;E$j%C+MeH6@<*^WNba7$SJ z^2DZ^J8O0G^3NNkM!wf9D-Bq_Q)I=J>v0u3EiH~cVoUb!o8;qhha-MYL42N-^15W9 zXy#Ju2tLW|l@+Tm-Pxhyz3T1KN57Wqc6+LDz|$)a^P^u_V%wb@M~xI=zMphO5s<_2`1|sFZLc~Ja9{X&gE@Vvw!fe znAoy~U#)djn`588(Vv%9IX*RYDq9bB^11Hn%Qx?u7qhrdW16{L|0I`{ucFqoO>|7r zG57j%$^1pwjGFCXUhW;gqx_PC79D2P@BFLa5%Z;Yk8Ps710H=*`2(}GZ*x`T9^KDwVl}1Fq#;<92 zMJ*;Rp1GKL758Qjb%h1V8Ogm|=a89q4{Fz?6wmf51njw>D9$DSn71*Lw zctPf@!%n4&?*?Z)PX)cY?cw|Pl6+EYfROmpNlsgh_MD$|snwb_SBRbAeEICEITzv- zyN_7D(9GUdw!|@4-)`ZRH9=B2YhQ<4T=~3HBc5gIYUeebUfQ) z5j@SyIeFGJ-6r=6p<5dSj=nv?IKM00_p;Oz9s!~4pR$C^i&=%@0~VYvHtgH`ny>K^ z%6y*yEt@_ z*40ysDq`xB{kg*I9i^_>nChRnb(71%=UL%*fmM~>7no-x-YC92Tk48aU?|hpvrlUc z3$2z;JmP;}bGlf(`s}wRyML}X^e~8Yeih_8S(Mpr-MOawt&VF>WlUK3&Nnm7??e9$ zrtjiH=59Oqx?ayXGSf*g-deA(WWL1=-ApzG?F&}drtmB)TcfyoMoE9yi{O`eg_)}t zsT3ytkm}>sPF}6Tw_t6|R920xMc20*9Gzn9w%#bkFI8IplhUi}!by3`ou);nmzH`Y zTPCR4^nUI zN@FnTUZ0v5t4fNK3@68&7Dm(cvy7JfQxg8TXvg1% z8^>1Ic_~eAF}WzHw3cnJKr3TLRQe@`D~A&fU+k{qmEw5Mam8n<7U6Tv^eR94@+mZm`jpwWZuV?(6)7r>*@mgyFSIf z=JYwZeVM-u!ya|n%T8Z{)Gt)Gy^qxi_(`9 zY5OESR!-`hcu&W(D@tS~_unjr2Q}h(b((osTSI4ietCOsR&4Y>@9F!jyTe$`UUffO zpEjw{`O%sBjXON=NH$rktb6RcFt()2&D#6;wgN+uGhTvW{o4*-U7Fdu>&;AuN3+~6 zd&K;4Q(q!0bY184mh;o9R;3!Qh@2>3;hu8By!NJ8zqF`B)+vpi7pt9C_{X%pzH;rr z4W8Q7DYA>-Pq|Ua9T1q z=Hb#ReVr=rxEXz&yY^{ZY!qHGHMQtkkhim?zUIHH*S1_cZSnF(c;qqD#ep84GArkw zULpHx=_6&6E`9m4MOU+B>lY3t7Y3hHvR*L19&c!`b3~DsXVt?)Rly$uQEhZ{l z!DgO7@`g?GkIX&OJ@3FX$+k4L{j@>+L<=X9Kochc2 z&iNB{Lg8&Ix{BJkHW;sppLC>inVD&z=QbbhTU-95YI3CHJ1HL)WKZ41*?%cwzEkZw zHGwrPJiRX^{gaAYzMTHju5#lR?}T|(g@qB?rVsolPbjv3aFEaDWZ$pGtLvAYWsTZ% zcXKaCR-ehw7ng#zUJ1ITvod$K=FgcCLbcnxcKI^5?78!Hb&&d^JAo%>PpVX^*&MQD zO%zZ6yETQ@5%2#xU0bx^(zlM(ng9QMe}AXy_gqddHWn5ZmNS}hKkgX+dlvfKe$(b< z`){!@dKkU5nc`s4vq~UmX*hTeD(RfI5$t=yUE&rA8fX0mJtvT z5V&9{;aB)UX5B9N9d^u2OibU57tFe+uzAb3st;-E4oo2MOs4C|&(tTK+#r)8GA?+Z z`_gn|ji3lf`v!%^OP|7|yP3BiWUggrVPVm!*>V5(kMFLWV8sm^JnkfZNazF0_)K^k zY~jPk|3y|nKwyKz!tGzeLUi}9`ku2*2yE1X1N)y{jE{G7^8xSTb!tz0eS!~U3`fKS zhv&<0h_}A$lDJ``prDYD*!0G%FX2o|*JE*z3z@{^YTo3`xoBLiegzaREN4W{O%lEz z`L*#l$WLMtd)l|`yr0rmdkD-`x?t&d{%)+90?4R`O_O%~SmZ8iBJ<{bLqkJDE9dn2 zwXY90%gTXVDWR}`RrsC0gM9oP92^lH4h!bLV`!PXR!mza2d#>&OGBd`i!jb@-}-E}!H+ljd7+Y$DMGXKChc%8+w(2@q*L=6hegzkPB!DqOE&v2(afB?@1xn(48v5Xyv2{V^lX#7e!?QzlqrqtJSYDt zgZZ}nUa2Vs8)77!`!2?4t~CsIW4me4v&e_{slkQw98zO2 z*_W@axVW`;@t^Mzn)CHVKHXF5Xer-!d2#1r*>)!l3dCYl#)wRMTLRD4l5^v2BDp^v#YEjFLnt5%X9Ionx z>WH|7T5eM-%Ujzgs#3b?UI^D>KewfAzb>|D++?3yCwoCgZ`YGg?d3jy&c84F3&Kyz zch`N|9lKjSOPz1sJZrXci^?qtg)L2L+}Z)Hr}o@?qZQ=dE9TI?((ZxoVNMmJ%yogq z9!in!+thr0VThj{E!@6X(pK`Z0z4)%RH=ft&spj|D zLEGgNSANY5ue)siZX4tFf5IZhZYKNN{E9!_+ZVa*fxVGI#=I>OF?QnJ6KWUlGi7=q zVU=)V`ExI0<6S)Ogk8D6UCDLmUcmFuzUAOs{VEB)p5p$`Kj)}#2zj!&YH3tx-lu~> zOM_N2ecZ%9ePNWTjLFoj&}V1)ML#_)n(1}k&^qT1)wRW#xWP&vV~e_5aj~2MH@56_;%3f0kOd z;bg?3Pe%<^Hv~!Xc!ycBnusr+pkF0WXm)*(h<8BL`e%Bl4>vE33G6$*?O=q)v;`(B z=2uqUsQLFZW?hif##t>Ub9cBhgcy0o-wau&a#P~xLZ%r>dyV$4=;7%Pd7_=VmCKIT zwtSVdjq8-tsj2+SJOoy$O_?$0Ot9#_8-D^A-P~5SF0^^l&K02NeCPl-14FBmV(pjE zU(2to)mC}=?#b)vfj{qEnw`Tevgcp8srr$t7jpd`RMwBIVdYpEYzUlvS=65V&BhEMCj zOSAdSMW*@uTGLtrBeUO0@3~ZeIUwuqE~lW^#g~mXf4aS+uxZLKf8j@28D`5j?O$2E z-G8aci5tKCX0GHk;yxM_r_U?$@Aamey=K!sEn@1pn3DEo>hrEk-t9kMADFYJ_1*mk ze`E}g?btn=eV)aRU-Ncv>$A05dP%l6I=5O=M*c&${;BgNo0N{tK~uni!^c z=8EYBLB+F+dw=QkZ=U$)QAD)lhK!G(O77z7E`FPnol=YsEZx7&FML)!ResLdyOOrI z;`r8w{8l{mxBC00)YE(^th0_hdGh4j+uNIO=9HJ0i@fAzkxcG5(P2Kj{+ofJ;m4c$ zHES2%=rBxZSg~CDYvfm%gPh<>jzMwX(}&RuJeKu^Ea{lReiU4#N;z&cnYm8Ic;+30 z`Fq!{Wny9yvn<%R-*Ij^>odtL-L5Z(Q$jV8H``8^1XbP_>?BM#9z8xYVP24Y1h|TB zbgHw~U*F2Ru6!F8sK%erP+6XIW;c_ui`wMQMH+pNtM=Z@iaU8WNt1hjPln0t-|s8G z=q=*iHcOX(Hs_Iz9lpwQ_=N-vq!pwY&mVWpYH_?|dVwdQxN}M}tJI{@J3KR5E`PUt zK1bL!P;GLiGgGpFVM4~a`;{}@ z(`crT+GI%yi5G9**8aYI{~lkb@jiJ)=D&{p_rzHxPux5c>AW^<{ng~k(7ORz>-T29 zx)gd@crru5rKRzEi@x+cx^DO7>(+qv%-5Dx>^QP&a`DsN_}MjgqZk^_-q%TF;qx!v z{odxA_U75y*@A+FpO@)oUtjBZ`PpX7?_Q*(WNVk6lKQzQ{oEam zop%~!L+*ZiU26XB_pPWCv4z*4{P2C9@oH;!@$GG)j0vZooz1?!mib1_!&hgs-_Me{ zZ*Ey9oO2^URH(?j_xp4qeYV`{G+@SO}2dB3aZwzR+a z&jq^{?#ipV4>EaMZ0*-+k-J|uH2mdwop-1F{4L$(-@kv2+0hy=HMd;%ea0U9u*tj3 z9Fw;DI+h-OHSgcPdH>80^?D}#y%18MoRhcuwD-1;#S`83#{K^^egB{S|3CWI*Z+Ne z-unF>@qHg!)92TI>yG=f=oxPTpW~Gj&%_kh^Do71uf8&~)-W$9O8V4j`a0qCwA_HZ z-(KH2aFXF_?(Hv!Z}0KtIK4J@GBbmPrTK=ZysPJ~YI(IScSD|TzRXVk_>J3ky}iEZ zh4#7#c7_dQccUICyE-^DuqDTtm%QuRy~FT`=baXX*Vjop zu&_jYzxuIr@1OI%*}Xl?;ddzJ04#nrA)e zS|2y@_NGeVOYegBW_^`@xcaeh_3`)nk{npnN=-iAez}cTR3WzR?5)OE+j2XX-mqsl zsC``eQL_5n0}mJV6)xjEHsgmv@UB3XW_Q7ECA017Yo6-uPr5se`@RPI^Rwb>_erhW zq4f1yarU)CZQSeIwq~<4BqSs-nANM4o{`=0=$-ZY6Ov+I4;)~~`KP8|di$#U%}se{ zbFP*-9QfC#8(!}+WA@ejyp?=BGx9Fx-rn|cL2mRmi}kk|n3vy(`!F z#`naRq-%? zIf1?XC2t!~>&5SG{eDDuM_c#S-MPxF0s^a~!&bkmxt^-NIDXT+>n&XSv?j%}WM8*9 zws+c{{STj5f4{qdP58-z)2^Fc7M|Iepw72$-}iTG>u&@yue>05deQgzussid@y^x# zy{f?rC)S<_Ov*Tc-j4lzUilVI5=KN{Hm&!`*&H{UFKs?OWdCS+81ng zZ3>kB-MoCx0#HY|@U6R7|C=={Rn=GXy{|kcnLb&+YDcHs+0)Njvh!~gE5}^fpOg9j zru@e}d90xBq>GQf`@<8fEIvg(TN7xpEGK)zGwt2q>spsbJ&BfQVR^G$U|;jk*9$+d zJ5bZKM)Zn^ZrQf3AIE2S^gF+^3Gjcw#=@dwv>@fe&sRr3uRE|u`4PJm^D5p$Pc^f9 zHf}IX1f5vr#QJ?fgrCqxeXgy$)BBJ8|M2^Fns1qd!-1HDd(|KJXkXy*vv}CjcUt80 zl!k=&{O80)&%Ik0#=xLHx8#z}bO8YYgYFI20%aPwOghcB{m)~2H+S_+AD4dz&*yBa zFq@q_M+4L(nV5V{LPk&_>6*{7KZn}S^S5m71Gh`0B!c5(78TX5p6SD|)znMj1E^8c z%3ifk>i_g}DMm9&{VPBnatG^#cQdn|-D}Bs8@(eSQ108@j&MoIoRVv4ARi>LD))(e zeOq%RS?Sr&xZ=2i)4JPh{ydh?pQ1H?eP6`!Nqtk8D%n|B-fT~pv_koN3wxo$<}aJi zi0AG5`OI5y=acUEKS_tD?39^eesS^ZXxpC_AQx|JH1xcdQeW`YCXr{+Pve96`+hzv z-~apW@;OCb#+{#!Cap73veleAabniW6`Xr)blw+5s7snOojROTutbNc{j^n_byA7g z^>krS2yIt5H_5}wyQkP_@lWFeqP6CKg#t80PNn*-nd+OW!SmGfj>i2hXk2Jx6LG50GI{B%f)5+mSy;}fOZ;4%Fz2GM z;k3>hcRp9V{=&-;pfPQS@gAF?Q=;9KQtCYgnO5PeLRU;#vNv|+hs7qJmi8XCVG!YB zJ<%<=AV9-mYt+NYCGl$UI$|lyK;izAA=yX3)INxp;fwjq&%3T)zqU4d`SRuO_x;YR ztNeIW+^4v>_L(Rb!vY~dBey4}OU;lQGn<80q= zJuhza*5CWZoMn1!S!D6gPoNNsF|yTQxay@k|2(5ZYVge6cAs|2OmUC;)cmB_G9Yf& z#EAy}QUU@7_b-U(&Wt*fa?ZGQd#}^RDf$s|A{rvz0a7VFYu7(<@kuQ4X)(3ckCc$r z4&7;-wjoABnwLdRK)|5?!s~-4vz+$obNO!H5Gdj5y8P#(8!Lq8>GvgGJoThSP?7b2 z{`?tWzd9Yd*K#I?P0q{>G+Y$Xpm1$_rQ7*E8KC$QxFEBq?wyBwls&jPD#rIh@z|u( zJ9*D3J(A}4n*!3`%6=>&MK)|cD}&3Nb;tim304_3LPmJRl8(HLTB9eZ{D8+Uw!OXV z*a7?3juyWrXm}n;I=+0}?sYR$-dDe`PLG}pGH2R`YNdaVgD=1Ov|t}k0o(ecKaSj! zU@&lFE4VS~?@hM)-?#5goA;o2{{KIBGC)IB7i_-y9>4wl%9Yf$eFxHw1Q`Sk*jzda z|JyHr&ThZ&?61#hrn@x#Xk;rT3wpRF4SlB$>ZzuAIbfenO8rak1MSy4>!~Gubjaf z?p@RDETcVz{b}GC@Aw!8FMzn7M?w0XB}_?x%S;@U*( z)jeyj&p-9-^VNqeqEat3%hs0I?_Ar{6T;2BPxlZ8`B)(KDKrWM;(V?$~qF$zn-5pP=iS<-1pJ-@beM^3}_CuhyRJ=@%_2 zsVVLz`t?b-wD$sYjqgqQ=QiD6Y+x03>U^c~wla}0=}@)9i`DNlpS7MBVm5VQfR5Oi zW)~}l;`HA~`_;1Qz6D4|#-F;V`}&h>kq?7N*V0!x!9U)JCpN4XQBm1<-!E#Ja@V4D z>vH_d!{hVAqf3lhs$b>U&pB=`k;q)zFDPpD6e= z(ageT&IhLTiE7z@=WspW(EZ6kT1HY*?c|>A3=cH*7=JEwihIxGw#mc3ec#lHU9S%= zV73G-k)`B8gyH;}2$!X^ z?st6St~q+M!CN)^@f@!28@L%(OwnSUbf%hnLV=E()f$}uombP(6z$B(a|)A`3|U!u z(y#NWU}RyKX{h$pm~$p`xfd_ywY;<9dC<+9BEGJt7?m0im2T~y>L9*qzH8Lq=fyk! zW^b>IKYP1BXt(sKr&)1VGE;*k(|#LFdbQqsee-&opv00b3!9y6 zH`QdCe0-sr^zeB*S6u$gHD#Y0C#6pe`u}^TAm6-M-|bFiZDk733+Fy$`E-xRR>u6@ zIz6vePIFplxIgNw&cel~qFGp})56fkW%d*Eif$xE5VSNJP$us(`dDH}Rl``ijH?e2ofVQy}#d`rWOtM^&7 z?GU_X{^{|GJ4b^~9hvp@MA6ZW7h_I-mWr3t485}YLc&U>%(#DErl}d9ukU}(nso7S z@aJobpX3`qE!t`jBBAB5)T)@Nyn3ns<|etAqROb4rBSUhdi?v+rrr5e+sR#Qw{_u+ zUk+cI%ga-D@7{DXXPR)ih-=SAjjmmrG_wOg9Zg!eW_Ctp#RisTzBA`+b#8avQs~!O zeZ%#6_hUPye@-t?PLkJhs7zUsBj0j-_xy<#3y;(k=B!DHTzdqv~JzwKjhJ8QmnYa0wZNHIyNW-Tpy9v+RxvqZlNIfQI z@qTJb$@-q2DQ}mCrff2te>!x^{^d47i~9Y{H>*YMyQ=oQ%5L%lhm;TZ=DmA+d;X1$ zk5?`)e|KkV_4j#utH1a4zrSle@8ptoYC1iSG)`2me3+H#vu}kc7wdf!g|jzj9#)F7 zUw)|gMyvhY_hOg2gWXn;Ce%PMQ9>q4}HViq3zTC&bOA z)=S6P%BsGI`dD)mcPpfY~kvW_GD~uB~TJ^H_>-(_dSLfT? z7?xgCou0h>c+Xz#I1i1(Q7pa41Ndz5lKhT+T7F02B$T)D|z3a{Tl{RxefTl?7 z9StnzAF~lSQ}CXX|7OlK!?5+&A6xLL+kj?+#AaAWE6QtFT;&RJgBmWwN)^{sU9y@{3>L6x!x?)~>2H{jIFY#m3D{X+ICN792V} zXWoYgt@&!7859aj_Z+_HF1z*BkH>W%?Dy}_esl4@{RbDR=5}E@9uC{yy+5aXT3o~4 zbn1jca_Wcmw>9z~No$@uQumYl5liPZxxM$eSqpXIr_P_bz4C%f@)FzKH|+zI=6o=C z9{qT>#e(aLTm++c{+aOq-%t56o4wz6EDoDf^+~W$Mtupdy3LP?`eNLo&wrO~w2a@E z@jk-)vdGtUESk|O=l*jF>DpCo73aFa&d1=en%(z|#OAsME*1|H_m#Ok6yT{-s5qec z>vwhdI*TRSmskH>$X@&T_jk9zE&r}Ae}8kgx}meh!-Xeji7vfW-MwUC(As6{^X?0) zL{)!D>Yr({dwXlMnvJ{L46WN%XAU60$@$dWo`unxt zx5l!wFXH{zb2$8+Wc&O(KQ9Qj>+gU3&OWcc=zZXMt1ovp_syR*$LqA1U&V)oMn+C2 zqO{`mOx~Vc(X(dz_O)KeZ00IlJhYg7-_4+fHaG6b3 zME?Je+kt+h+98qd*0n!Tb9D8~v{4!$jNJ{~zDeNO~Pt7$tMu_F)Tq^xG-IaxPaAG~Mt0 z|Gac#%iRd!2e&_6?XI+ST=dj^zJA}wi&mXSW?N+(D(-VRoNWH=xkG2cq2}csZ*Onc zkKZT5Ah0oPwg2_3;NZ)T9}8E1e|L9p`ulTpcW<}<_{5pte$vSlx!<3Y*WTOSlveQb z+tF{2zdn%hxBdF1`v3KAiR9_^k9PChfBW)Kd)nR~Kh=*F%J@}eEVZyTO@BR6KQHH; zsn(Y43gyq$O)j_l?c(pekUc%iHsjC<=W`Q1>NGxAfCFYZo47#nmB&?k?MzK=EiFwg zL11V8eHQ+l*Uwn_T%>D?ii%!Nnm2u3wGi_$iR!nf{SzA=wzTt!EZ?+D)>>!ol&2y8 z^?mKnt9xwu@uG8kR`AY8H(vS5n}7zgmHsX~^BffM?EgKQItq0>_QdsPe~nrjHhbQz zd9!96i|7&by|?!ICOZL1o7tW7?rp4nA-a6ulb`B;zV1{9(eLhUR-g0X!Xr+8Uy(ik z-v9HfXx3ipn7uYHHD!rU&A)X&T1%Q-y!-b}SiOSz)|U2_Pn*>$HWc@@L^Hdz|FjJN zWsu+6MO&7;w9c{EQT6)T{QKV;<{go?u!+_Y%imGwoPK)WtK|9nJ~_XCx#mpR$Caa9GI=1Pij?%T)rB*z3?>^7Z{}NhTIm7hpH~9@6fs&Fj{L*iK-f;c?;_vpt1E7wT z?zueO8LmEleswRsk=FgfnYt9^-9}iOP z_x@FHU3e&c|A(z2Z8ev7uhS6io_c&)=!y7w7s|igOfOztY+qgz+#)Q;G^^=9OQ-9% z7l#{#n127|Sk7G^Zs-S*pU}MDX#)II_v$jREvVzv>nnH`@8@{}l7M=I=$8r063Kx0G@4UaF$WV8dX(y=jD5%7caOKUsaH0J_pUu|a`DBuQ z-N){gE3I}vt^?Vb)EeiTQJZJ~eaFvdv+w_XS3bY!lqT<`(uCu+shZ|CijB9f$o;-m za^8Y#OZ^6rD;<(=7|;Cd`lxH)?4Sjct>2kjC@RW6Yx^~gNmup_c$D5q>`2sqe?HW;-}`ji{JZ}?@4mE2w<}rcmc@@nrn;vN@5@clQf_t%Fuv-vE$2z* z>0@=KX=kU{R^N1}v@Adsz*&rS+Zvw1?vp{OWGQGF+?iM$fWMD|xihaGhsf zygkv`;%9shpS*pWD{*38+<JZAyFeYzzven*$!M_I#M@}K|iNBN;If!Uk0D%p7!adpT_9% zPdM#d8GN*`Df*k8iTKnOkki>)zs;TM_VPyBw6*RV{{$R-y?c`Gku`Cba#H?QNF8P} zKXfp7^3<%U`@b0;YdbyFEA+0*&KO;e^x#_$?(6JHj!q0Ye^i94_owOf^V3f*E}hDL zq4uEHofJV?R@1}$F8W?(vtPbDRhGILGy{0jCGg1qcV073hD2;Q?y{x!gX`_1j+MbX zU2mOvUgWtrN^k!9u+vwyLQ_Xnw9UHao`JH;2mAJwnq`|B7 z8OytEmGjeBZFfBRv}K3aR<4~faS_7OiMEoKzE69dY&*G&jYA!6R0BmmN}gt(cyRab zO?P8&=9r!CwEk89c5Zb|$knYsuFte_oS@R6!M}Fq$;HKPr}t*8o{*Kz&B<}Y-EYUY z&#SjCc*?7^XzjN0v{j-!P7W?>9zFh6eA|hQWs%B??bo6MZ*y(CGV^3IgKpHG6Ur(o z6CBRn+i!m^`CRe6nI}`OeJ{5AIp=1&{k6I|Q)|E7OxNvhO_b<9I%#t5x`USw__|E# z(@)ZIjhu5g^l{fGIT4>#(l33s&0-Gk^{!f#_O`75^wO&_pK4Wg7&(P?6R%$WFsbLJ z$+Xfu^UDtpotpIPo2bve?0?o3Hgc8B-79Lo-qm@#&Mo&6#PXCD71b>Clx#NUI`=ZkH@xj^!rZv66K+2}YkXB^b;P!Z7JLeqboCx~ zn?}zUlUpUS|LMssvrTWAoZu2Jd>U8S@4oj&iiL5?+kKXoJ{ac5H6NTH7hJ&L>s|CU zZll(xSpv~#8<%XknRV{{NA&}VI^q6L7oIjaBeTM+#$Ru5PDoeiYU?X1gpDHXJ}wT<4E^YY!hcduT(dhx=hc-h}8 zD=(}2&B@8Ne)D;&jMWp{iVqilzpwxB?e_2g-?lr?o`3VtQStbeYZL5aK7BZz{%cm0 zK9_s4_xqdNOO6ziyYEsu5mgp9u=|N{B0CVwP4@@12Jxf0H-Glau^Ej zcdR+6`Cx|Q1eT_AffN5J{ZKPrZ1>7hfJKreqdY$4P@D*h8w>15(#p0M(&-9+uLv0*c8YtH&IoY z#phEI{36{}Gu(^x>*y0aw1Y|w)a&MY6WGEYC z>~{I(a8KdL`*4ZXms3}6xFwRhzhz~0NuBy5wLSHmUp@$I>sYg9&7C`U_UyUy=g*$g z?fmkFk3Jnb)U;^Pp~S;_-SG`RTXI-mJXB2M=l7Z|@5rhb?zLGaG3Mh3Zk1ctu7w<2 zV%scs{BKvwtEJp=&M2>k_UqE?ZN+y|uARnfh17^SIBNrSZp4qGCco z`NXich(F#7+S?0UBXp*n$_#!Vy|3o$ufT+w5Ic>hXp9<$2Q2St&J1*$D4D zDdND-UszEgaFt);+<~pf-Yc(MA1RWWEgk0Qyn*YsqrIll>IJLT-YHIrU1P4gl>6Zv zy|4@3RjP~3+(cdXzj!S-YeJnm&mFIf8u1&ZMn|5-Guhg-=r*O^jLzHn^x4VDt%nQm zmL?zX?cOs@G2rY$){R1w-aD|_+8hb)N_l$z#Iu$6e(Y6Le6?ER_@1r4s}z1tHi)P; zSi2xdW9dzY+T)o{HF@n@{zUO7ru6KJKXlDjX}>UAo@!66xJJjt{VY`#9HA_VDYbXo z-q-&BegDTX^ZmcB&Q|l?wQ$>| z=uFUan-mrZNoW>cjSKYIChzu7{Bv)`qlK@vPs#1t+Pf+BZCU0;uMMB%U0H2sEq$_J zxk={2Q29j~w;hzVpRW!4<~?JV`Vq@|9;$Xm;bqV z6aPO?>;JzJ>*5#qTUb?jbS4W0KbleU-~fC5&neSc^<+=}d1U|pv-#{gR?epvO{MEU zUVhqn);Q{wSx(23*=N4|Uv)3|utpf`geQ-St)Cqzdn>ko%WLt+Sxe;SNwwdI3 z@10riZi?55J2~Im`emZKeC?L6B?YHXo)y+Hzf+KWtTuGMr2N^%?d>7SZvvFg{!0Du zW4g!I_V!b!PQ6~g|KBG;<(B!*Z9I}zB^fzS4Y<4?Ovo$?yi{K#YxzQ2;phyDDIUw~ zJk=xF4O%Ar4!3jARBV}NU*Gt=(uw2zUuvLv^iL4mju;Q47Y`E~Dl1ONq?O?>@hNH5hMVf16jn!^izxW)J@YZd#D989CR(S% zm^7!TW%9_*vd>C!tc%MFeE4*C-2e8YNi&T<-`}?fWXN z@cN2bht8<%PuUb^A{m>zz1u13=x|6lp3~xvYzLgpC=e&e82sK-pj{)RZ!>qv_?DpFf*QE1 z-_&;F`~U2TkP}B$MaMde4{tuWEHqD)dyZRD+}qMc3|!lltdfnKDnRs=B&8cG~x~T|sOTZHez@l*uxS*xI@*3TwFH)OI6U;=}JmR3Xd7^JZ8Kb z$F`h1hOaI0*$@S`h8h{98H&_ts<=P$Wy~{+~Y&2ro$B8)H`1<1)Dui>ow!ubjT%U^^wTk`F&F+Pv}_vz3Z>O z?lg@Q0|{y75-vUkyTu;%U%m>>TkW#+Y*=w!zkM7l-=U^XlM>0cnao$)-k)4Lz1M4F z)}M6`-UY2}p6hol;D^Gk6StHm`F17;rSt!sf4KJ0$Fv8R>~H@(_;#`Tg5A4!Z{NOs z`EvJ9ixra|Emq&V;(3qE@f4G&^_EPT*8`4SbvP7o{%iH>mE8fqUcAKDRupLNm;3qR z#X{9S&s&kt7u@fdBq@J(`Aqf3lm$zM7R3=~0EPSiQ#X8GL^xw7UeBH=RPmYSm^N40Hu#Pq`_}Q<(F-c-Y2}8p}tBO^2 zk`=GlZl9(bU3RzhdTZzMtvl8i)oZNnYx%m1fuXAS_ray2cddFS?q@QdqINmt*@LsL zQ*+c?H=Fb;a0sO=*mH8q)pC~87E;~6*IbtT68ik(iEm#ISH)hKeLH-rqLg*OjAh0j z!UfoRS5_DZhMtLk>3HeRC7ULNjuQHtd}0C`yUUQy{GHd{&?7a==|>Y`>YqG ztSR1o`tgT~hR1XCzRPSs&zEPv-S*e?Ca>b(P7OacO<|sY+fe=2pR$UYGIj0;%qQnZ zPS9|@s^%`hGI64fjmHv~j&`}K6`=>u*L~X@u(4O?-R7$@6?fjfsHuB#=I!a0Z@UE8 zT2Iz12Y;Nj!s>oXj_L7L%I*o7a*h*x+;(?O`gFJDq2ZPt=dI?J^~Y(qx#Z`?>m53= zsZN5&_n-94uJqNGA1ZiiK6S-0iWE9W&2kq|dF<)_debsBGg0Bpb@STn!r7YMX}$gu zwEUy$;VsX??7v!OHk(*p4k#34aTJlr_|Rz2ZGPZ++3(ofg$E@ZC-@{eym9U1pMU$H z0U!T%S^FFp0hP@j$3sPUcU)*t@MtsQcm_&MlF($9DzIjei{srk-ia=!RoYK*G%Ya% z^%@?if4?Vfb*T8f{d^fu0T#zcD#GD`_kKLyJ?rt=?f0vH-`&6G|Mlj?AT1fomhw{y zE`8T3nXT3voL+fMnQL*D#Li7=MX!A9rM9kKeoQCY*(ttPEvQO(k@Y0c3k}P675MjV z+id#isDADZrC)P>t~_8cNc>arQ{&$y)1})U8ATW7`JGS~^5+eHJpGPEg=N2U{^T&x z-Nz1Jz5HU1`GU_}&Nc5W<<4o>JwLVSpOmoRp%a=>Raa)u{J8UOUEgQ*8+DA~@1NR4 z&7R)eCvbP7NKGF5;}4cAPn6vd6j94?TX)~XNigw50Iy!cMuW){8?#Pxzp0} zX5_QN+Pv-UtEYbze0}F#lYv=Us=bI{^EvIF4{rl*?tVCDUBRhq4t@{kFMjx6_&y(h zfuB12qPcTg4qDCq=J8fwxvpS|`~Qc<=L>I6-FE*txY8hC&K&J|pO-|; zlR6d{ytr=F`HbhHY3FoIxMU8zE4fw5cGvj?CxdmC%)!V#Y=-sQZUwZijMdN>7E{Yt|B71T`bB)^ii4Xs zZ~pYTsO{NvKIvKZe>N#j=aro_fBN*vlPAx&R|zp{*4%pjx%is>oAmTU&#*K##;I#Z zYKvTRi}^QeLD1*Tw^zPeY1ceAyy8xfbmle7KX&tDljD0b--J#N!o0Nna7rtETbLGL#CN}v=)+HWsadB~Zd3kxQp#%;yZ!NI zyOw@ZJ1BMY(AkjZqGi**UUB)u*Rgs%|857tmi^csHynTb{D`Rb-OHgo691Z?ylQ?QZ=tuR?rM*1@_DUGz02fR zOcc48pR$PU{JC?d&YnDX^4z&oAh0Py=g|E*0{KR!{!bNl6?WYCmNR9;xwns;*6ld+ zqImb;jXY(+&qb$H#Ts&~U$xcbrAWH+#jaI;=dAWl$!oWq`0midIqL-8UohF5EY9=& z)#BI{Z#?|uxFWPJHhGnvl-Zht%tsy^SzvAQSKH=Mg-zYMS*xENc-|l1`1-w< z^2r?!?8U8D>zsT3z4`9Bri(W&_vEH7WShA2%HH=UTzKcro;-K<T2Y5A3bEy zb2RDXNxqHZt)*6${skRXSu%PBuHV*8+%WuSQ4p^6@9FP5dHrSOGajWXXK!bZH>td%ms-zuJdR~vs0p)a=6mCn zdAh2?rWJK@?@mr$er`^t{q2hvE8oS0mzRJ4`T6eM=bJYy@6 zg>#wXN+;WLd{wfvfKW?DyAecXMdI?(!? zQ&pIu%!+64jayeTDz*qXX)4-Ge88#NGD$*f?WM=6eV%h|zwo zYX248FJ8X9xhd5OOC8|8aeN?Z1oe`}Y5Rdx4$ZuIB&W{r_Ih z{r>O6wg3O#=C_;KZ~ob>zmH?BV*QRM5Btx5_|0^1@#6Mr7HX+?!oPO@$e6c!`Bzh( z!wee^&aBwqcuqUwdD*##D>g2lem=dBJ!sjP1MFrod(B_EiinBLv#l=s@!_FZH)}(b zj>F2-7Z((5{53c(7kP2KeD_XIB2b`sEljWzUlp?m3t-Eu}3U7 z=R7+%Vv@1T1jf^**JC!<|NnP6-LJhb%wW-jF70(4JExqv^x!3%)p`%hwtpdlDmIUg z_y4~%eczPXv$Hp{#G4!OIBTYgtkY=?{W@>nyc=F8Ie58ZU$9p8g;`hZY-y;+P_?Qyjee-sdlu=zeM)FJ1lfLeC2QrZ2*CpZ{i1X#E~| zinU|Ly(c2ZAEcESf7rjCW&TwvK__~<%aex>*Uewh&dy?(;8ADB5c9-1yn*8+Z=$OH z!ju-a{Wshi_+;nv`Nz!zIFdY0<@ZkEHn?zNihh*_tJ2rK z$M!a_fBGT6{O?cu>!vdHg>Dsx9afzD=ymo*VoyPc%{$}XWj!^EcUzX2Tvo~|bDwHZ zQSpqo_{y)VjdkU%b_SR3%+Sc1JHu(K`{&1f7wx|sxyOC*o5||FO&4pnnj0N_bY_;x zspRkci*xpxSlE1SQ{A_4k$ufpbFbP}yYAY2-eNw{ZO@OTrn*X*DP3&pA{9sL^Kb4w zd{tQOM%Vh<$8(k0_s*C9`DDt1gOyn&dxDIg>HR;o|H9+BUn-WDKhry|+yA?Q%jWAH z<2!+`uOIn-r+9k$wfc*X>kDu36dT+8c^CbzDZc#DD_rZ4OE#uFr@4Jj1s_%ZJ zDjxebPr-pBK(qd-W23I7@tIS9GQMq{wpsO1<;>!vvVm&+Vz~tYlc&1M_u2%T>`3FYE6Mn`Vj}C$%AKyQ)8AM9l^5$yJ$I)5^{aP6>!ki{&b{|B zirf4#pQ}gY*SAmqT}wOvr)k#p1Ka4}L%#ce5h|Hk~X`(X!q^b?MW8+|Kz5KH%y?hLZBLxx06o$3HUBO}MmVmR3gUg{{UP zQgbr9_giLuzWmQ#gF(0WUbtM&lZ4N!es6!6clCt0yX)rP+jcA0Ex9cJ>*E5cx&zZg z@85eg&27QD@6Gmy`TU;VUDcNp)Y7(Q%^J<%Wj=E(3LhQmoUG=%YR#IMjY&tR=|)e9 zKANmN*<^ex1%zQ5Ex{=pLOg9mC?N6f1b zyZ2_(UXT8H%iQmmZvA^><2`;GMy`F^HobNCzaGx|`H9)wZ+`dR?pQV_7u_+prM|CrITP9QVO{sS znaZNwSlU77C zt1aTntbLtdwx_K9J4npru1WO#JICJ_U7vbYTj@mm{;fyzbbA+ye|amp$jaeh_;xpu z+Y7$)&I$=;-R;I!YyEj?S#gB?Fj=^A|@-j=O?VNZ9SSGczAKu8ctGb^lTU+pV zj}&j7;f4474B@8UJKE=Zr~kecb>zwA^i8{(Zm7P$aKL)qfta+9c@NSHFMqFyQ$8Sk z{$AMiNs&p1QqNm=bAH&o<7JWB<{d8||)1uPZ+`;Lj_y=3k>^=k6;4XV{yTJt}=lyWJ( z?s}X17N|_Vz@fi`saRI}&o7^zSt0SPzRz}*J?p$1wl4SH7P}?CilpN=*{(TrwY4!wG&ra{!j>ev?q!0 z-o3hS`*v3lYM7uI6(J|kzN`1Gz? zwKE@0o1=M_Xvw-XRb5t?8Zu{dp6Kl@#}5nVebo9NymjBTsPcrc(v5lxAMRATaQ)gU zy>&NjYvpn*9HadzrcZhKSlVML*Tih!MyBl#S#kyYp6?7;v?|&mOStq?(DT*m8M1SO zjb=seidJ`6vv)zZ|KwL34^_{F&);tU_3Ny?ZmYa*FJaSN(2;iKoXyAWo=186lq2rX zJg2(W)Vo}}I_C2Jt5dIBzVRkA=jpPuYt}8U^C@gDx)AE&!6dB)cVW58FJ@g?!FBLV z@2#2nAG;fyp9Ywy?fzhS{b6l>nm0ku6_MMCvTOAuEjT}?`zaH zZR5CVRS_08&8;)oEB(w2M@`ih4gI5QZW_5ZbMH1~-LzRJ{rsFY^XmTQPF{O|oyN}G zqLVw<=`C$%f4q0T@oW1kzIXd4C9Y4op`G1l^Wg5*Nva|oPnVtjl)G3&XTBm<~XP16W`nU94>(Y7Gz2|a!eYKRH zADqw~{d_~X(VMmF9zDNu^lXV9({Rrnr_w%QI-R76!AD^s#j+mBls@wYc#sA%FcPwWAx1qNAkFVNcgPS*RP6?X# zeC4C3AB)f1|6gmlaQ~|BYowx?_bWi!@q@_sO`AfvCpGSg`n=cdxwiK2%O0C|b!=L6Z?d|-*Rg}mFLH&sVs;cf zL`>Pl|NC??taatB+3FE_J07<6{8&|&5f^se^&V5Cz|8jcg7|kuTmP?$H|_g*s%FEw zFYos3pPyU4eb@Zl;;ZM*Jb2&fJ$I|I?ET-Jf8Xy9ldAH~(?4={_Gj5>uUG%$X5ITc z<0u2ehn1_HdYI0vxqtJ1{1a(WMV|vx6%U=acz)N*$f>!$@=mJm{IU(#MQXmgbAJBt z;m%Bzo}~N7PWJKYzNvj*`M=iV|8%p4pWog0$V;=RFBcbb{+gdrx+=9}{ysYxNF_`O4`V!`F>gKMd^C`y|4Gy$G!2MEiK2u(AHD+=0q|>!JilT{mY}o zSQt;7O@s9@1Phr^XA2RdfM8rZ){B7ey=Lq(UH;jb-4pa(-Ft&>fhGy z_XNkp%*k@xB6TNeV}#DMHEVPd-!C|tGR_(_?VecdNyt zUJQ zruy}@;qyYm!tQN<^lzWtl?OAK6sM^FY1ni-Wn+Yvme#lT_vg=@J6GVdn&IRmUcD9X zJB8J+UAfZIt(U zj9pU8hx;}llbQsaI2V>2s6A?2@*-gS?YBicS(?=~Cn_G5syQ`9Gx=E0OpC&##Kgpo z8RB}Nta9jRH)u|AlA7G4D82nPI|?pcy}H)^0* znwGt}(J8EMW@_p?-_BOpv?4zK{=dJ!#dV`hik_TMbatvW(_7R0*`|N>{F%(>Ckv=s z2pO?EaooS|9+c60v?Fk_o23lj>Z@83zx}34XkL53@ZpT{`J8)uEbZ;D*hd^}N{E;5 zFaB_*@%hiy>vm<`*pN7DvZ8a_2b;bYo+kB{_m5ZJ`|Rtr@%G!~<9)jN`p+xlHi*p@ zG7S2o7JQ>-Q^m(e<@amNT}%@B?p?p${yq1Z1INy1v$EUx<=0tCT9vHW(5(#$A*W3% zZ8to7uypBC^LrJGA7rVw#xGq`XTEU3k>x%!g_45(;d~iriv46TUYu514c%yMSRw$;(MM{R$ep_ljFv zpBFqN{HH-Z`Gx0PS(6k7$3`xmC3oGKp9>nSl(PBse&v&VeOU)>TfyqU2O^{8r00q z%g@X()Vw$;k$dXZ?+V+yg>ElCzN7H*v0mxv1&IPIp4NJCduG%~FJ-=26BlIqW3&Dr zy_rW9IhuI#CM`c0{B(t!qd>|AqX%)^3LH%ef=yE3*<(lWbo06eZ0-Uqp5Xz_${bBg zv{xJyWO2MSHRZNz<*%2^?SH@79A{EF@!6B7PkZI<>rPHmT`9)mXf$g{)`weLvp;|S z6t*V9Fzd>Slxf{6bAp%q<=)@7x9sgL_VBe{pplZDDxuButtyMIt_o#kWqp2rzJJZ+=$niQ#VN&d^1FCwC%t=l+z6g=uD zzbP#^cqxApx9czFH|{K+mYN?vG?d#lDR^v=kn-?3nCCRB(PaJ3m&;7g{uQ@p`{L>n zneoY;uPMc%N_Aciub-ysKT~sYt~-0XRrvnTnw=l__e*0%K#%C&+QMZ3IY94Ga=buLd5U7B8I84t9b zPs!ie|Nmf7s)}!A>gsRr&7*EkEH>^I=(7F1?9I%*|F8TjVz^15qoyIkf4 ztSj=)J!+MNbRs=47_AYas zsDH@Aqz-{d$qO;jfq~K1;XiK1RQu<8d*>cq5h%L#lUGB`oHO%w7PUOP)fFhZwRfwi z=+?8R_Go9#p1RZaM}n(sZt(^k=gN?!L0lqUr%$zfz8Ss!oR~^xfO`0nX+ozRMYrk} z{eH3Pj!xU@n;nlbR^PdGDJUvTO?~3zZpALW3nEgIC*>_Unle1LvAuu&`t_SPZ{ECn z`tx4i!zD|9-r{xd%b9i2AU|(?!KP;$n~Q!3KD^Ywtu*iV#p~JK=CYPWPfqN6diHbO zmbIIAPtRZZ)z7x*iN{@YtK;YHZ`iXW<>x+S_iyLqZ);w-dwTnoy4o#Ao*d^Zt6Q9R zzi40C*KOyT`_JAD-I@RXk9Jk%zU{vsBo`mu)1RaD?O*K7=(7d$-oNFWrs}z3!t)dR zo~k;Py6iJ7bvwN0;$rvz8MA|gNrIJ|W?yBhJj%~ZN`sW7RdGxnB{rN%J z-CgNl-rl)(^XAWT{ra~SJ5y4pJ~!2m|I(WfeERIVKhmqj5+y9&?GjW`HmI69v&nKt z)yb(&C%<@UD~3gP)-ah!_;IXUHH)wDfOMn7$xW)EEdohv=fqvQv159`1Sg+qg_=`z zvUxmA^fn4Pt?@R~64y6$CD{yjXeb#g9szRk_f&d$EQd&`jx9E-K0a|Jj|%w)Gk=1vW5pDo4A7#%vbaB6N?w1R-a z`D;7k1SkKQ*sQ=|pk+I+Yp=#3JGO^s-njhp_^%cqs+ zgolN(&YE?rhbyZ(>)0l@mo@?$BG>+UG9@T_>4ymyuU!#YFePejn5MI9$F5T?5!%`> zm-#lH^3vWI7ItZw+NwE?t5q^{vV^*(&2l{x*10dh@n6tNrnKif#919D@h!IYJ{Tu* zXuafP*q8Y6&CRDzlTMfvStzIp ze$tKGvg1-+eC5vELg&Mvj@H61ABF?lb|ij$cvE}9Is4uNTXw1aKJzrpu^~yiHmWBh z`p$&_9}bV5cPrH$CI+-cOw)L{94+OPj~cQIb`uJpLsbmP#gD39<~ zy#*#3YcE`gy)SEbZO)uIA>2(0k}V64ObuSXBUKW8DL}W5gF8U3cvi7h! z;U!~g(WKz;FR$4gVg`D%XE6k8kr%(gtN@4Z#0^Wo;=yZisWR&;vtJ#R*WMB?eq=lNuf zQjT_sE_Unn+LZJ6$jad5+w$-4dwMfnTrWbv85FRS*1h?AywLmT*?7sB_WKJa_;}RM zHGgv9y4t(D|M$&gvoHSjWl!j8E-tQf^X=!S-2BzKXwf3j7~k7lTQ{n@^Y$scJk{AZ z?@glfbMY^6b0=p73LW{=KW6oK;$2P`d`mYBB$IVJht+4SqR`T9KGfB)WH`+oZRKZ$Mo z{%F9U%@w-xZC>T)vdcF)10GIsN|IKbWVBQ`#?^5`iQCR!0*{sV{3`$aDq3xQ zUS?eF=_gmS>ur*JE_N8YD!;p_+Zuf9(~;{f2Mi~NZx7&dke+h!k*ZSuYs05^?p$Et z-?zDR+n4HZ*Vb;<%w4xuLNzGxwohhpuB&VA+Ze-)cXEpFZ?a5hV_VUKh>i#qA3=PMYUb}kxnf~ji(PmZR@|HpDpvw2z#^(Do z?uD4H&%ZoT*|J+V60d8=mqzL7h-;rT*qv6(JTdu0_{Ev)nsf1j()K|I-~kZ$Iq+ zdhwC!o7p~I$=XYcJ__x6`7O2g()(knr=>KPZad|rt=O`~)RZ-4u2z?m=F%%sk)Gzc zlO{*5z1Hw(xs0yb%qKiaatxq?>?IGY6Q}%nEiMLsjrF{NE!xg&RKKju_pjk%II!!> z*ggH52%r zDzuQHaCXASMPIw0rc5pUx2x@e{|4Q>i1i+mN}zG4+9ITO&2vua&28aVr2;t^Ioeh` zC6t~%zIy2nmT8%bk1jvKk$A|@BU9%0!EW()-}FMn+?TEUTy=frqc`_-uP&-sSh3E_ zjblY|pjs#AoMvT@XHF|N95IyW*dV7l>ph~;quC9s)jl0u1{*t&k+2XCRkKdbnEu*;ZK;`&j=XE|?bvhekUYz`Sq5AjN@0qMVxlsvRDOTgpmF(@kLTI_=1HsARk`t>pZ#&_#x%YvhJ=Gn ztmkb$pE=emom|#waN)$slbSj@FDs0Y5We9W^-iFiK+bhZU~NO(N2scq&a& zz4Ydhw_N0}2}-N$Jl85_n!CQv&_0#Xyj4;&s;hI`RNy(Ec^Az|7Q!+Rd%-t z&8re6zwYqg)?E5o&&OBDUw~zZNL-fIY+>qhG0(g* zzphAR(H()C$28;SOueN1r@KR|Q`LsO-7^9?+*VA43DvFqjnlL~1$GvA~IK|lWnY;aorid*7_aGStcA*FqjDwc7c%$@zA zls8`dm_?XL?}D1u3xC$^@_!y2aL@g# q#n`04A!K~*R} diff --git a/doc/images/qtcreator-qt4-qtversions-win-symbian.png b/doc/images/qtcreator-qt4-qtversions-win-symbian.png index eaf9beaaa0060b34d69db6b3db8424375f6bd35e..ccde01f4d05265904bde4eccc61eaabb3d4416c6 100644 GIT binary patch literal 26937 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ðs(N zMa$m&`Td}eQa;J0rZbJ6KU;V1N$|;({|Tdd zMB1+#>Xz4k{=3>{`)8|6B%|w>yx`<(rkd*g4=1lVmc%|k<<8s#oe$jfcZ&(KzsYAhZ{AvOzG2$tZ>^?E*-{;gs{eMaQd_8Sps=;&ne=7?F85n+@|NHdnyhF#AajyP$`+QGa z<=danSr68IpBc20#kTrv<>#9h=LN02vibU-yIZfEul7>CksY^Xw&&imr(XVCd%CVI zyB@T|G(eyH6LBS#AbOI&8&I9_xri|_VK%K+~l|0#Kc>7d{(=mTdHWWOiRG& z(vlJ#UER00w!Xf$HhS$l@6hURZz7|jUcGp+Vn0`#41cKao_q$yD||woN3L8ES!y!Z zZ~HF&(7U_K^Ru$FCT2W{;sf6nXV6X{|e(xyjUgF^QsCD_(DWuT#5qQ^D`N)z(b{S;774a@nQgO09~^ zJGbS(zq4=e=Bs-hI2M*Q_GdWbsyjf|qjh?gh$^*Gr#>{f8*24=U*7(UxRasQ#Hifgy~zhD1$L49$rX+)`3LQv}Y=J&Zz z9&AmVld&qSe|kEEB~u^UX;6Pud!;@ss%Ft%xWLKh+f>M^E}b+jpdyG2d^z# z$>nufO-5<`??MZou2jW0iG@C0o(rP)SoT%QD(&(AT{wICWy?d%*AD7*}x&tcoS4IOPsp$h&U0O7!_d8||)1Dp9I$ol+kc1#LUf_a-WFcR~4s zrFs9%PILdV*HSxrb@Jpu^FG|lrnr* z-fVZ`1eLVz#TUYY-A_F1dVg!ykp|C2N-Mrq?hbjIBp7b7^|R8nvqkZ`!NI50 z;?}*s7jMD9AmI2Qh8@zgu&-9wXj6ZHz!u5zIEDU_pa-3cKAAh33RLV^#}J9eJfcg1}7vEw02 zYcfu6?VJ7n`^2DAOE#T1-Q{?*o`oYLiG@h(4+nM@JsN$38^uSuQC*eI~!U*B9^ zY3G%H&CkzRcS2;xy6S9AuI>MP?$!!A7EDsqzt17-@E_M zYh3Huw&~Y&W~be5yZ4wXse zocg)qO>whSY*Cq4o5n}~EqQJVh8xcPWR?$()DjG`Tk~{Rz4Y7uX-4l`lqNaeTyJ>R zG1^c1j*2f!&;f2a_N_U^y}B#&RsWF6?FaDlq_q#s@zcj#uQWA>dD2)f4plB%A9*U_w&aL=gD8E z#PhG3wd_@jc_0thf@`f2EoSSFIr9m!yo=$Vk#gtP?&4=bb|(+1JI2RwPFYy=VNv@V zpVx|;O(YjtO`g;7__aUBys4XH8dfb^CJ;M+yWOdaA$V+-dRkP3#7HZYNro_hp?h`XO~U zjMY^{eSh#y<+zLYA3Xe8x;pn&bXDJd;GjL`<+eyzfOGpYnK?~p`Y)<+IW{`pG~-Xb?eJ>SKr#K zJ9R7UGW*dbGnV}RcbmZ}+CAsVouk|DSM9xe*MUQEOX}Re50tepY>AxKEZ~&!`Vh)M zk~5zZ{zg1XLHwVEA>IDR3W&L1kNRBBDU}y+;;7aBW8Yw+KW8Cp(|-mA1_n=8KbLh* G2~7aQ!b1lD literal 27927 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 TFWSq%z`)??>gTe~DWM4ffH5#M delta 6101 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 Date: Thu, 10 Jun 2010 14:29:45 +0200 Subject: [PATCH 05/32] Doc - Add information about testing with user data on the Nokia N900. Reviewed-by: Christian Kamm --- doc/qtcreator.qdoc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4c910bed327..c5cd75ef06e 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -5995,6 +5995,13 @@ necessary software is installed and configured automatically and you only need to configure a connection to the device. + By default, you create the connection as the \e developer user. This + protects real user data on the device from getting corrupted during + testing. If you write applications that use Mobility APIs, you might want + to test them with real user data. To create a connection as a user, specify + the \gui Username and \gui Password in Qt Creator. For more information, see + \l{Testing with User Data}. + You can protect the connections between Qt Creator and the Maemo emulator or a device by using either a password or an SSH key. You must always use a password for the initial connection, but can then deploy an SSH @@ -6116,6 +6123,30 @@ \endlist + \section2 Testing with User Data + + To run your application as the default user, you must first assign a password + for the user account and then create the connection to the device as the + user: + + \list 1 + + \o On the device, in \gui Programs, select \c {X Terminal} to open a + terminal window. + + \o To switch to the root user, enter the following command: + \c{sudo gainroot} + + \o To specify the password, enter the following command: + \c {passwd user} + + \o In Qt Creator, Select \gui Tools > \gui Options... > \gui Projects > + \gui{Maemo Device Configurations}. + + \o Specify the username \c user and the password in the device configuration. + + \endlist + \section2 Generating SSH Keys If you do not have an SSH public and private key pair, you can generate it From 47165a9119ee789fda4889df06b6732044de1a3e Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 10 Jun 2010 14:30:31 +0200 Subject: [PATCH 06/32] Doc - Fixed punctuation. --- doc/qtcreator.qdoc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index c5cd75ef06e..2dae548c89e 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -2762,12 +2762,12 @@ \o Click \inlineimage{qtcreator-run.png} - to build the application for Qt Simulator. + to build the application and run it in Qt Simulator. \o To see the compilation progress, press \key{Alt+4} to open the \gui Compile Output pane. - The gui Build progress bar on the toolbar turns green when the project + The \gui Build progress bar on the toolbar turns green when the project is successfully built. The application opens in Qt Simulator. \image {qt-simulator.png} "Qt Simulator" @@ -5884,7 +5884,7 @@ \o On the device, install \c rootsh from the \gui {Application Manager}. - \o In \gui Programs, select \c {X Terminal} to open a terminal window + \o In \gui Programs, select \c {X Terminal} to open a terminal window. \o To switch to the root user, enter the following command: \c{sudo gainroot} @@ -5892,7 +5892,7 @@ \o To install Qt Mobility libraries, enter the following command: \c{apt-get install libqtm-*} - \o To confirm the installation, enter: \c Y. + \o To confirm the installation, enter: \c Y \o Close the terminal. @@ -6338,9 +6338,9 @@ \o The \l{http://tools.ext.nokia.com/trk/}{App TRK} application for your device \o The \e{qt_installer.sis} package installed on the device, that is - delivered with the Qt SDK. - \o Qt Mobility APIs installed on the device, if you use them in - applications. + delivered with the Qt SDK + \o \e {Qt Mobility APIs} installed on the device, if you use them in + applications \endlist To run your applications in the Symbian emulator, you also need From 273a3c14cb69ddaaa0058933ce25a5a76097b225 Mon Sep 17 00:00:00 2001 From: dt Date: Wed, 9 Jun 2010 15:07:41 +0200 Subject: [PATCH 07/32] Fix message shown on building --- src/plugins/projectexplorer/buildmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index 2a2ef6ec1d9..d8b7f539f6d 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -344,7 +344,7 @@ void BuildManager::nextStep() const QString projectName = m_currentBuildStep->buildConfiguration()->target()->project()->displayName(); QTextCharFormat textCharFormat; textCharFormat.setFontWeight(QFont::Bold); - addToOutputWindow(tr("Running build steps for project %2...") + addToOutputWindow(tr("Running build steps for project %1...") .arg(projectName), textCharFormat); m_previousBuildStepProject = m_currentBuildStep->buildConfiguration()->target()->project(); } From 6dc0faceb21ae19e8b18628b6a41183497a64163 Mon Sep 17 00:00:00 2001 From: dt Date: Wed, 9 Jun 2010 15:08:06 +0200 Subject: [PATCH 08/32] Make code thread safe again. --- src/plugins/qt4projectmanager/qmakestep.cpp | 15 +++++++++------ src/plugins/qt4projectmanager/qmakestep.h | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp index 12629bf2961..12cbf8ab28b 100644 --- a/src/plugins/qt4projectmanager/qmakestep.cpp +++ b/src/plugins/qt4projectmanager/qmakestep.cpp @@ -176,23 +176,26 @@ bool QMakeStep::init() setEnvironment(qt4bc->environment()); setOutputParser(new QMakeParser); + + Qt4Project *pro = qt4BuildConfiguration()->qt4Target()->qt4Project(); + QString proFile = pro->file()->fileName(); + m_tasks = qt4BuildConfiguration()->qtVersion()->reportIssues(proFile); + m_scriptTemplate = pro->rootProjectNode()->projectType() == ScriptTemplate; + return AbstractProcessStep::init(); } void QMakeStep::run(QFutureInterface &fi) { - Qt4Project *pro = qt4BuildConfiguration()->qt4Target()->qt4Project(); - if (pro->rootProjectNode()->projectType() == ScriptTemplate) { + if (m_scriptTemplate) { fi.reportResult(true); return; } // Warn on common error conditions: - QList issues = - qt4BuildConfiguration()->qtVersion()->reportIssues(qt4BuildConfiguration()->qt4Target()-> - qt4Project()->file()->fileName()); + bool canContinue = true; - foreach (const ProjectExplorer::Task &t, issues) { + foreach (const ProjectExplorer::Task &t, m_tasks) { addTask(t); if (t.type == Task::Error) canContinue = false; diff --git a/src/plugins/qt4projectmanager/qmakestep.h b/src/plugins/qt4projectmanager/qmakestep.h index 79156622d18..bc0de0f4b9a 100644 --- a/src/plugins/qt4projectmanager/qmakestep.h +++ b/src/plugins/qt4projectmanager/qmakestep.h @@ -110,6 +110,8 @@ private: bool m_forced; bool m_needToRunQMake; // set in init(), read in run() QStringList m_userArgs; + bool m_scriptTemplate; + QList m_tasks; }; From 15f2e4e98dbcbdf2001e402499979afe36f9bfcb Mon Sep 17 00:00:00 2001 From: dt Date: Wed, 9 Jun 2010 15:21:44 +0200 Subject: [PATCH 09/32] Don't reset build directory for clone cmake buildconfigurations --- src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index b69b5d4c833..d83c78166bf 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -62,7 +62,6 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(CMakeTarget *parent, CMakeBuild m_msvcVersion(source->m_msvcVersion) { cloneSteps(source); - m_buildDirectory = cmakeTarget()->defaultBuildDirectory(); } QVariantMap CMakeBuildConfiguration::toMap() const From 67de12279f821bff46c4bcec7e10523dc3935828 Mon Sep 17 00:00:00 2001 From: dt Date: Thu, 10 Jun 2010 14:18:20 +0200 Subject: [PATCH 10/32] Fix comment --- src/plugins/projectexplorer/taskwindow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h index 4dd8cba3a1b..7c8d6101b6b 100644 --- a/src/plugins/projectexplorer/taskwindow.h +++ b/src/plugins/projectexplorer/taskwindow.h @@ -76,7 +76,7 @@ struct PROJECTEXPLORER_EXPORT Task { QString file; int line; QString category; - // Having a QList in Task + // Having a QList in Task // isn't that great // It would be cleaner to split up the text into // the logical hunks and then assemble them again From cdbb7c6a851bd46eec35af989ab87c2f61c78bb0 Mon Sep 17 00:00:00 2001 From: dt Date: Thu, 10 Jun 2010 14:48:59 +0200 Subject: [PATCH 11/32] Remove Qt4 runconfigurations again which don't work. Task-Nr: QTCREATORBUG-1593 --- src/plugins/qt4projectmanager/qt4project.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 006352f4a01..ab57f72f593 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -313,6 +313,7 @@ bool Qt4Project::fromMap(const QVariantMap &map) updateFileList(); // This might be incorrect, need a full update updateCodeModel(); + createApplicationProjects(); foreach (Target *t, targets()) @@ -998,10 +999,26 @@ void Qt4Project::createApplicationProjects() target->removeRunConfiguration(rc); } + // We use the list twice + QList profiles = applicationProFiles(); + QStringList paths; + foreach (Qt4ProFileNode *pro, profiles) + paths << pro->path(); + + foreach (RunConfiguration *rc, target->runConfigurations()) { + if (Qt4RunConfiguration *qt4rc = qobject_cast(rc)) { + if (!paths.contains(qt4rc->proFilePath())) { + // A deleted .pro file? or a change template + // We do remove those though + target->removeRunConfiguration(rc); + } + } + } + // Only add new runconfigurations if there are none. if (target->runConfigurations().isEmpty()) { Qt4Target *qt4Target = static_cast(target); - foreach (Qt4ProFileNode *qt4proFile, applicationProFiles()) { + foreach (Qt4ProFileNode *qt4proFile, profiles) { qt4Target->addRunConfigurationForPath(qt4proFile->path()); } } From 61c1c59f8792667c69a47c035cbf24becb21b3c3 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 10 Jun 2010 11:55:40 +0200 Subject: [PATCH 12/32] QmlDesigner: Store imports in a list, not a set The order of imports does matter, therefore it should also be represented as a list in the model. Reviewed-by: Marco Bubke --- src/plugins/qmldesigner/designercore/include/model.h | 2 +- src/plugins/qmldesigner/designercore/model/model.cpp | 6 +++--- src/plugins/qmldesigner/designercore/model/model_p.h | 4 ++-- .../qmldesigner/designercore/model/texttomodelmerger.cpp | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 641c1cd5744..a8523623d9e 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -96,7 +96,7 @@ public: // Editing sub-components: // Imports: - QSet imports() const; + QList imports() const; void addImport(const Import &import); void removeImport(const Import &import); diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 3cfafe5008c..2a9fdaf199f 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -122,13 +122,13 @@ void ModelPrivate::addImport(const Import &import) if (m_imports.contains(import)) return; - m_imports.insert(import); + m_imports.append(import); notifyImportAdded(import); } void ModelPrivate::removeImport(const Import &import) { - if (!m_imports.remove(import)) + if (!m_imports.removeOne(import)) return; notifyImportRemoved(import); @@ -1004,7 +1004,7 @@ Model *Model::create(QString type, int major, int minor) // return subModel; //} -QSet Model::imports() const +QList Model::imports() const { return m_d->imports(); } diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index fcd38b37166..026f0b079af 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -154,7 +154,7 @@ public: // Imports: - QSet imports() const { return m_imports; } + QList imports() const { return m_imports; } void addImport(const Import &import); void removeImport(const Import &import); void notifyImportAdded(const Import &import) const; @@ -197,7 +197,7 @@ private: Model *m_q; MetaInfo m_metaInfo; - QSet m_imports; + QList m_imports; QList > m_viewList; QList m_selectedNodeList; QHash m_idNodeHash; diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 81a1dd18d62..909487cfcc6 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -491,7 +491,7 @@ bool TextToModelMerger::isActive() const void TextToModelMerger::setupImports(const Document::Ptr &doc, DifferenceHandler &differenceHandler) { - QSet existingImports = m_rewriterView->model()->imports(); + QList existingImports = m_rewriterView->model()->imports(); for (UiImportList *iter = doc->qmlProgram()->imports; iter; iter = iter->next) { UiImport *import = iter->import; @@ -510,13 +510,13 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc, const Import newImport = Import::createFileImport(strippedFileName, version, as); - if (!existingImports.remove(newImport)) + if (!existingImports.removeOne(newImport)) differenceHandler.modelMissesImport(newImport); } else { const Import newImport = Import::createLibraryImport(flatten(import->importUri), as, version); - if (!existingImports.remove(newImport)) + if (!existingImports.removeOne(newImport)) differenceHandler.modelMissesImport(newImport); } } From 644f98483a9bbf6dfd16af9563523c2a59b23c04 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 10 Jun 2010 11:58:23 +0200 Subject: [PATCH 13/32] QmlDesigner: Fix import handling in rewriter Task-number: BAUHAUS-602 Reviewed-by: Erik Verbruggen --- .../filemanager/changeimportsvisitor.cpp | 2 +- .../designercore/model/rewriteaction.cpp | 2 +- .../designercore/model/texttomodelmerger.cpp | 2 +- .../qml/qmldesigner/coretests/testcore.cpp | 125 ++++++++++++++++++ .../auto/qml/qmldesigner/coretests/testcore.h | 2 + .../auto/qml/qmldesigner/data/fx/imports.qml | 6 + 6 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 tests/auto/qml/qmldesigner/data/fx/imports.qml diff --git a/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp b/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp index c79e115af62..55534d5d9a2 100644 --- a/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp +++ b/src/plugins/qmldesigner/designercore/filemanager/changeimportsvisitor.cpp @@ -62,7 +62,7 @@ bool ChangeImportsVisitor::add(QmlJS::AST::UiProgram *ast, const Import &import) if (!c.isSpace() && c != QLatin1Char(';')) break; } - replace(insertionPoint, 0, QLatin1String("\n") + import.toString(false)); + replace(insertionPoint+1, 0, QLatin1String("\n") + import.toString(false)); } else { replace(0, 0, import.toString(false) + QLatin1String("\n\n")); } diff --git a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp index 6475137688b..1d344887ad5 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriteaction.cpp @@ -369,7 +369,7 @@ QString AddImportRewriteAction::info() const bool RemoveImportRewriteAction::execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &/*positionStore*/) { - const bool result = refactoring.addImport(m_import); + const bool result = refactoring.removeImport(m_import); if (!result) qDebug() << "*** RemoveImportRewriteAction::execute failed in changeImports (" diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 909487cfcc6..6288aabe5f3 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -514,7 +514,7 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc, differenceHandler.modelMissesImport(newImport); } else { const Import newImport = - Import::createLibraryImport(flatten(import->importUri), as, version); + Import::createLibraryImport(flatten(import->importUri), version, as); if (!existingImports.removeOne(newImport)) differenceHandler.modelMissesImport(newImport); diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.cpp b/tests/auto/qml/qmldesigner/coretests/testcore.cpp index b3a36212ce4..8ff2caba1bc 100644 --- a/tests/auto/qml/qmldesigner/coretests/testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/testcore.cpp @@ -767,6 +767,131 @@ void TestCore::testRewriterActionCompression() QCOMPARE(textEdit.toPlainText(), expected); } +void TestCore::testRewriterImports() +{ + QString fileName = QString(QTCREATORDIR) + "/tests/auto/qml/qmldesigner/data/fx/imports.qml"; + QFile file(fileName); + QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); + + QPlainTextEdit textEdit; + textEdit.setPlainText(file.readAll()); + NotIndentingTextEditModifier modifier(&textEdit); + + QScopedPointer model(Model::create("Qt/Item")); + model->setFileUrl(QUrl::fromLocalFile(fileName)); + + QScopedPointer testRewriterView(new TestRewriterView()); + testRewriterView->setTextModifier(&modifier); + model->attachView(testRewriterView.data()); + + QVERIFY(testRewriterView->errors().isEmpty()); + + QVERIFY(model->imports().size() == 3); + + // import Qt 4.7 + Import import = model->imports().at(0); + QVERIFY(import.isLibraryImport()); + QCOMPARE(import.url(), QString("Qt")); + QVERIFY(import.hasVersion()); + QCOMPARE(import.version(), QString("4.7")); + QVERIFY(!import.hasAlias()); + + // import "subitems" + import = model->imports().at(1); + QVERIFY(import.isFileImport()); + QCOMPARE(import.file(), QString("subitems")); + QVERIFY(!import.hasVersion()); + QVERIFY(!import.hasAlias()); + + // import org.webkit 1.0 as Web + import = model->imports().at(2); + QVERIFY(import.isLibraryImport()); + QCOMPARE(import.url(), QString("org.webkit")); + QVERIFY(import.hasVersion()); + QCOMPARE(import.version(), QString("1.0")); + QVERIFY(import.hasAlias()); + QCOMPARE(import.alias(), QString("Web")); +} + +void TestCore::testRewriterChangeImports() +{ + const QLatin1String qmlString("\n" + "import Qt 4.7\n" + "\n" + "Rectangle {}\n"); + + QPlainTextEdit textEdit; + textEdit.setPlainText(qmlString); + NotIndentingTextEditModifier modifier(&textEdit); + + QScopedPointer model(Model::create("Qt/Rectangle")); + + QScopedPointer testRewriterView(new TestRewriterView(0, RewriterView::Amend)); + testRewriterView->setTextModifier(&modifier); + model->attachView(testRewriterView.data()); + + QVERIFY(testRewriterView->errors().isEmpty()); + + // + // Add / Remove an import in the model + // + Import webkitImport = Import::createLibraryImport("org.webkit", "1.0"); + model->addImport(webkitImport); + + const QLatin1String qmlWithImport("\n" + "import Qt 4.7\n" + "import org.webkit 1.0\n" + "\n" + "Rectangle {}\n"); + QCOMPARE(textEdit.toPlainText(), qmlWithImport); + + model->removeImport(webkitImport); + + QCOMPARE(model->imports().size(), 1); + QCOMPARE(model->imports().first(), Import::createLibraryImport("Qt", "4.7")); + + QCOMPARE(textEdit.toPlainText(), qmlString); + + + // + // Add / Remove an import in the model (with alias) + // + webkitImport = Import::createLibraryImport("org.webkit", "1.0", "Web"); + model->addImport(webkitImport); + + const QLatin1String qmlWithAliasImport("\n" + "import Qt 4.7\n" + "import org.webkit 1.0 as Web\n" + "\n" + "Rectangle {}\n"); + QCOMPARE(textEdit.toPlainText(), qmlWithAliasImport); + + model->removeImport(webkitImport); + + QCOMPARE(model->imports().size(), 1); + QCOMPARE(model->imports().first(), Import::createLibraryImport("Qt", "4.7")); + + QCOMPARE(textEdit.toPlainText(), qmlString); + + + // + // Add / Remove an import in text + // + textEdit.setPlainText(qmlWithImport); + QCOMPARE(model->imports().size(), 2); + QCOMPARE(model->imports().first(), Import::createLibraryImport("Qt", "4.7")); + QCOMPARE(model->imports().last(), Import::createLibraryImport("org.webkit", "1.0")); + + textEdit.setPlainText(qmlWithAliasImport); + QCOMPARE(model->imports().size(), 2); + QCOMPARE(model->imports().first(), Import::createLibraryImport("Qt", "4.7")); + QCOMPARE(model->imports().last(), Import::createLibraryImport("org.webkit", "1.0", "Web")); + + textEdit.setPlainText(qmlString); + QCOMPARE(model->imports().size(), 1); + QCOMPARE(model->imports().first(), Import::createLibraryImport("Qt", "4.7")); +} + void TestCore::testRewriterForGradientMagic() { const QLatin1String qmlString("\n" diff --git a/tests/auto/qml/qmldesigner/coretests/testcore.h b/tests/auto/qml/qmldesigner/coretests/testcore.h index 685a1e6a729..3f29d22be15 100644 --- a/tests/auto/qml/qmldesigner/coretests/testcore.h +++ b/tests/auto/qml/qmldesigner/coretests/testcore.h @@ -129,6 +129,8 @@ private slots: void testRewriterGroupedProperties(); void testRewriterPreserveOrder(); void testRewriterActionCompression(); + void testRewriterImports(); + void testRewriterChangeImports(); // // unit tests QmlModelNodeFacade/QmlModelState diff --git a/tests/auto/qml/qmldesigner/data/fx/imports.qml b/tests/auto/qml/qmldesigner/data/fx/imports.qml new file mode 100644 index 00000000000..0c528046e0f --- /dev/null +++ b/tests/auto/qml/qmldesigner/data/fx/imports.qml @@ -0,0 +1,6 @@ +import Qt 4.7 +import "subitems" +import org.webkit 1.0 as Web + +Rectangle { +} From 2fa6d31ab4dcbbba52797a8b31a483393ce1a7be Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 10 Jun 2010 13:36:45 +0200 Subject: [PATCH 14/32] QuickDesigner: Automatically use alias of namespace in Rewriter E.g. if the type of the node is 'Qt/Image', version 4, 6, search through the list of imports to find 'Qt'. If an alias for the namespace has been defined, prepend this to the element name. Reviewed-by: Erik Verbruggen --- .../designercore/model/qmltextgenerator.cpp | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp index 8ad16ab0b5e..f912214db8f 100644 --- a/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmltextgenerator.cpp @@ -35,6 +35,7 @@ #include "nodelistproperty.h" #include "qmltextgenerator.h" #include "variantproperty.h" +#include "model.h" using namespace QmlDesigner; using namespace QmlDesigner::Internal; @@ -122,11 +123,31 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept QString QmlTextGenerator::toQml(const ModelNode &node, int indentDepth) const { QString type = node.type(); - int lastSlashIndex = type.lastIndexOf('/'); - if (lastSlashIndex != -1) - type = type.mid(lastSlashIndex + 1); + QString url; + if (type.contains('/')) { + QStringList nameComponents = type.split("/"); + url = nameComponents.first(); + type = nameComponents.last(); + } - QString result = type; + QString alias; + if (!url.isEmpty()) { + const QString &versionUrl = QString("%1.%2").arg(QString::number(node.majorVersion()), QString::number(node.minorVersion())); + foreach (const Import &import, node.model()->imports()) { + if (import.url() == url + && import.version() == versionUrl) { + alias = import.alias(); + break; + } + } + } + + QString result; + + if (!alias.isEmpty()) + result = alias + "."; + + result += type; result += QLatin1String(" {\n"); const int propertyIndentDepth = indentDepth + 4; From 010e6a9ed5101c8fcea737283e96e317121fcc9f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 10 Jun 2010 12:03:43 +0200 Subject: [PATCH 15/32] Revert "QmlDesigner: crash fix for copy and paste" Enable correct handling of imports again. This reverts commit de610cac45f227d7c15015000d6e32d5dc614e09. --- .../components/integration/designdocumentcontroller.cpp | 2 +- src/plugins/qmldesigner/designercore/model/modelmerger.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp index 5c38be2dcbd..f68dfa0fef4 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp @@ -459,7 +459,7 @@ void DesignDocumentController::deleteSelected() void DesignDocumentController::copySelected() { - QScopedPointer model(Model::create("import Qt 4.7; Qt/Rectangle")); + QScopedPointer model(Model::create("Qt/Rectangle")); model->setMetaInfo(m_d->model->metaInfo()); model->setFileUrl(m_d->model->fileUrl()); diff --git a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp index 922e8c88e3b..7e9290cda76 100644 --- a/src/plugins/qmldesigner/designercore/model/modelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelmerger.cpp @@ -170,9 +170,8 @@ void ModelMerger::replaceModel(const ModelNode &modelNode) { RewriterTransaction transaction(view()->beginRewriterTransaction()); - foreach (const Import &import, modelNode.model()->imports()) { - //view()->model()->addImport(import); //### - } + foreach (const Import &import, modelNode.model()->imports()) + view()->model()->addImport(import); view()->model()->setFileUrl(modelNode.model()->fileUrl()); ModelNode rootNode(view()->rootModelNode()); From c2a618ae2fd70885b1fea98e2b9e0251cce56806 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 10 Jun 2010 13:02:45 +0200 Subject: [PATCH 16/32] QmlDesigner: Add missing imports when doing drag&drop from the library Fixes a crash when drag&dropping e.g. the WebView element to a file which doesn't already import the org.webkit package. --- .../designercore/model/qmlmodelview.cpp | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp index d11d5f93ab0..ad888c5ae49 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp @@ -98,6 +98,24 @@ QmlItemNode QmlModelView::createQmlItemNodeFromImage(const QString &imageName, c QmlItemNode newNode; RewriterTransaction transaction = beginRewriterTransaction(); { + const QString newImportUrl = QLatin1String("Qt"); + const QString newImportVersion = QLatin1String("4.7"); + Import newImport = Import::createLibraryImport(newImportUrl, newImportVersion); + + foreach (const Import &import, model()->imports()) { + if (import.isLibraryImport() + && import.url() == newImport.url() + && import.version() == newImport.version()) { + // reuse this import + newImport = import; + break; + } + } + + if (!model()->imports().contains(newImport)) { + model()->addImport(newImport); + } + QList > propertyPairList; propertyPairList.append(qMakePair(QString("x"), QVariant( round(position.x(), 4)))); propertyPairList.append(qMakePair(QString("y"), QVariant( round(position.y(), 4)))); @@ -111,7 +129,7 @@ QmlItemNode QmlModelView::createQmlItemNodeFromImage(const QString &imageName, c } propertyPairList.append(qMakePair(QString("source"), QVariant(relativeImageName))); - newNode = createQmlItemNode("Qt/Image",4, 7, propertyPairList); + newNode = createQmlItemNode("Qt/Image", 4, 7, propertyPairList); parentNode.nodeAbstractProperty("data").reparentHere(newNode); Q_ASSERT(newNode.isValid()); @@ -146,10 +164,29 @@ QmlItemNode QmlModelView::createQmlItemNode(const ItemLibraryEntry &itemLibraryE Q_ASSERT(parentNode.isValid()); - QmlItemNode newNode; RewriterTransaction transaction = beginRewriterTransaction(); { + if (itemLibraryEntry.typeName().contains('.')) { + const QString newImportUrl = itemLibraryEntry.typeName().split('/').first(); + const QString newImportVersion = QString("%1.%2").arg(QString::number(itemLibraryEntry.majorVersion()), QString::number(itemLibraryEntry.minorVersion())); + Import newImport = Import::createLibraryImport(newImportUrl, newImportVersion); + + foreach (const Import &import, model()->imports()) { + if (import.isLibraryImport() + && import.url() == newImport.url() + && import.version() == newImport.version()) { + // reuse this import + newImport = import; + break; + } + } + + if (!model()->imports().contains(newImport)) { + model()->addImport(newImport); + } + } + QList > propertyPairList; propertyPairList.append(qMakePair(QString("x"), QVariant(round(position.x(), 4)))); propertyPairList.append(qMakePair(QString("y"), QVariant(round(position.y(), 4)))); From e80a4b962f096b006ca01761fad485f475813fd1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Jun 2010 16:20:01 +0200 Subject: [PATCH 17/32] VCS[svn]: Incomplete environment passed to Subversion process. Fixes breakage introduced by 34982c1f2361be0428a00007e7b0dea310a0b315. Task-number: QTCREATORBUG-1612 Reviewed-by: dt --- src/plugins/subversion/subversionplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 60173d28d06..824fec09be0 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -1062,7 +1062,7 @@ SubversionResponse SubversionPlugin::runSvn(const QString &workingDir, Utils::SynchronousProcess process; if (!workingDir.isEmpty()) process.setWorkingDirectory(workingDir); - QProcessEnvironment env = process.processEnvironment(); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(QLatin1String("LANG"), QString(QLatin1Char('C'))); process.setProcessEnvironment(env); process.setTimeout(timeOut); From 24f07b7a72a0f07068a63b6b576cce51609dfc7f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Jun 2010 17:03:02 +0200 Subject: [PATCH 18/32] fix wildcard expansion, etc. under windows raw strings would break things due to the missing null terminator. this did not affect unix, as there we convert to 8 bit anyway. Task-number: QTCREATORBUG-1364 --- src/shared/proparser/ioutils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp index f43c29aa9ae..5ed9ea50220 100644 --- a/src/shared/proparser/ioutils.cpp +++ b/src/shared/proparser/ioutils.cpp @@ -46,7 +46,7 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName) { Q_ASSERT(fileName.isEmpty() || isAbsolutePath(fileName)); #ifdef Q_OS_WIN - DWORD attr = GetFileAttributesW((WCHAR*)fileName.constData()); + DWORD attr = GetFileAttributesW((WCHAR*)fileName.utf16()); if (attr == INVALID_FILE_ATTRIBUTES) return FileNotFound; return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FileIsDir : FileIsRegular; From 35263628d13a3b02fd48eb3fe4077211bab938d9 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 10 Jun 2010 17:36:14 +0200 Subject: [PATCH 19/32] Add script function to the model This is needed to suppert inline script function of Qml in the designer --- .../components/formeditor/formeditorview.cpp | 8 ++++- .../components/formeditor/formeditorview.h | 1 + .../components/integration/componentview.cpp | 1 + .../components/integration/componentview.h | 2 +- .../designdocumentcontrollerview.cpp | 5 ++++ .../designdocumentcontrollerview.h | 1 + .../components/navigator/navigatorview.cpp | 5 ++++ .../components/navigator/navigatorview.h | 1 + .../propertyeditor/propertyeditor.cpp | 5 ++++ .../propertyeditor/propertyeditor.h | 1 + .../stateseditor/stateseditorview.cpp | 9 ++++++ .../stateseditor/stateseditorview.h | 2 +- .../designercore/include/abstractview.h | 2 ++ .../designercore/include/forwardview.h | 8 +++++ .../designercore/include/modelnode.h | 4 +++ .../designercore/include/nodeinstanceview.h | 2 ++ .../designercore/include/rewriterview.h | 1 + .../instances/nodeinstanceview.cpp | 4 +++ .../designercore/model/internalnode.cpp | 10 +++++++ .../designercore/model/internalnode_p.h | 5 ++++ .../qmldesigner/designercore/model/model.cpp | 30 +++++++++++++++++++ .../qmldesigner/designercore/model/model_p.h | 4 +++ .../designercore/model/modelnode.cpp | 10 +++++++ .../designercore/model/rewriterview.cpp | 4 +++ .../designercore/model/viewlogger.cpp | 6 ++++ .../designercore/model/viewlogger.h | 1 + 26 files changed, 129 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index 1904c0bec20..3488be937ab 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -235,7 +235,7 @@ FormEditorWidget *FormEditorView::widget() const void FormEditorView::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId) { - nodeInstanceView()->nodeIdChanged(node, newId, oldId); + QmlModelView::nodeIdChanged(node, newId, oldId); } void FormEditorView::selectedNodesChanged(const QList &selectedNodeList, @@ -258,6 +258,12 @@ void FormEditorView::selectedNodesChanged(const QList &selectedNodeLi m_scene->update(); } +void FormEditorView::scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList) +{ + QmlModelView::scriptFunctionsChanged(node, scriptFunctionList); +} + + AbstractFormEditorTool* FormEditorView::currentTool() const { return m_currentTool; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h index 1c7d787c351..4123ffdd7e0 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h @@ -77,6 +77,7 @@ public: void selectedNodesChanged(const QList &selectedNodeList, const QList &lastSelectedNodeList); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); // FormEditorView FormEditorWidget *widget() const; diff --git a/src/plugins/qmldesigner/components/integration/componentview.cpp b/src/plugins/qmldesigner/components/integration/componentview.cpp index 8d52c3c4a2e..af8a9181e8f 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.cpp +++ b/src/plugins/qmldesigner/components/integration/componentview.cpp @@ -159,6 +159,7 @@ void ComponentView::propertiesRemoved(const QList& /*propertyL void ComponentView::variantPropertiesChanged(const QList& /*propertyList*/, PropertyChangeFlags /*propertyChange*/) {} void ComponentView::bindingPropertiesChanged(const QList& /*propertyList*/, PropertyChangeFlags /*propertyChange*/) {} void ComponentView::rootNodeTypeChanged(const QString &/*type*/, int /*majorVersion*/, int /*minorVersion*/) {} +void ComponentView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) {} diff --git a/src/plugins/qmldesigner/components/integration/componentview.h b/src/plugins/qmldesigner/components/integration/componentview.h index f4f553d6ef8..b1028b23e2f 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.h +++ b/src/plugins/qmldesigner/components/integration/componentview.h @@ -66,7 +66,7 @@ public: void variantPropertiesChanged(const QList& propertyList, PropertyChangeFlags propertyChange); void bindingPropertiesChanged(const QList& propertyList, PropertyChangeFlags propertyChange); void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion); - + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); void selectedNodesChanged(const QList &selectedNodeList, diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp index e3d695d8885..dc5244f79f3 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp @@ -56,6 +56,11 @@ void DesignDocumentControllerView::selectedNodesChanged(const QList & void DesignDocumentControllerView::nodeOrderChanged(const NodeListProperty & /*listProperty*/, const ModelNode & /*movedNode*/, int /*oldIndex*/) {}; +void DesignDocumentControllerView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) +{ +} + + static QStringList arrayToStringList(const QByteArray &byteArray) { QString str(QString::fromLatin1(byteArray)); diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h index 7a167555883..9632c3569a2 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h +++ b/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h @@ -57,6 +57,7 @@ public: const QList &lastSelectedNodeList); virtual void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex); + virtual void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); ModelNode insertModel(const ModelNode &modelNode) { return m_modelMerger.insertModel(modelNode); } diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index bdbdd634878..44e940b3a6d 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -186,6 +186,11 @@ void NavigatorView::auxiliaryDataChanged(const ModelNode &node, const QString & } } +void NavigatorView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) +{ +} + + void NavigatorView::nodeOrderChanged(const NodeListProperty &/*listProperty*/, const ModelNode &node, int /*oldIndex*/) { if (m_treeModel->isInTree(node)) diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h index 791498297c6..27ffbb47bc8 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.h +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h @@ -80,6 +80,7 @@ public: void selectedNodesChanged(const QList &selectedNodeList, const QList &lastSelectedNodeList); void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); private slots: diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp index 613f2272888..b4061b1d2b4 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp @@ -798,6 +798,11 @@ void PropertyEditor::nodeIdChanged(const ModelNode& node, const QString& newId, } } +void PropertyEditor::scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList) +{ + QmlModelView::scriptFunctionsChanged(node, scriptFunctionList); +} + void PropertyEditor::select(const ModelNode &node) { if (QmlItemNode(node).isValid()) diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h index a3e0bb65710..70cdedda179 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.h @@ -101,6 +101,7 @@ public: void bindingPropertiesChanged(const QList& propertyList, PropertyChangeFlags propertyChange); void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); protected: void timerEvent(QTimerEvent *event); diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index 0c76cd254fe..6b0834fed7d 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -399,6 +399,15 @@ void StatesEditorView::customNotification(const AbstractView * view, const QStri QmlModelView::customNotification(view, identifier, nodeList, data); } +void StatesEditorView::scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList) +{ + if (debug) + qDebug() << __FUNCTION__; + + QmlModelView::scriptFunctionsChanged(node, scriptFunctionList); +} + + QPixmap StatesEditorView::renderState(int i) { if (debug) diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h index cab2badec75..9e5098c76f4 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h @@ -57,7 +57,6 @@ public: void nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName); -protected: // AbstractView void modelAttached(Model *model); void modelAboutToBeDetached(Model *model); @@ -76,6 +75,7 @@ protected: void otherPropertyChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName); void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); protected: diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 155f18eaff3..1351f83e922 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -129,6 +129,8 @@ public: virtual void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data); + virtual void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList) = 0; + QmlModelView *toQmlModelView(); void changeRootNodeType(const QString &type, int majorVersion, int minorVersion); diff --git a/src/plugins/qmldesigner/designercore/include/forwardview.h b/src/plugins/qmldesigner/designercore/include/forwardview.h index 7edeae303ca..a08dcda19c9 100644 --- a/src/plugins/qmldesigner/designercore/include/forwardview.h +++ b/src/plugins/qmldesigner/designercore/include/forwardview.h @@ -76,6 +76,7 @@ public: void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); protected: void appendView(ViewType *view); @@ -245,6 +246,13 @@ void ForwardView::auxiliaryDataChanged(const ModelNode &node, const QS view->auxiliaryDataChanged(ModelNode(node, view.data()), name, data); } +template + void ForwardView::scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList) +{ + foreach (const ViewTypePointer &view, m_targetViewList) + view->scriptFunctionsChanged(node, scriptFunctionList); +} + template void ForwardView::appendView(ViewType *view) { diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h index 1e6ec3b3db0..8d0e9033203 100644 --- a/src/plugins/qmldesigner/designercore/include/modelnode.h +++ b/src/plugins/qmldesigner/designercore/include/modelnode.h @@ -135,6 +135,10 @@ public: bool hasNodeProperty(const QString &name) const; bool hasNodeListProperty(const QString &name) const; + + void setScriptFunctions(const QStringList &scriptFunctionList); + QStringList scriptFunctions() const; + //### void destroy(); diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h index 6483f55c7b8..64835fbe367 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h @@ -84,6 +84,8 @@ public: void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId); void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex); void selectedNodesChanged(const QList &selectedNodeList, const QList &lastSelectedNodeList); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); + QList instances() const; NodeInstance instanceForNode(const ModelNode &node); diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h index 2e4cd1e0257..77875ff64fb 100644 --- a/src/plugins/qmldesigner/designercore/include/rewriterview.h +++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h @@ -124,6 +124,7 @@ public: void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex); void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion); void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); void importAdded(const Import &import); void importRemoved(const Import &import); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 39876a08a78..443c189d0c9 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -374,6 +374,10 @@ void NodeInstanceView::selectedNodesChanged(const QList &/*selectedNo { } +void NodeInstanceView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) +{ + +} //\} diff --git a/src/plugins/qmldesigner/designercore/model/internalnode.cpp b/src/plugins/qmldesigner/designercore/model/internalnode.cpp index 21183fdaab2..19d53860048 100644 --- a/src/plugins/qmldesigner/designercore/model/internalnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/internalnode.cpp @@ -311,5 +311,15 @@ bool operator <(const InternalNode::Pointer &firstNode, const InternalNode::Poin return firstNode.data() < secondNode.data(); } +void InternalNode::setScriptFunctions(const QStringList &scriptFunctionList) +{ + m_scriptFunctionList = scriptFunctionList; +} + +QStringList InternalNode::scriptFunctions() const +{ + return m_scriptFunctionList; +} + } } diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h index 840744738d6..8c5e317e487 100644 --- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h +++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "internalproperty.h" #include "internalvariantproperty.h" #include "internalbindingproperty.h" @@ -112,6 +113,9 @@ public: QList allSubNodes() const; QList allDirectSubNodes() const; + void setScriptFunctions(const QStringList &scriptFunctionList); + QStringList scriptFunctions() const; + protected: Pointer internalPointer() const; void setInternalWeakPointer(const Pointer &pointer); @@ -133,6 +137,7 @@ private: bool m_valid; QHash m_namePropertyHash; + QStringList m_scriptFunctionList; }; uint qHash(const InternalNodePointer& node); diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 2a9fdaf199f..7c0bc1d90f2 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -531,6 +531,29 @@ void ModelPrivate::notifyBindingPropertiesChanged(const QList &view, m_viewList) { + Q_ASSERT(view != 0); + + + ModelNode node(internalNodePointer, model(), view.data()); + try { + view->scriptFunctionsChanged(node, scriptFunctionList); + } catch (RewritingException &e) { + description = e.description(); + resetModel = true; + } + } + if (resetModel) { + resetModelByRewriter(description); + } +} + + void ModelPrivate::notifyVariantPropertiesChanged(const InternalNodePointer &internalNodePointer, const QStringList& propertyNameList, AbstractView::PropertyChangeFlags propertyChange) { bool resetModel = false; @@ -840,6 +863,13 @@ void ModelPrivate::changeRootNodeType(const QString &type, int majorVersion, int notifyRootNodeTypeChanged(type, majorVersion, minorVersion); } +void ModelPrivate::setScriptFunctions(const InternalNode::Pointer &internalNode, const QStringList &scriptFunctionList) +{ + internalNode->setScriptFunctions(scriptFunctionList); + + notifyScriptFunctionsChanged(internalNode, scriptFunctionList); +} + void ModelPrivate::changeNodeOrder(const InternalNode::Pointer &internalParentNode, const QString &listPropertyName, int from, int to) { InternalNodeListProperty::Pointer nodeList(internalParentNode->nodeListProperty(listPropertyName)); diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index 026f0b079af..f678e362db7 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -132,6 +132,7 @@ public: void notifyPropertiesAboutToBeRemoved(const QList &propertyList); void notifyBindingPropertiesChanged(const QList &propertyList, AbstractView::PropertyChangeFlags propertyChange); void notifyVariantPropertiesChanged(const InternalNodePointer &internalNodePointer, const QStringList& propertyNameList, AbstractView::PropertyChangeFlags propertyChange); + void notifyScriptFunctionsChanged(const InternalNodePointer &internalNodePointer, const QStringList &scriptFunctionList); void notifyNodeOrderChanged(const InternalNodeListPropertyPointer &internalListPropertyPointer, const InternalNodePointer &internalNodePointer, int oldIndex); void notifyAuxiliaryDataChanged(const InternalNodePointer &internalNode, const QString &name, const QVariant &data); @@ -140,6 +141,8 @@ public: void notifyCustomNotification(const AbstractView *senderView, const QString &identifier, const QList &nodeList, const QList &data); + + void setSelectedNodes(const QList &selectedNodeList); void clearSelectedNodes(); QList selectedNodes() const; @@ -176,6 +179,7 @@ public: void checkPropertyName(const QString &propertyName); void clearParent(const InternalNodePointer &internalNode); void changeRootNodeType(const QString &type, int majorVersion, int minorVersion); + void setScriptFunctions(const InternalNodePointer &internalNode, const QStringList &scriptFunctionList); InternalNodePointer nodeForId(const QString &id) const; bool hasId(const QString &id) const; diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index ec8c6e36515..722f93777f3 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -908,4 +908,14 @@ bool ModelNode::hasAuxiliaryData(const QString &name) const return internalNode()->hasAuxiliaryData(name); } +void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList) +{ + model()->m_d->setScriptFunctions(internalNode(), scriptFunctionList); +} + +QStringList ModelNode::scriptFunctions() const +{ + return internalNode()->scriptFunctions(); +} + } diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index 71746b7f062..8cc7575269e 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -352,6 +352,10 @@ void RewriterView::customNotification(const AbstractView * /*view*/, const QStri } } +void RewriterView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) +{ +} + void RewriterView::selectedNodesChanged(const QList & /* selectedNodeList, */, const QList & /*lastSelectedNodeList */) { } diff --git a/src/plugins/qmldesigner/designercore/model/viewlogger.cpp b/src/plugins/qmldesigner/designercore/model/viewlogger.cpp index 1cb8a1b4e5e..3e4d33852d5 100644 --- a/src/plugins/qmldesigner/designercore/model/viewlogger.cpp +++ b/src/plugins/qmldesigner/designercore/model/viewlogger.cpp @@ -194,6 +194,12 @@ void ViewLogger::customNotification(const AbstractView *view, const QString &ide m_output << time() << indent("data: ") << variant.toString() << endl; } +void ViewLogger::scriptFunctionsChanged(const ModelNode &node, const QStringList &/*scriptFunctionList*/) +{ + m_output << time() << indent("function scripts changed:") << node << endl; + +} + } // namespace Internal } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/model/viewlogger.h b/src/plugins/qmldesigner/designercore/model/viewlogger.h index 321e41fce5a..cdadd623734 100644 --- a/src/plugins/qmldesigner/designercore/model/viewlogger.h +++ b/src/plugins/qmldesigner/designercore/model/viewlogger.h @@ -70,6 +70,7 @@ public: void auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data); void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data); + void scriptFunctionsChanged(const ModelNode &node, const QStringList &scriptFunctionList); protected: QString time() const; From 49edd8208a9eb79ae360e2570b2a232ef856d447 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 9 Jun 2010 15:18:59 +0200 Subject: [PATCH 20/32] QmlDesigner: Switch 'only select items with content' off by default Reviewed-by: Marco Bubke Task-id: QTCREATORBUG-1493 --- .../qmldesigner/components/formeditor/formeditorwidget.cpp | 2 +- src/plugins/qmldesigner/components/formeditor/selectiontool.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp index cde79f3dd96..6c125bc5d4b 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp @@ -123,7 +123,7 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view) m_selectOnlyContentItemsAction->setShortcut(Qt::Key_S); m_selectOnlyContentItemsAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); m_selectOnlyContentItemsAction->setCheckable(true); - m_selectOnlyContentItemsAction->setChecked(true); + m_selectOnlyContentItemsAction->setChecked(false); m_selectOnlyContentItemsAction->setIcon(QPixmap(":/icon/selection/selectonlycontentitems.png")); addAction(m_selectOnlyContentItemsAction.data()); diff --git a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp index 7c42af95bb4..b4175612f6a 100644 --- a/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/selectiontool.cpp @@ -50,7 +50,7 @@ SelectionTool::SelectionTool(FormEditorView *editorView) m_singleSelectionManipulator(editorView), m_selectionIndicator(editorView->scene()->manipulatorLayerItem()), m_resizeIndicator(editorView->scene()->manipulatorLayerItem()), - m_selectOnlyContentItems(true) + m_selectOnlyContentItems(false) { // view()->setCursor(Qt::CrossCursor); } From ae9da516acb8d1762430aafd7d3006901d7e0c8c Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 10 Jun 2010 16:31:26 +0200 Subject: [PATCH 21/32] Don't overwrite bindings --- .../components/formeditor/movemanipulator.cpp | 77 ++++++++++++------- .../components/formeditor/movemanipulator.h | 8 +- .../formeditor/resizemanipulator.cpp | 45 +++++++---- .../components/formeditor/resizemanipulator.h | 2 + .../designercore/include/qmlitemnode.h | 6 +- .../instances/qmlgraphicsitemnodeinstance.cpp | 6 ++ .../designercore/model/qmlitemnode.cpp | 27 ++----- 7 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp index b318a3037f2..76df3d4ecc1 100644 --- a/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.cpp @@ -145,15 +145,29 @@ void MoveManipulator::begin(const QPointF &beginPoint) -QPointF MoveManipulator::findSnappingOffset(const QList &boundingRectList) +QPointF MoveManipulator::findSnappingOffset(const QHash &boundingRectHash) { QPointF offset; QMap verticalOffsetMap; - foreach (const QRectF &boundingRect, boundingRectList) { - double verticalOffset = m_snapper.snappedVerticalOffset(boundingRect); - if (verticalOffset < std::numeric_limits::max()) - verticalOffsetMap.insert(qAbs(verticalOffset), verticalOffset); + QMap horizontalOffsetMap; + + QHashIterator hashIterator(boundingRectHash); + while(hashIterator.hasNext()) { + hashIterator.next(); + FormEditorItem *formEditorItem = hashIterator.key(); + QRectF boundingRect = hashIterator.value(); + if (!formEditorItem->qmlItemNode().hasBindingProperty("x")) { + double verticalOffset = m_snapper.snappedVerticalOffset(boundingRect); + if (verticalOffset < std::numeric_limits::max()) + verticalOffsetMap.insert(qAbs(verticalOffset), verticalOffset); + } + + if (!formEditorItem->qmlItemNode().hasBindingProperty("y")) { + double horizontalOffset = m_snapper.snappedHorizontalOffset(boundingRect); + if (horizontalOffset < std::numeric_limits::max()) + horizontalOffsetMap.insert(qAbs(horizontalOffset), horizontalOffset); + } } @@ -161,15 +175,6 @@ QPointF MoveManipulator::findSnappingOffset(const QList &boundingRectLis offset.rx() = verticalOffsetMap.begin().value(); - - QMap horizontalOffsetMap; - foreach (const QRectF &boundingRect, boundingRectList) { - double horizontalOffset = m_snapper.snappedHorizontalOffset(boundingRect); - if (horizontalOffset < std::numeric_limits::max()) - horizontalOffsetMap.insert(qAbs(horizontalOffset), horizontalOffset); - } - - if (!horizontalOffsetMap.isEmpty()) offset.ry() = horizontalOffsetMap.begin().value(); @@ -177,22 +182,33 @@ QPointF MoveManipulator::findSnappingOffset(const QList &boundingRectLis } -void MoveManipulator::generateSnappingLines(const QList &boundingRectList) +void MoveManipulator::generateSnappingLines(const QHash &boundingRectHash) { - m_graphicsLineList = m_snapper.generateSnappingLines(boundingRectList, + m_graphicsLineList = m_snapper.generateSnappingLines(boundingRectHash.values(), m_layerItem.data(), m_snapper.transformtionSpaceFormEditorItem()->sceneTransform()); } -QList MoveManipulator::tanslatedBoundingRects(const QList &boundingRectList, const QPointF& offsetVector) +QHash MoveManipulator::tanslatedBoundingRects(const QHash &boundingRectHash, const QPointF& offsetVector) { - QList translatedBoundingRectList; - foreach (const QRectF &boundingRect, boundingRectList) - translatedBoundingRectList.append(boundingRect.translated(offsetVector)); + QHash translatedBoundingRectHash; - return translatedBoundingRectList; + QHashIterator hashIterator(boundingRectHash); + while(hashIterator.hasNext()) { + QPointF alignedOffset(offsetVector); + hashIterator.next(); + FormEditorItem *formEditorItem = hashIterator.key(); + QRectF boundingRect = hashIterator.value(); + if (formEditorItem->qmlItemNode().hasBindingProperty("x")) + alignedOffset.setX(0); + if (formEditorItem->qmlItemNode().hasBindingProperty("y")) + alignedOffset.setY(0); + translatedBoundingRectHash.insert(formEditorItem, boundingRect.translated(offsetVector)); + } + + return translatedBoundingRectHash; } @@ -220,8 +236,8 @@ void MoveManipulator::update(const QPointF& updatePoint, Snapping useSnapping, S } if (useSnapping == UseSnapping || useSnapping == UseSnappingAndAnchoring) { - offsetVector -= findSnappingOffset(tanslatedBoundingRects(m_beginItemRectHash.values(), offsetVector)); - generateSnappingLines(tanslatedBoundingRects(m_beginItemRectHash.values(), offsetVector)); + offsetVector -= findSnappingOffset(tanslatedBoundingRects(m_beginItemRectHash, offsetVector)); + generateSnappingLines(tanslatedBoundingRects(m_beginItemRectHash, offsetVector)); } foreach (FormEditorItem* item, m_itemList) { @@ -255,7 +271,7 @@ void MoveManipulator::update(const QPointF& updatePoint, Snapping useSnapping, S anchors.setMargin(AnchorLine::VerticalCenter, m_beginVerticalCenterHash.value(item) + offsetVector.y()); } - item->qmlItemNode().setPosition(positionInContainerSpace); + setPosition(item->qmlItemNode(), positionInContainerSpace); } else { item->qmlItemNode().modelNode().variantProperty("x").setValue(qRound(positionInContainerSpace.x())); item->qmlItemNode().modelNode().variantProperty("y").setValue(qRound(positionInContainerSpace.y())); @@ -345,8 +361,8 @@ void MoveManipulator::moveBy(double deltaX, double deltaY) anchors.setMargin(AnchorLine::VerticalCenter, anchors.instanceMargin(AnchorLine::VerticalCenter) + deltaY); } - item->qmlItemNode().setPosition(QPointF(item->qmlItemNode().instanceValue("x").toDouble() + deltaX, - item->qmlItemNode().instanceValue("y").toDouble() + deltaY)); + setPosition(item->qmlItemNode(), QPointF(item->qmlItemNode().instanceValue("x").toDouble() + deltaX, + item->qmlItemNode().instanceValue("y").toDouble() + deltaY)); } } @@ -381,4 +397,13 @@ bool MoveManipulator::isActive() const return m_isActive; } +void MoveManipulator::setPosition(QmlItemNode itemNode, const QPointF &position) +{ + if (!itemNode.hasBindingProperty("x")) + itemNode.setVariantProperty("x", qRound(position.x())); + + if (!itemNode.hasBindingProperty("y")) + itemNode.setVariantProperty("y", qRound(position.y())); +} + } diff --git a/src/plugins/qmldesigner/components/formeditor/movemanipulator.h b/src/plugins/qmldesigner/components/formeditor/movemanipulator.h index 976a4e71ac0..00d7f847e03 100644 --- a/src/plugins/qmldesigner/components/formeditor/movemanipulator.h +++ b/src/plugins/qmldesigner/components/formeditor/movemanipulator.h @@ -86,19 +86,21 @@ public: protected: void setOpacityForAllElements(qreal opacity); - QPointF findSnappingOffset(const QList &boundingRectList); + QPointF findSnappingOffset(const QHash &boundingRectHash); void deleteSnapLines(); - QList tanslatedBoundingRects(const QList &boundingRectList, const QPointF& offset); + QHash tanslatedBoundingRects(const QHash &boundingRectHash, const QPointF& offset); QPointF calculateBoundingRectMovementOffset(const QPointF& updatePoint); QRectF boundingRect(FormEditorItem* item, const QPointF& updatePoint); - void generateSnappingLines(const QList &boundingRectList); + void generateSnappingLines(const QHash &boundingRectHash); void updateHashes(); bool itemsCanReparented() const; + void setPosition(QmlItemNode itemNode, const QPointF &position); + private: Snapper m_snapper; QWeakPointer m_layerItem; diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp index 4fe8ffd1ae5..7229c786245 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.cpp @@ -146,7 +146,7 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.height() < minimumHeight) boundingRect.setHeight(minimumHeight); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { @@ -186,8 +186,8 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.height() < minimumHeight) boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); - formEditorItem->qmlItemNode().setPositionWithBorder(m_beginToParentTransform.map(boundingRect.topLeft())); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); + setPosition(formEditorItem->qmlItemNode(), m_beginToParentTransform.map(boundingRect.topLeft())); if (anchors.instanceHasAnchor(AnchorLine::Top)) { @@ -227,8 +227,8 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.width() < minimumWidth) boundingRect.setWidth(minimumWidth); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); - formEditorItem->qmlItemNode().setPositionWithBorder(m_beginToParentTransform.map(boundingRect.topLeft())); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); + setPosition(formEditorItem->qmlItemNode(), m_beginToParentTransform.map(boundingRect.topLeft())); if (anchors.instanceHasAnchor(AnchorLine::Top)) { anchors.setMargin(AnchorLine::Top, @@ -267,8 +267,8 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.width() < minimumWidth) boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); - formEditorItem->qmlItemNode().setPositionWithBorder(m_beginToParentTransform.map(boundingRect.topLeft())); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); + setPosition(formEditorItem->qmlItemNode(), m_beginToParentTransform.map(boundingRect.topLeft())); if (anchors.instanceHasAnchor(AnchorLine::Left)) { anchors.setMargin(AnchorLine::Left, @@ -297,7 +297,7 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.height() < minimumHeight) boundingRect.setHeight(minimumHeight); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { anchors.setMargin(AnchorLine::Bottom, @@ -321,8 +321,8 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.height() < minimumHeight) boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); - formEditorItem->qmlItemNode().setPositionWithBorder(m_beginToParentTransform.map(boundingRect.topLeft())); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); + setPosition(formEditorItem->qmlItemNode(), m_beginToParentTransform.map(boundingRect.topLeft())); if (anchors.instanceHasAnchor(AnchorLine::Top)) { anchors.setMargin(AnchorLine::Top, @@ -346,7 +346,7 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.width() < minimumWidth) boundingRect.setWidth(minimumWidth); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); if (anchors.instanceHasAnchor(AnchorLine::Right)) { @@ -371,8 +371,8 @@ void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) if (boundingRect.width() < minimumWidth) boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); - formEditorItem->qmlItemNode().setSize(boundingRect.size()); - formEditorItem->qmlItemNode().setPositionWithBorder(m_beginToParentTransform.map(boundingRect.topLeft())); + setSize(formEditorItem->qmlItemNode(), boundingRect.size()); + setPosition(formEditorItem->qmlItemNode(), m_beginToParentTransform.map(boundingRect.topLeft())); if (anchors.instanceHasAnchor(AnchorLine::Left)) { anchors.setMargin(AnchorLine::Left, @@ -503,4 +503,23 @@ void ResizeManipulator::clear() removeHandle(); } +void ResizeManipulator::setSize(QmlItemNode itemNode, const QSizeF &size) +{ + int penWidth = (itemNode.instancePenWidth() / 2) * 2; + + if (!itemNode.hasBindingProperty("width")) + itemNode.setVariantProperty("width", qRound(size.width()) - penWidth); + + if (!itemNode.hasBindingProperty("height")) + itemNode.setVariantProperty("height", qRound(size.height()) - penWidth); +} + +void ResizeManipulator::setPosition(QmlItemNode itemNode, const QPointF &position) +{ + if (!itemNode.hasBindingProperty("x")) + itemNode.setVariantProperty("x", qRound(position.x()) + (itemNode.instancePenWidth() / 2)); + + if (!itemNode.hasBindingProperty("y")) + itemNode.setVariantProperty("y", qRound(position.y()) + (itemNode.instancePenWidth() / 2)); +} } diff --git a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h index c673563e07f..43a73910dab 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h +++ b/src/plugins/qmldesigner/components/formeditor/resizemanipulator.h @@ -68,6 +68,8 @@ protected: bool isInvalidSize(const QSizeF & size); void deleteSnapLines(); ResizeHandleItem *resizeHandle(); + void setSize(QmlItemNode itemNode, const QSizeF &size); + void setPosition(QmlItemNode itemNode, const QPointF &position); private: Snapper m_snapper; diff --git a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h index 07f0d48889b..28e927af089 100644 --- a/src/plugins/qmldesigner/designercore/include/qmlitemnode.h +++ b/src/plugins/qmldesigner/designercore/include/qmlitemnode.h @@ -71,13 +71,11 @@ public: QTransform instanceSceneTransform() const; QPointF instancePosition() const; QSizeF instanceSize() const; + int instancePenWidth() const; + void paintInstance(QPainter *painter) const; - void setSize(const QSizeF &size); - void setPosition(const QPointF &position); - void setPositionWithBorder(const QPointF &position); - void selectNode(); void deselectNode(); bool isSelected() const; diff --git a/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp index 4f7c39d9db4..121b6e03113 100644 --- a/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/qmlgraphicsitemnodeinstance.cpp @@ -196,6 +196,9 @@ QRectF QmlGraphicsItemNodeInstance::boundingRect() const void QmlGraphicsItemNodeInstance::setPropertyVariant(const QString &name, const QVariant &value) { + if (name == "state") + return; // states are only set by us + if (name == "height") { if (value.isValid()) m_hasHeight = true; @@ -215,6 +218,9 @@ void QmlGraphicsItemNodeInstance::setPropertyVariant(const QString &name, const void QmlGraphicsItemNodeInstance::setPropertyBinding(const QString &name, const QString &expression) { + if (name == "state") + return; // states are only set by us + GraphicsObjectNodeInstance::setPropertyBinding(name, expression); } diff --git a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp index c9e22350802..746d3ffa916 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlitemnode.cpp @@ -191,34 +191,17 @@ QSizeF QmlItemNode::instanceSize() const return nodeInstance().size(); } +int QmlItemNode::instancePenWidth() const +{ + return nodeInstance().penWidth(); +} + void QmlItemNode::paintInstance(QPainter *painter) const { if (nodeInstance().isValid()) nodeInstance().paint(painter); } -void QmlItemNode::setSize(const QSizeF &size) -{ - int penWidth = (nodeInstance().penWidth() / 2) * 2; - RewriterTransaction transaction = qmlModelView()->beginRewriterTransaction(); - setVariantProperty("width", qRound(size.width()) - penWidth); - setVariantProperty("height", qRound(size.height()) - penWidth); -} - -void QmlItemNode::setPosition(const QPointF &position) -{ - RewriterTransaction transaction = qmlModelView()->beginRewriterTransaction(); - setVariantProperty("x", qRound(position.x())); - setVariantProperty("y", qRound(position.y())); -} - -void QmlItemNode::setPositionWithBorder(const QPointF &position) -{ - RewriterTransaction transaction = qmlModelView()->beginRewriterTransaction(); - setVariantProperty("x", qRound(position.x()) + (nodeInstance().penWidth() / 2)); - setVariantProperty("y", qRound(position.y()) + (nodeInstance().penWidth() / 2)); -} - void QmlItemNode::selectNode() { modelNode().selectNode(); From bf33e654aa0cde3f896a6707689ea5761cbf6970 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 9 Jun 2010 14:52:33 +0200 Subject: [PATCH 22/32] Get in component and connect every signal to the signal watcher This is improving the updating. --- .../instances/nodeinstancesignalspy.cpp | 28 +++++++++++++++++++ .../instances/nodeinstancesignalspy.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp index f28a8768ab5..d47bf05fe37 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.cpp @@ -26,10 +26,16 @@ void NodeInstanceSignalSpy::setObjectNodeInstance(const ObjectNodeInstance::Poin void NodeInstanceSignalSpy::registerObject(QObject *spiedObject, const QString &prefix) { + if (registeredObjectList.contains(spiedObject)) // prevent cycles + return; + + registeredObjectList.append(spiedObject); for (int index = QObject::staticMetaObject.propertyOffset(); index < spiedObject->metaObject()->propertyCount(); index++) { QMetaProperty metaProperty = spiedObject->metaObject()->property(index); + + // handle dot properties and connect the signals to the object if (metaProperty.isReadable() && !metaProperty.isWritable() && QDeclarativeMetaType::isQObject(metaProperty.userType())) { @@ -43,6 +49,28 @@ void NodeInstanceSignalSpy::registerObject(QObject *spiedObject, const QString & m_indexPropertyHash.insert(methodeOffset, prefix + metaProperty.name()); methodeOffset++; } + + // search recursive in objects + if (metaProperty.isReadable() + && metaProperty.isWritable() + && QDeclarativeMetaType::isQObject(metaProperty.userType())) { + QObject *propertyObject = QDeclarativeMetaType::toQObject(metaProperty.read(spiedObject)); + if (propertyObject) + registerObject(propertyObject, prefix + metaProperty.name() + "/"); + } + + // search recursive in objects list + if (metaProperty.isReadable() + && QDeclarativeMetaType::isList(metaProperty.userType())) { + QDeclarativeListReference list(spiedObject, metaProperty.name()); + if (list.canCount() && list.canAt()) { + for (int i = 0; i < list.count(); i++) { + QObject *propertyObject = list.at(i); + if (propertyObject) + registerObject(propertyObject, prefix + metaProperty.name() + "/"); + } + } + } } } diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h index ff33b8cdbef..94cef6d2321 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstancesignalspy.h @@ -27,6 +27,7 @@ protected: private: int methodeOffset; QHash m_indexPropertyHash; + QObjectList registeredObjectList; ObjectNodeInstanceWeakPointer m_objectNodeInstance; }; From 9d7a054c6bcc8599001027e6706b2d19ee77ee12 Mon Sep 17 00:00:00 2001 From: dt Date: Thu, 10 Jun 2010 18:02:38 +0200 Subject: [PATCH 23/32] Fix escaped output in the compile output window --- src/plugins/projectexplorer/abstractprocessstep.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index a6d5c13bd9f..64983b99729 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -248,7 +248,7 @@ void AbstractProcessStep::stdOutput(const QString &line) if (m_outputParserChain) m_outputParserChain->stdOutput(line); QTextCharFormat textCharFormat; - emit addOutput(Qt::escape(line), textCharFormat); + emit addOutput(line, textCharFormat); } void AbstractProcessStep::processReadyReadStdError() From 20764c225b5cd623e4541c0bd9ccbd5f14fb6006 Mon Sep 17 00:00:00 2001 From: dt Date: Thu, 10 Jun 2010 18:04:31 +0200 Subject: [PATCH 24/32] Fix double output in compile output window --- src/plugins/projectexplorer/buildmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index d8b7f539f6d..272e38e0bed 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -151,8 +151,8 @@ void BuildManager::cancel() disconnect(m_currentBuildStep, SIGNAL(addTask(ProjectExplorer::Task)), this, SLOT(addToTaskWindow(ProjectExplorer::Task))); - disconnect(m_currentBuildStep, SIGNAL(addOutput(QString)), - this, SLOT(addToOutputWindow(QString))); + disconnect(m_currentBuildStep, SIGNAL(addOutput(QString, QTextCharFormat)), + this, SLOT(addToOutputWindow(QString, QTextCharFormat))); decrementActiveBuildSteps(m_currentBuildStep->buildConfiguration()->target()->project()); m_progressFutureInterface->setProgressValueAndText(m_progress*100, "Build canceled"); //TODO NBS fix in qtconcurrent @@ -191,8 +191,8 @@ void BuildManager::clearBuildQueue() decrementActiveBuildSteps(bs->buildConfiguration()->target()->project()); disconnect(bs, SIGNAL(addTask(ProjectExplorer::Task)), this, SLOT(addToTaskWindow(ProjectExplorer::Task))); - disconnect(bs, SIGNAL(addOutput(QString)), - this, SLOT(addToOutputWindow(QString))); + disconnect(bs, SIGNAL(addOutput(QString, QTextCharFormat)), + this, SLOT(addToOutputWindow(QString, QTextCharFormat))); } m_buildQueue.clear(); From 2592e6eed0265970086c967d80e22287257452e1 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Jun 2010 17:58:23 +0200 Subject: [PATCH 25/32] non-python: fix dumping of structs inside qt containers Reviewed-by: hjk --- src/plugins/debugger/gdb/classicgdbengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp index 5bed94cc426..1ac4432e210 100644 --- a/src/plugins/debugger/gdb/classicgdbengine.cpp +++ b/src/plugins/debugger/gdb/classicgdbengine.cpp @@ -813,7 +813,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item, data.type = tr(""); } else { // A structure. Hope there's nothing else... - data.exp = parent.exp + '.' + data.name.toLatin1(); + data.exp = '(' + parent.exp + ")." + data.name.toLatin1(); } if (hasDebuggingHelperForType(data.type)) { From 5221e8eff99d266d3d4ccd03de6e8e9724296b63 Mon Sep 17 00:00:00 2001 From: ck Date: Fri, 11 Jun 2010 11:58:12 +0200 Subject: [PATCH 26/32] Maemo: Make packaging step optional. Reviewed-by: kh1 --- .../qt-maemo/maemopackagecreationstep.cpp | 12 ++++-- .../qt-maemo/maemopackagecreationstep.h | 4 ++ .../qt-maemo/maemopackagecreationwidget.cpp | 8 ++++ .../qt-maemo/maemopackagecreationwidget.h | 1 + .../qt-maemo/maemopackagecreationwidget.ui | 39 +++++++++++++++++-- 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp index 0a007795970..d0bd214c8ab 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.cpp @@ -59,6 +59,8 @@ #include #include +namespace { const QLatin1String PackagingEnabledKey("Packaging Enabled"); } + using namespace ProjectExplorer::Constants; using ProjectExplorer::BuildConfiguration; using ProjectExplorer::BuildStepConfigWidget; @@ -69,14 +71,16 @@ namespace Internal { MaemoPackageCreationStep::MaemoPackageCreationStep(BuildConfiguration *buildConfig) : ProjectExplorer::BuildStep(buildConfig, CreatePackageId), - m_packageContents(new MaemoPackageContents(this)) + m_packageContents(new MaemoPackageContents(this)), + m_packagingEnabled(true) { } MaemoPackageCreationStep::MaemoPackageCreationStep(BuildConfiguration *buildConfig, MaemoPackageCreationStep *other) : BuildStep(buildConfig, other), - m_packageContents(new MaemoPackageContents(this)) + m_packageContents(new MaemoPackageContents(this)), + m_packagingEnabled(other->m_packagingEnabled) { @@ -90,18 +94,20 @@ bool MaemoPackageCreationStep::init() QVariantMap MaemoPackageCreationStep::toMap() const { QVariantMap map(ProjectExplorer::BuildStep::toMap()); + map.insert(PackagingEnabledKey, m_packagingEnabled); return map.unite(m_packageContents->toMap()); } bool MaemoPackageCreationStep::fromMap(const QVariantMap &map) { m_packageContents->fromMap(map); + m_packagingEnabled = map.value(PackagingEnabledKey, true).toBool(); return ProjectExplorer::BuildStep::fromMap(map); } void MaemoPackageCreationStep::run(QFutureInterface &fi) { - fi.reportResult(createPackage()); + fi.reportResult(m_packagingEnabled ? createPackage() : true); } BuildStepConfigWidget *MaemoPackageCreationStep::createConfigWidget() diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h index 60f2bbce526..255fb1d5cff 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationstep.h @@ -68,6 +68,9 @@ public: QString executableFileName() const; MaemoPackageContents *packageContents() const { return m_packageContents; } + bool isPackagingEnabled() const { return m_packagingEnabled; } + void setPackagingEnabled(bool enabled) { m_packagingEnabled = enabled; } + private: MaemoPackageCreationStep(ProjectExplorer::BuildConfiguration *buildConfig, MaemoPackageCreationStep *other); @@ -94,6 +97,7 @@ private: static const QLatin1String CreatePackageId; MaemoPackageContents *const m_packageContents; + bool m_packagingEnabled; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp index 109bd548e36..8f1005f1aad 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.cpp @@ -64,6 +64,8 @@ MaemoPackageCreationWidget::MaemoPackageCreationWidget(MaemoPackageCreationStep m_ui(new Ui::MaemoPackageCreationWidget) { m_ui->setupUi(this); + m_ui->skipCheckBox->setChecked(!m_step->isPackagingEnabled()); + m_ui->packageContentsView->setEnabled(m_step->isPackagingEnabled()); m_ui->packageContentsView->setModel(step->packageContents()); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); connect(step->packageContents(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), @@ -136,5 +138,11 @@ void MaemoPackageCreationWidget::enableOrDisableRemoveButton() && selectedRows.first().row() != 0); } +void MaemoPackageCreationWidget::handleSkipButtonToggled(bool checked) +{ + m_step->setPackagingEnabled(!checked); + m_ui->packageContentsView->setEnabled(m_step->isPackagingEnabled()); +} + } // namespace Internal } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h index 3c8d10d79c1..ead07fac55f 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.h @@ -67,6 +67,7 @@ private slots: void addFile(); void removeFile(); void enableOrDisableRemoveButton(); + void handleSkipButtonToggled(bool checked); private: MaemoPackageCreationStep * const m_step; diff --git a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui index a650baa0cbc..ef1ed2334d1 100644 --- a/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui +++ b/src/plugins/qt4projectmanager/qt-maemo/maemopackagecreationwidget.ui @@ -17,6 +17,20 @@ + + 6 + + + + + Check this if you build the package externally. It still needs to be at the location listed above +and the remote executable is assumed to be in the directory mentioned below. + + + Skip Packaging Step + + + @@ -126,8 +140,8 @@ addFile() - 712 - 44 + 729 + 88 732 @@ -142,8 +156,8 @@ removeFile() - 723 - 77 + 729 + 124 735 @@ -151,9 +165,26 @@ + + skipCheckBox + clicked(bool) + MaemoPackageCreationWidget + handleSkipButtonToggled(bool) + + + 129 + 18 + + + 240 + 31 + + + addFile() removeFile() + handleSkipButtonToggled(bool) From 40b983a91b306c3f21e2b973b8b63f1b913e26c2 Mon Sep 17 00:00:00 2001 From: kh1 Date: Fri, 11 Jun 2010 12:49:19 +0200 Subject: [PATCH 27/32] Fix missing check-boxes on initial startup. Task-number: QTCREATORBUG-1621 Reviewed-by: ck --- src/plugins/help/filtersettingspage.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/help/filtersettingspage.cpp b/src/plugins/help/filtersettingspage.cpp index 8577b42960e..ed27e455d15 100644 --- a/src/plugins/help/filtersettingspage.cpp +++ b/src/plugins/help/filtersettingspage.cpp @@ -114,8 +114,10 @@ void FilterSettingsPage::updateFilterPage() foreach (const QString &attribute, attributes) new QTreeWidgetItem(m_ui.attributeWidget, QStringList(attribute)); - if (m_filterMap.keys().count()) + if (m_filterMap.keys().isEmpty()) { m_ui.filterWidget->setCurrentRow(0); + updateAttributes(m_ui.filterWidget->currentItem()); + } } void FilterSettingsPage::updateAttributes(QListWidgetItem *item) From 1b6ad087950ca0753f9e17016b618bc6656004af Mon Sep 17 00:00:00 2001 From: kh1 Date: Fri, 11 Jun 2010 13:11:37 +0200 Subject: [PATCH 28/32] Move help manager into core. - lessens open file handles - improves help plugin startup further Task-number: QTCREATORBUG-337 Reviewed-by: ck --- src/plugins/coreplugin/coreimpl.cpp | 5 + src/plugins/coreplugin/coreimpl.h | 1 + src/plugins/coreplugin/coreplugin.pro | 7 +- src/plugins/coreplugin/helpmanager.cpp | 321 ++++++++++++++++++ src/plugins/coreplugin/helpmanager.h | 96 ++++++ src/plugins/coreplugin/icore.h | 2 + src/plugins/coreplugin/mainwindow.cpp | 10 + src/plugins/coreplugin/mainwindow.h | 3 + src/plugins/cppeditor/cppeditor.pro | 1 - src/plugins/cppeditor/cpphoverhandler.cpp | 30 +- src/plugins/cppeditor/cpphoverhandler.h | 3 - src/plugins/designer/formeditorw.cpp | 11 +- src/plugins/designer/qtcreatorintegration.cpp | 4 +- src/plugins/designer/qtcreatorintegration.h | 4 +- src/plugins/help/centralwidget.cpp | 5 +- src/plugins/help/docsettingspage.cpp | 29 +- src/plugins/help/docsettingspage.h | 3 - src/plugins/help/filtersettingspage.cpp | 17 +- src/plugins/help/filtersettingspage.h | 6 + src/plugins/help/generalsettingspage.cpp | 12 +- src/plugins/help/helpindexfilter.cpp | 187 +--------- src/plugins/help/helpindexfilter.h | 8 +- src/plugins/help/helpmanager.cpp | 140 ++------ src/plugins/help/helpmanager.h | 48 +-- src/plugins/help/helpplugin.cpp | 106 +++--- src/plugins/help/helpplugin.h | 5 +- src/plugins/help/helpviewer.cpp | 6 +- src/plugins/help/helpviewer_qwv.cpp | 6 +- src/plugins/help/openpagesmanager.cpp | 4 +- src/plugins/help/searchwidget.cpp | 4 +- src/plugins/plugins.pro | 1 - src/plugins/qmljseditor/qmljseditor.pro | 1 - src/plugins/qmljseditor/qmljshoverhandler.cpp | 27 +- src/plugins/qmljseditor/qmljshoverhandler.h | 3 - .../Qt4ProjectManager.pluginspec | 1 - .../gettingstartedwelcomepagewidget.cpp | 9 +- .../qt4projectmanager_dependencies.pri | 1 - .../qt4projectmanager/qtversionmanager.cpp | 4 +- src/shared/help/bookmarkmanager.cpp | 7 +- src/shared/help/contentwindow.cpp | 2 +- src/shared/help/indexwindow.cpp | 2 +- 41 files changed, 622 insertions(+), 520 deletions(-) create mode 100644 src/plugins/coreplugin/helpmanager.cpp create mode 100644 src/plugins/coreplugin/helpmanager.h diff --git a/src/plugins/coreplugin/coreimpl.cpp b/src/plugins/coreplugin/coreimpl.cpp index d072e8df091..99d76f35395 100644 --- a/src/plugins/coreplugin/coreimpl.cpp +++ b/src/plugins/coreplugin/coreimpl.cpp @@ -144,6 +144,11 @@ MimeDatabase *CoreImpl::mimeDatabase() const return m_mainwindow->mimeDatabase(); } +HelpManager *CoreImpl::helpManager() const +{ + return m_mainwindow->helpManager(); +} + QSettings *CoreImpl::settings(QSettings::Scope scope) const { return m_mainwindow->settings(scope); diff --git a/src/plugins/coreplugin/coreimpl.h b/src/plugins/coreplugin/coreimpl.h index 50a8a673fbd..efd971f3b6b 100644 --- a/src/plugins/coreplugin/coreimpl.h +++ b/src/plugins/coreplugin/coreimpl.h @@ -67,6 +67,7 @@ public: VCSManager *vcsManager() const; ModeManager *modeManager() const; MimeDatabase *mimeDatabase() const; + HelpManager *helpManager() const; QSettings *settings(QSettings::Scope scope = QSettings::UserScope) const; SettingsDatabase *settingsDatabase() const; diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro index d5b30647137..3b607d037b6 100644 --- a/src/plugins/coreplugin/coreplugin.pro +++ b/src/plugins/coreplugin/coreplugin.pro @@ -6,6 +6,7 @@ QT += xml \ script \ svg \ sql +CONFIG += help include(../../qtcreatorplugin.pri) include(../../libs/utils/utils.pri) include(../../shared/scriptwrapper/scriptwrapper.pri) @@ -86,7 +87,8 @@ SOURCES += mainwindow.cpp \ editortoolbar.cpp \ ssh/ne7sshobject.cpp \ ssh/sshconnection.cpp \ - ssh/sshkeygenerator.cpp + ssh/sshkeygenerator.cpp \ + helpmanager.cpp HEADERS += mainwindow.h \ editmode.h \ @@ -171,7 +173,8 @@ HEADERS += mainwindow.h \ editortoolbar.h \ ssh/ne7sshobject.h \ ssh/sshconnection.h \ - ssh/sshkeygenerator.h + ssh/sshkeygenerator.h \ + helpmanager.h FORMS += dialogs/newdialog.ui \ actionmanager/commandmappings.ui \ diff --git a/src/plugins/coreplugin/helpmanager.cpp b/src/plugins/coreplugin/helpmanager.cpp new file mode 100644 index 00000000000..85cf89a1a51 --- /dev/null +++ b/src/plugins/coreplugin/helpmanager.cpp @@ -0,0 +1,321 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "helpmanager.h" + +#include "icore.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace Core { + +HelpManager *HelpManager::m_instance = 0; + +static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, " + "d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, " + "NamespaceTable f WHERE a.FileId=d.FileId AND d.FolderId=e.Id AND " + "a.NamespaceId=f.Id AND a.Name='%1'"; + +// -- DbCleaner + +struct DbCleaner { + DbCleaner(const QString &dbName) + : name(dbName) {} + ~DbCleaner() { + QSqlDatabase::removeDatabase(name); + } + QString name; +}; + +// -- HelpManager + +HelpManager::HelpManager(QObject *parent) + : QObject(parent) + , m_needsSetup(true) + , m_helpEngine(0) +{ + Q_ASSERT(!m_instance); + m_instance = this; + + connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, + SLOT(setupHelpManager())); +} + +HelpManager::~HelpManager() +{ + delete m_helpEngine; + m_helpEngine = 0; + + m_instance = 0; +} + +HelpManager* HelpManager::instance() +{ + Q_ASSERT(m_instance); + return m_instance; +} + +QString HelpManager::collectionFilePath() +{ + const QFileInfo fi(Core::ICore::instance()->settings()->fileName()); + const QDir directory(fi.absolutePath() + QLatin1String("/qtcreator")); + if (!directory.exists()) + directory.mkpath(directory.absolutePath()); + return QDir::cleanPath(directory.absolutePath() + QLatin1String("/helpcollection.qhc")); +} + +void HelpManager::registerDocumentation(const QStringList &files) +{ + if (m_needsSetup) { + m_filesToRegister.append(files); + return; + } + + bool docsChanged = false; + foreach (const QString &file, files) { + const QString &nameSpace = m_helpEngine->namespaceName(file); + if (nameSpace.isEmpty()) + continue; + if (!m_helpEngine->registeredDocumentations().contains(nameSpace)) { + if (m_helpEngine->registerDocumentation(file)) { + docsChanged = true; + } else { + qWarning() << "Error registering namespace '" << nameSpace + << "' from file '" << file << "':" << m_helpEngine->error(); + } + } + } + if (docsChanged) + emit documentationChanged(); +} + +void HelpManager::unregisterDocumentation(const QStringList &nameSpaces) +{ + if (m_needsSetup) { + m_nameSpacesToUnregister.append(nameSpaces); + return; + } + + bool docsChanged = false; + foreach (const QString &nameSpace, nameSpaces) { + if (m_helpEngine->unregisterDocumentation(nameSpace)) { + docsChanged = true; + } else { + qWarning() << "Error unregistering namespace '" << nameSpace + << "' from file '" << m_helpEngine->documentationFileName(nameSpace) + << "': " << m_helpEngine->error(); + } + } + if (docsChanged) + emit documentationChanged(); +} + +QUrl buildQUrl(const QString &nameSpace, const QString &folder, + const QString &relFileName, const QString &anchor) +{ + QUrl url; + url.setScheme(QLatin1String("qthelp")); + url.setAuthority(nameSpace); + url.setPath(folder + QLatin1Char('/') + relFileName); + url.setFragment(anchor); + return url; +} + +// This should go into Qt 4.8 once we start using it for Qt Creator +QMap HelpManager::linksForKeyword(const QString &key) const +{ + QMap links; + if (m_needsSetup) + return links; + + const QLatin1String sqlite("QSQLITE"); + const QLatin1String name("HelpManager::linksForKeyword"); + + DbCleaner cleaner(name); + QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); + if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { + const QStringList ®isteredDocs = m_helpEngine->registeredDocumentations(); + foreach (const QString &nameSpace, registeredDocs) { + db.setDatabaseName(m_helpEngine->documentationFileName(nameSpace)); + if (db.open()) { + QSqlQuery query = QSqlQuery(db); + query.setForwardOnly(true); + query.exec(QString::fromLatin1(linksForKeyQuery).arg(key)); + while (query.next()) { + QString title = query.value(0).toString(); + if (title.isEmpty()) // generate a title + corresponding path + title = key + QLatin1String(" : ") + query.value(3).toString(); + links.insertMulti(title, buildQUrl(query.value(1).toString(), + query.value(2).toString(), query.value(3).toString(), + query.value(4).toString())); + } + } + } + } + return links; +} + +QMap HelpManager::linksForIdentifier(const QString &id) const +{ + if (m_needsSetup) + return QMap(); + return m_helpEngine->linksForIdentifier(id); +} + +// This should go into Qt 4.8 once we start using it for Qt Creator +QStringList HelpManager::findKeywords(const QString &key, int maxHits) const +{ + QStringList keywords; + if (m_needsSetup) + return keywords; + + const QLatin1String sqlite("QSQLITE"); + const QLatin1String name("HelpManager::findKeywords"); + + DbCleaner cleaner(name); + QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); + if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { + const QStringList ®isteredDocs = m_helpEngine->registeredDocumentations(); + foreach (const QString &nameSpace, registeredDocs) { + db.setDatabaseName(m_helpEngine->documentationFileName(nameSpace)); + if (db.open()) { + QSqlQuery query = QSqlQuery(db); + query.setForwardOnly(true); + query.exec(QString::fromLatin1("SELECT DISTINCT Name FROM " + "IndexTable WHERE Name LIKE '%%1%'").arg(key)); + while (query.next()) { + const QString &key = query.value(0).toString(); + if (!key.isEmpty()) { + keywords.append(key); + if (keywords.count() == maxHits) + return keywords; + } + } + } + } + } + return keywords; +} + +QUrl HelpManager::findFile(const QUrl &url) const +{ + if (m_needsSetup) + return QUrl(); + return m_helpEngine->findFile(url); +} + +void HelpManager::handleHelpRequest(const QString &url) +{ + emit helpRequested(QUrl(url)); +} + +QStringList HelpManager::registeredNamespaces() const +{ + if (m_needsSetup) + return QStringList(); + return m_helpEngine->registeredDocumentations(); +} + +QString HelpManager::namespaceFromFile(const QString &file) const +{ + if (m_needsSetup) + return QString(); + return m_helpEngine->namespaceName(file); +} + +QString HelpManager::fileFromNamespace(const QString &nameSpace) const +{ + if (m_needsSetup) + return QString(); + return m_helpEngine->documentationFileName(nameSpace); +} + +// -- private slots + +void HelpManager::setupHelpManager() +{ + if (!m_needsSetup) + return; + m_needsSetup = false; + + m_helpEngine = new QHelpEngineCore(collectionFilePath(), this); + m_helpEngine->setAutoSaveFilter(false); + m_helpEngine->setCurrentFilter(tr("Unfiltered")); + m_helpEngine->setupData(); + + verifyDocumenation(); + + if (!m_nameSpacesToUnregister.isEmpty()) { + unregisterDocumentation(m_nameSpacesToUnregister); + m_nameSpacesToUnregister.clear(); + } + + // this might come from the installer + const QLatin1String key("AddedDocs"); + const QString &addedDocs = m_helpEngine->customValue(key).toString(); + if (!addedDocs.isEmpty()) { + m_helpEngine->removeCustomValue(key); + m_filesToRegister += addedDocs.split(QLatin1Char(';')); + } + + if (!m_filesToRegister.isEmpty()) { + registerDocumentation(m_filesToRegister); + m_filesToRegister.clear(); + } + + emit setupFinished(); +} + +// -- private + +void HelpManager::verifyDocumenation() +{ + QStringList nameSpacesToUnregister; + const QStringList ®isteredDocs = m_helpEngine->registeredDocumentations(); + foreach (const QString &nameSpace, registeredDocs) { + const QString &file = m_helpEngine->documentationFileName(nameSpace); + if (!QFileInfo(file).exists()) + nameSpacesToUnregister.append(nameSpace); + } + + if (!nameSpacesToUnregister.isEmpty()) + unregisterDocumentation(nameSpacesToUnregister); +} + +} // Core diff --git a/src/plugins/coreplugin/helpmanager.h b/src/plugins/coreplugin/helpmanager.h new file mode 100644 index 00000000000..7df6c55659c --- /dev/null +++ b/src/plugins/coreplugin/helpmanager.h @@ -0,0 +1,96 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef HELPMANAGER_H +#define HELPMANAGER_H + +#include "core_global.h" + +#include +#include +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QHelpEngineCore) +QT_FORWARD_DECLARE_CLASS(QSqlQuery) + +namespace Core { + +class CORE_EXPORT HelpManager : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(HelpManager) + +public: + explicit HelpManager(QObject *parent = 0); + virtual ~HelpManager(); + + static HelpManager* instance(); + static QString collectionFilePath(); + + void registerDocumentation(const QStringList &fileNames); + void unregisterDocumentation(const QStringList &nameSpaces); + + QMap linksForKeyword(const QString &key) const; + QMap linksForIdentifier(const QString &id) const; + QStringList findKeywords(const QString &key, int maxHits = INT_MAX) const; + + QUrl findFile(const QUrl &url) const; + void handleHelpRequest(const QString &url); + + QStringList registeredNamespaces() const; + QString namespaceFromFile(const QString &file) const; + QString fileFromNamespace(const QString &nameSpace) const; + +signals: + void setupFinished(); + void documentationChanged(); + void helpRequested(const QUrl &url); + +private slots: + void setupHelpManager(); + +private: + void verifyDocumenation(); + +private: + bool m_needsSetup; + QHelpEngineCore *m_helpEngine; + + QStringList m_filesToRegister; + QStringList m_nameSpacesToUnregister; + + static HelpManager *m_instance; +}; + +} // Core + +#endif // HELPMANAGER_H diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h index cae3da1b4d9..4eb3c897186 100644 --- a/src/plugins/coreplugin/icore.h +++ b/src/plugins/coreplugin/icore.h @@ -50,6 +50,7 @@ namespace Core { class ActionManager; class EditorManager; class FileManager; +class HelpManager; class IContext; class MessageManager; class MimeDatabase; @@ -96,6 +97,7 @@ public: virtual VCSManager *vcsManager() const = 0; virtual ModeManager *modeManager() const = 0; virtual MimeDatabase *mimeDatabase() const = 0; + virtual HelpManager *helpManager() const = 0; virtual QSettings *settings(QSettings::Scope scope = QSettings::UserScope) const = 0; virtual SettingsDatabase *settingsDatabase() const = 0; diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index ed1d48afb8d..1555395c741 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -37,6 +37,7 @@ #include "fancytabwidget.h" #include "filemanager.h" #include "generalsettings.h" +#include "helpmanager.h" #include "ifilefactory.h" #include "messagemanager.h" #include "modemanager.h" @@ -132,6 +133,7 @@ MainWindow::MainWindow() : m_statusBarManager(0), m_modeManager(0), m_mimeDatabase(new MimeDatabase), + m_helpManager(new HelpManager), m_navigationWidget(0), m_rightPaneWidget(0), m_versionDialog(0), @@ -288,6 +290,9 @@ MainWindow::~MainWindow() m_modeManager = 0; delete m_mimeDatabase; m_mimeDatabase = 0; + + delete m_helpManager; + m_helpManager = 0; } bool MainWindow::init(QString *errorMessage) @@ -1011,6 +1016,11 @@ MimeDatabase *MainWindow::mimeDatabase() const return m_mimeDatabase; } +HelpManager *MainWindow::helpManager() const +{ + return m_helpManager; +} + IContext *MainWindow::contextObject(QWidget *widget) { return m_contextWidgets.value(widget); diff --git a/src/plugins/coreplugin/mainwindow.h b/src/plugins/coreplugin/mainwindow.h index 60b911ba1d1..3b890439b01 100644 --- a/src/plugins/coreplugin/mainwindow.h +++ b/src/plugins/coreplugin/mainwindow.h @@ -52,6 +52,7 @@ class ActionManager; class StatusBarWidget; class EditorManager; class FileManager; +class HelpManager; class IContext; class IWizard; class MessageManager; @@ -107,6 +108,7 @@ public: Core::VariableManager *variableManager() const; Core::ModeManager *modeManager() const; Core::MimeDatabase *mimeDatabase() const; + Core::HelpManager *helpManager() const; VCSManager *vcsManager() const; QSettings *settings(QSettings::Scope scope) const; @@ -193,6 +195,7 @@ private: StatusBarManager *m_statusBarManager; ModeManager *m_modeManager; MimeDatabase *m_mimeDatabase; + HelpManager *m_helpManager; FancyTabWidget *m_modeStack; NavigationWidget *m_navigationWidget; RightPaneWidget *m_rightPaneWidget; diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 13f532e57a6..e9f4f0d0f4d 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -1,7 +1,6 @@ TEMPLATE = lib TARGET = CppEditor DEFINES += CPPEDITOR_LIBRARY -CONFIG += help include(../../qtcreatorplugin.pri) include(../../libs/utils/utils.pri) include(../../shared/indenter/indenter.pri) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index dabf25c7917..2b691e6be98 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -32,6 +32,7 @@ #include "cppplugin.h" #include +#include #include #include #include @@ -60,7 +61,6 @@ #include #include #include -#include using namespace CppEditor::Internal; using namespace CPlusPlus; @@ -68,27 +68,11 @@ using namespace Core; CppHoverHandler::CppHoverHandler(QObject *parent) : QObject(parent) - , m_helpEngineNeedsSetup(false) { m_modelManager = ExtensionSystem::PluginManager::instance()->getObject(); - ICore *core = ICore::instance(); - QFileInfo fi(core->settings()->fileName()); - // FIXME shouldn't the help engine create the directory if it doesn't exist? - QDir directory(fi.absolutePath()+"/qtcreator"); - if (!directory.exists()) - directory.mkpath(directory.absolutePath()); - - m_helpEngine = new QHelpEngineCore(directory.absolutePath() - + QLatin1String("/helpcollection.qhc"), this); - if (!m_helpEngine->setupData()) - qWarning() << "Could not initialize help engine:" << m_helpEngine->error(); - m_helpEngine->setAutoSaveFilter(false); - m_helpEngine->setCurrentFilter(tr("Unfiltered")); - m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0; - // Listen for editor opened events in order to connect to tooltip/helpid requests - connect(core->editorManager(), SIGNAL(editorOpened(Core::IEditor *)), + connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)), this, SLOT(editorOpened(Core::IEditor *))); } @@ -297,19 +281,13 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in } } - if (m_helpEngineNeedsSetup - && m_helpEngine->registeredDocumentations().count() > 0) { - m_helpEngine->setupData(); - m_helpEngineNeedsSetup = false; - } QMap helpLinks; - if (m_toolTip.isEmpty()) { foreach (const Document::Include &incl, doc->includes()) { if (incl.line() == lineNumber) { m_toolTip = QDir::toNativeSeparators(incl.fileName()); m_helpId = QFileInfo(incl.fileName()).fileName(); - helpLinks = m_helpEngine->linksForIdentifier(m_helpId); + helpLinks = Core::HelpManager::instance()->linksForIdentifier(m_helpId); break; } } @@ -388,7 +366,7 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in // To show their help anyway, try stripping scopes until we find something. const QString startHelpId = m_helpId; while (!m_helpId.isEmpty()) { - helpLinks = m_helpEngine->linksForIdentifier(m_helpId); + helpLinks = Core::HelpManager::instance()->linksForIdentifier(m_helpId); if (!helpLinks.isEmpty()) break; diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h index d0f5b11dc5d..311b8292236 100644 --- a/src/plugins/cppeditor/cpphoverhandler.h +++ b/src/plugins/cppeditor/cpphoverhandler.h @@ -33,7 +33,6 @@ #include QT_BEGIN_NAMESPACE -class QHelpEngineCore; class QPoint; QT_END_NAMESPACE @@ -70,10 +69,8 @@ private: void updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos); CppTools::CppModelManagerInterface *m_modelManager; - QHelpEngineCore *m_helpEngine; QString m_helpId; QString m_toolTip; - bool m_helpEngineNeedsSetup; }; } // namespace Internal diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp index 7ac31008452..54779835b5a 100644 --- a/src/plugins/designer/formeditorw.cpp +++ b/src/plugins/designer/formeditorw.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -282,14 +283,8 @@ void FormEditorW::fullInit() m_integration = new QtCreatorIntegration(m_formeditor, this); m_formeditor->setIntegration(m_integration); // Connect Qt Designer help request to HelpManager. - // TODO: Use Core::HelpManager once it has been introduced. - foreach(QObject *object, ExtensionSystem::PluginManager::instance()->allObjects()) { - if (!qstrcmp(object->metaObject()->className(), "Help::HelpManager")) { - connect(m_integration, SIGNAL(creatorHelpRequested(QString)), - object, SLOT(handleHelpRequest(QString))); - break; - } - } + connect(m_integration, SIGNAL(creatorHelpRequested(QUrl)), + Core::HelpManager::instance(), SIGNAL(helpRequested(QUrl))); /** * This will initialize our TabOrder, Signals and slots and Buddy editors. diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index e6439d71b72..4cc1e1140bf 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -61,6 +61,7 @@ #include #include +#include enum { indentation = 4 }; @@ -101,7 +102,8 @@ QtCreatorIntegration::QtCreatorIntegration(QDesignerFormEditorInterface *core, F void QtCreatorIntegration::slotDesignerHelpRequested(const QString &manual, const QString &document) { // Pass on as URL. - emit creatorHelpRequested(QString::fromLatin1("qthelp://com.trolltech.%1/qdoc/%2").arg(manual, document)); + emit creatorHelpRequested(QUrl(QString::fromLatin1("qthelp://com.trolltech.%1/qdoc/%2") + .arg(manual, document))); } void QtCreatorIntegration::updateSelection() diff --git a/src/plugins/designer/qtcreatorintegration.h b/src/plugins/designer/qtcreatorintegration.h index c667ea8504d..a246a283c3c 100644 --- a/src/plugins/designer/qtcreatorintegration.h +++ b/src/plugins/designer/qtcreatorintegration.h @@ -34,6 +34,8 @@ #include "qt_private/qdesigner_integration_p.h" +QT_FORWARD_DECLARE_CLASS(QUrl) + namespace Designer { namespace Internal { @@ -49,7 +51,7 @@ public: bool supportsToSlotNavigation() { return true; } signals: - void creatorHelpRequested(const QString &url); + void creatorHelpRequested(const QUrl &url); public slots: void updateSelection(); diff --git a/src/plugins/help/centralwidget.cpp b/src/plugins/help/centralwidget.cpp index d1f77bb5571..9dbc069f376 100644 --- a/src/plugins/help/centralwidget.cpp +++ b/src/plugins/help/centralwidget.cpp @@ -45,7 +45,6 @@ #include #include -#include #include using namespace Help::Internal; @@ -85,7 +84,7 @@ CentralWidget::~CentralWidget() } } - QHelpEngineCore *engine = &HelpManager::helpEngineCore(); + QHelpEngineCore *engine = &LocalHelpManager::helpEngine(); engine->setCustomValue(QLatin1String("LastShownPages"), currentPages); engine->setCustomValue(QLatin1String("LastShownPagesZoom"), zoomFactors); engine->setCustomValue(QLatin1String("LastTabPage"), currentIndex()); @@ -314,7 +313,7 @@ void CentralWidget::highlightSearchTerms() { if (HelpViewer *viewer = currentHelpViewer()) { QHelpSearchEngine *searchEngine = - HelpManager::instance().helpEngine().searchEngine(); + LocalHelpManager::helpEngine().searchEngine(); QList queryList = searchEngine->query(); QStringList terms; diff --git a/src/plugins/help/docsettingspage.cpp b/src/plugins/help/docsettingspage.cpp index 4933f53dd4e..a860446ba5c 100644 --- a/src/plugins/help/docsettingspage.cpp +++ b/src/plugins/help/docsettingspage.cpp @@ -29,7 +29,8 @@ #include "docsettingspage.h" #include "helpconstants.h" -#include "helpmanager.h" + +#include #include @@ -37,8 +38,6 @@ #include #include -#include - using namespace Help::Internal; DocSettingsPage::DocSettingsPage() @@ -80,10 +79,10 @@ QWidget *DocSettingsPage::createPage(QWidget *parent) m_ui.docsListWidget->installEventFilter(this); - QHelpEngineCore *engine = &HelpManager::helpEngineCore(); - const QStringList &nameSpaces = engine->registeredDocumentations(); + Core::HelpManager *manager = Core::HelpManager::instance(); + const QStringList &nameSpaces = manager->registeredNamespaces(); foreach (const QString &nameSpace, nameSpaces) - addItem(nameSpace, engine->documentationFileName(nameSpace)); + addItem(nameSpace, manager->fileFromNamespace(nameSpace)); m_filesToRegister.clear(); m_filesToUnregister.clear(); @@ -103,11 +102,11 @@ void DocSettingsPage::addDocumentation() return; m_recentDialogPath = QFileInfo(files.first()).canonicalPath(); - const QHelpEngineCore &engine = HelpManager::helpEngineCore(); - const QStringList &nameSpaces = engine.registeredDocumentations(); + Core::HelpManager *manager = Core::HelpManager::instance(); + const QStringList &nameSpaces = manager->registeredNamespaces(); foreach (const QString &file, files) { - const QString &nameSpace = engine.namespaceName(file); + const QString &nameSpace = manager->namespaceFromFile(file); if (nameSpace.isEmpty()) continue; @@ -130,14 +129,10 @@ void DocSettingsPage::removeDocumentation() void DocSettingsPage::apply() { - HelpManager* manager = &HelpManager::instance(); + Core::HelpManager *manager = Core::HelpManager::instance(); + manager->unregisterDocumentation(m_filesToUnregister.keys()); manager->registerDocumentation(m_filesToRegister.values()); - if (manager->guiEngineNeedsUpdate()) { - // emit this signal to the help plugin, since we don't want - // to force gui help engine setup if we are not in help mode - emit documentationChanged(); - } m_filesToRegister.clear(); m_filesToUnregister.clear(); @@ -172,10 +167,10 @@ void DocSettingsPage::removeDocumentation(const QList items) return; int row = 0; - QHelpEngineCore *engine = &HelpManager::helpEngineCore(); + Core::HelpManager *manager = Core::HelpManager::instance(); foreach (QListWidgetItem* item, items) { const QString &nameSpace = item->text(); - const QString &docPath = engine->documentationFileName(nameSpace); + const QString &docPath = manager->fileFromNamespace(nameSpace); if (m_filesToRegister.value(nameSpace) != docPath) { if (!m_filesToUnregister.contains(nameSpace)) diff --git a/src/plugins/help/docsettingspage.h b/src/plugins/help/docsettingspage.h index 66de3ac8ae3..7d292b2fee0 100644 --- a/src/plugins/help/docsettingspage.h +++ b/src/plugins/help/docsettingspage.h @@ -55,9 +55,6 @@ public: void finish() {} virtual bool matches(const QString &s) const; -signals: - void documentationChanged(); - private slots: void addDocumentation(); void removeDocumentation(); diff --git a/src/plugins/help/filtersettingspage.cpp b/src/plugins/help/filtersettingspage.cpp index ed27e455d15..ccdde31a262 100644 --- a/src/plugins/help/filtersettingspage.cpp +++ b/src/plugins/help/filtersettingspage.cpp @@ -33,16 +33,19 @@ #include "helpconstants.h" #include "helpmanager.h" +#include + #include #include #include -#include +#include using namespace Help::Internal; FilterSettingsPage::FilterSettingsPage() + : m_helpManager(0) { } @@ -76,6 +79,7 @@ QWidget *FilterSettingsPage::createPage(QWidget *parent) QWidget *widget = new QWidget(parent); m_ui.setupUi(widget); + m_helpManager->setupGuiHelpEngine(); updateFilterPage(); // does call setupData on the engine connect(m_ui.attributeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), @@ -86,6 +90,8 @@ QWidget *FilterSettingsPage::createPage(QWidget *parent) connect(m_ui.filterAddButton, SIGNAL(clicked()), this, SLOT(addFilter())); connect(m_ui.filterRemoveButton, SIGNAL(clicked()), this, SLOT(removeFilter())); + connect(Core::HelpManager::instance(), SIGNAL(documentationChanged()), + this, SLOT(updateFilterPage())); if (m_searchKeywords.isEmpty()) { m_searchKeywords = m_ui.filterGroupBox->title() + QLatin1Char(' ') @@ -100,7 +106,7 @@ void FilterSettingsPage::updateFilterPage() m_ui.attributeWidget->clear(); m_filterMapBackup.clear(); - const QHelpEngineCore &engine = HelpManager::helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); const QStringList &filters = engine.customFilters(); foreach (const QString &filter, filters) { const QStringList &attributes = engine.filterAttributes(filter); @@ -210,7 +216,7 @@ void FilterSettingsPage::apply() } if (changed) { - QHelpEngineCore *engine = &HelpManager::helpEngineCore(); + QHelpEngineCore *engine = &LocalHelpManager::helpEngine(); foreach (const QString &filter, m_removedFilters) engine->removeCustomFilter(filter); @@ -228,3 +234,8 @@ bool FilterSettingsPage::matches(const QString &s) const { return m_searchKeywords.contains(s, Qt::CaseInsensitive); } + +void FilterSettingsPage::setHelpManager(LocalHelpManager *manager) +{ + m_helpManager = manager; +} diff --git a/src/plugins/help/filtersettingspage.h b/src/plugins/help/filtersettingspage.h index b8f74d5359d..96b2a57778d 100644 --- a/src/plugins/help/filtersettingspage.h +++ b/src/plugins/help/filtersettingspage.h @@ -36,6 +36,8 @@ namespace Help { namespace Internal { +class LocalHelpManager; + class FilterSettingsPage : public Core::IOptionsPage { Q_OBJECT @@ -55,6 +57,8 @@ public: void finish() {} virtual bool matches(const QString &s) const; + void setHelpManager(LocalHelpManager *manager); + signals: void filtersChanged(); @@ -73,6 +77,8 @@ private: QString m_searchKeywords; QStringList m_removedFilters; + + LocalHelpManager *m_helpManager; }; } // namespace Help diff --git a/src/plugins/help/generalsettingspage.cpp b/src/plugins/help/generalsettingspage.cpp index edc20b511b7..2703f9a8103 100644 --- a/src/plugins/help/generalsettingspage.cpp +++ b/src/plugins/help/generalsettingspage.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include #if !defined(QT_NO_WEBKIT) #include @@ -94,7 +94,7 @@ QWidget *GeneralSettingsPage::createPage(QWidget *parent) m_ui.sizeComboBox->setEditable(false); m_ui.styleComboBox->setEditable(false); - const QHelpEngineCore &engine = HelpManager::helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); m_font = qVariantValue(engine.customValue(QLatin1String("font"), m_font)); updateFontSize(); @@ -163,7 +163,7 @@ void GeneralSettingsPage::apply() if (weight >= 0) // Weight < 0 asserts... newFont.setWeight(weight); - QHelpEngineCore *engine = &HelpManager::helpEngineCore(); + QHelpEngineCore *engine = &LocalHelpManager::helpEngine(); engine->setCustomValue(QLatin1String("font"), newFont); if (newFont != m_font) @@ -197,7 +197,7 @@ void GeneralSettingsPage::setBlankPage() void GeneralSettingsPage::setDefaultPage() { - const QString &defaultHomePage = HelpManager::helpEngineCore() + const QString &defaultHomePage = LocalHelpManager::helpEngine() .customValue(QLatin1String("DefaultHomePage"), QString()).toString(); m_ui.homePageLineEdit->setText(defaultHomePage); } @@ -214,7 +214,7 @@ void GeneralSettingsPage::importBookmarks() QFile file(fileName); if (file.open(QIODevice::ReadOnly)) { - const BookmarkManager &manager = HelpManager::bookmarkManager(); + const BookmarkManager &manager = LocalHelpManager::bookmarkManager(); XbelReader reader(manager.treeBookmarkModel(), manager.listBookmarkModel()); if (reader.readFromFile(&file)) return; @@ -237,7 +237,7 @@ void GeneralSettingsPage::exportBookmarks() QFile file(fileName); if (file.open(QIODevice::WriteOnly)) { - XbelWriter writer(HelpManager::bookmarkManager().treeBookmarkModel()); + XbelWriter writer(LocalHelpManager::bookmarkManager().treeBookmarkModel()); writer.writeToFile(&file); } } diff --git a/src/plugins/help/helpindexfilter.cpp b/src/plugins/help/helpindexfilter.cpp index ff148efade6..411d823691b 100644 --- a/src/plugins/help/helpindexfilter.cpp +++ b/src/plugins/help/helpindexfilter.cpp @@ -28,197 +28,28 @@ **************************************************************************/ #include "helpindexfilter.h" -#include "helpmanager.h" #include #include +#include #include -#include -#include - -#include -#include -#include -#include - using namespace Locator; using namespace Help; using namespace Help::Internal; Q_DECLARE_METATYPE(ILocatorFilter*); -static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, " - "d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, " - "NamespaceTable f WHERE a.FileId=d.FileId AND d.FolderId=e.Id AND " - "a.NamespaceId=f.Id AND a.Name='%1'"; - -// -- HelpIndexFilter::HelpFileReader - -class HelpIndexFilter::HelpFileReader -{ - struct dbCleaner { - dbCleaner(const QString &dbName) - : name(dbName) {} - ~dbCleaner() { - QSqlDatabase::removeDatabase(name); - } - QString name; - }; - -public: - HelpFileReader(); - ~HelpFileReader(); - -public: - void updateHelpFiles(); - QMap linksForKey(const QString &key); - QList matchesFor(const QString &entry, ILocatorFilter *locator, - int maxHits = INT_MAX); - -private: - QIcon m_icon; - bool m_initialized; - QStringList m_helpFiles; -}; - -HelpIndexFilter::HelpFileReader::HelpFileReader() - : m_initialized(false) -{ - m_icon = QIcon(QLatin1String(":/help/images/bookmark.png")); -} - -HelpIndexFilter::HelpFileReader::~HelpFileReader() -{ -} - -void HelpIndexFilter::HelpFileReader::updateHelpFiles() -{ - m_helpFiles.clear(); - const QLatin1String id("HelpIndexFilter::HelpFileReader::helpFiles"); - { - QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), id); - if (db.driver() - && db.driver()->lastError().type() == QSqlError::NoError) { - db.setDatabaseName(HelpManager::collectionFilePath()); - if (db.open()) { - QSqlQuery query = QSqlQuery(db); - query.exec(QLatin1String("SELECT a.FilePath FROM NamespaceTable a")); - while (query.next()) - m_helpFiles.append(query.value(0).toString()); - } - } - } - QSqlDatabase::removeDatabase(id); -} - -QUrl buildQUrl(const QString &nameSpace, const QString &folder, - const QString &relFileName, const QString &anchor) -{ - QUrl url; - url.setScheme(QLatin1String("qthelp")); - url.setAuthority(nameSpace); - url.setPath(folder + QLatin1Char('/') + relFileName); - url.setFragment(anchor); - return url; -} - -QMapHelpIndexFilter::HelpFileReader::linksForKey(const QString &key) -{ - if (!m_initialized) { - updateHelpFiles(); - m_initialized = true; - } - - QMap links; - const QLatin1String sqlite("QSQLITE"); - const QLatin1String name("HelpIndexFilter::HelpFileReader::linksForKey"); - - dbCleaner cleaner(name); - QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); - if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { - foreach(const QString &file, m_helpFiles) { - if (!QFile::exists(file)) - continue; - db.setDatabaseName(file); - if (db.open()) { - QSqlQuery query = QSqlQuery(db); - query.setForwardOnly(true); - query.exec(QString::fromLatin1(linksForKeyQuery).arg(key)); - while (query.next()) { - QString title = query.value(0).toString(); - if (title.isEmpty()) // generate a title + corresponding path - title = key + QLatin1String(" : ") + query.value(3).toString(); - links.insertMulti(title, buildQUrl(query.value(1).toString(), - query.value(2).toString(), query.value(3).toString(), - query.value(4).toString())); - } - } - } - } - return links; -} - -QList HelpIndexFilter::HelpFileReader::matchesFor(const QString &id, - ILocatorFilter *locator, int maxHits) -{ - if (!m_initialized) { - updateHelpFiles(); - m_initialized = true; - } - - QList entries; - const QLatin1String sqlite("QSQLITE"); - const QLatin1String name("HelpIndexFilter::HelpFileReader::matchesFor"); - - dbCleaner cleaner(name); - QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); - if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { - foreach(const QString &file, m_helpFiles) { - if (!QFile::exists(file)) - continue; - db.setDatabaseName(file); - if (db.open()) { - QSqlQuery query = QSqlQuery(db); - query.setForwardOnly(true); - query.exec(QString::fromLatin1("SELECT DISTINCT Name FROM " - "IndexTable WHERE Name LIKE '%%1%'").arg(id)); - while (query.next()) { - const QString &key = query.value(0).toString(); - if (!key.isEmpty()) { - entries.append(FilterEntry(locator, key, QVariant(), - m_icon)); - if (entries.count() == maxHits) - return entries; - } - } - } - } - } - return entries; -} - -// -- HelpIndexFilter - HelpIndexFilter::HelpIndexFilter() - : m_fileReader(new HelpFileReader) { setIncludedByDefault(false); setShortcutString(QString(QLatin1Char('?'))); - - connect(&HelpManager::helpEngineCore(), SIGNAL(setupFinished()), this, - SLOT(updateHelpFiles())); + m_icon = QIcon(QLatin1String(":/help/images/bookmark.png")); } HelpIndexFilter::~HelpIndexFilter() { - delete m_fileReader; -} - -void HelpIndexFilter::updateHelpFiles() -{ - m_fileReader->updateHelpFiles(); } QString HelpIndexFilter::displayName() const @@ -238,15 +69,23 @@ ILocatorFilter::Priority HelpIndexFilter::priority() const QList HelpIndexFilter::matchesFor(const QString &entry) { + QStringList keywords; if (entry.length() < 2) - return m_fileReader->matchesFor(entry, this, 300); - return m_fileReader->matchesFor(entry, this); + keywords = Core::HelpManager::instance()->findKeywords(entry, 300); + else + keywords = Core::HelpManager::instance()->findKeywords(entry); + + QList entries; + foreach (const QString &keyword, keywords) + entries.append(FilterEntry(this, keyword, QVariant(), m_icon)); + + return entries; } void HelpIndexFilter::accept(FilterEntry selection) const { const QString &key = selection.displayName; - const QMap &links = m_fileReader->linksForKey(key); + const QMap &links = Core::HelpManager::instance()->linksForKeyword(key); if (links.size() == 1) { emit linkActivated(links.begin().value()); } else if (!links.isEmpty()) { diff --git a/src/plugins/help/helpindexfilter.h b/src/plugins/help/helpindexfilter.h index 9c3a6de4659..859dc5a056a 100644 --- a/src/plugins/help/helpindexfilter.h +++ b/src/plugins/help/helpindexfilter.h @@ -32,6 +32,8 @@ #include +#include + namespace Help { namespace Internal { @@ -40,7 +42,6 @@ class HelpPlugin; class HelpIndexFilter : public Locator::ILocatorFilter { Q_OBJECT - class HelpFileReader; public: HelpIndexFilter(); @@ -58,11 +59,8 @@ signals: void linkActivated(const QUrl &link) const; void linksActivated(const QMap &urls, const QString &keyword) const; -private slots: - void updateHelpFiles(); - private: - HelpFileReader *m_fileReader; + QIcon m_icon; }; } // namespace Internal diff --git a/src/plugins/help/helpmanager.cpp b/src/plugins/help/helpmanager.cpp index bc5bef0a465..10f4197ab96 100644 --- a/src/plugins/help/helpmanager.cpp +++ b/src/plugins/help/helpmanager.cpp @@ -30,38 +30,29 @@ #include "helpmanager.h" #include "bookmarkmanager.h" -#include +#include +#include -#include -#include -#include #include #include -#include -using namespace Help; +using namespace Help::Internal; -bool HelpManager::m_guiNeedsSetup = true; -bool HelpManager::m_needsCollectionFile = true; +QMutex LocalHelpManager::m_guiMutex; +QHelpEngine* LocalHelpManager::m_guiEngine = 0; -QMutex HelpManager::m_guiMutex; -QHelpEngine* HelpManager::m_guiEngine = 0; +QMutex LocalHelpManager::m_bkmarkMutex; +BookmarkManager* LocalHelpManager::m_bookmarkManager = 0; -QMutex HelpManager::m_coreMutex; -QHelpEngineCore* HelpManager::m_coreEngine = 0; - -HelpManager* HelpManager::m_helpManager = 0; -BookmarkManager* HelpManager::m_bookmarkManager = 0; - -HelpManager::HelpManager(QObject *parent) +LocalHelpManager::LocalHelpManager(QObject *parent) : QObject(parent) + , m_guiNeedsSetup(true) + , m_needsCollectionFile(true) { - Q_ASSERT(!m_helpManager); - m_helpManager = this; } -HelpManager::~HelpManager() +LocalHelpManager::~LocalHelpManager() { if (m_bookmarkManager) { m_bookmarkManager->saveBookmarks(); @@ -71,88 +62,27 @@ HelpManager::~HelpManager() delete m_guiEngine; m_guiEngine = 0; - - delete m_coreEngine; - m_coreEngine = 0; } -HelpManager& HelpManager::instance() -{ - Q_ASSERT(m_helpManager); - return *m_helpManager; -} - -void HelpManager::setupGuiHelpEngine() +void LocalHelpManager::setupGuiHelpEngine() { if (m_needsCollectionFile) { m_needsCollectionFile = false; - (&helpEngine())->setCollectionFile(collectionFilePath()); + helpEngine().setCollectionFile(Core::HelpManager::collectionFilePath()); } if (m_guiNeedsSetup) { m_guiNeedsSetup = false; - (&helpEngine())->setupData(); + helpEngine().setupData(); } } -bool HelpManager::guiEngineNeedsUpdate() const +void LocalHelpManager::setEngineNeedsUpdate() { - return m_guiNeedsSetup; + m_guiNeedsSetup = true; } -void HelpManager::handleHelpRequest(const QString &url) -{ - emit helpRequested(QUrl(url)); -} - -void HelpManager::verifyDocumenation() -{ - QStringList nameSpacesToUnregister; - QHelpEngineCore *engine = &helpEngineCore(); - const QStringList ®isteredDocs = engine->registeredDocumentations(); - foreach (const QString &nameSpace, registeredDocs) { - const QString &file = engine->documentationFileName(nameSpace); - if (!QFileInfo(file).exists()) - nameSpacesToUnregister.append(nameSpace); - } - - if (!nameSpacesToUnregister.isEmpty()) - unregisterDocumentation(nameSpacesToUnregister); -} - -void HelpManager::registerDocumentation(const QStringList &files) -{ - QHelpEngineCore *engine = &helpEngineCore(); - foreach (const QString &file, files) { - const QString &nameSpace = engine->namespaceName(file); - if (nameSpace.isEmpty()) - continue; - if (!engine->registeredDocumentations().contains(nameSpace)) { - if (engine->registerDocumentation(file)) { - m_guiNeedsSetup = true; - } else { - qWarning() << "Error registering namespace '" << nameSpace - << "' from file '" << file << "':" << engine->error(); - } - } - } -} - -void HelpManager::unregisterDocumentation(const QStringList &nameSpaces) -{ - QHelpEngineCore *engine = &helpEngineCore(); - foreach (const QString &nameSpace, nameSpaces) { - const QString &file = engine->documentationFileName(nameSpace); - if (engine->unregisterDocumentation(nameSpace)) { - m_guiNeedsSetup = true; - } else { - qWarning() << "Error unregistering namespace '" << nameSpace - << "' from file '" << file << "': " << engine->error(); - } - } -} - -QHelpEngine &HelpManager::helpEngine() +QHelpEngine &LocalHelpManager::helpEngine() { if (!m_guiEngine) { QMutexLocker _(&m_guiMutex); @@ -164,34 +94,18 @@ QHelpEngine &HelpManager::helpEngine() return *m_guiEngine; } -QString HelpManager::collectionFilePath() -{ - const QFileInfo fi(Core::ICore::instance()->settings()->fileName()); - const QDir directory(fi.absolutePath() + QLatin1String("/qtcreator")); - if (!directory.exists()) - directory.mkpath(directory.absolutePath()); - return QDir::cleanPath(directory.absolutePath() + QLatin1String("/helpcollection.qhc")); -} - -QHelpEngineCore& HelpManager::helpEngineCore() -{ - if (!m_coreEngine) { - QMutexLocker _(&m_coreMutex); - if (!m_coreEngine) { - m_coreEngine = new QHelpEngineCore(collectionFilePath()); - m_coreEngine->setAutoSaveFilter(false); - m_coreEngine->setCurrentFilter(tr("Unfiltered")); - m_coreEngine->setupData(); - } - } - return *m_coreEngine; -} - -BookmarkManager& HelpManager::bookmarkManager() +BookmarkManager& LocalHelpManager::bookmarkManager() { if (!m_bookmarkManager) { - m_bookmarkManager = new BookmarkManager; - m_bookmarkManager->setupBookmarkModels(); + QMutexLocker _(&m_bkmarkMutex); + if (!m_bookmarkManager) { + m_bookmarkManager = new BookmarkManager; + m_bookmarkManager->setupBookmarkModels(); + const QString &url = QString::fromLatin1("qthelp://com.nokia.qtcreator." + "%1%2%3/doc/index.html").arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR) + .arg(IDE_VERSION_RELEASE); + helpEngine().setCustomValue(QLatin1String("DefaultHomePage"), url); + } } return *m_bookmarkManager; } diff --git a/src/plugins/help/helpmanager.h b/src/plugins/help/helpmanager.h index 18a36bcd08a..3dc333d405f 100644 --- a/src/plugins/help/helpmanager.h +++ b/src/plugins/help/helpmanager.h @@ -27,66 +27,44 @@ ** **************************************************************************/ -#ifndef HELPMANAGER_H -#define HELPMANAGER_H - -#include "help_global.h" +#ifndef LOCALHELPMANAGER_H +#define LOCALHELPMANAGER_H #include #include QT_FORWARD_DECLARE_CLASS(QHelpEngine) -QT_FORWARD_DECLARE_CLASS(QHelpEngineCore) -QT_FORWARD_DECLARE_CLASS(QString) -QT_FORWARD_DECLARE_CLASS(QStringList) -QT_FORWARD_DECLARE_CLASS(QUrl) class BookmarkManager; namespace Help { + namespace Internal { -class HELP_EXPORT HelpManager : public QObject +class LocalHelpManager : public QObject { Q_OBJECT -public: - HelpManager(QObject *parent = 0); - ~HelpManager(); - static HelpManager& instance(); +public: + LocalHelpManager(QObject *parent = 0); + ~LocalHelpManager(); void setupGuiHelpEngine(); - bool guiEngineNeedsUpdate() const; - - void verifyDocumenation(); - void registerDocumentation(const QStringList &fileNames); - void unregisterDocumentation(const QStringList &nameSpaces); + void setEngineNeedsUpdate(); static QHelpEngine& helpEngine(); - static QString collectionFilePath(); - static QHelpEngineCore& helpEngineCore(); - static BookmarkManager& bookmarkManager(); -public slots: - void handleHelpRequest(const QString &url); - -signals: - void helpRequested(const QUrl &url); - private: - static bool m_guiNeedsSetup; - static bool m_needsCollectionFile; + bool m_guiNeedsSetup; + bool m_needsCollectionFile; static QMutex m_guiMutex; static QHelpEngine *m_guiEngine; - static QMutex m_coreMutex; - static QHelpEngineCore *m_coreEngine; - - static HelpManager *m_helpManager; + static QMutex m_bkmarkMutex; static BookmarkManager *m_bookmarkManager; }; - + } // Internal } // Help -#endif // HELPMANAGER_H +#endif // LOCALHELPMANAGER_H diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index b03719cd10e..ec515753e89 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -78,10 +79,8 @@ #include #include -#include using namespace Core::Constants; -using namespace Help; using namespace Help::Internal; const char * const SB_INDEX = "Index"; @@ -140,22 +139,20 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error) qApp->installTranslator(qhelptr); } - addAutoReleasedObject(m_helpManager = new HelpManager(this)); + addAutoReleasedObject(m_helpManager = new LocalHelpManager(this)); addAutoReleasedObject(m_openPagesManager = new OpenPagesManager(this)); - addAutoReleasedObject(m_docSettingsPage = new DocSettingsPage()); addAutoReleasedObject(m_filterSettingsPage = new FilterSettingsPage()); addAutoReleasedObject(m_generalSettingsPage = new GeneralSettingsPage()); - connect(m_docSettingsPage, SIGNAL(documentationChanged()), m_filterSettingsPage, - SLOT(updateFilterPage())); connect(m_generalSettingsPage, SIGNAL(fontChanged()), this, SLOT(fontChanged())); - connect(m_helpManager, SIGNAL(helpRequested(QUrl)), this, + connect(Core::HelpManager::instance(), SIGNAL(helpRequested(QUrl)), this, SLOT(handleHelpRequest(QUrl))); + m_filterSettingsPage->setHelpManager(m_helpManager); connect(m_filterSettingsPage, SIGNAL(filtersChanged()), this, SLOT(setupHelpEngineIfNeeded())); - connect(m_docSettingsPage, SIGNAL(documentationChanged()), this, + connect(Core::HelpManager::instance(), SIGNAL(documentationChanged()), this, SLOT(setupHelpEngineIfNeeded())); m_splitter = new Core::MiniSplitter; @@ -313,30 +310,20 @@ bool HelpPlugin::initialize(const QStringList &arguments, QString *error) void HelpPlugin::extensionsInitialized() { - const QString &filterInternal = QString::fromLatin1("Qt Creator %1.%2.%3") - .arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR).arg(IDE_VERSION_RELEASE); - const QRegExp filterRegExp(QLatin1String("Qt Creator \\d*\\.\\d*\\.\\d*")); - - QHelpEngineCore *engine = &m_helpManager->helpEngineCore(); - const QStringList &filters = engine->customFilters(); - foreach (const QString &filter, filters) { - if (filterRegExp.exactMatch(filter) && filter != filterInternal) - engine->removeCustomFilter(filter); - } - - const QString &docInternal = QString::fromLatin1("com.nokia.qtcreator.%1%2%3") + const QString &nsInternal = QString::fromLatin1("com.nokia.qtcreator.%1%2%3") .arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR).arg(IDE_VERSION_RELEASE); - foreach (const QString &ns, engine->registeredDocumentations()) { + Core::HelpManager *helpManager = Core::HelpManager::instance(); + foreach (const QString &ns, helpManager->registeredNamespaces()) { if (ns.startsWith(QLatin1String("com.nokia.qtcreator.")) - && ns != docInternal) - m_helpManager->unregisterDocumentation(QStringList() << ns); + && ns != nsInternal) + helpManager->unregisterDocumentation(QStringList() << ns); } QStringList filesToRegister; // Explicitly register qml.qch if located in creator directory. This is only // needed for the creator-qml package, were we want to ship the documentation - // without a qt development version. + // without a qt development version. TODO: is this still really needed, remove const QString &appPath = QCoreApplication::applicationDirPath(); filesToRegister.append(QDir::cleanPath(QDir::cleanPath(appPath + QLatin1String(DOCPATH "qml.qch")))); @@ -344,24 +331,6 @@ void HelpPlugin::extensionsInitialized() // we might need to register creators inbuild help filesToRegister.append(QDir::cleanPath(appPath + QLatin1String(DOCPATH "qtcreator.qch"))); - - // this comes from the installer - const QLatin1String key("AddedDocs"); - const QString &addedDocs = engine->customValue(key).toString(); - if (!addedDocs.isEmpty()) { - engine->removeCustomValue(key); - filesToRegister += addedDocs.split(QLatin1Char(';')); - } - - updateFilterComboBox(); - m_helpManager->verifyDocumenation(); - m_helpManager->registerDocumentation(filesToRegister); - - const QString &url = QString::fromLatin1("qthelp://com.nokia.qtcreator." - "%1%2%3/doc/index.html").arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR) - .arg(IDE_VERSION_RELEASE); - engine->setCustomValue(QLatin1String("DefaultHomePage"), url); - connect(engine, SIGNAL(setupFinished()), this, SLOT(updateFilterComboBox())); } void HelpPlugin::aboutToShutdown() @@ -424,7 +393,7 @@ void HelpPlugin::setupUi() // connect(shortcut, SIGNAL(activated()), this, SLOT(activateSearch())); // shortcutMap.insert("Search", cmd); - BookmarkManager *manager = &HelpManager::bookmarkManager(); + BookmarkManager *manager = &LocalHelpManager::bookmarkManager(); BookmarkWidget *bookmarkWidget = new BookmarkWidget(manager, 0, false); bookmarkWidget->setWindowTitle(tr("Bookmarks")); m_bookmarkItem = new Core::SideBarItem(bookmarkWidget, QLatin1String(SB_BOOKMARKS)); @@ -469,24 +438,36 @@ void HelpPlugin::setupUi() void HelpPlugin::resetFilter() { + const QString &filterInternal = QString::fromLatin1("Qt Creator %1.%2.%3") + .arg(IDE_VERSION_MAJOR).arg(IDE_VERSION_MINOR).arg(IDE_VERSION_RELEASE); + const QRegExp filterRegExp(QLatin1String("Qt Creator \\d*\\.\\d*\\.\\d*")); + + QHelpEngineCore *engine = &LocalHelpManager::helpEngine(); + const QStringList &filters = engine->customFilters(); + foreach (const QString &filter, filters) { + if (filterRegExp.exactMatch(filter) && filter != filterInternal) + engine->removeCustomFilter(filter); + } + const QLatin1String weAddedFilterKey("UnfilteredFilterInserted"); const QLatin1String previousFilterNameKey("UnfilteredFilterName"); - - QHelpEngineCore *core = &m_helpManager->helpEngineCore(); - if (core->customValue(weAddedFilterKey).toInt() == 1) { + if (engine->customValue(weAddedFilterKey).toInt() == 1) { // we added a filter at some point, remove previously added filter - const QString &filter = core->customValue(previousFilterNameKey).toString(); + const QString &filter = engine->customValue(previousFilterNameKey).toString(); if (!filter.isEmpty()) - core->removeCustomFilter(filter); + engine->removeCustomFilter(filter); } // potentially remove a filter with new name const QString filterName = tr("Unfiltered"); - core->removeCustomFilter(filterName); - core->addCustomFilter(filterName, QStringList()); - core->setCustomValue(weAddedFilterKey, 1); - core->setCustomValue(previousFilterNameKey, filterName); - (&m_helpManager->helpEngine())->setCurrentFilter(filterName); + engine->removeCustomFilter(filterName); + engine->addCustomFilter(filterName, QStringList()); + engine->setCustomValue(weAddedFilterKey, 1); + engine->setCustomValue(previousFilterNameKey, filterName); + engine->setCurrentFilter(filterName); + + updateFilterComboBox(); + connect(engine, SIGNAL(setupFinished()), this, SLOT(updateFilterComboBox())); } void HelpPlugin::createRightPaneContextViewer() @@ -594,9 +575,9 @@ void HelpPlugin::modeChanged(Core::IMode *mode) qApp->processEvents(); qApp->setOverrideCursor(Qt::WaitCursor); + m_helpManager->setupGuiHelpEngine(); setupUi(); resetFilter(); - m_helpManager->setupGuiHelpEngine(); OpenPagesManager::instance().setupInitialPages(); qApp->restoreOverrideCursor(); @@ -632,7 +613,7 @@ void HelpPlugin::fontChanged() if (!m_helpViewerForSideBar) createRightPaneContextViewer(); - const QHelpEngineCore &engine = m_helpManager->helpEngineCore(); + const QHelpEngine &engine = LocalHelpManager::helpEngine(); QFont font = qVariantValue(engine.customValue(QLatin1String("font"), m_helpViewerForSideBar->viewerFont())); @@ -646,7 +627,8 @@ void HelpPlugin::fontChanged() void HelpPlugin::setupHelpEngineIfNeeded() { - if (Core::ICore::instance()->modeManager()->currentMode() == m_mode) + m_helpManager->setEngineNeedsUpdate(); + if (Core::ModeManager::instance()->currentMode() == m_mode) m_helpManager->setupGuiHelpEngine(); } @@ -655,7 +637,7 @@ HelpViewer* HelpPlugin::viewerForContextMode() using namespace Core; bool showSideBySide = false; - const QHelpEngineCore &engine = m_helpManager->helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); RightPanePlaceHolder *placeHolder = RightPanePlaceHolder::current(); switch (engine.customValue(QLatin1String("ContextHelpOption"), 0).toInt()) { case 0: { @@ -712,7 +694,7 @@ void HelpPlugin::activateContext() // Find out what to show if (IContext *context = m_core->currentContextObject()) { id = context->contextHelpId(); - links = m_helpManager->helpEngineCore().linksForIdentifier(id); + links = Core::HelpManager::instance()->linksForIdentifier(id); } if (HelpViewer* viewer = viewerForContextMode()) { @@ -802,7 +784,7 @@ QToolBar *HelpPlugin::createToolBar() void HelpPlugin::updateFilterComboBox() { - const QHelpEngine &engine = m_helpManager->helpEngine(); + const QHelpEngine &engine = LocalHelpManager::helpEngine(); QString curFilter = m_filterComboBox->currentText(); if (curFilter.isEmpty()) curFilter = engine.currentFilter(); @@ -816,7 +798,7 @@ void HelpPlugin::updateFilterComboBox() void HelpPlugin::filterDocumentation(const QString &customFilter) { - (&m_helpManager->helpEngine())->setCurrentFilter(customFilter); + LocalHelpManager::helpEngine().setCurrentFilter(customFilter); } void HelpPlugin::addBookmark() @@ -827,7 +809,7 @@ void HelpPlugin::addBookmark() if (url.isEmpty() || url == Help::Constants::AboutBlank) return; - BookmarkManager *manager = &HelpManager::bookmarkManager(); + BookmarkManager *manager = &LocalHelpManager::bookmarkManager(); manager->showBookmarkDialog(m_centralWidget, viewer->title(), url); } @@ -836,7 +818,7 @@ void HelpPlugin::handleHelpRequest(const QUrl &url) if (HelpViewer::launchWithExternalApp(url)) return; - if (m_helpManager->helpEngineCore().findFile(url).isValid()) { + if (Core::HelpManager::instance()->findFile(url).isValid()) { if (url.queryItemValue(QLatin1String("view")) == QLatin1String("split")) { if (HelpViewer* viewer = viewerForContextMode()) viewer->setSource(url); diff --git a/src/plugins/help/helpplugin.h b/src/plugins/help/helpplugin.h index 1ac051cdfb1..9ad6644eb08 100644 --- a/src/plugins/help/helpplugin.h +++ b/src/plugins/help/helpplugin.h @@ -49,8 +49,6 @@ class SideBarItem; } // Core namespace Help { -class HelpManager; - namespace Internal { class CentralWidget; class DocSettingsPage; @@ -58,6 +56,7 @@ class FilterSettingsPage; class GeneralSettingsPage; class HelpMode; class HelpViewer; +class LocalHelpManager; class OpenPagesManager; class SearchWidget; @@ -129,7 +128,7 @@ private: Core::SideBar *m_sideBar; bool m_firstModeChange; - HelpManager *m_helpManager; + LocalHelpManager *m_helpManager; OpenPagesManager *m_openPagesManager; Core::MiniSplitter *m_splitter; diff --git a/src/plugins/help/helpviewer.cpp b/src/plugins/help/helpviewer.cpp index 3fa9fcc9481..d351a982265 100644 --- a/src/plugins/help/helpviewer.cpp +++ b/src/plugins/help/helpviewer.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include using namespace Help::Internal; @@ -126,7 +126,7 @@ QString HelpViewer::mimeFromUrl(const QUrl &url) bool HelpViewer::launchWithExternalApp(const QUrl &url) { if (isLocalUrl(url)) { - const QHelpEngineCore &helpEngine = Help::HelpManager::helpEngineCore(); + const QHelpEngineCore &helpEngine = LocalHelpManager::helpEngine(); const QUrl &resolvedUrl = helpEngine.findFile(url); if (!resolvedUrl.isValid()) return false; @@ -155,7 +155,7 @@ bool HelpViewer::launchWithExternalApp(const QUrl &url) void HelpViewer::home() { - const QHelpEngineCore &engine = Help::HelpManager::helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); QString homepage = engine.customValue(QLatin1String("HomePage"), QLatin1String("")).toString(); diff --git a/src/plugins/help/helpviewer_qwv.cpp b/src/plugins/help/helpviewer_qwv.cpp index abf812797e7..461eefafd91 100644 --- a/src/plugins/help/helpviewer_qwv.cpp +++ b/src/plugins/help/helpviewer_qwv.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include #include #include @@ -125,7 +125,7 @@ QNetworkReply *HelpNetworkAccessManager::createRequest(Operation /*op*/, const QNetworkRequest &request, QIODevice* /*outgoingData*/) { QString url = request.url().toString(); - const QHelpEngineCore &engine = HelpManager::helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); // TODO: For some reason the url to load is already wrong (passed from webkit) // though the css file and the references inside should work that way. One // possible problem might be that the css is loaded at the same level as the @@ -265,7 +265,7 @@ QFont HelpViewer::viewerFont() const QWebSettings* webSettings = QWebSettings::globalSettings(); QFont font(QApplication::font().family(), webSettings->fontSize(QWebSettings::DefaultFontSize)); - const QHelpEngineCore &engine = HelpManager::helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); return qVariantValue(engine.customValue(QLatin1String("font"), font)); } diff --git a/src/plugins/help/openpagesmanager.cpp b/src/plugins/help/openpagesmanager.cpp index 5396f05aac2..5762ee7686a 100644 --- a/src/plugins/help/openpagesmanager.cpp +++ b/src/plugins/help/openpagesmanager.cpp @@ -41,7 +41,7 @@ #include #include -#include +#include using namespace Help::Internal; @@ -118,7 +118,7 @@ QStringList splitString(const QVariant &value) void OpenPagesManager::setupInitialPages() { - const QHelpEngineCore &engine = HelpManager::helpEngineCore(); + const QHelpEngineCore &engine = LocalHelpManager::helpEngine(); const int option = engine.customValue(QLatin1String("StartOption"), Help::Constants::ShowLastPages).toInt(); QString homePage = engine.customValue(QLatin1String("DefaultHomePage"), diff --git a/src/plugins/help/searchwidget.cpp b/src/plugins/help/searchwidget.cpp index 933abd36890..5e564388a78 100644 --- a/src/plugins/help/searchwidget.cpp +++ b/src/plugins/help/searchwidget.cpp @@ -100,7 +100,7 @@ void SearchWidget::showEvent(QShowEvent *event) QVBoxLayout *vLayout = new QVBoxLayout(this); vLayout->setMargin(4); - searchEngine = (&HelpManager::helpEngine())->searchEngine(); + searchEngine = (&LocalHelpManager::helpEngine())->searchEngine(); resultWidget = searchEngine->resultWidget(); QHelpSearchQueryWidget *queryWidget = searchEngine->queryWidget(); @@ -126,7 +126,7 @@ void SearchWidget::showEvent(QShowEvent *event) connect(searchEngine, SIGNAL(indexingFinished()), this, SLOT(indexingFinished())); - QMetaObject::invokeMethod(&HelpManager::helpEngine(), "setupFinished", + QMetaObject::invokeMethod(&LocalHelpManager::helpEngine(), "setupFinished", Qt::QueuedConnection); } } diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 156d5ce9f8f..f59ddb97a4d 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -114,7 +114,6 @@ plugin_qt4projectmanager.depends = plugin_texteditor plugin_qt4projectmanager.depends += plugin_projectexplorer plugin_qt4projectmanager.depends += plugin_cpptools plugin_qt4projectmanager.depends += plugin_cppeditor -plugin_qt4projectmanager.depends += plugin_help plugin_qt4projectmanager.depends += plugin_designer plugin_qt4projectmanager.depends += plugin_debugger diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro index 0f0c3e238ce..d7f95441dd0 100644 --- a/src/plugins/qmljseditor/qmljseditor.pro +++ b/src/plugins/qmljseditor/qmljseditor.pro @@ -3,7 +3,6 @@ TARGET = QmlJSEditor include(../../qtcreatorplugin.pri) include(qmljseditor_dependencies.pri) -CONFIG += help DEFINES += \ QMLJSEDITOR_LIBRARY \ QT_CREATOR diff --git a/src/plugins/qmljseditor/qmljshoverhandler.cpp b/src/plugins/qmljseditor/qmljshoverhandler.cpp index 38cc47cae56..e3ed5011864 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.cpp +++ b/src/plugins/qmljseditor/qmljshoverhandler.cpp @@ -32,6 +32,7 @@ #include "qmljshoverhandler.h" #include +#include #include #include #include @@ -52,7 +53,6 @@ #include #include #include -#include using namespace Core; using namespace QmlJS; @@ -61,27 +61,11 @@ using namespace QmlJSEditor::Internal; HoverHandler::HoverHandler(QObject *parent) : QObject(parent) - , m_helpEngineNeedsSetup(false) { m_modelManager = ExtensionSystem::PluginManager::instance()->getObject(); - ICore *core = ICore::instance(); - QFileInfo fi(core->settings()->fileName()); - // FIXME shouldn't the help engine create the directory if it doesn't exist? - QDir directory(fi.absolutePath()+"/qtcreator"); - if (!directory.exists()) - directory.mkpath(directory.absolutePath()); - - m_helpEngine = new QHelpEngineCore(directory.absolutePath() - + QLatin1String("/helpcollection.qhc"), this); - if (!m_helpEngine->setupData()) - qWarning() << "Could not initialize help engine:" << m_helpEngine->error(); - m_helpEngine->setAutoSaveFilter(false); - m_helpEngine->setCurrentFilter(tr("Unfiltered")); - m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0; - // Listen for editor opened events in order to connect to tooltip/helpid requests - connect(core->editorManager(), SIGNAL(editorOpened(Core::IEditor *)), + connect(ICore::instance()->editorManager(), SIGNAL(editorOpened(Core::IEditor *)), this, SLOT(editorOpened(Core::IEditor *))); } @@ -151,11 +135,6 @@ void HoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int p const Snapshot snapshot = semanticInfo.snapshot; const Document::Ptr qmlDocument = semanticInfo.document; - if (m_helpEngineNeedsSetup && m_helpEngine->registeredDocumentations().count() > 0) { - m_helpEngine->setupData(); - m_helpEngineNeedsSetup = false; - } - // We only want to show F1 if the tooltip matches the help id bool showF1 = true; @@ -188,7 +167,7 @@ void HoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int p QString helpId = QLatin1String("QML."); helpId += baseClass; - if (! m_helpEngine->linksForIdentifier(helpId).isEmpty()) { + if (!Core::HelpManager::instance()->linksForIdentifier(helpId).isEmpty()) { m_helpId = helpId; break; } diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h index f41ad628678..2cffd888e04 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.h +++ b/src/plugins/qmljseditor/qmljshoverhandler.h @@ -35,7 +35,6 @@ #include QT_BEGIN_NAMESPACE -class QHelpEngineCore; class QPoint; class QStringList; QT_END_NAMESPACE @@ -80,10 +79,8 @@ private: private: ModelManagerInterface *m_modelManager; - QHelpEngineCore *m_helpEngine; QString m_helpId; QString m_toolTip; - bool m_helpEngineNeedsSetup; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec index 3a5b5e62c46..2b2e73472de 100644 --- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec +++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec @@ -18,7 +18,6 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General - diff --git a/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp b/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp index 1e82fc64e0e..c84cd25a884 100644 --- a/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp +++ b/src/plugins/qt4projectmanager/gettingstartedwelcomepagewidget.cpp @@ -31,6 +31,7 @@ #include "ui_gettingstartedwelcomepagewidget.h" #include +#include #include #include @@ -38,8 +39,6 @@ #include -#include - #include #include #include @@ -338,15 +337,13 @@ void GettingStartedWelcomePageWidget::slotOpenExample() void GettingStartedWelcomePageWidget::slotOpenHelpPage(const QString& url) { - Help::HelpManager *helpManager - = ExtensionSystem::PluginManager::instance()->getObject(); + Core::HelpManager *helpManager = Core::HelpManager::instance(); Q_ASSERT(helpManager); helpManager->handleHelpRequest(url); } void GettingStartedWelcomePageWidget::slotOpenContextHelpPage(const QString& url) { - Help::HelpManager *helpManager - = ExtensionSystem::PluginManager::instance()->getObject(); + Core::HelpManager *helpManager = Core::HelpManager::instance(); Q_ASSERT(helpManager); helpManager->handleHelpRequest(url % QLatin1String("?view=split")); } diff --git a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri index 5e11deb8b51..e40eac29c4b 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri +++ b/src/plugins/qt4projectmanager/qt4projectmanager_dependencies.pri @@ -1,7 +1,6 @@ include(../../plugins/projectexplorer/projectexplorer.pri) include(../../plugins/cpptools/cpptools.pri) include(../../plugins/cppeditor/cppeditor.pri) -include(../../plugins/help/help.pri) include(../../plugins/designer/designer.pri) include(../../plugins/debugger/debugger.pri) include(../../libs/symbianutils/symbianutils.pri) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 4b7fc1f1c87..02246c7c98b 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -211,8 +212,7 @@ QSet QtVersionManager::supportedTargetIds() const void QtVersionManager::updateDocumentation() { - Help::HelpManager *helpManager - = ExtensionSystem::PluginManager::instance()->getObject(); + Core::HelpManager *helpManager = Core::HelpManager::instance(); Q_ASSERT(helpManager); QStringList files; foreach (QtVersion *version, m_versions) { diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp index e8619922e00..21406b06470 100644 --- a/src/shared/help/bookmarkmanager.cpp +++ b/src/shared/help/bookmarkmanager.cpp @@ -50,10 +50,11 @@ #include #include #include -#include #include #include +#include + using namespace Help::Internal; BookmarkDialog::BookmarkDialog(BookmarkManager *manager, const QString &title, @@ -646,7 +647,7 @@ void BookmarkManager::saveBookmarks() QDataStream stream(&bookmarks, QIODevice::WriteOnly); readBookmarksRecursive(treeModel->invisibleRootItem(), stream, 0); - (&Help::HelpManager::helpEngineCore())->setCustomValue(QLatin1String("Bookmarks"), + (&LocalHelpManager::helpEngine())->setCustomValue(QLatin1String("Bookmarks"), bookmarks); } @@ -765,7 +766,7 @@ void BookmarkManager::setupBookmarkModels() QList lastDepths; QList parents; - QByteArray ba = Help::HelpManager::helpEngineCore() + QByteArray ba = LocalHelpManager::helpEngine() .customValue(QLatin1String("Bookmarks")).toByteArray(); QDataStream stream(ba); while (!stream.atEnd()) { diff --git a/src/shared/help/contentwindow.cpp b/src/shared/help/contentwindow.cpp index a8ed1f1613a..ef3479f170d 100644 --- a/src/shared/help/contentwindow.cpp +++ b/src/shared/help/contentwindow.cpp @@ -45,7 +45,7 @@ ContentWindow::ContentWindow() : m_contentWidget(0) , m_expandDepth(-2) { - m_contentWidget = (&Help::HelpManager::helpEngine())->contentWidget(); + m_contentWidget = (&LocalHelpManager::helpEngine())->contentWidget(); m_contentWidget->installEventFilter(this); m_contentWidget->viewport()->installEventFilter(this); m_contentWidget->setContextMenuPolicy(Qt::CustomContextMenu); diff --git a/src/shared/help/indexwindow.cpp b/src/shared/help/indexwindow.cpp index 1bc86d60ecf..b12d517c6d3 100644 --- a/src/shared/help/indexwindow.cpp +++ b/src/shared/help/indexwindow.cpp @@ -80,7 +80,7 @@ IndexWindow::IndexWindow() toolbar->setLayout(tbLayout); layout->addWidget(toolbar); - QHelpEngine *engine = &Help::HelpManager::helpEngine(); + QHelpEngine *engine = &LocalHelpManager::helpEngine(); m_indexWidget = engine->indexWidget(); m_indexWidget->installEventFilter(this); connect(engine->indexModel(), SIGNAL(indexCreationStarted()), this, From 16223cb83cd75b72489d4829bd48a6c0e7f8e7ce Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 10 Jun 2010 17:33:16 +0200 Subject: [PATCH 29/32] Doc - Removed fixed or obsolete issues and added a new issue for v2.0.0. Reviewed-by: con Reviewed-by: Friedemann Kleint Reviewed-by: dt --- doc/qtcreator.qdoc | 108 ++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 74 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 2dae548c89e..48ac15a99a5 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -5111,7 +5111,7 @@ specified in the \c CMake project file. Known issues for the current version can be found - \l{Known Issues of version 1.3.86}{here}. + \l{Known Issues}{here}. \section1 Adding External Libraries to a CMake Project @@ -7259,45 +7259,16 @@ \title Known Issues - There are some known issues with Qt Creator. - The development team is aware of them, there is no need to report them as bugs. + This section lists known issues in Qt Creator version 2.0.0. + The development team is aware of them, and therefore, you do not need to + report them as bugs. - \section1 Known Issues of Version 1.3.86 + For a list of fixed issues and added features, see the changelog file in + the qtcreator\dist folder or the \l{http://bugreports.qt.nokia.com}{Qt Bug Tracker}. + + \section1 General \list - \o On Windows, debugging a MinGW-built console application (with \gui{Run in terminal} - checked) using gdb does not work due to a bug in gdb related to attaching to - stopped processes (see \l{http://bugreports.qt.nokia.com/browse/QTCREATORBUG-1020}). - - \o Debugging Helper does not work while performing On-Device Debugging. - - \if defined(qtquick) - - \o QML Preview (Run Project) only works if built against Qt with - Declarative UI. - - \endif - - \o Setting breakpoints in code that is compiled into the binary more - than once does not work. - - \o On Linux and Windows, installing Qt with one user account and - then using it with another requires other users to manually set - the Qt version. On Windows, setting the MinGW location is - required as well. The same applies to the location of GDB for Symbian. - A workaround is to copy %APPDATA%/Nokia/qtcreator.ini (Windows) or - $HOME/.config/Nokia/QtCreator.ini (Linux) from the directory - of the user who installed Qt Creator to the other user. - This issue does not exist on Mac OS X. - \endlist - - \section1 Known Issues of Version 1.2.0 and 1.2.1 - - \list - \o Gdb on Windows may not work if the 'Embassy \reg Security Center' software - by 'Wave \reg Systems' is installed and active (causing crashes in \c{vxvault.dll)}). - - \o Only simple data types (POD) work in the Watch Window of CDB. \o Qt Creator uses SQLite for storing some of its settings. SQLite is known to have problems with certain NFS servers (most notably the @@ -7306,9 +7277,18 @@ NFS share and you encounter this issue, one option would be to switch to the nfs-kernel-server, or create a symlink so that the settings are stored locally. + \endlist - \section1 Known Issues of Version 1.1.0 + \section1 Editing + + \list + + \o Code completion does not support typedefs for nested classes. + + \endlist + + \section1 Projects \list \o Paths or file names containing spaces or special characters, e.g., @@ -7319,59 +7299,39 @@ items with names consisting of plain characters, numbers, underscores, and hyphens. - \o \c{.pro} files are reformatted if files have been added or removed. - Whitespace is not preserved. - - \o There is no IDE support for adding files to include (\c .pri) files. - \o There is no IDE support for adding/removing sub-projects. Project hierarchies (SUBDIRS template) have to be created manually. - \o The file system sidebar does not update automatically. As a - workaround, switch to another directory and then back. + \o Creating new \c CMake projects with Qt Creator is not supported. - \o Loading KDE4 designer plugins breaks the style in KDE < 4.2.1 - due to a bug in KDE. + \endlist - \o The DEFINES and INCLUDES set in \c{.pro} files are not dealt with - on a file-specific level. Because of this, handling of DEFINES has - been disabled completely. Also the \c{.qmake.cache} is not being - parsed. In general, the \c{.pro} file parser is incomplete and - problems are still to be expected. + \section1 Debugging - \o Code completion for generated UI header files is updated only - after a build. + \list - \o Code completion does not support typedefs for nested classes. + \o When debugging executables created by the GNU Compiler version 4.5.0 + (all platforms), some data types will not be displayed in the + \gui{Locals and Watchers} view due to missing debug information. - \o There is a kernel bug essentially making debugging unreliable on - 2.6.24 kernels for i386 (which is, unfortunately, the default on - Ubuntu 8.04). See - \l{https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/230315/} for - details. The only solution to this problem is to boot another - kernel. + \o On Windows, debugging a MinGW-built console application (with \gui{Run in terminal} + checked) using gdb does not work due to a bug in gdb related to attaching to + stopped processes (see \l{http://bugreports.qt.nokia.com/browse/QTCREATORBUG-1020}). + + \o Gdb on Windows may not work if the 'Embassy \reg Security Center' software + by 'Wave \reg Systems' is installed and active (causing crashes in \c{vxvault.dll)}). \o Gdb may take long to load debugging symbols, especially from large libraries like \c libQtWebKit. Starting the debugging module can take up to several minutes without visible progress. + \o Setting breakpoints in code that is compiled into the binary more + than once does not work. + \o Setting breakpoints in files that do not have unique absolute paths may fail. For example, remounting parts of a file system using the --bind mount option. - \o There is no syntax highlighting for \c CMake project files. - - \o Project files included from \c{CMakeLists.txt} are not shown in the - navigation tree. - - \o Using the Visual Studio Compiler with \c CMake is not supported. - - \o Creating new \c CMake projects with Qt Creator is not supported. - - \o Having more than one build directory for \c CMake is not supported. - - \o Changing the build directory for \c CMake after the initial import - is disabled. \endlist */ From e5f0ea6d036f8eba65c571349ac14158e6da6288 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 11 Jun 2010 14:21:45 +0200 Subject: [PATCH 30/32] Doc - Added fixed issues in 2.0.0 that were removed from known issues in Qt Creator manual. Reviewed-by: con --- dist/changes-2.0.0 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dist/changes-2.0.0 b/dist/changes-2.0.0 index 1a9ab1cbbc9..eef365f6f90 100644 --- a/dist/changes-2.0.0 +++ b/dist/changes-2.0.0 @@ -36,6 +36,11 @@ Editing the syntax highlighting. * Block selection defines a find & replace scope * Added customizable default file encoding (in addition to the project setting) + * Added syntax highlighting for CMake project files + * Fixed .pro files being reformatted if files have been added or removed. + In addition, whitespace is preserved + * Fixed the file system sidebar to update automatically + * Fixed updating code completion for generated UI header files CodePaster * Implemented new protocol of pastebin.com including list functionality @@ -55,6 +60,9 @@ Project support * Allow changing the build environment for Generic Projects * Added context menu options to open file manager or terminal in a files directory + * Fixed the DEFINES and INCLUDES set in .pro files to be dealt with + on a file-specific level and enabled the handling of DEFINES. + Also, the .qmake.cache is now parsed Debugging * Add on-device debugging for the Symbian platform using gdb @@ -72,6 +80,10 @@ Debugging names * pdb: Added some basic debugging for Python scripts based on pdb * Improvements in the dialogs, status messages, and general appearance + * Fixed debugging helpers to work while debugging applications on devices + * On Linux and Windows, enabled installing Qt with one user account and + then using it with another without workarounds + * Fixed all data types to work in the Watch Window of CDB Help From 3c6643cd75666bfc0ada05a0cffb48a230631b1a Mon Sep 17 00:00:00 2001 From: con Date: Fri, 11 Jun 2010 14:48:08 +0200 Subject: [PATCH 31/32] Fixes: Menu items disabled during keyboard navigation (Windows) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Thorbjørn Lindeijer Task-number: QTCREATORBUG-865 --- src/plugins/coreplugin/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 1555395c741..bde3a7ae25c 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -1078,8 +1078,8 @@ void MainWindow::updateFocusWidget(QWidget *old, QWidget *now) { Q_UNUSED(old) - // Prevent changing the context object just because the menu is activated - if (qobject_cast(now)) + // Prevent changing the context object just because the menu or a menu item is activated + if (qobject_cast(now) || qobject_cast(now)) return; IContext *newContext = 0; From 5e40846c2360877ddfbd54760e85b45929561373 Mon Sep 17 00:00:00 2001 From: con Date: Fri, 11 Jun 2010 15:33:11 +0200 Subject: [PATCH 32/32] Fixes: Not possible to tell whether "Operate by instruction" is enabled from Menu entry Don't show the icon of checkable items in the menu to avoid being affected by broken styles. Task-number: QTCREATORBUG-1173 --- src/plugins/debugger/debuggeractions.cpp | 1 + src/plugins/debugger/debuggermanager.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 7a8d7a3c485..ba95f5f380e 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -227,6 +227,7 @@ DebuggerSettings *DebuggerSettings::instance() "operation mode. In this mode, stepping operates on single " "instructions and the source location view also shows the " "disassembled instructions.")); + item->setIconVisibleInMenu(false); instance->insertItem(OperateByInstruction, item); item = new SavedAction(instance); diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index f9878aa2942..6bfa9b973e0 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -557,6 +557,7 @@ void DebuggerManager::init() d->m_actions.reverseDirectionAction->setChecked(false); d->m_actions.reverseDirectionAction->setIcon( QIcon(":/debugger/images/debugger_reversemode_16.png")); + d->m_actions.reverseDirectionAction->setIconVisibleInMenu(false); connect(d->m_actions.continueAction, SIGNAL(triggered()), this, SLOT(executeContinue()));