qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/0000755000015301777760000000000012323167643020740 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/ubuntu-qtcreator.png0000644000015301777760000003002012323167147024764 0ustar pbusernogroup00000000000000PNG  IHDR>asBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATx}i$uޗU=,q,N !"iJ&"@١PlK6V! %-[hraS,9lSuE*HB&D .b]=fgzG|Uӳ; Ծ|W܀pn 7܀q * xke-X@|w$bL47 @`G0m]'A rcqR -i9EQs9YȲ@ v@)Wm Mt6*kMZ;愒szr$O[eVTȑR* '\3j4#H6BZkC\F`(L eLCiyY& K"JyHBϹ\N; [qVdr #K6$+GQ/Avr^|ɴsy]myX90s$9%ǽZ.̝옜Qtqxy\;k5Mn%ord=8\^7 Ea2y$[9đsYb O#;|^E4GZVb!GDvWYy=gq-E@ O[YD`Rr"Hy0t)]]euiD%8?1ey][q^`.il=x r4i" ] a~0=s5MȹinVo.0sO$~(LnJ)^1-WhTMJeHoPڳPBU^F BNVJ b}ԐEºF[ĺDEZLx*FGFxW(7QSE0iV\w 8}Tr`+uk.y쮫ն0T#2.1燹DFBU"Q䷣ަIH.K(>E!9+ԍʅ@UJDzٴ4J}t (.]B<=P %ϒ#?J}D)–0)ÿLقL 0DV -L|+`M*PȬ0I=>vynv "ͫ.;DT$YiјC"=< t8G5OaR#lPrR iȧ/ QINVOEHLեz:)ix0]I[O_m=IE1mZV,5G04jbe08p)C"xڍ U}QiG%/9:{ _5ޗ 3Ӓ>},^ F* ߮w0ܝ2ijpv-ԶsRڦ0UT]/G~Z 5h͚JfBYp]sC*{5U /rI<o1"(TJ.0\gU*Xb'B~#&SO '@'uDmVގz$]N%BaJ'؜Lqo'z!VpUV\yҪ}PExCG~& Ê~F~"@xZu·TMd}ï #" zVXۨ9j: (-' >3nt˩4DJaq`:UN@|As2%,FeԶhUOǿktƁ8wyS{Юɮ ̥67WQI81BAt kQܽB1K?pb[ \O􀎶IB[?rJy/ 80yw/9:P&.(y,r ak07%ps˃"qCYHPNy~z P}K@bs.z ʷ-@EB(&˃( o#Czp%徖ڴN9=OPW2iH"I8a"7 +QVʭ B_|N@]^OQFu'!%'*hrezvL/s@4c>8PJ&sv^:cV4,![^.q-./{گ\sM}+{,pk0{ea+ !jPx%iW~^,u~=^Vب'sXBݸh=z8 ƸpoCPbNȟ lg,'?B|xOu&am z1.5p*^]XN]1668rH[.1-uRWqxkxc İqW ak'W586K8si%#Fhi ;(\ċ'pqUg0ߟ)^%p_4ؒ6Hȹv/[+N }(Լ=qp` U !ϞǠ1թZگhJ .%.k4DG$RImN_"13P;qo޲v+2Ȼ$?{i?~VXZ#Z8t թ Dhog}m޽s[}mWp(7@TI^W_~4"6'Mp,-^8seaUj!cTᩗ/766`M=s*ZAs J|̓f yϭ8z(ʔWF|%.(1eL dȞw$t8$Edh΂x鉰*`C܎ /g^8s[e:w:T6(Ypa}37ux n?r8CpDf1 z ڈ$9:(uY0hiqFvz VE3g؏n7`iPW>q45vhxzBJy?l%|7'q &_6K!6#gj ^O'nM7XiJBgh+VpeNuvv3nqp%${IRcHj{wɹo{o K/c}J5yŝ8!c&JpOKXۨy Π'$,FT)MD|H?%J]~GرM yxyHܦF+3?z/GV[bs^EK\ޘᖒx?XYF}v-xqW~lVIZ)Ʒ3"vG?5* "9O6^@厷W/1{o>}Ke.mL_<d $s.N!N(Kt, D*  OЬz } l^"=sy/'x~-yjE)@p;r,xvw/'mв{wcup:Q"\^yKiJ&UQol$&|[Kmf .%bB5H6POꐕH+c6g^OK>^r['?tBvdAi(Id퐻ݭl_ZW'nC-Z/StìMʑW/J!̙(9Ch D0]}!ܿ>Ɵ>g^L.ĦK^1h4k:;m.q|u|':}d~kF엤o , Ϡ&$87fq+A!,&l`ؖ,.oLǗ:k"HSU5 '!38oٕŇUC9A|emsuPNk2 O|{ⵄFut/z<|ԢODV,"s\xj\𬸩ں!؆pqYkQ q3bṂϞN:Ҡi|C?ܽ?)Kk&w5McZNaj:g}"C8WP/:&*;wZ;ȑ%Sbm\)d~!@'}D㤿u>G]GMUxs9O|ܙݎ+TSui:t; ul>XS)D-68._= [1/Q= Z &MZɗS߆=֮gO3xzy OK'/xB|YV_%}(nd'݃sk1q<=?S ܏ k#?{'ήcsR >nݿ&E|2 屵{pML ~8v2N1Ĥv3K%v/pxrwU[;M\n&>~3_y{ɹu_,+~֒s2[˾H4ylkw0gN҈7|HeGCQ#nn{Vx]<Ǩ۟?Рgpm{pm{f`R7hH>ᥛ6F5_Ul BUO"8N-Ēɿu"^|Jcow;:Fv`Enyqb7.վ 9SWh\rWSVf́Ȯ_y1{ww &/OZ ^ M׵d^iB&.ց{pf $ 90\.!^=[0UQ$Z%+4bRk ܥA& ȗgDt3!u-ը&~rPD|&MR=)jE0+8KkUr ۩ݻR/^{tt(R6v9oeZqM=4YJFmq}%UJ/W"Z>WAa%\f )4䎍ePjâ|ԏ/XҜc6GtcwY=`AcN_//C@|L&bNuLA%fy9`KصkW6X/RZAi!m aZc}+y10%-59 0ENJAݧPp-Z)T;,>&F +V}o__Ei,d4L/_V4~~,^9ML"ͥ-t/oFuσ`G`H&A @"@5IB] sʄa*Sgn+Wi46FORp i>pxd2ƤEPUJڋBkVZe6$w2/$ea#(CQj4*:@VP [pSQ6&K]I(a>~4Y8.S+}\٬QIWF]>K}1McL9x5{ #PMKLFW/[ ¶!]GhoJV biDdx}t+_$wsfTcJ/|IU~kFG❷pe?닱ZA΋Y⾆Ngâۻ}(TpKS7r ݲ 40˿qpZE/_AeWB;Y;s\Y(P8w,kvxUOv-"iwCrfu.+5pms|ɝqLPU꨷W [T5[~ u]k4M;z8S&1:<'27٪g"cmZz="j{noדp-/4K{ЍLϽ7pBU~X \Apd9-5{aDuxH㎟EQb0-"Hu Ujz=e,ÂXIrox a̵s UݡF{*Bp]N2,8*"WH 'tn6jA(8{v<ԩSH: d84"iL&y "e& PǴ3j+]F EPd8l ɓ'^/፵ ߼]}$'M01E]W4X__b k-ʲDQ-.'}HtY$}v,ZBesqi^%pMu.\`/=s_:1ʏ=|VR:Pm#iZEx[LAsM& $H 9릤\<|;>)ePֈ)D^^h4qkbܵŠӶ®%d+f$jFﺘcDŽTn91 )-Qs|\-lP^)ϮBs KGRًc:ac ~Or%yhܵ{  d(0r"VlnnN% ~%,j j\wqjNׅԍjcZy컁86ƾ8s V O݊VLƨk Z#Yx3H )E.ܠLƉ:?k4z~= 㖝My 8\T?y30`sHgՙ-iH A*sZlllҥKXYY8o70`y1)ӃV-%^Vd+t|E , sk0 qs5pJ I(|!bpY+C?|}1TɎ{^5w"\e8` A,:t(ŊhW O|ypMJE23eSix!(qc?y2n^gQk;iZ#qN9WNésk:5:1 hƠ( nCZmk,K9~,'=s.Zc4[=ٞ:=2\wT WD rtcTF( Px"Ey~bP wǗ_+~H\n +"wNh[hL)M W ?_ #ZJ6S7)Q{Z8V%; {aHtXrIb’aQػwClv-TXUx!r!,JO#NWZa f!_pM@I0Tœ]obh{CCRk^Jٻ|>ΖaY~!ǂR K;/SC\X~aJ,\)Y1_Y&!K|^+c^/_q!ػʒFCK.q#g zfd,j· Wm\*nL<(J#nopx^:9LNpnW>! y3 vF6*+_ʏVpik|[5ŏXl6DӔ< 9D@U $W@.}R &#O׍ [ (*5«[U$DrØh}#u>w(~13cG z=<ZIb_`sb7zgb8@:ui\OƮ8;y. 2{JXjxp<=/sUpHM7Q %>^I[1c8Zcߔ~}:wiD\Ɛ&:S;x4X\ڨ`+APyx^GH3B h1bkDH`G|>&~!7m9 \7:M'$cjDl'\S3= 8ȇ@hlf!!^o׻yfFJ[&N-4PU)" J w{0҄|(vv @66k5v7|U@U5Ad~O߆ؕ`4 (.tJ%0taf媪 ϟGyWqE@N*1'L* #3\\A)wh[aձˁR Dlrq|R l6.\3rل2K/}r͂YX؝#2e29iPh{3{LOi}(wy[jPO^Zv-&{O}cs5S z/_MPW0v:mL>[lsݐ?o~gBW?RL'8Dgv֤ۿ,Jrp4Ee[ǃ)N/|1NO?o<@> nW/ Rz6ۜ)vN+v%SzL{/!tȟi{P9|`´w x]| ҙIcXh'\a]fIxN#=kIh,VSOc=vUxRX@9}~NFZ+AL.ylxfD[Uz9ԠE!G&oy]NCD9_ֳٔcUE0$#W/GmkaSİkcxgw[0o8mN*hwG/AI״yx3[[03|0nExPby6Rˠf zvd:Zw᪻Ӈ2?N4{Y{5Ñ3D W=쳟|G }:@W0:@.}F"ŕAjDD>&ZL4|jogK:CH5yh;i֏9@G]em7޴y]ods`n?@^3 dӼ}kz(wxw\5QKo2h8gc=KޤA;>UڊT"é3<_ݻ:# +)%+|OM³4:rC<䓟_`pG'H ^V*xܩ`M{x[G纮q%|gg'|//Hr vo|!|/4)v|RO?k'~)' g_؊h++zB] Vq)~?|0KxS̐Id2SO=k?s?+j<i#"eUZ]׵뺨hXk5_Dgyt OyNѬbD4[z#;\@;$px4G*dUJ5EQTZj}}j{/—ȟM`4p e}/7Ywڿ/-..A_~vLs,d ?ƛhmt9qƿSH.UY7.Ug,EJ{~d,"rsbμj jH]I[A/Έu5ip= `@:sOsi@/D .] iu/!Gx~?/|[恭d4~!܀pfxG{@IENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/qtcreator-plugin-ubuntu.pro0000644000015301777760000000005012323167147026274 0ustar pbusernogroup00000000000000TEMPLATE = subdirs SUBDIRS = src/ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/LICENSE.LGPL0000644000015301777760000006350212323167147022507 0ustar pbusernogroup00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/0000755000015301777760000000000012323167643021527 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/0000755000015301777760000000000012323167643023051 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuwelcomemode.cpp0000644000015301777760000001211712323167147027321 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuwelcomemode.h" #include "ubuntuconstants.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuWelcomeMode::UbuntuWelcomeMode(QObject *parent) : Core::IMode(parent), m_declarativeView(new QDeclarativeView) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_WELCOME_DISPLAYNAME)); setIcon(QIcon(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_WELCOME_ICON))); setPriority(Core::Constants::P_MODE_WELCOME); setId(Ubuntu::Constants::UBUNTU_MODE_WELCOME); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_WELCOME)); QDeclarativeContext *context = m_declarativeView->rootContext(); context->setContextProperty(QLatin1String("welcomeMode"), this); m_declarativeView->setResizeMode(QDeclarativeView::SizeRootObjectToView); m_declarativeView->setMinimumWidth(860); m_declarativeView->setMinimumHeight(548); m_modeWidget = new QWidget; QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_modeWidget->setLayout(layout); Utils::StyledBar* styledBar = new Utils::StyledBar(m_modeWidget); layout->addWidget(styledBar); QScrollArea *scrollArea = new QScrollArea(m_modeWidget); scrollArea->setFrameShape(QFrame::NoFrame); layout->addWidget(scrollArea); scrollArea->setWidget(m_declarativeView); scrollArea->setWidgetResizable(true); m_declarativeView->setMinimumWidth(860); m_declarativeView->setMinimumHeight(548); connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), SLOT(modeChanged(Core::IMode*))); ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); connect(pluginManager, SIGNAL(objectAdded(QObject*)), SLOT(objectAdded(QObject*))); setWidget(m_modeWidget); //qDebug() << __PRETTY_FUNCTION__; } void UbuntuWelcomeMode::modeChanged(Core::IMode *mode) { Q_UNUSED(mode); } void UbuntuWelcomeMode::initialize() { //qDebug() << __PRETTY_FUNCTION__; QDeclarativeContext *context = m_declarativeView->rootContext(); context->setContextProperty(QLatin1String("pagesModel"), QVariant::fromValue(m_welcomeTabPluginList)); m_declarativeView->setSource(QUrl::fromLocalFile(Constants::UBUNTU_WELCOMESCREEN_QML)); m_declarativeView->show(); // Load existing welcome screen plugins - start /* QList loadedWelcomeScreenPlugins = ExtensionSystem::PluginManager::getObjects(); QDeclarativeEngine *engine = m_declarativeView->engine(); QStringList importPathList = engine->importPathList(); importPathList << Core::ICore::resourcePath() + QLatin1String("/welcomescreen") << QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/../" IDE_LIBRARY_BASENAME "/qtcreator")); engine->setImportPathList(importPathList); qDebug() << engine->importPathList(); qDebug() << "Checking for loaded plugins"; foreach (Utils::IWelcomePage *plugin, loadedWelcomeScreenPlugins) { qDebug() << "Load welcomepage plugin: " << plugin->title(); plugin->facilitateQml(engine); m_welcomeTabPluginList.append(plugin); } context->setContextProperty(QLatin1String("pagesModel"), QVariant::fromValue(m_welcomeTabPluginList)); qDebug() << "check complete";*/ // end } void UbuntuWelcomeMode::objectAdded(QObject* obj) { Q_UNUSED(obj); //qDebug() << __PRETTY_FUNCTION__; } void UbuntuWelcomeMode::newProject() { Core::ICore::showNewItemDialog(tr("New Project"), Core::IWizard::wizardsOfKind(Core::IWizard::ProjectWizard)); } void UbuntuWelcomeMode::openProject() { ProjectExplorer::ProjectExplorerPlugin::instance()->openOpenProjectDialog(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuvalidationresultmodel.cpp0000644000015301777760000003360112323167147031434 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntuvalidationresultmodel.h" #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { /*! * \class UbuntuValidationResultModel * Implements a model to show the output of the click-run-checks parser */ UbuntuValidationResultModel::UbuntuValidationResultModel(QObject *parent) : QAbstractItemModel(parent) , m_rootItem(new ClickRunChecksParser::DataItem()) , m_nextSectionOffset(0) { m_rootItem->type = QLatin1String("RootItem"); QHash roleNames; roleNames[TypeRole] = "TypeRole"; roleNames[LinkRole] = "LinkRole"; roleNames[DescriptionRole] = "DescriptionRole"; setRoleNames(roleNames); } UbuntuValidationResultModel::~UbuntuValidationResultModel() { delete m_rootItem; } void UbuntuValidationResultModel::clear() { beginRemoveRows(QModelIndex(),0,m_rootItem->children.size()-1); delete m_rootItem; m_rootItem = new ClickRunChecksParser::DataItem(); m_rootItem->type = QLatin1String("RootItem"); endRemoveRows(); } QModelIndex UbuntuValidationResultModel::index(int row, int column, const QModelIndex &parent) const { ClickRunChecksParser::DataItem* item = getItem(parent); if(!item) { return QModelIndex(); } if(row < 0 || row > item->children.length()-1 || column != 0){ return QModelIndex(); } ClickRunChecksParser::DataItem* indexItem = item->children[row]; return createIndex(row,column,indexItem); } QModelIndex UbuntuValidationResultModel::parent(const QModelIndex &child) const { if(!child.isValid()) return QModelIndex(); ClickRunChecksParser::DataItem* item = getItem(child); ClickRunChecksParser::DataItem* parentItem = item->parent; if(!parentItem || parentItem == m_rootItem) return QModelIndex(); ClickRunChecksParser::DataItem* ppItem = parentItem->parent; if(!ppItem) return QModelIndex(); int row = ppItem->children.indexOf(parentItem); Q_ASSERT_X(row >= 0,Q_FUNC_INFO,"Child must be a element of parent list"); return createIndex(row,0,parentItem); } int UbuntuValidationResultModel::rowCount(const QModelIndex &parent) const { int rC = 1; ClickRunChecksParser::DataItem* item = getItem(parent); if(item) rC = item->children.size(); return rC; } int UbuntuValidationResultModel::columnCount(const QModelIndex &parent) const { return 1; } QVariant UbuntuValidationResultModel::data(const QModelIndex &index, int role) const { if(!index.isValid()) return QVariant(); ClickRunChecksParser::DataItem* item = getItem(index); if(item == m_rootItem) return QVariant(); switch(role) { case Qt::DisplayRole: case Qt::EditRole: { QString text = item->type; return text; break; } case TypeRole: { return item->type; break; } case DescriptionRole: { return item->text; break; } case LinkRole: { return item->link; break; } case Qt::DecorationRole: switch(item->icon){ case ClickRunChecksParser::Warning: return QIcon(QLatin1String(":/projectexplorer/images/compile_warning.png")); case ClickRunChecksParser::Error: return QIcon(QLatin1String(":/projectexplorer/images/compile_error.png")); case ClickRunChecksParser::Check: return QIcon(QLatin1String(":/projectexplorer/images/run.png")); default: break; } break; } return QVariant(); } Qt::ItemFlags UbuntuValidationResultModel::flags(const QModelIndex &index) const { return QAbstractItemModel::flags(index); } QModelIndex UbuntuValidationResultModel::findFirstErrorItem() const { int parentRow = 0; foreach(const ClickRunChecksParser::DataItem* parentItem, m_rootItem->children) { int innerRow = 0; bool found = false; foreach(const ClickRunChecksParser::DataItem* item, parentItem->children) { if(item->icon == ClickRunChecksParser::Error || item->icon == ClickRunChecksParser::Warning) { found = true; break; } innerRow++; } if(found) { QModelIndex idx = index(innerRow,0,index(parentRow,0,QModelIndex())); return idx; } parentRow++; } return QModelIndex(); } void UbuntuValidationResultModel::appendItem(ClickRunChecksParser::DataItem *item) { beginInsertRows(QModelIndex(),m_rootItem->children.length(),m_rootItem->children.length()); item->parent = m_rootItem; m_rootItem->children.append(item); endInsertRows(); } ClickRunChecksParser::DataItem *UbuntuValidationResultModel::getItem(const QModelIndex &index) const { if(index.isValid()){ ClickRunChecksParser::DataItem* elem = static_cast(index.internalPointer()); if(elem) { return elem; } } return m_rootItem; } ClickRunChecksParser::DataItem::DataItem() : parent(0) , icon(ClickRunChecksParser::NoIcon) { } ClickRunChecksParser::DataItem::~DataItem() { qDeleteAll(children.begin(),children.end()); children.clear(); } /*! * \class ClickRunChecksParser * Implements a incremental parser for the click-run-checks output * As soon as a complete section is available (marked by start of * a new one) the section is parsed and a new item is emitted */ ClickRunChecksParser::ClickRunChecksParser(QObject *parent) : QObject(parent) , m_nextSectionOffset(0) , m_errorCount(0) , m_warnCount(0) { } /*! * \brief ClickRunChecksParser::beginRecieveData * Clear alls internal data and starts a completely new parse */ void ClickRunChecksParser::beginRecieveData(const QString &data) { m_data.clear(); m_nextSectionOffset = m_errorCount = m_warnCount = 0; m_data.append(data); bool canContinue = true; while(canContinue) canContinue=tryParseNextSection(); } /*! * \brief ClickRunChecksParser::addRecievedData * Appends new \a data to the internal buffer and tries to read * as far as possible and emit new items, the parser always requires * to find a new section start before considering the current section * to be available completely */ void ClickRunChecksParser::addRecievedData(const QString &data) { m_data.append(data); bool canContinue = true; while(canContinue) canContinue=tryParseNextSection(); } /*! * \brief ClickRunChecksParser::endRecieveData * Tells the parser every data is available now and it should just * parse until the end of the internal buffer */ void ClickRunChecksParser::endRecieveData(const QString &data) { m_data.append(data); bool canContinue = true; while(canContinue) canContinue=tryParseNextSection(true); } /*! * \brief UbuntuValidationResultModel::tryParseNextSection * Tries to parse the next output section from the dataString * * \return false if there is no next section */ bool ClickRunChecksParser::tryParseNextSection(bool dataComplete) { QRegularExpression re(QLatin1String("^([=]+[\\s]+[A-Za-z0-9\\-_]+[\\s]+[=]+)$")); // match section beginnings re.setPatternOptions(QRegularExpression::MultilineOption); QRegularExpressionMatchIterator matchIter = re.globalMatch(m_data,m_nextSectionOffset); if(!matchIter.hasNext()) return false; QRegularExpressionMatch match = matchIter.next(); int startOffset = match.capturedStart(1) + match.capturedLength(1); int endOffset = -1; if(matchIter.hasNext()) { QRegularExpressionMatch match = matchIter.next(); endOffset = match.capturedStart(); } if(endOffset < 0 && dataComplete) endOffset = m_data.length()-1; if(startOffset == -1 || endOffset == -1) return false; //set the offset for the next parse m_nextSectionOffset = endOffset; QString type = match.captured(1); type.remove(QLatin1String("=")); type = type.trimmed(); if(type == QLatin1String("click-check-lint") || type == QLatin1String("click-check-desktop") || type == QLatin1String("click-check-security") || type == QLatin1String("click-check-functional")) { parseJsonSection(type,startOffset,endOffset-startOffset); } else { //ignore unknown sections return true; } return true; } /*! * \brief ClickRunChecksParser::parseJsonSection * Parses a part of the input data, that can contain only a JSON object * or alternatively a single line starting with the string ERROR: * emits parsedNewItem if the section was parsed successfully */ void ClickRunChecksParser::parseJsonSection(const QString §ionName, int offset, int length) { QJsonParseError error; QString sectionData = m_data.mid(offset,length); sectionData = sectionData.trimmed(); if(sectionData.startsWith(QLatin1String("ERROR:"))) { QStringList lines = sectionData.split(QLatin1String("\n")); QString errLine = lines.size() > 0 ? lines[0] : sectionData; errLine.remove(QLatin1String("ERROR:")); emitTextItem(sectionName,errLine,Error); return; } QJsonDocument doc = QJsonDocument::fromJson(sectionData.toUtf8(),&error); if(error.error != QJsonParseError::NoError) { emitParseErrorItem(QString::fromLocal8Bit("Json Parse Error: %0").arg(error.errorString())); return; } if(!doc.isObject()) { emitParseErrorItem(QString::fromLocal8Bit("Json unexpected format")); return; } bool hasErrors = false; bool hasWarnings = false; DataItem* item = new DataItem(); item->text = QLatin1String("No description"); item->type = sectionName; item->icon = Check; // we are optimisic QJsonObject obj = doc.object(); QJsonValue errValue = obj.value(QLatin1String("error")); QJsonValue warnValue = obj.value(QLatin1String("warn")); QJsonValue infoValue = obj.value(QLatin1String("info")); if(errValue.isObject()) { QJsonObject errors = errValue.toObject(); QStringList keys = errors.keys(); hasErrors = (errors.keys().size() > 0); foreach(const QString &key, keys) { QJsonValue messageValue = errors.value(key); if(messageValue.isObject()){ QJsonObject messageObject = messageValue.toObject(); QString text = messageObject.value(QLatin1String("text")).toString(); DataItem* subItem = new DataItem(); subItem->parent = item; subItem->text = text; subItem->type = key; subItem->icon = Error; if(messageObject.keys().contains(QLatin1String("link"))) { subItem->link = QUrl::fromUserInput(messageObject.value(QLatin1String("link")).toString()); } item->children.append(subItem); } } } if(warnValue.isObject()) { QJsonObject warnings = warnValue.toObject(); QStringList keys = warnings.keys(); hasWarnings = (warnings.keys().size() > 0); foreach(const QString &key, keys) { QJsonValue messageValue = warnings.value(key); if(messageValue.isObject()){ QJsonObject messageObject = messageValue.toObject(); QString text = messageObject.value(QLatin1String("text")).toString(); DataItem* subItem = new DataItem(); subItem->parent = item; subItem->text = text; subItem->type = key; subItem->icon = Warning; item->children.append(subItem); } } } if(infoValue.isObject()) { QJsonObject infos = infoValue.toObject(); QStringList keys = infos.keys(); foreach(const QString &key, keys) { QJsonValue messageValue = infos.value(key); if(messageValue.isObject()){ QJsonObject messageObject = messageValue.toObject(); QString text = messageObject.value(QLatin1String("text")).toString(); DataItem* subItem = new DataItem(); subItem->parent = item; subItem->type = key; subItem->text = text; subItem->icon = Check; item->children.append(subItem); } } } if(hasErrors) item->icon = Error; else if(hasWarnings) item->icon = Warning; emit parsedNewTopLevelItem(item); } /*! * \brief ClickRunChecksParser::emitParseErrorItem * Creates a new Error DataItem and emits it */ void ClickRunChecksParser::emitParseErrorItem(const QString &text) { DataItem *elem = new DataItem(); elem->icon = Error; elem->type = QLatin1String("Error"); elem->text = text; emit parsedNewTopLevelItem(elem); } /*! * \brief ClickRunChecksParser::emitTextItem * Creates a new text item and emits it */ void ClickRunChecksParser::emitTextItem(const QString& type,const QString &text, const ItemIcon icon) { DataItem *elem = new DataItem(); elem->icon = icon; elem->type = type; elem->text = text; emit parsedNewTopLevelItem(elem); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntumenu.cpp0000644000015301777760000006604412323167204025767 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntumenu.h" #include "ubuntushared.h" #include "ubuntuconstants.h" #include "ubuntudeviceswidget.h" #include "ubuntuproject.h" #include "ubuntuclicktool.h" #include "ubuntudevice.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuMenu *UbuntuMenu::m_instance = 0; UbuntuMenu *UbuntuMenu::instance() { return m_instance; } QAction *UbuntuMenu::menuAction(const Core::Id &id) { UbuntuMenu* men = UbuntuMenu::instance(); if(men->m_actions.contains(id)) return men->m_actions[id]; return 0; } UbuntuMenu::UbuntuMenu(QObject *parent) : QObject(parent) { m_instance = this; m_obj = getMenuJSON(); connect(&m_ubuntuProcess,SIGNAL(message(QString)),this,SLOT(onMessage(QString))); connect(&m_ubuntuProcess,SIGNAL(finished(QString,int)),this,SLOT(onFinished(QString,int))); connect(&m_ubuntuProcess,SIGNAL(finished(const QProcess*,QString,int)),this,SLOT(onFinished(const QProcess*,QString,int))); connect(&m_ubuntuProcess,SIGNAL(started(QString)),this,SLOT(onStarted(QString))); connect(&m_ubuntuProcess,SIGNAL(error(QString)),this,SLOT(onError(QString))); connect(ProjectExplorer::ProjectExplorerPlugin::instance(),SIGNAL(updateRunActions()),this,SLOT(slotUpdateActions())); connect(UbuntuDevicesWidget::instance(),SIGNAL(updateDeviceActions()),this,SLOT(slotUpdateActions())); } void UbuntuMenu::slotUpdateActions() { ProjectExplorer::Project* startupProject = ProjectExplorer::SessionManager::startupProject(); bool isQmlProject = false; bool isQmakeProject = false; bool isUbuntuProject = false; bool isUbuntuHtmlProject = false; if (startupProject) { isQmlProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::QMLPROJECT_MIMETYPE)); isQmakeProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::QMAKE_MIMETYPE)); isUbuntuProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE)); isUbuntuHtmlProject = isProperUbuntuHtmlProject(startupProject); isUbuntuProject = isUbuntuProject || isUbuntuHtmlProject || isQmlProject; } //bool canRun = projectExplorerInstance->canRun(startupProject,ProjectExplorer::NormalRunMode); bool projectOpen = (startupProject!=NULL); bool deviceDetected = UbuntuDevicesWidget::instance()->deviceDetected(); foreach(QAction* act, m_actions) { bool requiresDevice = act->property(Constants::UBUNTU_MENUJSON_DEVICEREQUIRED).toBool(); bool requiresProject = act->property(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED).toBool(); bool requiresQmlProject = act->property(Constants::UBUNTU_MENUJSON_QMLPROJECTREQUIRED).toBool(); bool requiresQmakeProject = act->property(Constants::UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED).toBool(); bool requiresUbuntuProject = act->property(Constants::UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED).toBool(); bool requiresUbuntuHtmlProject = act->property(Constants::UBUNTU_MENUJSON_UBUNTUHTMLPROJECTREQUIRED).toBool(); bool actionEnabled = ( (requiresQmakeProject ? isQmakeProject : true) && (requiresQmlProject ? isQmlProject : true) && (requiresUbuntuHtmlProject ? isUbuntuHtmlProject : true) && (requiresDevice ? deviceDetected : true) && (requiresProject ? projectOpen : true) && (requiresUbuntuProject ? isUbuntuProject : true)); act->setEnabled( actionEnabled ); } } void UbuntuMenu::onStarted(QString cmd) { printToOutputPane(QString::fromLatin1(Constants::UBUNTUMENU_ONSTARTED).arg(cmd)); } void UbuntuMenu::onMessage(QString msg) { printToOutputPane(msg); } void UbuntuMenu::onError(QString msg) { printToOutputPane(QString::fromLatin1(Constants::UBUNTUMENU_ONERROR).arg(msg)); } void UbuntuMenu::onFinished(QString cmd, int code) { emit finished_action(cmd); printToOutputPane(QString::fromLatin1(Constants::UBUNTUMENU_ONFINISHED).arg(cmd).arg(code)); } void UbuntuMenu::onFinished(const QProcess *programm, QString cmd, int) { emit finished_action(programm,cmd); } QString UbuntuMenu::menuPath(QString fileName) { return Constants::UBUNTU_MENUPATH + fileName; } QJsonDocument UbuntuMenu::getMenuJSON() { QByteArray contents; QString errorMsg; if (readFile(menuPath(QLatin1String(Constants::UBUNTU_MENUJSON)),&contents, &errorMsg) == false) { qDebug() << __PRETTY_FUNCTION__ << errorMsg; } QJsonParseError error; QJsonDocument retval = QJsonDocument::fromJson(contents,&error); if (error.error != QJsonParseError::NoError) { qDebug() << error.errorString(); } return retval; } void UbuntuMenu::parseMenu(QJsonObject obj, Core::ActionContainer*& parent, const Core::Id &group) { if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_SUBMENU))) { QString menuName, menuId; if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_NAME))) { menuName = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_NAME)).toString(); } if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_ID))) { menuId = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_ID)).toString(); } Core::ActionContainer *actionContainer = Core::ActionManager::createMenu(Core::Id(menuId.toUtf8().constData())); actionContainer->menu()->setTitle(menuName); actionContainer->menu()->setObjectName(menuId); QJsonValue submenu = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_SUBMENU)); if (submenu.isArray()) { QJsonArray submenuArray = submenu.toArray(); for (int idx=0; idxaddMenu(actionContainer,group); } } else if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_ACTIONS))) { QString actionName; QString actionId; QString actionKeySequence; QString actionWorkingDirectory; QStringList contexts = QStringList()<setObjectName(actionId); act->setProperty(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED,actionProjectRequired); act->setProperty(Constants::UBUNTU_MENUJSON_DEVICEREQUIRED,actionDeviceRequired); act->setProperty(Constants::UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED,actionQmakeProjectRequired); act->setProperty(Constants::UBUNTU_MENUJSON_QMLPROJECTREQUIRED,actionQmlProjectRequired); act->setProperty(Constants::UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED,actionUbuntuProjectRequired); act->setProperty(Constants::UBUNTU_MENUJSON_UBUNTUHTMLPROJECTREQUIRED,actionUbuntuHtmlProjectRequired); act->setProperty(Constants::UBUNTU_MENUJSON_SAVEREQUIRED,actionSaveRequired); act->setProperty(Constants::UBUNTU_MENUJSON_CLICKTARGETREQUIRED,clickTargetRequired); connect(act, SIGNAL(triggered()), this, SLOT(menuItemTriggered())); m_actions.insert(Core::Id(actionId.toUtf8().constData()),act); foreach(const QString& context,contexts) { Core::Command *cmd = Core::ActionManager::registerAction(act, Core::Id(actionId.toUtf8().constData()), Core::Context(context.toUtf8().constData())); if (actionKeySequence.isEmpty() == false) { cmd->setDefaultKeySequence(QKeySequence(actionKeySequence)); } if (actionWorkingDirectory.isEmpty() == false) { act->setProperty(Constants::UBUNTU_MENUJSON_WORKINGDIRECTORY,actionWorkingDirectory); } //hide if the context does not match creators current context cmd->setAttribute(Core::Command::CA_Hide); if (parent == NULL) { qWarning() << Constants::ERROR_MSG_NO_MENU_DEFINED; } else { parent->addAction(cmd,group); } } } } bool UbuntuMenu::isProperUbuntuHtmlProject(ProjectExplorer::Project *project) const { if (Q_UNLIKELY(NULL == project)) return false; UbuntuProject* ubuntuProject = qobject_cast(project); if (NULL == ubuntuProject) return false; return ubuntuProject->filesFileName().endsWith(QLatin1String(Constants::UBUNTUHTMLPROJECT_SUFFIX)); } void UbuntuMenu::menuItemTriggered() { QAction* act = qobject_cast(sender()); if (act) { // if we are executing something now, then kill it! if (m_ubuntuProcess.state() != QProcess::NotRunning) { m_ubuntuProcess.stop(); } QVariant projectRequired = act->property(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED); ProjectExplorer::Project* project = NULL; if (projectRequired.isValid() && projectRequired.toBool() == true) { project = ProjectExplorer::SessionManager::startupProject(); if (project == NULL) { QMessageBox::information(Core::ICore::mainWindow(),QLatin1String(Constants::UBUNTU_DIALOG_NO_PROJECTOPEN_TITLE),QLatin1String(Constants::UBUNTU_DIALOG_NO_PROJECTOPEN_TEXT)); return; } } QVariant saveModifiedFilesRequired = act->property(Constants::UBUNTU_MENUJSON_SAVEREQUIRED); if (saveModifiedFilesRequired.isValid() && saveModifiedFilesRequired.toBool()==true) { ProjectExplorer::ProjectExplorerPlugin::instance()->saveModifiedFiles(); } if (m_commandMap.contains(act->objectName())) { QJsonValueList actions = m_commandMap.value(act->objectName()); QString queryData; bool bQueryOk = false; bool bQuery = false; for (int idx=0; idx < actions.size(); idx++) { QJsonValue value = actions.at(idx); if (value.isObject()) { QJsonObject obj = value.toObject(); // check if the object is a querydialog if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_QUERYDIALOG))) { QJsonValue queryDialog = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_QUERYDIALOG)); if (queryDialog.isObject()) { QJsonObject queryDialogObj = queryDialog.toObject(); QString queryDialogTitle; QString queryDialogMessage; QString queryDialogValue; if (queryDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE))) { queryDialogTitle = queryDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE)).toString(); } if (queryDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE))) { queryDialogMessage = queryDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE)).toString(); } if (queryDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_VALUE))) { queryDialogValue = queryDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_VALUE)).toString(); } queryData = QInputDialog::getText(Core::ICore::mainWindow(), queryDialogTitle, queryDialogMessage, QLineEdit::Normal, queryDialogValue, &bQueryOk); // raise a flag that there is query data available for future actions bQuery = true; // if user has cancelled if (bQueryOk == false) { // clear queue m_ubuntuProcess.clear(); return; } } // check if messageDialog } else if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGEDIALOG))) { QJsonValue messageDialog = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGEDIALOG)); if (messageDialog.isObject()) { QJsonObject messageDialogObj = messageDialog.toObject(); QString messageDialogTitle; QString messageDialogMessage; if (messageDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE))) { messageDialogTitle = messageDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE)).toString(); } if (messageDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE))) { messageDialogMessage = messageDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE)).toString(); } QMessageBox::information(Core::ICore::mainWindow(), messageDialogTitle, messageDialogMessage); } } // check if command } else if (value.isString()) { QString command = value.toString(); QString workingDirectory; if (project) { QString projectDirectory = project->projectDirectory(); QString displayName = project->displayName(); QString folderName = projectDirectory; // Bug 1212937 workaround folderName = folderName.replace(QString(QLatin1String("%0/")).arg(QFileInfo(projectDirectory).path()),QLatin1String("")); QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles); QString workingDirectoryData = act->property(Constants::UBUNTU_MENUJSON_WORKINGDIRECTORY).toString(); if (workingDirectoryData.isEmpty() == false) { workingDirectory = workingDirectoryData.arg(projectDirectory); } else { workingDirectory = projectDirectory; } command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_PROJECTDIRECTORY),projectDirectory); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_FOLDERNAME),folderName); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_DISPLAYNAME),displayName); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_PROJECTFILES),projectFiles.join(QLatin1String(" "))); if (isProperUbuntuHtmlProject(project)) { command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_APP_RUNNER_EXECNAME), QLatin1String(Constants::UBUNTUHTML_PROJECT_LAUNCHER_EXE)); } QVariant clickTargetRequired = act->property(Constants::UBUNTU_MENUJSON_CLICKTARGETREQUIRED); if(clickTargetRequired.isValid() && clickTargetRequired.toBool()) { UbuntuClickTool::Target clickTarget; if(!UbuntuClickTool::getTargetFromUser(&clickTarget)) return; command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_CLICK_PACKAGING_FOLDER) ,QString::fromLatin1(Constants::UBUNTU_CLICK_CLICK_PACKAGE_DIR)); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_CLICK_ARCH),clickTarget.architecture); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_CLICK_FRAMEWORK),clickTarget.framework); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_CLICK_SERIES),clickTarget.series); //this is a clicktarget, so we change the builddirectory to the current active buildconfig //directory ProjectExplorer::Target* qtcTarget = project->activeTarget(); if(!qtcTarget) return; ProjectExplorer::BuildConfiguration* qtcBuildConfig = qtcTarget->activeBuildConfiguration(); if(!qtcBuildConfig) return; workingDirectory = qtcBuildConfig->buildDirectory().toString(); } } UbuntuDevice::ConstPtr device = UbuntuDevicesWidget::instance()->device(); if (device) { command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_DEVICE_IP),device->sshParameters().host); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_DEVICE_USERNAME),device->sshParameters().userName); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_DEVICE_PORT),QString::number(device->sshParameters().port)); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_SERIALNUMBER),device->id().toSetting().toString()); } command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_SHAREDIRECTORY),Constants::UBUNTU_SHAREPATH); command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_SCRIPTDIRECTORY),Constants::UBUNTU_SCRIPTPATH); if (bQuery && bQueryOk) { command = QString(command).arg(queryData); } QStringList cmdList; cmdList << command << workingDirectory; m_ubuntuProcess.append(cmdList); } } m_ubuntuProcess.start(act->text()); } else { qWarning() << __PRETTY_FUNCTION__ << Constants::ERROR_MSG_NOACTIONS; } } else { qWarning() << __PRETTY_FUNCTION__ << Constants::ERROR_MSG_COULD_NOT_CAST_TO_ACTION; } } void UbuntuMenu::initialize() { if (m_obj.isObject()) { QJsonObject tmp = m_obj.object(); foreach (QString key, tmp.keys()) { if (tmp.contains(key)) { QJsonObject obj = tmp.value(key).toObject(); Core::ActionContainer *actionContainer = NULL; if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_PARENT))) { QString parentValue = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_PARENT)).toString(); if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_TOOLS)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS); else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_EDIT)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_EDIT); else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_HELP)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_HELP); else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_WINDOW)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW); else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_FILE)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_FILE); else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_BUILD)) actionContainer = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT); else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_TOP)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::MENU_BAR); else actionContainer = Core::ActionManager::actionContainer(Core::Id(parentValue.toUtf8().constData())); } else { actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS); } QString group; if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_GROUP))) { group = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_GROUP)).toString(); } Core::Id groupId; if (!group.isEmpty()) { groupId = Core::Id(group.toUtf8().constData()); } parseMenu(obj,actionContainer,groupId); } } } else { qWarning() << Constants::ERROR_MSG_UNABLE_TO_PARSE_MENUJSON; } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuversionmanager.h0000644000015301777760000000274112323167147027510 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUVERSIONMANAGER_H #define UBUNTUVERSIONMANAGER_H #include #include #include #include "ubuntuversion.h" #include "ubuntuconstants.h" namespace Ubuntu { namespace Internal { class UbuntuVersionManager : public QObject { Q_OBJECT public: UbuntuVersionManager(QObject *parent = 0); void detectAvailableVersions(); Core::FeatureSet availableFeatures(const QString &platformName) const; QStringList availablePlatforms() const; QString displayNameForPlatform(const QString &string) const; static UbuntuVersionManager* instance(); protected: static UbuntuVersionManager *m_self; UbuntuVersion* m_hostVersion; }; } } #endif // UBUNTUVERSIONMANAGER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntulocalrunconfiguration.h0000644000015301777760000000464512323167147031104 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTURUNCONFIGURATION_H #define UBUNTURUNCONFIGURATION_H #include #include #include #include namespace ProjectExplorer { class Target; } namespace Ubuntu { namespace Internal { class UbuntuLocalRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration { Q_OBJECT public: UbuntuLocalRunConfiguration(ProjectExplorer::Target *parent, Core::Id id); UbuntuLocalRunConfiguration(ProjectExplorer::Target *parent, UbuntuLocalRunConfiguration* source); QWidget *createConfigurationWidget(); bool isEnabled() const; // LocalApplicationRunConfiguration interface virtual QString executable() const; virtual QString workingDirectory() const; virtual QString commandLineArguments() const; virtual QString dumperLibrary() const; virtual QStringList dumperLibraryLocations() const; virtual RunMode runMode() const; virtual void addToBaseEnvironment(Utils::Environment &env) const; // RunConfiguration interface virtual bool ensureConfigured(QString *errorMessage); //static helpers static QString getDesktopFile (RunConfiguration *config, QString *appId, QString *errorMessage = 0); static bool readDesktopFile (const QString &desktopFile, QString *executable, QStringList *arguments, QString *errorMessage); private: bool ensureClickAppConfigured (QString *errorMessage); bool ensureScopesAppConfigured (QString *errorMessage); bool ensureUbuntuProjectConfigured (QString *errorMessage); private: QString m_executable; QString m_workingDir; QStringList m_args; }; } } #endif // UBUNTURUNCONFIGURATION_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucmakemakestep.h0000644000015301777760000000725312323167147027305 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUCMAKEMAKESTEP_H #define UBUNTU_INTERNAL_UBUNTUCMAKEMAKESTEP_H #include #include namespace Ubuntu { namespace Internal { class UbuntuCMakeMakeStepFactory : public ProjectExplorer::IBuildStepFactory { Q_OBJECT public: // IBuildStepFactory interface virtual QList availableCreationIds(ProjectExplorer::BuildStepList *parent) const; virtual QString displayNameForId(const Core::Id id) const; virtual bool canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const; virtual ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, const Core::Id id); virtual bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; virtual ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map); virtual bool canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const; virtual ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product); private: bool canHandle(const ProjectExplorer::Target *t) const; }; class UbuntuCMakeMakeStep : public CMakeProjectManager::MakeStep { Q_OBJECT public: UbuntuCMakeMakeStep(ProjectExplorer::BuildStepList *bsl); UbuntuCMakeMakeStep(ProjectExplorer::BuildStepList *bsl, UbuntuCMakeMakeStep *bs); virtual ~UbuntuCMakeMakeStep(); virtual QString makeCommand(ProjectExplorer::ToolChain *tc, const Utils::Environment &env) const; friend class UbuntuCMakeMakeStepFactory; }; class UbuntuCMakeDeployStep : public CMakeProjectManager::MakeStep { Q_OBJECT public: UbuntuCMakeDeployStep(ProjectExplorer::BuildStepList *bsl); UbuntuCMakeDeployStep(ProjectExplorer::BuildStepList *bsl, UbuntuCMakeDeployStep *bs); virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); virtual ~UbuntuCMakeDeployStep(); protected: virtual bool fromMap(const QVariantMap &map); friend class UbuntuCMakeMakeStepFactory; }; class UbuntuClickPackageStep : public ProjectExplorer::AbstractProcessStep { Q_OBJECT public: UbuntuClickPackageStep(ProjectExplorer::BuildStepList *bsl); UbuntuClickPackageStep(ProjectExplorer::BuildStepList *bsl, UbuntuClickPackageStep *bs); virtual ~UbuntuClickPackageStep(); virtual bool init(); virtual void run(QFutureInterface &fi); virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); QString packagePath () const; protected: // AbstractProcessStep interface virtual void stdOutput(const QString &line); virtual void stdError(const QString &line); virtual void processFinished(int exitCode, QProcess::ExitStatus status); private: QList m_tasks; QString m_lastLine; QString m_clickPackageName; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUCMAKEMAKESTEP_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsclickwidget.cpp0000644000015301777760000001356512323167147031103 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusettingsclickwidget.h" #include "ui_ubuntusettingsclickwidget.h" #include "ubuntuconstants.h" #include "ubuntuclicktool.h" #include "ubuntuclickdialog.h" #include #include #include #include #include using namespace Ubuntu; UbuntuSettingsClickWidget::UbuntuSettingsClickWidget(QWidget *parent) : QWidget(parent), ui(new Ui::UbuntuSettingsClickWidget) { ui->setupUi(this); m_settings = new QSettings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_CLICK)); ui->groupBox_4->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS),Constants::SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS).toBool()); ui->lineEditPackagingToolsLocation->setText(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS_LOCATION),QLatin1String(Constants::SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS_LOCATION)).toString()); m_settings->endGroup(); m_deleteMapper = new QSignalMapper(this); connect(m_deleteMapper, SIGNAL(mapped(int)),this, SLOT(on_deleteClickChroot(int))); m_maintainMapper = new QSignalMapper(this); connect(m_maintainMapper, SIGNAL(mapped(int)),this, SLOT(on_maintainClickChroot(int))); m_updateMapper = new QSignalMapper(this); connect(m_updateMapper, SIGNAL(mapped(int)),this, SLOT(on_upgradeClickChroot(int))); QStringList headers; headers << tr("Series")<< tr("Framework") << tr("Architecture")<treeWidgetClickTargets->setHeaderLabels(headers); listExistingClickTargets(); } void UbuntuSettingsClickWidget::apply() { m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_CLICK)); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS),ui->groupBox_4->isChecked()); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS_LOCATION),ui->lineEditPackagingToolsLocation->text()); m_settings->endGroup(); m_settings->sync(); } UbuntuSettingsClickWidget::~UbuntuSettingsClickWidget() { delete ui; } void UbuntuSettingsClickWidget::on_pushButtonFindClickPackagingTools_clicked() { QString path = QFileDialog::getExistingDirectory(this,QLatin1String(Constants::UBUNTUSETTINGSCLICKWIDGET_FILEDIALOG)); if (path.isEmpty()) return; ui->lineEditPackagingToolsLocation->setText(path); } void UbuntuSettingsClickWidget::on_pushButtonCreateClickTarget_clicked() { Internal::UbuntuClickDialog::createClickChrootModal(); listExistingClickTargets(); } void UbuntuSettingsClickWidget::on_deleteClickChroot(const int index) { if(index < 0 || index > m_availableTargets.size()) return; qDebug()<<"Destroying chroot "<< m_availableTargets.at(index); Internal::UbuntuClickDialog::maintainClickModal(m_availableTargets.at(index),Internal::UbuntuClickTool::Delete); listExistingClickTargets(); } void UbuntuSettingsClickWidget::on_maintainClickChroot(const int index) { if(index < 0 || index > m_availableTargets.size()) return; Internal::UbuntuClickTool::openChrootTerminal(m_availableTargets.at(index)); } void UbuntuSettingsClickWidget::on_upgradeClickChroot(const int index) { if(index < 0 || index > m_availableTargets.size()) return; Internal::UbuntuClickDialog::maintainClickModal(m_availableTargets.at(index),Internal::UbuntuClickTool::Upgrade); } /** * @brief UbuntuSettingsClickWidget::listExistingClickTargets * Lists all existing click targets in /var/lib/schroot/chroots * that match the click-- pattern */ void UbuntuSettingsClickWidget::listExistingClickTargets() { //this should hopefully also delete all mapped pushbuttons ui->treeWidgetClickTargets->clear(); QList items = Internal::UbuntuClickTool::listAvailableTargets(); m_availableTargets = items; QAbstractItemModel* model = ui->treeWidgetClickTargets->model(); //fill the treeview with all existing chroots for(int i = 0; i < items.size(); i++) { const Internal::UbuntuClickTool::Target& target = items.at(i); QTreeWidgetItem* chrootItem = new QTreeWidgetItem; chrootItem->setText(0,target.series); chrootItem->setText(1,target.framework); chrootItem->setText(2,target.architecture); ui->treeWidgetClickTargets->addTopLevelItem(chrootItem); QPushButton* push = new QPushButton(tr("Update")); m_updateMapper->setMapping(push,i); connect(push,SIGNAL(clicked()),m_updateMapper,SLOT(map())); ui->treeWidgetClickTargets->setIndexWidget(model->index(i,3), push); push = new QPushButton(tr("Maintain")); m_maintainMapper->setMapping(push,i); connect(push,SIGNAL(clicked()),m_maintainMapper,SLOT(map())); ui->treeWidgetClickTargets->setIndexWidget(model->index(i,4), push); push = new QPushButton(tr("Delete")); m_deleteMapper->setMapping(push,i); connect(push,SIGNAL(clicked()),m_deleteMapper,SLOT(map())); ui->treeWidgetClickTargets->setIndexWidget(model->index(i,5), push); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudeviceswidget.ui0000644000015301777760000011263112323167147027504 0ustar pbusernogroup00000000000000 UbuntuDevicesWidget 0 0 1456 741 Form 0 0 0 0 0 0 0 0 0 0 0 color: #DD4818 QFrame::Plain 3 Qt::Horizontal 9 9 0 50 Ubuntu 26 Ubuntu Device Qt::Horizontal 40 20 0 20 false color: rgba(0,0,0,0.2) QFrame::Plain 20 0 Qt::Horizontal 0 0 0 0 20 5 20 5 Ubuntu Serial number 200 0 Qt::Horizontal 40 20 Redetect Devices false QFrame::NoFrame true 0 0 1456 629 0 0 0 0 QTabWidget::tab-bar { alignment: center; } QTabWidget { border: 0; } QTabWidget::South 0 false false Device Actions 0 1 Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 Qt::Vertical 20 40 QFrame::NoFrame QFrame::Raised Ubuntu 12 50 false false No devices detected. Qt::AlignCenter Redetect devices <html><head/><body><p><span style=" font-size:16pt; font-weight:600;">Please wait</span></p><p><br/></p><p>See more details by changing to <span style=" font-style:italic;">Log</span> tab below.</p></body></html> Qt::AlignCenter Qt::Vertical 20 40 Qt::Horizontal QSizePolicy::MinimumExpanding 365 20 0 0 0 24 0 0 TextLabel 0 0 0 <html><head/><body><p><span style=" font-size:16pt;">Your device has been detected.</span></p><p>Next<span style=" font-weight:600; font-style:italic;"> you </span><span style=" font-weight:600; font-style:italic;">will need to Enable Developer Mode </span>from the right side.</p></body></html> Qt::RichText <html><head/><body><p><span style=" font-size:16pt;">Your device has been enabled for developer use!</span></p><p>You will find Ubuntu UI templates from <span style=" font-weight:600;">File &gt; New File or Project</span>. </p><p>After which you can deploy your app to the device using <span style=" font-weight:600; font-style:italic;">CTRL+F12</span> or<br/>by browsing <span style=" font-weight:600; font-style:italic;">Build &gt; Ubuntu Touch &gt; Run Application on Device.</span></p><p>You can also find screenshot feature from <span style=" font-weight:600; font-style:italic;">Tools &gt; Ubuntu Touch</span> and<br/>links from <span style=" font-weight:600; font-style:italic;">Help &gt; Ubuntu Touch</span>.</p><p><br/></p></body></html> Qt::Vertical 20 192 <html><head/><body><p><span style=" font-size:16pt;">No network connection on your device!</span></p><p>You will need to connect your device to a network with connection to the Internet. </p><p>Then replug the device to your workstation.<br/></p></body></html> Qt::Horizontal 40 20 Clone network config from host to device Qt::Horizontal 40 20 Qt::Vertical 20 192 0 0 Qt::Vertical 20 40 Executing following script in the background.. Qt::AlignCenter 20 TextLabel Qt::AlignCenter 24 Please wait.. if you like you can follow the progress on the <i>Log</i> tab at the bottom. Qt::AlignCenter Qt::Vertical 20 40 Emulators 0 0 Install emulator package The emulator package is not installed. Do you want to install? Qt::AlignCenter The installation of the emulator package is in progress. Please check the "Log" tab for details. Qt::AlignCenter 24 Qt::Horizontal 40 20 OK Qt::Horizontal 40 20 The "version" version of the "packagename" emulator package is installed. Create new emulator false 24 Name: Qt::Vertical 20 40 Start selected emulator false 18 75 true true Log QFrame::NoFrame QFrame::Raised 0 0 0 0 Ubuntu background: rgba(238,238,238,0.1) QFrame::Plain Qt::ScrollBarAlwaysOn Qt::ScrollBarAlwaysOff Utils::ProjectNameValidatingLineEdit QLineEdit
utils/projectnamevalidatinglineedit.h
qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusecuritypolicypickerdialog.ui0000644000015301777760000001307112323167147032321 0ustar pbusernogroup00000000000000 UbuntuSecurityPolicyPickerDialog 0 0 744 404 Add Security Policies 1 Qt::Vertical 20 40 Reading available policy groups from device.. 0 0 Qt::Vertical 20 40 Available Policy Groups 200 16777215 false true QAbstractItemView::ExtendedSelection QTextEdit::NoWrap true Qt::Vertical 20 40 Could not automatically detect policy groups (device not connected). Policy group: Qt::Vertical 20 40 Cancel Qt::Horizontal 40 20 Add qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingswidget.cpp0000644000015301777760000000535712323167147030075 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusettingswidget.h" #include "ui_ubuntusettingswidget.h" #include "ubuntuconstants.h" using namespace Ubuntu; UbuntuSettingsWidget::UbuntuSettingsWidget(QWidget *parent) : QWidget(parent), ui(new Ui::UbuntuSettingsWidget) { ui->setupUi(this); m_settings = new QSettings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_MODE)); ui->checkBox_mode_api->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_API),Constants::SETTINGS_DEFAULT_API_VISIBILITY).toBool()); ui->checkBox_mode_coreapps->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_COREAPPS),Constants::SETTINGS_DEFAULT_COREAPPS_VISIBILITY).toBool()); ui->checkBox_mode_irc->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_IRC),Constants::SETTINGS_DEFAULT_IRC_VISIBILITY).toBool()); ui->checkBox_mode_pastebin->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_PASTEBIN),Constants::SETTINGS_DEFAULT_PASTEBIN_VISIBILITY).toBool()); ui->checkBox_mode_wiki->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_WIKI),Constants::SETTINGS_DEFAULT_WIKI_VISIBILITY).toBool()); m_settings->endGroup(); } void UbuntuSettingsWidget::apply() { m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_MODE)); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_API),ui->checkBox_mode_api->isChecked()); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_COREAPPS),ui->checkBox_mode_coreapps->isChecked()); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_IRC),ui->checkBox_mode_irc->isChecked()); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_PASTEBIN),ui->checkBox_mode_pastebin->isChecked()); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_WIKI),ui->checkBox_mode_wiki->isChecked()); m_settings->endGroup(); m_settings->sync(); } UbuntuSettingsWidget::~UbuntuSettingsWidget() { delete ui; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingspage.h0000644000015301777760000000253312323167147027164 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSETTINGSPAGE_H #define UBUNTUSETTINGSPAGE_H #include //#include "ubuntuconstants.h" #include "ubuntusettingswidget.h" #include namespace Ubuntu { namespace Internal { class UbuntuSettingsPage : public Core::IOptionsPage { Q_OBJECT public: explicit UbuntuSettingsPage(); ~UbuntuSettingsPage(); QWidget *createPage(QWidget *parent); void apply(); void finish() { } protected: QPointer m_widget; }; } } #endif // UBUNTUSETTINGSPAGE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupolicygroupinfo.h0000644000015301777760000000257212323167147027722 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPOLICYGROUPINFO_H #define UBUNTUPOLICYGROUPINFO_H #include #include "ubuntuprocess.h" namespace Ubuntu { namespace Internal { class UbuntuPolicyGroupInfo : public QObject { Q_OBJECT public: explicit UbuntuPolicyGroupInfo(QObject *parent = 0); QString info() { return m_replies; } bool isLocal() { return m_bLocal; } public slots: void getInfo(QString); void onMessage(QString); void onFinished(QString, int); void onError(QString); signals: void infoReady(bool); protected: UbuntuProcess m_process; QString m_replies; QString m_policyGroup; bool m_bLocal; }; } } #endif // UBUNTUPOLICYGROUPINFO_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevicefactory.h0000644000015301777760000000277512323167147027326 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUDEVICEFACTORY_H #define UBUNTU_INTERNAL_UBUNTUDEVICEFACTORY_H #include namespace Ubuntu { namespace Internal { class UbuntuDeviceFactory : public ProjectExplorer::IDeviceFactory { Q_OBJECT public: UbuntuDeviceFactory(QObject* parent = 0); // IDeviceFactory interface virtual QString displayNameForId(Core::Id type) const; virtual QList availableCreationIds() const; virtual bool canCreate() const; virtual ProjectExplorer::IDevice::Ptr create(Core::Id id) const; virtual bool canRestore(const QVariantMap &map) const; virtual ProjectExplorer::IDevice::Ptr restore(const QVariantMap &map) const; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUDEVICEFACTORY_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprocess.cpp0000644000015301777760000001306312323167147026500 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuprocess.h" #include #include #include #include #include #include "ubuntuconstants.h" using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuProcess::UbuntuProcess(QObject *parent) : QObject(parent) , m_currentProcess(new QProcess(this)) , m_futureInterface(0) { connect(m_currentProcess,SIGNAL(readyReadStandardError()),this,SLOT(processReadyRead())); connect(m_currentProcess,SIGNAL(started()),this,SLOT(processStarted())); connect(m_currentProcess,SIGNAL(finished(int)),this,SLOT(processFinished(int))); connect(m_currentProcess,SIGNAL(readyRead()),this,SLOT(processReadyRead())); connect(m_currentProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(processError(QProcess::ProcessError))); } void UbuntuProcess::initializeProgressBar(QString title, int max) { if (m_futureInterface) { m_futureInterface->reportCanceled(); delete m_futureInterface; m_futureInterface = 0; } m_futureInterface = new QFutureInterface(); m_futureInterface->setProgressRange(0,max); Core::Id id(Constants::TASK_DEVICE_SCRIPT); Core::FutureProgress* futureProgress = Core::ProgressManager::addTask(m_futureInterface->future(),title,id.withSuffix(QUuid::createUuid().toString())); connect(futureProgress,SIGNAL(clicked()),this,SLOT(stop())); } void UbuntuProcess::setProgressBarStarted() { m_futureInterface->reportStarted(); } void UbuntuProcess::setProgressBarFinished() { m_futureInterface->reportFinished(); } void UbuntuProcess::increaseProgress(QString msg) { int currentValue = m_futureInterface->progressValue(); m_futureInterface->setProgressValueAndText(currentValue++,msg); } void UbuntuProcess::setProgressBarCancelled() { m_futureInterface->reportCanceled(); m_futureInterface->reportFinished(); } void UbuntuProcess::close() { m_currentProcess->close(); m_currentProcess->waitForFinished(); } void UbuntuProcess::stop() { kill(); } void UbuntuProcess::processStarted() { increaseProgress(m_currentProcess->program()); emit started(m_currentProcess->program()); } void UbuntuProcess::kill() { this->clear(); m_currentProcess->kill(); m_currentProcess->waitForFinished(); if(m_futureInterface) m_futureInterface->reportFinished(); } void UbuntuProcess::processError(QProcess::ProcessError err) { Q_UNUSED(err); if (m_currentProcess->exitCode() == 0) { return; } emit error(QString(QLatin1String("ERROR: (%0) %1")).arg(m_currentProcess->program()).arg(m_currentProcess->errorString())); // lets clear the remaining actions m_pendingProcesses.clear(); setProgressBarCancelled(); } void UbuntuProcess::start(QString taskTitle) { initializeProgressBar(taskTitle,m_pendingProcesses.length()); processCmdQueue(); } void UbuntuProcess::processFinished(int code) { if (code != 0) { emit error(QString::fromLocal8Bit(m_currentProcess->readAllStandardError())); m_pendingProcesses.clear(); setProgressBarCancelled(); //failing process has to emit finished too emit finished(m_currentProcess->program(), code); return; } QString errorMsg = QString::fromLocal8Bit(m_currentProcess->readAllStandardError()); if (errorMsg.trimmed().length()>0) emit error(errorMsg); QString msg = QString::fromLocal8Bit(m_currentProcess->readAllStandardOutput()); if (msg.trimmed().length()>0) emit message(msg); emit finished(m_currentProcess->program(), code); emit finished(m_currentProcess,m_currentProcess->program(),code); processCmdQueue(); } void UbuntuProcess::processReadyRead() { QString stderr = QString::fromLocal8Bit(m_currentProcess->readAllStandardError()); QString stdout = QString::fromLocal8Bit(m_currentProcess->readAllStandardOutput()); if (!stderr.isEmpty()) { emit message(stderr); } if (!stdout.isEmpty()) { emit message(stdout); } } void UbuntuProcess::processCmdQueue() { if (m_pendingProcesses.length() == 0) { setProgressBarFinished(); return; } QStringList cmdList = m_pendingProcesses.takeFirst(); QString cmd = cmdList.takeFirst(); QStringList args; QString workingDirectory; if (cmdList.length()>0) { workingDirectory = cmdList.takeLast(); } if (cmdList.length()>0) { args << cmdList; } if (!workingDirectory.isEmpty()) { m_currentProcess->setWorkingDirectory(workingDirectory); } QString msg(QString(QLatin1String("%0 %1")).arg(cmd).arg(args.join(QLatin1String(" ")))); //emit message(msg); m_currentProcess->setProperty("command",cmd); if (args.length()>0) { m_currentProcess->start(cmd,args); } else { m_currentProcess->start(cmd); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuemulatornotifier.cpp0000644000015301777760000000573312323167147030417 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntuemulatornotifier.h" #include #include namespace Ubuntu { namespace Internal { /*! * \class UbuntuEmulatorNotifier * Polls adb if a specific */ UbuntuEmulatorNotifier::UbuntuEmulatorNotifier(QObject *parent) : IUbuntuDeviceNotifier(parent) { m_pollTimout = new QTimer(this); m_pollProcess = new QProcess(this); connect(m_pollTimout,SIGNAL(timeout()),this,SLOT(pollTimeout())); connect(m_pollProcess,SIGNAL(readyRead()),this,SLOT(pollProcessReadyRead())); connect(m_pollProcess,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(pollProcessFinished(int,QProcess::ExitStatus))); } void UbuntuEmulatorNotifier::startMonitoring(const QString &serialNumber) { m_serial = serialNumber; m_pollTimout->setInterval(5000); m_pollTimout->start(); } void UbuntuEmulatorNotifier::stopMonitoring() { m_pollTimout->stop(); m_pollProcess->kill(); } bool UbuntuEmulatorNotifier::isConnected() const { return (m_lastState == QLatin1String("device")); } void UbuntuEmulatorNotifier::pollTimeout() { m_buffer.clear(); m_pollProcess->start(QLatin1String("adb"), QStringList() <readAllStandardOutput()); } void UbuntuEmulatorNotifier::pollProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitCode == 0 && exitStatus == QProcess::NormalExit) { QString str = QString::fromLocal8Bit(m_buffer.data()); QRegularExpression expr(QLatin1String("(device|unknown|offline|bootloader)")); QRegularExpressionMatch match = expr.match(str); if(match.hasMatch()) { bool wasConnected = isConnected(); QString newState = match.captured(1); if(newState != m_lastState) { m_lastState = newState; if(isConnected() && !wasConnected) emit deviceConnected(); else if(!isConnected() && wasConnected) emit deviceDisconnected(); } } } } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupackagingmode.cpp0000644000015301777760000001406012323167147027611 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntupackagingmode.h" #include "ubuntuconstants.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; UbuntuPackagingMode *UbuntuPackagingMode::m_instance = 0; UbuntuPackagingMode::UbuntuPackagingMode(QObject *parent) : Core::IMode(parent) { Q_ASSERT(m_instance == 0); m_instance = this; setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_PACKAGING_DISPLAYNAME)); setIcon(QIcon(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_PACKAGING_ICON))); setPriority(Ubuntu::Constants::UBUNTU_MODE_PACKAGING_PRIORITY); setId(Ubuntu::Constants::UBUNTU_MODE_PACKAGING); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_PACKAGING)); m_modeWidget = new QWidget; QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_modeWidget->setLayout(layout); Utils::StyledBar* styledBar = new Utils::StyledBar(m_modeWidget); layout->addWidget(styledBar); QScrollArea *scrollArea = new QScrollArea(m_modeWidget); scrollArea->setFrameShape(QFrame::NoFrame); layout->addWidget(scrollArea); scrollArea->setWidget(&m_ubuntuPackagingWidget); scrollArea->setWidgetResizable(true); connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), SLOT(modeChanged(Core::IMode*))); QObject* sessionManager = ProjectExplorer::SessionManager::instance(); connect(sessionManager,SIGNAL(projectAdded(ProjectExplorer::Project*)),SLOT(on_projectAdded(ProjectExplorer::Project*))); connect(sessionManager,SIGNAL(projectRemoved(ProjectExplorer::Project*)),SLOT(on_projectRemoved(ProjectExplorer::Project*))); connect(sessionManager,SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),SLOT(on_projectAdded(ProjectExplorer::Project*))); connect(&m_ubuntuPackagingWidget,SIGNAL(reviewToolsInstalledChanged(bool)),this,SLOT(updateModeState())); setWidget(m_modeWidget); setEnabled(false); } void UbuntuPackagingMode::initialize() { } UbuntuClickManifest *UbuntuPackagingMode::manifest() { return m_instance->m_ubuntuPackagingWidget.manifest(); } UbuntuClickManifest *UbuntuPackagingMode::appArmor() { return m_instance->m_ubuntuPackagingWidget.appArmor(); } void UbuntuPackagingMode::modeChanged(Core::IMode* currentMode) { if (currentMode->id() == id()) { ProjectExplorer::Project* startupProject = ProjectExplorer::SessionManager::startupProject(); bool isQmlProject = false; bool isQmakeProject = false; bool isUbuntuProject = false; bool isCMakeProject = false; if (startupProject) { isQmlProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::QMLPROJECT_MIMETYPE)); isQmakeProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::QMAKE_MIMETYPE)); isUbuntuProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE)); isCMakeProject = (startupProject->projectManager()->mimeType() == QLatin1String(CMakeProjectManager::Constants::CMAKEMIMETYPE)); } if (isQmlProject || isUbuntuProject || isCMakeProject) { m_ubuntuPackagingWidget.openManifestForProject(); m_ubuntuPackagingWidget.setAvailable(true); } else { m_ubuntuPackagingWidget.setAvailable(false); } } else if (previousMode == id()) { m_ubuntuPackagingWidget.save(); } previousMode = currentMode->id(); } void UbuntuPackagingMode::updateModeState() { ProjectExplorer::Project* startupProject = ProjectExplorer::SessionManager::startupProject(); bool isQmlProject = false; bool isQmakeProject = false; bool isUbuntuProject = false; bool isCMakeProject = false; bool reviewToolsInstalled = m_ubuntuPackagingWidget.reviewToolsInstalled(); if (startupProject) { isQmlProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::QMLPROJECT_MIMETYPE)); isQmakeProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::QMAKE_MIMETYPE)); isUbuntuProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE)); isCMakeProject = (startupProject->projectManager()->mimeType() == QLatin1String(CMakeProjectManager::Constants::CMAKEMIMETYPE)); } this->setEnabled((isQmlProject || isUbuntuProject || isCMakeProject || reviewToolsInstalled)); if (this->isEnabled()) { //save only if something was loaded if(m_ubuntuPackagingWidget.openManifestForProject()) { m_ubuntuPackagingWidget.save(); } } } void UbuntuPackagingMode::on_projectAdded(ProjectExplorer::Project *project) { Q_UNUSED(project); updateModeState(); } void UbuntuPackagingMode::on_projectRemoved(ProjectExplorer::Project *project) { Q_UNUSED(project); updateModeState(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubunturemotedeployconfiguration.h0000644000015301777760000000740212323167147031767 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUDEPLOYCONFIGURATION_H #define UBUNTU_INTERNAL_UBUNTUDEPLOYCONFIGURATION_H #include #include namespace RemoteLinux { class GenericDirectUploadService; } namespace Ubuntu { namespace Internal { class UbuntuDirectUploadStep : public RemoteLinux::AbstractRemoteLinuxDeployStep { Q_OBJECT public: UbuntuDirectUploadStep(ProjectExplorer::BuildStepList *bsl); UbuntuDirectUploadStep(ProjectExplorer::BuildStepList *bsl, UbuntuDirectUploadStep *other); ~UbuntuDirectUploadStep(); // BuildStep interface virtual void run(QFutureInterface &fi); ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); bool initInternal(QString *error = 0); RemoteLinux::AbstractRemoteLinuxDeployService *deployService() const; bool fromMap(const QVariantMap &map); QVariantMap toMap() const; static Core::Id stepId(); static QString displayName(); private slots: void projectNameChanged(); private: RemoteLinux::GenericDirectUploadService *m_deployService; }; class UbuntuDeployStepFactory : public ProjectExplorer::IBuildStepFactory { Q_OBJECT public: // IBuildStepFactory interface virtual QList availableCreationIds(ProjectExplorer::BuildStepList *parent) const; virtual QString displayNameForId(const Core::Id id) const; virtual bool canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const; virtual ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, const Core::Id id); virtual bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; virtual ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map); virtual bool canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const; virtual ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product); private: bool canHandle(const ProjectExplorer::Target *t) const; }; class UbuntuRemoteDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory { Q_OBJECT public: explicit UbuntuRemoteDeployConfigurationFactory(QObject *parent = 0); QList availableCreationIds(ProjectExplorer::Target *parent) const; QString displayNameForId(const Core::Id id) const; bool canCreate(ProjectExplorer::Target *parent, const Core::Id id) const; ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, const Core::Id id); bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const; ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map); ProjectExplorer::DeployConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *product); }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUDEPLOYCONFIGURATION_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubunturemotedeployconfiguration.cpp0000644000015301777760000003010312323167147032314 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubunturemotedeployconfiguration.h" #include "ubuntucmakebuildconfiguration.h" #include "ubuntucmakemakestep.h" #include "ubuntuconstants.h" #include "ubuntuprojectguesser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { UbuntuDirectUploadStep::UbuntuDirectUploadStep(ProjectExplorer::BuildStepList *bsl) : AbstractRemoteLinuxDeployStep(bsl, UbuntuDirectUploadStep::stepId()) , m_deployService(new RemoteLinux::GenericDirectUploadService(this)) { setDefaultDisplayName(displayName()); } UbuntuDirectUploadStep::UbuntuDirectUploadStep(ProjectExplorer::BuildStepList *bsl, UbuntuDirectUploadStep *other) : AbstractRemoteLinuxDeployStep(bsl, other) , m_deployService(new RemoteLinux::GenericDirectUploadService(this)) { setDefaultDisplayName(displayName()); connect(target()->project(),SIGNAL(displayNameChanged()),this,SLOT(projectNameChanged())); connect(target(),SIGNAL(applicationTargetsChanged()),this,SLOT(projectNameChanged())); } UbuntuDirectUploadStep::~UbuntuDirectUploadStep() { } void UbuntuDirectUploadStep::run(QFutureInterface &fi) { projectNameChanged(); m_deployService->setIncrementalDeployment(false); m_deployService->setIgnoreMissingFiles(false); QString whyNot; if(!deployService()->isDeploymentPossible(&whyNot)) { emit addOutput(tr("Deploy step failed. %1").arg(whyNot), ErrorMessageOutput); fi.reportResult(false); emit finished(); return; } AbstractRemoteLinuxDeployStep::run(fi); } ProjectExplorer::BuildStepConfigWidget *UbuntuDirectUploadStep::createConfigWidget() { return new ProjectExplorer::SimpleBuildStepConfigWidget(this); } bool UbuntuDirectUploadStep::initInternal(QString *error) { Q_UNUSED(error) return true; } RemoteLinux::AbstractRemoteLinuxDeployService *UbuntuDirectUploadStep::deployService() const { return m_deployService; } bool UbuntuDirectUploadStep::fromMap(const QVariantMap &map) { if (!AbstractRemoteLinuxDeployStep::fromMap(map)) return false; return true; } QVariantMap UbuntuDirectUploadStep::toMap() const { return AbstractRemoteLinuxDeployStep::toMap(); } Core::Id UbuntuDirectUploadStep::stepId() { return Constants::UBUNTU_DEPLOY_UPLOADSTEP_ID; } QString UbuntuDirectUploadStep::displayName() { return tr("Upload files to Ubuntu Device"); } static void createFileList(const QDir &rootDir , const QString& subDir , const QString& remoteRoot , QList* list) { QDir currentDir(rootDir.absolutePath()+subDir); if(!currentDir.exists()) return; QFileInfoList entries = currentDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); foreach (const QFileInfo &entry, entries) { if(entry.isDir()) { QString newSub = (subDir.endsWith(QLatin1String("/"))) ? (QString)(subDir+entry.fileName()) : (QString)(subDir+(QLatin1String("/")+entry.fileName())); createFileList(rootDir,newSub,remoteRoot,list); } else { QString targetPath = QDir::cleanPath(remoteRoot + subDir + QLatin1String("/")); qDebug()<<"Uploading: "<append(ProjectExplorer::DeployableFile(entry.absoluteFilePath() , targetPath , entry.isExecutable() ? ProjectExplorer::DeployableFile::TypeExecutable : ProjectExplorer::DeployableFile::TypeNormal)); } } } void UbuntuDirectUploadStep::projectNameChanged() { qDebug()<<"------------------------ Updating DEPLOYLIST ---------------------------"; //iterate over the .deploy dir and put all files in the list QDir d(target()->activeBuildConfiguration()->buildDirectory().toString()+QDir::separator()+QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR)); QList list; createFileList( d , QLatin1String("/") , QString::fromLatin1("/home/phablet/dev_tmp/%1").arg(target()->project()->displayName()) , &list); m_deployService->setDeployableFiles(list); target()->project()->displayName(); } UbuntuRemoteDeployConfigurationFactory::UbuntuRemoteDeployConfigurationFactory(QObject *parent) : DeployConfigurationFactory(parent) { setObjectName(QLatin1String("UbuntuDeployConfiguration")); } QList UbuntuRemoteDeployConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const { QList ids; if (!parent->project()->supportsKit(parent->kit())) return ids; ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(parent->kit()); if (!tc || tc->targetAbi().os() != ProjectExplorer::Abi::LinuxOS) return ids; //for now only support cmake projects if(parent->project()->id() != CMakeProjectManager::Constants::CMAKEPROJECT_ID) return ids; const Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(parent->kit()); if (devType == Constants::UBUNTU_DEVICE_TYPE_ID && !UbuntuProjectGuesser::isScopesProject(parent->project())) ids << Core::Id(Constants::UBUNTU_DEPLOYCONFIGURATION_ID); return ids; } QString UbuntuRemoteDeployConfigurationFactory::displayNameForId(const Core::Id id) const { if (id == Core::Id(Constants::UBUNTU_DEPLOYCONFIGURATION_ID)) return tr("Deploy to Ubuntu Device"); return QString(); } bool UbuntuRemoteDeployConfigurationFactory::canCreate(ProjectExplorer::Target *parent, const Core::Id id) const { return availableCreationIds(parent).contains(id); } ProjectExplorer::DeployConfiguration *UbuntuRemoteDeployConfigurationFactory::create(ProjectExplorer::Target *parent, const Core::Id id) { Q_ASSERT(canCreate(parent, id)); ProjectExplorer::DeployConfiguration * const dc = new RemoteLinux::RemoteLinuxDeployConfiguration(parent, id, tr("Deploy to Ubuntu Device")); int step = 0; if(parent->project()->id() == Core::Id(CMakeProjectManager::Constants::CMAKEPROJECT_ID)){ UbuntuCMakeDeployStep* mkStep = new UbuntuCMakeDeployStep(dc->stepList()); mkStep->setUseNinja(false); dc->stepList()->insertStep(0, mkStep); step++; } dc->stepList()->insertStep(step+1, new RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep(dc->stepList())); UbuntuDirectUploadStep* upload = new UbuntuDirectUploadStep(dc->stepList()); dc->stepList()->insertStep(step+2,upload); return dc; } bool UbuntuRemoteDeployConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const { return canCreate(parent, ProjectExplorer::idFromMap(map)); } ProjectExplorer::DeployConfiguration *UbuntuRemoteDeployConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map) { if (!canRestore(parent, map)) return 0; Core::Id id = ProjectExplorer::idFromMap(map); RemoteLinux::RemoteLinuxDeployConfiguration * const dc = new RemoteLinux::RemoteLinuxDeployConfiguration(parent, id, tr("Deploy to Ubuntu Device")); if (!dc->fromMap(map)) { delete dc; return 0; } return dc; } ProjectExplorer::DeployConfiguration *UbuntuRemoteDeployConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *product) { if (!canClone(parent, product)) return 0; return new RemoteLinux::RemoteLinuxDeployConfiguration(parent ,qobject_cast(product)); } QList UbuntuDeployStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const { if(!canHandle(parent->target())) return QList(); return QList() <target())) return false; return availableCreationIds(parent).contains(id); } ProjectExplorer::BuildStep *UbuntuDeployStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id) { if (!canCreate(parent, id)) return 0; if(id == Constants::UBUNTU_DEPLOY_UPLOADSTEP_ID) return new UbuntuDirectUploadStep(parent); return 0; } bool UbuntuDeployStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const { return canCreate(parent,ProjectExplorer::idFromMap(map)); } ProjectExplorer::BuildStep *UbuntuDeployStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) { Core::Id id = ProjectExplorer::idFromMap(map); if(!canCreate(parent,id)) return 0; ProjectExplorer::BuildStep* step = create(parent,id); if (!step->fromMap(map)) { delete step; return 0; } return step; } bool UbuntuDeployStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const { return canCreate(parent,product->id()); } ProjectExplorer::BuildStep *UbuntuDeployStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) { if (!canClone(parent, product)) return 0; const Core::Id id = product->id(); if(id == Constants::UBUNTU_DEPLOY_UPLOADSTEP_ID) return new UbuntuDirectUploadStep(parent, static_cast(product)); return 0; } bool UbuntuDeployStepFactory::canHandle(const ProjectExplorer::Target *t) const { QTC_ASSERT(t, return false); if (!t->project()->supportsKit(t->kit())) return false; ProjectExplorer::ToolChain* tc = ProjectExplorer::ToolChainKitInformation::toolChain(t->kit()); if(!tc || tc->type() != QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) return false; return (t->project()->id() == Core::Id(CMakeProjectManager::Constants::CMAKEPROJECT_ID) && !UbuntuProjectGuesser::isScopesProject(t->project())); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntubzr.h0000644000015301777760000000251112323167147025260 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUBZR_H #define UBUNTUBZR_H #include #include namespace Ubuntu { namespace Internal { class UbuntuBzr : public QObject { Q_OBJECT public: explicit UbuntuBzr(QObject *parent = 0); signals: void initializedChanged(); public slots: bool isInitialized() { return m_bInitialized; } QString whoami() { return m_whoami; } QString launchpadId() { return m_launchpadId; } void initialize(); protected slots: void scriptExecuted(int); protected: bool m_bInitialized; QString m_whoami; QString m_launchpadId; QProcess m_cmd; }; } } #endif // UBUNTUBZR_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntu.pri0000644000015301777760000000004312323167147025103 0ustar pbusernogroup00000000000000LIBS += -lUbuntu INCLUDEPATH += .. qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntulocalrunconfiguration.cpp0000644000015301777760000003321412323167147031431 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntulocalrunconfiguration.h" #include "ubuntuproject.h" #include "ubuntuprojectguesser.h" #include "ubuntuclickmanifest.h" #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; UbuntuLocalRunConfiguration::UbuntuLocalRunConfiguration(ProjectExplorer::Target *parent, Core::Id id) : ProjectExplorer::LocalApplicationRunConfiguration(parent, id) { setDisplayName(parent->project()->displayName()); addExtraAspect(new ProjectExplorer::LocalEnvironmentAspect(this)); } UbuntuLocalRunConfiguration::UbuntuLocalRunConfiguration(ProjectExplorer::Target *parent, UbuntuLocalRunConfiguration *source) : ProjectExplorer::LocalApplicationRunConfiguration(parent,source) { } QWidget *UbuntuLocalRunConfiguration::createConfigurationWidget() { return NULL; } bool UbuntuLocalRunConfiguration::isEnabled() const { return true; } QString UbuntuLocalRunConfiguration::executable() const { return m_executable; } QString UbuntuLocalRunConfiguration::workingDirectory() const { return m_workingDir; } QString UbuntuLocalRunConfiguration::commandLineArguments() const { return Utils::QtcProcess::joinArgs(m_args); } QString UbuntuLocalRunConfiguration::dumperLibrary() const { return QtSupport::QtKitInformation::dumperLibrary(target()->kit()); } QStringList UbuntuLocalRunConfiguration::dumperLibraryLocations() const { return QtSupport::QtKitInformation::dumperLibraryLocations(target()->kit()); } ProjectExplorer::LocalApplicationRunConfiguration::RunMode UbuntuLocalRunConfiguration::runMode() const { return Gui; } bool UbuntuLocalRunConfiguration::ensureConfigured(QString *errorMessage) { if(!LocalApplicationRunConfiguration::ensureConfigured(errorMessage)) return false; if(UbuntuProjectGuesser::isClickAppProject(target()->project())) return ensureClickAppConfigured(errorMessage); else if(UbuntuProjectGuesser::isScopesProject(target()->project())) return ensureScopesAppConfigured(errorMessage); return ensureUbuntuProjectConfigured(errorMessage); } QString UbuntuLocalRunConfiguration::getDesktopFile(ProjectExplorer::RunConfiguration* config, QString *appId, QString *errorMessage) { QString manifestPath; if(qobject_cast(config)) { //For a locally compiled project, we have no CLICK_MODE enabled, that means we have to search //the project and build trees for our desktop file so we can query the main qml file from the desktop file *appId = config->target()->project()->displayName(); QRegularExpression desktopFinder = QRegularExpression(QString::fromLatin1("^%1.desktop$") .arg(*appId)); QFileInfo desktopInfo = UbuntuProjectGuesser::findFileRecursive(config->target()->activeBuildConfiguration()->buildDirectory(), desktopFinder).toFileInfo(); if (!desktopInfo.exists()) { //search again in the project directory desktopInfo = UbuntuProjectGuesser::findFileRecursive(Utils::FileName::fromString(config->target()->project()->projectDirectory()), desktopFinder).toFileInfo(); if(!desktopInfo.exists()) { if(errorMessage) *errorMessage = tr("Could not find a desktop file for project"); } } return desktopInfo.absoluteFilePath(); } QDir package_dir(config->target()->activeBuildConfiguration()->buildDirectory().toString()+QDir::separator()+QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR)); if(!package_dir.exists()) { if(errorMessage) *errorMessage = tr("No packaging directory available, please check if the deploy configuration is correct."); return QString(); } manifestPath = package_dir.absoluteFilePath(QLatin1String("manifest.json")); //read the manifest UbuntuClickManifest manifest; if(!manifest.load(manifestPath,config->target()->project()->displayName())) { if(errorMessage) *errorMessage = tr("Could not open the manifest file in the package directory, maybe you have to create one."); return QString(); } QList hooks = manifest.hooks(); if (hooks.isEmpty()) { if(errorMessage) *errorMessage = tr("No valid hooks property in the manifest"); } *appId = hooks[0].appId; return QDir::cleanPath(package_dir.absoluteFilePath(hooks[0].desktopFile)); } bool UbuntuLocalRunConfiguration::readDesktopFile(const QString &desktopFile, QString *executable, QStringList *arguments, QString *errorMessage) { QFile desktop(desktopFile); if(!desktop.exists()) { if(errorMessage) *errorMessage = tr("Desktop file does not exist"); return false; } if(!desktop.open(QIODevice::ReadOnly)) { if(errorMessage) *errorMessage = tr("Could not open desktop file for reading"); return false; } QString execLine; QString name; QTextStream in(&desktop); while(!in.atEnd()) { QString line = in.readLine(); if(line.startsWith(QLatin1String("#"))) continue; line = line.mid(0,line.indexOf(QChar::fromLatin1('#'))).trimmed(); if(line.startsWith(QLatin1String("Exec"),Qt::CaseInsensitive)) { execLine = line.mid(line.indexOf(QChar::fromLatin1('='))+1); qDebug()<<"Found exec line: "<activeBuildConfiguration()->buildDirectory().toString() + QDir::separator() + QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR); QFileInfo commInfo(command); if(commInfo.fileName().startsWith(QLatin1String("qmlscene"))) { m_executable = QtSupport::QtKitInformation::qtVersion(target()->kit())->qmlsceneCommand(); QString mainQml; foreach(const QString &arg, args) { if(arg.contains(QLatin1String(".qml"))) { QFileInfo info(arg); mainQml = info.fileName(); } } if(mainQml.isEmpty()) { if(errorMessage) *errorMessage = tr("Could not get the main qml file from the desktop EXEC line."); return false; } QFileInfo mainFileInfo = UbuntuProjectGuesser::findFileRecursive(Utils::FileName::fromString(target()->project()->projectDirectory()), QString::fromLatin1("^%1$").arg(mainQml)).toFileInfo(); if(!mainFileInfo.exists()) { if(errorMessage) *errorMessage = tr("Could not find the main qml file (%1) in the project directory.").arg(mainQml); return false; } m_args = QStringList()< (target()->project()); QList targets = proj->buildTargets(); foreach (const CMakeProjectManager::CMakeBuildTarget& t, targets) { if(t.library) continue; QFileInfo targetInfo(t.executable); if(!targetInfo.exists()) continue; if(targetInfo.fileName() == commInfo.fileName()) { m_executable = targetInfo.absoluteFilePath(); break; } } if (m_executable.isEmpty()) { if(errorMessage) tr("Could not find executable specified in the desktop file"); return false; } m_args = args; m_workingDir = target()->project()->projectDirectory(); } qDebug()<<"Configured with: "<activeBuildConfiguration()->buildDirectory().toString(); Utils::Environment env = Utils::Environment::systemEnvironment(); m_executable = env.searchInPath(QString::fromLatin1(Ubuntu::Constants::UBUNTUSCOPES_PROJECT_LAUNCHER_EXE)); if(m_executable.isEmpty()) { if(errorMessage) *errorMessage = tr("Could not find launcher %1 in path").arg(QLatin1String(Ubuntu::Constants::UBUNTUSCOPES_PROJECT_LAUNCHER_EXE)); return false; } Utils::FileName iniFile = UbuntuProjectGuesser::findScopesIniRecursive(target()->activeBuildConfiguration()->buildDirectory()); if(iniFile.toFileInfo().exists()) m_args = QStringList()<(target()->project()); if (ubuntuProject) { m_workingDir = ubuntuProject->projectDirectory(); if (ubuntuProject->mainFile().compare(QString::fromLatin1("www/index.html"), Qt::CaseInsensitive) == 0) { Utils::Environment env = Utils::Environment::systemEnvironment(); m_executable = env.searchInPath(QString::fromLatin1(Ubuntu::Constants::UBUNTUHTML_PROJECT_LAUNCHER_EXE)); m_args = QStringList()<projectDirectory()) <kit())->qmlsceneCommand(); m_args = QStringList()<displayName()); } if(m_executable.isEmpty()) { if(errorMessage) *errorMessage = tr("Could not find a launcher for this projecttype in path"); return false; } return true; } if(errorMessage) *errorMessage = tr("Unsupported Project Type used with UbuntuRunConfiguration"); return false; } void UbuntuLocalRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const { if(UbuntuProjectGuesser::isClickAppProject(target()->project())) { CMakeProjectManager::CMakeProject* proj = static_cast (target()->project()); QList targets = proj->buildTargets(); QSet usedPaths; foreach (const CMakeProjectManager::CMakeBuildTarget& t, targets) { if(t.library) { qDebug()<<"Looking at executable "<. * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUVERSION_H #define UBUNTUVERSION_H #include #include #include "ubuntuconstants.h" namespace Ubuntu { namespace Internal { class UbuntuVersion : public QObject { Q_OBJECT public: explicit UbuntuVersion(); public slots: QString id() { return m_id; } QString release() { return m_release; } QString codename() { return m_codename; } QString description() { return m_description; } Core::FeatureSet features(); protected: QString m_id; QString m_release; QString m_codename; QString m_description; }; } } #endif // UBUNTUVERSION_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudeviceconfigurationwidget.ui0000644000015301777760000003464612323167147032122 0ustar pbusernogroup00000000000000 Ubuntu::Internal::UbuntuDeviceConfigurationWidget 0 0 819 368 Form QTabWidget::West 0 true Simple Qt::Vertical 20 40 Ubuntu 12 50 false false padding: 10; color: #333 Enable Developer Mode false Ubuntu 12 padding: 10; color: #333 Disable Developer Mode Qt::Vertical 20 40 Advanced Clone time config from host to device color: #333 Enable port forward from device to localhost true color: #333 Setup public key authentication color: #333 Open ssh connection to device Qt::Vertical 20 40 Device Mode 0 0 0 color: #333 Reboot 0 0 color: #333 Shutdown 0 0 color: #333 Reboot to Bootloader 0 0 color: #333 Reboot to Recovery Qt::Vertical 20 40 Builder Qt::Vertical 20 40 Platform Development The connected device can be turned to be a native development environment. Use this feature with care and only if you know what are you doing. Qt::Horizontal 40 20 Disable RW filesystem Enable RW filesystem Disable Development Enable Development Qt::Horizontal 40 20 Qt::Vertical 20 40 Log Ubuntu background: rgba(238,238,238,0.1) QFrame::Plain Qt::ScrollBarAlwaysOn Qt::ScrollBarAlwaysOff qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuclickdialog.cpp0000644000015301777760000001356512323167147027276 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntuclickdialog.h" #include "ui_ubuntuclickdialog.h" #include "ubuntuconstants.h" #include #include #include #include #include #include "ubuntucreatenewchrootdialog.h" namespace Ubuntu { namespace Internal { UbuntuClickDialog::UbuntuClickDialog(QWidget *parent) : QDialog(parent) ,m_ui(new Ui::UbuntuClickDialog) { m_ui->setupUi(this); QFont f(TextEditor::FontSettings::defaultFixedFontFamily()); f.setStyleHint(QFont::TypeWriter); m_ui->output->setFont(f); m_ui->exitStatusLabel->setVisible(false); m_process = new Utils::QtcProcess(this); connect(m_process,SIGNAL(readyReadStandardOutput()),this,SLOT(on_clickReadyReadStandardOutput())); connect(m_process,SIGNAL(readyReadStandardError()),this,SLOT(on_clickReadyReadStandardError())); connect(m_process,SIGNAL(finished(int)),this,SLOT(on_clickFinished(int))); } UbuntuClickDialog::~UbuntuClickDialog() { delete m_ui; } void UbuntuClickDialog::setParameters(ProjectExplorer::ProcessParameters *params) { params->resolveAll(); m_process->setCommand(params->command(),params->arguments()); m_process->setEnvironment(params->environment()); m_process->setWorkingDirectory(params->workingDirectory()); } int UbuntuClickDialog::lastExitCode() const { return m_exitCode; } void UbuntuClickDialog::runClick( ) { #if 0 //change the button to cancel m_buttonBox->clear(); m_buttonBox->addButton(QDialogButtonBox::Cancel); #endif disableCloseButton(true); m_process->start(); } int UbuntuClickDialog::runClickModal(ProjectExplorer::ProcessParameters *params) { UbuntuClickDialog dlg; dlg.setParameters(params); QMetaObject::invokeMethod(&dlg,"runClick",Qt::QueuedConnection); dlg.exec(); return dlg.m_exitCode; } int UbuntuClickDialog::createClickChrootModal() { UbuntuClickTool::Target t; if(!UbuntuCreateNewChrootDialog::getNewChrootTarget(&t)) return 0; ProjectExplorer::ProcessParameters params; UbuntuClickTool::parametersForCreateChroot(t,¶ms); return runClickModal(¶ms); } int UbuntuClickDialog::maintainClickModal(const UbuntuClickTool::Target &target, const UbuntuClickTool::MaintainMode &mode) { if(mode == UbuntuClickTool::Delete) { QString title = tr(Constants::UBUNTU_CLICK_DELETE_TITLE); QString text = tr(Constants::UBUNTU_CLICK_DELETE_MESSAGE); if( QMessageBox::question(Core::ICore::mainWindow(),title,text) != QMessageBox::Yes ) return 0; } ProjectExplorer::ProcessParameters params; UbuntuClickTool::parametersForMaintainChroot(mode,target,¶ms); return runClickModal(¶ms); } void UbuntuClickDialog::done(int code) { if(code == QDialog::Rejected) { if(m_process->state() != QProcess::NotRunning) { //ask the user if he really wants to do that QString title = tr(Constants::UBUNTU_CLICK_STOP_TITLE); QString text = tr(Constants::UBUNTU_CLICK_STOP_MESSAGE); if( QMessageBox::question(Core::ICore::mainWindow(),title,text)!= QMessageBox::Yes ) return; m_process->terminate(); m_process->waitForFinished(100); m_process->kill(); m_ui->exitStatusLabel->setText(tr(Constants::UBUNTU_CLICK_STOP_WAIT_MESSAGE)); m_ui->exitStatusLabel->setVisible(true); return; } } QDialog::done(code); } void UbuntuClickDialog::disableCloseButton(const bool &disabled) { QPushButton* bt = m_ui->buttonBox->button(QDialogButtonBox::Close); if(bt) bt->setDisabled(disabled); } void UbuntuClickDialog::on_clickFinished(int exitCode) { disableCloseButton(false); #if 0 //set the button to close again m_buttonBox->clear(); m_buttonBox->addButton(QDialogButtonBox::Close); #endif if (exitCode != 0) { on_clickReadyReadStandardError(tr("---%0---").arg(QLatin1String(Constants::UBUNTU_CLICK_ERROR_EXIT_MESSAGE))); } else { on_clickReadyReadStandardOutput(tr("---%0---").arg(QLatin1String(Constants::UBUNTU_CLICK_SUCCESS_EXIT_MESSAGE))); } m_exitCode = exitCode; } void UbuntuClickDialog::on_clickReadyReadStandardOutput(const QString txt) { QTextCursor cursor(m_ui->output->document()); cursor.movePosition(QTextCursor::End); QTextCharFormat tf; QFont font = m_ui->output->font(); tf.setFont(font); tf.setForeground(m_ui->output->palette().color(QPalette::Text)); if(txt.isEmpty()) cursor.insertText(QString::fromLocal8Bit(m_process->readAllStandardOutput()), tf); else cursor.insertText(txt, tf); } void UbuntuClickDialog::on_clickReadyReadStandardError(const QString txt) { QTextCursor cursor(m_ui->output->document()); QTextCharFormat tf; QFont font = m_ui->output->font(); QFont boldFont = font; boldFont.setBold(true); tf.setFont(boldFont); tf.setForeground(QColor(Qt::red)); if(txt.isEmpty()) cursor.insertText(QString::fromLocal8Bit(m_process->readAllStandardError()), tf); else cursor.insertText(txt, tf); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectmanager.cpp0000644000015301777760000000441212323167147030021 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuprojectmanager.h" #include #include using namespace Ubuntu::Internal; UbuntuProjectManager::UbuntuProjectManager() { QObject* sessionManager = ProjectExplorer::SessionManager::instance(); connect(sessionManager,SIGNAL(projectAdded(ProjectExplorer::Project*)),SLOT(onProjectAdded(ProjectExplorer::Project*))); } ProjectExplorer::Project* UbuntuProjectManager::openProject(const QString &filePath, QString *errorString) { QFileInfo fileInfo(filePath); foreach (ProjectExplorer::Project *pi, ProjectExplorer::SessionManager::projects()) { if (filePath == pi->document()->filePath()) { if (errorString) *errorString = tr("Failed opening project '%1': Project already open") .arg(QDir::toNativeSeparators(filePath)); return 0; } } if (fileInfo.isFile()) return new UbuntuProject(this, filePath); *errorString = tr("Failed opening project '%1': Project file is not a file").arg(QDir::toNativeSeparators(filePath)); return 0; } void UbuntuProjectManager::registerProject(UbuntuProject *project) { m_projects.append(project); } void UbuntuProjectManager::unregisterProject(UbuntuProject *project) { m_projects.removeAll(project); } QString UbuntuProjectManager::mimeType() const { return QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE); } void UbuntuProjectManager::onProjectAdded(ProjectExplorer::Project* addedProject) { QString mimeType = addedProject->projectManager()->mimeType(); qDebug() << mimeType; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuplugin.cpp0000644000015301777760000001574312323167214026322 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuplugin.h" #include "ubuntuconstants.h" #include "ubuntuprojectapplicationwizard.h" #include "ubuntuprojectmanager.h" #include "ubuntulocalrunconfiguration.h" #include "ubuntulocalrunconfigurationfactory.h" #include "ubunturemoteruncontrolfactory.h" #include "ubuntuclicktool.h" #include "ubuntukitmanager.h" #include "ubuntucmaketool.h" #include "ubuntudevicefactory.h" #include "clicktoolchain.h" #include "ubuntucmakebuildconfiguration.h" #include "ubunturemotedeployconfiguration.h" #include "ubuntulocaldeployconfiguration.h" #include "localportsmanager.h" #include #include #include #include #include #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuPlugin::UbuntuPlugin() { } UbuntuPlugin::~UbuntuPlugin() { } bool UbuntuPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments) Q_UNUSED(errorString) const QLatin1String mimetypesXml(Constants::UBUNTU_MIMETYPE_XML); if (!Core::MimeDatabase::addMimeTypes(mimetypesXml, errorString)) return false; QJsonDocument jsonDoc = QJsonDocument::fromJson(Internal::UbuntuProjectApplicationWizard::getProjectTypesJSON()); if (jsonDoc.isArray()) { QJsonArray array = jsonDoc.array(); for (int idx = 0; idx < array.size(); idx++) { if (array.at(idx).isObject()) { QJsonObject obj = array.at(idx).toObject(); QString folder; QJsonValue tmp_folder = obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_FOLDER)); if (tmp_folder.isUndefined() == false) { folder = tmp_folder.toString(); if (QFileInfo(UbuntuProjectApplicationWizard::templatesPath(folder)).exists()) { addAutoReleasedObject(new Internal::UbuntuProjectApplicationWizard(obj)); } } } } } else { qWarning() << __PRETTY_FUNCTION__ << Constants::ERROR_MSG_FAILED_TO_READ_JSON; } m_ubuntuDeviceMode = new UbuntuDeviceMode(); addAutoReleasedObject(m_ubuntuDeviceMode); m_ubuntuWelcomeMode = new UbuntuWelcomeMode; addAutoReleasedObject(m_ubuntuWelcomeMode); QSettings settings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); settings.beginGroup(QLatin1String(Constants::SETTINGS_GROUP_MODE)); if (settings.value(QLatin1String(Constants::SETTINGS_KEY_API),Constants::SETTINGS_DEFAULT_API_VISIBILITY).toBool()) { m_ubuntuAPIMode = new UbuntuAPIMode; addAutoReleasedObject(m_ubuntuAPIMode); } if (settings.value(QLatin1String(Constants::SETTINGS_KEY_COREAPPS),Constants::SETTINGS_DEFAULT_COREAPPS_VISIBILITY).toBool()) { m_ubuntuCoreAppsMode = new UbuntuCoreAppsMode; addAutoReleasedObject(m_ubuntuCoreAppsMode); } if (settings.value(QLatin1String(Constants::SETTINGS_KEY_IRC),Constants::SETTINGS_DEFAULT_IRC_VISIBILITY).toBool()) { m_ubuntuIRCMode = new UbuntuIRCMode; addAutoReleasedObject(m_ubuntuIRCMode); } if (settings.value(QLatin1String(Constants::SETTINGS_KEY_PASTEBIN),Constants::SETTINGS_DEFAULT_PASTEBIN_VISIBILITY).toBool()) { m_ubuntuPastebinMode = new UbuntuPastebinMode; addAutoReleasedObject(m_ubuntuPastebinMode); } if (settings.value(QLatin1String(Constants::SETTINGS_KEY_WIKI),Constants::SETTINGS_DEFAULT_WIKI_VISIBILITY).toBool()) { m_ubuntuWikiMode = new UbuntuWikiMode; addAutoReleasedObject(m_ubuntuWikiMode); } settings.endGroup(); m_ubuntuMenu = new UbuntuMenu; addAutoReleasedObject(m_ubuntuMenu); m_ubuntuPackagingMode = new UbuntuPackagingMode(); addAutoReleasedObject(m_ubuntuPackagingMode); addAutoReleasedObject(new UbuntuSettingsClickPage); addAutoReleasedObject(new UbuntuSettingsDeviceConnectivityPage); addAutoReleasedObject(new UbuntuSettingsPage); addAutoReleasedObject(new UbuntuVersionManager); addAutoReleasedObject(new UbuntuFeatureProvider); // Handle new project type files addAutoReleasedObject(new UbuntuProjectManager); addAutoReleasedObject(new UbuntuLocalRunConfigurationFactory); addAutoReleasedObject(new UbuntuRemoteRunControlFactory); // Build support addAutoReleasedObject(new ClickToolChainFactory); addAutoReleasedObject(new UbuntuCMakeToolFactory); addAutoReleasedObject(new UbuntuCMakeMakeStepFactory); addAutoReleasedObject(new UbuntuCMakeBuildConfigurationFactory); //ubuntu device support addAutoReleasedObject(new UbuntuDeviceFactory); addAutoReleasedObject(new UbuntuLocalPortsManager); //deploy support addAutoReleasedObject(new UbuntuRemoteDeployConfigurationFactory); //disabled for now, keeping the code because we might need a deploy method //for local applications in the future //addAutoReleasedObject(new UbuntuLocalDeployConfigurationFactory); addAutoReleasedObject(new UbuntuDeployStepFactory); #if 0 //cmake build support, hack until we have a better solution m_ubuntuClickManager = new UbuntuClickManager(); addAutoReleasedObject(m_ubuntuClickManager); #endif //trigger kit autodetection and update after projectexplorer loaded the kits connect(ProjectExplorer::KitManager::instance(),SIGNAL(kitsLoaded()) ,this,SLOT(onKitsLoaded())); return true; } void UbuntuPlugin::extensionsInitialized() { qDebug()<<"extensions loaded"; if (m_ubuntuMenu) m_ubuntuMenu->initialize(); m_ubuntuWelcomeMode->initialize(); m_ubuntuDeviceMode->initialize(); if (m_ubuntuIRCMode) m_ubuntuIRCMode->initialize(); if (m_ubuntuAPIMode) m_ubuntuAPIMode->initialize(); if (m_ubuntuCoreAppsMode) m_ubuntuCoreAppsMode->initialize(); if (m_ubuntuWikiMode) m_ubuntuWikiMode->initialize(); m_ubuntuPackagingMode->initialize(); #if 0 m_ubuntuClickManager->initialize(); #endif Core::ModeManager::activateMode(m_ubuntuWelcomeMode->id()); } void UbuntuPlugin::onKitsLoaded() { UbuntuKitManager::autoDetectKits(); disconnect(ProjectExplorer::KitManager::instance(),SIGNAL(kitsLoaded()) ,this,SLOT(onKitsLoaded())); } Q_EXPORT_PLUGIN2(Ubuntu, UbuntuPlugin) qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevice.h0000644000015301777760000001516312323167147025731 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUDEVICE_H #define UBUNTU_INTERNAL_UBUNTUDEVICE_H #include #include #include #include #include class IUbuntuDeviceNotifier; namespace Ubuntu { namespace Internal { class UbuntuDevice; class UbuntuDeviceFactory; class UbuntuDeviceHelper : public QObject { Q_OBJECT friend class UbuntuDevice; public: explicit UbuntuDeviceHelper(UbuntuDevice* dev); ~UbuntuDeviceHelper(); UbuntuDevice *device () const; QString log () const; void refresh (); signals: void beginQueryDevice (); void endQueryDevice (); void detectionStateChanged (); void connected (); void disconnected (); void deviceNeedsSetup (); void featureDetected (); void message (const QString &message); protected: void init (); void detect (); void detectOpenSsh(); void startSshService(); void enableDeveloperMode(); void disableDeveloperMode(); void detectHasNetworkConnection(); void detectDeviceVersion(); void detectDeviceWritableImage(); void detectDeveloperTools(); void beginAction(QString msg); void endAction(QString msg); void resetToDefaults(); void cloneTimeConfig (); void enableRWImage (); void disableRWImage (); void enablePortForward (); void installDevTools (); void removeDevTools (); void deployPublicKey (); void cloneNetwork (); void startProcess (const QString& command); protected slots: void onProcessReadyRead (); void onProcessFinished (const int code); void onProcessError (const QProcess::ProcessError error); void onMessage(const QString &msg); void onError(const QString &error); void processFinished (const QString&, const int code); void deviceConnected (); void deviceDisconnected (); protected: void readProcessOutput (QProcess* proc); void stopProcess (); void addToLog (const QString &msg); void setProcessState (const int newState); private: QString m_log; QString m_reply; int m_clonedNwCount; UbuntuDevice *m_dev; QProcess *m_process; IUbuntuDeviceNotifier *m_deviceWatcher; }; class UbuntuDevice : public RemoteLinux::LinuxDevice { Q_DECLARE_TR_FUNCTIONS(Ubuntu::Internal::UbuntuDevice) friend class UbuntuDeviceHelper; friend class UbuntuDeviceFactory; public: enum FeatureState { NotAvailable, //Feature is not available on the device Unknown, //Feature is not detected yet Available //Feature is available on the device }; enum ProcessState { NotStarted, DetectDeviceVersion, DetectNetworkConnection, CloneNetwork, DetectOpenSSH, InstallOpenSSH, RemoveOpenSSH, StartOpenSSH, EnablePortForwarding, DeployPublicKey, DetectDeviceWriteableImage, DetectDeveloperTools, FirstNonCriticalTask, CloneTimeConfig, EnableRWImage, DisableRWImage, InstallDevTools, RemoveDevTools, Done }; typedef QSharedPointer Ptr; typedef QSharedPointer ConstPtr; virtual ~UbuntuDevice (); static Ptr create(); static Ptr create(const QString &name,const QString &serial, MachineType machineType, Origin origin = ManuallyAdded); QString serialNumber () const; UbuntuDeviceHelper *helper () const; void openTerminal (); void cloneTimeConfig (); void enablePortForward (); void shutdown (); void reboot (); void rebootToRecovery (); void rebootToBootloader (); void deployPublicKey (); void setDeveloperModeEnabled ( const bool enabled = true ); void setWriteableImageEnabled ( const bool enabled = true ); void setDeveloperToolsInstalled ( const bool installed = true ); void setDeviceInfoString (const QString &info); QString deviceInfoString () const; FeatureState developerModeEnabled () const; FeatureState hasNetworkConnection () const; FeatureState hasWriteableImage () const; FeatureState hasDeveloperTools () const; ProcessState detectionState () const; QString detectionStateString () const; // IDevice interface virtual ProjectExplorer::IDeviceWidget *createWidget(); virtual QList actionIds() const; virtual QString displayType() const; virtual ProjectExplorer::IDevice::Ptr clone() const; virtual void fromMap(const QVariantMap &map); virtual QVariantMap toMap() const; virtual ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const; Ptr sharedFromThis (); ConstPtr sharedFromThis() const; protected: UbuntuDevice(); UbuntuDevice(const QString &name,MachineType machineType, Origin origin, Core::Id id); UbuntuDevice(const UbuntuDevice &other); void loadDefaultConfig(); void setupPrivateKey (); private: UbuntuDeviceHelper* m_helper; FeatureState m_openSSHStarted; FeatureState m_hasOpenSSHServer; FeatureState m_hasNetworkConnection; FeatureState m_hasWriteableImage; FeatureState m_hasDeveloperTools; ProcessState m_processState; QString m_deviceInfoString; Utils::PortList m_localForwardedPorts; private: UbuntuDevice &operator=(const UbuntuDevice &); }; class UbuntuDeviceProcess : public RemoteLinux::LinuxDeviceProcess { Q_OBJECT public: explicit UbuntuDeviceProcess(const QSharedPointer &device, QObject *parent = 0); void setWorkingDirectory(const QString &directory); // DeviceProcess interface public: virtual void terminate(); private: // SshDeviceProcess interface virtual QString fullCommandLine() const; QString m_workingDir; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUDEVICE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsdeviceconnectivitywidget.cpp0000644000015301777760000000524512323167147033710 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusettingsdeviceconnectivitywidget.h" #include "ui_ubuntusettingsdeviceconnectivitywidget.h" #include "ubuntudeviceswidget.h" #include "ubuntuconstants.h" using namespace Ubuntu; UbuntuSettingsDeviceConnectivityWidget::UbuntuSettingsDeviceConnectivityWidget(QWidget *parent) : QWidget(parent), ui(new Ui::UbuntuSettingsDeviceConnectivityWidget) { ui->setupUi(this); m_settings = new QSettings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICE_CONNECTIVITY)); ui->lineEditDeviceUserName->setText(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_USERNAME),QLatin1String(Constants::SETTINGS_DEFAULT_DEVICE_USERNAME)).toString()); ui->lineEditDeviceIP->setText(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_IP),QLatin1String(Constants::SETTINGS_DEFAULT_DEVICE_IP)).toString()); m_settings->endGroup(); m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICES)); ui->checkBox_mode_devices_autotoggle->setChecked(m_settings->value(QLatin1String(Constants::SETTINGS_KEY_AUTOTOGGLE),Constants::SETTINGS_DEFAULT_DEVICES_AUTOTOGGLE).toBool()); m_settings->endGroup(); } UbuntuSettingsDeviceConnectivityWidget::~UbuntuSettingsDeviceConnectivityWidget() { delete ui; } void UbuntuSettingsDeviceConnectivityWidget::apply() { m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICE_CONNECTIVITY)); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_USERNAME),ui->lineEditDeviceUserName->text()); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_IP),ui->lineEditDeviceIP->text()); m_settings->endGroup(); m_settings->beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICES)); m_settings->setValue(QLatin1String(Constants::SETTINGS_KEY_AUTOTOGGLE),ui->checkBox_mode_devices_autotoggle->isChecked()); m_settings->endGroup(); m_settings->sync(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsdeviceconnectivitypage.h0000644000015301777760000000271412323167147033004 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSETTINGSDEVICECONNECTIVITYPAGE_H #define UBUNTUSETTINGSDEVICECONNECTIVITYPAGE_H #include #include "ubuntusettingsdeviceconnectivitywidget.h" #include namespace Ubuntu { namespace Internal { class UbuntuSettingsDeviceConnectivityPage : public Core::IOptionsPage { Q_OBJECT public: explicit UbuntuSettingsDeviceConnectivityPage(); ~UbuntuSettingsDeviceConnectivityPage(); QWidget *createPage(QWidget *parent); void apply(); void finish() { } protected: QPointer m_widget; }; } } #endif // UBUNTUSETTINGSDEVICECONNECTIVITYPAGE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntulocalrunconfigurationfactory.h0000644000015301777760000000553412323167147032472 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTURUNCONFIGURATIONFACTORY_H #define UBUNTURUNCONFIGURATIONFACTORY_H #include #include #include "ubuntuproject.h" #include "ubuntuconstants.h" #include "ubuntulocalrunconfiguration.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuLocalRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory { Q_OBJECT public: explicit UbuntuLocalRunConfigurationFactory() { setObjectName(QLatin1String("UbuntuRunConfigurationFactory")); } QList availableCreationIds(ProjectExplorer::Target *parent) const; QString displayNameForId(const Core::Id id) const; bool canCreate(ProjectExplorer::Target *parent, const Core::Id id) const; bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const; bool canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product) const; ProjectExplorer::RunConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source); private: bool canHandle(ProjectExplorer::Target *parent) const; ProjectExplorer::RunConfiguration *doCreate(ProjectExplorer::Target *parent, const Core::Id id); ProjectExplorer::RunConfiguration *doRestore(ProjectExplorer::Target *parent, const QVariantMap &map); }; } } #endif // UBUNTURUNCONFIGURATIONFACTORY_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectguesser.cpp0000644000015301777760000001651112323167147030067 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntuprojectguesser.h" #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { const char SCOPES_TYPE_CACHE_PROPERTY[] = "__ubuntu_sdk_is_scopes_project_property"; const char SCOPES_INIFILE_CACHE_PROPERTY[] = "__ubuntu_sdk_scopes_project_inifile_property"; const char CLICK_TYPE_CACHE_PROPERTY[] = "__ubuntu_sdk_is_click_project_property"; UbuntuProjectGuesser::UbuntuProjectGuesser() { } bool UbuntuProjectGuesser::isScopesProject(ProjectExplorer::Project *project, QString *iniFileName) { //query the project type from CMakeCache always, only fall back on searching the directory QString type = projectTypeFromCacheOrProject(project); qDebug()<<"Project type from CMake "<property(SCOPES_TYPE_CACHE_PROPERTY); if(cachedResult.isValid()) { if(!cachedResult.toBool()) return false; if(iniFileName) { QVariant cachedIni = project->property(SCOPES_INIFILE_CACHE_PROPERTY); *iniFileName = cachedIni.toString(); } return true; } if(!qobject_cast(project)) return false; Utils::FileName iniFile = findScopesIniRecursive(Utils::FileName::fromString(project->projectDirectory())); QFileInfo info = iniFile.toFileInfo(); if (iniFileName && info.exists()) { *iniFileName = info.absolutePath(); } if(info.exists()){ project->setProperty(SCOPES_TYPE_CACHE_PROPERTY,true); project->setProperty(SCOPES_INIFILE_CACHE_PROPERTY,iniFile.toString()); } return info.exists(); } bool UbuntuProjectGuesser::isClickAppProject(ProjectExplorer::Project *project) { //query the project type from CMakeCache always, only fall back on searching the directory QString type = projectTypeFromCacheOrProject(project); qDebug()<<"Project type from CMake "<property(CLICK_TYPE_CACHE_PROPERTY); if(cachedResult.isValid()) { return cachedResult.toBool(); } if(!qobject_cast(project)) return false; QFile projectFile(project->projectFilePath()); if (!projectFile.open(QIODevice::ReadOnly)) return false; bool usesClick = false; QRegularExpression regExp(QLatin1String("include\\(Click\\)|CLICK_MODE")); QTextStream in(&projectFile); while (!in.atEnd()) { QString contents = in.readLine(); QRegularExpressionMatch m = regExp.match(contents); if(m.hasMatch()) { usesClick = true; break; } } if(usesClick) { Utils::FileName iniFile = findFileRecursive(Utils::FileName::fromString(project->projectDirectory()), QLatin1String("^.*desktop.in.*$")); QFileInfo info = iniFile.toFileInfo(); if(info.exists()) { project->setProperty(CLICK_TYPE_CACHE_PROPERTY,true); return true; } iniFile = findFileRecursive(Utils::FileName::fromString(project->projectDirectory()), QLatin1String("^.*desktop.*$")); info = iniFile.toFileInfo(); if(info.exists()) { project->setProperty(CLICK_TYPE_CACHE_PROPERTY,true); return true; } } project->setProperty(CLICK_TYPE_CACHE_PROPERTY,false); return false; } Utils::FileName UbuntuProjectGuesser::findScopesIniRecursive(const Utils::FileName &searchdir) { return findFileRecursive(searchdir,QLatin1String("^.*-scope.ini.*$")); } Utils::FileName UbuntuProjectGuesser::findFileRecursive(const Utils::FileName &searchdir, const QString ®exp) { QRegularExpression regex(regexp); return findFileRecursive(searchdir,regex); } Utils::FileName UbuntuProjectGuesser::findFileRecursive(const Utils::FileName &searchdir, const QRegularExpression ®exp) { QFileInfo dirInfo = searchdir.toFileInfo(); if(!dirInfo.exists()) return Utils::FileName(); if(!dirInfo.isDir()) return Utils::FileName(); QDir dir(dirInfo.absoluteFilePath()); QStringList entries = dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files); foreach (const QString& entry, entries) { QFileInfo info(dir.absoluteFilePath(entry)); if(info.isDir()) { Utils::FileName f = findFileRecursive(Utils::FileName::fromString(dir.absoluteFilePath(entry)),regexp); if(!f.isEmpty()) return f; continue; } QRegularExpressionMatch match = regexp.match(entry); if(match.hasMatch()) { return Utils::FileName(info); } } return Utils::FileName(); } QString UbuntuProjectGuesser::projectTypeFromCacheOrProject(ProjectExplorer::Project *project) { //First try to get the variable from the Cache file if(project->activeTarget() && project->activeTarget()->activeBuildConfiguration()) { QFile cache(project->activeTarget()->activeBuildConfiguration()->buildDirectory().toString() + QDir::separator() + QLatin1String("CMakeCache.txt")); if(cache.exists() && cache.open(QIODevice::ReadOnly)) { QRegularExpression regExp(QLatin1String("^UBUNTU_PROJECT_TYPE:(.*)=\\s*(\\S*)\\s*$")); QTextStream in(&cache); while (!in.atEnd()) { QString contents = in.readLine(); QRegularExpressionMatch m = regExp.match(contents); if(m.hasMatch()) { return m.captured(2); } } } } QFile projectFile(project->projectFilePath()); if (!projectFile.exists() || !projectFile.open(QIODevice::ReadOnly)) { QRegularExpression regExp(QLatin1String("^\\s*SET\\s*\\(\\s*UBUNTU_PROJECT_TYPE\\s*\"?(\\S*)\"?")); QTextStream in(&projectFile); while (!in.atEnd()) { QString contents = in.readLine(); QRegularExpressionMatch m = regExp.match(contents); if(m.hasMatch()) { return m.captured(1); } } } return QString(); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntu_dependencies.pri0000644000015301777760000000040212323167147027610 0ustar pbusernogroup00000000000000QTC_PLUGIN_NAME = Ubuntu QTC_LIB_DEPENDS += \ utils QTC_PLUGIN_DEPENDS += \ coreplugin \ projectexplorer \ qmakeprojectmanager \ qmlprojectmanager \ cmakeprojectmanager \ debugger \ qtsupport \ remotelinux \ qtsupport qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntushared.h0000644000015301777760000000257412323167147025742 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSHARED_H #define UBUNTUSHARED_H #include #include #include #include static bool readFile(QString fileName, QByteArray *data, QString *errorMessage) { Utils::FileReader reader; if (!reader.fetch(fileName, errorMessage)) return false; *data = reader.data(); return true; } static void printToOutputPane(QString msg) { QString timestamp = QDateTime::currentDateTime().toString(QString::fromLatin1("HH:mm:ss")); Core::MessageManager::write(QString(QLatin1String("[%0] %1")).arg(timestamp).arg(msg),Core::MessageManager::NoModeSwitch); } #endif // UBUNTUSHARED_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuircmode.h0000644000015301777760000000175312323167147026114 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUIRCMODE_H #define UBUNTUIRCMODE_H #include "ubuntuwebmode.h" #include namespace Ubuntu { namespace Internal { class UbuntuIRCMode : public UbuntuWebMode { Q_OBJECT public: UbuntuIRCMode(QObject *parent = 0); }; } } #endif // UBUNTUIRCMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntumenu.h0000644000015301777760000000426412323167147025436 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUMENU_H #define UBUNTUMENU_H #include #include "ubuntuprocess.h" #include "ubuntuconstants.h" #include #include #include #include namespace ProjectExplorer { class Project; } namespace Ubuntu { namespace Internal { class UbuntuMenu : public QObject { Q_OBJECT public: explicit UbuntuMenu(QObject *parent = 0); void initialize(); static UbuntuMenu* instance(); static QAction* menuAction(const Core::Id& id); void parseMenu(QJsonObject obj, Core::ActionContainer*& parent, const Core::Id &group = Core::Id()); QString menuPath(QString fileName); QJsonDocument getMenuJSON(); public slots: void slotUpdateActions(); signals: void finished_action(QString); void finished_action(const QProcess* process, QString cmd); protected slots: void menuItemTriggered(); void onStarted(QString); void onMessage(QString); void onError(QString); void onFinished(QString cmd, int code); void onFinished(const QProcess* programm, QString cmd, int code); protected: typedef QList QJsonValueList; QJsonDocument m_obj; QMap m_commandMap; UbuntuProcess m_ubuntuProcess; QMap m_actions; private: bool isProperUbuntuHtmlProject(ProjectExplorer::Project *project) const; static UbuntuMenu *m_instance; }; } // Internal } // Ubuntu #endif // UBUNTUMENU_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuwebmode.h0000644000015301777760000000247512323167147026116 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUWEBMODE_H #define UBUNTUWEBMODE_H #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuWebMode : public Core::IMode { Q_OBJECT public: explicit UbuntuWebMode(QObject *parent = 0); void initialize(); public slots: void setUrl(QUrl url) { m_webView.setUrl(url); } protected slots: void modeChanged(Core::IMode*); void updateAddress(QUrl url); void goToAddress(); protected: QWidget m_modeWidget; QWebView m_webView; QLineEdit m_addressBar; }; } } #endif // UBUNTUWEBMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuplugin.h0000644000015301777760000000446412323167147025772 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTU_H #define UBUNTU_H #include "ubuntu_global.h" #include "ubuntuwelcomemode.h" #include "ubuntudevicemode.h" #include "ubuntumenu.h" #include "ubuntuprojectmanager.h" #include "ubuntufeatureprovider.h" #include "ubuntuversionmanager.h" #include "ubuntuircmode.h" #include "ubuntuapimode.h" #include "ubuntucoreappsmode.h" #include "ubuntuwikimode.h" #include "ubuntupackagingmode.h" #include "ubuntupastebinmode.h" #include "ubuntusettingspage.h" #include "ubuntusettingsdeviceconnectivitypage.h" #include "ubuntusettingsclickpage.h" #include #include #include namespace Ubuntu { namespace Internal { class UbuntuClickManager; class UBUNTUSHARED_EXPORT UbuntuPlugin: public ExtensionSystem::IPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Ubuntu.json") public: UbuntuPlugin(); ~UbuntuPlugin(); virtual bool initialize(const QStringList &arguments, QString *errorString); virtual void extensionsInitialized(); private slots: void onKitsLoaded (); protected: UbuntuWelcomeMode* m_ubuntuWelcomeMode; UbuntuDeviceMode* m_ubuntuDeviceMode; UbuntuMenu* m_ubuntuMenu; UbuntuIRCMode* m_ubuntuIRCMode; UbuntuAPIMode* m_ubuntuAPIMode; UbuntuCoreAppsMode* m_ubuntuCoreAppsMode; UbuntuWikiMode* m_ubuntuWikiMode; UbuntuPackagingMode* m_ubuntuPackagingMode; UbuntuPastebinMode* m_ubuntuPastebinMode; UbuntuClickManager* m_ubuntuClickManager; }; } // Internal } // Ubuntu #endif // UBUNTU_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucoreappsmode.h0000644000015301777760000000201112323167147027137 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUCOREAPPSMODE_H #define UBUNTUCOREAPPSMODE_H #include "ubuntuwebmode.h" #include namespace Ubuntu { namespace Internal { class UbuntuCoreAppsMode : public UbuntuWebMode { Q_OBJECT public: explicit UbuntuCoreAppsMode(QObject *parent = 0); }; } } #endif // UBUNTUCOREAPPSMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuclickmanifest.h0000644000015301777760000000710612323167147027304 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUCLICKMANIFEST_H #define UBUNTUCLICKMANIFEST_H #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuClickManifest : public QObject { Q_OBJECT public: explicit UbuntuClickManifest(QObject *parent = 0); struct Hook { QString appId; QString desktopFile; QString appArmorFile; }; signals: void nameChanged(); void maintainerChanged(); void titleChanged(); void policyGroupsChanged(); void policyVersionChanged(); void versionChanged(); void descriptionChanged(); void saved(); void loaded(); void error(); void fileNameChanged(QString); void frameworkNameChanged(const QString &name); void appArmorFileNameChanged (const QString &appId, const QString &name); public slots: void setName(QString name); QString name(); void setMaintainer(QString maintainer); QString maintainer(); void setTitle(QString title); QString title(); void setVersion(QString version); QString version(); void setDescription(QString description); QString description(); void setPolicyGroups(QString appName, QStringList groups); QStringList policyGroups(QString appName); QList hooks (); void setPolicyVersion(const QString &version); QString policyVersion(); void setFrameworkName (const QString& name); QString frameworkName (); QString appArmorFileName ( const QString &appId ); bool setAppArmorFileName( const QString &appId, const QString &name ); void save() { save(m_fileName); } void save(QString fileName); bool load(const QString &fileName, const QString &projectName); void reload(); QString raw(); void setRaw(QString); QString fileName() { return m_fileName; } void setFileName(QString fileName) { m_fileName = fileName; emit fileNameChanged(fileName); } bool isInitialized() const { return m_bInitialized; } void nameDashReplaced(){ m_bNameDashReplaced = true; } protected: void callSetFunction(QString functionName, QScriptValueList args); void callSetStringListFunction(QString functionName, QStringList args); void callSetStringFunction(QString functionName, QString args); QScriptValue callGetFunction(QString functionName, QScriptValueList args); QStringList callGetStringListFunction(QString functionName); QStringList callGetStringListFunction(QString functionName, QString args); QString callGetStringFunction(QString functionName); QScriptValue callFunction(QString functionName, QScriptValueList args); QScriptProgram m_manifestJsApp; QScriptEngine engine; QString m_userName; QString m_fileName; QString m_projectName; bool m_bInitialized; bool m_bNameDashReplaced; }; } } #endif // UBUNTUCLICKMANIFEST_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevicemode.cpp0000644000015301777760000000445712323167147027135 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntudevicemode.h" #include "ubuntuconstants.h" #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; UbuntuDeviceMode::UbuntuDeviceMode(QObject *parent) : Core::IMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_DEVICES_DISPLAYNAME)); setIcon(QIcon(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_DEVICES_ICON))); setPriority(Ubuntu::Constants::UBUNTU_MODE_DEVICES_PRIORITY); setId(Ubuntu::Constants::UBUNTU_MODE_DEVICES); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_DEVICES)); m_modeWidget = new QWidget; QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_modeWidget->setLayout(layout); Utils::StyledBar* styledBar = new Utils::StyledBar(m_modeWidget); layout->addWidget(styledBar); QScrollArea *scrollArea = new QScrollArea(m_modeWidget); scrollArea->setFrameShape(QFrame::NoFrame); layout->addWidget(scrollArea); scrollArea->setWidget(&m_ubuntuDevicesWidget); scrollArea->setWidgetResizable(true); connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), SLOT(modeChanged(Core::IMode*))); setWidget(m_modeWidget); } void UbuntuDeviceMode::modeChanged(Core::IMode *mode) { } void UbuntuDeviceMode::initialize() { } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsdeviceconnectivitywidget.ui0000644000015301777760000000336712323167147033546 0ustar pbusernogroup00000000000000 UbuntuSettingsDeviceConnectivityWidget 0 0 661 533 Form Switch to Devices -tab when USB device is connected. QFormLayout::AllNonFixedFieldsGrow Username true phablet IP 127.0.0.1 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsclickpage.h0000644000015301777760000000254612323167147030176 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSETTINGSCLICKPAGE_H #define UBUNTUSETTINGSCLICKPAGE_H #include #include "ubuntusettingsclickwidget.h" #include namespace Ubuntu { namespace Internal { class UbuntuSettingsClickPage : public Core::IOptionsPage { Q_OBJECT public: explicit UbuntuSettingsClickPage(); ~UbuntuSettingsClickPage(); QWidget *createPage(QWidget *parent); void apply(); void finish() { } protected: QPointer m_widget; }; } } #endif // UBUNTUSETTINGSCLICKPAGE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntufeatureprovider.h0000644000015301777760000000233612323167147027676 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUFEATUREPROVIDER_H #define UBUNTUFEATUREPROVIDER_H #include #include "ubuntuversionmanager.h" namespace Ubuntu { namespace Internal { class UbuntuFeatureProvider : public Core::IFeatureProvider { Q_OBJECT public: UbuntuFeatureProvider() {} Core::FeatureSet availableFeatures(const QString &platformName) const; QStringList availablePlatforms() const; QString displayNameForPlatform(const QString &string) const; }; } } #endif // UBUNTUFEATUREPROVIDER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupolicygroupmodel.h0000644000015301777760000000253112323167147030062 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef POLICYGROUPMODEL_H #define POLICYGROUPMODEL_H #include #include #include "ubuntuprocess.h" namespace Ubuntu { namespace Internal { class UbuntuPolicyGroupModel : public QStringListModel { Q_OBJECT public: explicit UbuntuPolicyGroupModel(QObject *parent = 0); void scanPolicyGroups(); bool isLocal() { return m_bLocal; } public slots: void onMessage(QString); void onFinished(QString, int); void onError(QString); signals: void scanComplete(bool); protected: UbuntuProcess m_process; QStringList m_replies; bool m_bLocal; }; } } #endif // POLICYGROUPMODEL_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/clicktoolchain.cpp0000644000015301777760000002156412323167147026552 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "clicktoolchain.h" #include "ubuntuconstants.h" #include #include #include #include #include namespace Ubuntu { namespace Internal { QLatin1String UBUNTU_TARGET_ARCH_KEY = QLatin1String("Ubuntu.ClickToolChain.Target.Arch"); QLatin1String UBUNTU_TARGET_FRAMEWORK_KEY = QLatin1String("Ubuntu.ClickToolChain.Target.Framework"); QLatin1String UBUNTU_TARGET_SERIES_KEY = QLatin1String("Ubuntu.ClickToolChain.Target.Series"); QLatin1String UBUNTU_TARGET_MINOR_KEY = QLatin1String("Ubuntu.ClickToolChain.Target.MinorV"); QLatin1String UBUNTU_TARGET_MAJOR_KEY = QLatin1String("Ubuntu.ClickToolChain.Target.MajorV"); #if 1 static QMap init_architectures() { QMap map; map.insert(QLatin1String("armhf") , ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::GenericLinuxFlavor, ProjectExplorer::Abi::ElfFormat, 32)); map.insert(QLatin1String("i386") ,ProjectExplorer::Abi(ProjectExplorer::Abi::X86Architecture, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::GenericLinuxFlavor, ProjectExplorer::Abi::ElfFormat, 32)); map.insert(QLatin1String("amd64"),ProjectExplorer::Abi(ProjectExplorer::Abi::X86Architecture, ProjectExplorer::Abi::LinuxOS, ProjectExplorer::Abi::GenericLinuxFlavor, ProjectExplorer::Abi::ElfFormat, 64)); return map; } QMap clickArchitectures = init_architectures(); #endif QList ClickToolChain::suggestedMkspecList() const { return QList()<< Utils::FileName::fromString(QLatin1String("linux-g++")); } Utils::FileName ClickToolChain::suggestedDebugger() const { return Utils::FileName::fromString(QLatin1String("/usr/bin/gdb-multiarch")); } QString ClickToolChain::type() const { return QString::fromLatin1(Constants::UBUNTU_CLICK_TOOLCHAIN_ID); } QString ClickToolChain::typeDisplayName() const { return ClickToolChainFactory::tr("Ubuntu GCC"); } bool ClickToolChain::isValid() const { return GccToolChain::isValid() && targetAbi().isValid() && UbuntuClickTool::targetExists(m_clickTarget); } void ClickToolChain::addToEnvironment(Utils::Environment &env) const { GccToolChain::addToEnvironment(env); env.set(QLatin1String("CLICK_SDK_ARCH") , m_clickTarget.architecture); env.set(QLatin1String("CLICK_SDK_FRAMEWORK"), m_clickTarget.framework); env.set(QLatin1String("CLICK_SDK_SERIES") , m_clickTarget.series); } QString ClickToolChain::makeCommand(const Utils::Environment &) const { QString command = QString::fromLatin1(Constants::UBUNTU_CLICK_MAKE_WRAPPER).arg(Constants::UBUNTU_SCRIPTPATH); return command; } bool ClickToolChain::operator ==(const ProjectExplorer::ToolChain &tc) const { if (!GccToolChain::operator ==(tc)) return false; return (m_clickTarget.architecture == m_clickTarget.architecture && m_clickTarget.framework == m_clickTarget.framework && m_clickTarget.series == m_clickTarget.series); } ProjectExplorer::ToolChainConfigWidget *ClickToolChain::configurationWidget() { return GccToolChain::configurationWidget(); } const UbuntuClickTool::Target &ClickToolChain::clickTarget() const { return m_clickTarget; } QVariantMap ClickToolChain::toMap() const { QVariantMap map = GccToolChain::toMap(); map.insert(UBUNTU_TARGET_ARCH_KEY,m_clickTarget.architecture); map.insert(UBUNTU_TARGET_FRAMEWORK_KEY,m_clickTarget.framework); map.insert(UBUNTU_TARGET_SERIES_KEY,m_clickTarget.series); map.insert(UBUNTU_TARGET_MAJOR_KEY,m_clickTarget.majorVersion); map.insert(UBUNTU_TARGET_MINOR_KEY,m_clickTarget.minorVersion); return map; } QString ClickToolChain::gnutriplet() const { switch(targetAbi().architecture()) { case ProjectExplorer::Abi::ArmArchitecture: return QLatin1String("arm-linux-gnueabihf"); break; case ProjectExplorer::Abi::X86Architecture: switch(targetAbi().wordWidth()) { case 32: return QLatin1String("i386-linux-gnu"); case 64: return QLatin1String("x86_64-linux-gnu"); } break; default: Q_ASSERT_X(false,Q_FUNC_INFO,"Unknown Target architecture"); } } bool ClickToolChain::fromMap(const QVariantMap &data) { if(!GccToolChain::fromMap(data)) return false; if(!data.contains(UBUNTU_TARGET_ARCH_KEY) || !data.contains(UBUNTU_TARGET_FRAMEWORK_KEY) || !data.contains(UBUNTU_TARGET_SERIES_KEY) || !data.contains(UBUNTU_TARGET_MAJOR_KEY) || !data.contains(UBUNTU_TARGET_MINOR_KEY)) return false; m_clickTarget.architecture = data[UBUNTU_TARGET_ARCH_KEY].toString(); m_clickTarget.framework = data[UBUNTU_TARGET_FRAMEWORK_KEY].toString(); m_clickTarget.series = data[UBUNTU_TARGET_SERIES_KEY].toString(); m_clickTarget.majorVersion = data[UBUNTU_TARGET_MAJOR_KEY].toInt(); m_clickTarget.minorVersion = data[UBUNTU_TARGET_MINOR_KEY].toInt(); //only valid click targets are used for Kit creation m_clickTarget.maybeBroken = false; return isValid(); } Utils::FileName ClickToolChain::compilerCommand() const { return GccToolChain::compilerCommand(); } ClickToolChain::ClickToolChain(const UbuntuClickTool::Target &target, Detection d) : GccToolChain(QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID), d) , m_clickTarget(target) { setCompilerCommand(Utils::FileName::fromString( QString::fromLatin1(Constants::UBUNTU_CLICK_GCC_WRAPPER) .arg(Constants::UBUNTU_SCRIPTPATH))); setDisplayName(QString::fromLatin1("Ubuntu GCC (%1-%2-%3)") .arg(ProjectExplorer::Abi::toString(targetAbi().architecture())) .arg(target.framework) .arg(target.series)); } ClickToolChain::ClickToolChain(const ClickToolChain &other) : GccToolChain(other) , m_clickTarget(other.m_clickTarget) { } ClickToolChain::ClickToolChain() : GccToolChain(QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID),ManualDetection) { } ClickToolChainFactory::ClickToolChainFactory() { setId(Constants::UBUNTU_CLICK_TOOLCHAIN_ID); setDisplayName(tr("Ubuntu GCC")); } QList ClickToolChainFactory::autoDetect() { return createToolChainsForClickTargets(); } bool ClickToolChainFactory::canRestore(const QVariantMap &data) { return idFromMap(data).startsWith(QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID) + QLatin1Char(':')); } ProjectExplorer::ToolChain *ClickToolChainFactory::restore(const QVariantMap &data) { ClickToolChain *tc = new ClickToolChain(); if (tc->fromMap(data)) return tc; delete tc; return 0; } QList ClickToolChainFactory::createToolChainsForClickTargets() { QList toolChains; QList targets = UbuntuClickTool::listAvailableTargets(); foreach(const UbuntuClickTool::Target &target, targets) { qDebug()<<"Found Target"<. * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUDEVICEMODE_H #define UBUNTUDEVICEMODE_H #include #include "ubuntudeviceswidget.h" namespace Ubuntu { namespace Internal { class UbuntuDeviceMode : public Core::IMode { Q_OBJECT public: UbuntuDeviceMode(QObject *parent = 0); void initialize(); protected slots: void modeChanged(Core::IMode*); protected: QWidget* m_modeWidget; UbuntuDevicesWidget m_ubuntuDevicesWidget; }; } // Internal } // Ubuntu #endif // UBUNTUDEVICEMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuclickmanifest.cpp0000644000015301777760000002703212323167147027637 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuclickmanifest.h" #include "ubuntuconstants.h" #include "ubuntuclicktool.h" #include "ubuntushared.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; UbuntuClickManifest::UbuntuClickManifest(QObject *parent) : QObject(parent), m_bInitialized(false), m_bNameDashReplaced(false) { QScriptEngineDebugger debugger; debugger.attachTo(&engine); debugger.setAutoShowStandardWindow(true); QFile manifestAppFile(QLatin1String(":/ubuntu/manifestlib.js")); if (!manifestAppFile.open(QIODevice::ReadOnly)) { qDebug() << QLatin1String("unable to open js app"); return; } QString manifestApp = QString::fromLatin1(manifestAppFile.readAll()); manifestAppFile.close(); QScriptProgram program(manifestApp); QScriptValue val = engine.evaluate(program); if (val.isNull()) { qWarning() << QLatin1String("unable to process app"); return; } //load(QLatin1String(":/ubuntu/manifest.json.template")); } void UbuntuClickManifest::setName(QString name) { if (!isInitialized()) { return; } callSetStringFunction(QLatin1String("setName"),name); emit nameChanged(); } QString UbuntuClickManifest::name() { return callGetStringFunction(QLatin1String("getName")); } void UbuntuClickManifest::setVersion(QString version) { if (!isInitialized()) { return; } callSetStringFunction(QLatin1String("setVersion"),version); emit versionChanged(); } QString UbuntuClickManifest::version() { return callGetStringFunction(QLatin1String("getVersion")); } void UbuntuClickManifest::setDescription(QString description) { if (!isInitialized()) { return; } callSetStringFunction(QLatin1String("setDescription"),description); emit descriptionChanged(); } QString UbuntuClickManifest::description() { return callGetStringFunction(QLatin1String("getDescription")); } void UbuntuClickManifest::setMaintainer(QString maintainer) { if (!isInitialized()) { return; } callSetStringFunction(QLatin1String("setMaintainer"),maintainer); emit maintainerChanged(); } QString UbuntuClickManifest::maintainer() { if (!isInitialized()) { return QString(); } return callGetStringFunction(QLatin1String("getMaintainer")); } void UbuntuClickManifest::setTitle(QString title) { if (!isInitialized()) { return; } callSetStringFunction(QLatin1String("setTitle"),title); emit titleChanged(); } QString UbuntuClickManifest::title() { if (!isInitialized()) { return QString(); } return callGetStringFunction(QLatin1String("getTitle")); } void UbuntuClickManifest::setPolicyVersion(const QString &version) { if (!isInitialized()) { return; } QStringList args; args << version; callSetStringListFunction(QLatin1String("setPolicyVersion"),args); emit policyVersionChanged(); } QString UbuntuClickManifest::policyVersion () { if (!isInitialized()) { return QString(); } return callGetStringFunction(QLatin1String("getPolicyVersion")); } void UbuntuClickManifest::setPolicyGroups(QString appName, QStringList groups) { if (!isInitialized()) { return; } QStringList args; args << appName << groups.join(QLatin1String(" ")); callSetStringListFunction(QLatin1String("setPolicyGroups"),args); emit policyGroupsChanged(); } QStringList UbuntuClickManifest::policyGroups(QString appName) { if (!isInitialized()) { return QStringList(); } QStringList retval = callGetStringListFunction(QLatin1String("getPolicyGroups"),appName); return retval; } QList UbuntuClickManifest::hooks() { QList hooks; if (!isInitialized()) { return hooks; } QScriptValue scriptHooks = callGetFunction(QLatin1String("getHooks"),QScriptValueList()); if(!scriptHooks.isObject()) return hooks; QScriptValueIterator it(scriptHooks); while (it.hasNext()) { it.next(); QScriptValue appDescriptor = it.value(); if(!appDescriptor.isObject() || !appDescriptor.property(QLatin1String("desktop")).isValid() || !appDescriptor.property(QLatin1String("apparmor")).isValid()) { printToOutputPane(tr("Invalid hook in manifest.json file.")); continue; } Hook app; app.appId = it.name(); app.desktopFile = it.value().property(QLatin1String("desktop")).toString(); app.appArmorFile = it.value().property(QLatin1String("apparmor")).toString(); hooks.append(app); } return hooks; } void UbuntuClickManifest::setFrameworkName(const QString &name) { if (!isInitialized()) { return; } callSetStringFunction(QLatin1String("setFrameworkName"),name); emit frameworkNameChanged(name); } QString UbuntuClickManifest::frameworkName() { if (!isInitialized()) { return QString(); } return callGetStringFunction(QLatin1String("getFrameworkName")); } QString UbuntuClickManifest::appArmorFileName(const QString &appId) { if (!isInitialized()) { return QString(); } QScriptValue v = callGetFunction(QLatin1String("getAppArmorFileName"),QScriptValueList()<projectManager()->mimeType(); QString proName = ProjectExplorer::SessionManager::startupProject()->projectFilePath(); bool isUbuntuProject = (mimeType == QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE)); bool isUbuntuHtmlProject = proName.endsWith(QLatin1String(Constants::UBUNTUHTMLPROJECT_SUFFIX)); QString defFramework; if(isUbuntuProject && isUbuntuHtmlProject) { defFramework = UbuntuClickTool::getMostRecentFramework(QLatin1String("html")); if(defFramework.isEmpty()) defFramework = QLatin1String(Constants::UBUNTU_DEFAULT_HTML_FRAMEWORK); } else { defFramework = UbuntuClickTool::getMostRecentFramework(QLatin1String("qml")); if(defFramework.isEmpty()) defFramework = QLatin1String(Constants::UBUNTU_DEFAULT_QML_FRAMEWORK); } data.replace(QLatin1String("myFramework"),defFramework); QString tmpProjectName = projectName; tmpProjectName.replace(QLatin1String("_"),QLatin1String("-")); data.replace(QLatin1String("myapp"),tmpProjectName); QString original_security_manifest_name = QString(QLatin1String("%0.json")).arg(tmpProjectName); QString replaced_security_manifest_name = original_security_manifest_name; replaced_security_manifest_name.replace(QLatin1String("_"),QLatin1String("-")); data.replace(original_security_manifest_name,replaced_security_manifest_name); QString original_desktop_file = QString(QLatin1String("%0.desktop")).arg(tmpProjectName); if (m_bNameDashReplaced) { original_desktop_file.replace(QLatin1String("-"),QLatin1String("_")); data.replace(QString(QLatin1String("%0.desktop")).arg(tmpProjectName),original_desktop_file); } } callSetStringFunction(QLatin1String("fromJSON"),data); m_bInitialized = true; emit loaded(); return true; } QScriptValue UbuntuClickManifest::callFunction(QString functionName, QScriptValueList args) { QScriptValue global = engine.globalObject(); QScriptValue cmd = global.property(functionName); return cmd.call(QScriptValue(),args); } void UbuntuClickManifest::callSetFunction(QString functionName, QScriptValueList args) { callFunction(functionName,args); } QScriptValue UbuntuClickManifest::callGetFunction(QString functionName, QScriptValueList args) { return callFunction(functionName,args); } QStringList UbuntuClickManifest::callGetStringListFunction(QString functionName) { QScriptValue retval = callFunction(functionName,QScriptValueList()); return retval.toVariant().toStringList(); } QString UbuntuClickManifest::callGetStringFunction(QString functionName) { QScriptValue retval = callFunction(functionName,QScriptValueList()); return retval.toVariant().toString(); } void UbuntuClickManifest::callSetStringListFunction(QString functionName, QStringList args) { QScriptValueList vargs; foreach (QString arg, args) vargs << QScriptValue(arg); callSetFunction(functionName,vargs); } void UbuntuClickManifest::callSetStringFunction(QString functionName, QString args) { QScriptValueList vargs; vargs << QScriptValue(args); callSetFunction(functionName,vargs); } QStringList UbuntuClickManifest::callGetStringListFunction(QString functionName, QString args) { QScriptValueList vargs; vargs << QScriptValue(args); QScriptValue retval = callFunction(functionName,vargs); return retval.toVariant().toStringList(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuwelcomemode.h0000644000015301777760000000253112323167147026765 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUWELCOMEMODE_H #define UBUNTUWELCOMEMODE_H #include #include #include namespace Ubuntu { namespace Internal { class UbuntuWelcomeMode : public Core::IMode { Q_OBJECT public: UbuntuWelcomeMode(QObject *parent = 0); void initialize(); public slots: void newProject(); void openProject(); protected slots: void modeChanged(Core::IMode*); void objectAdded(QObject* obj); protected: QDeclarativeView* m_declarativeView; QWidget* m_modeWidget; QList m_welcomeTabPluginList; }; } // Internal } // Ubuntu #endif // UBUNTUWELCOMEMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntufeatureprovider.cpp0000644000015301777760000000236112323167147030227 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntufeatureprovider.h" using namespace Ubuntu::Internal; Core::FeatureSet UbuntuFeatureProvider::availableFeatures(const QString &platformName) const { return UbuntuVersionManager::instance()->availableFeatures(platformName); } QStringList UbuntuFeatureProvider::availablePlatforms() const { return UbuntuVersionManager::instance()->availablePlatforms(); } QString UbuntuFeatureProvider::displayNameForPlatform(const QString &string) const { return UbuntuVersionManager::instance()->displayNameForPlatform(string); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubunturemoterunconfiguration.h0000644000015301777760000000460312323167147031277 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUREMOTERUNCONFIGURATION_H #define UBUNTU_INTERNAL_UBUNTUREMOTERUNCONFIGURATION_H #include #include namespace Ubuntu { namespace Internal { class UbuntuRemoteRunConfiguration : public RemoteLinux::AbstractRemoteLinuxRunConfiguration { Q_OBJECT public: UbuntuRemoteRunConfiguration(ProjectExplorer::Target *parent); UbuntuRemoteRunConfiguration(ProjectExplorer::Target *parent, UbuntuRemoteRunConfiguration *source); // AbstractRemoteLinuxRunConfiguration interface public: virtual QString localExecutableFilePath() const; virtual QString remoteExecutableFilePath() const; virtual QStringList arguments() const; virtual QString workingDirectory() const; virtual QString alternateRemoteExecutable() const; virtual bool useAlternateExecutable() const; virtual Utils::Environment environment() const; virtual QStringList soLibSearchPaths () const; // RunConfiguration interface virtual QWidget *createConfigurationWidget(); virtual bool isEnabled() const; virtual QString disabledReason() const; virtual bool isConfigured() const; virtual bool ensureConfigured(QString *errorMessage); // ProjectConfiguration interface virtual bool fromMap(const QVariantMap &map); virtual QVariantMap toMap() const; static Core::Id typeId (); void setArguments (const QStringList &args); private: QString m_appId; QString m_desktopFile; QString m_localExecutable; QString m_remoteExecutable; QStringList m_arguments; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUREMOTERUNCONFIGURATION_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuemulatornotifier.h0000644000015301777760000000315112323167147030054 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUEMULATORNOTIFIER_H #define UBUNTU_INTERNAL_UBUNTUEMULATORNOTIFIER_H #include "ubuntudevicenotifier.h" #include class QTimer; namespace Ubuntu { namespace Internal { class UbuntuEmulatorNotifier : public IUbuntuDeviceNotifier { Q_OBJECT public: explicit UbuntuEmulatorNotifier(QObject *parent = 0); // IUbuntuDeviceNotifier interface virtual void startMonitoring(const QString &serialNumber); virtual void stopMonitoring(); virtual bool isConnected() const; private slots: void pollTimeout (); void pollProcessReadyRead (); void pollProcessFinished (int exitCode, QProcess::ExitStatus exitStatus); private: QByteArray m_buffer; QString m_lastState; QString m_serial; QTimer *m_pollTimout; QProcess *m_pollProcess; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUEMULATORNOTIFIER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntu.pro0000644000015301777760000001031712323167147025116 0ustar pbusernogroup00000000000000QT += network qml quick webkitwidgets script scripttools declarative include(../plugin.pri) ##################################### # required for Ubuntu Device Notifier CONFIG += link_pkgconfig PKGCONFIG += libudev ##################################### ##################################### ## Project files FORMS += \ ubuntudeviceswidget.ui \ ubuntupackagingwidget.ui \ ubuntusettingswidget.ui \ ubuntusecuritypolicypickerdialog.ui \ ubuntusettingsdeviceconnectivitywidget.ui \ ubuntusettingsclickwidget.ui \ ubuntuclickdialog.ui \ ubuntucreatenewchrootdialog.ui \ ubuntudeviceconfigurationwidget.ui RESOURCES += \ resources.qrc OTHER_FILES += \ UbuntuProject.mimetypes.xml \ manifest.json.template \ myapp.json.template \ manifestlib.js SOURCES += \ ubuntuplugin.cpp \ ubuntuwelcomemode.cpp \ ubuntuprojectapplicationwizard.cpp \ ubuntumenu.cpp \ ubuntuprojectmanager.cpp \ ubuntuproject.cpp \ ubuntuprojectfile.cpp \ ubuntuprojectnode.cpp \ ubuntuprojectapp.cpp \ ubuntuversion.cpp \ ubuntufeatureprovider.cpp \ ubuntuversionmanager.cpp \ ubuntuircmode.cpp \ ubuntuapimode.cpp \ ubuntucoreappsmode.cpp \ ubuntuwikimode.cpp \ ubuntupackagingmode.cpp \ ubuntupackagingwidget.cpp \ ubuntubzr.cpp \ ubuntuclickmanifest.cpp \ ubuntuwebmode.cpp \ ubuntupastebinmode.cpp \ ubuntudeviceswidget.cpp \ ubuntudevicemode.cpp \ ubuntuprocess.cpp \ ubuntudevicenotifier.cpp \ ubuntusettingspage.cpp \ ubuntusettingswidget.cpp \ ubuntusecuritypolicypickerdialog.cpp \ ubuntupolicygroupmodel.cpp \ ubuntupolicygroupinfo.cpp \ ubuntusettingsdeviceconnectivitypage.cpp \ ubuntusettingsdeviceconnectivitywidget.cpp \ ubuntusettingsclickpage.cpp \ ubuntusettingsclickwidget.cpp \ ubuntuclicktool.cpp \ ubuntucreatenewchrootdialog.cpp \ ubuntuclickdialog.cpp \ ubuntuvalidationresultmodel.cpp \ clicktoolchain.cpp \ ubuntukitmanager.cpp \ ubuntucmaketool.cpp \ ubuntucmakebuildconfiguration.cpp \ ubuntudevicefactory.cpp \ ubuntudevice.cpp \ ubuntudeviceconfigurationwidget.cpp \ ubunturemoterunconfiguration.cpp \ ubuntucmakemakestep.cpp \ ubuntuemulatornotifier.cpp \ localportsmanager.cpp \ ubuntuprojectguesser.cpp \ ubuntulocaldeployconfiguration.cpp \ ubunturemotedeployconfiguration.cpp \ ubuntulocalrunconfigurationfactory.cpp \ ubunturemoteruncontrolfactory.cpp \ ubuntulocalrunconfiguration.cpp HEADERS += \ ubuntuplugin.h \ ubuntu_global.h \ ubuntuconstants.h \ ubuntuwelcomemode.h \ ubuntuprojectapplicationwizard.h \ ubuntumenu.h \ ubuntushared.h \ ubuntuprojectmanager.h \ ubuntuproject.h \ ubuntuprojectfile.h \ ubuntuprojectnode.h \ ubuntuprojectapp.h \ ubuntuversion.h \ ubuntufeatureprovider.h \ ubuntuversionmanager.h \ ubuntuircmode.h \ ubuntuapimode.h \ ubuntucoreappsmode.h \ ubuntuwikimode.h \ ubuntupackagingmode.h \ ubuntupackagingwidget.h \ ubuntubzr.h \ ubuntuclickmanifest.h \ ubuntuwebmode.h \ ubuntupastebinmode.h \ ubuntudevicemode.h \ ubuntudeviceswidget.h \ ubuntuprocess.h \ ubuntudevicenotifier.h \ ubuntusettingspage.h \ ubuntusettingswidget.h \ ubuntusecuritypolicypickerdialog.h \ ubuntupolicygroupmodel.h \ ubuntupolicygroupinfo.h \ ubuntusettingsdeviceconnectivitypage.h \ ubuntusettingsdeviceconnectivitywidget.h \ ubuntusettingsclickpage.h \ ubuntusettingsclickwidget.h \ ubuntuclicktool.h \ ubuntucreatenewchrootdialog.h \ ubuntuclickdialog.h \ ubuntuvalidationresultmodel.h \ clicktoolchain.h \ ubuntukitmanager.h \ ubuntucmaketool.h \ ubuntucmakebuildconfiguration.h \ ubuntudevicefactory.h \ ubuntudevice.h \ ubuntudeviceconfigurationwidget.h \ ubunturemoterunconfiguration.h \ ubuntucmakemakestep.h \ ubuntuemulatornotifier.h \ localportsmanager.h \ ubuntuprojectguesser.h \ ubuntulocaldeployconfiguration.h \ ubunturemotedeployconfiguration.h \ ubuntulocalrunconfigurationfactory.h \ ubunturemoteruncontrolfactory.h \ ubuntulocalrunconfiguration.h qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsclickwidget.h0000644000015301777760000000332312323167147030537 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSETTINGSCLICKWIDGET_H #define UBUNTUSETTINGSCLICKWIDGET_H #include #include #include #include "ubuntuclicktool.h" namespace Ui { class UbuntuSettingsClickWidget; } class UbuntuSettingsClickWidget : public QWidget { Q_OBJECT public: explicit UbuntuSettingsClickWidget(QWidget *parent = 0); ~UbuntuSettingsClickWidget(); void apply(); protected slots: void on_pushButtonFindClickPackagingTools_clicked(); void on_pushButtonCreateClickTarget_clicked(); void on_deleteClickChroot (const int index); void on_maintainClickChroot (const int index); void on_upgradeClickChroot (const int index); private: void listExistingClickTargets (); private: Ui::UbuntuSettingsClickWidget *ui; QSettings* m_settings; QSignalMapper* m_deleteMapper; QSignalMapper* m_updateMapper; QSignalMapper* m_maintainMapper; QList m_availableTargets; }; #endif // UBUNTUSETTINGSCLICKWIDGET_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupolicygroupmodel.cpp0000644000015301777760000000415612323167147030422 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntupolicygroupmodel.h" #include using namespace Ubuntu::Internal; UbuntuPolicyGroupModel::UbuntuPolicyGroupModel(QObject *parent) : QStringListModel(parent), m_bLocal(false) { connect(&m_process,SIGNAL(message(QString)),this,SLOT(onMessage(QString))); connect(&m_process,SIGNAL(finished(QString,int)),this,SLOT(onFinished(QString,int))); connect(&m_process,SIGNAL(error(QString)),this,SLOT(onError(QString))); } void UbuntuPolicyGroupModel::scanPolicyGroups() { QStringList cmd; if (!isLocal()) { cmd << QLatin1String("adb shell aa-easyprof --list-policy-groups --policy-vendor=ubuntu --policy-version=1.0"); } else { cmd << QLatin1String("aa-easyprof --list-policy-groups --policy-vendor=ubuntu --policy-version=1.0"); } m_process.append(cmd); m_process.start(QLatin1String("Scanning policy groups")); } void UbuntuPolicyGroupModel::onMessage(QString line) { m_replies.append(line.trimmed().replace(QLatin1String("\r"),QLatin1String("")).split(QLatin1String("\n"))); } void UbuntuPolicyGroupModel::onFinished(QString, int result) { setStringList(m_replies); m_replies.clear(); emit scanComplete(true); } void UbuntuPolicyGroupModel::onError(QString) { setStringList(m_replies); m_replies.clear(); if (!isLocal()) { m_bLocal = true; scanPolicyGroups(); } else { emit scanComplete(false); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/resources.qrc0000644000015301777760000000121312323167147025566 0ustar pbusernogroup00000000000000 images/ubuntu-64.png images/ubuntu-128.png images/ubuntu-qtcreator.png images/ubuntu-48.png images/device.png UbuntuProject.mimetypes.xml images/irc.png images/ubuntu-32.png images/launchpad.png images/coreapps.png images/packaging.png manifest.json.template myapp.json.template manifestlib.js qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntulocaldeployconfiguration.h0000644000015301777760000000447112323167147031571 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTULOCALDEPLOYCONFIGURATIONFACTORY_H #define UBUNTU_INTERNAL_UBUNTULOCALDEPLOYCONFIGURATIONFACTORY_H #include namespace Ubuntu { namespace Internal { class UbuntuLocalDeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory { Q_OBJECT public: explicit UbuntuLocalDeployConfigurationFactory(QObject *parent = 0); QList availableCreationIds(ProjectExplorer::Target *parent) const; QString displayNameForId(const Core::Id id) const; bool canCreate(ProjectExplorer::Target *parent, const Core::Id id) const; ProjectExplorer::DeployConfiguration *create(ProjectExplorer::Target *parent, const Core::Id id); bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const; ProjectExplorer::DeployConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map); ProjectExplorer::DeployConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *product); }; class UbuntuLocalDeployConfiguration : public ProjectExplorer::DeployConfiguration { Q_OBJECT friend class UbuntuLocalDeployConfigurationFactory; // for the ctors protected: UbuntuLocalDeployConfiguration(ProjectExplorer::Target *target, const Core::Id id); UbuntuLocalDeployConfiguration(ProjectExplorer::Target *target, UbuntuLocalDeployConfiguration *source); protected slots: void selectAsDefaultHack(); }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTULOCALDEPLOYCONFIGURATIONFACTORY_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuproject.cpp0000644000015301777760000000730012323167147026465 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuproject.h" #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuProject::UbuntuProject(UbuntuProjectManager *manager, const QString &fileName) : m_manager(manager), m_fileName(fileName) { setProjectContext(Core::Context(Constants::UBUNTUPROJECT_PROJECTCONTEXT)); QFileInfo fileInfo(m_fileName); m_projectName = fileInfo.completeBaseName(); m_file = QSharedPointer(new UbuntuProjectFile(this, fileName)); Core::DocumentManager::addDocument(m_file.data(), true); m_rootNode = QSharedPointer(new UbuntuProjectNode(this, m_file.data())); m_manager->registerProject(this); QList kits = ProjectExplorer::KitManager::kits(); foreach (ProjectExplorer::Kit *kit, kits) { addTarget(createTarget(kit)); } if (needsConfiguration()) { Core::ModeManager::activateMode(ProjectExplorer::Constants::MODE_SESSION); } extractProjectFileData(fileName); } void UbuntuProject::extractProjectFileData(const QString& filename) { QmlJS::SimpleReader reader; const QmlJS::SimpleReaderNode::Ptr root = reader.readFile(filename); if(!reader.errors().isEmpty()) { foreach(const QString &error, reader.errors()) { qWarning()<name().compare(QString::fromLatin1("Project")) == 0) { QVariant mainFileVariant = root->property(QLatin1String("mainFile")); if (mainFileVariant.isValid()) m_mainFile = mainFileVariant.toString(); } else { qWarning()<< tr("There is no Project root element in the projectfile"); } } QString UbuntuProject::displayName() const { return m_projectName; } Core::Id UbuntuProject::id() const { return Core::Id(Constants::UBUNTUPROJECT_ID); } Core::IDocument *UbuntuProject::document() const { return m_file.data(); } ProjectExplorer::IProjectManager *UbuntuProject::projectManager() const { return m_manager; } ProjectExplorer::ProjectNode *UbuntuProject::rootProjectNode() const { return m_rootNode.data(); } static void enumChild(const QDir &dir, QStringList &res) { foreach (const QFileInfo &info, dir.entryInfoList(QDir::NoDotAndDotDot|QDir::Dirs|QDir::Files)) { if (info.fileName().indexOf(QLatin1String(Constants::UBUNTUPROJECT_SUFFIX)) != -1 || info.fileName().indexOf(QLatin1String(Constants::UBUNTUHTMLPROJECT_SUFFIX)) != -1) continue; if (info.isFile()) { res.append(info.absoluteFilePath()); } else if (info.isDir()) { enumChild(QDir(info.absoluteFilePath()), res); } } } QStringList UbuntuProject::files(FilesMode) const { QStringList files; enumChild(projectDir(), files); return files; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuapimode.h0000644000015301777760000000176112323167147026107 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUAPIMODE_H #define UBUNTUAPIMODE_H #include #include "ubuntuwebmode.h" namespace Ubuntu { namespace Internal { class UbuntuAPIMode : public UbuntuWebMode { Q_OBJECT public: explicit UbuntuAPIMode(QObject *parent = 0); }; } } #endif // UBUNTUAPIMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuwikimode.cpp0000644000015301777760000000221512323167147026627 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuwikimode.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; UbuntuWikiMode::UbuntuWikiMode(QObject *parent) : UbuntuWebMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_WIKI_DISPLAYNAME)); setId(Ubuntu::Constants::UBUNTU_MODE_WIKI); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_WIKI)); setUrl(QUrl::fromUserInput(QLatin1String(Ubuntu::Constants::UBUNTU_WIKI))); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevicenotifier.cpp0000644000015301777760000001013712323167147030020 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntudevicenotifier.h" IUbuntuDeviceNotifier::IUbuntuDeviceNotifier(QObject *parent) : QObject(parent) { } UbuntuDeviceNotifier::UbuntuDeviceNotifier(QObject *parent) : IUbuntuDeviceNotifier(parent) { m_dev = udev_new(); m_udevMonitor = NULL; m_udevMonitor = udev_monitor_new_from_netlink(m_dev,"udev"); if (!m_udevMonitor) { qWarning() << QLatin1String("could not monitor devices"); return; } udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitor,"usb",0); udev_monitor_enable_receiving(m_udevMonitor); m_udevMonitorFileDescriptor = udev_monitor_get_fd(m_udevMonitor); m_udevSocketNotifier = new QSocketNotifier(m_udevMonitorFileDescriptor,QSocketNotifier::Read, this); connect(m_udevSocketNotifier,SIGNAL(activated(int)),this,SLOT(on_udev_event())); } UbuntuDeviceNotifier::~UbuntuDeviceNotifier() { m_udevSocketNotifier->disconnect(SIGNAL(activated(int))); m_udevSocketNotifier->deleteLater(); udev_monitor_unref(m_udevMonitor); udev_unref(m_dev); } void UbuntuDeviceNotifier::startMonitoring(const QString &serialNumber) { m_serialNumber = serialNumber; // check if the device is connected or disconnected at the moment struct udev_list_entry *dev_list_entry; struct udev_device *dev; struct udev_enumerate *enumerate = udev_enumerate_new(m_dev); udev_enumerate_add_match_subsystem(enumerate, "usb"); udev_enumerate_add_match_sysattr(enumerate,"serial",serialNumber.toLatin1().constData()); udev_enumerate_scan_devices(enumerate); struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(dev_list_entry, devices) { const char *path; path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(m_dev, path); m_devNode = QLatin1String(udev_device_get_devnode(dev)); udev_device_unref(dev); } udev_enumerate_unref(enumerate); } void UbuntuDeviceNotifier::stopMonitoring() { m_serialNumber = QLatin1String(""); } /*! * \brief UbuntuDeviceNotifier::isConnected * Returns true if the device that is currently monitored * is connected. * \note you need to call startMonitoring() first */ bool UbuntuDeviceNotifier::isConnected() const { return !m_devNode.isEmpty(); } void UbuntuDeviceNotifier::on_udev_event() { if (!m_udevMonitor) { qDebug() << QLatin1String("no monitor"); return; } struct udev_device *dev; dev = udev_monitor_receive_device(m_udevMonitor); if (!dev) { qDebug() << QLatin1String("no device"); udev_device_unref(dev); return; } QString serial = QLatin1String(udev_device_get_sysattr_value(dev,"serial")); QString action = QLatin1String(udev_device_get_action(dev)); QString devNode = QLatin1String(udev_device_get_devnode(dev)); udev_device_unref(dev); if (action == QLatin1String("remove") && (m_devNode == devNode) && m_devNode.isEmpty()==false) { m_devNode = QLatin1String(""); emit deviceDisconnected(); } else if (action == QLatin1String("add") && m_serialNumber == serial && m_serialNumber.isEmpty()==false) { emit deviceConnected(); emit deviceConnected(m_serialNumber); m_devNode = devNode; } else if (action == QLatin1String("add")) { if (!serial.isEmpty()) { emit deviceConnected(serial); } } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuversionmanager.cpp0000644000015301777760000000351112323167147030037 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuversionmanager.h" #include #include using namespace Ubuntu::Internal; UbuntuVersionManager *UbuntuVersionManager::m_self = 0; UbuntuVersionManager::UbuntuVersionManager(QObject *parent) : QObject(parent) { m_hostVersion = new UbuntuVersion(); m_self = this; } void UbuntuVersionManager::detectAvailableVersions() { // no other platforms yet, add support for Touch devices. // now just the desktop platform. } Core::FeatureSet UbuntuVersionManager::availableFeatures(const QString &platformName) const { Q_UNUSED(platformName); return m_hostVersion->features(); } QStringList UbuntuVersionManager::availablePlatforms() const { QStringList platforms; platforms << QLatin1String(Constants::PLATFORM_DESKTOP); return platforms; } QString UbuntuVersionManager::displayNameForPlatform(const QString &string) const { Q_UNUSED(string); return QString(QLatin1String(Constants::PLATFORM_DESKTOP_DISPLAYNAME)).arg(m_hostVersion->release()); } UbuntuVersionManager *UbuntuVersionManager::instance() { return m_self; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucreatenewchrootdialog.ui0000644000015301777760000000411212323167147031224 0ustar pbusernogroup00000000000000 Ubuntu::Internal::UbuntuCreateNewChrootDialog 0 0 257 111 Dialog Architecture Framework Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() Ubuntu::Internal::UbuntuCreateNewChrootDialog accept() 248 254 157 274 buttonBox rejected() Ubuntu::Internal::UbuntuCreateNewChrootDialog reject() 316 260 286 274 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingspage.cpp0000644000015301777760000000260112323167147027513 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusettingspage.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; using namespace Ubuntu; UbuntuSettingsPage::UbuntuSettingsPage() : m_widget(0) { setId("A.Tabs"); setDisplayName(tr("Tabs")); setCategory("Ubuntu"); setDisplayCategory(QLatin1String("Ubuntu")); setCategoryIcon(QLatin1String(Ubuntu::Constants::UBUNTU_SETTINGS_ICON)); } UbuntuSettingsPage::~UbuntuSettingsPage() { } QWidget *UbuntuSettingsPage::createPage(QWidget *parent) { m_widget = new UbuntuSettingsWidget(parent); return m_widget; } void UbuntuSettingsPage::apply() { if (!m_widget) // page was never shown return; m_widget->apply(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/clicktoolchain.h0000644000015301777760000000505412323167147026213 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_CLICKTOOLCHAIN_H #define UBUNTU_INTERNAL_CLICKTOOLCHAIN_H #include #include "ubuntuclicktool.h" namespace Ubuntu { namespace Internal { class ClickToolChainFactory; class ClickToolChain : public ProjectExplorer::GccToolChain { friend class ClickToolChainFactory; // ToolChain interface public: virtual QList suggestedMkspecList() const; virtual Utils::FileName suggestedDebugger() const; virtual QString type() const; virtual QString typeDisplayName() const; virtual bool isValid() const; virtual void addToEnvironment(Utils::Environment &env) const; virtual QString makeCommand(const Utils::Environment &) const; virtual bool operator ==(const ProjectExplorer::ToolChain &tc) const; virtual ProjectExplorer::ToolChainConfigWidget *configurationWidget(); virtual QVariantMap toMap() const; QString gnutriplet () const; const UbuntuClickTool::Target &clickTarget () const; protected: virtual bool fromMap(const QVariantMap &data); ClickToolChain(const UbuntuClickTool::Target &target,Detection d); ClickToolChain(const ClickToolChain& other); ClickToolChain(); private: UbuntuClickTool::Target m_clickTarget; // ToolChain interface public: virtual Utils::FileName compilerCommand() const; }; class ClickToolChainFactory : public ProjectExplorer::ToolChainFactory { Q_OBJECT public: ClickToolChainFactory(); // ToolChainFactory interface public: virtual QList autoDetect(); virtual bool canRestore(const QVariantMap &data); virtual ProjectExplorer::ToolChain *restore(const QVariantMap &data); static QList createToolChainsForClickTargets(); }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_CLICKTOOLCHAIN_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/myapp.json.template0000644000015301777760000000012112323167147026675 0ustar pbusernogroup00000000000000{ "policy_groups": [ "networking" ], "policy_version": 1.1 } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuapimode.cpp0000644000015301777760000000257612323167147026447 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuapimode.h" #include "ubuntuconstants.h" #include using namespace Ubuntu::Internal; UbuntuAPIMode::UbuntuAPIMode(QObject *parent) : UbuntuWebMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_API_DISPLAYNAME)); setId(Ubuntu::Constants::UBUNTU_MODE_API); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_API)); QFile offlineDocs(QLatin1String(Ubuntu::Constants::UBUNTU_API_OFFLINE)); if (offlineDocs.exists()) { setUrl(QUrl::fromUserInput(QLatin1String(Ubuntu::Constants::UBUNTU_API_OFFLINE))); } else { setUrl(QUrl::fromUserInput(QLatin1String(Ubuntu::Constants::UBUNTU_API_ONLINE))); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectapplicationwizard.cpp0000644000015301777760000001703312323167147032136 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntushared.h" #include "ubuntuprojectapplicationwizard.h" #include "ubuntuconstants.h" #include "ubuntuproject.h" #include #include #include #include #include #include #include #include #include // Utils::matchCaseReplacement #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; UbuntuProjectApplicationWizardDialog::UbuntuProjectApplicationWizardDialog(QWidget *parent, const Core::WizardDialogParameters ¶meters) : ProjectExplorer::BaseProjectWizardDialog(parent, parameters) , m_targetSetupPage(0) { setWindowTitle(tr("New Ubuntu QML Project")); setIntroDescription(tr("This wizard generates a Ubuntu QML project based on Ubuntu Components.")); connect(this,SIGNAL(projectParametersChanged(QString,QString)),this,SLOT(on_projectParametersChanged(QString,QString))); } int UbuntuProjectApplicationWizardDialog::addTargetSetupPage(int id) { m_targetSetupPage = new ProjectExplorer::TargetSetupPage; const QString platform = selectedPlatform(); //prefer Qt Desktop or Platform Kit Core::FeatureSet features = Core::FeatureSet(QtSupport::Constants::FEATURE_DESKTOP); if (platform.isEmpty()) m_targetSetupPage->setPreferredKitMatcher(new QtSupport::QtVersionKitMatcher(features)); else m_targetSetupPage->setPreferredKitMatcher(new QtSupport::QtPlatformKitMatcher(platform)); //make sure only CMake compatible Kits are shown m_targetSetupPage->setRequiredKitMatcher(new CMakeProjectManager::CMakeKitMatcher()); resize(900, 450); if (id >= 0) setPage(id, m_targetSetupPage); else id = addPage(m_targetSetupPage); wizardProgress()->item(id)->setTitle(tr("Kits")); return id; } bool UbuntuProjectApplicationWizardDialog::writeUserFile(const QString &cmakeFileName) const { if (!m_targetSetupPage) return false; CMakeProjectManager::CMakeManager *manager = ExtensionSystem::PluginManager::getObject(); Q_ASSERT(manager); CMakeProjectManager::CMakeProject *pro = new CMakeProjectManager::CMakeProject(manager, cmakeFileName); bool success = m_targetSetupPage->setupProject(pro); if (success) pro->saveSettings(); delete pro; return success; } void UbuntuProjectApplicationWizardDialog::on_projectParametersChanged(const QString &projectName, const QString &path) { if(m_targetSetupPage) { m_targetSetupPage->setProjectPath(path+QDir::separator()+projectName+QDir::separator()+QLatin1String("CMakeLists.txt")); } } UbuntuProjectApplicationWizard::UbuntuProjectApplicationWizard(QJsonObject obj) : Core::BaseFileWizard(), m_app(new UbuntuProjectApp()) { m_app->setupParameters(obj,this); m_app->setData(obj); m_projectType = obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_TYPE)).toString(); } UbuntuProjectApplicationWizard::~UbuntuProjectApplicationWizard() { } Core::FeatureSet UbuntuProjectApplicationWizard::requiredFeatures() const { #ifdef Q_PROCESSOR_ARM return Core::Feature(m_app->requiredFeature()); #else return Core::Feature(QtSupport::Constants::FEATURE_QMLPROJECT) | Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_2) | Core::Feature(m_app->requiredFeature()); #endif } QWizard *UbuntuProjectApplicationWizard::createWizardDialog(QWidget *parent, const Core::WizardDialogParameters &wizardDialogParameters) const { UbuntuProjectApplicationWizardDialog *wizard = new UbuntuProjectApplicationWizardDialog(parent, wizardDialogParameters); if(m_projectType == QLatin1String(Constants::UBUNTU_CMAKEPROJECT_TYPE)) { wizard->addTargetSetupPage(1); } wizard->setProjectName(UbuntuProjectApplicationWizardDialog::uniqueProjectName(wizardDialogParameters.defaultPath())); wizard->addExtensionPages(wizardDialogParameters.extensionPages()); return wizard; } Core::GeneratedFiles UbuntuProjectApplicationWizard::generateFiles(const QWizard *w, QString *errorMessage) const { return m_app->generateFiles(w,errorMessage); } bool UbuntuProjectApplicationWizard::postGenerateFiles(const QWizard *w, const Core::GeneratedFiles &l, QString *errorMessage) { const UbuntuProjectApplicationWizardDialog *dialog = qobject_cast(w); bool retval = true; // make sure that the project gets configured properly if (m_app->projectType() == QLatin1String(Constants::UBUNTU_QTPROJECT_TYPE)) { QmakeProjectManager::QmakeManager *manager = ExtensionSystem::PluginManager::getObject(); ProjectExplorer::Project* project = new QmakeProjectManager::QmakeProject(manager, m_app->projectFileName()); retval = BaseFileWizard::postGenerateOpenEditors(l,errorMessage); ProjectExplorer::ProjectExplorerPlugin::instance()->openProject(m_app->projectFileName(), errorMessage); if (project->needsConfiguration()) { Core::ModeManager::activateMode(ProjectExplorer::Constants::MODE_SESSION); } delete project; } else { if(m_app->projectType() == QLatin1String(Constants::UBUNTU_CMAKEPROJECT_TYPE)) { // Generate user settings foreach (const Core::GeneratedFile &file, l) if (file.attributes() & Core::GeneratedFile::OpenProjectAttribute) { dialog->writeUserFile(file.path()); break; } } retval = ProjectExplorer::CustomProjectWizard::postGenerateOpen(l,errorMessage); } return retval; } /**** statics ****/ QString UbuntuProjectApplicationWizard::templatesPath(QString fileName) { return Constants::UBUNTU_TEMPLATESPATH + fileName; } QByteArray UbuntuProjectApplicationWizard::getProjectTypesJSON() { QByteArray contents; QString errorMsg; if (readFile(templatesPath(QLatin1String(Constants::UBUNTU_PROJECTJSON)),&contents, &errorMsg) == false) { contents = errorMsg.toAscii(); qDebug() << __PRETTY_FUNCTION__ << contents; } return contents; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuclicktool.cpp0000644000015301777760000007065112323167147027013 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntuclicktool.h" #include "ubuntupackagingmode.h" #include "ubuntuclickmanifest.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ubuntuconstants.h" #include "ubuntushared.h" #include namespace Ubuntu { namespace Internal { /** * @brief UbuntuClickTool::UbuntuClickTool * Implements functionality needed for executing the click * tool */ UbuntuClickTool::UbuntuClickTool() { } /** * @brief UbuntuClickTool::parametersForCreateChroot * Initializes a ProjectExplorer::ProcessParameters object with command and arguments * to create a new chroot */ void UbuntuClickTool::parametersForCreateChroot(const Target &target, ProjectExplorer::ProcessParameters *params) { QString command = QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_CREATE_ARGS) .arg(Constants::UBUNTU_SCRIPTPATH) .arg(target.architecture) .arg(target.framework) .arg(target.series); params->setCommand(QLatin1String(Constants::UBUNTU_SUDO_BINARY)); params->setEnvironment(Utils::Environment::systemEnvironment()); params->setArguments(command); } /** * @brief UbuntuClickTool::parametersForMaintainChroot * Initializes params with the arguments for maintaining the chroot * @note does not call ProjectExplorer::ProcessParameters::resolveAll() */ void UbuntuClickTool::parametersForMaintainChroot(const UbuntuClickTool::MaintainMode &mode, const Target &target, ProjectExplorer::ProcessParameters *params) { QString arguments; switch (mode) { case Upgrade: params->setCommand(QLatin1String(Constants::UBUNTU_CLICK_BINARY)); arguments = QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_UPGRADE_ARGS) .arg(target.architecture) .arg(target.framework) .arg(target.series); break; case Delete: params->setCommand(QLatin1String(Constants::UBUNTU_SUDO_BINARY)); arguments = QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_DESTROY_ARGS) .arg(Constants::UBUNTU_SCRIPTPATH) .arg(target.architecture) .arg(target.framework) .arg(target.series); break; } params->setEnvironment(Utils::Environment::systemEnvironment()); params->setArguments(arguments); } /** * @brief UbuntuClickTool::parametersForCmake * Fills ProcessParameters to run cmake inside the Target * @note does not call ProjectExplorer::ProcessParameters::resolveAll() */ void UbuntuClickTool::parametersForCmake(const Target &target, const QString &buildDir , const QString &relPathToSource, const QStringList &userArgs, ProjectExplorer::ProcessParameters *params) { QString arguments = QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_CMAKE_ARGS) .arg(target.architecture) .arg(target.framework) .arg(target.series) .arg(userArgs.join(QChar::fromLatin1(' '))) .arg(relPathToSource); params->setWorkingDirectory(buildDir); params->setCommand(QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_CMAKE_SCRIPT).arg(Constants::UBUNTU_SCRIPTPATH)); params->setArguments(arguments); params->setEnvironment(Utils::Environment::systemEnvironment()); } /** * @brief UbuntuClickTool::parametersForMake * Fills ProcessParameters to run make inside the Target * @note does not call ProjectExplorer::ProcessParameters::resolveAll() */ void UbuntuClickTool::parametersForMake(const UbuntuClickTool::Target &target, const QString &buildDir , const QString& makeArgs, ProjectExplorer::ProcessParameters *params) { QString arguments = QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_MAKE_ARGS) .arg(target.architecture) .arg(target.framework) .arg(target.series) .arg(makeArgs); params->setWorkingDirectory(buildDir); params->setCommand(QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_MAKE_SCRIPT).arg(Constants::UBUNTU_SCRIPTPATH)); params->setArguments(arguments); params->setEnvironment(Utils::Environment::systemEnvironment()); } /** * @brief UbuntuClickTool::openChrootTerminal * Opens a new terminal logged into the chroot specified by \a target * The terminal emulator used is specified in the Creator environment option page */ void UbuntuClickTool::openChrootTerminal(const UbuntuClickTool::Target &target) { QStringList args = Utils::QtcProcess::splitArgs(Utils::ConsoleProcess::terminalEmulator(Core::ICore::settings())); QString term = args.takeFirst(); args << QString(QLatin1String(Constants::UBUNTU_CLICK_OPEN_TERMINAL)) .arg(target.architecture) .arg(target.framework) .arg(target.series); if(!QProcess::startDetached(term,args,QDir::homePath())) { printToOutputPane(QLatin1String(Constants::UBUNTU_CLICK_OPEN_TERMINAL_ERROR)); } } bool UbuntuClickTool::getTargetFromUser(Target *target, const QString &framework) { QList targets = UbuntuClickTool::listAvailableTargets(framework); if (!targets.size()) { QString message = QCoreApplication::translate("UbuntuClickTool",Constants::UBUNTU_CLICK_NOTARGETS_MESSAGE); if(!framework.isEmpty()) { message = QCoreApplication::translate("UbuntuClickTool",Constants::UBUNTU_CLICK_NOTARGETS_FRAMEWORK_MESSAGE) .arg(framework); } QMessageBox::warning(Core::ICore::mainWindow(), QCoreApplication::translate("UbuntuClickTool",Constants::UBUNTU_CLICK_NOTARGETS_TITLE), message); return false; } //if we have only 1 target there is nothing to choose if(targets.size() == 1){ *target = targets[0]; return true; } QStringList items; foreach(const UbuntuClickTool::Target& t, targets) items << QString::fromLatin1("%0-%1").arg(t.framework).arg(t.architecture); bool ok = false; QString item = QInputDialog::getItem(Core::ICore::mainWindow() ,QCoreApplication::translate("UbuntuClickTool",Constants::UBUNTU_CLICK_SELECT_TARGET_TITLE) ,QCoreApplication::translate("UbuntuClickTool",Constants::UBUNTU_CLICK_SELECT_TARGET_LABEL) ,items,0,false,&ok); //get index of item in the targets list int idx = items.indexOf(item); if(!ok || idx < 0 || idx >= targets.size()) return false; *target = targets[idx]; return true; } QString UbuntuClickTool::targetBasePath(const UbuntuClickTool::Target &target) { return QString::fromLatin1("%1/click-%2-%3") .arg(QLatin1String(Constants::UBUNTU_CLICK_CHROOT_BASEPATH)) .arg(target.framework) .arg(target.architecture); } /*! * \brief UbuntuClickTool::getSupportedFrameworks * returns all available frameworks on the host system */ QStringList UbuntuClickTool::getSupportedFrameworks() { QStringList items; QDir frameworksDir(QLatin1String(Constants::UBUNTU_CLICK_FRAMEWORKS_BASEPATH)); if(!frameworksDir.exists()) return items; QStringList availableFrameworkFiles = frameworksDir.entryList(QStringList()< targetVer = targetVersion(target); if(targetVer.first == -1) return false; return true; } /*! * \brief UbuntuClickTool::getMostRecentFramework * returns the framework with the highest number supporting the subFramework * or a empty string of no framework with the given \a subFramework was found */ QString UbuntuClickTool::getMostRecentFramework(const QString &subFramework) { //returned list is ordered from newest -> oldest framework QStringList allFws = getSupportedFrameworks(); QString currFw; foreach(const QString &framework, allFws) { QString basename; QStringList extensions; QRegularExpression expr(QLatin1String(Constants::UBUNTU_CLICK_BASE_FRAMEWORK_REGEX)); QRegularExpressionMatch match = expr.match(framework); if(match.hasMatch()) { basename = match.captured(1); extensions = QString(framework).replace(basename, QString()).split(QChar::fromLatin1('-'), QString::SkipEmptyParts); } else { continue; } //this is a multi purpose framework if (extensions.size() == 0 || (extensions.size() == 1 && extensions[0].startsWith(QLatin1String("dev")) )) { if (currFw.isEmpty()) { currFw = framework; } //if the subframework is empty we return //the first baseframework we can find if(subFramework.isEmpty()) return currFw; continue; } if(extensions.contains(subFramework)) return framework; } return currFw; } /** * @brief UbuntuClickTool::listAvailableTargets * @return all currently existing chroot targets in the system */ QList UbuntuClickTool::listAvailableTargets(const QString &framework) { QList items; QDir chrootDir(QLatin1String(Constants::UBUNTU_CLICK_CHROOT_BASEPATH)); QString filterRegex = QLatin1String(Constants::UBUNTU_CLICK_TARGETS_REGEX); if(!framework.isEmpty()) { QRegularExpression expr(QLatin1String(Constants::UBUNTU_CLICK_BASE_FRAMEWORK_REGEX)); QRegularExpressionMatch match = expr.match(framework); if(match.hasMatch()) { qDebug()<<"Filtering for base framework: "< UbuntuClickTool::targetVersion(const UbuntuClickTool::Target &target) { QFile f(QString::fromLatin1("%1/%2") .arg(targetBasePath(target)) .arg(QLatin1String("etc/lsb-release"))); if (!f.open(QIODevice::ReadOnly)) { //there is no lsb-release file... what now? return qMakePair(-1,-1); } QString info = QString::fromLatin1(f.readAll()); QRegularExpression grep(QLatin1String(Constants::UBUNTU_CLICK_VERSION_REGEX),QRegularExpression::MultilineOption); QRegularExpressionMatch match = grep.match(info); if(!match.hasMatch()) { return qMakePair(-1,-1); } bool ok = false; int majorV = match.captured(1).toInt(&ok); if(!ok) { return qMakePair(-1,-1); } int minorV = match.captured(2).toInt(); return qMakePair(majorV,minorV); } /*! * \brief UbuntuClickTool::targetFromPath * returns true if the given path is a click target * if it is, \a tg will be initialized with that targets values */ bool UbuntuClickTool::targetFromPath(const QString &targetPath, UbuntuClickTool::Target *tg) { QRegularExpression clickFilter(QLatin1String(Constants::UBUNTU_CLICK_TARGETS_REGEX)); QRegularExpressionMatch match = clickFilter.match(targetPath); if(!match.hasMatch()) { return false; } Target t; t.maybeBroken = false; //we are optimistic t.framework = match.captured(1); t.architecture = match.captured(2); //now read informations about the target QFile f(QString::fromLatin1("%1/%2") .arg(targetBasePath(t)) .arg(QLatin1String("/etc/lsb-release"))); if (!f.open(QIODevice::ReadOnly)) { //there is no lsb-release file... what now? t.maybeBroken = true; } else { QString info = QString::fromLatin1(f.readAll()); //read version QRegularExpression grep(QLatin1String(Constants::UBUNTU_CLICK_VERSION_REGEX),QRegularExpression::MultilineOption); QRegularExpressionMatch match = grep.match(info); if(!match.hasMatch()) { t.maybeBroken = true; } else { bool ok = false; t.majorVersion = match.captured(1).toInt(&ok); if(!ok) { t.maybeBroken = true; t.majorVersion = -1; } t.minorVersion = match.captured(2).toInt(&ok); if(!ok) { t.maybeBroken = true; t.minorVersion = -1; } } //read series grep.setPattern(QString::fromLatin1(Constants::UBUNTU_CLICK_SERIES_REGEX)); grep.setPatternOptions(QRegularExpression::MultilineOption); match = grep.match(info); if(!match.hasMatch()) { t.maybeBroken = true; } else { t.series = match.captured(1); } } *tg = t; return true; } /** * @class UbuntuClickManager * Build support for click chroot targets, this is a * temporary solution until we find a way to make cmakeplugin * work like we need it */ UbuntuClickManager::UbuntuClickManager(QObject *parent) : QObject(parent) , m_buildInChrootAction(0) , m_failOnError(true) , m_process(0) , m_futureInterface(0) , m_currentBuild(0) { m_process = new Utils::QtcProcess(this); connect(m_process,SIGNAL(readyRead()),this,SLOT(on_processReadyRead())); connect(m_process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(on_processFinished(int,QProcess::ExitStatus))); } UbuntuClickManager::~UbuntuClickManager() { cleanup(); } void UbuntuClickManager::initialize() { Core::ActionContainer *mproject = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT); Core::ActionContainer *mbuild = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT); //only visible for a cmake project const Core::Context projectContext(CMakeProjectManager::Constants::PROJECTCONTEXT); m_buildInChrootAction = new QAction(QIcon(), tr(Constants::UBUNTU_CLICK_BUILD_CONTEXTMENU_TEXT), this); Core::Command *command = Core::ActionManager::registerAction(m_buildInChrootAction, Constants::UBUNTU_CLICK_BUILD_CONTEXTMENU_ID, projectContext); command->setAttribute(Core::Command::CA_Hide); mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD); if(mbuild) { mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD); } connect(m_buildInChrootAction,SIGNAL(triggered()),this,SLOT(on_buildInChrootAction())); } void UbuntuClickManager::processBuildQueue() { //build is already running if(m_currentBuild) return; //build queue is empty if(m_pendingBuilds.isEmpty()) { cleanup(); return; } if (!m_futureInterface) { m_futureInterface = new QFutureInterface(); m_futureInterface->setProgressRange(0,5); Core::FutureProgress* futureProgress = Core::ProgressManager::addTask(m_futureInterface->future() ,tr(Constants::UBUNTU_CLICK_BUILDTASK_TITLE) ,Core::Id(Constants::UBUNTU_CLICK_BUILDTASK_ID)); connect(futureProgress,SIGNAL(canceled()),this,SLOT(stop())); } m_currentBuild = m_pendingBuilds.dequeue(); ProjectExplorer::BuildConfiguration* bc = m_currentBuild->buildTarget->activeBuildConfiguration(); if(!bc) { delete m_currentBuild; m_currentBuild = 0; printToOutputPane(tr("--- %0 ---") .arg(QLatin1String(Constants::UBUNTU_CLICK_NOBUILDCONFIG_ERROR)) .arg(m_currentBuild->buildTarget->project()->displayName())); QMetaObject::invokeMethod(this,"processBuildQueue",Qt::QueuedConnection); return; } //only one build at a time setBuildActionsEnabled(false); QString buildDirStr = bc->buildDirectory().toString(); buildDirStr.append(QString::fromLatin1("/%0-%1") .arg(m_currentBuild->targetChroot.framework) .arg(m_currentBuild->targetChroot.architecture)); QDir buildDir (buildDirStr); if(!buildDir.exists()) buildDir.mkpath(buildDirStr); m_currentBuild->buildDir = buildDirStr; nextStep(); } void UbuntuClickManager::stop() { if (m_currentBuild) { m_futureInterface->reportCanceled(); m_futureInterface->reportFinished(); if (m_process->state() != QProcess::NotRunning) { printToOutputPane(tr("--- %0 ---").arg(QLatin1String(Constants::UBUNTU_CLICK_BUILD_CANCELED_MESSAGE))); m_process->kill(); m_process->waitForFinished(); } } cleanup(); } void UbuntuClickManager::cleanup() { if (m_pendingBuilds.size()) { qDeleteAll(m_pendingBuilds.begin(),m_pendingBuilds.end()); m_pendingBuilds.clear(); } if (m_currentBuild) { delete m_currentBuild; m_currentBuild = 0; } if (m_futureInterface) { delete m_futureInterface; m_futureInterface = 0; } setBuildActionsEnabled(true); } /* *implementation of the statemachine, runs over *all buildsteps needed for a target to be built */ void UbuntuClickManager::nextStep() { if(!m_currentBuild) return; Q_ASSERT(m_process->state() != QProcess::Running); switch(m_currentBuild->currentState) { case NotStarted: { m_currentBuild->currentState = MakeClean; ProjectExplorer::ProcessParameters params; UbuntuClickTool::parametersForMake(m_currentBuild->targetChroot ,m_currentBuild->buildDir ,QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_MAKE_CLEAN_ARGS) ,¶ms); params.resolveAll(); //just continue if make clean fails, maybe we never built before m_failOnError = false; m_futureInterface->reportStarted(); m_futureInterface->setProgressValueAndText(1,tr(Constants::UBUNTU_CLICK_BUILD_CLEAN_MESSAGE)); printToOutputPane(tr(Constants::UBUNTU_CLICK_BUILD_START_MESSAGE).arg(m_currentBuild->buildTarget->project()->displayName())); printToOutputPane(tr(Constants::UBUNTU_CLICK_BUILDDIR_MESSAGE).arg(m_currentBuild->buildDir)); printToOutputPane(tr(Constants::UBUNTU_CLICK_BUILD_CLEAN_MESSAGE)); startProcess(params); break; } case MakeClean:{ m_currentBuild->currentState = Cmake; ProjectExplorer::ProcessParameters params; QStringList userArgs; CMakeProjectManager::CMakeBuildConfiguration* conf = qobject_cast(m_currentBuild->buildTarget->activeBuildConfiguration()); if(conf) { userArgs = conf->arguments(); } //get relative directory to source dir QDir bd(m_currentBuild->buildDir); QString relPath = bd.relativeFilePath(m_currentBuild->buildTarget->project()->projectDirectory()); UbuntuClickTool::parametersForCmake(m_currentBuild->targetChroot ,m_currentBuild->buildDir ,relPath ,userArgs ,¶ms); params.resolveAll(); m_failOnError = true; m_futureInterface->setProgressValueAndText(2,tr(Constants::UBUNTU_CLICK_BUILD_CMAKE_MESSAGE)); printToOutputPane(tr(Constants::UBUNTU_CLICK_BUILD_CMAKE_MESSAGE)); startProcess(params); break; } case Cmake:{ m_currentBuild->currentState = FixMoc; ProjectExplorer::ProcessParameters params; QString arguments = QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_CMAKE_ARGS) .arg(m_currentBuild->targetChroot.architecture) .arg(m_currentBuild->targetChroot.framework) .arg(m_currentBuild->targetChroot.series); params.setWorkingDirectory(m_currentBuild->buildDir); params.setCommand(QString::fromLatin1(Constants::UBUNTU_CLICK_FIXAUTOMOC_SCRIPT) .arg(Constants::UBUNTU_SCRIPTPATH)); params.setArguments(arguments); params.setEnvironment(Utils::Environment::systemEnvironment()); m_futureInterface->setProgressValueAndText(3,tr(Constants::UBUNTU_CLICK_FIXAUTOMOC_MESSAGE)); printToOutputPane(tr(Constants::UBUNTU_CLICK_FIXAUTOMOC_MESSAGE)); startProcess(params); break; } case FixMoc:{ m_currentBuild->currentState = Make; ProjectExplorer::ProcessParameters params; UbuntuClickTool::parametersForMake(m_currentBuild->targetChroot ,m_currentBuild->buildDir ,QString::fromLatin1("") ,¶ms); params.resolveAll(); m_failOnError = true; m_futureInterface->setProgressValueAndText(4,tr(Constants::UBUNTU_CLICK_MAKE_MESSAGE)); printToOutputPane(tr(Constants::UBUNTU_CLICK_MAKE_MESSAGE)); startProcess(params); break; } case Make:{ m_currentBuild->currentState = MakeInstall; ProjectExplorer::ProcessParameters params; UbuntuClickTool::parametersForMake(m_currentBuild->targetChroot ,m_currentBuild->buildDir ,QString::fromLatin1(Constants::UBUNTU_CLICK_CHROOT_MAKE_INSTALL_ARGS) ,¶ms); params.resolveAll(); m_failOnError = true; m_futureInterface->setProgressValueAndText(4,tr(Constants::UBUNTU_CLICK_MAKE_MESSAGE)); printToOutputPane(tr(Constants::UBUNTU_CLICK_MAKE_MESSAGE)); startProcess(params); break; } case MakeInstall:{ m_currentBuild->currentState = Finished; delete m_currentBuild; m_currentBuild = 0; m_futureInterface->reportFinished(); printToOutputPane(tr("--- %0 ---").arg(QLatin1String(Constants::UBUNTU_CLICK_BUILD_OK_MESSAGE))); //give the UI time to show we are finished QMetaObject::invokeMethod(this,"processBuildQueue",Qt::QueuedConnection); setBuildActionsEnabled(true); break; } default: Q_ASSERT(false); //this should never happen } } /** * @brief UbuntuClickManager::startProcess * Starts the internal QProcess that executes the current buildstep */ void UbuntuClickManager::startProcess(const ProjectExplorer::ProcessParameters ¶ms) { printToOutputPane(tr(Constants::UBUNTU_CLICK_RUN_COMMAND_MESSAGE).arg(params.command()).arg(params.arguments())); m_process->setCommand(params.command(),params.arguments()); m_process->setWorkingDirectory(params.workingDirectory()); m_process->setEnvironment(params.environment()); m_process->start(); } /** * @brief UbuntuClickManager::setBuildActionsEnabled * Enables or disables the build actions shown in the menu, for example * if a build is currently running */ void UbuntuClickManager::setBuildActionsEnabled(const bool enabled) { m_buildInChrootAction->setEnabled(enabled); } /** * @brief UbuntuClickManager::on_buildInChrootAction * callback slot that is called by the action */ void UbuntuClickManager::on_buildInChrootAction() { ProjectExplorer::Project* currentProject = ProjectExplorer::ProjectExplorerPlugin::currentProject(); if(!currentProject) return; ProjectExplorer::Target* buildTarget = currentProject->activeTarget(); if(!buildTarget) return; QString fw = UbuntuPackagingMode::manifest()->frameworkName(); UbuntuClickTool::Target clickTarget; if(!UbuntuClickTool::getTargetFromUser(&clickTarget,fw)) return; Build* b = new Build(); b->targetChroot = clickTarget; b->buildTarget = buildTarget; b->currentState = NotStarted; m_pendingBuilds.enqueue(b); processBuildQueue(); } void UbuntuClickManager::on_processFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitCode != 0 || exitStatus == QProcess::CrashExit) { printToOutputPane(QString::fromLocal8Bit(m_process->readAllStandardError())); if(m_failOnError) { printToOutputPane(tr("--- %0 ---").arg(QLatin1String(Constants::UBUNTU_CLICK_SELECT_TARGET_LABEL))); stop(); } } QString errorMsg = QString::fromLocal8Bit(m_process->readAllStandardError()); if (errorMsg.trimmed().length()>0) printToOutputPane(errorMsg); QString msg = QString::fromLocal8Bit(m_process->readAllStandardOutput()); if (msg.trimmed().length()>0) printToOutputPane(msg); nextStep(); } void UbuntuClickManager::on_processReadyRead() { QString stderr = QString::fromLocal8Bit(m_process->readAllStandardError()); QString stdout = QString::fromLocal8Bit(m_process->readAllStandardOutput()); if (!stderr.isEmpty()) { printToOutputPane(stderr); } if (!stdout.isEmpty()) { printToOutputPane(stdout); } } QDebug operator<<(QDebug dbg, const UbuntuClickTool::Target& t) { dbg.nospace() << "("<<"series: "<. * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUDEVICESWIDGET_H #define UBUNTUDEVICESWIDGET_H #include #include #include "ubuntudevicenotifier.h" #include "ubuntuprocess.h" #include "ubuntudevice.h" namespace Ui { class UbuntuDevicesWidget; } namespace Ubuntu { namespace Internal { class UbuntuDevice; } } class UbuntuDevicesWidget : public QWidget { Q_OBJECT public: explicit UbuntuDevicesWidget(QWidget *parent = 0); ~UbuntuDevicesWidget(); static UbuntuDevicesWidget* instance(); bool deviceDetected(); QString serialNumber(); Ubuntu::Internal::UbuntuDevice::ConstPtr device(); signals: void updateDeviceActions(); protected slots: void onMessage(QString msg); void onFinished(QString cmd, int code); void onError(QString msg); void onStarted(QString cmd); void on_pushButton_InstallEmulator_OK_clicked(); void on_pushButton_CreateNewEmulator_clicked(); void on_pushButton_StartEmulator_clicked(); void onDeviceConnected(const QString&id); void on_pushButtonRefresh_clicked(); void on_pushButtonRefresh_2_clicked() { on_pushButtonRefresh_clicked(); } void on_comboBoxSerialNumber_currentIndexChanged( const QString & text ); void checkEmulator(); void checkEmulatorInstances(); void detectDevices( const bool restartAdb = false ); private slots: void readDevicesFromSettings(); void deviceAdded (const Core::Id& id); void deviceRemoved (const Core::Id& id); void deviceUpdated (const Core::Id& id); void knownDeviceFeatureChange (); void slotChanged(); void startEmulator(QListWidgetItem*); void setupDevicePage (); private: void beginAction(QString); void endAction(QString); int addDevice(Ubuntu::Internal::UbuntuDevice* dev); void removeDevice(Ubuntu::Internal::UbuntuDevice* dev); void registerNewDevice (const QString &serial, const QString &deviceInfo); QMap m_knownDevices; Ui::UbuntuDevicesWidget *ui; Ubuntu::Internal::UbuntuProcess *m_ubuntuProcess; QString m_reply; UbuntuDeviceNotifier m_ubuntuDeviceNotifier; bool m_refreshKnownAfterScan; bool m_aboutToClose; QString m_deviceSerialNumber; static UbuntuDevicesWidget *m_instance; bool validate(); }; #endif // UBUNTUDEVICESWIDGET_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntukitmanager.cpp0000644000015301777760000002276512323167147027155 0ustar pbusernogroup00000000000000#include "ubuntukitmanager.h" #include "clicktoolchain.h" #include "ubuntuconstants.h" #include "ubuntucmaketool.h" #include "ubuntudevice.h" #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { static bool equalKits(ProjectExplorer::Kit *a, ProjectExplorer::Kit *b) { return ProjectExplorer::ToolChainKitInformation::toolChain(a) == ProjectExplorer::ToolChainKitInformation::ToolChainKitInformation::toolChain(b); } UbuntuKitManager::UbuntuKitManager() { } void UbuntuKitManager::autoDetectKits() { QList toolchains; // having a empty toolchains list will remove all autodetected kits for android // exactly what we want in that case foreach (ProjectExplorer::ToolChain *tc, ProjectExplorer::ToolChainManager::toolChains()) { if(tc) { if (!tc->isAutoDetected()) continue; if (tc->type() != QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) continue; toolchains << static_cast(tc); } } QList existingKits; foreach (ProjectExplorer::Kit *k, ProjectExplorer::KitManager::kits()) { if (k->isSdkProvided()) continue; ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k); if (tc && tc->type() != QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) continue; CMakeProjectManager::ICMakeTool* icmake = CMakeProjectManager::CMakeKitInformation::cmakeTool(k); UbuntuCMakeTool* cmake = qobject_cast(icmake); //if the kit has no valid UbuntuCMakeTool, let it be removed from the code later if(cmake) { Utils::Environment env = Utils::Environment::systemEnvironment(); k->addToEnvironment(env); cmake->setEnvironment(env); } //@TODO check for ubuntu device information qDebug()<<"Found possible Ubuntu Kit: "<displayName(); existingKits << k; } #if 0 QMap > qtVersionsForArch; foreach (QtSupport::BaseQtVersion *qtVersion, QtSupport::QtVersionManager::versions()) { if (qtVersion->type() != QLatin1String(Constants::ANDROIDQT)) continue; QList qtAbis = qtVersion->qtAbis(); if (qtAbis.empty()) continue; qtVersionsForArch[qtAbis.first().architecture()].append(qtVersion); } DeviceManager *dm = DeviceManager::instance(); IDevice::ConstPtr device = dm->find(Core::Id(Constants::ANDROID_DEVICE_ID)); if (device.isNull()) { // no device, means no sdk path foreach (Kit *k, existingKits) KitManager::deregisterKit(k); return; } #endif // create new kits QList newKits; foreach (ClickToolChain *tc, toolchains) { ProjectExplorer::Kit* newKit = createKit(tc); newKit->makeSticky(); newKits << newKit; } //remove already existing kits for (int i = existingKits.count() - 1; i >= 0; --i) { ProjectExplorer::Kit *existingKit = existingKits.at(i); for (int j = 0; j < newKits.count(); ++j) { ProjectExplorer::Kit *newKit = newKits.at(j); if (equalKits(existingKit, newKit)) { // Kit is already registered, nothing to do ProjectExplorer::Kit *oldKit = existingKits.takeAt(i); oldKit->makeSticky(); //make sure kit has all required informations fixKit(oldKit); newKits.removeAt(j); ProjectExplorer::KitManager::deleteKit(newKit); j = newKits.count(); } } } //all kits remaining need to be removed if they don't have all informations foreach (ProjectExplorer::Kit *k, existingKits) { ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k); CMakeProjectManager::ICMakeTool* icmake = CMakeProjectManager::CMakeKitInformation::cmakeTool(k); if (tc && tc->type() == QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID) && icmake && icmake->id().toString().startsWith(QLatin1String(Constants::UBUNTU_CLICK_CMAKE_TOOL_ID)) && icmake->isValid()) { fixKit(k); //existing targets are not autodetected anymore k->makeUnSticky(); k->setAutoDetected(false); } else { //has not all informations, go away ProjectExplorer::KitManager::deregisterKit(k); } } foreach (ProjectExplorer::Kit *kit, newKits) { ClickToolChain *tc = static_cast(ProjectExplorer::ToolChainKitInformation::toolChain(kit)); //AndroidQtVersion *qt = static_cast(QtSupport::QtKitInformation::qtVersion(kit)); kit->setDisplayName(tr("UbuntuSDK for %1 (GCC %2-%3)") .arg(tc->clickTarget().architecture) .arg(tc->clickTarget().framework) .arg(tc->clickTarget().series)); ProjectExplorer::KitManager::registerKit(kit); fixKit(kit); } } /*! * \brief UbuntuKitManager::createKit * Creates a new Kit for the Ubunut toolchain and sets default * values */ ProjectExplorer::Kit *UbuntuKitManager::createKit(ClickToolChain *tc) { //@TODO find a qt version ProjectExplorer::Kit* newKit = new ProjectExplorer::Kit; newKit->setAutoDetected(false); //let the user delete that stuff newKit->setIconPath(Utils::FileName::fromString(QLatin1String(Constants::UBUNTU_MODE_WEB_ICON))); ProjectExplorer::ToolChainKitInformation::setToolChain(newKit, tc); //every kit gets its own instance of CMakeTool UbuntuCMakeTool* cmake = new UbuntuCMakeTool; Utils::Environment env = Utils::Environment::systemEnvironment(); newKit->addToEnvironment(env); cmake->setEnvironment(env); CMakeProjectManager::CMakeToolManager::registerCMakeTool(cmake); CMakeProjectManager::CMakeKitInformation::setCMakeTool(newKit,cmake->id()); ProjectExplorer::SysRootKitInformation::setSysRoot(newKit,Utils::FileName::fromString(UbuntuClickTool::targetBasePath(tc->clickTarget()))); //@TODO add gdbserver support //@TODO add real qt version QtSupport::QtKitInformation::setQtVersion(newKit, 0); return newKit; } /*! * \brief UbuntuKitManager::createOrFindDebugger * Tries to find a already existing ubuntu debugger, if it can not find one * it is registered and returned */ QVariant UbuntuKitManager::createOrFindDebugger(const Utils::FileName &path) { if(path.isEmpty()) return QVariant(); QList debuggers = Debugger::DebuggerItemManager::debuggers(); foreach(const Debugger::DebuggerItem& debugger,debuggers) { if(debugger.command() == path) { return debugger.id(); } } Debugger::DebuggerItem debugger; debugger.setCommand(path); debugger.setEngineType(Debugger::GdbEngineType); debugger.setDisplayName(tr("Ubuntu SDK Debugger")); debugger.setAutoDetected(true); //multiarch debugger ProjectExplorer::Abi abi(ProjectExplorer::Abi::UnknownArchitecture ,ProjectExplorer::Abi::LinuxOS ,ProjectExplorer::Abi::GenericLinuxFlavor ,ProjectExplorer::Abi::UnknownFormat ,0); debugger.setAbi(abi); return Debugger::DebuggerItemManager::registerDebugger(debugger); } /*! * \brief UbuntuKitManager::fixKit * Tries to fix a Kit if there is missing information */ void UbuntuKitManager::fixKit(ProjectExplorer::Kit *k) { k->setAutoDetected(false); ClickToolChain* tc = static_cast (ProjectExplorer::ToolChainKitInformation::toolChain(k)); if(!tc) { return; } //make sure we have the multiarch debugger if(!Debugger::DebuggerKitInformation::debugger(k)) { QVariant dId = createOrFindDebugger(tc->suggestedDebugger()); if(dId.isValid()) Debugger::DebuggerKitInformation::setDebugger(k,dId); } if(ProjectExplorer::SysRootKitInformation::sysRoot(k).isEmpty()) { ProjectExplorer::SysRootKitInformation::setSysRoot(k,Utils::FileName::fromString(UbuntuClickTool::targetBasePath(tc->clickTarget()))); } //make sure we point to a ubuntu device Core::Id devId = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(k); if(devId != Constants::UBUNTU_DEVICE_TYPE_ID || !devId.isValid()) { ProjectExplorer::DeviceTypeKitInformation::setDeviceTypeId(k,Core::Id(Constants::UBUNTU_DEVICE_TYPE_ID)); ProjectExplorer::DeviceKitInformation::setDevice(k,ProjectExplorer::IDevice::ConstPtr()); } //values the user can change k->setSticky(ProjectExplorer::DeviceKitInformation::id(),false); k->setSticky(Debugger::DebuggerKitInformation::id(),false); //values the user cannot change k->setSticky(ProjectExplorer::SysRootKitInformation::id(),true); k->setMutable(ProjectExplorer::SysRootKitInformation::id(),false); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsdeviceconnectivitywidget.h0000644000015301777760000000241412323167147033350 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSETTINGSDEVICECONNECTIVITYWIDGET_H #define UBUNTUSETTINGSDEVICECONNECTIVITYWIDGET_H #include #include namespace Ui { class UbuntuSettingsDeviceConnectivityWidget; } class UbuntuSettingsDeviceConnectivityWidget : public QWidget { Q_OBJECT public: explicit UbuntuSettingsDeviceConnectivityWidget(QWidget *parent = 0); ~UbuntuSettingsDeviceConnectivityWidget(); void apply(); private: Ui::UbuntuSettingsDeviceConnectivityWidget *ui; QSettings* m_settings; }; #endif // UBUNTUSETTINGSDEVICECONNECTIVITYWIDGET_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectguesser.h0000644000015301777760000000323312323167147027531 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUPROJECTGUESSER_H #define UBUNTU_INTERNAL_UBUNTUPROJECTGUESSER_H #include #include namespace ProjectExplorer { class Project; } namespace Ubuntu { namespace Internal { class UbuntuProjectGuesser { public: UbuntuProjectGuesser(); static bool isScopesProject ( ProjectExplorer::Project* project, QString *iniFileName = 0 ); static bool isClickAppProject ( ProjectExplorer::Project *project); static Utils::FileName findScopesIniRecursive (const Utils::FileName &searchdir); static Utils::FileName findFileRecursive (const Utils::FileName &searchdir, const QString ®exp); static Utils::FileName findFileRecursive (const Utils::FileName &searchdir, const QRegularExpression ®exp); static QString projectTypeFromCacheOrProject (ProjectExplorer::Project* project); }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUPROJECTGUESSER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/localportsmanager.cpp0000644000015301777760000000703512323167147027276 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "localportsmanager.h" #include #include #include #include namespace Ubuntu { namespace Internal { UbuntuLocalPortsManager* UbuntuLocalPortsManager::m_instance = 0; UbuntuLocalPortsManager::UbuntuLocalPortsManager( ) : QObject(0), m_first(10000), m_last (12000) { Q_ASSERT_X(m_instance == 0, Q_FUNC_INFO,"There can be only one instance of UbuntuLocalPortsManager"); m_instance = this; } void UbuntuLocalPortsManager::setPortsRange(const int first, const int last) { m_instance->m_first = first; m_instance->m_last = last; } /*! * \brief UbuntuLocalPortsManager::getFreeRange * Queries adb which ports are already in use and returns a list * of ports available. * \bug As long as there is only once instance of QtC running this should * be no problem, but when a second one is started it will break the ports for * the first instance, because the ports will be newly assigned */ Utils::PortList UbuntuLocalPortsManager::getFreeRange(const QString &serial, const int count) { QProcess adb; adb.start(QLatin1String("adb") ,QStringList()<= m_instance->m_first && localPort <= m_instance->m_last) { qDebug()<<"Found port already linked to device: "<m_first; for(int i = 0, found = 0; found <= required && firstPort+i < m_instance->m_last; i++) { int port = firstPort + i; if(usedPorts.contains(port)) continue; freePorts.addPort(port); found++; qDebug()<<"Found free port: "<. * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUKITMANAGER_H #define UBUNTU_INTERNAL_UBUNTUKITMANAGER_H #include "clicktoolchain.h" #include namespace Debugger{ class DebuggerItem; } namespace Ubuntu { namespace Internal { class UbuntuKitManager : public QObject { Q_OBJECT public: UbuntuKitManager(); static void autoDetectKits (); static ProjectExplorer::Kit *createKit (ClickToolChain* tc); static QVariant createOrFindDebugger(const Utils::FileName &path); static void fixKit (ProjectExplorer::Kit* k); }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUKITMANAGER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/0000755000015301777760000000000012323167643024316 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/ubuntu-48.png0000644000015301777760000000642512323167147026605 0ustar pbusernogroup00000000000000PNG  IHDR00WbKGD pHYs B(xtIME %, IDAThޭ{pTu?緻z Lx8صl.hǏqZ\28Nnt4i ƱShJ`j B+i+ !iq$Vº3;{>~sι5KKeӌe% Sr~(%"PQT`]ꆨYVL "yXy9?zlo BRTBP}AP@DQqNPE巢( W9&UPׇ ׂU 82+"SQW D%UtcM8@Kp(00X˟Tx,oMMf頵?(g {Ou|y ۢckƺwڞW=":KA'KxNJ %eۢ4m" Knc5*ZN :fjbCAj±+0B$\lEŇ#L1ؽ=D4A-E %TLU=6hDyd;do[x|yu#S=JT%T+pbE[c]Z4kP$ QB#7,v/y04vOו&E-U WN Zi9e@85e9Zi47~ɟ2dmwב< {IxdAh7Q[ e2A>sXpYxaH:zdAHo^UX-{E+l!Q3cqfƋ;ɪrsutN[9u}tÉ\`uFGv,6Vֵ k< IA7)hɟof jIm*rϼu=UkГΟ = ƃlcXQRg{Ϧuj?sEϘTzAή.q~S@&2?&;\q1J-I~(g5#|=qh,֥h7{, z<—E.~?ۅ͡XO:+4 yeUeD"_ Cc}a x7A7_!8< GbFM&33QxIC0Lq%;l^D:7\bmn|XK8ޘ[* 1("uP&okF\/zIr,3V&Tɩ[J_oL^T9HQAwg*G߾]\WT"`?%E 4,;Q딯4B-/8z3iTtznS=nJ I'C|: "}~Var j[뽄x|f)|30N@NU5i3ըjYDil,G:6=KTE+AʯϓHuC5j wj± U*Ɂ0qI۩T8'3 m|i 1>, aXQUE72Tyg _B ˀBZ %jLi}a]˿K XRxLY[!EuhrbvdoOuѵ^y}>0 (~jg7S 5b o) {͡TȮ74BݶF8ӗ!h_@Uq?+K3G"ûGB׮u$6 @>B{W姸!sP0_݌). Ϟ<72{D iz@:iO q׏k"ٴ P77KDDKSDn Q M tU= MN1#C`֯aUyn7ُ78@ٚwsc`gc1,RVw$O$+Ґ*&%Λy;7|1l{ -!Q"so7277G}7&-2*q(b۸4|$R C1D{toYK$SL͗E% .>gk7z {Pi"0~t|p,ݝ8UV`X? *l@U5/g~k5 ("IeHQG?Tϋ$H 8PVI0U* 3mn %f#EQ=hyZgQ`۵[ot,Xl&sYM즥={1NB,5u/S$oD1rHU.CZK##`NL<&&/Kja_&GW- GJοr"Y)&Vz8z[f -dʵR]WŠ:,m؝?gæ}nƽo#>/iEsָ;d9/;Lhޞs Lt|2jQ3mX,Wo0W霷w``*$-ͶRՌIENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/ubuntu-qtcreator.png0000644000015301777760000000311412323167147030346 0ustar pbusernogroup00000000000000PNG  IHDR szzsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATXKGsDdHģ0;AK 6( +.H"X!Bd/1=ęsXTW߾ISRVwy^7yۢ 3;,˲"wŇU-//ƳY{̌=UED5ޑ$ "B%8J—LYI+< @:>j*+ffp/|)6KQ3-,@Ha3+?B T'U`hYvTpA,1ĂcÊpSʀ SC msBwtc_{[O^LhɊ2@цAkCC# ) ,sNM 3K^&ONgxg9:5 0~~k_{]TKEީ:y7{o;KK8L-M՟xJ`UB{ȂW_N߽o=_}o^^4Is" b\S {8qM%)އMwv=?rm WPܺihd!y1{xog7Yiq;̧D@$Q/lvW/nWog]$ػwLGNF]zOo 6+Jlܺu~@F,he vu}+00)V^@DX[[.F^!kܟBp"!jr%2">y>eK͔{+os2*nfZ B>sOQըB܏cཕB#"aF"JX>y>f<4 /)B2?*Ṋʹ_A{_0Pk/^>g`%+Z΃*YE,y{{{N8TFUvf[j3ceel4t]$5@=/N6fEs8bfW?L3,-Y<-S 0'ޟ&̎IeR/gⲹLIENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/ubuntu-128.png0000644000015301777760000001461212323167147026661 0ustar pbusernogroup00000000000000PNG  IHDR>asRGBbKGD pHYs B(xtIME  "iE IDATx]i`Se~ޛ=i%iY HApc. n38.̌Χ#0(0QTTvdTڴJiM,r]MӛEJ'j:Wh6rJɛֈ@qFb0GH Z~8d'\ G"cg\ߐ͈#1 K?3"`4ƈ6P.h$g:c 33B&-# WCs4ȓ/4?? /Pc=x[=gz0PnW] H޶̜vTOToYP0pjeE 0Cm"H[`Jv`zaIP@@`rM/v>ޠ(+! Ib#8m:vy|O0Vn4͏ 'Bfdy c 7>z'  3gM@9V\k w@Aa~8>r -˧t &;lZV4(tOwFv$:Ue.! iAGtٚYeCE,SS(aiH Yȓ@R9l6x-౔SV poUE{[] ES \;` g3 Iv~F8 +4⟠9>{zLZ:+y@:G;(ڭ_ +S =v'ɕAe}SQu-\E .}Obi?yg e X]6k6z?4M :}bGkp=MN}/D)avSQȓ:\5LKx_q OoUCgJ<呜Wg%dD8j~w<ը ,Iteop<gQ[@nx xtsT9 ^FA;q:?\q3 OUykmn9QCΏAMPQok*S Ƃɕ 'QL+ĸNZhmSOǧC P _1 π>Ly\>^@B9D>?:ޚHNrї:A[N73g qtU@@K7 RKϡqU$TѝZZ>4`X17upA&P{ͥ]0 ch<۪[-k~.ꉖ[kaKݽ1wv~}"Mo+D癷yb?s_|6CkQ B5-_( Ff/CP)]v?s v_A}NY#i734]8PJWl] +D۪~CRsc T|3jt$wم@^jf$1:8OMxzC5z"_别$x\(- lcD^py~P嵇P7AvV%AMj苘6{.8uR܃7Þ@k&`Yz#d141ΆzzU̝൚;OIqsBtl k)C V[?d?GvTN~}wNPb(. \lXYCZaMO{H]v وe<&Z8Ny3&$KZWpAaT ?c'n2skT)u!ڤ"|\QؾZN.pAqs[G<{|@ќ<g#.1i/xk}}> :)G$'Kw䡐25v':{qv0 JCCEI MVS۾t] 3z\"z!xܨ>^NhC>6Q2XCh߿|m8m``~،m]@P];!V 1rpĘ)U XWZgEcM SE<dR#xio"2s'瓪?] naIrP>]6cig GlbxƘ9N Q伆7h [5ʖφƿfBs5>ɐ'F%WB1`k\~?"3G H}(V.j;a{Q'(5v6Y^9heE,ª}O~/X,UF\NB P}~#i\"z;ܥpբ$΀>+6P_65ގHhv.m5pEy78 ׵ģ~7eU Ip'f 5b=qkaDPR;*A׈\[8&}٢N|<ӯp!N~}1s<-k8,S#؛ lC:Hjs|3E_017?YQ$b{riqb=ܾ7Oxc0,}**|~ ^|BݗdեVi'FizrdpKwlX@ju vH %F19ٲ&+Azݴ+bFY7 ^U)nֽݹ<|E6[!D?!TpFT-umӳb0qsv=V~" >ڪNk4/zG8)n}H|h蝶nCFZVC|fHh/Ҷ{Emv>+sΛnFg\}6r/!)2LTQo۪a^u] V&r-൚Qa~bD"⠆9mbg.A5{# Bų .;?[7 R+Lj'iMNd WobJ5Io כ8C&Jը4c3'v+Qvh.Y/\`ʼZ|6{Zqs~cX^xa`DڪQѐIo CB18iPd(SC[':>$7ph'߷ھ—'"1'i(XX%TO}ƨr0 az~aFƀЪjmɹy,~g_`^Bfw rշ`"~΃TQ٭ 7}O_UL1pt0 'Ht2%ڼ~A[zP.TfG/}o!fI<õڂo%YbCG;[)^AH˳lp4dL^X^7i )?뇫Zw>ڡ)V.7EPQU{@ J7WQ$,{]/X{fJtqL8^㠹DࢢAn7gEݎD,L_+rnvND#Ibtz+=NQFuV̿X"u8 GVʵBciyr_+1r6k6 cyTol:f oanyD,;-ϔn|7I˩T %O,Oć-{[Ep&`e¯ODDɧqd E d}:}2y ZD|)m{y@a78=w$*s0N&+bPz`۲TBc+RwTCDži80=]V>4O=c3;˗E)89H%C`o@8z_yPȓC4\&M h|2x poazGOk43ىM^9ASwT.JO+U <ܥEpQo]é(UmRJy nL|G]vJi`  }] ok5{P4Q >7w tGw-d7rh `qyk5 G%Кh<qcp. = q0@IĘ`ZS`T0Qsd")NXK?B{OlIENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/launchpad.png0000644000015301777760000000437412323167147026772 0ustar pbusernogroup00000000000000PNG  IHDR05h4sRGBbKGD pHYs B(xtIME v^|IDAThZyPG܌2܇WgPjԨk1HDUnJ%eF%2q5q5FY"\# 007o00wSg~G7U7k(tj ;JLj3aky<؈ >ZFK\EX32 >Be&ؐe@D8S+k:A-?mD { T-[V;~}'ˈ ZF !0PߦwlѩGa}DFȿBA?cC @ϙp}:Sv#glUqEoψX6$.ޫOJhij>CYR+k=&El' yRe%V/;gPD|oɠLfɖӷwNA/F?'hrɬQrxԪ45z <\"XU5PA g6hY+1nxĹ1hvOoi埋GI`C&nW}]L:[8ӌ~V}y5͓bFN#]vN3 |q  t}S)j:;>1s½6]}FVQڢ~)1Sk& pt0ZCt8:H">`e(f/w3\.b.IfYS5Pf.({U)S @`ӶK/Qgpւ3xsb(]Yw_5W6`P>h#?hxaJܭ>CO֚ ]01u$137EEY 0'$oXF#+A5BݜyR|GXZ9{@=K"߂ B9#OOBbZf'r5oԡaI-Aӧcx{1pCH|F0~"]%@B>{5Cr F ܜ-tGR^JE_@$aKX4{I)50T$SGqq,A'֖)nY=@_ g=Nu)^1ӝ?ghĨiFM~j;gA3w/\BVaAy蛪$5p^?-&VhmLMSʛ4 `0a9G~qm`v gW _iJ_gd}2\;soWQQYVHtYpz= ` 7b)Ƽ*::vt$$.yϋE?GJ1h$Q3@ l|J8yZTLS}ʠg|>/AoX@ jTJgФL| ۷58`<1Q(%&Kz(9ے?uwdNv4-GEgѐ-88`| 틙()۳ub*C|۴RbZ}R8sct FoS !e+xB>'21;K߮scHQűlPo{p[ak@7gz3W~ h7s3G $IENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/irc.png0000644000015301777760000000106512323167147025602 0ustar pbusernogroup00000000000000PNG  IHDR(-SsBITOPLTElSLJ3-zrխ8;r_RDD8,( eNVH(&?4:0r[E8znɹdU^H0*u񢛼$%kT=1]H4-G>ǽN=j"?62.yazbXƵzq< pHYs  ~tEXtCreation Time21/9/11FtEXtSoftwareAdobe Fireworks CS5q6IDATMP@M-lSѩd"0݌i|,еݸtv58 v>yEP _̮l] B|C'!&nJ`E 遏V'.aJfLliZe#IASF2:ݰ1Xk2qbnC~QEIENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/packaging.png0000644000015301777760000000676312323167147026763 0ustar pbusernogroup00000000000000PNG  IHDR@@iqbKGDtIME .0 IDATx\u?kvfv׋jce7BZJڤ)MP?JZED#6m&EQ@"U D*MҀ7(]ٙy;^/RJWo}{yosXa/u퀉-h!2D_W]udq h}w<Уҍ|7c1~h?v[%:_6v W:F Wvѵj3Ϗ͟G+rzdߦ׈mo<@AB_kDNDFC'(B<;Z.28oJkv=xnSi;,KwXj ,5!`XjвTUL7Q8ZEB @XU(J/KN@0j7c};;ks^_/($΁85+UFF8FFHSz;_iV.t;<_)&J99Q!5mY%%cuJlXC#1m>t/''BiΟe^&)cIzڹqXI&c-:{=c_O=T>wL$G+9C)8<8ƱqؚC()㕄Bzv\޴k?gP*nO{lݼF&sC[0a:U9&8eͻߵ) ~߻tr 3ܼ 1*nKF-:uJ"eˎ>5U*B[P(O|.: os-)a]{fc:B![.:uXܼkgO<=,*Is]rGrm2" 8# )!Tckwak'7͞x5\qJǢ<@p8Qm %X,bz5!W}/=?s0#ʼnΞ|u&K~iYfUM> bۖymQ~57p9>6k3d՞czcƸ4@ Dsx8Xym |'ׯ- ko+wR5qj$KHj9_Ȍ$R\S@~Y\}%=2_?h@rV/_ƩR#J Q@Ogyc-+#6;_wqjXSaO:hQ ^:w8ndmcW!j !_yte(OQRm2ӅB#DکHSK6=l _]xWg O|j=!s@.B?Pz[ fG\v6$6,_#{X(Ē񕢚οz2HysGi}OR`x[3|J]H dŲW k_E9>f6Q@RKACTcHSM"@mX_ʻz@%,.Pm#+)XEZkʕRs7) @L8!@JTJ GowQ)_tV Ɔ|.bdrI4qbW*$Fj8}度)aE!6nj%:ran[ι D|OJP[Ȩ%.0<2Ԥs!Vdk,~!43^AO)pt\ 9 _"%23+e ۊZi.#l[gF A> =#SO@:h6q:J\ zn>qZ| F)˦Riu=A6d~W"p! nzjֳ焵5hU"KZ3& cLAgIphSs3MX:ژ,Zɰu7jy [\zkqsZ)%IjRHxrMκdfF1h<`^K5uDA\L]:9z^y;m8d: Q$FY|?b;tcāPiG_['C`1xvUYjteנuL dA^<3211|=Bcy=h벘mOeSJJl,~*xԩPh%k!Ӯ~>N8hq Hݑ{iWoyPi&,B<"H/ڄYK7F)pB9.xmgغ/pX485xE55̃92%1f^Msã6Mw~CˌNGw.e /#@I:S O>Ԛ8Ru|% =K4q@ .dH,p[DjJfeG%׮3TFB `Y>r']71 敃z7G HfvSov*O~r$(ך a=+U3ϡzZSLVMSdK־\αŗ/ݻahYajOs b'5I <ž0B|)xG˥]<%p<Zk3XkP"EQ1DPEkx!} =ʼnQJ׿7駟-nqhg uWL'?heuvmٸ!>jZRsSw' "6:e^=xT&^yO}~H@;X;)% >Ak|vus!5| #I5J̩1=pbhbt/_飳 }l sA@{&C?WS,wK%/qnZrXZ\z}Fmy@86djXC3CА}dIENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/coreapps.png0000644000015301777760000000123312323167147026636 0ustar pbusernogroup00000000000000PNG  IHDR szzsRGBbKGD pHYs&&lUtIME 6M IDATXݗkQ?8lRDLb!(b? 暀@EJ[ +<M,$iR"g#.6 XyƏ͋zJ5/,fUs:{BZ*c)%C >)\K`T˰3A2pQ]T7Ue 9Ju'fp ԧQ7fURK p X !|K!l NмQWyv?E'ׯLdIENDB`qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/images/device.png0000644000015301777760000000323012323167147026260 0ustar pbusernogroup00000000000000PNG  IHDRr ߔsRGBbKGD pHYs  tIME $>{IDATHǕs\W}45r4dE& (X@%kȆ *ņRC6qd+RdI#YҌF3Y7LL̫OO?ggl|Kܔ^QM_%|`ZOydp9"!R |EUg8JQin|B˭kqBQRD=R|LSDr'8xW 6]&7C]0 1%wX]]p;H˯ԊiGGq] sk_DiA@R$bdc^w7Ҷ5"#[`s \CrEފU#d2( ̵;m0׀vKk E,掺L;KY֌.skvk ܨ`N`joedY@3yc\%'ܬ#a`1 A(ks( zӥ֝I`n[c1NiaHQEzL&'CuoާY7#+ ))EO^2\}IDMg<EYbu#fՔoIK+&cғm%X`VEA,t."HW¹!{\ "TH֧lA$! $'@A S" ! +Y("H@JKjJUG Idsgc64IRI#ֱXP(4.TԠrgNeN@)FtxGؓ5wn}w%K4mNFYq$錔xf73Ho3(+Z37bt E'XO.OYX ;]Z '|̔{kUC_ +F5RB}ʂ}ލvmy)3SY/ {'Q?X٣'o11!0~}έ%;S 󐧊 XS޳q309Y6^1zdoPĂh1/]8q\E Ca<+0lrB5+l#l=>mX{0 d\ 3%0)Ł). )5:BnetS1>q|lWRSb,jٵS!CA$&KGq՟̨\>ʇy,p"~3|?H'h`'H5KpR]ǙE ](uL')u\AæK,x9+'P~Sՙm*o\M'M.ϵ}# ߊc oobe=|-1Yf'=e9 , 08{5FiW]E9#>6VV}sxF=wR=FXA-&o^%68r @LΈǒ'ibg\zAI6[pt(!iVgT+o o뎅ԲYktcIjh D^A-y>~qS'L>cs~x-PJPJg$2"C_eݱWw죨C4l,AicN2:OLMPDCYa~ëD:l(\:X,DЫ b1%ۿ+[^DQ@4oߠ_jC:5EtiOm%c~׼͘ p,} _7ۀqo_bRQFxEa-hl#I{Mb;+&K Aűg?ElްU"R1 LN&π.ȏEH)qM뒣_PY7Y>7 LqfG~A޶Έקi}kN@kRA4s^-qSgb1{d?-u8/ٟG4a^tn,CuIhV@zJN=<Ҷo;oGLZΌ5}4ĔDu DB*;CT,y8T[*bBuymNܔh {su}Sh=B8Nu%١>g.K"eRIȹ]wm!B9bdr{o>WGd8sAHaL}Ra)?cuJwr2YYF!];+Ɂ]PIպC5ԟ9*dKeB>aUN8.RЄZZXNNMMړ[dYƞGڪ;3n^Zl1vv2B!5%r-!OA:G27U-$t71–Ǟ1̶@a';[%c}%a1/4<7qau$^#2^7K"%K1fz8;,@ 4m]9-]0e%P9c6"$sy,=zaZd<"֝Q~%%TcZ+I;:A]S~I7ޅm/ p{yE[c]E.Z1Jyǰ-ZG~JB )Fmo۷_݉{fOBAhք8.Ł(͵.ORSGw+IaQD'KU(1Vԅ  Kkd^Z8W/+R" 4^-Xu؛ޤ~ÓHo·Ѝ&[wGjC4YdOŽóiں`melжo1&bn?6k[B&,-nt\WiX\D%5y5/;Iz@SǠ%xiZ{\u[Yh5> A?קM(ܔZIئZֶMпJ=W•}" )ֆ{*fm@lF. * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUCLICKDIALOG_H #define UBUNTU_INTERNAL_UBUNTUCLICKDIALOG_H #include #include #include "ubuntuclicktool.h" namespace ProjectExplorer { class Project; class Target; class ProcessParameters; } namespace Ubuntu { namespace Internal { namespace Ui { class UbuntuClickDialog; } class UbuntuClickDialog : public QDialog { Q_OBJECT public: UbuntuClickDialog (QWidget* parent = 0); ~UbuntuClickDialog (); void setParameters (ProjectExplorer::ProcessParameters* params); int lastExitCode () const; public slots: void runClick (); static int runClickModal (ProjectExplorer::ProcessParameters* params); static int createClickChrootModal (); static int maintainClickModal (const UbuntuClickTool::Target &target, const UbuntuClickTool::MaintainMode &mode); // QDialog interface virtual void done(int code); protected: void disableCloseButton (const bool &disabled = true); protected slots: void on_clickFinished(int exitCode); void on_clickReadyReadStandardOutput(const QString txt = QString()); void on_clickReadyReadStandardError(const QString txt = QString()); private: Utils::QtcProcess *m_process; Ui::UbuntuClickDialog *m_ui; int m_exitCode; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUCLICKDIALOG_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucmakebuildconfiguration.h0000644000015301777760000000662512323167147031365 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUCMAKEBUILDCONFIGURATION_H #define UBUNTU_INTERNAL_UBUNTUCMAKEBUILDCONFIGURATION_H #include #include #include #include "ubuntucmakemakestep.h" namespace Utils{ class PathChooser; } namespace CMakeProjectManager{ class ArgumentsLineEdit; } namespace Ubuntu { namespace Internal { class UbuntuCMakeBuildConfiguration : public CMakeProjectManager::CMakeBuildConfiguration { Q_OBJECT public: UbuntuCMakeBuildConfiguration(ProjectExplorer::Target *parent); virtual ProjectExplorer::NamedWidget *createConfigWidget(); protected: UbuntuCMakeBuildConfiguration(ProjectExplorer::Target *parent, UbuntuCMakeBuildConfiguration *source); virtual bool fromMap(const QVariantMap &map); friend class UbuntuCMakeBuildConfigurationFactory; }; class UbuntuCMakeBuildConfigurationFactory : public CMakeProjectManager::CMakeBuildConfigurationFactory { Q_OBJECT public: UbuntuCMakeBuildConfigurationFactory(QObject *parent = 0); ~UbuntuCMakeBuildConfigurationFactory(); // IBuildConfigurationFactory interface virtual int priority(const ProjectExplorer::Target *parent) const; virtual QList availableBuilds(const ProjectExplorer::Target *parent) const; virtual int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const; virtual QList availableSetups(const ProjectExplorer::Kit *k, const QString &projectPath) const; virtual UbuntuCMakeBuildConfiguration *create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const; virtual bool canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const; virtual UbuntuCMakeBuildConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map); virtual bool canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) const; virtual UbuntuCMakeBuildConfiguration*clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product); private: bool canHandle(const ProjectExplorer::Target *t) const; }; class UbuntuCMakeBuildSettingsWidget : public ProjectExplorer::NamedWidget { Q_OBJECT public: UbuntuCMakeBuildSettingsWidget(UbuntuCMakeBuildConfiguration *bc); private slots: void onArgumentsChanged(); void onBuilddirChanged(); private: Utils::PathChooser *m_pathChooser; CMakeProjectManager::ArgumentsLineEdit *m_userArguments; UbuntuCMakeBuildConfiguration *m_buildConfiguration; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUCMAKEBUILDCONFIGURATION_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudeviceconfigurationwidget.cpp0000644000015301777760000001655712323167147032270 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntudeviceconfigurationwidget.h" #include "ui_ubuntudeviceconfigurationwidget.h" namespace Ubuntu { namespace Internal { UbuntuDeviceConfigurationWidget::UbuntuDeviceConfigurationWidget(const ProjectExplorer::IDevice::Ptr &deviceConfig, QWidget *parent) : ProjectExplorer::IDeviceWidget(deviceConfig, parent) , ui(new Ui::UbuntuDeviceConfigurationWidget) { ui->setupUi(this); m_ubuntuDev = qSharedPointerCast(this->device()); connect(m_ubuntuDev->helper(),SIGNAL(featureDetected()),this,SLOT(updateWidgets())); connect(m_ubuntuDev->helper(),SIGNAL(disconnected()),this,SLOT(updateWidgets())); connect(m_ubuntuDev->helper(),SIGNAL(connected()),this,SLOT(updateWidgets())); connect(m_ubuntuDev->helper(),SIGNAL(message(QString)),this,SLOT(on_message(QString))); ui->plainTextEdit->appendHtml(m_ubuntuDev->helper()->log()); updateWidgets(); } UbuntuDeviceConfigurationWidget::~UbuntuDeviceConfigurationWidget() { delete ui; } void UbuntuDeviceConfigurationWidget::updateDeviceFromUi() { //write settings to device } void UbuntuDeviceConfigurationWidget::updateWidgets() { if(m_ubuntuDev->detectionState() != UbuntuDevice::Done) { ui->pushButtonSshInstall->setDisabled(true); ui->pushButtonSshRemove->setVisible(false); ui->pushButtonPortForward->setDisabled(true); ui->pushButtonSshSetupPublicKey->setDisabled(true); ui->pushButtonSshConnect->setDisabled(true); ui->pushButtonPlatformDevelopment->setDisabled(true); ui->pushButtonPlatformDevelopment->setVisible(true); ui->pushButtonPlatformDevelopmentRemove->setDisabled(true); ui->pushButtonPlatformDevelopmentRemove->setVisible(false); ui->pushButton_filesystem_rw_enable->setDisabled(true); ui->pushButton_filesystem_rw_disable->setVisible(false); } else { bool nwAvailable = m_ubuntuDev->hasNetworkConnection() == UbuntuDevice::Available; //Setup SSH relevant buttons bool sshUnknown = m_ubuntuDev->developerModeEnabled() == UbuntuDevice::Unknown; bool sshAvailable = (m_ubuntuDev->developerModeEnabled() == UbuntuDevice::Available); ui->pushButtonSshInstall->setVisible(!sshAvailable); ui->pushButtonSshInstall->setEnabled(!sshAvailable && !sshUnknown && nwAvailable); ui->pushButtonSshRemove->setVisible(sshAvailable && !sshUnknown); ui->pushButtonSshRemove->setEnabled(sshAvailable); ui->pushButtonSshSetupPublicKey->setEnabled(sshAvailable); ui->pushButtonSshConnect->setEnabled(sshAvailable); ui->pushButtonPortForward->setEnabled(sshAvailable); //Writeable Filesystem bool writeableImageAvailable = m_ubuntuDev->hasWriteableImage() == UbuntuDevice::Available; bool writeableImageUnknown = m_ubuntuDev->hasWriteableImage() == UbuntuDevice::Unknown; ui->pushButton_filesystem_rw_enable->setEnabled(!writeableImageAvailable && !writeableImageUnknown); ui->pushButton_filesystem_rw_enable->setVisible(!writeableImageAvailable); ui->pushButton_filesystem_rw_disable->setVisible(writeableImageAvailable); ui->pushButton_filesystem_rw_disable->setEnabled(writeableImageAvailable); //Platform Development bool platformDevAvailable = m_ubuntuDev->hasDeveloperTools() == UbuntuDevice::Available; bool platformDevUnknown = m_ubuntuDev->hasDeveloperTools() == UbuntuDevice::Unknown; ui->pushButtonPlatformDevelopment->setEnabled(!platformDevAvailable && !platformDevUnknown && nwAvailable); ui->pushButtonPlatformDevelopment->setVisible(!platformDevAvailable); ui->pushButtonPlatformDevelopmentRemove->setEnabled(platformDevAvailable); ui->pushButtonPlatformDevelopmentRemove->setVisible(platformDevAvailable); } bool connected = (m_ubuntuDev->deviceState() != ProjectExplorer::IDevice::DeviceDisconnected); ui->pushButtonReboot->setEnabled(connected); ui->pushButtonRebootToBootloader->setEnabled(connected); ui->pushButtonRebootToRecovery->setEnabled(connected); ui->pushButtonShutdown->setEnabled(connected); ui->pushButtonCloneTimeConfig->setEnabled(connected); } void UbuntuDeviceConfigurationWidget::on_message(const QString &message) { ui->plainTextEdit->appendHtml(message); } void UbuntuDeviceConfigurationWidget::on_pushButtonSshInstall_clicked() { ui->pushButtonSshInstall->setEnabled(false); m_ubuntuDev->setDeveloperModeEnabled(true); } void UbuntuDeviceConfigurationWidget::on_pushButtonSshRemove_clicked() { ui->pushButtonSshRemove->setEnabled(false); m_ubuntuDev->setDeveloperModeEnabled(false); } void UbuntuDeviceConfigurationWidget::on_pushButtonCloneTimeConfig_clicked() { ui->pushButtonCloneTimeConfig->setEnabled(false); m_ubuntuDev->cloneTimeConfig(); } void UbuntuDeviceConfigurationWidget::on_pushButtonPortForward_clicked() { ui->pushButtonPortForward->setEnabled(false); m_ubuntuDev->enablePortForward(); } void UbuntuDeviceConfigurationWidget::on_pushButtonSshSetupPublicKey_clicked() { ui->pushButtonSshSetupPublicKey->setEnabled(false); m_ubuntuDev->deployPublicKey(); } void UbuntuDeviceConfigurationWidget::on_pushButtonSshConnect_clicked() { m_ubuntuDev->openTerminal(); } void UbuntuDeviceConfigurationWidget::on_pushButton_filesystem_rw_disable_clicked() { ui->pushButton_filesystem_rw_disable->setEnabled(false); m_ubuntuDev->setWriteableImageEnabled(false); } void UbuntuDeviceConfigurationWidget::on_pushButton_filesystem_rw_enable_clicked() { ui->pushButton_filesystem_rw_enable->setEnabled(false); m_ubuntuDev->setWriteableImageEnabled(true); } void UbuntuDeviceConfigurationWidget::on_pushButtonPlatformDevelopmentRemove_clicked() { ui->pushButtonPlatformDevelopmentRemove->setEnabled(false); m_ubuntuDev->setDeveloperToolsInstalled(false); } void UbuntuDeviceConfigurationWidget::on_pushButtonPlatformDevelopment_clicked() { ui->pushButtonPlatformDevelopment->setEnabled(false); m_ubuntuDev->setDeveloperToolsInstalled(true); } void UbuntuDeviceConfigurationWidget::on_pushButtonReboot_clicked() { ui->pushButtonReboot->setEnabled(false); m_ubuntuDev->reboot(); } void UbuntuDeviceConfigurationWidget::on_pushButtonShutdown_clicked() { ui->pushButtonShutdown->setEnabled(false); m_ubuntuDev->shutdown(); } void UbuntuDeviceConfigurationWidget::on_pushButtonRebootToBootloader_clicked() { ui->pushButtonRebootToBootloader->setEnabled(false); m_ubuntuDev->rebootToBootloader(); } void UbuntuDeviceConfigurationWidget::on_pushButtonRebootToRecovery_clicked() { ui->pushButtonRebootToRecovery->setEnabled(false); m_ubuntuDev->rebootToRecovery(); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprocess.h0000644000015301777760000000414712323167147026150 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROCESS_H #define UBUNTUPROCESS_H #include #include #include #include "ubuntu_global.h" namespace Ubuntu { namespace Internal { class UBUNTUSHARED_EXPORT UbuntuProcess : public QObject { Q_OBJECT public: explicit UbuntuProcess(QObject *parent = 0); void clear() { m_pendingProcesses.clear(); } void append(QStringList cmds) { m_pendingProcesses << cmds; } QProcess::ProcessState state() { return m_currentProcess->state(); } public slots: void stop(); void start(QString taskTitle); signals: void message(QString); void error(QString); void finished(QString,int); void finished(const QProcess*,QString,int); void started(QString); protected slots: void processStarted(); void processReadyRead(); void processFinished(int code); void processError(QProcess::ProcessError error); void processCmdQueue(); protected: void close(); void kill(); QList m_pendingProcesses; QProcess *m_currentProcess; QFutureInterface *m_futureInterface; void initializeProgressBar(QString title, int max); void setProgressBarFinished(); void increaseProgress(QString msg); void setProgressBarCancelled(); void setProgressBarStarted(); bool m_bForceStop; private: Q_DISABLE_COPY(UbuntuProcess) }; } // Internal } // Ubuntu #endif // UBUNTUPROCESS_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectmanager.h0000644000015301777760000000441312323167147027467 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROJECTMANAGER_H #define UBUNTUPROJECTMANAGER_H #include #include "ubuntuconstants.h" #include "ubuntuproject.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuProject; class UbuntuProjectManager : public ProjectExplorer::IProjectManager { Q_OBJECT public: UbuntuProjectManager(); virtual QString mimeType() const; ProjectExplorer::Project* openProject(const QString &filePath, QString *errorString); void registerProject(UbuntuProject *project); void unregisterProject(UbuntuProject *project); protected slots: void onProjectAdded(ProjectExplorer::Project*); private: QList m_projects; }; } // Internal } // Ubuntu #endif // UBUNTUPROJECTMANAGER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucmaketool.cpp0000644000015301777760000000457512323167147027010 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntucmaketool.h" #include "ubuntuconstants.h" #include namespace Ubuntu { namespace Internal { /*! * \brief createId * Adds a suffix to every tool id, so every kit has its * own cmake instance */ static Core::Id createId() { Core::Id newId(Constants::UBUNTU_CLICK_CMAKE_TOOL_ID); return newId.withSuffix(QUuid::createUuid().toString()); } UbuntuCMakeTool::UbuntuCMakeTool(QObject *parent) : CMakeProjectManager::CMakeTool(parent) , m_hasEnvironment(false) { setId(createId()); } UbuntuCMakeTool::UbuntuCMakeTool(const Core::Id &id, QObject *parent) : CMakeProjectManager::CMakeTool(parent) , m_hasEnvironment(false) { setId(id); } QString UbuntuCMakeTool::displayName() { return tr("Ubuntu Chroot CMake"); } void UbuntuCMakeTool::addToEnvironment(Utils::Environment &env) const { Utils::Environment::const_iterator i = m_env.constBegin(); for(;i != m_env.constEnd();i++) env.set(i.key(),i.value()); } bool UbuntuCMakeTool::isValid() const { if(!m_hasEnvironment) return false; return CMakeTool::isValid(); } void UbuntuCMakeTool::setEnvironment(const Utils::Environment &env) { m_hasEnvironment = true; m_env = env; setCMakeExecutable(QString::fromLatin1(Constants::UBUNTU_CLICK_CMAKE_WRAPPER).arg(Constants::UBUNTU_SCRIPTPATH)); } bool UbuntuCMakeToolFactory::canCreate(const Core::Id &id) const { return (id.toString().startsWith(QLatin1String(Constants::UBUNTU_CLICK_CMAKE_TOOL_ID))); } CMakeProjectManager::ICMakeTool *UbuntuCMakeToolFactory::create(const Core::Id &id) { if(!canCreate(id)) return 0; return new UbuntuCMakeTool(id); } } //namespace Internal } //namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudeviceconfigurationwidget.h0000644000015301777760000000441012323167147031716 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUDEVICECONFIGURATIONWIDGET_H #define UBUNTU_INTERNAL_UBUNTUDEVICECONFIGURATIONWIDGET_H #include #include "ubuntudevice.h" namespace Ubuntu { namespace Internal { namespace Ui { class UbuntuDeviceConfigurationWidget; } class UbuntuDeviceConfigurationWidget : public ProjectExplorer::IDeviceWidget { Q_OBJECT public: explicit UbuntuDeviceConfigurationWidget(const ProjectExplorer::IDevice::Ptr &deviceConfig, QWidget *parent = 0); ~UbuntuDeviceConfigurationWidget(); // IDeviceWidget interface virtual void updateDeviceFromUi(); private slots: void updateWidgets(); void on_message (const QString &message); void on_pushButtonSshInstall_clicked(); void on_pushButtonSshRemove_clicked(); void on_pushButtonCloneTimeConfig_clicked(); void on_pushButtonPortForward_clicked(); void on_pushButtonSshSetupPublicKey_clicked(); void on_pushButtonSshConnect_clicked(); void on_pushButton_filesystem_rw_disable_clicked(); void on_pushButton_filesystem_rw_enable_clicked(); void on_pushButtonPlatformDevelopmentRemove_clicked(); void on_pushButtonPlatformDevelopment_clicked(); void on_pushButtonReboot_clicked(); void on_pushButtonShutdown_clicked(); void on_pushButtonRebootToBootloader_clicked(); void on_pushButtonRebootToRecovery_clicked(); private: Ui::UbuntuDeviceConfigurationWidget *ui; UbuntuDevice::Ptr m_ubuntuDev; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUDEVICECONFIGURATIONWIDGET_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/manifest.json.template0000644000015301777760000000051012323167147027357 0ustar pbusernogroup00000000000000{ "name": "com.ubuntu.developer.username.myapp", "description": "description of myapp", "framework": "myFramework", "architecture": "all", "title": "myapp", "hooks": { "myapp": { "apparmor": "myapp.json", "desktop": "myapp.desktop" } }, "version": "0.1" } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupackagingwidget.h0000644000015301777760000000663012323167147027621 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTUPACKAGINGWIDGET_H #define UBUNTUPACKAGINGWIDGET_H #include #include #include #include #include "ubuntubzr.h" #include "ubuntuclickmanifest.h" #include "ubuntuprocess.h" #include namespace Ui { class UbuntuPackagingWidget; } namespace Ubuntu{ namespace Internal{ class UbuntuValidationResultModel; class ClickRunChecksParser; } } using namespace Ubuntu::Internal; class UbuntuPackagingWidget : public QWidget { Q_OBJECT public: explicit UbuntuPackagingWidget(QWidget *parent = 0); ~UbuntuPackagingWidget(); bool reviewToolsInstalled (); UbuntuClickManifest *manifest (); UbuntuClickManifest *appArmor (); public slots: void autoSave(); void reload(); void load_manifest(QString fileName); void load_apparmor(QString fileAppArmorName); void save(bool bSaveSimple = true); bool openManifestForProject(); void setAvailable(bool); void load_excludes(QString excludesFile = QLatin1String("")); void save_excludes(); protected slots: void onMessage(QString msg); void onFinished(QString cmd, int code); void onError(QString msg); void onStarted(QString cmd); void onFinishedAction(const QProcess* proc,QString cmd); void onNewValidationData(); void onValidationItemSelected(const QModelIndex &index ); void on_pushButton_addpolicy_clicked(); void on_pushButtonClickPackage_clicked(); void on_pushButtonReset_clicked(); void on_pushButtonReviewersTools_clicked(); void on_pushButtonReload_clicked(); void on_tabWidget_currentChanged(int); void on_listWidget_customContextMenuRequested(QPoint); void bzrChanged(); void checkClickReviewerTool(); void buildFinished (const bool success); signals: void reviewToolsInstalledChanged(const bool& installed); private slots: void on_comboBoxFramework_currentIndexChanged(int index); private: void clearAdditionalBuildSteps (); private: bool m_reviewToolsInstalled; UbuntuClickManifest m_manifest; UbuntuClickManifest m_apparmor; QMetaObject::Connection m_UbuntuMenu_connection; QProcess m_click; UbuntuBzr m_bzr; QString m_projectName; QString m_projectDir; QString m_reply; QString m_excludesFile; int m_previous_tab; QString m_reviewesToolsLocation; UbuntuProcess m_ubuntuProcess; Ui::UbuntuPackagingWidget *ui; UbuntuValidationResultModel *m_validationModel; ClickRunChecksParser* m_inputParser; //packaging support with buildsteps QList > m_additionalPackagingBuildSteps; QMetaObject::Connection m_buildManagerConnection; }; #endif // UBUNTUPACKAGINGWIDGET_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupolicygroupinfo.cpp0000644000015301777760000000403612323167147030252 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntupolicygroupinfo.h" using namespace Ubuntu::Internal; UbuntuPolicyGroupInfo::UbuntuPolicyGroupInfo(QObject *parent) : QObject(parent), m_bLocal(false) { connect(&m_process,SIGNAL(message(QString)),this,SLOT(onMessage(QString))); connect(&m_process,SIGNAL(finished(QString,int)),this,SLOT(onFinished(QString,int))); connect(&m_process,SIGNAL(error(QString)),this,SLOT(onError(QString))); } void UbuntuPolicyGroupInfo::getInfo(QString policyGroup) { m_policyGroup = policyGroup; QStringList cmd; if (!isLocal()) { cmd << QString(QLatin1String("adb shell aa-easyprof --show-policy-group -p %0 --policy-vendor=ubuntu --policy-version=1.0")).arg(policyGroup); } else { cmd << QString(QLatin1String("aa-easyprof --show-policy-group -p %0 --policy-vendor=ubuntu --policy-version=1.0")).arg(policyGroup); } m_process.append(cmd); m_replies.clear(); m_process.start(QLatin1String("Reading policy group")); } void UbuntuPolicyGroupInfo::onMessage(QString line) { m_replies.append(line); } void UbuntuPolicyGroupInfo::onFinished(QString, int result) { emit infoReady(true); } void UbuntuPolicyGroupInfo::onError(QString) { m_replies.clear(); if (!isLocal()) { m_bLocal = true; getInfo(m_policyGroup); } else { emit infoReady(false); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupackagingmode.h0000644000015301777760000000313612323167147027260 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPACKAGINGMODE_H #define UBUNTUPACKAGINGMODE_H #include #include "ubuntupackagingwidget.h" #include #include namespace Ubuntu { namespace Internal { class UbuntuClickManifest; class UbuntuPackagingMode : public Core::IMode { Q_OBJECT public: explicit UbuntuPackagingMode(QObject *parent = 0); void initialize(); static UbuntuClickManifest *manifest (); static UbuntuClickManifest *appArmor (); protected slots: void modeChanged(Core::IMode*); void on_projectAdded(ProjectExplorer::Project *project); void on_projectRemoved(ProjectExplorer::Project *project); void updateModeState(); protected: QWidget* m_modeWidget; UbuntuPackagingWidget m_ubuntuPackagingWidget; Core::Id previousMode; private: static UbuntuPackagingMode* m_instance; }; } } #endif // UBUNTUPACKAGINGMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectnode.cpp0000644000015301777760000001230712323167147027336 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuprojectnode.h" using namespace Ubuntu::Internal; UbuntuProjectNode::UbuntuProjectNode(UbuntuProject *project, Core::IDocument *projectFile) : ProjectExplorer::ProjectNode(QFileInfo(projectFile->filePath()).absoluteFilePath()), m_project(project), m_projectFile(projectFile) { setDisplayName(QFileInfo(projectFile->filePath()).completeBaseName()); refresh(); } Core::IDocument *UbuntuProjectNode::projectFile() const { return m_projectFile; } QString UbuntuProjectNode::projectFilePath() const { return m_projectFile->filePath(); } void UbuntuProjectNode::refresh() { using namespace ProjectExplorer; removeFileNodes(fileNodes(), this); removeFolderNodes(subFolderNodes(), this); QStringList files = m_project->files(Project::AllFiles); files.removeAll(m_project->filesFileName()); QHash filesInDirectory; foreach (const QString &fileName, files) { QFileInfo fileInfo(fileName); QString absoluteFilePath; QString relativeDirectory; if (fileInfo.isAbsolute()) { absoluteFilePath = fileInfo.filePath(); relativeDirectory = m_project->projectDir().relativeFilePath(fileInfo.path()); } else { absoluteFilePath = m_project->projectDir().absoluteFilePath(fileInfo.filePath()); relativeDirectory = fileInfo.path(); if (relativeDirectory == QLatin1String(".")) relativeDirectory.clear(); } filesInDirectory[relativeDirectory].append(absoluteFilePath); } const QHash::ConstIterator cend = filesInDirectory.constEnd(); for (QHash::ConstIterator it = filesInDirectory.constBegin(); it != cend; ++it) { FolderNode *folder = findOrCreateFolderByName(it.key()); QList fileNodes; foreach (const QString &file, it.value()) { FileType fileType = SourceType; // ### FIXME FileNode *fileNode = new FileNode(file, fileType, false); fileNodes.append(fileNode); } addFileNodes(fileNodes, folder); } m_folderByName.clear(); } ProjectExplorer::FolderNode *UbuntuProjectNode::findOrCreateFolderByName(const QStringList &components, int end) { if (! end) return 0; QString baseDir = QFileInfo(path()).path(); QString folderName; for (int i = 0; i < end; ++i) { folderName.append(components.at(i)); folderName += QLatin1Char('/'); } const QString component = components.at(end - 1); if (component.isEmpty()) return this; else if (FolderNode *folder = m_folderByName.value(folderName)) return folder; FolderNode *folder = new FolderNode(baseDir + QLatin1Char('/') + folderName); folder->setDisplayName(component); m_folderByName.insert(folderName, folder); FolderNode *parent = findOrCreateFolderByName(components, end - 1); if (! parent) parent = this; addFolderNodes(QList() << folder, parent); return folder; } ProjectExplorer::FolderNode *UbuntuProjectNode::findOrCreateFolderByName(const QString &filePath) { QStringList components = filePath.split(QLatin1Char('/')); return findOrCreateFolderByName(components, components.length()); } bool UbuntuProjectNode::hasBuildTargets() const { return true; } QList UbuntuProjectNode::supportedActions(Node *node) const { Q_UNUSED(node); QList actions; actions.append(AddNewFile); actions.append(EraseFile); actions.append(Rename); return actions; } bool UbuntuProjectNode::canAddSubProject(const QString &proFilePath) const { Q_UNUSED(proFilePath) return false; } bool UbuntuProjectNode::addSubProjects(const QStringList &proFilePaths) { Q_UNUSED(proFilePaths) return false; } bool UbuntuProjectNode::removeSubProjects(const QStringList &proFilePaths) { Q_UNUSED(proFilePaths) return false; } bool UbuntuProjectNode::addFiles(const QStringList &, QStringList *) { return false; } bool UbuntuProjectNode::removeFiles(const QStringList &, QStringList *) { return false; } bool UbuntuProjectNode::deleteFiles(const QStringList &) { return true; } bool UbuntuProjectNode::renameFile(const QString &, const QString &) { return true; } QList UbuntuProjectNode::runConfigurationsFor(Node *node) { Q_UNUSED(node) return QList(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuircmode.cpp0000644000015301777760000000220612323167147026441 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuircmode.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; UbuntuIRCMode::UbuntuIRCMode(QObject *parent) : UbuntuWebMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_IRC_DISPLAYNAME)); setId(Ubuntu::Constants::UBUNTU_MODE_IRC); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_IRC)); setUrl(QUrl::fromUserInput(QLatin1String(Ubuntu::Constants::UBUNTU_IRC))); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuwebmode.cpp0000644000015301777760000000521112323167147026440 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuwebmode.h" #include "ubuntuconstants.h" #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; UbuntuWebMode::UbuntuWebMode(QObject *parent) : Core::IMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_WEB_DISPLAYNAME)); setIcon(QIcon(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_WEB_ICON))); setPriority(Ubuntu::Constants::UBUNTU_MODE_WEB_PRIORITY); setId(Ubuntu::Constants::UBUNTU_MODE_WEB); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_WEB)); QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); m_modeWidget.setLayout(layout); connect(&m_webView,SIGNAL(urlChanged(QUrl)),SLOT(updateAddress(QUrl))); connect(&m_addressBar,SIGNAL(returnPressed()),SLOT(goToAddress())); Utils::StyledBar* styledBar = new Utils::StyledBar(&m_modeWidget); //layout->addWidget(styledBar); QScrollArea *scrollArea = new QScrollArea(&m_modeWidget); scrollArea->setFrameShape(QFrame::NoFrame); layout->addWidget(scrollArea); layout->addWidget(&m_addressBar); scrollArea->setWidget(&m_webView); scrollArea->setWidgetResizable(true); connect(Core::ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)), SLOT(modeChanged(Core::IMode*))); m_webView.setFocus(); setWidget(&m_modeWidget); } void UbuntuWebMode::updateAddress(QUrl url) { m_addressBar.setText(url.toString()); } void UbuntuWebMode::goToAddress() { m_webView.setUrl(QUrl::fromUserInput(m_addressBar.text())); } void UbuntuWebMode::initialize() { } void UbuntuWebMode::modeChanged(Core::IMode*) { } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucreatenewchrootdialog.h0000644000015301777760000000255212323167147031044 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUCREATENEWCHROOTDIALOG_H #define UBUNTU_INTERNAL_UBUNTUCREATENEWCHROOTDIALOG_H #include #include #include "ubuntuclicktool.h" namespace Ubuntu { namespace Internal { namespace Ui { class UbuntuCreateNewChrootDialog; } class UbuntuCreateNewChrootDialog : public QDialog { Q_OBJECT public: explicit UbuntuCreateNewChrootDialog(QWidget *parent = 0); ~UbuntuCreateNewChrootDialog(); static bool getNewChrootTarget(UbuntuClickTool::Target *target); private: Ui::UbuntuCreateNewChrootDialog *ui; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUCREATENEWCHROOTDIALOG_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusecuritypolicypickerdialog.cpp0000644000015301777760000000633712323167147032475 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusecuritypolicypickerdialog.h" #include "ui_ubuntusecuritypolicypickerdialog.h" UbuntuSecurityPolicyPickerDialog::UbuntuSecurityPolicyPickerDialog(QWidget *parent) : QDialog(parent), ui(new Ui::UbuntuSecurityPolicyPickerDialog) { ui->setupUi(this); this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint | Qt::Popup); m_model.scanPolicyGroups(); connect(&m_model,SIGNAL(scanComplete(bool)),this,SLOT(onScanComplete(bool))); ui->listViewPolicyGroups->setModel(&m_model); ui->stackedWidget->setCurrentIndex(0); connect(ui->listViewPolicyGroups,SIGNAL(clicked(QModelIndex)),this,SLOT(onPolicyClicked(QModelIndex))); connect(&m_info,SIGNAL(infoReady(bool)),this,SLOT(onInfoChanged(bool))); } UbuntuSecurityPolicyPickerDialog::~UbuntuSecurityPolicyPickerDialog() { delete ui; } void UbuntuSecurityPolicyPickerDialog::onScanComplete(bool ok) { if (ok) { ui->stackedWidget->setCurrentIndex(1); } else { ui->stackedWidget->setCurrentIndex(2); } } QStringList UbuntuSecurityPolicyPickerDialog::selectedPolicyGroups() { QStringList retval; if (ui->stackedWidget->currentIndex()==2) { retval.append(ui->lineEditPolicyGroup->text()); } else { QModelIndexList selected = ui->listViewPolicyGroups->selectionModel()->selectedIndexes(); foreach (QModelIndex idx, selected) { retval.append(m_model.data(idx,Qt::DisplayRole).toString()); } } return retval; } void UbuntuSecurityPolicyPickerDialog::on_pushButtonCancel_clicked() { this->reject(); } void UbuntuSecurityPolicyPickerDialog::on_pushButtonAdd_clicked() { this->accept(); } void UbuntuSecurityPolicyPickerDialog::onPolicyClicked(QModelIndex idx) { m_info.getInfo(m_model.data(idx,Qt::DisplayRole).toString()); } void UbuntuSecurityPolicyPickerDialog::onInfoChanged(bool ok) { if (ok) { QString policyGroupInfo = m_info.info(); policyGroupInfo = policyGroupInfo.replace(QRegExp(QLatin1String("#([^\n]*)")), QLatin1String("#\\1")); policyGroupInfo = policyGroupInfo.replace(QRegExp(QLatin1String("(# Usage: reserved)"),Qt::CaseInsensitive), QLatin1String("\\1")); policyGroupInfo = policyGroupInfo.replace(QRegExp(QLatin1String("\n")), QLatin1String("
")); ui->textBrowserEditInfo->setHtml(policyGroupInfo); ui->textBrowserEditInfo->show(); } else { ui->textBrowserEditInfo->hide(); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntu_global.h0000644000015301777760000000166312323167147026071 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTU_GLOBAL_H #define UBUNTU_GLOBAL_H #include #if defined(UBUNTU_LIBRARY) # define UBUNTUSHARED_EXPORT Q_DECL_EXPORT #else # define UBUNTUSHARED_EXPORT Q_DECL_IMPORT #endif #endif // UBUNTU_GLOBAL_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucmakebuildconfiguration.cpp0000644000015301777760000002426712323167214031715 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntucmakebuildconfiguration.h" #include "ubuntuconstants.h" #include "clicktoolchain.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { /*! * \class UbuntuCMakeBuildConfiguration * Represents the build configuration for a Ubuntu-SDK * CMake Project */ UbuntuCMakeBuildConfiguration::UbuntuCMakeBuildConfiguration(ProjectExplorer::Target *parent) :CMakeBuildConfiguration(parent,Core::Id(Constants::UBUNTU_CLICK_CMAKE_BC_ID)) { } ProjectExplorer::NamedWidget *UbuntuCMakeBuildConfiguration::createConfigWidget() { return new UbuntuCMakeBuildSettingsWidget(this); } UbuntuCMakeBuildConfiguration::UbuntuCMakeBuildConfiguration(ProjectExplorer::Target *parent, UbuntuCMakeBuildConfiguration *source) : CMakeBuildConfiguration(parent,source) { } bool UbuntuCMakeBuildConfiguration::fromMap(const QVariantMap &map) { if(!CMakeBuildConfiguration::fromMap(map)) return false; this->setUseNinja(false); return true; } /*! * \class UbuntuCMakeBuildConfigurationFactory * Factory class to create UbuntuCMakeBuildConfiguration * instances. */ UbuntuCMakeBuildConfigurationFactory::UbuntuCMakeBuildConfigurationFactory(QObject *parent) : CMakeBuildConfigurationFactory(parent) { } UbuntuCMakeBuildConfigurationFactory::~UbuntuCMakeBuildConfigurationFactory() { } int UbuntuCMakeBuildConfigurationFactory::priority(const ProjectExplorer::Target *parent) const { if(canHandle(parent)) return 10; return -1; } QList UbuntuCMakeBuildConfigurationFactory::availableBuilds(const ProjectExplorer::Target *parent) const { if(!canHandle(parent)) QList(); QList infos = CMakeBuildConfigurationFactory::availableBuilds(parent); foreach(ProjectExplorer::BuildInfo* info, infos) info->typeName = tr("Ubuntu SDK Build"); return infos; } int UbuntuCMakeBuildConfigurationFactory::priority(const ProjectExplorer::Kit *k, const QString &projectPath) const { if(!k) return false; ProjectExplorer::ToolChain* tc = ProjectExplorer::ToolChainKitInformation::toolChain(k); if(!tc || tc->type() != QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) return false; return (Core::MimeDatabase::findByFile(QFileInfo(projectPath)).matchesType(QLatin1String(CMakeProjectManager::Constants::CMAKEMIMETYPE))) ? 10 : -1; } QList UbuntuCMakeBuildConfigurationFactory::availableSetups(const ProjectExplorer::Kit *k, const QString &projectPath) const { QList infos = CMakeBuildConfigurationFactory::availableSetups(k,projectPath); foreach(ProjectExplorer::BuildInfo* info, infos) info->typeName = tr("Ubuntu SDK Build"); return infos; } UbuntuCMakeBuildConfiguration *UbuntuCMakeBuildConfigurationFactory::create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const { QTC_ASSERT(info->factory() == this, return 0); QTC_ASSERT(info->kitId == parent->kit()->id(), return 0); QTC_ASSERT(!info->displayName.isEmpty(), return 0); QTC_ASSERT(canHandle(parent),return 0); CMakeProjectManager::CMakeBuildInfo copy(*static_cast(info)); CMakeProjectManager::CMakeProject *project = static_cast(parent->project()); if (copy.buildDirectory.isEmpty()) copy.buildDirectory = Utils::FileName::fromString(project->shadowBuildDirectory(project->projectFilePath(), parent->kit(), copy.displayName)); UbuntuCMakeBuildConfiguration *bc = new UbuntuCMakeBuildConfiguration(parent); bc->setDisplayName(copy.displayName); bc->setDefaultDisplayName(copy.displayName); ProjectExplorer::BuildStepList *buildSteps = bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD); ProjectExplorer::BuildStepList *cleanSteps = bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_CLEAN); UbuntuCMakeMakeStep *makeStep = new UbuntuCMakeMakeStep(buildSteps); buildSteps->insertStep(0, makeStep); UbuntuCMakeMakeStep *cleanMakeStep = new UbuntuCMakeMakeStep(cleanSteps); cleanSteps->insertStep(0, cleanMakeStep); cleanMakeStep->setAdditionalArguments(QLatin1String("clean")); cleanMakeStep->setClean(true); bc->setBuildDirectory(Utils::FileName::fromString(copy.buildDirectory.toString())); bc->setUseNinja(false); // Default to all if (project->hasBuildTarget(QLatin1String("all"))) makeStep->setBuildTarget(QLatin1String("all"), true); return bc; } bool UbuntuCMakeBuildConfigurationFactory::canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const { if (!canHandle(parent)) return false; return ProjectExplorer::idFromMap(map) == Constants::UBUNTU_CLICK_CMAKE_BC_ID; } UbuntuCMakeBuildConfiguration *UbuntuCMakeBuildConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map) { if (!canRestore(parent, map)) return 0; UbuntuCMakeBuildConfiguration *bc = new UbuntuCMakeBuildConfiguration(parent); if (bc->fromMap(map)) return bc; delete bc; return 0; } bool UbuntuCMakeBuildConfigurationFactory::canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) const { if (!canHandle(parent)) return false; return product->id() == Constants::UBUNTU_CLICK_CMAKE_BC_ID; } UbuntuCMakeBuildConfiguration *UbuntuCMakeBuildConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) { if (!canClone(parent, product)) return 0; UbuntuCMakeBuildConfiguration *old = static_cast(product); return new UbuntuCMakeBuildConfiguration(parent, old); } /*! * \brief UbuntuCMakeBuildConfigurationFactory::canHandle * checks if we can create buildconfigurations for the given target */ bool UbuntuCMakeBuildConfigurationFactory::canHandle(const ProjectExplorer::Target *t) const { QTC_ASSERT(t, return false); if (!t->project()->supportsKit(t->kit())) return false; ProjectExplorer::ToolChain* tc = ProjectExplorer::ToolChainKitInformation::toolChain(t->kit()); if(!tc || tc->type() != QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) return false; return t->project()->id() == Core::Id(CMakeProjectManager::Constants::CMAKEPROJECT_ID); } UbuntuCMakeBuildSettingsWidget::UbuntuCMakeBuildSettingsWidget(UbuntuCMakeBuildConfiguration *bc) : m_buildConfiguration(bc) { QFormLayout *fl = new QFormLayout(this); fl->setContentsMargins(20, -1, 0, -1); fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); setLayout(fl); bool inSource = CMakeProjectManager::CMakeProject::hasInSourceBuild(bc->target()->project()->projectDirectory()); if(inSource) { QLabel* inSourceLabel = new QLabel(this); inSourceLabel->setWordWrap(true); inSourceLabel->setText(tr("Qt Creator has detected an in-source-build in %1 " "which prevents shadow builds. Qt Creator will not allow you to change the build directory. " "If you want a shadow build, clean your source directory and re-open the project.") .arg(bc->target()->project()->projectDirectory())); fl->addRow(inSourceLabel); } if(!inSource) { m_pathChooser = new Utils::PathChooser(this); m_pathChooser->setPath(m_buildConfiguration->rawBuildDirectory().toString()); fl->addRow(tr("Build directory:"), m_pathChooser); connect(m_pathChooser->lineEdit(),SIGNAL(editingFinished()),this,SLOT(onBuilddirChanged())); } m_userArguments = new CMakeProjectManager::ArgumentsLineEdit(this); fl->addRow(tr("CMake arguments:"),m_userArguments); m_userArguments->setText(Utils::QtcProcess::joinArgs(m_buildConfiguration->arguments())); //m_userArguments->setHistoryCompleter(QLatin1String("CMakeArgumentsLineEdit")); connect(m_userArguments,SIGNAL(editingFinished()),this,SLOT(onArgumentsChanged())); setDisplayName(tr("Ubuntu SDK CMake")); } void UbuntuCMakeBuildSettingsWidget::onArgumentsChanged() { if(!m_userArguments->isValid()) return; QStringList args = Utils::QtcProcess::splitArgs(m_userArguments->text()); if(m_buildConfiguration->arguments() != args) m_buildConfiguration->setArguments(args); } void UbuntuCMakeBuildSettingsWidget::onBuilddirChanged() { qDebug()<<"Changing builddir to: "<fileName().toString(); m_buildConfiguration->setBuildDirectory(m_pathChooser->fileName()); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevice.cpp0000644000015301777760000010752012323167214026256 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntudevice.h" #include "ubuntudevicenotifier.h" #include "ubuntuemulatornotifier.h" #include "ubuntuprocess.h" #include "ubuntuconstants.h" #include "ubuntudeviceconfigurationwidget.h" #include "localportsmanager.h" #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { const QLatin1String DEVICE_INFO_KEY("UbuntuDevice.InfoString"); /*! * \class UbuntuDeviceHelper * Helper class that collects informations about the * device, and can be used to monitor connect/disconnect * and other device events */ UbuntuDeviceHelper::UbuntuDeviceHelper(UbuntuDevice *dev) : QObject(0) , m_clonedNwCount(0) , m_dev(dev) , m_process(0) , m_deviceWatcher(0) { #if 0 connect(m_process,SIGNAL(finished(QString,int)),this,SLOT(processFinished(QString,int))); connect(m_process,SIGNAL(message(QString)),this,SLOT(onMessage(QString))); connect(m_process,SIGNAL(error(QString)),this,SLOT(onError(QString))); #endif resetToDefaults(); } UbuntuDeviceHelper::~UbuntuDeviceHelper() { if(m_deviceWatcher) m_deviceWatcher->stopMonitoring(); if(m_process) stopProcess(); } UbuntuDevice *UbuntuDeviceHelper::device() const { return m_dev; } QString UbuntuDeviceHelper::log() const { return m_log; } void UbuntuDeviceHelper::refresh() { deviceDisconnected(); if(m_deviceWatcher && m_deviceWatcher->isConnected()) { deviceConnected(); } } void UbuntuDeviceHelper::init() { if(!m_dev->serialNumber().isEmpty()) { if(!m_deviceWatcher) { if(m_dev->serialNumber().startsWith(QLatin1String("emulator"))) m_deviceWatcher = new UbuntuEmulatorNotifier(this); else m_deviceWatcher = new UbuntuDeviceNotifier(this); m_deviceWatcher->stopMonitoring(); m_deviceWatcher->startMonitoring(m_dev->id().toSetting().toString()); connect(m_deviceWatcher,SIGNAL(deviceConnected()),this,SLOT(deviceConnected())); connect(m_deviceWatcher,SIGNAL(deviceDisconnected()),this,SLOT(deviceDisconnected())); } } if(m_deviceWatcher && m_deviceWatcher->isConnected()) { deviceConnected(); } } void UbuntuDeviceHelper::processFinished(const QString &, const int code) { Q_UNUSED(code) switch(m_dev->m_processState) { case UbuntuDevice::DetectDeviceVersion:{ //seems to do just nothing, devicewidget did not check return code //emit a message here detectHasNetworkConnection(); break; } case UbuntuDevice::DetectNetworkConnection:{ if (m_reply.trimmed() == QString::fromLatin1(Constants::ONE_STR)) { // we have network m_clonedNwCount = 0; if(m_dev->m_hasNetworkConnection != UbuntuDevice::Available) { m_dev->m_hasNetworkConnection = UbuntuDevice::Available; emit featureDetected(); } detectOpenSsh(); } else { // not set if (m_clonedNwCount == 0) cloneNetwork(); else { //we tried to enable network and failed if(m_dev->m_hasNetworkConnection != UbuntuDevice::NotAvailable) { m_dev->m_hasNetworkConnection = UbuntuDevice::NotAvailable; emit featureDetected(); emit deviceNeedsSetup(); } //detect other features detectOpenSsh(); } } break; } case UbuntuDevice::CloneNetwork:{ endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_NETWORK_CONF_COPIED)); detectHasNetworkConnection(); break; } case UbuntuDevice::DetectOpenSSH:{ if (m_reply.trimmed() != QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_NONE) && m_reply.trimmed() != QLatin1String(Constants::EMPTY)) { if(m_dev->m_hasOpenSSHServer != UbuntuDevice::Available) { m_dev->m_hasOpenSSHServer = UbuntuDevice::Available; emit featureDetected(); } ProjectExplorer::DeviceManager::instance()->setDeviceState(m_dev->id(),ProjectExplorer::IDevice::DeviceConnected); endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SSH_IS_INSTALLED).arg(m_reply.trimmed())); startSshService(); } else { //device is only connected but not ready for use ProjectExplorer::DeviceManager::instance()->setDeviceState(m_dev->id(),ProjectExplorer::IDevice::DeviceConnected); if(m_dev->m_hasOpenSSHServer != UbuntuDevice::NotAvailable) { m_dev->m_hasOpenSSHServer = UbuntuDevice::NotAvailable; emit featureDetected(); emit deviceNeedsSetup(); } endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SSH_NOT_INSTALLED)); //detect other options detectDeviceWritableImage(); } break; } case UbuntuDevice::InstallOpenSSH:{ endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SSH_WAS_INSTALLED)); detectOpenSsh(); break; } case UbuntuDevice::RemoveOpenSSH:{ endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SSH_WAS_REMOVED)); detectOpenSsh(); break; } case UbuntuDevice::StartOpenSSH:{ if(m_dev->m_openSSHStarted != UbuntuDevice::Available) { m_dev->m_openSSHStarted = UbuntuDevice::Available; emit featureDetected(); } endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SSH_WAS_STARTED)); enablePortForward(); break; } case UbuntuDevice::EnablePortForwarding:{ endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_PORTS_FORWARDED)); deployPublicKey(); break; } case UbuntuDevice::DeployPublicKey:{ //ready to use ProjectExplorer::DeviceManager::instance()->setDeviceState(m_dev->id(),ProjectExplorer::IDevice::DeviceReadyToUse); endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_PUBLICKEY_AUTH_SET)); detectDeviceWritableImage(); break; } case UbuntuDevice::DetectDeviceWriteableImage:{ if (m_reply.trimmed() == QLatin1String(Constants::ZERO_STR)) { m_dev->m_hasWriteableImage = UbuntuDevice::Available; endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLEIMAGE)); } else { m_dev->m_hasWriteableImage = UbuntuDevice::NotAvailable; endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_READONLYIMAGE)); } emit featureDetected(); detectDeveloperTools(); break; } case UbuntuDevice::DetectDeveloperTools:{ setProcessState(UbuntuDevice::Done); stopProcess(); if (m_reply.trimmed() == QLatin1String(Constants::ZERO_STR)) { m_dev->m_hasDeveloperTools = UbuntuDevice::NotAvailable; endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_NOT_INSTALLED)); } else { m_dev->m_hasDeveloperTools = UbuntuDevice::Available; endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_INSTALLED)); } emit featureDetected(); break; } case UbuntuDevice::CloneTimeConfig: endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_TIME_CONF_COPIED)); setProcessState(UbuntuDevice::Done); break; case UbuntuDevice::EnableRWImage: endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLE_ENABLED)); detectDeviceWritableImage(); break; case UbuntuDevice::DisableRWImage: endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLE_DISABLED)); detectDeviceWritableImage(); break; case UbuntuDevice::InstallDevTools: endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_WAS_INSTALLED)); detectDeveloperTools(); break; case UbuntuDevice::RemoveDevTools: endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_REMOVED)); detectDeveloperTools(); break; default:{ break; } } m_reply.clear(); } void UbuntuDeviceHelper::onMessage(const QString &msg) { m_reply.append(msg); QString message = msg; message.replace(QChar::fromLatin1('\n'),QLatin1String("
")); addToLog(message); } void UbuntuDeviceHelper::onError(const QString &error) { qDebug()<<"Received error "<id().toSetting().toString())); } void UbuntuDeviceHelper::startSshService() { setProcessState(UbuntuDevice::StartOpenSSH); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_STARTSSHSERVICE)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_STARTSSHSERVICE_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::enableDeveloperMode() { setProcessState(UbuntuDevice::InstallOpenSSH); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SSH_INSTALL)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SSH_INSTALL_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::disableDeveloperMode() { setProcessState(UbuntuDevice::RemoveOpenSSH); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SSH_REMOVE)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SSH_REMOVE_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::detectHasNetworkConnection() { //@TODO use adb shell nmcli -t -f DEVICE,TYPE,STATE dev status // adb shell nmcli dev list iface | grep IP4.ADDRESS // to find out the devices ip address setProcessState(UbuntuDevice::DetectNetworkConnection); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_HASNETWORK)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_HASNETWORK_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::detectDeviceVersion() { setProcessState(UbuntuDevice::DetectDeviceVersion); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVICEVERSION)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVICEVERSION_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::detectDeviceWritableImage() { setProcessState(UbuntuDevice::DetectDeviceWriteableImage); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTWRITABLEIMAGE)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTWRITABLEIMAGE_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::detectDeveloperTools() { setProcessState(UbuntuDevice::DetectDeveloperTools); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVELOPERTOOLS)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVELOPERTOOLS_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::deviceConnected() { qDebug()<<"Device "<id().toString()<<" connected"; ProjectExplorer::DeviceManager::instance()->setDeviceState(m_dev->id(),ProjectExplorer::IDevice::DeviceConnected); detect(); } void UbuntuDeviceHelper::deviceDisconnected() { qDebug()<<"Device "<id().toString()<<" disconnected"; ProjectExplorer::DeviceManager::instance()->setDeviceState(m_dev->id(),ProjectExplorer::IDevice::DeviceDisconnected); setProcessState(UbuntuDevice::NotStarted); stopProcess(); resetToDefaults(); emit disconnected(); } void UbuntuDeviceHelper::readProcessOutput(QProcess *proc) { QString stderr = QString::fromLocal8Bit(proc->readAllStandardError()); QString stdout = QString::fromLocal8Bit(proc->readAllStandardOutput()); QString msg; if (!stderr.isEmpty()) { msg.append(stderr); } if (!stdout.isEmpty()) { msg.append(stdout); } if(!msg.isEmpty()) onMessage(msg); } void UbuntuDeviceHelper::stopProcess() { if(m_process) { m_process->disconnect(this); if(m_process->state() != QProcess::NotRunning) { m_process->kill(); m_process->waitForFinished(); } m_process->deleteLater(); m_process = 0; } } void UbuntuDeviceHelper::addToLog(const QString &msg) { m_log.append(msg); emit message(msg); } void UbuntuDeviceHelper::setProcessState(const int newState) { Q_ASSERT_X(newState >= UbuntuDevice::NotStarted && newState <= UbuntuDevice::Done, Q_FUNC_INFO, "State variable out of bounds"); if( newState == m_dev->m_processState) return; if(m_dev->m_processState == UbuntuDevice::NotStarted || m_dev->m_processState == UbuntuDevice::Done) emit beginQueryDevice(); else if((newState == UbuntuDevice::Done || newState == UbuntuDevice::NotStarted)) emit endQueryDevice(); m_dev->m_processState = static_cast(newState); emit detectionStateChanged(); } void UbuntuDeviceHelper::resetToDefaults() { m_clonedNwCount = 0; m_reply.clear(); m_dev->m_openSSHStarted = UbuntuDevice::Unknown; m_dev->m_hasOpenSSHServer = UbuntuDevice::Unknown; m_dev->m_hasNetworkConnection = UbuntuDevice::Unknown; m_dev->m_hasWriteableImage = UbuntuDevice::Unknown; m_dev->m_hasDeveloperTools = UbuntuDevice::Unknown; setProcessState(UbuntuDevice::NotStarted); emit featureDetected(); } void UbuntuDeviceHelper::cloneTimeConfig() { if(m_dev->m_processState < UbuntuDevice::FirstNonCriticalTask && m_dev->m_processState != UbuntuDevice::NotStarted) return; setProcessState(UbuntuDevice::CloneTimeConfig); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONETIME)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONETIME_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::enableRWImage() { if(m_dev->m_processState < UbuntuDevice::FirstNonCriticalTask && m_dev->m_processState != UbuntuDevice::NotStarted) return; setProcessState(UbuntuDevice::EnableRWImage); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_MAKEFSWRITABLE)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_MAKEFSWRITABLE_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::disableRWImage() { if(m_dev->m_processState < UbuntuDevice::FirstNonCriticalTask && m_dev->m_processState != UbuntuDevice::NotStarted) return; setProcessState(UbuntuDevice::DisableRWImage); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_MAKEFSREADONLY)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_MAKEFSREADONLY_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } /*! * \brief UbuntuDeviceHelper::enablePortForward * Sets up the port forwarding for the device, this is executed * synchronously and will block the eventloop to make sure we only * use the same port once */ void UbuntuDeviceHelper::enablePortForward() { setProcessState(UbuntuDevice::EnablePortForwarding); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_PORTFORWARD)); stopProcess(); if(!m_dev->m_localForwardedPorts.hasMore()) { m_dev->m_localForwardedPorts = UbuntuLocalPortsManager::getFreeRange(m_dev->id().toSetting().toString(),20); if(!m_dev->m_localForwardedPorts.hasMore()) { //Oh noes , no ports available endAction(tr("No ports available on the host, please detach some devices")); setProcessState(UbuntuDevice::Done); return; } } Utils::PortList copy = m_dev->m_localForwardedPorts; //first port is SSH port QSsh::SshConnectionParameters connParms = m_dev->sshParameters(); connParms.port = copy.getNext(); m_dev->setSshParameters(connParms); m_dev->setFreePorts(copy); QStringList ports; while(copy.hasMore()) ports.append(QString::number(copy.getNext())); //@TODO per device settings QSettings settings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); settings.beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICE_CONNECTIVITY)); QString deviceSshPort = QString::number(connParms.port); QStringList args = QStringList() << m_dev->id().toSetting().toString() <m_processState < UbuntuDevice::FirstNonCriticalTask && m_dev->m_processState != UbuntuDevice::NotStarted) return; setProcessState(UbuntuDevice::InstallDevTools); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ENABLEPLATFORMDEVELOPMENT)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ENABLEPLATFORMDEVELOPMENT_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::removeDevTools() { if(m_dev->m_processState < UbuntuDevice::FirstNonCriticalTask && m_dev->m_processState != UbuntuDevice::NotStarted) return; setProcessState(UbuntuDevice::RemoveDevTools); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DISABLEPLATFORMDEVELOPMENT)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DISABLEPLATFORMDEVELOPMENT_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::deployPublicKey() { setProcessState(UbuntuDevice::DeployPublicKey); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SETUP_PUBKEY_AUTH)); QSettings settings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); settings.beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICE_CONNECTIVITY)); QString deviceUsername = settings.value(QLatin1String(Constants::SETTINGS_KEY_USERNAME),QLatin1String(Constants::SETTINGS_DEFAULT_DEVICE_USERNAME)).toString(); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SETUP_PUBKEY_AUTH_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString()) .arg(deviceUsername)); } void UbuntuDeviceHelper::cloneNetwork() { m_clonedNwCount++; setProcessState(UbuntuDevice::CloneNetwork); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONENETWORK)); stopProcess(); startProcess(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONENETWORK_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(m_dev->id().toSetting().toString())); } void UbuntuDeviceHelper::startProcess(const QString &command) { if(!m_process) { m_process = new QProcess(this); connect(m_process,SIGNAL(readyRead()),this,SLOT(onProcessReadyRead())); connect(m_process,SIGNAL(finished(int)),this,SLOT(onProcessFinished(int))); connect(m_process,SIGNAL(error(QProcess::ProcessError)),this,SLOT(onProcessError(QProcess::ProcessError))); } m_process->setWorkingDirectory(QCoreApplication::applicationDirPath()); m_process->start(command); } void UbuntuDeviceHelper::onProcessReadyRead() { readProcessOutput(m_process); } void UbuntuDeviceHelper::onProcessFinished(const int code) { if (code != 0) { onError(QString::fromLocal8Bit(m_process->readAll())); processFinished(m_process->program(), code); return; } QString errorMsg = QString::fromLocal8Bit(m_process->readAllStandardError()); if (errorMsg.trimmed().length()>0) onError(errorMsg); QString msg = QString::fromLocal8Bit(m_process->readAllStandardOutput()); if (msg.trimmed().length()>0) onMessage(msg); processFinished(QString(),code); } void UbuntuDeviceHelper::onProcessError(const QProcess::ProcessError error) { //if (m_process->exitCode() == 0) { return; } onError(QString(QLatin1String("ERROR: (%0) %1 %2")).arg(m_process->program()).arg(m_process->errorString()).arg(error)); } void UbuntuDeviceHelper::beginAction(QString msg) { addToLog(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ACTION_BEGIN).arg(msg)); } void UbuntuDeviceHelper::endAction(QString msg) { addToLog(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ACTION_END).arg(msg)); } UbuntuDevice::UbuntuDevice() : LinuxDevice() , m_helper(new UbuntuDeviceHelper(this)) , m_processState(NotStarted) { setDeviceState(ProjectExplorer::IDevice::DeviceStateUnknown); loadDefaultConfig(); } UbuntuDevice::UbuntuDevice(const QString &name, ProjectExplorer::IDevice::MachineType machineType, ProjectExplorer::IDevice::Origin origin, Core::Id id) : LinuxDevice(name,Core::Id(Constants::UBUNTU_DEVICE_TYPE_ID),machineType,origin,id) , m_helper(new UbuntuDeviceHelper(this)) , m_processState(NotStarted) { setDeviceState(ProjectExplorer::IDevice::DeviceStateUnknown); loadDefaultConfig(); setupPrivateKey(); m_helper->init(); } UbuntuDevice::UbuntuDevice(const UbuntuDevice &other) : LinuxDevice(other) , m_helper(new UbuntuDeviceHelper(this)) , m_processState(NotStarted) , m_deviceInfoString(other.deviceInfoString()) { setDeviceState(ProjectExplorer::IDevice::DeviceDisconnected); setupPrivateKey(); m_helper->init(); } /*! * \brief UbuntuDevice::loadDefaultConfig * loads the default ssh connect and generic parameters from settings * * \note call this before fromMap() so every device can have its own settings */ void UbuntuDevice::loadDefaultConfig() { QSettings settings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); settings.beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICE_CONNECTIVITY)); QString ip = settings.value(QLatin1String(Constants::SETTINGS_KEY_IP),QLatin1String(Constants::SETTINGS_DEFAULT_DEVICE_IP)).toString(); QString username = settings.value(QLatin1String(Constants::SETTINGS_KEY_USERNAME),QLatin1String(Constants::SETTINGS_DEFAULT_DEVICE_USERNAME)).toString(); //even though this is set here, it will be changed dynamically when the device is connected QString deviceSshPort = QString::number(Constants::SETTINGS_DEFAULT_DEVICE_SSH_PORT); QSsh::SshConnectionParameters params; params.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePublicKey; params.host = ip; params.port = deviceSshPort.toUInt(); params.userName = username; params.timeout = 20; setSshParameters(params); } void UbuntuDevice::setupPrivateKey() { if(!id().isValid()) return; QSsh::SshConnectionParameters params = this->sshParameters(); params.privateKeyFile = QString::fromLatin1(Constants::UBUNTU_DEVICE_SSHIDENTITY).arg(QDir::homePath()).arg(id().toSetting().toString()); setSshParameters(params); } UbuntuDevice::~UbuntuDevice() { delete m_helper; } UbuntuDevice::Ptr UbuntuDevice::create() { return Ptr(new UbuntuDevice()); } QString UbuntuDevice::serialNumber() const { return id().toSetting().toString(); } UbuntuDeviceHelper *UbuntuDevice::helper() const { return m_helper; } /*! * \brief UbuntuDevice::openTerminal * Opens a detached terminal, logged into the device */ void UbuntuDevice::openTerminal() { QProcess p; QStringList args = QStringList() << id().toSetting().toString() << QString::number(sshParameters().port) << sshParameters().userName << sshParameters().host; p.startDetached(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SSHCONNECT_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) , args , QCoreApplication::applicationDirPath()); } void UbuntuDevice::cloneTimeConfig() { m_helper->cloneTimeConfig(); } void UbuntuDevice::enablePortForward() { m_helper->enablePortForward(); } void UbuntuDevice::shutdown() { QProcess p; QStringList args = QStringList() << id().toSetting().toString(); //no need to redetect this should happen automagically p.startDetached(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_SHUTDOWN_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) , args , QCoreApplication::applicationDirPath()); } void UbuntuDevice::reboot() { QProcess p; QStringList args = QStringList() << id().toSetting().toString(); //no need to redetect this should happen automagically bool started = p.startDetached(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_REBOOT_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) , args , QCoreApplication::applicationDirPath()); if(!started) { qDebug()<<"Could not start process " <deployPublicKey(); } void UbuntuDevice::setDeveloperModeEnabled(const bool enabled) { if(m_processState != Done) return; if(enabled && m_hasOpenSSHServer == NotAvailable) m_helper->enableDeveloperMode(); else if(!enabled && m_hasOpenSSHServer == Available) m_helper->disableDeveloperMode(); } UbuntuDevice::FeatureState UbuntuDevice::developerModeEnabled() const { return m_hasOpenSSHServer; } void UbuntuDevice::setWriteableImageEnabled(const bool enabled) { if(m_hasWriteableImage == Unknown) return; if(enabled && m_hasWriteableImage != Available) m_helper->enableRWImage(); else if(!enabled && m_hasWriteableImage != NotAvailable) m_helper->disableRWImage(); } void UbuntuDevice::setDeveloperToolsInstalled(const bool installed) { if(installed && m_hasDeveloperTools != Available) m_helper->installDevTools(); else if(!installed && m_hasDeveloperTools != NotAvailable) m_helper->removeDevTools(); } void UbuntuDevice::setDeviceInfoString(const QString &info) { m_deviceInfoString = info; } QString UbuntuDevice::deviceInfoString() const { return m_deviceInfoString; } UbuntuDevice::FeatureState UbuntuDevice::hasNetworkConnection() const { return m_hasNetworkConnection; } UbuntuDevice::FeatureState UbuntuDevice::hasWriteableImage() const { return m_hasWriteableImage; } UbuntuDevice::FeatureState UbuntuDevice::hasDeveloperTools() const { return m_hasDeveloperTools; } UbuntuDevice::ProcessState UbuntuDevice::detectionState() const { return m_processState; } QString UbuntuDevice::detectionStateString( ) const { switch (m_processState) { case NotStarted: return tr(""); case DetectDeviceVersion: return tr("Detecting device version"); case DetectNetworkConnection: return tr("Detecting network connection"); case CloneNetwork: return tr("Cloning network configuration"); case DetectOpenSSH: return tr("Detecting OpenSSH"); case InstallOpenSSH: return tr("Installing OpenSSH"); case RemoveOpenSSH: return tr("Removing OpenSSH"); case StartOpenSSH: return tr("Starting OpenSSH"); case EnablePortForwarding: return tr("Enable portforwarding"); case DeployPublicKey: return tr("Deploying public key to device"); case DetectDeviceWriteableImage: return tr("Detecting if image is writeable"); case DetectDeveloperTools: return tr("Detecting if developer tools are installed"); case FirstNonCriticalTask: return tr(""); case CloneTimeConfig: return tr("Cloning time configuration"); case EnableRWImage: return tr("Enabling writeable image"); case DisableRWImage: return tr("Disabling writeable image"); case InstallDevTools: return tr("Installing development tools"); case RemoveDevTools: return tr("Removing development tools"); case Done: return tr("Finished"); } return QString(); } ProjectExplorer::IDeviceWidget *UbuntuDevice::createWidget() { return new UbuntuDeviceConfigurationWidget(sharedFromThis()); } QList UbuntuDevice::actionIds() const { return QList(); } QString UbuntuDevice::displayType() const { return tr("Ubuntu Device"); } ProjectExplorer::IDevice::Ptr UbuntuDevice::clone() const { return UbuntuDevice::Ptr(new UbuntuDevice(*this)); } void UbuntuDevice::fromMap(const QVariantMap &map) { LinuxDevice::fromMap(map); if(map.contains(DEVICE_INFO_KEY)) m_deviceInfoString = map[DEVICE_INFO_KEY].toString(); setupPrivateKey(); m_helper->init(); } QVariantMap UbuntuDevice::toMap() const { QVariantMap map = LinuxDevice::toMap(); map.insert(DEVICE_INFO_KEY,m_deviceInfoString); return map; } ProjectExplorer::DeviceProcess *UbuntuDevice::createProcess(QObject *parent) const { return new UbuntuDeviceProcess(sharedFromThis(), parent); } UbuntuDevice::Ptr UbuntuDevice::sharedFromThis() { return qSharedPointerCast(LinuxDevice::sharedFromThis()); } UbuntuDevice::ConstPtr UbuntuDevice::sharedFromThis() const { return qSharedPointerCast(LinuxDevice::sharedFromThis()); } UbuntuDevice::Ptr UbuntuDevice::create(const QString &name, const QString& serial, ProjectExplorer::IDevice::MachineType machineType, ProjectExplorer::IDevice::Origin origin) { return Ptr(new UbuntuDevice(name,machineType,origin,Core::Id::fromSetting(serial))); } ////////////// /// UbuntuDeviceProcess ///////////// static QString quote(const QString &s) { return Utils::QtcProcess::quoteArgUnix(s); } UbuntuDeviceProcess::UbuntuDeviceProcess(const QSharedPointer &device, QObject *parent) : RemoteLinux::LinuxDeviceProcess(device,parent) { } void UbuntuDeviceProcess::setWorkingDirectory(const QString &directory) { m_workingDir = directory; } void UbuntuDeviceProcess::terminate() { LinuxDeviceProcess::terminate(); } QString UbuntuDeviceProcess::fullCommandLine() const { QStringList rcFiles = QStringList() << QLatin1String("/etc/profile") << QLatin1String("$HOME/.profile") << QLatin1String("$HOME/.bashrc"); QStringList confFiles = QStringList()<. * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROJECTAPPLICATIONWIZARD_H #define UBUNTUPROJECTAPPLICATIONWIZARD_H #include #include #include #include #include #include #include #include "ubuntuprojectapp.h" namespace Ubuntu { namespace Internal { class UbuntuProjectApplicationWizardDialog : public ProjectExplorer::BaseProjectWizardDialog { Q_OBJECT public: explicit UbuntuProjectApplicationWizardDialog(QWidget *parent, const Core::WizardDialogParameters ¶meters); int addTargetSetupPage(int id = -1); bool writeUserFile(const QString &cmakeFileName) const; private slots: void on_projectParametersChanged(const QString &projectName, const QString &path); private: ProjectExplorer::TargetSetupPage *m_targetSetupPage; }; class UbuntuProjectApplicationWizard : public Core::BaseFileWizard { Q_OBJECT public: UbuntuProjectApplicationWizard(QJsonObject); virtual ~UbuntuProjectApplicationWizard(); virtual Core::FeatureSet requiredFeatures() const; static QByteArray getProjectTypesJSON(); static QString templatesPath(QString fileName); protected: virtual QWizard *createWizardDialog(QWidget *parent, const Core::WizardDialogParameters &wizardDialogParameters) const; virtual Core::GeneratedFiles generateFiles(const QWizard *w, QString *errorMessage) const; virtual bool postGenerateFiles(const QWizard *w, const Core::GeneratedFiles &l, QString *errorMessage); private: UbuntuProjectApp* m_app; QString m_projectType; }; } // Internal } // Ubuntu #endif // UBUNTUPROJECTAPPLICATIONWIZARD_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntulocaldeployconfiguration.cpp0000644000015301777760000001116112323167147032116 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntulocaldeployconfiguration.h" #include "ubuntuprojectguesser.h" #include "ubuntuconstants.h" #include "ubuntucmakemakestep.h" #include #include #include #include #include #include namespace Ubuntu { namespace Internal { /*! * \class UbuntuLocalDeployConfigurationFactory * Creates the required deploy configuration for locally * run click apps. Click apps need a extra step to group * all components into one directory and make them easily executable * * \note NOT IN USE CURRENTLY */ UbuntuLocalDeployConfigurationFactory::UbuntuLocalDeployConfigurationFactory(QObject *parent) :DeployConfigurationFactory(parent) { } QList UbuntuLocalDeployConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const { QList ids; if (!parent->project()->supportsKit(parent->kit())) return ids; if(ProjectExplorer::DeviceKitInformation::deviceId(parent->kit()) != ProjectExplorer::Constants::DESKTOP_DEVICE_ID) return ids; if(UbuntuProjectGuesser::isClickAppProject(parent->project())) ids << Core::Id(Constants::UBUNTU_LOCAL_DEPLOYCONFIGURATION_ID); return ids; } QString UbuntuLocalDeployConfigurationFactory::displayNameForId(const Core::Id id) const { if( Core::Id(Constants::UBUNTU_LOCAL_DEPLOYCONFIGURATION_ID) == id ) return tr("Ubuntu SDK Local Deployment"); return QString(); } bool UbuntuLocalDeployConfigurationFactory::canCreate(ProjectExplorer::Target *parent, const Core::Id id) const { return availableCreationIds(parent).contains(id); } ProjectExplorer::DeployConfiguration *UbuntuLocalDeployConfigurationFactory::create(ProjectExplorer::Target *parent, const Core::Id id) { if(!canCreate(parent,id)) return false; UbuntuLocalDeployConfiguration* conf = new UbuntuLocalDeployConfiguration(parent,id); ProjectExplorer::BuildStepList* steps = conf->stepList(); UbuntuCMakeDeployStep* depl = new UbuntuCMakeDeployStep(steps); depl->setUseNinja(false); steps->insertStep(0,depl); return conf; } bool UbuntuLocalDeployConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const { return canCreate(parent, ProjectExplorer::idFromMap(map)); } ProjectExplorer::DeployConfiguration *UbuntuLocalDeployConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map) { if (!canRestore(parent, map)) return 0; Core::Id id = ProjectExplorer::idFromMap(map); UbuntuLocalDeployConfiguration* const dc = new UbuntuLocalDeployConfiguration(parent, id); if (!dc->fromMap(map)) { delete dc; return 0; } return dc; } ProjectExplorer::DeployConfiguration *UbuntuLocalDeployConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::DeployConfiguration *product) { if (!canClone(parent, product)) return 0; return new UbuntuLocalDeployConfiguration(parent,qobject_cast(product)); } /// // UbuntuLocalDeployConfiguration /// UbuntuLocalDeployConfiguration::UbuntuLocalDeployConfiguration(ProjectExplorer::Target *target, const Core::Id id) : DeployConfiguration(target, id) { setDefaultDisplayName(tr("UbuntuSDK Deploy locally")); //this should run after the configurations are set up //and selects us as the default one, its ugly but works QTimer::singleShot(0,this,SLOT(selectAsDefaultHack())); } UbuntuLocalDeployConfiguration::UbuntuLocalDeployConfiguration(ProjectExplorer::Target *target, UbuntuLocalDeployConfiguration *source) : DeployConfiguration(target, source) { cloneSteps(source); } void UbuntuLocalDeployConfiguration::selectAsDefaultHack() { target()->setActiveDeployConfiguration(this); } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucoreappsmode.cpp0000644000015301777760000000225112323167147027500 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntucoreappsmode.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; UbuntuCoreAppsMode::UbuntuCoreAppsMode(QObject *parent) : UbuntuWebMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_COREAPPS_DISPLAYNAME)); setId(Ubuntu::Constants::UBUNTU_MODE_COREAPPS); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_COREAPPS)); setUrl(QUrl::fromUserInput(QLatin1String(Ubuntu::Constants::UBUNTU_COREAPPS))); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudeviceswidget.cpp0000644000015301777760000006652612323167214027657 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntudeviceswidget.h" #include "ui_ubuntudeviceswidget.h" #include #include #include #include #include "ubuntuconstants.h" #include #include #include #include #include #include #include using namespace Ubuntu; UbuntuDevicesWidget *UbuntuDevicesWidget::m_instance = 0; UbuntuDevicesWidget *UbuntuDevicesWidget::instance() { return m_instance; } bool UbuntuDevicesWidget::deviceDetected() { return ui->comboBoxSerialNumber->count(); } UbuntuDevicesWidget::UbuntuDevicesWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::UbuntuDevicesWidget) , m_ubuntuProcess(new Ubuntu::Internal::UbuntuProcess(this)) , m_refreshKnownAfterScan(false) { ui->setupUi(this); //Disable the clone network button for now ui->pushButtonCloneNetworkConfig->setVisible(false); ui->stackedEmulatorConfigWidget->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_PAGE_EMULATOR_PACKAGE_CHECK); m_instance = this; m_aboutToClose = false; ui->progressBar_InstallEmulator->setMinimum(0); ui->progressBar_InstallEmulator->setMaximum(0); ui->progressBar_InstallEmulator->hide(); ui->progressBar_CreateEmulator->setMinimum(0); ui->progressBar_CreateEmulator->setMaximum(0); ui->progressBar_CreateEmulator->hide(); ui->label_InstallEmulatorQuestion->show(); ui->pushButton_InstallEmulator_OK->show(); ui->nameLineEdit->setInitialText( QLatin1String(Constants::UBUNTU_INITIAL_EMULATOR_NAME)); slotChanged(); //devices page setupDevicePage(); ui->progressBar->setMinimum(0); ui->progressBar->setMaximum(0); ui->progressBarDeviceDetection->setMinimum(0); ui->progressBarDeviceDetection->setMaximum(0); connect(m_ubuntuProcess,SIGNAL(started(QString)),this,SLOT(onStarted(QString))); connect(m_ubuntuProcess,SIGNAL(message(QString)),this,SLOT(onMessage(QString))); connect(m_ubuntuProcess,SIGNAL(finished(QString,int)),this,SLOT(onFinished(QString, int))); connect(m_ubuntuProcess,SIGNAL(error(QString)),this,SLOT(onError(QString))); connect(ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged())); connect(ui->listWidget_EmulatorImages, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(startEmulator(QListWidgetItem*))); connect(&m_ubuntuDeviceNotifier,SIGNAL(deviceConnected(QString)),this,SLOT(onDeviceConnected(QString))); ProjectExplorer::DeviceManager* devMgr = ProjectExplorer::DeviceManager::instance(); connect(devMgr,SIGNAL(devicesLoaded()),this,SLOT(readDevicesFromSettings())); connect(devMgr,SIGNAL(deviceAdded(Core::Id)),this,SLOT(deviceAdded(Core::Id))); connect(devMgr,SIGNAL(deviceRemoved(Core::Id)),this,SLOT(deviceRemoved(Core::Id))); connect(devMgr,SIGNAL(deviceUpdated(Core::Id)),this,SLOT(deviceUpdated(Core::Id))); } UbuntuDevicesWidget::~UbuntuDevicesWidget() { m_aboutToClose = true; m_ubuntuProcess->stop(); delete ui; } bool UbuntuDevicesWidget::validate() { if (!ui->nameLineEdit->isValid()) { ui->label_EmulatorValidationMessage->setText(QLatin1String(Constants::ERROR_MSG_EMULATOR_NAME)); return false; } // Check existence of the directory QString projectDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); projectDir += QDir::separator(); projectDir += QLatin1String(Constants::DEFAULT_EMULATOR_PATH); projectDir += QDir::separator(); projectDir += ui->nameLineEdit->text(); const QFileInfo projectDirFile(projectDir); if (!projectDirFile.exists()) { // All happy return true; } if (projectDirFile.isDir()) { ui->label_EmulatorValidationMessage->setText(QLatin1String(Constants::ERROR_MSG_EMULATOR_EXISTS)); return false; } return true; } void UbuntuDevicesWidget::slotChanged() { if (!validate()) { ui->pushButton_CreateNewEmulator->setEnabled(false); } else { ui->label_EmulatorValidationMessage->setText(QLatin1String(Constants::EMPTY)); ui->pushButton_CreateNewEmulator->setEnabled(true); } } void UbuntuDevicesWidget::onMessage(QString msg) { if (msg.startsWith(QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_UNABLE_TO_FETCH))) { ui->progressBar_InstallEmulator->hide(); ui->label_InstallEmulatorStatus->hide(); ui->label_InstallEmulatorQuestion->show(); ui->pushButton_InstallEmulator_OK->show(); } m_reply.append(msg); ui->plainTextEdit->appendPlainText(msg.trimmed()); } void UbuntuDevicesWidget::onStarted(QString cmd) { ui->stackedWidgetConnectedDevice->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_INPUT); ui->lblDeviceProcessInfo->setText(QFileInfo(cmd).baseName()); ui->lblLoading->show(); ui->progressBar->show(); } void UbuntuDevicesWidget::onFinished(QString cmd, int code) { Q_UNUSED(code); ui->stackedWidgetConnectedDevice->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_INFO); if (m_aboutToClose) { return; } if (cmd == QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_START_EMULATOR).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { on_pushButtonRefresh_clicked(); } if (cmd == QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_CREATE_EMULATOR).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { ui->progressBar_CreateEmulator->hide(); ui->label_EmulatorValidationMessage->setText(QLatin1String(Constants::EMPTY)); ui->pushButton_CreateNewEmulator->setEnabled(true); checkEmulatorInstances(); } if (cmd == QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_SEARCH_IMAGES).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { QStringList lines = m_reply.trimmed().split(QLatin1String(Constants::LINEFEED)); ui->listWidget_EmulatorImages->clear(); foreach(QString line, lines) { line = line.trimmed(); if (line.isEmpty()) { ui->pushButton_StartEmulator->setEnabled(false); continue; } ui->pushButton_StartEmulator->setEnabled(true); QListWidgetItem* item = new QListWidgetItem(line); ui->listWidget_EmulatorImages->addItem(item); ui->listWidget_EmulatorImages->setCurrentItem(item); } on_pushButtonRefresh_clicked(); } if (cmd == QString::fromLatin1(Constants::UBUNTUWIDGETS_ONFINISHED_SCRIPT_LOCAL_PACKAGE_INSTALLED).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { QStringList lines = m_reply.trimmed().split(QLatin1String(Constants::LINEFEED)); ui->stackedEmulatorConfigWidget->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_PAGE_EMULATOR_PACKAGE_CHECK); foreach(QString line, lines) { line = line.trimmed(); if (line.isEmpty()) { continue; } if (line.startsWith(QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_LOCAL_NO_EMULATOR_INSTALLED))) { ui->label_InstallEmulatorStatus->hide(); ui->pushButton_InstallEmulator_OK->setEnabled(true); detectDevices(); } else { QStringList lineData = line.split(QLatin1String(Constants::SPACE)); QString sEmulatorPackageStatus = lineData.takeFirst(); QString sEmulatorPackageName = lineData.takeFirst(); QString sEmulatorPackageVersion = lineData.takeFirst(); if (sEmulatorPackageStatus.startsWith(QLatin1String(Constants::INSTALLED))) { checkEmulatorInstances(); ui->label_EmulatorInfo->setText(QString::fromLatin1(Ubuntu::Constants::UBUNTUDEVICESWIDGET_LABEL_EMULATOR_INFO).arg(sEmulatorPackageVersion).arg(sEmulatorPackageName)); ui->stackedEmulatorConfigWidget->setCurrentIndex(Ubuntu::Constants::UBUNTUDEVICESWIDGET_PAGE_EMULATOR_INSTANCES); } } } } if (cmd == QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_INSTALL_EMULATOR).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { QStringList lines = m_reply.trimmed().split(QLatin1String(Constants::LINEFEED)); foreach(QString line, lines) { line = line.trimmed(); if (line.startsWith(QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_UNABLE_TO_FETCH))) { ui->progressBar_InstallEmulator->hide(); ui->label_InstallEmulatorStatus->hide(); ui->label_InstallEmulatorQuestion->show(); ui->pushButton_InstallEmulator_OK->hide(); } } checkEmulator(); } if (cmd == QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVICESEARCH).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { QStringList lines = m_reply.trimmed().split(QLatin1String(Constants::LINEFEED)); //ugly hack to prevent running the search script and device //detection scripts at the same time if(m_refreshKnownAfterScan) { m_refreshKnownAfterScan = false; foreach(Ubuntu::Internal::UbuntuDevice::Ptr ptr, m_knownDevices) { removeDevice(ptr.data()); ptr->helper()->refresh(); } } // fill combobox data ui->comboBoxSerialNumber->setEnabled(false); foreach(QString line, lines) { line = line.trimmed(); if (line.isEmpty()) { continue; } QRegularExpression exp(QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_ADB_REGEX)); QRegularExpressionMatch match = exp.match(line); if(match.hasMatch()) { QStringList lineData = match.capturedTexts(); //The first entry is always the full match //which means in our case its the complete string lineData.takeFirst(); if (lineData.count() == 2) { QString sSerialNumber = lineData.takeFirst(); QString sDeviceInfo = lineData.takeFirst(); //sometimes the adb server is not started when adb devices is //executed, we just skip those lines if(sSerialNumber == QLatin1String("*")) continue; if(sSerialNumber.isEmpty() || sSerialNumber.startsWith(QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_ADB_NOACCESS))) { continue; } registerNewDevice(sSerialNumber,sDeviceInfo); } } } // if there are no devices if (ui->comboBoxSerialNumber->count() == 0) { endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_NO_DEVICE)); } else if (lines.count() > 0) { endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_FOUND_DEVICES).arg(lines.count())); //detectDeviceVersion(); } emit updateDeviceActions(); } else if (cmd == QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVICEVERSION).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { endAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_DEVICEVERSION_DETECTED)); //detectHasNetworkConnection(); } else { // left empty } ui->lblLoading->hide(); m_reply.clear(); } /*! * \brief UbuntuDevicesWidget::readDevicesFromSettings * read all known devices from the DeviceManager, this is triggered * automatically on startup */ void UbuntuDevicesWidget::readDevicesFromSettings() { ProjectExplorer::DeviceManager* devMgr = ProjectExplorer::DeviceManager::instance(); for(int i = 0; i < devMgr->deviceCount(); i++) { ProjectExplorer::IDevice::ConstPtr dev = devMgr->deviceAt(i); if(dev && dev->type() == Core::Id(Constants::UBUNTU_DEVICE_TYPE_ID)) { //ugly hack to get a mutable version of the device //no idea why its necessary to lock it up Ubuntu::Internal::UbuntuDevice* cPtr = qSharedPointerCast(dev)->helper()->device(); if(cPtr) { m_knownDevices.insert(cPtr->id().uniqueIdentifier(),cPtr->sharedFromThis()); connect(cPtr->helper(),SIGNAL(featureDetected()),this,SLOT(knownDeviceFeatureChange())); addDevice(cPtr); } } } setupDevicePage(); //will trigger detectDevices checkEmulator(); } /*! * \brief UbuntuDevicesWidget::deviceAdded * A device was added in the DeviceManager, check if know it and * if we should know it. If its a new Ubuntu device its added to * the known devices */ void UbuntuDevicesWidget::deviceAdded(const Core::Id &id) { qDebug()<<"Device Manager reports device added: "<find(id); if(!ptr) return; if(ptr->type() != Core::Id(Constants::UBUNTU_DEVICE_TYPE_ID)) return; Ubuntu::Internal::UbuntuDevice::ConstPtr ubuntuDev = qSharedPointerCast(ptr); Ubuntu::Internal::UbuntuDeviceHelper* hlp = ubuntuDev->helper(); Ubuntu::Internal::UbuntuDevice* dev = hlp->device(); m_knownDevices.insert(dev->id().uniqueIdentifier(),dev->sharedFromThis()); if(dev->deviceState() == ProjectExplorer::IDevice::DeviceConnected) { addDevice(dev); } connect(dev->helper(),SIGNAL(featureDetected()),this,SLOT(knownDeviceFeatureChange())); connect(dev->helper(),SIGNAL(detectionStateChanged()),this,SLOT(knownDeviceFeatureChange())); } /*! * \brief UbuntuDevicesWidget::deviceRemoved * A device was removed from the device manager, if its one of ours * we will also remove it */ void UbuntuDevicesWidget::deviceRemoved(const Core::Id &id) { qDebug()<<"Device Manager reports device removed: "<deviceState() == ProjectExplorer::IDevice::DeviceConnected || dev->deviceState() == ProjectExplorer::IDevice::DeviceReadyToUse) { addDevice(dev.data()); } else { removeDevice(dev.data()); } } void UbuntuDevicesWidget::knownDeviceFeatureChange() { Ubuntu::Internal::UbuntuDeviceHelper* hlpr = qobject_cast(sender()); if(!hlpr) return; if(hlpr->device()->id().uniqueIdentifier() == ui->comboBoxSerialNumber->currentData().toInt()) setupDevicePage(); } void UbuntuDevicesWidget::checkEmulatorInstances(){ beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_SEARCH_IMAGES)); m_ubuntuProcess->stop(); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_SEARCH_IMAGES_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) << QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_SEARCH_IMAGES)); } void UbuntuDevicesWidget::checkEmulator() { beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_EMULATOR_INSTALLED)); m_ubuntuProcess->stop(); QString sEmulatorPackageName = QLatin1String(Ubuntu::Constants::EMULATOR_PACKAGE_NAME); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUWIDGETS_LOCAL_PACKAGE_INSTALLED_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH).arg(sEmulatorPackageName) << QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_EMULATOR_INSTALLED)); } void UbuntuDevicesWidget::on_pushButton_InstallEmulator_OK_clicked() { ui->progressBar_InstallEmulator->show(); ui->label_InstallEmulatorStatus->show(); ui->label_InstallEmulatorQuestion->hide(); ui->pushButton_InstallEmulator_OK->hide(); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_INSTALL_EMULATOR_PACKAGE)); QString sEmulatorPackageName = QLatin1String(Ubuntu::Constants::EMULATOR_PACKAGE_NAME); m_ubuntuProcess->stop(); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_INSTALL_EMULATOR_PACKAGE_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH).arg(sEmulatorPackageName) << QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_INSTALL_EMULATOR_PACKAGE)); } void UbuntuDevicesWidget::on_pushButton_CreateNewEmulator_clicked() { beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_CREATE_EMULATOR)); m_ubuntuProcess->stop(); ui->progressBar_CreateEmulator->show(); ui->label_EmulatorValidationMessage->setText(QLatin1String(Constants::MSG_EMULATOR_IS_CREATED)); ui->pushButton_CreateNewEmulator->setEnabled(false); QString strEmulatorName = ui->nameLineEdit->text(); QString strEmulatorPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); strEmulatorPath += QDir::separator(); strEmulatorPath += QLatin1String(Constants::DEFAULT_EMULATOR_PATH); strEmulatorPath += QDir::separator(); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_CREATE_EMULATOR_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH).arg(strEmulatorPath).arg(strEmulatorName) << QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_CREATE_EMULATOR)); } void UbuntuDevicesWidget::on_pushButton_StartEmulator_clicked() { startEmulator(ui->listWidget_EmulatorImages->currentItem()); } void UbuntuDevicesWidget::startEmulator(QListWidgetItem * item) { QStringList lineData = item->text().trimmed().split(QLatin1String(Constants::TAB)); QString sEmulatorPath = lineData.takeFirst(); beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_START_EMULATOR)); m_ubuntuProcess->stop(); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_START_EMULATOR_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH).arg(sEmulatorPath) << QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_LOCAL_START_EMULATOR)); } void UbuntuDevicesWidget::setupDevicePage() { if(ui->comboBoxSerialNumber->count() == 0) { ui->frameNoDevices->show(); ui->widgetDeviceSerial->hide(); ui->comboBoxSerialNumber->clear(); ui->comboBoxSerialNumber->setEnabled(false); ui->stackedWidgetDeviceConnected->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_NODEVICE_CONNECTED); } else { ui->stackedWidgetDeviceConnected->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_DEVICE_CONNECTED); ui->frameNoDevices->hide(); ui->widgetDeviceSerial->show(); ui->comboBoxSerialNumber->setEnabled(true); int devId = ui->comboBoxSerialNumber->currentData().toInt(); if(m_knownDevices.contains(devId)) { Ubuntu::Internal::UbuntuDevice::Ptr dev = m_knownDevices[devId]; if (dev->detectionState() != Ubuntu::Internal::UbuntuDevice::Done) { ui->labelDeviceDetection->setText(dev->detectionStateString()); ui->labelDeviceDetection->show(); ui->progressBarDeviceDetection->show(); } else { ui->labelDeviceDetection->hide(); ui->progressBarDeviceDetection->hide(); } if (dev->hasNetworkConnection() != Ubuntu::Internal::UbuntuDevice::Available) { ui->stackedWidgetDeveloperMode->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_DEVELOPERMODE_PAGE_NONETWORK); } else { if(dev->developerModeEnabled() == Ubuntu::Internal::UbuntuDevice::Available) { ui->stackedWidgetDeveloperMode->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_DEVELOPERMODE_PAGE_ENABLED); } else { ui->stackedWidgetDeveloperMode->setCurrentIndex(Constants::UBUNTUDEVICESWIDGET_DEVELOPERMODE_PAGE_DEVICEFOUND); } } } } } void UbuntuDevicesWidget::detectDevices(const bool restartAdb) { beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVICES)); m_ubuntuProcess->stop(); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVICES_SCRIPT) .arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH) .arg(restartAdb ? QString::number(1) : QString::number(0))<< QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_DETECTDEVICES)); } #if 0 //this was not used, still needed? void UbuntuDevicesWidget::on_pushButtonCloneNetworkConfig_clicked() { beginAction(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONENETWORK)); m_ubuntuProcess->stop(); m_ubuntuProcess->append(QStringList() << QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONENETWORK_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH).arg(serialNumber()) << QApplication::applicationDirPath()); m_ubuntuProcess->start(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_CLONENETWORK)); } #endif QString UbuntuDevicesWidget::serialNumber() { return ui->comboBoxSerialNumber->currentText(); } Internal::UbuntuDevice::ConstPtr UbuntuDevicesWidget::device() { if(ui->comboBoxSerialNumber->count()) { int devId = ui->comboBoxSerialNumber->currentData().toInt(); if(m_knownDevices.contains(devId)) { return m_knownDevices[devId]; } } return Internal::UbuntuDevice::ConstPtr(); } void UbuntuDevicesWidget::on_comboBoxSerialNumber_currentIndexChanged( const QString & text ) { if(text.isEmpty()) return; int idx = ui->comboBoxSerialNumber->findText(text); Q_ASSERT_X(idx >= 0, Q_FUNC_INFO, "Index can not be invalid"); int devId = ui->comboBoxSerialNumber->itemData(idx).toInt(); ui->stackedWidgetDeviceConfig->setCurrentIndex(idx); ui->lblDeviceInfo->setText(m_knownDevices[devId]->deviceInfoString()); setupDevicePage(); } void UbuntuDevicesWidget::onDeviceConnected(const QString &id) { QSettings settings(QLatin1String(Constants::SETTINGS_COMPANY),QLatin1String(Constants::SETTINGS_PRODUCT)); settings.beginGroup(QLatin1String(Constants::SETTINGS_GROUP_DEVICES)); if (settings.value(QLatin1String(Constants::SETTINGS_KEY_AUTOTOGGLE),Constants::SETTINGS_DEFAULT_DEVICES_AUTOTOGGLE).toBool()) { Core::ModeManager::activateMode(Ubuntu::Constants::UBUNTU_MODE_DEVICES); } Core::Id qtcid = Core::Id::fromSetting(id); if(m_knownDevices.contains(qtcid.uniqueIdentifier())) return; m_reply.clear(); ui->plainTextEdit->clear(); m_ubuntuProcess->stop(); ui->frameNoDevices->hide(); ui->frameProgress->show(); ui->lblLoading->show(); detectDevices(); } void UbuntuDevicesWidget::on_pushButtonRefresh_clicked() { m_refreshKnownAfterScan = true; m_ubuntuProcess->stop(); ui->plainTextEdit->clear(); m_reply.clear(); detectDevices(true); } void UbuntuDevicesWidget::onError(QString msg) { ui->plainTextEdit->appendHtml(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ONERROR).arg(msg)); } void UbuntuDevicesWidget::beginAction(QString msg) { ui->plainTextEdit->appendHtml(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ACTION_BEGIN).arg(msg)); } void UbuntuDevicesWidget::endAction(QString msg) { ui->plainTextEdit->appendHtml(QString::fromLatin1(Constants::UBUNTUDEVICESWIDGET_ACTION_END).arg(msg)); } /*! * \brief UbuntuDevicesWidget::addDevice * Adds a device to the dropdown box, and creates the config widget * for it */ int UbuntuDevicesWidget::addDevice(Internal::UbuntuDevice *dev) { int idx = ui->comboBoxSerialNumber->findData(dev->id().uniqueIdentifier()); //already there if(idx >= 0) return idx; qDebug()<<"Show device "<id().toString()<<" Because its in connected state"; if(dev->deviceState() == ProjectExplorer::IDevice::DeviceConnected || dev->deviceState() == ProjectExplorer::IDevice::DeviceReadyToUse) { ui->comboBoxSerialNumber->addItem(dev->id().toSetting().toString(),dev->id().uniqueIdentifier()); //pointer ownership goes to the stack idx = ui->stackedWidgetDeviceConfig->addWidget(dev->createWidget()); } setupDevicePage(); return idx; } /*! * \brief UbuntuDevicesWidget::removeDevice * Removes a device from the dropdown box and deletes the config widget */ void UbuntuDevicesWidget::removeDevice(Internal::UbuntuDevice *dev) { int idx = ui->comboBoxSerialNumber->findData(dev->id().uniqueIdentifier()); if(idx < 0) return; QWidget* w = ui->stackedWidgetDeviceConfig->widget(idx); ui->stackedWidgetDeviceConfig->removeWidget(w); delete w; ui->comboBoxSerialNumber->removeItem(idx); setupDevicePage(); } /*! * \brief UbuntuDevicesWidget::registerNewDevice * Registers a new device in the device manager if its not * already in the known devices map. * \note will not add it into the devices dropdown box, this * will happen automatically when the device switches to * connected state */ void UbuntuDevicesWidget::registerNewDevice(const QString &serial, const QString &deviceInfo) { if(!m_knownDevices.contains(Core::Id::fromSetting(serial).uniqueIdentifier())) { bool isEmu = serial.startsWith(QLatin1String("emulator")); Ubuntu::Internal::UbuntuDevice::Ptr dev = Ubuntu::Internal::UbuntuDevice::create( tr("Ubuntu Device") , serial , isEmu ? ProjectExplorer::IDevice::Emulator : ProjectExplorer::IDevice::Hardware , ProjectExplorer::IDevice::AutoDetected); dev->setDeviceInfoString(deviceInfo); ProjectExplorer::DeviceManager::instance()->addDevice(dev); } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntulocalrunconfigurationfactory.cpp0000644000015301777760000001363412323167147033025 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntulocalrunconfigurationfactory.h" #include "ubunturemoterunconfiguration.h" #include "ubuntuprojectguesser.h" #include "ubuntudevice.h" #include "clicktoolchain.h" #include #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; QList UbuntuLocalRunConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent) const { if (!canHandle(parent)) return QList(); QList list; bool isDesktopDevice = ProjectExplorer::DeviceKitInformation::deviceId(parent->kit()) == ProjectExplorer::Constants::DESKTOP_DEVICE_ID; ProjectExplorer::IDevice::ConstPtr devPtr = ProjectExplorer::DeviceKitInformation::device(parent->kit()); bool isUbuntuDevice = (devPtr.isNull() == false) && (devPtr->type() == Constants::UBUNTU_DEVICE_TYPE_ID); if(parent->project()->id() == CMakeProjectManager::Constants::CMAKEPROJECT_ID) { if (UbuntuProjectGuesser::isScopesProject(parent->project())) { if(isDesktopDevice) list << Core::Id(Constants::UBUNTUPROJECT_RUNCONTROL_ID); } else { //the scopes project has no run on device yet, thats why finding a //scopes project will block creating any runconfigurations for the device if(isUbuntuDevice) list << UbuntuRemoteRunConfiguration::typeId(); else if(isDesktopDevice && UbuntuProjectGuesser::isClickAppProject(parent->project())) list << Core::Id(Constants::UBUNTUPROJECT_RUNCONTROL_ID); } } else { list << Core::Id(Constants::UBUNTUPROJECT_RUNCONTROL_ID); } return list; } QString UbuntuLocalRunConfigurationFactory::displayNameForId(const Core::Id id) const { if (id == Constants::UBUNTUPROJECT_RUNCONTROL_ID) return tr(Constants::UBUNTUPROJECT_DISPLAYNAME); else if(id == UbuntuRemoteRunConfiguration::typeId()) return tr(Constants::UBUNTUPROJECT_DISPLAYNAME); return QString(); } bool UbuntuLocalRunConfigurationFactory::canHandle(ProjectExplorer::Target *parent) const { if(qobject_cast(parent->project())) { if (!parent->project()->supportsKit(parent->kit())) return false; ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(parent->kit()); if (!tc || tc->targetAbi().os() != ProjectExplorer::Abi::LinuxOS) return false; if(tc->type() == QString::fromLatin1(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) return true; bool isDesktopDevice = ProjectExplorer::DeviceKitInformation::deviceId(parent->kit()) == ProjectExplorer::Constants::DESKTOP_DEVICE_ID; if(UbuntuProjectGuesser::isScopesProject(parent->project()) && isDesktopDevice) return true; else if(isDesktopDevice && UbuntuProjectGuesser::isClickAppProject(parent->project())) return true; return false; } if (!qobject_cast(parent->project())) return false; return true; } bool UbuntuLocalRunConfigurationFactory::canCreate(ProjectExplorer::Target *parent, const Core::Id id) const { if (!canHandle(parent)) return false; return availableCreationIds(parent).contains(id); } bool UbuntuLocalRunConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const { return parent && canCreate(parent, ProjectExplorer::idFromMap(map)); } ProjectExplorer::RunConfiguration *UbuntuLocalRunConfigurationFactory::doCreate(ProjectExplorer::Target *parent, const Core::Id id) { if (!canCreate(parent, id)) return NULL; if( id == UbuntuRemoteRunConfiguration::typeId() ) return new UbuntuRemoteRunConfiguration(parent); else if ( id == Constants::UBUNTUPROJECT_RUNCONTROL_ID) return new UbuntuLocalRunConfiguration(parent, id); return 0; } ProjectExplorer::RunConfiguration *UbuntuLocalRunConfigurationFactory::doRestore(ProjectExplorer::Target *parent, const QVariantMap &map) { if (!canRestore(parent, map)) return NULL; ProjectExplorer::RunConfiguration *conf = create(parent,ProjectExplorer::idFromMap(map)); if(!conf) return NULL; if(!conf->fromMap(map)) { delete conf; return NULL; } return conf; } bool UbuntuLocalRunConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product) const { return canCreate(parent,product->id()); } ProjectExplorer::RunConfiguration *UbuntuLocalRunConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *source) { if (!canClone(parent, source)) return NULL; if(source->id() == UbuntuRemoteRunConfiguration::typeId()) return new UbuntuRemoteRunConfiguration(parent,static_cast(source)); return new UbuntuLocalRunConfiguration(parent,static_cast(source)); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuwikimode.h0000644000015301777760000000176512323167147026305 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUWIKIMODE_H #define UBUNTUWIKIMODE_H #include "ubuntuwebmode.h" #include namespace Ubuntu { namespace Internal { class UbuntuWikiMode : public UbuntuWebMode { Q_OBJECT public: explicit UbuntuWikiMode(QObject *parent = 0); }; } } #endif // UBUNTUWIKIMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuproject.h0000644000015301777760000000535112323167147026136 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROJECT_H #define UBUNTUPROJECT_H #include "ubuntuprojectmanager.h" #include "ubuntuprojectfile.h" #include "ubuntuprojectnode.h" #include "ubuntuconstants.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuProjectManager; class UbuntuProjectFile; class UbuntuProjectNode; class UbuntuProject : public ProjectExplorer::Project { Q_OBJECT public: UbuntuProject(UbuntuProjectManager *manager, const QString &fileName); QString displayName() const; Core::Id id() const; Core::IDocument *document() const; ProjectExplorer::IProjectManager *projectManager() const; ProjectExplorer::ProjectNode *rootProjectNode() const; QStringList files(FilesMode fileMode) const; QDir projectDir() const { return projectDirectory(); } QString filesFileName() const { return m_fileName; } QString mainFile() const { return m_mainFile; } private: void extractProjectFileData(const QString& filename); UbuntuProjectManager *m_manager; QString m_projectName; QSharedPointer m_file; QString m_mainFile; QString m_fileName; QSharedPointer m_rootNode; }; } } #endif // UBUNTUPROJECT_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucreatenewchrootdialog.cpp0000644000015301777760000000545112323167147031400 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntucreatenewchrootdialog.h" #include "ui_ubuntucreatenewchrootdialog.h" #include "ubuntuconstants.h" namespace Ubuntu { namespace Constants { const char* UBUNTU_CLICK_SUPPORTED_ARCHS[] = {"armhf","i386","amd64","\0"}; //lists all currently supported targets by the plugin const char* UBUNTU_CLICK_SUPPORTED_TARGETS[][3] = { //Series Framework Displayname {"trusty","ubuntu-sdk-14.04","Framework-14.04"}, {"saucy" ,"ubuntu-sdk-13.10","Framework-13.10"}, {"\0","\0","\0"} }; } namespace Internal { UbuntuCreateNewChrootDialog::UbuntuCreateNewChrootDialog(QWidget *parent) : QDialog(parent), ui(new Ui::UbuntuCreateNewChrootDialog) { ui->setupUi(this); //add supported targets for(int i = 0; Constants::UBUNTU_CLICK_SUPPORTED_TARGETS[i][0][0] != '\0'; i++){ ui->comboBoxSeries->addItem(QLatin1String(Constants::UBUNTU_CLICK_SUPPORTED_TARGETS[i][2]),i); } //add supported architectures for(int i = 0; Constants::UBUNTU_CLICK_SUPPORTED_ARCHS[i][0] != '\0' ;i++) { ui->comboBoxArch->addItem(QLatin1String(Constants::UBUNTU_CLICK_SUPPORTED_ARCHS[i])); } } UbuntuCreateNewChrootDialog::~UbuntuCreateNewChrootDialog() { delete ui; } /** * @brief UbuntuCreateNewChrootDialog::getNewChrootParams * Opens a dialog that lets the user select a new chroot, returns false * if the user pressed cancel */ bool UbuntuCreateNewChrootDialog::getNewChrootTarget(UbuntuClickTool::Target *target) { UbuntuCreateNewChrootDialog dlg; if( dlg.exec() == QDialog::Accepted) { bool ok = false; int idx = dlg.ui->comboBoxSeries->itemData(dlg.ui->comboBoxSeries->currentIndex()).toInt(&ok); if(!ok) return false; target->architecture = dlg.ui->comboBoxArch->currentText(); target->series = QString::fromLatin1(Constants::UBUNTU_CLICK_SUPPORTED_TARGETS[idx][0]); target->framework = QString::fromLatin1(Constants::UBUNTU_CLICK_SUPPORTED_TARGETS[idx][1]); return true; } return false; } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuvalidationresultmodel.h0000644000015301777760000000630412323167147031101 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_UBUNTUVALIDATIONRESULTMODEL_H #define UBUNTU_INTERNAL_UBUNTUVALIDATIONRESULTMODEL_H #include #include #include #include namespace Ubuntu { namespace Internal { class ClickRunChecksParser : public QObject { Q_OBJECT public: enum ItemIcon { Error, Warning, Check, NoIcon }; struct DataItem { DataItem(); ~DataItem(); DataItem* parent; QString type; QString text; QUrl link; ItemIcon icon; QList children; }; ClickRunChecksParser(QObject* parent = 0); void beginRecieveData(const QString& data = QString()); void addRecievedData (const QString& data); void endRecieveData (const QString& data = QString()); void emitTextItem (const QString &type, const QString &text, const ItemIcon icon = NoIcon); protected: bool tryParseNextSection ( bool dataComplete = false); void emitParseErrorItem (const QString &text); void parseJsonSection (const QString §ionName, int offset, int length = -1); signals: void parsedNewTopLevelItem (DataItem* item); private: QString m_data; int m_nextSectionOffset; int m_errorCount; int m_warnCount; }; class UbuntuValidationResultModel : public QAbstractItemModel { Q_OBJECT public: enum Roles { TypeRole = Qt::UserRole+1, LinkRole, DescriptionRole }; UbuntuValidationResultModel(QObject *parent = 0); ~UbuntuValidationResultModel(); // QAbstractItemModel interface virtual QModelIndex index(int row, int column, const QModelIndex &parent) const; virtual QModelIndex parent(const QModelIndex &child) const; virtual int rowCount(const QModelIndex &parent) const; virtual int columnCount(const QModelIndex &parent) const; virtual QVariant data(const QModelIndex &index, int role) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const; QModelIndex findFirstErrorItem () const; public slots: void appendItem ( ClickRunChecksParser::DataItem* item ); void clear (); private: ClickRunChecksParser::DataItem *getItem(const QModelIndex &index) const; private: ClickRunChecksParser::DataItem* m_rootItem; QString m_data; int m_nextSectionOffset; }; } // namespace Internal } // namespace Ubuntu Q_DECLARE_METATYPE(Ubuntu::Internal::ClickRunChecksParser::DataItem*) #endif // UBUNTU_INTERNAL_UBUNTUVALIDATIONRESULTMODEL_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsclickpage.cpp0000644000015301777760000000262312323167147030525 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusettingsclickpage.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; UbuntuSettingsClickPage::UbuntuSettingsClickPage() : m_widget(0) { setId("A.Click"); setDisplayName(tr("Click")); setCategory("Ubuntu"); setDisplayCategory(QLatin1String("Ubuntu")); setCategoryIcon(QLatin1String(Ubuntu::Constants::UBUNTU_SETTINGS_ICON)); } UbuntuSettingsClickPage::~UbuntuSettingsClickPage() { } QWidget *UbuntuSettingsClickPage::createPage(QWidget *parent) { m_widget = new UbuntuSettingsClickWidget(parent); return m_widget; } void UbuntuSettingsClickPage::apply() { if (!m_widget) // page was never shown return; m_widget->apply(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubunturemoteruncontrolfactory.cpp0000644000015301777760000001221312323167147032027 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubunturemoteruncontrolfactory.h" #include "ubunturemoterunconfiguration.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu::Internal; bool UbuntuRemoteRunControlFactory::canRun(ProjectExplorer::RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode) const { if(qobject_cast(runConfiguration)) { if (mode != ProjectExplorer::NormalRunMode && mode != ProjectExplorer::DebugRunMode && mode != ProjectExplorer::DebugRunModeWithBreakOnMain && mode != ProjectExplorer::QmlProfilerRunMode) { return false; } return runConfiguration->isEnabled(); } return false; } ProjectExplorer::RunControl *UbuntuRemoteRunControlFactory::create(ProjectExplorer::RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode, QString *errorMessage) { if (qobject_cast(runConfiguration)) { /* * Taken from remotelinuxruncontrolfactory.cpp and adapted * to work here. */ QTC_ASSERT(canRun(runConfiguration, mode), return 0); UbuntuRemoteRunConfiguration *rc = qobject_cast(runConfiguration); QTC_ASSERT(rc, return 0); switch (mode) { case ProjectExplorer::NormalRunMode: return new RemoteLinux::RemoteLinuxRunControl(rc); case ProjectExplorer::DebugRunMode: case ProjectExplorer::DebugRunModeWithBreakOnMain: { ProjectExplorer::IDevice::ConstPtr dev = ProjectExplorer::DeviceKitInformation::device(rc->target()->kit()); if (!dev) { *errorMessage = tr("Cannot debug: Kit has no device."); return 0; } qDebug()<<"Free ports on the device: "<freePorts().count(); if (2 > dev->freePorts().count()) { *errorMessage = tr("Cannot debug: Not enough free ports available."); return 0; } Debugger::DebuggerStartParameters params = RemoteLinux::LinuxDeviceDebugSupport::startParameters(rc); if (mode == ProjectExplorer::DebugRunModeWithBreakOnMain) params.breakOnMain = true; params.solibSearchPath.append(rc->soLibSearchPaths()); qDebug()<<"Solib search path : "<engine()); connect(runControl, SIGNAL(finished()), debugSupport, SLOT(handleDebuggingFinished())); return runControl; } case ProjectExplorer::QmlProfilerRunMode: { Analyzer::AnalyzerStartParameters params = RemoteLinux::RemoteLinuxAnalyzeSupport::startParameters(rc, mode); Analyzer::AnalyzerRunControl *runControl = Analyzer::AnalyzerManager::createRunControl(params, runConfiguration); RemoteLinux::RemoteLinuxAnalyzeSupport * const analyzeSupport = new RemoteLinux::RemoteLinuxAnalyzeSupport(rc, runControl, mode); connect(runControl, SIGNAL(finished()), analyzeSupport, SLOT(handleProfilingFinished())); return runControl; } case ProjectExplorer::NoRunMode: case ProjectExplorer::CallgrindRunMode: case ProjectExplorer::MemcheckRunMode: QTC_ASSERT(false, return 0); } QTC_ASSERT(false, return 0); return 0; } return 0; } QString UbuntuRemoteRunControlFactory::displayName() const { return tr("Run on Ubuntu Touch Device"); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntubzr.cpp0000644000015301777760000000307312323167147025617 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntubzr.h" #include "ubuntuconstants.h" #include using namespace Ubuntu::Internal; UbuntuBzr::UbuntuBzr(QObject *parent) : QObject(parent), m_bInitialized(false) { connect(&m_cmd,SIGNAL(finished(int)),this,SLOT(scriptExecuted(int))); m_cmd.setWorkingDirectory(QCoreApplication::applicationDirPath()); } void UbuntuBzr::initialize() { m_cmd.start(QString(QLatin1String(Constants::UBUNTUBZR_INITIALIZE)).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)); } void UbuntuBzr::scriptExecuted(int sta) { QStringList data = QString(QString::fromLocal8Bit(m_cmd.readAllStandardOutput())).trimmed().split(QLatin1String(Constants::LINEFEED)); if (data.length()!=2) { return; } this->m_whoami = data.takeFirst(); this->m_launchpadId = data.takeFirst(); m_bInitialized = true; emit initializedChanged(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/localportsmanager.h0000644000015301777760000000256212323167147026743 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTU_INTERNAL_LOCALPORTSMANAGER_H #define UBUNTU_INTERNAL_LOCALPORTSMANAGER_H #include #include namespace Ubuntu { namespace Internal { class UbuntuLocalPortsManager : public QObject { Q_OBJECT public: explicit UbuntuLocalPortsManager(); static void setPortsRange (const int first, const int last); static Utils::PortList getFreeRange ( const QString &serial, const int count); signals: public slots: private: static UbuntuLocalPortsManager *m_instance; int m_first; int m_last; Utils::PortList m_usedPorts; }; } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_LOCALPORTSMANAGER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevicenotifier.h0000644000015301777760000000346312323167147027471 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUDEVICENOTIFIER_H #define UBUNTUDEVICENOTIFIER_H #include #include #include #include class IUbuntuDeviceNotifier : public QObject { Q_OBJECT public: IUbuntuDeviceNotifier (QObject *parent = 0); virtual void startMonitoring(const QString &serialNumber) = 0; virtual void stopMonitoring() = 0; virtual bool isConnected () const = 0; signals: void deviceConnected(); void deviceConnected(const QString &serialNumber); void deviceDisconnected(); }; class UbuntuDeviceNotifier : public IUbuntuDeviceNotifier { Q_OBJECT public: explicit UbuntuDeviceNotifier(QObject *parent = 0); ~UbuntuDeviceNotifier(); public slots: void startMonitoring(const QString &serialNumber); void stopMonitoring(); bool isConnected () const; protected slots: void on_udev_event(); private: struct udev *m_dev; struct udev_monitor *m_udevMonitor; int m_udevMonitorFileDescriptor; QSocketNotifier* m_udevSocketNotifier; QString m_devNode; QString m_serialNumber; }; #endif // UBUNTUDEVICENOTIFIER_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucmakemakestep.cpp0000644000015301777760000002523412323167147027637 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntucmakemakestep.h" #include "ubuntuconstants.h" #include "ubuntuprojectguesser.h" #include "clicktoolchain.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { /*! * \class UbuntuCMakeMakeStepFactory * Factory class to create UbuntuCMakeMakeStep * build steps */ QList UbuntuCMakeMakeStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const { if(!canHandle(parent->target())) return QList(); if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_DEPLOY) return QList() << Core::Id(Constants::UBUNTU_DEPLOY_MAKESTEP_ID); return QList() << Core::Id(Constants::UBUNTU_CLICK_CMAKE_MAKESTEP_ID); } /*! * \brief UbuntuCMakeBuildConfigurationFactory::canHandle * checks if we can create buildconfigurations for the given target */ bool UbuntuCMakeMakeStepFactory::canHandle(const ProjectExplorer::Target *t) const { QTC_ASSERT(t, return false); if (!t->project()->supportsKit(t->kit())) return false; if(ProjectExplorer::DeviceKitInformation::deviceId(t->kit()) == ProjectExplorer::Constants::DESKTOP_DEVICE_ID) { return UbuntuProjectGuesser::isClickAppProject(t->project()); } ProjectExplorer::ToolChain* tc = ProjectExplorer::ToolChainKitInformation::toolChain(t->kit()); if(!tc || tc->type() != QLatin1String(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) return false; return t->project()->id() == Core::Id(CMakeProjectManager::Constants::CMAKEPROJECT_ID); } QString UbuntuCMakeMakeStepFactory::displayNameForId(const Core::Id id) const { if (id == Constants::UBUNTU_CLICK_CMAKE_MAKESTEP_ID) return tr("UbuntuSDK-Make", "Display name for UbuntuCMakeMakeStep id."); if (id == Constants::UBUNTU_DEPLOY_MAKESTEP_ID) return tr("UbuntuSDK create deployment package", "Display name for UbuntuCMakeDeployStep id."); return QString(); } bool UbuntuCMakeMakeStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const { if (canHandle(parent->target())) return availableCreationIds(parent).contains(id); return false; } ProjectExplorer::BuildStep *UbuntuCMakeMakeStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id) { if (!canCreate(parent, id)) return 0; if ( id == Core::Id(Constants::UBUNTU_DEPLOY_MAKESTEP_ID) ) { UbuntuCMakeDeployStep *step = new UbuntuCMakeDeployStep(parent); step->setUseNinja(false); step->setClean(false); return step; } UbuntuCMakeMakeStep *step = new UbuntuCMakeMakeStep(parent); if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) { step->setUseNinja(false); step->setClean(true); step->setAdditionalArguments(QLatin1String("clean")); } return step; } bool UbuntuCMakeMakeStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const { return canCreate(parent, ProjectExplorer::idFromMap(map)); } ProjectExplorer::BuildStep *UbuntuCMakeMakeStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) { if (!canRestore(parent, map)) return 0; ProjectExplorer::BuildStep* step = create(parent,ProjectExplorer::idFromMap(map)); if(step->fromMap(map)) return step; delete step; return 0; } bool UbuntuCMakeMakeStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const { return canCreate(parent, product->id()); } ProjectExplorer::BuildStep *UbuntuCMakeMakeStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) { if (!canClone(parent, product)) return 0; if(product->id() == Core::Id(Constants::UBUNTU_DEPLOY_MAKESTEP_ID)) return new UbuntuCMakeDeployStep(parent,static_cast(product)); else if(product->id() == Core::Id(Constants::UBUNTU_DEPLOY_MAKESTEP_ID)) return new UbuntuCMakeMakeStep(parent, static_cast(product)); QTC_ASSERT(false,return 0); } /*! * \class UbuntuCMakeMakeStep * Represents a make or make clean call in the Ubuntu-SDK build chain */ UbuntuCMakeMakeStep::UbuntuCMakeMakeStep(ProjectExplorer::BuildStepList *bsl) : MakeStep(bsl,Core::Id(Constants::UBUNTU_CLICK_CMAKE_MAKESTEP_ID)) { setDefaultDisplayName(tr("Ubuntu SDK Make")); } UbuntuCMakeMakeStep::UbuntuCMakeMakeStep(ProjectExplorer::BuildStepList *bsl, UbuntuCMakeMakeStep *bs) : MakeStep(bsl,bs) { } UbuntuCMakeMakeStep::~UbuntuCMakeMakeStep() { } QString UbuntuCMakeMakeStep::makeCommand(ProjectExplorer::ToolChain *tc, const Utils::Environment &env) const { if (tc) return tc->makeCommand(env); return QString::fromLatin1(Constants::UBUNTU_CLICK_MAKE_WRAPPER).arg(Constants::UBUNTU_SCRIPTPATH); } UbuntuCMakeDeployStep::UbuntuCMakeDeployStep(ProjectExplorer::BuildStepList *bsl) : MakeStep(bsl,Core::Id(Constants::UBUNTU_DEPLOY_MAKESTEP_ID)) { setDefaultDisplayName(tr("UbuntuSDK create deploy package")); setAdditionalArguments(QString::fromLatin1("DESTDIR=%1 install").arg(QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR))); } UbuntuCMakeDeployStep::UbuntuCMakeDeployStep(ProjectExplorer::BuildStepList *bsl, UbuntuCMakeDeployStep *bs) : MakeStep(bsl,bs) { } ProjectExplorer::BuildStepConfigWidget *UbuntuCMakeDeployStep::createConfigWidget() { return new ProjectExplorer::SimpleBuildStepConfigWidget(this); } UbuntuCMakeDeployStep::~UbuntuCMakeDeployStep() { } bool UbuntuCMakeDeployStep::fromMap(const QVariantMap &map) { if(MakeStep::fromMap(map)) { setAdditionalArguments(QString::fromLatin1("DESTDIR=%1 install").arg(QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR))); return true; } return false; } UbuntuClickPackageStep::UbuntuClickPackageStep(ProjectExplorer::BuildStepList *bsl) : ProjectExplorer::AbstractProcessStep(bsl,Constants::UBUNTU_CLICK_PACKAGESTEP_ID) { } UbuntuClickPackageStep::UbuntuClickPackageStep(ProjectExplorer::BuildStepList *bsl, UbuntuClickPackageStep *bs) : ProjectExplorer::AbstractProcessStep(bsl,bs) { } UbuntuClickPackageStep::~UbuntuClickPackageStep() { } void UbuntuClickPackageStep::stdOutput(const QString &line) { m_lastLine = line; AbstractProcessStep::stdOutput(line); } void UbuntuClickPackageStep::stdError(const QString &line) { AbstractProcessStep::stdError(line); } void UbuntuClickPackageStep::processFinished(int exitCode, QProcess::ExitStatus status) { if( exitCode == 0 && status == QProcess::NormalExit ) { QRegularExpression exp(QLatin1String(Constants::UBUNTU_CLICK_SUCCESS_PACKAGE_REGEX)); QRegularExpressionMatch m = exp.match(m_lastLine); if(m.hasMatch()) m_clickPackageName = m.captured(1); } ProjectExplorer::AbstractProcessStep::processFinished(exitCode,status); } bool UbuntuClickPackageStep::init() { m_tasks.clear(); ProjectExplorer::BuildConfiguration *bc = buildConfiguration(); if (!bc){ ProjectExplorer::Task t(ProjectExplorer::Task::Error ,tr("No valid BuildConfiguration set for step: %1").arg(displayName()) ,Utils::FileName(),-1 ,ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); m_tasks.append(t); //UbuntuClickPackageStep::run will stop if tasks exist return true; } //builds the process arguments QStringList arguments; arguments << QLatin1String("build") << bc->buildDirectory().toString() + QDir::separator() + QString::fromLatin1(Constants::UBUNTU_DEPLOY_DESTDIR); setIgnoreReturnValue(false); ProjectExplorer::ProcessParameters* params = processParameters(); params->setMacroExpander(bc->macroExpander()); //setup process parameters params->setWorkingDirectory(bc->buildDirectory().toString()); params->setCommand(QLatin1String("click")); params->setArguments(Utils::QtcProcess::joinArgs(arguments)); Utils::Environment env = bc->environment(); // Force output to english for the parsers. Do this here and not in the toolchain's // addToEnvironment() to not screw up the users run environment. env.set(QLatin1String("LC_ALL"), QLatin1String("C")); params->setEnvironment(env); params->resolveAll(); ProjectExplorer::IOutputParser *parser = target()->kit()->createOutputParser(); if (parser) { setOutputParser(parser); outputParser()->setWorkingDirectory(params->effectiveWorkingDirectory()); } return AbstractProcessStep::init(); } void UbuntuClickPackageStep::run(QFutureInterface &fi) { if (m_tasks.size()) { foreach (const ProjectExplorer::Task& task, m_tasks) { addTask(task); } emit addOutput(tr("Configuration is invalid. Aborting build") ,ProjectExplorer::BuildStep::MessageOutput); fi.reportResult(false); emit finished(); return; } AbstractProcessStep::run(fi); } ProjectExplorer::BuildStepConfigWidget *UbuntuClickPackageStep::createConfigWidget() { return new ProjectExplorer::SimpleBuildStepConfigWidget(this); } QString UbuntuClickPackageStep::packagePath() const { if(m_clickPackageName.isEmpty()) return QString(); return buildConfiguration()->buildDirectory().toString() + QDir::separator() + m_clickPackageName; } } // namespace Internal } // namespace Ubuntu qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/Ubuntu.pluginspec.in0000644000015301777760000000201212323167214027020 0ustar pbusernogroup00000000000000 Canonical (C) Canonical Ltd. LGPL Ubuntu support library http://www.ubuntu.com qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsclickwidget.ui0000644000015301777760000000541512323167147030731 0ustar pbusernogroup00000000000000 UbuntuSettingsClickWidget 0 0 925 512 Form Click Packaging Reviewer false true false Tools: ... Click Build Targets QAbstractItemView::NoEditTriggers QAbstractItemView::NoSelection false false 1 Create Click Target Qt::Vertical 20 40 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectfile.h0000644000015301777760000000414512323167147026776 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROJECTFILE_H #define UBUNTUPROJECTFILE_H #include #include "ubuntuconstants.h" #include "ubuntuproject.h" #include "ubuntuprojectmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuProject; class UbuntuProjectFile : public Core::IDocument { Q_OBJECT public: UbuntuProjectFile(UbuntuProject *parent, QString fileName); ~UbuntuProjectFile() {} bool save(QString *errorString, const QString &fileName, bool autoSave); QString fileName() const; void rename(const QString &newName); QString defaultPath() const; QString suggestedFileName() const; QString mimeType() const; bool isModified() const; bool isSaveAsAllowed() const; ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const; bool reload(QString *errorString, ReloadFlag flag, ChangeType); private: UbuntuProject *m_project; QString m_fileName; }; } } #endif // UBUNTUPROJECTFILE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectapp.cpp0000644000015301777760000003760412323167147027200 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuprojectapp.h" #include "ubuntushared.h" #include "ubuntuprojectapplicationwizard.h" #include "ubuntuconstants.h" #include "ubuntuproject.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuProjectApp::UbuntuProjectApp(QObject *parent) : QObject(parent) { m_bzrInfo.initialize(); } Core::GeneratedFiles UbuntuProjectApp::generateFiles(const QWizard *w, QString *errorMessage) { Q_UNUSED(errorMessage); QByteArray contents; Core::GeneratedFiles files; QJsonValue tmp_type = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_TYPE)); QString projectType = QLatin1String(Constants::UBUNTU_QMLPROJECT_TYPE); if (tmp_type.isUndefined() == false) { projectType = tmp_type.toString(); } setProjectType(projectType); QJsonValue tmp_hasTests = m_obj.value(QLatin1String(Constants::UBUNTU_HAS_TESTS)); bool hasTests = false; if (tmp_hasTests.isUndefined() == false) { hasTests = tmp_hasTests.toBool(); } const UbuntuProjectApplicationWizardDialog *wizard = qobject_cast(w); const QString projectName = wizard->projectName(); const QString projectPath = wizard->path() + QLatin1Char('/') + projectName; QString folder; QJsonValue tmp_folder = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_FOLDER)); if (tmp_folder.isUndefined() == false) { folder = tmp_folder.toString(); } if (m_projectType == QLatin1String(Constants::UBUNTU_QMLPROJECT_TYPE) || m_projectType == QLatin1String(Constants::UBUNTU_AUTOPILOTPROJECT_TYPE) || m_projectType == QLatin1String(Constants::UBUNTU_HTMLPROJECT_TYPE) || m_projectType == QLatin1String(Constants::UBUNTU_UBUNTUPROJECT_TYPE)) { const QString creatorFileName = Core::BaseFileWizard::buildFileName(projectPath, projectName, m_projectType); QString mainFileName; // load the mainFile if (m_projectType == QLatin1String(Constants::UBUNTU_HTMLPROJECT_TYPE)) { mainFileName = Core::BaseFileWizard::buildFileName(projectPath + QLatin1String("/www"), QLatin1String("index"), QLatin1String("html")); } else { mainFileName = Core::BaseFileWizard::buildFileName(projectPath, projectName, QLatin1String(Constants::UBUNTU_QML_TYPE)); } QJsonValue tmp_mainFile = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_MAINFILE)); if (tmp_mainFile.isUndefined() == false && tmp_folder.isUndefined() == false) { QString errorMsg; QString fileName = tmp_mainFile.toString(); if (readFile(QString(QLatin1String("%0/%1")).arg(UbuntuProjectApplicationWizard::templatesPath(folder)).arg(fileName),&contents, &errorMsg) == false) { contents = errorMsg.toAscii(); qDebug() << __PRETTY_FUNCTION__ << contents; } } contents = processReservedWords(contents,projectPath,projectName); mainFileName = processReservedWordsInFileName(mainFileName,projectName); Core::GeneratedFile generatedMainFile(mainFileName); generatedMainFile.setContents(QString::fromLatin1(contents)); generatedMainFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute); // create the project file QByteArray projectContents; { QTextStream out(&projectContents); QDeclarativeEngine engine; // QQmlEngine engine; out << "/* File generated by Qt Creator (with Ubuntu Plugin), version " << Core::Constants::IDE_VERSION_LONG << " */" << endl << endl << "import QmlProject 1.1" << endl << endl << "Project {" << endl << " mainFile: \"" << QDir(projectPath).relativeFilePath(mainFileName) << '"' << endl << endl << " /* Include .qml, .js, and image files from current directory and subdirectories */" << endl << " QmlFiles {" << endl << " directory: \".\"" << endl << " }" << endl << " JavaScriptFiles {" << endl << " directory: \".\"" << endl << " }" << endl << " ImageFiles {" << endl << " directory: \".\"" << endl << " }" << endl << " Files {" << endl << " filter: \"*.desktop\"" << endl << " }" << endl << " Files {" << endl << " filter: \"www/*.html\"" << endl << " }" << endl << " Files {" << endl << " filter: \"Makefile\"" << endl << " }" << endl; out << " Files {" << endl << " directory: \"www\"" << endl << " filter: \"*\"" << endl << " }" << endl; out << " Files {" << endl << " directory: \"www/img/\"" << endl << " filter: \"*\"" << endl << " }" << endl; out << " Files {" << endl << " directory: \"www/css/\"" << endl << " filter: \"*\"" << endl << " }" << endl; out << " Files {" << endl << " directory: \"www/js/\"" << endl << " filter: \"*\"" << endl << " }" << endl; out << " Files {" << endl << " directory: \"tests/\"" << endl << " filter: \"*\"" << endl << " }" << endl; // } out << " Files {" << endl << " directory: \"debian\"" << endl << " filter: \"*\"" << endl << " }" << endl << " /* List of plugin directories passed to QML runtime */" << endl << " importPaths: [ \".\" ,\"" // FIX ME: use QQmlEngine instead of QDeclarativeEngine. Then remove the replace. << engine.importPathList().join(QLatin1String("\",\"")).replace(QLatin1String("imports"),QLatin1String("qml")) << "\" ]" << endl << "}" << endl; } setProjectFileName(creatorFileName); Core::GeneratedFile generatedCreatorFile(creatorFileName); generatedCreatorFile.setContents(QLatin1String(projectContents)); generatedCreatorFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute); // add created files files.append(generatedMainFile); files.append(generatedCreatorFile); } else { const bool isCMakeProject = (m_projectType == QLatin1String(Constants::UBUNTU_CMAKEPROJECT_TYPE)); QString errorMsg; QJsonValue tmp_mainFile = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_MAINFILE)); if (tmp_mainFile.isUndefined() == false) { QString fileName_target = Core::BaseFileWizard::buildFileName(projectPath, tmp_mainFile.toString(),QString()); QString fileName_source = tmp_mainFile.toString(); if (readFile(QString(QLatin1String("%0/%1")).arg(UbuntuProjectApplicationWizard::templatesPath(folder)).arg(fileName_source),&contents, &errorMsg) == false) { contents = errorMsg.toAscii(); qDebug() << __PRETTY_FUNCTION__ << contents; } contents = processReservedWords(contents,projectPath,projectName); fileName_target = processReservedWordsInFileName(fileName_target,projectName); Core::GeneratedFile generatedMainFile(fileName_target); generatedMainFile.setContents(QLatin1String(contents)); generatedMainFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute); files.append(generatedMainFile); } QJsonValue tmp_projectFile = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_PROJECTFILE)); if (tmp_projectFile.isUndefined() == false) { QString fileName_target = isCMakeProject ? QString::fromLatin1("%0/CMakeLists.txt").arg(projectPath) : Core::BaseFileWizard::buildFileName(projectPath, QString(QLatin1String("%0.%1")).arg(projectName).arg(QLatin1String(Constants::UBUNTU_QTPROJECT_TYPE)),QString()); QString fileName_source = tmp_projectFile.toString(); if (readFile(QString(QLatin1String("%0/%1")).arg(UbuntuProjectApplicationWizard::templatesPath(folder)).arg(fileName_source),&contents, &errorMsg) == false) { contents = errorMsg.toAscii(); qDebug() << __PRETTY_FUNCTION__ << contents; } contents = processReservedWords(contents,projectPath,projectName); fileName_target = processReservedWordsInFileName(fileName_target,projectName); setProjectFileName(fileName_target); Core::GeneratedFile generatedCreatorFile(fileName_target); generatedCreatorFile.setContents(QLatin1String(contents)); generatedCreatorFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute); files.append(generatedCreatorFile); } } // create and add the other files QJsonValue tmp = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_FILES)); if (tmp.isUndefined() == false && tmp.isArray() ) { QJsonArray jsonFiles = tmp.toArray(); for (int idx = 0; idx < jsonFiles.size(); idx++) { QJsonValue tmp_value = jsonFiles.at(idx); if (tmp_value.isObject()) { QJsonValue tmp_fileName = tmp_value.toObject().value(QLatin1String(Constants::UBUNTU_PROJECTJSON_FILENAME)); if (tmp_fileName.isUndefined() == false) { QString fileName = tmp_fileName.toString(); QString errorMsg; QByteArray contents; if (readFile(QString(QLatin1String("%0/%1")).arg(UbuntuProjectApplicationWizard::templatesPath(folder)).arg(fileName),&contents, &errorMsg) == false) { contents = errorMsg.toAscii(); qDebug() << __PRETTY_FUNCTION__ << contents; } else { contents = processReservedWords(contents,projectPath,projectName); fileName = processReservedWordsInFileName(fileName,projectName); Core::GeneratedFile generatedFile(Core::BaseFileWizard::buildFileName(projectPath,fileName,QString())); generatedFile.setBinaryContents(contents); files.append(generatedFile); } } } } } return files; } QByteArray UbuntuProjectApp::processReservedWordsInFileName(QByteArray data, QString projectName) { data = data.replace(Constants::UBUNTU_FILENAME_DISPLAYNAME_UPPER,projectName.toUpper().toLatin1()); data = data.replace(Constants::UBUNTU_FILENAME_DISPLAYNAME_LOWER,projectName.toLower().toLatin1()); data = data.replace(Constants::UBUNTU_FILENAME_DISPLAYNAME_CAPITAL,Utils::matchCaseReplacement(QLatin1String("Capitalize"),projectName).toLatin1()); data = data.replace(Constants::UBUNTU_FILENAME_DISPLAYNAME,projectName.toLatin1()); return data; } QByteArray UbuntuProjectApp::processReservedWords(QByteArray data, QString projectPath, QString projectName) { QString folderName = QFileInfo(projectPath).baseName(); data = data.replace(Constants::UBUNTU_ACTION_FOLDERNAME,folderName.toLatin1()); data = data.replace(Constants::UBUNTU_ACTION_DISPLAYNAME_LOWER,projectName.toLower().toLatin1()); data = data.replace(Constants::UBUNTU_ACTION_DISPLAYNAME_UPPER,projectName.toUpper().toLatin1()); data = data.replace(Constants::UBUNTU_ACTION_DISPLAYNAME_CAPITAL,Utils::matchCaseReplacement(QLatin1String("Capitalize"),projectName).toLatin1()); data = data.replace(Constants::UBUNTU_ACTION_DISPLAYNAME,projectName.toLatin1()); data = data.replace(Constants::UBUNTU_ACTION_BZR_USERNAME,m_bzrInfo.launchpadId().toLatin1()); data = data.replace(Constants::UBUNTU_ACTION_SHAREDIRECTORY,Constants::UBUNTU_SHAREPATH.toLatin1()); return data; } /*! Initializes a Core::IWizard with the internal Ubuntu parameters */ void UbuntuProjectApp::setupParameters(QJsonObject params, Core::IWizard* wizard) { QString displayName, id, description, category, displayCategory; category = QLatin1String(Ubuntu::Constants::UBUNTU_PROJECT_WIZARD_CATEGORY); displayCategory = QLatin1String(Ubuntu::Constants::UBUNTU_PROJECT_WIZARD_CATEGORY_DISPLAY); QJsonValue tmp = params.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_DISPLAYNAME)); if (tmp.isUndefined() == false) { displayName = tmp.toString(); } tmp = params.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_ID)); if (tmp.isUndefined() == false) { id = tmp.toString(); } tmp = params.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_DESCRIPTION)); if (tmp.isUndefined() == false) { description = tmp.toString(); } tmp = params.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_CATEGORY)); if (tmp.isUndefined() == false) { category = tmp.toString(); } tmp = params.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_CATEGORY_DISPLAY)); if (tmp.isUndefined() == false) { displayCategory = tmp.toString(); } wizard->setIcon(QIcon(QLatin1String(QtSupport::Constants::QML_WIZARD_ICON))); wizard->setDisplayName(displayName); wizard->setId(id); wizard->setWizardKind(Core::IWizard::ProjectWizard); wizard->setFlags(Core::IWizard::PlatformIndependent); wizard->setDescription(description); wizard->setCategory(category); wizard->setDisplayCategory(displayCategory); } Core::Feature UbuntuProjectApp::requiredFeature() { QJsonValue tmp_feature = m_obj.value(QLatin1String(Constants::UBUNTU_PROJECTJSON_REQUIRED_FEATURE)); QString feature; if (tmp_feature.isUndefined() == false) { feature = tmp_feature.toString(); } if (!feature.isEmpty()) { return Core::Feature(feature.toLatin1().constData()); } return Core::Feature(0); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/UbuntuProject.mimetypes.xml0000644000015301777760000000052612323167147030421 0ustar pbusernogroup00000000000000 Ubuntu Project file qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuversion.cpp0000644000015301777760000000540612323167147026511 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuversion.h" #include #include using namespace Ubuntu::Internal; UbuntuVersion::UbuntuVersion() { QFile lsbRelease(QLatin1String(Constants::LSB_RELEASE)); if (lsbRelease.open(QIODevice::ReadOnly)) { QByteArray data = lsbRelease.readAll(); lsbRelease.close(); foreach(QString line, QString::fromLatin1(data).split(QLatin1String("\n"))) { if (line.startsWith(QLatin1String(Constants::DISTRIB_ID))) { m_id = line.replace(QLatin1String(Constants::DISTRIB_ID),QLatin1String("")); } else if (line.startsWith(QLatin1String(Constants::DISTRIB_RELEASE))) { m_release = line.replace(QLatin1String(Constants::DISTRIB_RELEASE),QLatin1String("")); } else if (line.startsWith(QLatin1String(Constants::DISTRIB_CODENAME))) { m_codename = line.replace(QLatin1String(Constants::DISTRIB_CODENAME),QLatin1String("")); } else if (line.startsWith(QLatin1String(Constants::DISTRIB_DESCRIPTION))) { m_description = line.replace(QLatin1String(Constants::DISTRIB_DESCRIPTION),QLatin1String("")); } } } } Core::FeatureSet UbuntuVersion::features() { Core::FeatureSet retval; if (codename()==QLatin1String(Constants::PRECISE)) { retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_PRECISE); } else if (codename()==QLatin1String(Constants::QUANTAL)) { retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_QUANTAL); } else if (codename()==QLatin1String(Constants::RARING)) { retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_RARING); } else if (codename()==QLatin1String(Constants::SAUCY)) { retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_SAUCY); retval |= Core::FeatureSet(Constants::FEATURE_UNITY_SCOPE); } else if (codename()==QLatin1String(Constants::TRUSTY)) { retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_TRUSTY); retval |= Core::FeatureSet(Constants::FEATURE_UNITY_SCOPE); } return retval; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectnode.h0000644000015301777760000000616312323167147027006 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROJECTNODE_H #define UBUNTUPROJECTNODE_H #include #include "ubuntuproject.h" #include "ubuntuprojectmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuProject; class UbuntuProjectNode : public ProjectExplorer::ProjectNode { Q_OBJECT public: UbuntuProjectNode(UbuntuProject *project, Core::IDocument *projectFile); Core::IDocument *projectFile() const; QString projectFilePath() const; virtual bool hasBuildTargets() const; virtual QList supportedActions(Node *node) const; virtual bool canAddSubProject(const QString &proFilePath) const; virtual bool addSubProjects(const QStringList &proFilePaths); virtual bool removeSubProjects(const QStringList &proFilePaths); virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0); virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0); virtual bool deleteFiles(const QStringList &filePaths); virtual bool renameFile(const QString &filePath, const QString &newFilePath); virtual QList runConfigurationsFor(Node *node); void refresh(); private: FolderNode *findOrCreateFolderByName(const QString &filePath); FolderNode *findOrCreateFolderByName(const QStringList &components, int end); private: UbuntuProject *m_project; Core::IDocument *m_projectFile; QHash m_folderByName; }; } } #endif // UBUNTUPROJECTNODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubunturemoteruncontrolfactory.h0000644000015301777760000000437112323167147031502 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTURUNCONTROLFACTORY_H #define UBUNTURUNCONTROLFACTORY_H #include #include "ubuntuproject.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { class UbuntuRemoteRunControlFactory : public ProjectExplorer::IRunControlFactory { Q_OBJECT public: explicit UbuntuRemoteRunControlFactory() = default; virtual ~UbuntuRemoteRunControlFactory() {} bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode) const; ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode, QString *errorMessage); QString displayName() const; }; } } #endif // UBUNTURUNCONTROLFACTORY_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupackagingwidget.cpp0000644000015301777760000006340612323167147030160 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntupackagingwidget.h" #include "ubuntusecuritypolicypickerdialog.h" #include "ui_ubuntupackagingwidget.h" #include "ubuntuconstants.h" #include "ubuntumenu.h" #include "ubuntuclicktool.h" #include "ubuntucmakemakestep.h" #include "ubuntuvalidationresultmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Ubuntu; using namespace Ubuntu::Internal; UbuntuPackagingWidget::UbuntuPackagingWidget(QWidget *parent) : QWidget(parent), ui(new Ui::UbuntuPackagingWidget) { m_previous_tab = 0; ui->setupUi(this); ui->groupBoxPackaging->hide(); ui->groupBoxValidate->hide(); ui->tabWidget->setCurrentIndex(0); ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu); m_inputParser = new ClickRunChecksParser(this); m_validationModel = new UbuntuValidationResultModel(this); connect(m_inputParser,&ClickRunChecksParser::parsedNewTopLevelItem ,m_validationModel,&UbuntuValidationResultModel::appendItem); ui->treeViewValidate->setModel(m_validationModel); connect(&m_bzr,SIGNAL(initializedChanged()),SLOT(bzrChanged())); connect(&m_manifest,SIGNAL(loaded()),SLOT(reload())); connect(&m_apparmor,SIGNAL(loaded()),SLOT(reload())); connect(&m_ubuntuProcess,SIGNAL(started(QString)),this,SLOT(onStarted(QString))); connect(&m_ubuntuProcess,SIGNAL(message(QString)),this,SLOT(onMessage(QString))); connect(&m_ubuntuProcess,SIGNAL(finished(QString,int)),this,SLOT(onFinished(QString, int))); connect(&m_ubuntuProcess,SIGNAL(error(QString)),this,SLOT(onError(QString))); connect(ui->treeViewValidate->selectionModel(),SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(onValidationItemSelected(QModelIndex))); connect(m_validationModel,SIGNAL(rowsInserted(QModelIndex,int,int)),this,SLOT(onNewValidationData())); m_bzr.initialize(); ui->comboBoxFramework->blockSignals(true); ui->comboBoxFramework->addItems(UbuntuClickTool::getSupportedFrameworks()); ui->comboBoxFramework->blockSignals(false); m_reviewToolsInstalled = false; checkClickReviewerTool(); } UbuntuPackagingWidget::~UbuntuPackagingWidget() { autoSave(); delete ui; clearAdditionalBuildSteps(); } void UbuntuPackagingWidget::onFinishedAction(const QProcess *proc, QString cmd) { disconnect(m_UbuntuMenu_connection); if (!m_reviewToolsInstalled) return; ProjectExplorer::Project* startupProject = ProjectExplorer::SessionManager::startupProject(); QString sClickPackageName; QString sClickPackagePath; sClickPackageName = QString::fromLatin1("%0_%1_all.click").arg(ui->lineEdit_name->text()).arg(ui->lineEdit_version->text()); sClickPackagePath = startupProject->projectDirectory(); QRegularExpression re(QLatin1String("\\/\\w+$")); // search for the project name in the path QRegularExpressionMatch match = re.match(sClickPackagePath); if (match.hasMatch()) { QString matched = match.captured(0); sClickPackagePath.chop(matched.length()-1); //leave the slash } sClickPackagePath.append(sClickPackageName); m_ubuntuProcess.stop(); if (sClickPackagePath.isEmpty()) return; qDebug()<<"Going to verify: "<treeViewValidate->selectionModel()->hasSelection()) { QModelIndex index = m_validationModel->findFirstErrorItem(); ui->treeViewValidate->setCurrentIndex(index); } } void UbuntuPackagingWidget::onValidationItemSelected(const QModelIndex &index) { if(index.isValid()) { QUrl link = m_validationModel->data(index,UbuntuValidationResultModel::LinkRole).toUrl(); if(link.isValid()) { ui->labelErrorLink->setText( QString::fromLatin1(Constants::UBUNTUPACKAGINGWIDGET_CLICK_REVIEWER_TOOLS_LINK_DISPLAYTEXT) .arg(link.toString(QUrl::FullyEncoded))); } else { ui->labelErrorLink->setText(QLatin1String("")); } ui->labelErrorType->setText(m_validationModel->data(index,UbuntuValidationResultModel::TypeRole).toString()); ui->plainTextEditDescription->setPlainText(m_validationModel->data(index,UbuntuValidationResultModel::DescriptionRole).toString()); } } void UbuntuPackagingWidget::onMessage(QString msg) { m_reply.append(msg); m_inputParser->addRecievedData(msg); } void UbuntuPackagingWidget::onFinished(QString cmd, int code) { Q_UNUSED(code); m_inputParser->endRecieveData(); if (cmd == QString::fromLatin1(Constants::UBUNTUWIDGETS_ONFINISHED_SCRIPT_LOCAL_PACKAGE_INSTALLED).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH)) { m_validationModel->clear(); QStringList lines = m_reply.trimmed().split(QLatin1String(Constants::LINEFEED)); QSettings settings(QLatin1String(Constants::SETTINGS_COMPANY), QLatin1String(Constants::SETTINGS_PRODUCT)); settings.beginGroup(QLatin1String(Constants::SETTINGS_GROUP_CLICK)); foreach(QString line, lines) { line = line.trimmed(); if (line.isEmpty()) { continue; } if (line.startsWith(QLatin1String(Constants::UBUNTUDEVICESWIDGET_ONFINISHED_LOCAL_NO_EMULATOR_INSTALLED))) { // There is no click reviewer tool installed m_reviewToolsInstalled = false; ui->groupBoxValidate->hide(); settings.setValue(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS_LOCATION), QLatin1String(Constants::EMPTY)); settings.setValue(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS), Constants::SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS); emit reviewToolsInstalledChanged(m_reviewToolsInstalled); } else { QStringList lineData = line.split(QLatin1String(Constants::SPACE)); QString sReviewerToolPackageStatus = lineData.takeFirst(); QString sReviewerToolPackageName = lineData.takeFirst(); QString sReviewerToolPackageVersion = lineData.takeFirst(); if (sReviewerToolPackageStatus.startsWith(QLatin1String(Constants::INSTALLED))) { // There is click reviewer tool installed ui->groupBoxValidate->show(); m_reviewToolsInstalled = true; settings.setValue(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS_LOCATION), QLatin1String(Constants::SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS_LOCATION)); settings.setValue(QLatin1String(Constants::SETTINGS_KEY_CLICK_REVIEWERSTOOLS), Constants::SETTINGS_CLICK_REVIEWERSTOOLS_TRUE); emit reviewToolsInstalledChanged(m_reviewToolsInstalled); } } } } m_reply.clear(); } void UbuntuPackagingWidget::onError(QString msg) { if(msg.isEmpty()) return; m_inputParser->emitTextItem(QLatin1String("Error"),msg,ClickRunChecksParser::Error); } void UbuntuPackagingWidget::onStarted(QString cmd) { m_validationModel->clear(); m_inputParser->emitTextItem(QLatin1String("Start Command"),cmd,ClickRunChecksParser::NoIcon); } void UbuntuPackagingWidget::setAvailable(bool available) { if (available) { ui->groupBoxPackaging->setVisible(true); } else { ui->groupBoxPackaging->setVisible(false); } } bool UbuntuPackagingWidget::reviewToolsInstalled() { return m_reviewToolsInstalled; } UbuntuClickManifest *UbuntuPackagingWidget::manifest() { return &m_manifest; } UbuntuClickManifest *UbuntuPackagingWidget::appArmor() { return &m_apparmor; } void UbuntuPackagingWidget::on_pushButtonReviewersTools_clicked() { ProjectExplorer::Project* startupProject = ProjectExplorer::SessionManager::startupProject(); m_ubuntuProcess.stop(); QString directory = QDir::homePath(); if(startupProject) directory = startupProject->projectDirectory(); QString clickPackage = QFileDialog::getOpenFileName(this,QString(QLatin1String(Constants::UBUNTU_CLICK_PACKAGE_SELECTOR_TEXT)),QString(QLatin1String("%0/..")).arg(directory),QLatin1String(Constants::UBUNTU_CLICK_PACKAGE_MASK)); if (clickPackage.isEmpty()) return; m_ubuntuProcess.append(QStringList() << QString::fromLatin1(Constants::SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS_LOCATION).arg(clickPackage)); m_ubuntuProcess.start(QString(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_CLICK_REVIEWER_TOOLS_AGAINST_PACKAGE)).arg(clickPackage)); } void UbuntuPackagingWidget::autoSave() { save((ui->tabWidget->currentWidget() == ui->tabSimple)); } bool UbuntuPackagingWidget::openManifestForProject() { ProjectExplorer::Project* startupProject = ProjectExplorer::SessionManager::startupProject(); if (startupProject) { m_projectName = startupProject->displayName(); m_projectDir = startupProject->projectDirectory(); QString fileName = QString(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_OPENMANIFEST)).arg(startupProject->projectDirectory()); QString no_underscore_displayName = startupProject->displayName(); m_projectName=no_underscore_displayName; no_underscore_displayName.replace(QLatin1String(Constants::UNDERLINE),QLatin1String(Constants::DASH)); if (no_underscore_displayName != startupProject->displayName()) { m_manifest.nameDashReplaced(); } QString defaultAppArmorName = QString(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_APPARMOR)) .arg(startupProject->projectDirectory()) .arg(no_underscore_displayName); if (QFile(fileName).exists()==false) { m_manifest.setFileName(fileName); m_apparmor.setFileName(defaultAppArmorName); on_pushButtonReset_clicked(); } else { load_manifest(fileName); } //we just support the first hook for now //@TODO proper support for multiple hooks QList hooks = m_manifest.hooks(); QString fileAppArmorName; if(hooks.isEmpty()) fileAppArmorName = defaultAppArmorName; else fileAppArmorName = QString(QLatin1String("%1/%2")).arg(startupProject->projectDirectory()).arg(hooks[0].appArmorFile); if (QFile(fileAppArmorName).exists()==false) { m_apparmor.setFileName(fileAppArmorName); on_pushButtonReset_clicked(); } else { load_apparmor(fileAppArmorName); } load_excludes(QString(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_EXCLUDES)).arg(startupProject->projectDirectory())); return true; } else { m_projectName.clear(); m_projectDir.clear(); } return false; } void UbuntuPackagingWidget::bzrChanged() { // left empty on purpose m_manifest.setMaintainer(m_bzr.whoami()); QString userName = m_bzr.launchpadId(); if (userName.isEmpty()) userName = QLatin1String(Constants::USERNAME); // Commented out for bug #1219948 - https://bugs.launchpad.net/qtcreator-plugin-ubuntu/+bug/1219948 //m_manifest.setName(QString(QLatin1String("com.ubuntu.developer.%0.%1")).arg(userName).arg(m_projectName)); reload(); } void UbuntuPackagingWidget::on_pushButtonReset_clicked() { QString fileName = m_manifest.fileName(); QString fileAppArmorName = m_apparmor.fileName(); load_manifest(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_DEFAULT_MANIFEST)); load_apparmor(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_DEFAULT_MYAPP)); m_manifest.setFileName(fileName); QDir projectDir(m_projectDir); if(fileAppArmorName.isEmpty() || !QFile::exists(fileAppArmorName)) { fileAppArmorName = m_manifest.appArmorFileName(m_manifest.hooks()[0].appId); fileAppArmorName = projectDir.absoluteFilePath(fileAppArmorName); } else { m_manifest.setAppArmorFileName(m_manifest.hooks()[0].appId,projectDir.relativeFilePath(fileAppArmorName)); } m_apparmor.setFileName(fileAppArmorName); m_apparmor.save(); m_manifest.setMaintainer(m_bzr.whoami()); QString userName = m_bzr.launchpadId(); if (userName.isEmpty()) userName = QLatin1String(Constants::USERNAME); m_manifest.setName(QString(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_DEFAULT_NAME)).arg(userName).arg(m_projectName)); m_manifest.save(); reload(); } void UbuntuPackagingWidget::save(bool bSaveSimple) { Q_UNUSED(bSaveSimple); switch (m_previous_tab) { case 0: { // set package name to lower, bug #1219877 m_manifest.setName(ui->lineEdit_name->text().toLower()); m_manifest.setMaintainer(ui->lineEdit_maintainer->text()); m_manifest.setVersion(ui->lineEdit_version->text()); m_manifest.setTitle(ui->lineEdit_title->text()); m_manifest.setDescription(ui->lineEdit_description->text()); if(ui->comboBoxFramework->currentText() != tr(Constants::UBUNTU_UNKNOWN_FRAMEWORK_NAME)) m_manifest.setFrameworkName(ui->comboBoxFramework->currentText()); QStringList items; for (int i=0; ilistWidget->count(); i++) { // Fix bug #1221407 - make sure that there are no empty policy groups. QString policyGroup = ui->listWidget->item(i)->text().trimmed(); if (!policyGroup.isEmpty()) { items.append(ui->listWidget->item(i)->text()); } } m_apparmor.setPolicyGroups(m_projectName,items); m_manifest.save(); m_apparmor.save(); save_excludes(); break; } case 1: { m_manifest.setRaw(ui->plainTextEditJson->toPlainText()); QList hooks = m_manifest.hooks(); if(hooks.size()) { QString appArmorFileName = hooks[0].appArmorFile; appArmorFileName = QString(QLatin1String("%1/%2")) .arg(m_projectDir) .arg(appArmorFileName); if (appArmorFileName != m_apparmor.fileName()) { if(!QFile::exists(appArmorFileName)) { load_apparmor(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_DEFAULT_MYAPP)); m_apparmor.setFileName(appArmorFileName); } else { load_apparmor(appArmorFileName); } } } m_manifest.save(); break; } case 2: { m_apparmor.setRaw(ui->plainTextEditAppArmorJson->toPlainText()); m_apparmor.save(); break; } case 3: { save_excludes(); break; } } } void UbuntuPackagingWidget::load_manifest(QString fileName) { m_manifest.load(fileName,m_projectName); // Commented out for bug #1274265 https://bugs.launchpad.net/qtcreator-plugin-ubuntu/+bug/1274265 //m_manifest.setMaintainer(m_bzr.whoami()); QString userName = m_bzr.launchpadId(); if (userName.isEmpty()) userName = QLatin1String(Constants::USERNAME); m_projectName.replace(QLatin1String(Constants::UNDERLINE),QLatin1String(Constants::DASH)); // Commented out for bug #1219948 - https://bugs.launchpad.net/qtcreator-plugin-ubuntu/+bug/1219948 //m_manifest.setName(QString(QLatin1String("com.ubuntu.developer.%0.%1")).arg(userName).arg(m_projectName)); } void UbuntuPackagingWidget::load_apparmor(QString fileAppArmorName) { m_apparmor.load(fileAppArmorName,m_projectName); } void UbuntuPackagingWidget::load_excludes(QString excludesFile) { if (!excludesFile.isEmpty()) m_excludesFile = excludesFile; QFile f(m_excludesFile); if (f.exists()) { if (f.open(QIODevice::ReadOnly)) { ui->plainTextEdit_excludes->setPlainText(QString::fromAscii(f.readAll())); f.close(); } } } void UbuntuPackagingWidget::save_excludes() { QFile f(m_excludesFile); if (f.open(QIODevice::WriteOnly)) { f.write(ui->plainTextEdit_excludes->toPlainText().toAscii()); f.close(); } } void UbuntuPackagingWidget::reload() { ui->lineEdit_maintainer->setText(m_manifest.maintainer()); ui->lineEdit_name->setText(m_manifest.name()); ui->lineEdit_title->setText(m_manifest.title()); ui->lineEdit_version->setText(m_manifest.version()); ui->lineEdit_description->setText(m_manifest.description()); int idx = ui->comboBoxFramework->findText(m_manifest.frameworkName()); //disable the currentIndexChanged signal, reloading the files //should never change the contents of the files (e.g. policy_version) ui->comboBoxFramework->blockSignals(true); //if the framework name is not valid set to empty item //just some data to easily find the unknown framework item without //using string compare if(idx < 0) { if(ui->comboBoxFramework->findData(Constants::UBUNTU_UNKNOWN_FRAMEWORK_DATA) < 0) ui->comboBoxFramework->addItem(tr(Constants::UBUNTU_UNKNOWN_FRAMEWORK_NAME),Constants::UBUNTU_UNKNOWN_FRAMEWORK_DATA); ui->comboBoxFramework->setCurrentIndex(ui->comboBoxFramework->count()-1); } else { ui->comboBoxFramework->setCurrentIndex(idx); ui->comboBoxFramework->removeItem(ui->comboBoxFramework->findData(Constants::UBUNTU_UNKNOWN_FRAMEWORK_DATA)); } ui->comboBoxFramework->blockSignals(false); QStringList policyGroups = m_apparmor.policyGroups(m_projectName); ui->listWidget->clear(); foreach( QString policy, policyGroups) { QListWidgetItem* item = new QListWidgetItem(policy); item->setFlags(item->flags() | Qt::ItemIsEditable); ui->listWidget->addItem(item); } ui->plainTextEditJson->setPlainText(m_manifest.raw()); ui->plainTextEditAppArmorJson->setPlainText(m_apparmor.raw()); load_excludes(QLatin1String(Constants::EMPTY)); } void UbuntuPackagingWidget::on_tabWidget_currentChanged(int tab) { save((ui->tabWidget->currentWidget() != ui->tabSimple)); m_previous_tab = tab; reload(); } void UbuntuPackagingWidget::on_pushButtonReload_clicked() { m_manifest.reload(); m_apparmor.reload(); } void UbuntuPackagingWidget::on_listWidget_customContextMenuRequested(QPoint p) { if (ui->listWidget->selectedItems().count()==0) { return; } QMenu contextMenu; contextMenu.addAction(QLatin1String(Constants::UBUNTUPACKAGINGWIDGET_MENU_REMOVE)); QAction* selectedItem = contextMenu.exec(ui->listWidget->mapToGlobal(p)); if (selectedItem) { delete ui->listWidget->currentItem(); } } void UbuntuPackagingWidget::on_pushButton_addpolicy_clicked() { UbuntuSecurityPolicyPickerDialog dialog; if (dialog.exec()) { ui->listWidget->addItems(dialog.selectedPolicyGroups()); } } void UbuntuPackagingWidget::on_pushButtonClickPackage_clicked() { ProjectExplorer::Project* project = ProjectExplorer::SessionManager::startupProject(); if(!project) return; if(project->projectManager()->mimeType() == QLatin1String(CMakeProjectManager::Constants::CMAKEMIMETYPE)) { ProjectExplorer::Target* target = project->activeTarget(); if(!target) return; ProjectExplorer::Kit* k = target->kit(); if(!k) return; if(ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(k) != Ubuntu::Constants::UBUNTU_DEVICE_TYPE_ID) { QMessageBox::warning(this,tr("Wrong kit type"),tr("It is not supported to create click packages for a non UbuntuSDK target")); return; } ProjectExplorer::BuildConfiguration* bc = target->activeBuildConfiguration(); if(!bc) return; if(!bc->isEnabled()) { QString disabledReason = bc->disabledReason(); QMessageBox::information(this,tr("Disabled"),tr("The currently selected Buildconfiguration is disabled. %1").arg(disabledReason)); return; } if(ProjectExplorer::BuildManager::isBuilding()) { QMessageBox::information(this,tr("Build running"),tr("There is currently a build running, please wait for it to be finished")); return; } clearAdditionalBuildSteps(); ProjectExplorer::BuildStepList* steps = bc->stepList(Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)); if(!steps || steps->isEmpty()) return; UbuntuCMakeDeployStep* deplStep = new UbuntuCMakeDeployStep(steps); m_additionalPackagingBuildSteps.append(deplStep); UbuntuClickPackageStep* package = new UbuntuClickPackageStep(steps); m_additionalPackagingBuildSteps.append(package); m_buildManagerConnection = connect(ProjectExplorer::BuildManager::instance(),SIGNAL(buildQueueFinished(bool)),this,SLOT(buildFinished(bool))); ProjectExplorer::BuildManager::buildList(steps,tr("Build Project")); ProjectExplorer::BuildManager::appendStep(deplStep,tr("Preparing Click package")); ProjectExplorer::BuildManager::appendStep(package ,tr("Creating Click package")); } else { m_UbuntuMenu_connection = QObject::connect(UbuntuMenu::instance(),SIGNAL(finished_action(const QProcess*,QString)),this,SLOT(onFinishedAction(const QProcess*,QString))); save((ui->tabWidget->currentWidget() == ui->tabSimple)); if(!m_UbuntuMenu_connection) qDebug()<<"Could not connect signals"; QAction* action = UbuntuMenu::menuAction(Core::Id(Constants::UBUNTUPACKAGINGWIDGET_BUILDPACKAGE_ID)); if(action) { action->trigger(); } } } void UbuntuPackagingWidget::checkClickReviewerTool() { m_ubuntuProcess.stop(); QString sReviewerPackageName = QLatin1String(Ubuntu::Constants::REVIEWER_PACKAGE_NAME); m_ubuntuProcess.append(QStringList() << QString::fromLatin1(Constants::UBUNTUWIDGETS_LOCAL_PACKAGE_INSTALLED_SCRIPT).arg(Ubuntu::Constants::UBUNTU_SCRIPTPATH).arg(sReviewerPackageName) << QApplication::applicationDirPath()); m_ubuntuProcess.start(QString::fromLatin1(Constants::UBUNTUPACKAGINGWIDGET_LOCAL_REVIEWER_INSTALLED)); } void UbuntuPackagingWidget::buildFinished(const bool success) { disconnect(m_buildManagerConnection); if (success) { UbuntuClickPackageStep *pckStep = qobject_cast(m_additionalPackagingBuildSteps.last()); if (pckStep && !pckStep->packagePath().isEmpty()) { m_ubuntuProcess.stop(); QString sClickPackagePath = pckStep->packagePath(); if (sClickPackagePath.isEmpty()) return; qDebug()<<"Going to verify: "<comboBoxFramework->itemText(index).startsWith(QLatin1String(Constants::UBUNTU_FRAMEWORK_14_04_BASENAME))) { ui->comboBoxFramework->removeItem(ui->comboBoxFramework->findData(Constants::UBUNTU_UNKNOWN_FRAMEWORK_DATA)); m_apparmor.setPolicyVersion(QLatin1String("1.1")); } else if(ui->comboBoxFramework->itemText(index).startsWith(QLatin1String(Constants::UBUNTU_FRAMEWORK_13_10_BASENAME))) { ui->comboBoxFramework->removeItem(ui->comboBoxFramework->findData(Constants::UBUNTU_UNKNOWN_FRAMEWORK_DATA)); m_apparmor.setPolicyVersion(QLatin1String("1.0")); } else { return; } m_apparmor.save(); } /*! * \brief UbuntuPackagingWidget::clearAdditionalBuildSteps * Clears the last used additional buildsteps * \note This will cancel a current build if its building the ProjectConfiguration * the BuildSteps belong to! */ void UbuntuPackagingWidget::clearAdditionalBuildSteps() { foreach(QPointer step,m_additionalPackagingBuildSteps) { if(step) { if(ProjectExplorer::BuildManager::isBuilding(step->projectConfiguration())) ProjectExplorer::BuildManager::cancel(); delete step.data(); } } m_additionalPackagingBuildSteps.clear(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuconstants.h0000644000015301777760000007507112323167147026512 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUCONSTANTS2_H #define UBUNTUCONSTANTS2_H #include #include namespace Ubuntu { namespace Constants { const char LINEFEED[] = "\n"; const char UNDERLINE[] = "_"; const char DASH[] = "-"; const char EMPTY[] = ""; const char SPACE[] = " "; const char TAB[] = " "; const char INSTALLED[] = "ii"; const char ZERO_STR[] = "0"; const char ONE_STR[] = "1"; const char USERNAME[] = "username"; const char UBUNTU_MIMETYPE_XML[] = ":/ubuntu/UbuntuProject.mimetypes.xml"; const char ERROR_MSG_FAILED_TO_READ_JSON[] = "failed to read from JSON."; const char UBUNTUDEVICESWIDGET_ONERROR[] = "

%0

"; const char UBUNTUDEVICESWIDGET_ACTION_BEGIN[] = "

%0

"; const char UBUNTUDEVICESWIDGET_ACTION_END[] = "

%0

"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVICESEARCH[] = "%0/device_search"; const char UBUNTUDEVICESWIDGET_ONFINISHED_LOCAL_NO_EMULATOR_INSTALLED[] = "The package is not installed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_ADB_REGEX[] = "(\\S+)\\s+(.*)"; const char UBUNTUDEVICESWIDGET_ONFINISHED_ADB_NOACCESS[] = "???"; const char UBUNTUDEVICESWIDGET_ONFINISHED_NO_DEVICE[] = " * there is no device connected."; const char UBUNTUDEVICESWIDGET_ONFINISHED_FOUND_DEVICES[] = " * found %0 devices."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVICEVERSION[] = "%0/device_version"; const char UBUNTUDEVICESWIDGET_ONFINISHED_DEVICEVERSION_DETECTED[] = "..device version detected."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_SSH_START[] = "%0/device_service_ssh_start"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SSH_WAS_STARTED[] = "..openssh-server was started."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_SSH_VERSION[] = "%0/openssh_version"; const char UBUNTUDEVICESWIDGET_ONFINISHED_NONE[] = "(none)"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SSH_IS_INSTALLED[] = "..openssh-server (%0) is installed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SSH_NOT_INSTALLED[] = "..openssh-server was not installed."; const int UBUNTUDEVICESWIDGET_DEVELOPERMODE_PAGE_ENABLED = 1; const int UBUNTUDEVICESWIDGET_DEVELOPERMODE_PAGE_DEVICEFOUND = 0; const int UBUNTUDEVICESWIDGET_DEVELOPERMODE_PAGE_NONETWORK = 2; const int UBUNTUDEVICESWIDGET_PAGE_EMULATOR_PACKAGE_CHECK = 0; const int UBUNTUDEVICESWIDGET_PAGE_EMULATOR_INSTANCES = 1; const int UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_NODEVICE_CONNECTED = 0; const int UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_DEVICE_CONNECTED = 1; const int UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_INFO = 0; const int UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONNECTIVITY_INPUT = 1; const int UBUNTUDEVICESWIDGET_PAGE_DEVICE_CONTROL_SIMPLE_TAB = 0; const char UBUNTUDEVICESWIDGET_ONFINISHED_UNABLE_TO_FETCH[] = "E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"; const char UBUNTUWIDGETS_ONFINISHED_SCRIPT_LOCAL_PACKAGE_INSTALLED[] = "%0/local_package_installed"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_INSTALL_EMULATOR[] = "%0/local_install_emulator"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_SEARCH_IMAGES[] = "%0/local_search_images"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_CREATE_EMULATOR[] = "%0/local_create_emulator"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_LOCAL_START_EMULATOR[] = "%0/local_start_emulator"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVICE_WRITABLE_SET[] = "%0/device_writableimage_set"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVICE_WRITABLE_UNSET[] = "%0/device_writableimage_unset"; const char UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLE_ENABLED[] = "..writable image has been enabled, device is rebooting."; const char UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLE_DISABLED[] = "..writable image has been disabled, device is rebooting."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVELOPERTOOLS_REMOVED[] = "%0/device_developertools_remove"; const char UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_REMOVED[] = "..developer tools have been removed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVELOPERTOOLS_HAS[] = "%0/device_developertools_has"; const char UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_NOT_INSTALLED[] = "..developer tools are not installed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_INSTALLED[] = "..developer tools are already installed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLE_HAS[] = "%0/device_writableimage_has"; const char UBUNTUDEVICESWIDGET_ONFINISHED_WRITABLEIMAGE[] = "..writable image."; const char UBUNTUDEVICESWIDGET_ONFINISHED_READONLYIMAGE[] = "..read-only image."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_DEVELOPERTOOLS_INSTALL[] = "%0/device_developertools_install"; const char UBUNTUDEVICESWIDGET_ONFINISHED_DEVELOPERTOOLS_WAS_INSTALLED[] = "..platform development was enabled."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_SSH_REMOVE[] = "%0/openssh_remove"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SSH_WAS_REMOVED[] = "..openssh-server was removed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_SSH_INSTALL[] = "%0/openssh_install"; const char UBUNTUDEVICESWIDGET_ONFINISHED_SSH_WAS_INSTALLED[] = "..openssh-server was installed."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_PORTFORWARD[] = "%0/device_portforward"; const char UBUNTUDEVICESWIDGET_ONFINISHED_PORTS_FORWARDED[] = "..ports forwarded."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_PUBLICKEY[] = "%0/openssh_publickey"; const char UBUNTUDEVICESWIDGET_ONFINISHED_PUBLICKEY_AUTH_SET[] = "..public key authentication is now set."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_NETWORKCLONE[] = "%0/device_network_clone"; const char UBUNTUDEVICESWIDGET_ONFINISHED_NETWORK_CONF_COPIED[] = "..network configuration copied."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_TIMECLONE[] = "%0/device_time_clone"; const char UBUNTUDEVICESWIDGET_ONFINISHED_TIME_CONF_COPIED[] = "..time configuration copied."; const char UBUNTUDEVICESWIDGET_ONFINISHED_SCRIPT_HASNETWORK[] = "%0/device_hasnetwork"; const char EMULATOR_PACKAGE_NAME[] = "ubuntu-emulator"; const char DEFAULT_EMULATOR_PATH[] = "ubuntu-emulator"; const char REVIEWER_PACKAGE_NAME[] = "click-reviewers-tools"; const char UBUNTUDEVICESWIDGET_LOCAL_EMULATOR_INSTALLED[] = "Checking installed emulator package."; const char UBUNTUDEVICESWIDGET_LABEL_EMULATOR_INFO[] = "The %0 version of the %1 emulator package is installed."; const char UBUNTUDEVICESWIDGET_INSTALL_EMULATOR_PACKAGE[] = "Install the emulator package on the system.."; const char UBUNTUDEVICESWIDGET_INSTALL_EMULATOR_PACKAGE_SCRIPT[] = "%0/local_install_emulator %1"; const char UBUNTUDEVICESWIDGET_LOCAL_SEARCH_IMAGES_SCRIPT[] = "%0/local_search_images"; const char UBUNTUDEVICESWIDGET_LOCAL_SEARCH_IMAGES[] = "Search configured emulator instances."; const char UBUNTUDEVICESWIDGET_LOCAL_CREATE_EMULATOR[] = "Creating new emulator instance."; const char UBUNTUDEVICESWIDGET_LOCAL_CREATE_EMULATOR_SCRIPT[] = "%0/local_create_emulator %1 %2"; const char UBUNTUDEVICESWIDGET_LOCAL_START_EMULATOR[] = "Starting the selected emulator."; const char UBUNTUDEVICESWIDGET_LOCAL_START_EMULATOR_SCRIPT[] = "%0/local_start_emulator %1"; const char UBUNTUDEVICESWIDGET_STARTSSHSERVICE[] = "Start ssh service on device.."; const char UBUNTUDEVICESWIDGET_STARTSSHSERVICE_SCRIPT[] = "%0/device_service_ssh_start %1"; const char UBUNTUDEVICESWIDGET_MAKEFSWRITABLE[] = "Make filesystem writable.."; const char UBUNTUDEVICESWIDGET_MAKEFSWRITABLE_SCRIPT[] = "%0/device_writableimage_set %1"; const char UBUNTUDEVICESWIDGET_MAKEFSREADONLY[] = "Make filesystem read-only.."; const char UBUNTUDEVICESWIDGET_MAKEFSREADONLY_SCRIPT[] = "%0/device_writableimage_unset %1"; const char UBUNTUDEVICESWIDGET_DETECTDEVELOPERTOOLS[] = "Are developer tools installed.."; const char UBUNTUDEVICESWIDGET_DETECTDEVELOPERTOOLS_SCRIPT[] = "%0/device_developertools_has %1"; const char UBUNTUDEVICESWIDGET_DETECTWRITABLEIMAGE[] = "Is device image read-only or writable.."; const char UBUNTUDEVICESWIDGET_DETECTWRITABLEIMAGE_SCRIPT[] = "%0/device_writableimage_has %1"; const char UBUNTUDEVICESWIDGET_DISABLEPLATFORMDEVELOPMENT[] = "Disable Platform Development.."; const char UBUNTUDEVICESWIDGET_DISABLEPLATFORMDEVELOPMENT_SCRIPT[] = "%0/device_developertools_remove %1"; const char UBUNTUDEVICESWIDGET_ENABLEPLATFORMDEVELOPMENT[] = "Enable Platform Development.."; const char UBUNTUDEVICESWIDGET_ENABLEPLATFORMDEVELOPMENT_SCRIPT[] = "%0/device_developertools_install %1"; const char UBUNTUPROJECT_MIMETYPE[] = "application/x-ubuntuproject"; const char UBUNTUPROJECT_ID[] = "UbuntuProjectManager.UbuntuProject"; const char UBUNTUPROJECT_PROJECTCONTEXT[] = "UbuntuProject.ProjectContext"; const char UBUNTUPROJECT_SUFFIX[] = ".ubuntuproject"; const char UBUNTUHTMLPROJECT_SUFFIX[] = ".ubuntuhtmlproject"; const char UBUNTU_PROJECT_WIZARD_CATEGORY[] = "A.UbuntuProjects"; const char UBUNTUPROJECT_DISPLAYNAME[] = "Ubuntu Project"; const char UBUNTUPROJECT_RUNCONTROL_ID[] = "UbuntuProjectManager.UbuntuRunConfiguration"; const char UBUNTUHTML_PROJECT_LAUNCHER_EXE[] = "ubuntu-html5-app-launcher"; const char UBUNTUSCOPES_PROJECT_LAUNCHER_EXE[] = "unity-scope-tool"; const char UBUNTU_PROJECT_WIZARD_CATEGORY_DISPLAY[] = QT_TRANSLATE_NOOP("ProjectExplorer", "Ubuntu"); const char UBUNTU_UBUNTUPROJECT_TYPE[] = "ubuntuproject"; const char UBUNTU_HTMLPROJECT_TYPE[] = "ubuntuhtmlproject"; const char UBUNTU_AUTOPILOTPROJECT_TYPE[] = "autopilotproject"; const char UBUNTU_QMLPROJECT_TYPE[] = "qmlproject"; const char UBUNTU_CMAKEPROJECT_TYPE[] = "cmake"; const char UBUNTU_QTPROJECT_TYPE[] = "pro"; const char UBUNTU_QML_TYPE[] = "qml"; const char UBUNTU_HAS_TESTS[] = "hasTests"; const char UBUNTU_INITIAL_EMULATOR_NAME[] = ""; const char UBUNTUBZR_INITIALIZE[] ="%0/qtc_bzr_info"; const char UBUNTUPACKAGINGWIDGET_ONFINISHED_ACTION_CLICK_CREATE[] = "%0/qtc_project_click_create"; const char UBUNTUPACKAGINGWIDGET_ONFINISHED_ACTION_CLICK_CMAKECREATE[] = "%0/qtc_cmakeproject_click_create"; const char UBUNTUPACKAGINGWIDGET_OPENMANIFEST[] ="%0/manifest.json"; const char UBUNTUPACKAGINGWIDGET_APPARMOR[] ="%0/%1.json"; const char UBUNTUPACKAGINGWIDGET_EXCLUDES[] ="%0/.excludes"; const char UBUNTUPACKAGINGWIDGET_MENU_REMOVE[] ="Remove"; const char UBUNTUPACKAGINGWIDGET_BUILDPACKAGE_ID[] ="Ubuntu.Build.Package"; const char UBUNTUPACKAGINGWIDGET_BUILDCMAKEPACKAGE_ID[] ="Ubuntu.Build.PackageCMake"; const char UBUNTUPACKAGINGWIDGET_DEFAULT_MANIFEST[] =":/ubuntu/manifest.json.template"; const char UBUNTUPACKAGINGWIDGET_DEFAULT_MYAPP[] =":/ubuntu/myapp.json.template"; const char UBUNTUPACKAGINGWIDGET_DEFAULT_NAME[] ="com.ubuntu.developer.%0.%1"; const char UBUNTUPACKAGINGWIDGET_LOCAL_REVIEWER_INSTALLED[] = "Checking installed click reviewer tools package."; const char UBUNTUPACKAGINGWIDGET_ONFINISHED_LOCAL_NO_EMULATOR_INSTALLED[] = "The package is not installed."; const char UBUNTUPACKAGINGWIDGET_CLICK_REVIEWER_TOOLS_AGAINST_PACKAGE[] = "Click Reviewers tools against %0"; const char UBUNTUPACKAGINGWIDGET_CLICK_REVIEWER_TOOLS_LINK_DISPLAYTEXT[] = "%0"; const char UBUNTU_CLICK_PACKAGE_MASK[] = "*.click"; const char UBUNTU_CLICK_PACKAGE_SELECTOR_TEXT[] = "Select click package which you want to test"; const char QMAKE_MIMETYPE[] = "application/vnd.qt.qmakeprofile"; const char QMLPROJECT_MIMETYPE[] = "application/x-qmlproject"; const char UBUNTUMENU_ONFINISHED[] = "%0 finished with code %1"; const char UBUNTUMENU_ONERROR[] = "%0"; const char UBUNTUMENU_ONSTARTED[] = "Started %0"; const char ERROR_MSG_NOACTIONS[] = "No actions defined in map"; const char ERROR_MSG_NO_MENU_DEFINED[] = "No menu defined"; const char ERROR_MSG_COULD_NOT_CAST_TO_ACTION[] = "Could not cast to action"; const char ERROR_MSG_UNABLE_TO_PARSE_MENUJSON[] = "Unable to parse menu.json"; const char ERROR_MSG_EMULATOR_PATH[] = "Invalid path to create the emulator."; const char ERROR_MSG_EMULATOR_NAME[] = "Invalid name for the emulator."; const char ERROR_MSG_EMULATOR_EXISTS[] = "The emulator already exists."; const char MSG_EMULATOR_IS_CREATED[] = "Check the logs for details."; const char UBUNTUDEVICESWIDGET_REBOOT[] = "Reboot device.."; const char UBUNTUDEVICESWIDGET_REBOOT_SCRIPT[] = "%0/device_reboot"; const char UBUNTUDEVICESWIDGET_SHUTDOWN[] = "Shutdown device.."; const char UBUNTUDEVICESWIDGET_SHUTDOWN_SCRIPT[] = "%0/device_shutdown"; const char UBUNTUDEVICESWIDGET_REBOOT_TO_BOOTLOADER[] = "Reboot to bootloader.."; const char UBUNTUDEVICESWIDGET_REBOOT_TO_BOOTLOADER_SCRIPT[] = "%0/device_reboot2bootloader"; const char UBUNTUDEVICESWIDGET_REBOOT_TO_RECOVERY[] = "Reboot to recovery.."; const char UBUNTUDEVICESWIDGET_REBOOT_TO_RECOVERY_SCRIPT[] = "%0/device_reboot2recovery"; const char UBUNTUWIDGETS_LOCAL_PACKAGE_INSTALLED_SCRIPT[] = "%0/local_package_installed %1"; const char UBUNTUDEVICESWIDGET_LOCAL_INSTALL_EMULATOR[] = "%0/local_install_emulator %1"; const char UBUNTUDEVICESWIDGET_DETECTOPENSSH[] = "Detecting if openssh-server is installed.."; const char UBUNTUDEVICESWIDGET_DETECTOPENSSH_SCRIPT[] = "%0/openssh_version %1"; const char UBUNTUDEVICESWIDGET_DETECTDEVICES[] = "Detecting device.."; const char UBUNTUDEVICESWIDGET_DETECTDEVICES_SCRIPT[] = "%0/device_search %1"; const char UBUNTUDEVICESWIDGET_SSHCONNECT_SCRIPT[] = "%0/openssh_connect"; const char UBUNTUDEVICESWIDGET_SSHCONNECT[] = "Opening ssh connection to device"; const char UBUNTUDEVICESWIDGET_CLONENETWORK[] = "Clone network configuration from host to device.."; const char UBUNTUDEVICESWIDGET_CLONENETWORK_SCRIPT[] = "%0/device_network_clone %1"; const char UBUNTUDEVICESWIDGET_PORTFORWARD[] = "Enabling port forward.."; const char UBUNTUDEVICESWIDGET_PORTFORWARD_SCRIPT[] = "%0/device_portforward"; const char UBUNTUDEVICESWIDGET_SETUP_PUBKEY_AUTH[] = "Setting up public key authentication.."; const char UBUNTUDEVICESWIDGET_SETUP_PUBKEY_AUTH_SCRIPT[] = "%0/openssh_publickey %1 %2"; const char UBUNTUDEVICESWIDGET_HASNETWORK[] = "Check if the device is connected to a network.."; const char UBUNTUDEVICESWIDGET_HASNETWORK_SCRIPT[] = "%0/device_hasnetwork %1"; const char UBUNTUDEVICESWIDGET_DETECTDEVICEVERSION[] = "Check device image version.."; const char UBUNTUDEVICESWIDGET_DETECTDEVICEVERSION_SCRIPT[] = "%0/device_version %1"; const char UBUNTUDEVICESWIDGET_SSH_INSTALL[] = "Installing openssh-server.."; const char UBUNTUDEVICESWIDGET_SSH_INSTALL_SCRIPT[] = "%0/openssh_install %1"; const char UBUNTUDEVICESWIDGET_CLONETIME[] = "Cloning time configuration from host to device.."; const char UBUNTUDEVICESWIDGET_CLONETIME_SCRIPT[] = "%0/device_time_clone %1"; const char UBUNTUDEVICESWIDGET_SSH_REMOVE[] = "Removing openssh-server.."; const char UBUNTUDEVICESWIDGET_SSH_REMOVE_SCRIPT[] = "%0/openssh_remove %1"; #ifdef UBUNTU_BUILD_LOCAL const QString UBUNTU_RESOURCE_PATH = QLatin1String(UBUNTU_RESOURCE_PATH_LOCAL); #else const QString UBUNTU_RESOURCE_PATH = Core::ICore::resourcePath(); #endif const QString UBUNTU_WELCOMESCREEN_QML = UBUNTU_RESOURCE_PATH + QLatin1String("/ubuntu/welcome/welcome.qml"); const QString UBUNTU_TEMPLATESPATH = UBUNTU_RESOURCE_PATH + QLatin1String("/templates/wizards/ubuntu/"); const QString UBUNTU_MENUPATH = UBUNTU_RESOURCE_PATH + QLatin1String("/ubuntu/"); const QString UBUNTU_SHAREPATH = UBUNTU_RESOURCE_PATH + QLatin1String("/ubuntu/"); const QString UBUNTU_SCRIPTPATH = UBUNTU_RESOURCE_PATH + QLatin1String("/ubuntu/scripts"); const char UBUNTU_MENUJSON[] = "menu.json"; const char UBUNTU_MENUJSON_NAME[] = "name"; const char UBUNTU_MENUJSON_ID[] = "id"; const char UBUNTU_MENUJSON_ACTIONS[] = "actions"; const char UBUNTU_MENUJSON_SUBMENU[] = "submenu"; const char UBUNTU_MENUJSON_KEYSEQUENCE[] = "keysequence"; const char UBUNTU_MENUJSON_QUERYDIALOG[] = "queryDialog"; const char UBUNTU_MENUJSON_TITLE[] = "title"; const char UBUNTU_MENUJSON_MESSAGE[] = "message"; const char UBUNTU_MENUJSON_VALUE[] = "value"; const char UBUNTU_MENUJSON_PARENT[] = "parent"; const char UBUNTU_MENUJSON_GROUP[] = "group"; const char UBUNTU_MENUJSON_WORKINGDIRECTORY[] = "workingDirectory"; const char UBUNTU_MENUJSON_PROJECTREQUIRED[] = "projectRequired"; const char UBUNTU_MENUJSON_DEVICEREQUIRED[] = "deviceRequired"; const char UBUNTU_MENUJSON_QMLPROJECTREQUIRED[] = "qmlProjectRequired"; const char UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED[] = "qmakeProjectRequired"; const char UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED[] = "ubuntuProjectRequired"; const char UBUNTU_MENUJSON_UBUNTUHTMLPROJECTREQUIRED[] = "ubuntuHtmlProjectRequired"; const char UBUNTU_MENUJSON_CLICKTARGETREQUIRED[] = "needsClickTarget"; //will ask the user to choose a click target const char UBUNTU_MENUJSON_SAVEREQUIRED[] = "saveRequired"; const char UBUNTU_MENUJSON_MESSAGEDIALOG[] = "messageDialog"; const char UBUNTU_MENUJSON_CONTEXT[] = "context"; const char UBUNTU_MENUJSON_PARENT_TOOLS[] = "Tools"; const char UBUNTU_MENUJSON_PARENT_WINDOW[] = "Window"; const char UBUNTU_MENUJSON_PARENT_HELP[] = "Help"; const char UBUNTU_MENUJSON_PARENT_BUILD[] = "Build"; const char UBUNTU_MENUJSON_PARENT_FILE[] = "File"; const char UBUNTU_MENUJSON_PARENT_EDIT[] = "Edit"; const char UBUNTU_MENUJSON_PARENT_TOP[] = "TOP"; const char UBUNTU_PROJECTJSON[] = "projectypes.json"; const char UBUNTU_PROJECTJSON_DISPLAYNAME[] = "displayName"; const char UBUNTU_PROJECTJSON_ID[] = "id"; const char UBUNTU_PROJECTJSON_DESCRIPTION[] = "description"; const char UBUNTU_PROJECTJSON_FOLDER[] = "folder"; const char UBUNTU_PROJECTJSON_TYPE[] = "type"; const char UBUNTU_PROJECTJSON_MAINFILE[] = "mainFile"; const char UBUNTU_PROJECTJSON_PROJECTFILE[] = "projectFile"; const char UBUNTU_PROJECTJSON_FILENAME[] = "fileName"; const char UBUNTU_PROJECTJSON_FILES[] = "files"; const char UBUNTU_PROJECTJSON_CATEGORY_DISPLAY[] = "categoryDisplay"; const char UBUNTU_PROJECTJSON_CATEGORY[] = "category"; const char UBUNTU_PROJECTJSON_REQUIRED_FEATURE[] = "requiredFeature"; const char UBUNTU_DIALOG_NO_PROJECTOPEN_TITLE[] = "No project open"; const char UBUNTU_DIALOG_NO_PROJECTOPEN_TEXT[] = "Open a project or create a new one."; const char UBUNTU_PROCESS_COMMAND[] = "command"; const char UBUNTU_ACTION_FOLDERNAME[] = "%FOLDERNAME%"; const char UBUNTU_ACTION_PROJECTDIRECTORY[] = "%PROJECTDIRECTORY%"; const char UBUNTU_ACTION_DISPLAYNAME[] = "%DISPLAYNAME%"; const char UBUNTU_ACTION_DISPLAYNAME_UPPER[] = "%DISPLAYNAME_UPPER%"; const char UBUNTU_ACTION_DISPLAYNAME_LOWER[] = "%DISPLAYNAME_LOWER%"; const char UBUNTU_ACTION_DISPLAYNAME_CAPITAL[] = "%DISPLAYNAME_CAPITAL%"; const char UBUNTU_ACTION_PROJECTFILES[] = "%PROJECTFILES%"; const char UBUNTU_ACTION_SCRIPTDIRECTORY[] = "%SCRIPTDIRECTORY%"; const char UBUNTU_ACTION_SHAREDIRECTORY[] = "%SHAREDIRECTORY%"; const char UBUNTU_ACTION_SERIALNUMBER[] = "%SERIALNUMBER%"; const char UBUNTU_ACTION_BZR_USERNAME[] = "%BZR_USERNAME%"; const char UBUNTU_ACTION_DEVICE_USERNAME[] = "%USERNAME%"; const char UBUNTU_ACTION_DEVICE_IP[] = "%IP%"; const char UBUNTU_ACTION_DEVICE_PORT[] = "%PORT%"; const char UBUNTU_ACTION_APP_RUNNER_EXECNAME[] = "%APPRUNNEREXECNAME%"; const char UBUNTU_ACTION_CLICK_ARCH[] = "%CLICK_ARCH%"; const char UBUNTU_ACTION_CLICK_FRAMEWORK[] = "%CLICK_FRAMEWORK%"; const char UBUNTU_ACTION_CLICK_SERIES[] = "%CLICK_SERIES%"; const char UBUNTU_ACTION_CLICK_PACKAGING_FOLDER[] = "%CLICK_PACKAGING_FOLDER%"; const char UBUNTU_FILENAME_DISPLAYNAME[] = "displayName"; const char UBUNTU_FILENAME_DISPLAYNAME_LOWER[] = "displayName_lower"; const char UBUNTU_FILENAME_DISPLAYNAME_UPPER[] = "displayName_upper"; const char UBUNTU_FILENAME_DISPLAYNAME_CAPITAL[] = "displayName_capital"; const char UBUNTU_MODE_WELCOME[] = "UbuntuWelcome"; const char UBUNTU_MODE_WELCOME_DISPLAYNAME[] = "Ubuntu"; const char UBUNTU_MODE_WELCOME_ICON[] = ":/ubuntu/images/ubuntu-qtcreator.png"; const int UBUNTU_MODE_WELCOME_PRIORITY = 1; const char UBUNTU_MODE_PACKAGING[] = "UbuntuPackaging"; const char UBUNTU_MODE_PACKAGING_DISPLAYNAME[] = "Publish"; const char UBUNTU_MODE_PACKAGING_ICON[] = ":/ubuntu/images/packaging.png"; const int UBUNTU_MODE_PACKAGING_PRIORITY = 80; const char UBUNTU_MODE_DEVICES[] = "UbuntuDevices"; const char UBUNTU_MODE_DEVICES_DISPLAYNAME[] = "Devices"; const char UBUNTU_MODE_DEVICES_ICON[] = ":/ubuntu/images/device.png"; const int UBUNTU_MODE_DEVICES_PRIORITY = 11; const char UBUNTU_MODE_WEB[] = "UbuntuWeb"; const char UBUNTU_MODE_WEB_DISPLAYNAME[] = "WEB"; const char UBUNTU_MODE_WEB_ICON[] = ":/ubuntu/images/ubuntu-32.png"; const int UBUNTU_MODE_WEB_PRIORITY = 10; const char UBUNTU_MODE_PASTEBIN[] = "UbuntuPasteBin"; const char UBUNTU_MODE_PASTEBIN_DISPLAYNAME[] = "Pastebin"; const char UBUNTU_MODE_IRC[] = "UbuntuIRC"; const char UBUNTU_MODE_IRC_DISPLAYNAME[] = "IRC"; const char UBUNTU_MODE_API[] = "UbuntuAPI"; const char UBUNTU_MODE_API_DISPLAYNAME[] = "API"; const char UBUNTU_MODE_COREAPPS[] = "UbuntuCoreApps"; const char UBUNTU_MODE_COREAPPS_DISPLAYNAME[] = "Core Apps"; const char UBUNTU_MODE_WIKI[] = "UbuntuWiki"; const char UBUNTU_MODE_WIKI_DISPLAYNAME[] = "Wiki"; const char UBUNTU_IRC[] = "http://webchat.freenode.net/?channels=ubuntu-app-devel"; const char UBUNTU_API_ONLINE[] = "http://developer.ubuntu.com/api/devel/ubuntu-13.10/qml/ui-toolkit/overview-ubuntu-sdk.html"; const char UBUNTU_API_OFFLINE[] = "/usr/share/ubuntu-ui-toolkit/doc/html/overview-ubuntu-sdk.html"; const char UBUNTU_COREAPPS[] = "https://launchpad.net/ubuntu-phone-coreapps/"; const char UBUNTU_WIKI[] = "https://wiki.ubuntu.com/Touch"; const char UBUNTU_PASTEBIN[] = "http://pastebin.ubuntu.com"; const char FEATURE_UNITY_SCOPE[] = "Ubuntu.Wizards.FeatureUnityScope"; const char FEATURE_UBUNTU_PRECISE[] = "Ubuntu.Wizards.FeatureUbuntuPrecise"; const char FEATURE_UBUNTU_QUANTAL[] = "Ubuntu.Wizards.FeatureUbuntuQuantal"; const char FEATURE_UBUNTU_RARING[] = "Ubuntu.Wizards.FeatureUbuntuRaring"; const char FEATURE_UBUNTU_SAUCY[] = "Ubuntu.Wizards.FeatureUbuntuSaucy"; const char FEATURE_UBUNTU_TRUSTY[] = "Ubuntu.Wizards.FeatureUbuntuTrusty"; const char DISTRIB_ID[] = "DISTRIB_ID="; const char DISTRIB_CODENAME[] = "DISTRIB_CODENAME="; const char DISTRIB_RELEASE[] = "DISTRIB_RELEASE="; const char DISTRIB_DESCRIPTION[] = "DISTRIB_DESCRIPTION="; const char LSB_RELEASE[] = "/etc/lsb-release"; const char PRECISE[] = "precise"; const char QUANTAL[] = "quantal"; const char RARING[] = "raring"; const char SAUCY[] = "saucy"; const char TRUSTY[] = "trusty"; const char PLATFORM_DESKTOP[] = "Desktop"; const char PLATFORM_DESKTOP_DISPLAYNAME[] = "Ubuntu %0"; const char TASK_DEVICE_SCRIPT[] = "Ubuntu.Task.DeviceScript"; const char UBUNTU_SETTINGS_ICON[] = ":/ubuntu/images/ubuntu-32.png"; const bool SETTINGS_DEFAULT_API_VISIBILITY = true; const bool SETTINGS_DEFAULT_COREAPPS_VISIBILITY = true; const bool SETTINGS_DEFAULT_IRC_VISIBILITY = true; const bool SETTINGS_DEFAULT_PASTEBIN_VISIBILITY = true; const bool SETTINGS_DEFAULT_WIKI_VISIBILITY = true; const char SETTINGS_DEFAULT_DEVICE_USERNAME[] = "phablet"; const char SETTINGS_DEFAULT_DEVICE_IP[] = "127.0.0.1"; const int SETTINGS_DEFAULT_DEVICE_QML_PORT = 3768; const int SETTINGS_DEFAULT_DEVICE_SSH_PORT = 2222; const bool SETTINGS_DEFAULT_DEVICES_AUTOTOGGLE = true; const char SETTINGS_COMPANY[] = "Canonical"; const char SETTINGS_PRODUCT[] = "UbuntuSDK"; const char SETTINGS_GROUP_MODE[] = "Mode"; const char SETTINGS_GROUP_DEVICE_CONNECTIVITY[] = "DeviceConnectivity"; const char SETTINGS_GROUP_DEVICES[] = "Devices"; const char SETTINGS_KEY_API[] = "API"; const char SETTINGS_KEY_COREAPPS[] = "CoreApps"; const char SETTINGS_KEY_IRC[] = "IRC"; const char SETTINGS_KEY_PASTEBIN[] = "Pastebin"; const char SETTINGS_KEY_WIKI[] = "Wiki"; const char SETTINGS_KEY_USERNAME[] = "Username"; const char SETTINGS_KEY_IP[] = "IP"; const char SETTINGS_KEY_QML[] = "QML"; const char SETTINGS_KEY_SSH[] = "SSH"; const char SETTINGS_KEY_AUTOTOGGLE[] = "Auto_Toggle"; const char SETTINGS_GROUP_CLICK[] = "Click"; const char SETTINGS_KEY_CLICK_REVIEWERSTOOLS[] = "ReviewersToolsEnabled"; const char SETTINGS_KEY_CLICK_REVIEWERSTOOLS_LOCATION[] = "ReviewersToolsLocation"; const bool SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS = false; const bool SETTINGS_CLICK_REVIEWERSTOOLS_TRUE = true; const char SETTINGS_DEFAULT_CLICK_REVIEWERSTOOLS_LOCATION[] = "/usr/bin/click-run-checks %0"; const char UBUNTUSETTINGSCLICKWIDGET_FILEDIALOG[] = "Location of click-reviewers-tools"; //build configuration const char UBUNTU_CLICK_BUILD_CONTEXTMENU_ID[] = "UbuntuProjectManager.RunClickBuildContextMenu"; const char UBUNTU_CLICK_BUILD_CONTEXTMENU_TEXT[] = "Build in chroot"; const char UBUNTU_CLICK_OPEN_TERMINAL_ERROR[] = "Error when starting terminal"; const char UBUNTU_CLICK_TARGETS_REGEX[] = "^click-(.*)-([A-Za-z0-9]+)$"; const char UBUNTU_CLICK_TARGETS_FRAMEWORK_REGEX[] = "^click-(%1)-([A-Za-z0-9]+)$"; const char UBUNTU_CLICK_BASE_FRAMEWORK_REGEX[] = "(ubuntu-sdk-[0-9]{1,2}.[0-9]{1,2})"; const char UBUNTU_CLICK_VERSION_REGEX[] = "^DISTRIB_RELEASE=([0-9]+)\\.([0-9]+)$"; const char UBUNTU_CLICK_SERIES_REGEX[] = "^DISTRIB_CODENAME=([A-Za-z]+)$"; const char UBUNTU_CLICK_BINARY[] = "/usr/bin/click"; const char UBUNTU_SUDO_BINARY[] = "/usr/bin/pkexec"; const char UBUNTU_CLICK_CHROOT_BASEPATH[] = "/var/lib/schroot/chroots"; const char UBUNTU_CLICK_FRAMEWORKS_BASEPATH[] = "/usr/share/click/frameworks"; const char UBUNTU_CLICK_CLICK_PACKAGE_DIR[] = "%CLICK_FRAMEWORK%-%CLICK_ARCH%/click_package"; const char UBUNTU_CLICK_CHROOT_CREATE_ARGS[] = "sh -c \"%0/click_create_target %1 %2 %3\""; const char UBUNTU_CLICK_CHROOT_DESTROY_ARGS[] = "sh -c \"%0/click_destroy_target %1 %2 %3\""; const char UBUNTU_CLICK_CHROOT_UPGRADE_ARGS[] = "chroot -a %0 -f %1 -s %2 upgrade"; const char UBUNTU_CLICK_CHROOT_CMAKE_SCRIPT[] = "%0/qtc_chroot_cmake"; const char UBUNTU_CLICK_CHROOT_CMAKE_ARGS[] = "%0 %1 %2 %3 %4"; const char UBUNTU_CLICK_CHROOT_MAKE_SCRIPT[] = "%0/qtc_chroot_make"; const char UBUNTU_CLICK_CHROOT_MAKE_ARGS[] = "%0 %1 %2 %4"; const char UBUNTU_CLICK_CHROOT_MAKE_CLEAN_ARGS[] = "clean"; const char UBUNTU_CLICK_CHROOT_MAKE_INSTALL_ARGS[] = "DESTDIR=click_package install"; const char UBUNTU_CLICK_FIXAUTOMOC_SCRIPT[] = "%0/qtc_fixmoc"; const char UBUNTU_CLICK_FIXAUTOMOC_ARGS[] = "%0 %1 %2"; const char UBUNTU_CLICK_OPEN_TERMINAL[] = "click chroot -a %0 -f %1 -s %2 maint /bin/bash"; const char UBUNTU_CLICK_DELETE_TITLE[] = "Delete click chroot"; const char UBUNTU_CLICK_DELETE_MESSAGE[] = "Are you sure you want to delete this chroot?"; const char UBUNTU_CLICK_STOP_TITLE[] = "Stop click tool"; const char UBUNTU_CLICK_STOP_MESSAGE[] = "Are you sure you want to stop click? This could break your chroot!"; const char UBUNTU_CLICK_STOP_WAIT_MESSAGE[] = "Waiting for click to stop"; const char UBUNTU_CLICK_ERROR_EXIT_MESSAGE[] = "Click exited with errors, please check the output"; const char UBUNTU_CLICK_SUCCESS_EXIT_MESSAGE[] = "Click exited with no errors"; const char UBUNTU_CLICK_BUILDTASK_ID[] = "UbuntuClickManager.Build"; const char UBUNTU_CLICK_BUILDTASK_TITLE[] = "Building"; const char UBUNTU_CLICK_NOBUILDCONFIG_ERROR[] = "Building %1 failed, No active build configuration"; const char UBUNTU_CLICK_BUILD_CANCELED_MESSAGE[] = "Build canceled"; const char UBUNTU_CLICK_BUILD_START_MESSAGE[] = "Starting to build %0"; const char UBUNTU_CLICK_BUILD_CLEAN_MESSAGE[] = "Cleaning old build"; const char UBUNTU_CLICK_BUILD_CMAKE_MESSAGE[] = "Running CMake"; const char UBUNTU_CLICK_BUILDDIR_MESSAGE[] = "Using build directory %0"; const char UBUNTU_CLICK_NOVERSIONINFO_ERROR[] = "Could not find any version information in click target: click-%0-%1"; const char UBUNTU_CLICK_FIXAUTOMOC_MESSAGE[] = "Fixing build script"; const char UBUNTU_CLICK_MAKE_MESSAGE[] = "Running Make"; const char UBUNTU_CLICK_BUILD_OK_MESSAGE[] = "Build was finished successfully"; const char UBUNTU_CLICK_BUILD_FAILED_MESSAGE[] = "Build failed"; const char UBUNTU_CLICK_RUN_COMMAND_MESSAGE[] = "Running command: %0 %1"; const char UBUNTU_CLICK_NOTARGETS_TITLE[] = "No click build targets available"; const char UBUNTU_CLICK_NOTARGETS_MESSAGE[] = "There are no click build targets available.\nPlease create a target in the Ubuntu option page."; const char UBUNTU_CLICK_NOTARGETS_FRAMEWORK_MESSAGE[] = "There are no click build targets for framework %1 available.\nPlease create a target in the Ubuntu option page."; const char UBUNTU_CLICK_SELECT_TARGET_TITLE[] = "Select build target"; const char UBUNTU_CLICK_SELECT_TARGET_LABEL[] = "Build target"; extern const char* UBUNTU_CLICK_SUPPORTED_ARCHS[]; extern const char* UBUNTU_CLICK_SUPPORTED_TARGETS[][3]; //Buildsupport const char UBUNTU_CLICK_TOOLCHAIN_ID[] = "UbuntuProjectManager.UbuntuGccToolChain"; const char UBUNTU_CLICK_CMAKE_TOOL_ID[] = "UbuntuProjectManager.UbuntuCMake"; const char UBUNTU_CLICK_CMAKE_BC_ID[] = "UbuntuProjectManager.UbuntuCMake.BuildConfiguration"; const char UBUNTU_CLICK_CMAKE_MAKESTEP_ID[] = "UbuntuProjectManager.UbuntuCMake.MakeStep"; const char UBUNTU_CLICK_CMAKE_WRAPPER[] = "%0/qtc_chroot_cmake2"; const char UBUNTU_CLICK_MAKE_WRAPPER[] = "%0/qtc_chroot_make2"; const char UBUNTU_CLICK_GCC_WRAPPER[] = "%0/qtc_chroot_gcc"; //Devicesupport const char UBUNTU_DEVICE_TYPE_ID[] = "UbuntuProjectManager.DeviceTypeId"; const char UBUNTU_DEVICE_SSHIDENTITY[] = "%0/.ssh/ubuntudevice_%1_id_rsa"; //Deploysupport const char UBUNTU_DEPLOYCONFIGURATION_ID[] = "UbuntuProjectManager.DeployConfiguration"; const char UBUNTU_LOCAL_DEPLOYCONFIGURATION_ID[] = "UbuntuProjectManager.LocalDeployConfiguration"; const char UBUNTU_DEPLOY_UPLOADSTEP_ID[] = "UbuntuProjectManager.UploadStep"; const char UBUNTU_DEPLOY_MAKESTEP_ID[] = "UbuntuProjectManager.UbuntuCMake.DeployMakeStep"; const char UBUNTU_CLICK_PACKAGESTEP_ID[] = "UbuntuProjectManager.ClickPackageStep"; const char UBUNTU_DEPLOY_DESTDIR[] = ".ubuntu-sdk-deploy"; const char UBUNTU_CLICK_SUCCESS_PACKAGE_REGEX[] = "^.*'(.*)'.$"; //Frameworks const char UBUNTU_FRAMEWORK_14_04_BASENAME[] = "ubuntu-sdk-14.04"; const char UBUNTU_FRAMEWORK_13_10_BASENAME[] = "ubuntu-sdk-13.10"; const char UBUNTU_DEFAULT_QML_FRAMEWORK[] = "ubuntu-sdk-14.04-qml"; const char UBUNTU_DEFAULT_HTML_FRAMEWORK[] = "ubuntu-sdk-14.04-html"; const char UBUNTU_UNKNOWN_FRAMEWORK_NAME[] = "Unknown framework"; const int UBUNTU_UNKNOWN_FRAMEWORK_DATA = 0xdeadbeef; } // namespace Ubuntu } // namespace Constants #endif // UBUNTUCONSTANTS_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntucmaketool.h0000644000015301777760000000323112323167147026441 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #ifndef UBUNTUCMAKETOOL_H #define UBUNTUCMAKETOOL_H #include #include namespace Ubuntu { namespace Internal { class UbuntuCMakeTool : public CMakeProjectManager::CMakeTool { Q_OBJECT public: explicit UbuntuCMakeTool(QObject *parent = 0); explicit UbuntuCMakeTool(const Core::Id &id, QObject *parent = 0); // ICMakeTool interface virtual void addToEnvironment(Utils::Environment &env) const; virtual QString displayName (); virtual bool isValid() const; void setEnvironment (const Utils::Environment &env); private: bool m_hasEnvironment; Utils::Environment m_env; }; class UbuntuCMakeToolFactory : public CMakeProjectManager::ICMakeToolFactory { Q_OBJECT public: virtual bool canCreate (const Core::Id& id) const; virtual CMakeProjectManager::ICMakeTool *create (const Core::Id& id); }; } //namespace Internal } //namespace Ubuntu #endif // UBUNTUCMAKETOOL_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubunturemoterunconfiguration.cpp0000644000015301777760000002026412323167147031633 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubunturemoterunconfiguration.h" #include "clicktoolchain.h" #include "ubuntuclicktool.h" #include "ubuntucmakebuildconfiguration.h" #include "ubuntuconstants.h" #include "ubuntulocalrunconfiguration.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace Ubuntu { namespace Internal { UbuntuRemoteRunConfiguration::UbuntuRemoteRunConfiguration(ProjectExplorer::Target *parent) : AbstractRemoteLinuxRunConfiguration(parent,typeId()) { setDisplayName(parent->project()->displayName()); addExtraAspect(new RemoteLinux::RemoteLinuxEnvironmentAspect(this)); } UbuntuRemoteRunConfiguration::UbuntuRemoteRunConfiguration(ProjectExplorer::Target *parent, UbuntuRemoteRunConfiguration *source) : AbstractRemoteLinuxRunConfiguration(parent,source) { } QString UbuntuRemoteRunConfiguration::localExecutableFilePath() const { return m_localExecutable; } QString UbuntuRemoteRunConfiguration::remoteExecutableFilePath() const { return m_remoteExecutable; } QStringList UbuntuRemoteRunConfiguration::arguments() const { return m_arguments; } QString UbuntuRemoteRunConfiguration::workingDirectory() const { return QString::fromLatin1("/home/phablet/dev_tmp/%1").arg(target()->project()->displayName()); } QString UbuntuRemoteRunConfiguration::alternateRemoteExecutable() const { return QString(); } bool UbuntuRemoteRunConfiguration::useAlternateExecutable() const { return false; } Utils::Environment UbuntuRemoteRunConfiguration::environment() const { RemoteLinux::RemoteLinuxEnvironmentAspect *aspect = extraAspect(); QTC_ASSERT(aspect, return Utils::Environment()); Utils::Environment env(Utils::OsTypeLinux); env.modify(aspect->userEnvironmentChanges()); ProjectExplorer::ToolChain* tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit()); if(tc->type() == QString::fromLatin1(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) { ClickToolChain* clickTc = static_cast(tc); env.appendOrSet(QLatin1String("gnutriplet"),clickTc->gnutriplet()); env.appendOrSet(QLatin1String("QML2_IMPORT_PATH"), QString::fromLatin1("lib/%1").arg(clickTc->gnutriplet()), QString::fromLatin1(":")); } env.appendOrSet(QLatin1String("pkgdir"),workingDirectory()); env.appendOrSet(QLatin1String("APP_ID"),m_appId); return env; } QStringList UbuntuRemoteRunConfiguration::soLibSearchPaths() const { QStringList paths; CMakeProjectManager::CMakeProject *cmakeProj = qobject_cast(target()->project()); if(cmakeProj) { QList targets = cmakeProj->buildTargets(); foreach(const CMakeProjectManager::CMakeBuildTarget& target, targets) { QFileInfo binary(target.executable); if(binary.exists()) { qDebug()<<"Adding path "</package. That means we can not cache that * information, because it could change anytime */ bool UbuntuRemoteRunConfiguration::ensureConfigured(QString *errorMessage) { qDebug()<<"--------------------- Reconfiguring RunConfiguration ----------------------------"; m_arguments.clear(); m_desktopFile.clear(); m_appId.clear(); QDir package_dir(target()->activeBuildConfiguration()->buildDirectory().toString()+QDir::separator()+QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR)); if(!package_dir.exists()) { if(errorMessage) *errorMessage = tr("No packaging directory available, please check if the deploy configuration is correct."); return false; } m_desktopFile = UbuntuLocalRunConfiguration::getDesktopFile(this,&m_appId,errorMessage); if(m_desktopFile.isEmpty()) return false; /* * Tries to read the Exec line from the desktop file, to * extract arguments and to know which "executor" is used on * the phone */ QStringList args; QString command; if(!UbuntuLocalRunConfiguration::readDesktopFile(m_desktopFile,&command,&args,errorMessage)) return false; QFileInfo commInfo(command); if(commInfo.completeBaseName().startsWith(QLatin1String("qmlscene"))) { ProjectExplorer::ToolChain* tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit()); if(tc->type() != QString::fromLatin1(Constants::UBUNTU_CLICK_TOOLCHAIN_ID)) { if(errorMessage) *errorMessage = tr("Wrong toolchain type. Please check your build configuration."); return false; } ClickToolChain* clickTc = static_cast(tc); m_localExecutable = QString::fromLatin1("%1/usr/lib/%2/qt5/bin/qmlscene") .arg(UbuntuClickTool::targetBasePath(clickTc->clickTarget())) .arg(clickTc->gnutriplet()); m_remoteExecutable = QLatin1String("/usr/bin/qmlscene"); m_arguments = args; } else if(commInfo.completeBaseName().startsWith(QLatin1String("ubuntu-html5-app-launcher"))) { if(errorMessage) *errorMessage = tr("Run support for remote html projects not available"); return false; } else { //looks like a application without a launcher m_localExecutable = target()->activeBuildConfiguration()->buildDirectory().toString() + QDir::separator() + QLatin1String(Constants::UBUNTU_DEPLOY_DESTDIR) + QDir::separator() + command; m_remoteExecutable = workingDirectory() + QDir::separator() + command; } QFileInfo desk(m_desktopFile); m_arguments.append(QString::fromLatin1("--desktop_file_hint=/home/phablet/dev_tmp/%1/%2") .arg(target()->project()->displayName()) .arg(desk.fileName())); m_arguments.append(QLatin1String("--stage_hint=main_stage")); return true; } bool UbuntuRemoteRunConfiguration::fromMap(const QVariantMap &map) { qDebug()<. * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPROJECTAPP_H #define UBUNTUPROJECTAPP_H #include #include #include #include #include #include #include #include "ubuntuconstants.h" #include "ubuntubzr.h" namespace Ubuntu { namespace Internal { class UbuntuProjectApp : public QObject { Q_OBJECT public: UbuntuProjectApp(QObject *parent = 0); Core::GeneratedFiles generateFiles(const QWizard *w, QString *errorMessage); QString projectType() { return m_projectType; } void setProjectType(QString projectType) { m_projectType = projectType; } QString projectFileName() { return m_projectFileName; } void setProjectFileName(QString projectFileName) { m_projectFileName = projectFileName; } void setData(QJsonObject obj) { m_obj = obj; } void setupParameters(QJsonObject params, Core::IWizard* wizard); QByteArray processReservedWords(QByteArray data, QString projectPath, QString projectName); QString processReservedWordsInFileName(QString data, QString projectName) { return QString::fromLatin1(processReservedWordsInFileName(data.toLatin1(),projectName)); } QByteArray processReservedWordsInFileName(QByteArray data, QString projectName); Core::Feature requiredFeature(); protected: QString m_projectType; QString m_projectFileName; UbuntuBzr m_bzrInfo; QJsonObject m_obj; }; } } #endif // UBUNTUPROJECTAPP_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuclicktool.h0000644000015301777760000001035012323167147026446 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTU_INTERNAL_UBUNTUCLICKTOOL_H #define UBUNTU_INTERNAL_UBUNTUCLICKTOOL_H #include #include #include #include #include #include #include #include class QDialogButtonBox; class QPlainTextEdit; class QLabel; class QAction; namespace ProjectExplorer { class Project; class Target; } namespace Ubuntu { namespace Internal { class UbuntuClickBuildConfiguration; class UbuntuClickTool { public: enum MaintainMode { Upgrade,//runs click chroot upgrade Delete //runs click chroot delete }; struct Target { bool maybeBroken; int majorVersion; int minorVersion; QString series; QString framework; QString architecture; }; UbuntuClickTool(); static void parametersForCreateChroot (const Target &target, ProjectExplorer::ProcessParameters* params); static void parametersForMaintainChroot (const MaintainMode &mode,const Target& target,ProjectExplorer::ProcessParameters* params); static void parametersForCmake (const Target& target, const QString &buildDir , const QString &relPathToSource, const QStringList& userArgs, ProjectExplorer::ProcessParameters* params); static void parametersForMake (const Target& target, const QString &buildDir, const QString &makeArgs, ProjectExplorer::ProcessParameters* params); static void openChrootTerminal (const Target& target); static QString targetBasePath (const Target& target); static bool getTargetFromUser (Target* target, const QString &framework=QString()); static QStringList getSupportedFrameworks (); static QString getMostRecentFramework ( const QString &subFramework ); static bool targetExists (const Target& target); static QList listAvailableTargets (const QString &framework=QString()); static QPair targetVersion (const Target& target); static bool targetFromPath(const QString& targetPath, Target* tg); }; class UbuntuClickManager : public QObject { Q_OBJECT public: enum BuildState { NotStarted, MakeClean, Cmake, FixMoc, Make, MakeInstall, Finished }; struct Build { ProjectExplorer::Target* buildTarget; UbuntuClickTool::Target targetChroot; BuildState currentState; QString buildDir; }; UbuntuClickManager (QObject* parent = 0); virtual ~UbuntuClickManager ( ); void initialize (); protected: void startProcess (const ProjectExplorer::ProcessParameters& params); void setBuildActionsEnabled (const bool enabled = true); public slots: void processBuildQueue (); void stop(); protected slots: void cleanup (); void nextStep (); void on_buildInChrootAction(); void on_processFinished(int exitCode, QProcess::ExitStatus exitStatus); void on_processReadyRead(); private: QAction *m_buildInChrootAction; //shown in the project context and global build menu bool m_failOnError; //should we fail if the current step has errors? Utils::QtcProcess *m_process; QFutureInterface *m_futureInterface; Build *m_currentBuild; QQueue m_pendingBuilds; }; QDebug operator<<(QDebug dbg, const UbuntuClickTool::Target& t); } // namespace Internal } // namespace Ubuntu #endif // UBUNTU_INTERNAL_UBUNTUCLICKTOOL_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntudevicefactory.cpp0000644000015301777760000000403212323167147027645 0ustar pbusernogroup00000000000000/* * Copyright 2014 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Benjamin Zeller */ #include "ubuntudevicefactory.h" #include "ubuntuconstants.h" #include "ubuntudevice.h" #include namespace Ubuntu { namespace Internal { UbuntuDeviceFactory::UbuntuDeviceFactory(QObject *parent) : ProjectExplorer::IDeviceFactory(parent) { } } // namespace Internal } // namespace Ubuntu QString Ubuntu::Internal::UbuntuDeviceFactory::displayNameForId(Core::Id type) const { QTC_ASSERT(type == Constants::UBUNTU_DEVICE_TYPE_ID, return QString()); return tr("Ubuntu Device"); } QList Ubuntu::Internal::UbuntuDeviceFactory::availableCreationIds() const { return QList() << Core::Id(Constants::UBUNTU_DEVICE_TYPE_ID); } bool Ubuntu::Internal::UbuntuDeviceFactory::canCreate() const { return false; } ProjectExplorer::IDevice::Ptr Ubuntu::Internal::UbuntuDeviceFactory::create(Core::Id id) const { return UbuntuDevice::Ptr(); } bool Ubuntu::Internal::UbuntuDeviceFactory::canRestore(const QVariantMap &map) const { return ProjectExplorer::IDevice::typeFromMap(map) == Constants::UBUNTU_DEVICE_TYPE_ID; } ProjectExplorer::IDevice::Ptr Ubuntu::Internal::UbuntuDeviceFactory::restore(const QVariantMap &map) const { QTC_ASSERT(canRestore(map), return UbuntuDevice::Ptr()); const ProjectExplorer::IDevice::Ptr device = UbuntuDevice::create(); device->fromMap(map); return device; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuprojectfile.cpp0000644000015301777760000000401112323167147027321 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntuprojectfile.h" using namespace Ubuntu::Internal; UbuntuProjectFile::UbuntuProjectFile(UbuntuProject *parent, QString fileName) : Core::IDocument(parent), m_project(parent), m_fileName(fileName) { QTC_CHECK(m_project); QTC_CHECK(!fileName.isEmpty()); setFilePath(fileName); } bool UbuntuProjectFile::save(QString *, const QString &, bool) { return false; } void UbuntuProjectFile::rename(const QString &newName) { // Can't happen... Q_UNUSED(newName); Q_ASSERT(false); } QString UbuntuProjectFile::fileName() const { return m_fileName; } QString UbuntuProjectFile::defaultPath() const { return QString(); } QString UbuntuProjectFile::suggestedFileName() const { return QString(); } QString UbuntuProjectFile::mimeType() const { return QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE); } bool UbuntuProjectFile::isModified() const { return false; } bool UbuntuProjectFile::isSaveAsAllowed() const { return false; } Core::IDocument::ReloadBehavior UbuntuProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const { Q_UNUSED(state) Q_UNUSED(type) return BehaviorSilent; } bool UbuntuProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType) { Q_UNUSED(errorString) Q_UNUSED(flag) return true; } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupastebinmode.h0000644000015301777760000000177212323167147027145 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUPASTEBINMODE_H #define UBUNTUPASTEBINMODE_H #include "ubuntuwebmode.h" namespace Ubuntu { namespace Internal { class UbuntuPastebinMode : public UbuntuWebMode { Q_OBJECT public: explicit UbuntuPastebinMode(QObject *parent = 0); }; } } #endif // UBUNTUPASTEBINMODE_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingswidget.h0000644000015301777760000000217512323167147027535 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef UBUNTUSETTINGSWIDGET_H #define UBUNTUSETTINGSWIDGET_H #include #include namespace Ui { class UbuntuSettingsWidget; } class UbuntuSettingsWidget : public QWidget { Q_OBJECT public: explicit UbuntuSettingsWidget(QWidget *parent = 0); ~UbuntuSettingsWidget(); void apply(); private: Ui::UbuntuSettingsWidget *ui; QSettings* m_settings; }; #endif // UBUNTUSETTINGSWIDGET_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusecuritypolicypickerdialog.h0000644000015301777760000000305312323167147032132 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #ifndef SECURITYPOLICYPICKERDIALOG_H #define SECURITYPOLICYPICKERDIALOG_H #include #include "ubuntupolicygroupmodel.h" #include "ubuntupolicygroupinfo.h" using namespace Ubuntu::Internal; namespace Ui { class UbuntuSecurityPolicyPickerDialog; } class UbuntuSecurityPolicyPickerDialog : public QDialog { Q_OBJECT public: explicit UbuntuSecurityPolicyPickerDialog(QWidget *parent = 0); ~UbuntuSecurityPolicyPickerDialog(); QStringList selectedPolicyGroups(); protected slots: void on_pushButtonCancel_clicked(); void on_pushButtonAdd_clicked(); void onScanComplete(bool ok); void onInfoChanged(bool ok); void onPolicyClicked(QModelIndex); private: Ui::UbuntuSecurityPolicyPickerDialog *ui; UbuntuPolicyGroupModel m_model; UbuntuPolicyGroupInfo m_info; }; #endif // SECURITYPOLICYPICKERDIALOG_H qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingsdeviceconnectivitypage.cpp0000644000015301777760000000301512323167147033332 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ #include "ubuntusettingsdeviceconnectivitypage.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; UbuntuSettingsDeviceConnectivityPage::UbuntuSettingsDeviceConnectivityPage() : m_widget(0) { setId("A.DeviceConnectivity"); setDisplayName(tr("Devices")); setCategory("Ubuntu"); setDisplayCategory(QLatin1String("Ubuntu")); setCategoryIcon(QLatin1String(Ubuntu::Constants::UBUNTU_SETTINGS_ICON)); } UbuntuSettingsDeviceConnectivityPage::~UbuntuSettingsDeviceConnectivityPage() { } QWidget *UbuntuSettingsDeviceConnectivityPage::createPage(QWidget *parent) { m_widget = new UbuntuSettingsDeviceConnectivityWidget(parent); return m_widget; } void UbuntuSettingsDeviceConnectivityPage::apply() { if (!m_widget) // page was never shown return; m_widget->apply(); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntusettingswidget.ui0000644000015301777760000000436312323167147027724 0ustar pbusernogroup00000000000000 UbuntuSettingsWidget 0 0 619 558 Form Visibility 8 (changing these values will require a restart of the Qt Creator.) Pastebin Wiki Core Apps API IRC Qt::Vertical 20 11 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupastebinmode.cpp0000644000015301777760000000071312323167147027472 0ustar pbusernogroup00000000000000#include "ubuntupastebinmode.h" #include "ubuntuconstants.h" using namespace Ubuntu::Internal; UbuntuPastebinMode::UbuntuPastebinMode(QObject *parent) : UbuntuWebMode(parent) { setDisplayName(tr(Ubuntu::Constants::UBUNTU_MODE_PASTEBIN_DISPLAYNAME)); setId(Ubuntu::Constants::UBUNTU_MODE_PASTEBIN); setObjectName(QLatin1String(Ubuntu::Constants::UBUNTU_MODE_PASTEBIN)); setUrl(QUrl(QLatin1String(Ubuntu::Constants::UBUNTU_PASTEBIN))); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntuclickdialog.ui0000644000015301777760000000477512323167147027134 0ustar pbusernogroup00000000000000 Ubuntu::Internal::UbuntuClickDialog 0 0 940 563 640 480 Run Click 75 true Run Click Exit Status 0 1 0 15 Qt::Horizontal QDialogButtonBox::Close buttonBox accepted() Ubuntu::Internal::UbuntuClickDialog accept() 88 553 157 274 buttonBox rejected() Ubuntu::Internal::UbuntuClickDialog reject() 88 553 286 274 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/ubuntu/ubuntupackagingwidget.ui0000644000015301777760000003013512323167147030004 0ustar pbusernogroup00000000000000 UbuntuPackagingWidget 0 0 975 770 Form 0 0 0 0 0 0 0 color: #DD4818 QFrame::Plain 3 Qt::Horizontal 0 50 Ubuntu 26 Ubuntu Publish Qt::Horizontal 40 20 0 20 false color: rgba(0,0,0,0.2) QFrame::Plain 20 0 Qt::Horizontal 0 0 0 500 0 Click Reload Reset to defaults Create package 0 General Name Title Maintainer Version Security Policy Groups true + Description Framework Manifest AppArmor Excludes Validation Validate Click package 0 0 0 0 Error Information Type: Description: 16777215 80 true true qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/src/plugin.pri0000644000015301777760000000175312323167147023546 0ustar pbusernogroup00000000000000PROVIDER = Canonical ## Where the Qt Creator headers are located at QTCREATOR_SOURCES = $$(QTC_SOURCE) isEmpty(QTCREATOR_SOURCES):QTCREATOR_SOURCES=/usr/src/qtcreator ## Where our plugin will be compiled to IDE_BUILD_TREE = $$(QTC_BUILD) isEmpty(IDE_BUILD_TREE):IDE_BUILD_TREE=../../builddir UBUNTU_LOCAL_BUILD = $$(UBUNTU_QTC_PLUGIN_LOCALBUILD) !isEmpty(UBUNTU_LOCAL_BUILD) { message("!!!!!!!!!!BUILDING LOCAL VERSION OF PLUGIN !!!!!!!!!!!!!!!!!!!") USE_USER_DESTDIR = yes PATHSTR = '\\"$${PWD}/../share/qtcreator\\"' DEFINES += UBUNTU_RESOURCE_PATH_LOCAL=\"$${PATHSTR}\" UBUNTU_BUILD_LOCAL } include($$QTCREATOR_SOURCES/src/qtcreatorplugin.pri) INCLUDEPATH += $$QTCREATOR_SOURCES/src/ ## make sure the QtProject libs are available when building locally !isEmpty(UBUNTU_LOCAL_BUILD) { LIBS += -L$$DESTDIRBASE/QtProject/$$DESTDIRAPPNAME/plugins/$$QTCREATOR_VERSION/QtProject } LIBS += -L$$[QT_INSTALL_LIBS]/qtcreator LIBS += -L$$[QT_INSTALL_LIBS]/qtcreator/plugins/QtProject qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/0000755000015301777760000000000012323167643022042 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/0000755000015301777760000000000012323167643024046 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/0000755000015301777760000000000012323167643026044 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/0000755000015301777760000000000012323167643027527 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/0000755000015301777760000000000012323167643031051 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/0000755000015301777760000000000012323167643032002 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/Makefile0000644000015301777760000000101312323167147033434 0ustar pbusernogroup00000000000000# More information: https://wiki.ubuntu.com/Touch/Testing # # Notes for autopilot tests: # ----------------------------------------------------------- # In order to run autopilot tests: # sudo apt-add-repository ppa:autopilot/ppa # sudo apt-get update # sudo apt-get install python-autopilot autopilot-qt ############################################################# all: autopilot: chmod +x tests/autopilot/run tests/autopilot/run check: qmltestrunner -input tests/unit run: /usr/bin/qmlscene $@ %DISPLAYNAME%.qml qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/0000755000015301777760000000000012323167643033144 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000755000015301777760000000000012323167643033656 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/runqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000755000015301777760000000026312323167147033663 0ustar pbusernogroup00000000000000#!/bin/bash if [[ -z `which autopilot` ]]; then echo "Autopilot is not installed. Skip" exit fi SCRIPTPATH=`dirname $0` pushd ${SCRIPTPATH} autopilot run %DISPLAYNAME% popd ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/displayName/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000755000015301777760000000000012323167643033656 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/displayName/__init__.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000644000015301777760000000742012323167147033662 0ustar pbusernogroup00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- """Ubuntu Touch App autopilot tests.""" from os import remove import os.path from tempfile import mktemp import subprocess from autopilot.input import Mouse, Touch, Pointer from autopilot.matchers import Eventually from autopilot.platform import model from testtools.matchers import Is, Not, Equals from autopilot.testcase import AutopilotTestCase def get_module_include_path(): return os.path.abspath( os.path.join( os.path.dirname(__file__), '..', '..', '..', '..', 'modules') ) class UbuntuTouchAppTestCase(AutopilotTestCase): """A common test case class that provides several useful methods for the tests.""" if model() == 'Desktop': scenarios = [ ('with mouse', dict(input_device_class=Mouse)) ] else: scenarios = [ ('with touch', dict(input_device_class=Touch)) ] @property def main_window(self): return MainWindow(self.app) def setUp(self): self.pointing_device = Pointer(self.input_device_class.create()) super(UbuntuTouchAppTestCase, self).setUp() self.launch_test_qml() def launch_test_qml(self): # If the test class has defined a 'test_qml' class attribute then we # write it to disk and launch it inside the QML Scene. If not, then we # silently do nothing (presumably the test has something else planned). arch = subprocess.check_output(["dpkg-architecture", "-qDEB_HOST_MULTIARCH"]).strip() if hasattr(self, 'test_qml') and isinstance(self.test_qml, basestring): qml_path = mktemp(suffix='.qml') open(qml_path, 'w').write(self.test_qml) self.addCleanup(remove, qml_path) self.app = self.launch_test_application( "/usr/lib/" + arch + "/qt5/bin/qmlscene", "-I", get_module_include_path(), qml_path, app_type='qt') if hasattr(self, 'test_qml_file') and isinstance(self.test_qml_file, basestring): qml_path = self.test_qml_file self.app = self.launch_test_application( "/usr/lib/" + arch + "/qt5/bin/qmlscene", "-I", get_module_include_path(), qml_path, app_type='qt') self.assertThat(self.get_qml_view().visible, Eventually(Equals(True))) def get_qml_view(self): """Get the main QML view""" return self.app.select_single("QQuickView") def get_mainview(self): """Get the QML MainView""" mainView = self.app.select_single("MainView") self.assertThat(mainView, Not(Is(None))) return mainView def get_object(self,objectName): """Get a object based on the objectName""" obj = self.app.select_single(objectName=objectName) self.assertThat(obj, Not(Is(None))) return obj def mouse_click(self,objectName): """Move mouse on top of the object and click on it""" obj = self.get_object(objectName) self.pointing_device.move_to_object(obj) self.pointing_device.click() def mouse_press(self,objectName): """Move mouse on top of the object and press mouse button (without releasing it)""" obj = self.get_object(objectName) self.pointing_device.move_to_object(obj) self.pointing_device.press() def mouse_release(self): """Release mouse button""" self.pointing_device.release() def type_string(self, string): """Type a string with keyboard""" self.keyboard.type(string) def type_key(self, key): """Type a single key with keyboard""" self.keyboard.key(key) ././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/displayName/main/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000755000015301777760000000000012323167643033656 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/displayName/main/__init__.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000644000015301777760000000003612323167147033656 0ustar pbusernogroup00000000000000""" A main.qml test suite """ ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/autopilot/displayName/main/test_main.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/aut0000644000015301777760000000130612323167147033657 0ustar pbusernogroup00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- """Tests for the Hello World""" from autopilot.matchers import Eventually from textwrap import dedent from testtools.matchers import Is, Not, Equals from testtools import skip import os from %DISPLAYNAME% import UbuntuTouchAppTestCase class MainTests(UbuntuTouchAppTestCase): """Generic tests for the Hello World""" test_qml_file = "%s/%s.qml" % (os.path.dirname(os.path.realpath(__file__)),"../../../../%DISPLAYNAME%") def test_0_can_select_mainView(self): """Must be able to select the mainview.""" mainView = self.get_mainview() self.assertThat(mainView.visible,Eventually(Equals(True))) ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/unit/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/uni0000755000015301777760000000000012323167643033660 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/unit/tst_hellocomponent.qmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/tests/uni0000644000015301777760000000224512323167147033664 0ustar pbusernogroup00000000000000import QtQuick 2.0 import QtTest 1.0 import Ubuntu.Components 0.1 import "../../components" // See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html // Execute tests with: // qmltestrunner Item { // The objects HelloComponent { id: objectUnderTest } TestCase { name: "HelloComponent" function init() { console.debug(">> init"); compare("",objectUnderTest.text,"text was not empty on init"); console.debug("<< init"); } function cleanup() { console.debug(">> cleanup"); console.debug("<< cleanup"); } function initTestCase() { console.debug(">> initTestCase"); console.debug("<< initTestCase"); } function cleanupTestCase() { console.debug(">> cleanupTestCase"); console.debug("<< cleanupTestCase"); } function test_canReadAndWriteText() { var expected = "Hello World"; objectUnderTest.text = expected; compare(expected,objectUnderTest.text,"expected did not equal result"); } } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/graphics/0000755000015301777760000000000012323167643033602 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/graphics/toolbarIcon@8.pngqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/tabs/graphics/0000644000015301777760000000443612323167147033612 0ustar pbusernogroup00000000000000PNG  IHDR$$tEXtSoftwareAdobe ImageReadyqe<fiTXtXML:com.adobe.xmp -NIDATxڤXIO:t2vCH! BB\י0Yj:,$c.WW/&H薾q."ʲ̡ߎAt:wa,Ǡ%I2HB<#Ad"dzVŻ]>Ӝ; 3@cAˀe`lü;orfprp]9waf4}Ӵ\+;H#k}L"L8Ƃ~ي|K57fAxf vʊuSSS29DfQ??9ZZ$@r?lx'dkkˍkڱg QdSd@?Hh,6'yw ߂A[ZZ VrnjlT̊U]MQQs`½=fEs'r༁YB_6XP榛A_زuȑ jV3̀.//I1o 6h! 0k LY 4ic^̖Ea]cMӉewnG Q ykp=&n!qr#b 5dM&S;~&33Y[k뛞o6]/Ԙd%A޶t٦V RYj:=|!߼ Q܌U׾!h: JSlMLP*> R߅eɌEb6#YYe=ǵ } Z4#c;/溘tȔG+~$1N>ҵ/C TBNOOU_\rYA2LfKJDmsXxqtK&p&ѢՉP;]2[('/KJ'𸟚 q'b\e2wp `, SQv 0eK<נ =Aʣq9F_4tCgJJg8} q$2U{^P `ۭi;H\&x4s@1yEpKI w/[]]lXxx㣯zؤ'WM 4gmll]=9oQ-O#p> init"); compare("",objectUnderTest.helloWorld,"text was not empty on init"); console.debug("<< init"); } function cleanup() { console.debug(">> cleanup"); console.debug("<< cleanup"); } function initTestCase() { console.debug(">> initTestCase"); console.debug("<< initTestCase"); } function cleanupTestCase() { console.debug(">> cleanupTestCase"); console.debug("<< cleanupTestCase"); } function test_canReadAndWriteText() { var expected = "Hello World 2"; objectUnderTest.helloWorld = expected; compare(expected,objectUnderTest.helloWorld,"expected did not equal result"); } } } ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/displayName.proqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/displa0000644000015301777760000000031512323167147033635 0ustar pbusernogroup00000000000000TEMPLATE = subdirs SUBDIRS = modules/%DISPLAYNAME% check.target = check check.commands = qmltestrunner -import modules -platform ubuntu check.depends = modules/%DISPLAYNAME% QMAKE_EXTRA_TARGETS += check ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000755000015301777760000000000012323167643033646 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000755000015301777760000000000012323167643033646 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/mytype.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000644000015301777760000000020012323167147033637 0ustar pbusernogroup00000000000000#include "mytype.h" MyType::MyType(QObject *parent) : QObject(parent), m_message("") { } MyType::~MyType() { } ././@LongLink0000000000000000000000000000017400000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/backend.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000644000015301777760000000115412323167147033650 0ustar pbusernogroup00000000000000#ifndef BACKEND_PLUGIN_H #define BACKEND_PLUGIN_H #include #include /* ----8<----- import %DISPLAYNAME% 1.0 Rectangle { width: 200 height: 200 MyType { id: helloType } Text { anchors.centerIn: parent text: helloType.helloworld } } -----8<------ */ class BackendPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: void registerTypes(const char *uri); void initializeEngine(QQmlEngine *engine, const char *uri); }; #endif // BACKEND_PLUGIN_H ././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/mytype.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000644000015301777760000000076112323167147033653 0ustar pbusernogroup00000000000000#ifndef MYTYPE_H #define MYTYPE_H #include class MyType : public QObject { Q_OBJECT Q_PROPERTY( QString helloWorld READ helloWorld WRITE setHelloWorld NOTIFY helloWorldChanged ) public: explicit MyType(QObject *parent = 0); ~MyType(); Q_SIGNALS: void helloWorldChanged(); protected: QString helloWorld() { return m_message; } void setHelloWorld(QString msg) { m_message = msg; Q_EMIT helloWorldChanged(); } QString m_message; }; #endif // MYTYPE_H ././@LongLink0000000000000000000000000000020200000000000011207 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/displayName.proqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000644000015301777760000000122212323167147033644 0ustar pbusernogroup00000000000000TEMPLATE = lib TARGET = %DISPLAYNAME% QT += qml quick CONFIG += qt plugin no_keywords #comment in the following line to disable traces DEFINES += QT_NO_DEBUG_OUTPUT TARGET = $$qtLibraryTarget($$TARGET) uri = %DISPLAYNAME% INCLUDEPATH += . # Input HEADERS += backend.h mytype.h SOURCES += backend.cpp mytype.cpp # Install path for the plugin installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /) target.path = $$installPath INSTALLS += target # find files QMLDIR_FILE = qmldir # make visible to qt creator OTHER_FILES += $$QMLDIR_FILE # create install targets for files qmldir.path = $$installPath qmldir.files = $$QMLDIR_FILE INSTALLS += qmldir ././@LongLink0000000000000000000000000000017100000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/qmldirqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000644000015301777760000000005212323167147033644 0ustar pbusernogroup00000000000000module %DISPLAYNAME% plugin %DISPLAYNAME% ././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/modules/displayName/backend.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backend/module0000644000015301777760000000057712323167147033660 0ustar pbusernogroup00000000000000#include #include #include "backend.h" #include "mytype.h" void BackendPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("%DISPLAYNAME%")); qmlRegisterType(uri, 1, 0, "MyType"); } void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { QQmlExtensionPlugin::initializeEngine(engine, uri); } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/0000755000015301777760000000000012323167643033371 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/www/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/w0000755000015301777760000000000012323167643033560 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/www/js/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/w0000755000015301777760000000000012323167643033560 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/www/js/app.jsqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/w0000644000015301777760000000404212323167147033561 0ustar pbusernogroup00000000000000/** * Wait before the DOM has been loaded before initializing the Ubuntu UI layer */ window.onload = function () { var UI = new UbuntuUI(); UI.init(); // Wire all the simple logic document.getElementById('no').addEventListener('click', function() { UI.dialog('dialog1').hide(); }); function getContacts() { return [].slice.call(document.querySelectorAll('#contacts li')); }; var contacts = getContacts(); contacts.forEach(function (contact) { contact.addEventListener('click', function() { contact.classList.add('selected'); }); }); function getSelectedContacts() { var selectedContactInputs = [].slice.call(document.querySelectorAll('#contacts li label input:checked')); return selectedContactInputs.map(function (contactInputElement) { return contactInputElement.parentNode.parentNode; }); } function getContactName(contact) { return contact.querySelector('p').innerHTML; } function displayMessage(message) { document.querySelector('#dialog1 h1').innerHTML = message; UI.dialog('dialog1').show(); }; document.getElementById('call').addEventListener('click', function() { var sc = getSelectedContacts(); if (! sc || sc.length !== 1) { displayMessage('Please select one and only one contact'); return; } displayMessage('Calling: ' + getContactName(sc[0])); }); document.getElementById('text').addEventListener('click', function() { var sc = getSelectedContacts(); if (! sc || sc.length !== 1) { displayMessage('Please select one and only one contact'); return; } displayMessage('Texting: ' + getContactName(sc[0])); }); // Add an event listener that is pending on the initialization // of the platform layer API, if it is being used. document.addEventListener("deviceready", function() { if (console && console.log) console.log('Platform layer API ready'); }, false); }; ././@LongLink0000000000000000000000000000016200000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/www/index.htmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/w0000644000015301777760000001161512323167147033565 0ustar pbusernogroup00000000000000 An Ubuntu HTML5 application
  • Hello World
My List Header
  • Jane

  • Mark

  • Olivier

././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/displayName.desktopqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/html5-simple/d0000644000015301777760000000022112323167147033531 0ustar pbusernogroup00000000000000[Desktop Entry] Name=%DISPLAYNAME% Exec=ubuntu-html5-app-launcher $@ --www=www Icon=qmlscene Terminal=false Type=Application X-Ubuntu-Touch=true ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/projectypes.jsonqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/projectypes.js0000644000015301777760000001647412323167147033771 0ustar pbusernogroup00000000000000[ { "type": "qmlproject", "folder": "simple", "displayName": "Simple UI", "id": "UbuntuAppSimple", "description": "Creates a Qt Quick 2 application project with a sample UI containing a Label and a Button. This project contains QML code only.\n\nIncludes also unit and functional tests.", "mainFile" : "main.qml", "hasTests" : true, "files": [ { "fileName": "displayName.desktop" }, { "fileName": "tests/unit/tst_hellocomponent.qml" }, { "fileName": "components/HelloComponent.qml" }, { "fileName": "Makefile" }, { "fileName": "tests/autopilot/run" }, { "fileName": "tests/autopilot/displayName/test_main.py" }, { "fileName": "tests/autopilot/displayName/__init__.py" } ] }, { "type": "scriptgeneratedproject", "folder": "webapp", "displayName": "Web App", "id": "UbuntuWebApp", "description": "Web App template, for converting a web site into a standalone application. Web Apps are restricted to using available W3C APIs only, unlike HTML5 Apps which have full platform access.", "mainFile": "app.desktop", "hasTests": false, "files": [ { "fileName": "app.json" } ] }, { "type": "qmlproject", "folder": "tabs", "displayName": "Tabbed UI", "id": "UbuntuAppTabs", "description": "Creates a Qt Quick 2 application project using Tabs component. This project contains QML code only.\n\nIncludes also unit and functional tests.", "mainFile" : "main.qml", "hasTests" : true, "files": [ { "fileName": "graphics/toolbarIcon@8.png" }, { "fileName": "displayName.desktop" }, { "fileName": "tests/unit/tst_hellocomponent.qml" }, { "fileName": "components/HelloComponent.qml" }, { "fileName": "ui/WorldTabTools.qml" }, { "fileName": "ui/WorldTab.qml" }, { "fileName": "ui/HelloTab.qml" }, { "fileName": "Makefile" }, { "fileName": "tests/autopilot/run" }, { "fileName": "tests/autopilot/displayName/main/test_main.py" }, { "fileName": "tests/autopilot/displayName/__init__.py" }, { "fileName": "tests/autopilot/displayName/main/__init__.py" } ] }, { "type": "ubuntuhtmlproject", "folder": "html5-simple", "displayName": "HTML5 App", "id": "UbuntuAppSimpleHtml5", "description": "Template for creating a native HTML5 app Native HTML5 apps have unrestricted access to Platform APIs. This project contains only HTML/CSS and Javascript code. \n\nThe UI is designed for a mobile form-factor and uses the Ubuntu Touch design building blocks.\n\nUnlike the default Qt HTML5 template, there is no C++ code or compilation necessary for this application type", "mainFile" : "www/index.html", "files": [ { "fileName": "displayName.desktop" }, { "fileName": "www/js/app.js" }, { "fileName": "www/plugins.xml" } ] }, { "type": "pro", "folder": "backend", "displayName": "QtQuick2 Extension Library", "id": "UbuntuAppWBackend", "description": "A simple C++ based QtQuick2 Extension Library.\n\nIncludes also a unit test.", "mainFile" : "modules/displayName/backend.h", "projectFile" : "displayName.pro", "files": [ { "fileName": "modules/displayName/displayName.pro" }, { "fileName": "modules/displayName/backend.cpp" }, { "fileName": "modules/displayName/mytype.h" }, { "fileName": "modules/displayName/mytype.cpp" }, { "fileName": "modules/displayName/qmldir" }, { "fileName": "tests/unit/tst_mytype.qml" } ] }, { "type": "cmake", "folder": "backendplustabs", "displayName": "QML Extension Library + Tabbed UI", "id": "UbuntuAppWBackendPlusTabsCMake", "description": "A simple C++ based QtQuick2 Extension Library with\nTabbed UI written in QML.\n\nIncludes also\n - a unit test for C++\n - unit and functional tests for QML\n", "mainFile" : "backend/modules/displayName/backend.h", "projectFile" : "CMakeLists.txt", "files": [ { "fileName": "backend/CMakeLists.txt" }, { "fileName": "backend/modules/displayName/backend.cpp" }, { "fileName": "backend/modules/displayName/mytype.h" }, { "fileName": "backend/modules/displayName/mytype.cpp" }, { "fileName": "backend/modules/displayName/qmldir" }, { "fileName": "backend/tests/unit/tst_mytype.qml" }, { "fileName": "app/graphics/toolbarIcon@8.png" }, { "fileName": "app/displayName.desktop.in" }, { "fileName": "app/displayName.qml" }, { "fileName": "app/tests/unit/tst_hellocomponent.qml" }, { "fileName": "app/components/CMakeLists.txt" }, { "fileName": "app/components/HelloComponent.qml" }, { "fileName": "app/ui/CMakeLists.txt" }, { "fileName": "app/ui/WorldTabTools.qml" }, { "fileName": "app/ui/WorldTab.qml" }, { "fileName": "app/ui/HelloTab.qml" }, { "fileName": "app/CMakeLists.txt" }, { "fileName": "app/tests/autopilot/run" }, { "fileName": "app/tests/autopilot/displayName/main/test_main.py" }, { "fileName": "app/tests/autopilot/displayName/__init__.py" }, { "fileName": "app/tests/autopilot/displayName/main/__init__.py" }, { "fileName": "cmake/Click.cmake"} ] }, { "type": "cmake", "folder": "scope", "displayName": "Unity Scope Template", "id": "UbuntuUnityScope", "description": "A Unity Scope template", "mainFile" : "src/displayName-scope.cpp", "projectFile" : "CMakeLists.txt", "requiredFeature": "Ubuntu.Wizards.FeatureUnityScope", "files": [ { "fileName": "src/displayName-preview.cpp" }, { "fileName": "src/CMakeLists.txt" }, { "fileName": "src/displayName-preview.h" }, { "fileName": "src/displayName-query.cpp" }, { "fileName": "src/displayName-query.h" }, { "fileName": "src/displayName-scope.h" }, { "fileName": "data/displayName-scope.ini.in" }, { "fileName": "data/CMakeLists.txt" }, { "fileName": "test/simpletest.cpp" }, { "fileName": "test/CMakeLists.txt" }, { "fileName": "readme.txt" } ] } ] qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/0000755000015301777760000000000012323167643032342 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/Makefileqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/Makefil0000644000015301777760000000101312323167147033627 0ustar pbusernogroup00000000000000# More information: https://wiki.ubuntu.com/Touch/Testing # # Notes for autopilot tests: # ----------------------------------------------------------- # In order to run autopilot tests: # sudo apt-add-repository ppa:autopilot/ppa # sudo apt-get update # sudo apt-get install python-autopilot autopilot-qt ############################################################# all: autopilot: chmod +x tests/autopilot/run tests/autopilot/run check: qmltestrunner -input tests/unit run: /usr/bin/qmlscene $@ %DISPLAYNAME%.qml qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/0000755000015301777760000000000012323167643033504 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/autopilot/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/a0000755000015301777760000000000012323167643033645 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/autopilot/runqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/a0000755000015301777760000000026312323167147033652 0ustar pbusernogroup00000000000000#!/bin/bash if [[ -z `which autopilot` ]]; then echo "Autopilot is not installed. Skip" exit fi SCRIPTPATH=`dirname $0` pushd ${SCRIPTPATH} autopilot run %DISPLAYNAME% popd ././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/autopilot/displayName/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/a0000755000015301777760000000000012323167643033645 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/autopilot/displayName/__init__.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/a0000644000015301777760000000460012323167147033646 0ustar pbusernogroup00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- """Ubuntu Touch App autopilot tests.""" import os import subprocess from autopilot import input, platform from autopilot.matchers import Eventually from testtools.matchers import Equals from ubuntuuitoolkit import base, emulators def _get_module_include_path(): return os.path.join(get_path_to_source_root(), 'modules') def get_path_to_source_root(): return os.path.abspath( os.path.join( os.path.dirname(__file__), '..', '..', '..', '..')) class ClickAppTestCase(base.UbuntuUIToolkitAppTestCase): """Common test case that provides several useful methods for the tests.""" package_id = '' # TODO app_name = '%DISPLAYNAME%' def setUp(self): super(ClickAppTestCase, self).setUp() self.pointing_device = input.Pointer(self.input_device_class.create()) self.launch_application() self.assertThat(self.main_view.visible, Eventually(Equals(True))) def launch_application(self): if platform.model() == 'Desktop': self._launch_application_from_desktop() else: self._launch_application_from_phablet() def _launch_application_from_desktop(self): app_qml_source_location = self._get_app_qml_source_path() if os.path.exists(app_qml_source_location): self.app = self.launch_test_application( base.get_qmlscene_launch_command(), '-I' + _get_module_include_path(), app_qml_source_location, app_type='qt', emulator_base=emulators.UbuntuUIToolkitEmulatorBase) else: raise NotImplementedError( "On desktop we can't install click packages yet, so we can " "only run from source.") def _get_app_qml_source_path(self): qml_file_name = '{0}.qml'.format(self.app_name) return os.path.join(self._get_path_to_app_source(), qml_file_name) def _get_path_to_app_source(self): return os.path.join(get_path_to_source_root(), self.app_name) def _launch_application_from_phablet(self): # On phablet, we only run the tests against the installed click # package. self.app = self.launch_click_package(self.pacakge_id, self.app_name) @property def main_view(self): return self.app.select_single(emulators.MainView) ././@LongLink0000000000000000000000000000020600000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/autopilot/displayName/test_main.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/a0000644000015301777760000000141712323167147033651 0ustar pbusernogroup00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- """Tests for the Hello World""" import os from autopilot.matchers import Eventually from testtools.matchers import Equals import %DISPLAYNAME% class MainViewTestCase(%DISPLAYNAME%.ClickAppTestCase): """Generic tests for the Hello World""" def test_initial_label(self): label = self.main_view.select_single(objectName='label') self.assertThat(label.text, Equals('Hello..')) def test_click_button_should_update_label(self): button = self.main_view.select_single(objectName='button') self.pointing_device.click_object(button) label = self.main_view.select_single(objectName='label') self.assertThat(label.text, Eventually(Equals('..world!'))) ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/unit/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/u0000755000015301777760000000000012323167643033671 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017700000000000011222 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/unit/tst_hellocomponent.qmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/tests/u0000644000015301777760000000224512323167147033675 0ustar pbusernogroup00000000000000import QtQuick 2.0 import QtTest 1.0 import Ubuntu.Components 0.1 import "../../components" // See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html // Execute tests with: // qmltestrunner Item { // The objects HelloComponent { id: objectUnderTest } TestCase { name: "HelloComponent" function init() { console.debug(">> init"); compare("",objectUnderTest.text,"text was not empty on init"); console.debug("<< init"); } function cleanup() { console.debug(">> cleanup"); console.debug("<< cleanup"); } function initTestCase() { console.debug(">> initTestCase"); console.debug("<< initTestCase"); } function cleanupTestCase() { console.debug(">> cleanupTestCase"); console.debug("<< cleanupTestCase"); } function test_canReadAndWriteText() { var expected = "Hello World"; objectUnderTest.text = expected; compare(expected,objectUnderTest.text,"expected did not equal result"); } } } ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/components/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/compone0000755000015301777760000000000012323167643033723 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/components/HelloComponent.qmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/compone0000644000015301777760000000032012323167147033717 0ustar pbusernogroup00000000000000import QtQuick 2.0 import Ubuntu.Components 0.1 UbuntuShape { width: 200 height: width property alias text : myText.text Label { id: myText anchors.centerIn: parent } } ././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/displayName.desktopqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/display0000644000015301777760000000025212323167147033730 0ustar pbusernogroup00000000000000[Desktop Entry] Name=%DISPLAYNAME% Exec=/usr/bin/qmlscene $@ /usr/share/%DISPLAYNAME%/%DISPLAYNAME%.qml Icon=qmlscene Terminal=false Type=Application X-Ubuntu-Touch=true ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/main.qmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/simple/main.qm0000644000015301777760000000232112323167147033622 0ustar pbusernogroup00000000000000import QtQuick 2.0 import Ubuntu.Components 0.1 import "components" /*! \brief MainView with a Label and Button elements. */ MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "com.ubuntu.developer.%BZR_USERNAME%.%DISPLAYNAME%" /* This property enables the application to change orientation when the device is rotated. The default is false. */ //automaticOrientation: true width: units.gu(100) height: units.gu(75) Page { title: i18n.tr("Simple") Column { spacing: units.gu(1) anchors { margins: units.gu(2) fill: parent } HelloComponent { id: label objectName: "label" text: i18n.tr("Hello..") } Button { objectName: "button" width: parent.width text: i18n.tr("Tap me!") onClicked: { label.text = i18n.tr("..world!") } } } } } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/cmake/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/cmake/Click.cmakeqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000152112323167147033754 0ustar pbusernogroup00000000000000if(CLICK_MODE) STRING(REPLACE "/usr/" "/" QT_IMPORTS_DIR ${QT_IMPORTS_DIR}) set(CMAKE_INSTALL_PREFIX /) set(CMAKE_INSTALL_BINDIR /) set(DATA_DIR /) set(EXEC "qmlscene $@ -I .${QT_IMPORTS_DIR} ${%DISPLAYNAME_UPPER%_DIR}/${MAIN_QML}") set(DESKTOP_DIR ${DATA_DIR}) set(ICON ".${DATA_DIR}/${ICON}") install(FILES manifest.json DESTINATION ${CMAKE_INSTALL_PREFIX}) install(DIRECTORY "app/graphics" DESTINATION ${DATA_DIR}) install(FILES "${CMAKE_PROJECT_NAME}.json" DESTINATION ${DATA_DIR}) else(CLICK_MODE) set(DATA_DIR ${CMAKE_INSTALL_DATADIR}/${APP_NAME}) set(EXEC "qmlscene $@ ${CMAKE_INSTALL_PREFIX}/${DATA_DIR}/qml/${MAIN_QML}") set(ICON "${CMAKE_INSTALL_PREFIX}/${DATA_DIR}/${ICON}") set(DESKTOP_DIR ${CMAKE_INSTALL_DATADIR}/applications) endif(CLICK_MODE) ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/tests/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017200000000000011215 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/tests/unit/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000021000000000000011206 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/tests/unit/tst_mytype.qmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000225012323167147033754 0ustar pbusernogroup00000000000000import QtQuick 2.0 import QtTest 1.0 import Ubuntu.Components 0.1 import %DISPLAYNAME% 1.0 // See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html // Execute tests with: // qmltestrunner Item { // The objects MyType { id: objectUnderTest } TestCase { name: "MyType" function init() { console.debug(">> init"); compare("",objectUnderTest.helloWorld,"text was not empty on init"); console.debug("<< init"); } function cleanup() { console.debug(">> cleanup"); console.debug("<< cleanup"); } function initTestCase() { console.debug(">> initTestCase"); console.debug("<< initTestCase"); } function cleanupTestCase() { console.debug(">> cleanupTestCase"); console.debug("<< cleanupTestCase"); } function test_canReadAndWriteText() { var expected = "Hello World 2"; objectUnderTest.helloWorld = expected; compare(expected,objectUnderTest.helloWorld,"expected did not equal result"); } } } ././@LongLink0000000000000000000000000000017500000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/CMakeLists.txtqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000151612323167147033760 0ustar pbusernogroup00000000000000include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) set( %DISPLAYNAME%backend_SRCS modules/%DISPLAYNAME%/backend.cpp modules/%DISPLAYNAME%/mytype.cpp ) add_library(%DISPLAYNAME%backend MODULE ${%DISPLAYNAME%backend_SRCS} ) set_target_properties(%DISPLAYNAME%backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY %DISPLAYNAME%) qt5_use_modules(%DISPLAYNAME%backend Gui Qml Quick) # Copy qmldir file to build dir for running in QtCreator add_custom_target(%DISPLAYNAME%backend-qmldir ALL COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/modules/%DISPLAYNAME%/qmldir ${CMAKE_CURRENT_BINARY_DIR}/%DISPLAYNAME% DEPENDS ${QMLFILES} ) # Install plugin file install(TARGETS %DISPLAYNAME%backend DESTINATION ${QT_IMPORTS_DIR}/%DISPLAYNAME%/) install(FILES modules/%DISPLAYNAME%/qmldir DESTINATION ${QT_IMPORTS_DIR}/%DISPLAYNAME%/) ././@LongLink0000000000000000000000000000016700000000000011221 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000020300000000000011210 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/displayName/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000021500000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/displayName/mytype.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000020012323167147033745 0ustar pbusernogroup00000000000000#include "mytype.h" MyType::MyType(QObject *parent) : QObject(parent), m_message("") { } MyType::~MyType() { } ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/displayName/backend.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000115412323167147033756 0ustar pbusernogroup00000000000000#ifndef BACKEND_PLUGIN_H #define BACKEND_PLUGIN_H #include #include /* ----8<----- import %DISPLAYNAME% 1.0 Rectangle { width: 200 height: 200 MyType { id: helloType } Text { anchors.centerIn: parent text: helloType.helloworld } } -----8<------ */ class BackendPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: void registerTypes(const char *uri); void initializeEngine(QQmlEngine *engine, const char *uri); }; #endif // BACKEND_PLUGIN_H ././@LongLink0000000000000000000000000000021300000000000011211 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/displayName/mytype.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000076112323167147033761 0ustar pbusernogroup00000000000000#ifndef MYTYPE_H #define MYTYPE_H #include class MyType : public QObject { Q_OBJECT Q_PROPERTY( QString helloWorld READ helloWorld WRITE setHelloWorld NOTIFY helloWorldChanged ) public: explicit MyType(QObject *parent = 0); ~MyType(); Q_SIGNALS: void helloWorldChanged(); protected: QString helloWorld() { return m_message; } void setHelloWorld(QString msg) { m_message = msg; Q_EMIT helloWorldChanged(); } QString m_message; }; #endif // MYTYPE_H ././@LongLink0000000000000000000000000000021100000000000011207 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/displayName/qmldirqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000006112323167147033752 0ustar pbusernogroup00000000000000module %DISPLAYNAME% plugin %DISPLAYNAME%backend ././@LongLink0000000000000000000000000000021600000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/backend/modules/displayName/backend.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000057712323167147033766 0ustar pbusernogroup00000000000000#include #include #include "backend.h" #include "mytype.h" void BackendPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("%DISPLAYNAME%")); qmlRegisterType(uri, 1, 0, "MyType"); } void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { QQmlExtensionPlugin::initializeEngine(engine, uri); } ././@LongLink0000000000000000000000000000016500000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/CMakeLists.txtqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000376312323167147033766 0ustar pbusernogroup00000000000000project(%DISPLAYNAME% C CXX) cmake_minimum_required(VERSION 2.8.9) set (UBUNTU_PROJECT_TYPE "ClickApp" CACHE INTERNAL "Tells QtCreator this is a Click application project") set (CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") find_package(Qt5Core) find_package(Qt5Qml) find_package(Qt5Quick) #find_package(ubuntu-sdk-libs) #automatically create moc files set(CMAKE_AUTOMOC ON) # components PATH execute_process( COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH OUTPUT_VARIABLE ARCH_TRIPLET OUTPUT_STRIP_TRAILING_WHITESPACE ) set(QT_IMPORTS_DIR "lib/${ARCH_TRIPLET}") option(INSTALL_TESTS "Install the tests on make install" on) set(APP_NAME %DISPLAYNAME%) set(%DISPLAYNAME_UPPER%_DIR "share/qml/%DISPLAYNAME%") set(MAIN_QML "%DISPLAYNAME%.qml") set(ICON "grapics/toolbarIcon@8.png") #set install paths set(CMAKE_INSTALL_PREFIX /) set(DATA_DIR /) set(DESKTOP_DIR ${DATA_DIR}) set(ICON ".${DATA_DIR}/${ICON}") set(EXEC "qmlscene $@ ${%DISPLAYNAME_UPPER%_DIR}/${MAIN_QML}") install(FILES manifest.json DESTINATION ${CMAKE_INSTALL_PREFIX}) install(DIRECTORY "app/graphics" DESTINATION ${DATA_DIR}) install(FILES "${CMAKE_PROJECT_NAME}.json" DESTINATION ${DATA_DIR}) add_subdirectory(app) add_subdirectory(backend) add_custom_target("autopilot" chmod +x ${CMAKE_SOURCE_DIR}/app/tests/autopilot/run COMMAND ${CMAKE_SOURCE_DIR}/app/tests/autopilot/run DEPENDS %DISPLAYNAME%backend %DISPLAYNAME%backend-qmldir WORKING_DIRECTORY ./app) add_custom_target("check" /usr/bin/qmltestrunner -input ${CMAKE_SOURCE_DIR}/app/tests/unit -import ${CMAKE_BINARY_DIR}/backend DEPENDS %DISPLAYNAME%backend %DISPLAYNAME%backend-qmldir WORKING_DIRECTORY ./app) add_custom_target("run" /usr/bin/qmlscene -I ${CMAKE_BINARY_DIR}/backend ${CMAKE_SOURCE_DIR}/app/%DISPLAYNAME%.qml DEPENDS %DISPLAYNAME%backend %DISPLAYNAME%backend-qmldir WORKING_DIRECTORY ./app) ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016100000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017300000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000017600000000000011221 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/runqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000026312323167147033761 0ustar pbusernogroup00000000000000#!/bin/bash if [[ -z `which autopilot` ]]; then echo "Autopilot is not installed. Skip" exit fi SCRIPTPATH=`dirname $0` pushd ${SCRIPTPATH} autopilot run %DISPLAYNAME% popd ././@LongLink0000000000000000000000000000020700000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/displayName/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000022200000000000011211 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/displayName/__init__.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000744712323167147033771 0ustar pbusernogroup00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- """Ubuntu Touch App autopilot tests.""" from os import remove import os.path from tempfile import mktemp import subprocess from autopilot.input import Mouse, Touch, Pointer from autopilot.matchers import Eventually from autopilot.platform import model from testtools.matchers import Is, Not, Equals from autopilot.testcase import AutopilotTestCase def get_module_include_path(): return os.path.abspath( os.path.join( os.path.dirname(__file__), '..', '..', '..', '..', 'backend', 'modules') ) class UbuntuTouchAppTestCase(AutopilotTestCase): """A common test case class that provides several useful methods for the tests.""" if model() == 'Desktop': scenarios = [ ('with mouse', dict(input_device_class=Mouse)) ] else: scenarios = [ ('with touch', dict(input_device_class=Touch)) ] @property def main_window(self): return MainWindow(self.app) def setUp(self): self.pointing_device = Pointer(self.input_device_class.create()) super(UbuntuTouchAppTestCase, self).setUp() self.launch_test_qml() def launch_test_qml(self): # If the test class has defined a 'test_qml' class attribute then we # write it to disk and launch it inside the QML Scene. If not, then we # silently do nothing (presumably the test has something else planned). arch = subprocess.check_output(["dpkg-architecture", "-qDEB_HOST_MULTIARCH"]).strip() if hasattr(self, 'test_qml') and isinstance(self.test_qml, basestring): qml_path = mktemp(suffix='.qml') open(qml_path, 'w').write(self.test_qml) self.addCleanup(remove, qml_path) self.app = self.launch_test_application( "/usr/lib/" + arch + "/qt5/bin/qmlscene", "-I", get_module_include_path(), qml_path, app_type='qt') if hasattr(self, 'test_qml_file') and isinstance(self.test_qml_file, basestring): qml_path = self.test_qml_file self.app = self.launch_test_application( "/usr/lib/" + arch + "/qt5/bin/qmlscene", "-I", get_module_include_path(), qml_path, app_type='qt') self.assertThat(self.get_qml_view().visible, Eventually(Equals(True))) def get_qml_view(self): """Get the main QML view""" return self.app.select_single("QQuickView") def get_mainview(self): """Get the QML MainView""" mainView = self.app.select_single("MainView") self.assertThat(mainView, Not(Is(None))) return mainView def get_object(self,objectName): """Get a object based on the objectName""" obj = self.app.select_single(objectName=objectName) self.assertThat(obj, Not(Is(None))) return obj def mouse_click(self,objectName): """Move mouse on top of the object and click on it""" obj = self.get_object(objectName) self.pointing_device.move_to_object(obj) self.pointing_device.click() def mouse_press(self,objectName): """Move mouse on top of the object and press mouse button (without releasing it)""" obj = self.get_object(objectName) self.pointing_device.move_to_object(obj) self.pointing_device.press() def mouse_release(self): """Release mouse button""" self.pointing_device.release() def type_string(self, string): """Type a string with keyboard""" self.keyboard.type(string) def type_key(self, key): """Type a single key with keyboard""" self.keyboard.key(key) ././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/displayName/main/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000022700000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/displayName/main/__init__.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000003612323167147033754 0ustar pbusernogroup00000000000000""" A main.qml test suite """ ././@LongLink0000000000000000000000000000023000000000000011210 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/autopilot/displayName/main/test_main.pyqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000130612323167147033755 0ustar pbusernogroup00000000000000# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- """Tests for the Hello World""" from autopilot.matchers import Eventually from textwrap import dedent from testtools.matchers import Is, Not, Equals from testtools import skip import os from %DISPLAYNAME% import UbuntuTouchAppTestCase class MainTests(UbuntuTouchAppTestCase): """Generic tests for the Hello World""" test_qml_file = "%s/%s.qml" % (os.path.dirname(os.path.realpath(__file__)),"../../../../%DISPLAYNAME%") def test_0_can_select_mainView(self): """Must be able to select the mainview.""" mainView = self.get_mainview() self.assertThat(mainView.visible,Eventually(Equals(True))) ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/unit/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000021400000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/tests/unit/tst_hellocomponent.qmlqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000224512323167147033760 0ustar pbusernogroup00000000000000import QtQuick 2.0 import QtTest 1.0 import Ubuntu.Components 0.1 import "../../components" // See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html // Execute tests with: // qmltestrunner Item { // The objects HelloComponent { id: objectUnderTest } TestCase { name: "HelloComponent" function init() { console.debug(">> init"); compare("",objectUnderTest.text,"text was not empty on init"); console.debug("<< init"); } function cleanup() { console.debug(">> cleanup"); console.debug("<< cleanup"); } function initTestCase() { console.debug(">> initTestCase"); console.debug("<< initTestCase"); } function cleanupTestCase() { console.debug(">> cleanupTestCase"); console.debug("<< cleanupTestCase"); } function test_canReadAndWriteText() { var expected = "Hello World"; objectUnderTest.text = expected; compare(expected,objectUnderTest.text,"expected did not equal result"); } } } ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/graphics/qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000755000015301777760000000000012323167643033754 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000020500000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustabs/app/graphics/toolbarIcon@8.pngqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/backendplustab0000644000015301777760000000443612323167147033764 0ustar pbusernogroup00000000000000PNG  IHDR$$tEXtSoftwareAdobe ImageReadyqe<fiTXtXML:com.adobe.xmp -NIDATxڤXIO:t2vCH! BB\י0Yj:,$c.WW/&H薾q."ʲ̡ߎAt:wa,Ǡ%I2HB<#Ad"dzVŻ]>Ӝ; 3@cAˀe`lü;orfprp]9waf4}Ӵ\+;H#k}L"L8Ƃ~ي|K57fAxf vʊuSSS29DfQ??9ZZ$@r?lx'dkkˍkڱg QdSd@?Hh,6'yw ߂A[ZZ VrnjlT̊U]MQQs`½=fEs'r༁YB_6XP榛A_زuȑ jV3̀.//I1o 6h! 0k LY 4ic^̖Ea]cMӉewnG Q ykp=&n!qr#b 5dM&S;~&33Y[k뛞o6]/Ԙd%A޶t٦V RYj:=|!߼ Q܌U׾!h: JSlMLP*> R߅eɌEb6#YYe=ǵ } Z4#c;/溘tȔG+~$1N>ҵ/C TBNOOU_\rYA2LfKJDmsXxqtK&p&ѢՉP;]2[('/KJ'𸟚 q'b\e2wp `, SQv 0eK<נ =Aʣq9F_4tCgJJg8} q$2U{^P `ۭi;H\&x4s@1yEpKI w/[]]lXxx㣯zؤ'WM 4gmll]=9oQ-O#p=0.4.0 REQUIRED) add_subdirectory(src) add_subdirectory(data) enable_testing() add_subdirectory(test) qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/0000755000015301777760000000000012323167643032751 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/disp0000644000015301777760000000063512323167147033636 0ustar pbusernogroup00000000000000#include #include class %DISPLAYNAME_CAPITAL%Query : public unity::scopes::SearchQueryBase { public: %DISPLAYNAME_CAPITAL%Query(std::string const& query); ~%DISPLAYNAME_CAPITAL%Query(); virtual void cancelled() override; virtual void run(unity::scopes::SearchReplyProxy const& reply) override; private: std::string query_; }; ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/disp0000644000015301777760000000065612323167147033641 0ustar pbusernogroup00000000000000#ifndef DEMOPREVIEW_H #define DEMOPREVIEW_H #include class %DISPLAYNAME_CAPITAL%Preview : public unity::scopes::PreviewQueryBase { public: %DISPLAYNAME_CAPITAL%Preview(std::string const& uri); ~%DISPLAYNAME_CAPITAL%Preview(); virtual void cancelled() override; virtual void run(unity::scopes::PreviewReplyProxy const& reply) override; private: std::string uri_; }; #endif ././@LongLink0000000000000000000000000000017000000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/disp0000644000015301777760000000273112323167147033635 0ustar pbusernogroup00000000000000#include"%DISPLAYNAME%-preview.h" #include #include #include using namespace unity::scopes; %DISPLAYNAME_CAPITAL%Preview::%DISPLAYNAME_CAPITAL%Preview(std::string const& uri) : uri_(uri) { } %DISPLAYNAME_CAPITAL%Preview::~%DISPLAYNAME_CAPITAL%Preview() { } void %DISPLAYNAME_CAPITAL%Preview::cancelled() { } void %DISPLAYNAME_CAPITAL%Preview::run(unity::scopes::PreviewReplyProxy const& reply) { PreviewWidgetList widgets; widgets.emplace_back(PreviewWidget(R"({"id": "header", "type": "header", "title": "title", "subtitle": "author", "rating": "rating"})")); widgets.emplace_back(PreviewWidget(R"({"id": "img", "type": "image", "art": "screenshot-url"})")); PreviewWidget w("img2", "image"); w.add_attribute_value("zoomable", Variant(false)); w.add_attribute_mapping("art", "screenshot-url"); widgets.emplace_back(w); ColumnLayout layout1col(1); layout1col.add_column({"header", "title"}); ColumnLayout layout2col(2); layout2col.add_column({"header", "title"}); layout2col.add_column({"author", "rating"}); ColumnLayout layout3col(3); layout3col.add_column({"header", "title"}); layout3col.add_column({"author"}); layout3col.add_column({"rating"}); reply->register_layout({layout1col, layout2col, layout3col}); reply->push(widgets); reply->push("author", Variant("Foo")); reply->push("rating", Variant("4 blah")); } ././@LongLink0000000000000000000000000000016400000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.hqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/disp0000644000015301777760000000134412323167147033634 0ustar pbusernogroup00000000000000#ifndef DEMOSCOPE_H #define DEMOSCOPE_H #include #include #include #include #include class %DISPLAYNAME_CAPITAL%Scope : public unity::scopes::ScopeBase { public: virtual int start(std::string const&, unity::scopes::RegistryProxy const&) override; virtual void stop() override; unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&, const unity::scopes::ActionMetadata&) override; virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const& q, unity::scopes::SearchMetadata const&) override; }; #endif ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/CMakeLists.txtqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/CMak0000644000015301777760000000050312323167147033504 0ustar pbusernogroup00000000000000add_library(${SCOPE_NAME} SHARED %DISPLAYNAME%-preview.cpp %DISPLAYNAME%-query.cpp %DISPLAYNAME%-scope.cpp) target_link_libraries(${SCOPE_NAME} ${UNITY_SCOPES_LDFLAGS}) set_property(TARGET ${SCOPE_NAME} PROPERTY COMPILE_FLAGS ${UNITY_SCOPES_CFLAGS}) install(TARGETS ${SCOPE_NAME} LIBRARY DESTINATION ${SCOPE_INSTALLDIR} ) ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/disp0000644000015301777760000000234012323167147033631 0ustar pbusernogroup00000000000000#include "%DISPLAYNAME%-scope.h" #include "%DISPLAYNAME%-query.h" #include "%DISPLAYNAME%-preview.h" #include using namespace unity::scopes; int %DISPLAYNAME_CAPITAL%Scope::start(std::string const&, unity::scopes::RegistryProxy const&) { return VERSION; } void %DISPLAYNAME_CAPITAL%Scope::stop() { } SearchQueryBase::UPtr %DISPLAYNAME_CAPITAL%Scope::search(unity::scopes::CannedQuery const &q, unity::scopes::SearchMetadata const&) { unity::scopes::SearchQueryBase::UPtr query(new %DISPLAYNAME_CAPITAL%Query(q.query_string())); return query; } PreviewQueryBase::UPtr %DISPLAYNAME_CAPITAL%Scope::preview(Result const& result, ActionMetadata const& /*metadata*/) { unity::scopes::PreviewQueryBase::UPtr preview(new %DISPLAYNAME_CAPITAL%Preview(result.uri())); return preview; } #define EXPORT __attribute__ ((visibility ("default"))) extern "C" { EXPORT unity::scopes::ScopeBase* // cppcheck-suppress unusedFunction UNITY_SCOPE_CREATE_FUNCTION() { return new %DISPLAYNAME_CAPITAL%Scope(); } EXPORT void // cppcheck-suppress unusedFunction UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { delete scope_base; } } ././@LongLink0000000000000000000000000000016600000000000011220 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.cppqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/src/disp0000644000015301777760000000202612323167147033632 0ustar pbusernogroup00000000000000#include "%DISPLAYNAME%-query.h" #include #include #include #include #include using namespace unity::scopes; %DISPLAYNAME_CAPITAL%Query::%DISPLAYNAME_CAPITAL%Query(std::string const& query) : query_(query) { } %DISPLAYNAME_CAPITAL%Query::~%DISPLAYNAME_CAPITAL%Query() { } void %DISPLAYNAME_CAPITAL%Query::cancelled() { } void %DISPLAYNAME_CAPITAL%Query::run(unity::scopes::SearchReplyProxy const& reply) { CategoryRenderer rdr; auto cat = reply->register_category("cat1", "Category 1", "", rdr); CategorisedResult res(cat); res.set_uri("uri"); res.set_title("scope-A: result 1 for query \"" + query_ + "\""); res.set_art("icon"); res.set_dnd_uri("dnd_uri"); reply->push(res); CannedQuery q("scope-A", query_, ""); Annotation annotation(Annotation::Type::Link); annotation.add_link("More...", q); reply->register_annotation(annotation); } ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/readme.txtqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/scope/readme.t0000644000015301777760000000067112323167147033607 0ustar pbusernogroup00000000000000Unity scope template This project contains a simple Unity Scope and all files needed to build and deploy it. Building it is simple. First you need to install the scopes development package and CMake. Then you go into the source root and type the following commands. mkdir build cd build cmake -DCMAKE_BUILD_TYPE=debug .. make (make install) The build system uses standard CMake conventions. See CMake's documentation for further details. qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/webapp/0000755000015301777760000000000012323167643032327 5ustar pbusernogroup00000000000000././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/webapp/app.desktopqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/webapp/app.des0000644000015301777760000000034512323167147033605 0ustar pbusernogroup00000000000000[Desktop Entry] Name=%DISPLAYNAME% Type=Application Icon=app.png Exec=webbrowser-app --webapp --enable-back-forward --webappUrlPatterns=https?://m.%DISPLAYNAME%.com/* http://m.%DISPLAYNAME%.com Terminal=false X-Ubuntu-Touch=true ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/webapp/app.jsonqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/templates/wizards/ubuntu/webapp/app.jso0000644000015301777760000000013212323167147033617 0ustar pbusernogroup00000000000000{ "template": "ubuntu-webapp", "policy_groups": [ "networking" ], "policy_version": 1.0 } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/0000755000015301777760000000000012323167643025370 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/0000755000015301777760000000000012323167643027023 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/welcome.qmlproject0000644000015301777760000000070112323167147032555 0ustar pbusernogroup00000000000000/* File generated by Qt Creator, version 2.7.0 */ import QmlProject 1.1 Project { mainFile: "welcome.qml" /* Include .qml, .js, and image files from current directory and subdirectories */ QmlFiles { directory: "." } JavaScriptFiles { directory: "." } ImageFiles { directory: "." } /* List of plugin directories passed to QML runtime */ // importPaths: [ "../exampleplugin" ] } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/welcome.qml0000644000015301777760000001647312323167161031177 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ import QtQuick 1.1 Rectangle { color: "#F7F6F5" property int maximumWidth : 900 property int maximumHeight: 579 Image { anchors.fill: parent fillMode: Image.Tile source: "images/bg_dotted.png" } Rectangle { anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top anchors.bottom: parent.bottom height: maximumHeight width: parent.width>maximumWidth ? maximumWidth : parent.width color: "#fff" Image { anchors.top: parent.top anchors.topMargin: 10 anchors.right: parent.right source: "images/devices.png" width: parent.width/2 fillMode: Image.PreserveAspectFit } Rectangle { color: "transparent" anchors.margins: 20 anchors.top: parent.top anchors.topMargin: 40 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter width: parent.width - anchors.margins*2 Column { id: headerColumn spacing: 20 anchors.top: parent.top anchors.left: parent.left width: parent.width/2 Text { width: parent.width wrapMode: Text.WordWrap font.family: "Ubuntu" font.weight: Font.Light font.pointSize: 42 font.letterSpacing: 2 text: "Make it Ubuntu" } Text { wrapMode: Text.WordWrap width: parent.width font.family: "Ubuntu" font.weight: Font.Light font.pointSize: 20 font.letterSpacing: 1.5 textFormat: Text.RichText text: "Get started today with the Ubuntu SDK Preview and the App Design Guides." onLinkActivated: { Qt.openUrlExternally(link); } } } Column { id: topLinks anchors.topMargin: 50 anchors.top: headerColumn.bottom width: parent.width spacing: 5 Link { width: parent.width title: "Create a New Project >" onClicked: welcomeMode.newProject() } Link { width: parent.width title: "See Ubuntu Touch core apps @ Launchpad >" link: "https://launchpad.net/ubuntu-phone-coreapps/" } Link { width: parent.width title: "Design something beautiful >" link: "http://design.ubuntu.com/apps" } Link { width: parent.width title: "Build something solid in QML >" link: "http://developer.ubuntu.com/api/qml/current/" } Link { width: parent.width title: "Build something solid in HTML5 >" link: "http://developer.ubuntu.com/api/html5/current/" } } Column { id: bottomBox anchors.top: topLinks.bottom anchors.left: parent.left anchors.topMargin: 20 width: parent.width spacing: 5 Text { wrapMode: Text.WordWrap width: parent.width font.family: "Ubuntu" font.pixelSize: 26 font.weight: Font.Light text: "Get in touch" } Text { wrapMode: Text.WordWrap width: parent.width font.family: "Ubuntu" font.pixelSize: 18 textFormat: Text.RichText font.weight: Font.Light text: "By joining our mailing list and for real-time communication join #ubuntu-touch on freenode." onLinkActivated: { Qt.openUrlExternally(link); } } } /* Column { id: welcomeScreenPlugins anchors.top: bottomBox.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom anchors.right: parent.right anchors.margins: 10 anchors.topMargin: 20 spacing: 20 property int currentIndex : 0 Row { Repeater { id: welcomeTabPluginHeaders model: pagesModel Text { text: title MouseArea { anchors.fill: parent onClicked: { welcomeScreenPlugins.currentIndex = index welcomeTabLoader.source = pageLocation } } } } } Row { Loader { id: welcomeTabLoader anchors.fill: parent //source: visible ? pageLocation : "" //visible: index === welcomeScreenPlugins.currentIndex } } }*/ /* Commented out until we get Qt 5.1 Row { NewsBox { height: parent.height width: parent.width/2 link: "http://developer.ubuntu.com/feed/" } NewsBox { height: parent.height width: parent.width/2 link: "http://developer.ubuntu.com/category/event/feed/" } }*/ } } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/Link.qml0000644000015301777760000000404112323167147030431 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ import QtQuick 1.0 Rectangle { id: linkRoot width: linkTitle.paintedWidth height: 60 color: "transparent" opacity: 0.8 property alias title : linkTitle.text property url link property color defaultColor : "#DD4814" property color hoverColor : "#eee" signal clicked() Rectangle { id: background color: hoverColor opacity: 0 anchors.fill: parent Behavior on opacity { NumberAnimation { duration: 250 } } } Text { id: linkTitle anchors.centerIn: parent wrapMode: Text.WordWrap width: parent.width - 20 font.family: "Ubuntu" font.pixelSize: 20 font.letterSpacing: 1.5 color: defaultColor font.weight: Font.Light textFormat: Text.RichText text: "" } MouseArea { anchors.fill: parent hoverEnabled: true onEntered: { background.opacity = 1; } onExited: { background.opacity = 0; } onClicked: { if (link !== undefined) Qt.openUrlExternally(link); linkRoot.clicked() } onPressed: { linkTitle.color = Qt.lighter(defaultColor); } onReleased: { linkTitle.color = defaultColor; } } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/NewsBox.qml0000644000015301777760000000444012323167147031124 0ustar pbusernogroup00000000000000/* * Copyright 2013 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author: Juhapekka Piiroinen */ import QtQuick 2.0 import QtQuick.XmlListModel 2.0 ListView { clip: true property url link model: XmlListModel { source: link query: "/rss/channel/item" XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "link"; query: "link/string()" } XmlRole { name: "description"; query: "description/string()" } XmlRole { name: "pubDate"; query: "pubDate/string()" } } delegate: Item { id: delegate height: itemContent.height+ 20 width: delegate.ListView.view.width Column { id: itemContent width: parent.width Text { text: pubDate font.pixelSize: 10 font.family: "Ubuntu" font.weight: Font.Light } Text { text: title font.family: "Ubuntu" font.pixelSize: 20 font.letterSpacing: 1.5 wrapMode: Text.WordWrap font.weight: Font.Light width: parent.width } Text { text: description font.family: "Ubuntu" font.pixelSize: 12 wrapMode: Text.WordWrap font.weight: Font.Light font.letterSpacing: 1.5 width: parent.width textFormat: Text.RichText } } MouseArea { anchors.fill: parent onClicked: { Qt.openUrlExternally(linkText) } } } } qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/images/0000755000015301777760000000000012323167643030270 5ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/welcome/images/devices.png0000644000015301777760000166573612323167147032447 0ustar pbusernogroup00000000000000PNG  IHDRvbKGD pHYs  tIME4+ IDATx[m[vzc*Uc <"䪼F)yED.!+ Eײ rթ֜~+.IkM}k1{ ~܏q??̾ S߫*D??ԠPTa`̀_W _Ļ{BBпu D7W C?@ *~]NXπD4ߟIDGC ]+"B"ey7< 5^pk`fi{kWk]/֯ӣ߷q?w8Wfd`N S֟<0Tb)qzP 8*1cA1ߋA) & 0l@`k_s`f(fEL U] L 2ߵ~Qe^o]wY )o,^(=?gœ,`@&10`Y`"a 8SA1Dc P 0_k" 9` 57M 08!D#211EG0Sf3c1p')d- @c''p=56ve40DſjPav@e?`6pDS nPu05uKX˽)hLPcv`b1_')Va*0Rb8&CU ]k|-0TbߠC0r)!#R 5"P0B@cC`a~M0@gn Uwv-V "& ٿ[1 50yu{~o \vfNB:̀C`B6 @Ɓ;af~]ݏ6_z8|ݏU4߾mhvxxиAcLm}GѷA~4m;zSx/иw}@mL Uo{ ֱ;m( "F߷o &m03l^?Awf~܏q?M(T]maa4pb?zûテc8%:L;pַWcD< Lb@lP%܎+ R!' 4&1T @S$Ek1@F/4e^^;ne@hhAXqDG3D@~N@ qCkbu4J7r vy! 8p5$h 0@;Z'xӉ!XRvmcy7sUlA7\Txx:L'./јt{A@ . SeF)0"4~-}1d0!0t\o7̾.ÈagL5(ȿsž{cL@CcÐcvDOo 36F"}24r0s393F@ocPZ`v at,.` #q iFp o<; ` o,<f@̀ij e(\r'mh`*R!F8`G^`>x @ gvg o1w{B HyT| C}ۘp rwl״0c8%./ C pJܖNT+L'F[4pa̸q?<1pnoޮxop=xz oq':OCH=_ɟ!q}zrv8y8v 9 G8Do|5>+ۉ@"xk@!)"xg7PԂY1MQDžX09ж }cr&x'lBBhێFwNˇ qž?ٟnWy1Ɓm7@ƌ} f@`p?]Q1e3Ġ:PjAط9o(6A~71{6!^X- 1Xwqމs1~]o#*@@lڎSbP]vv@m8gmzq ^|S3f;Woim+vyㆶo8Ex$4"w0x?7W~x˿u÷t eALcAiz)C@vC.#SڀEһSqml T wh{W 7Qܮ^mλ4ذ?8QL0(Nco q+& "<+ps8`Vah8+^|S#xE`_@fnR /Ay^Q1-7<%5Aox{;Af0!c8I^cDDjطr*3m8_p]aɳ9Su0`>e]"&qew%Jh=9C3jfƾx<]D$ Br fz=A䍀ˋdv쭹Ѐm!3Rj e 9oxx}sV 6h[p\qٲЈq;N <ԪeC8qYFa BBhՃ7Sp`7{9CjC 5O~3ܚ73U`~܏q?q7s׿5 msۧ+a_t15po[)xȥqCT7yDj)W/a">]Aж|t H,ˎF:YQ C},XfG eypn⌨qÛ%: q\ 1NϽ`90T2B1I 8p\df b8'°5gy9 ՁuƸCt' c;; Jt2pԂU8}PbqJ}F_Q Fc 1usz{1ZK<\6l䌍5OpR971BVIddqy W۬A0r3 U/:LVL{Й} :' ALBr 4$d uyl#@ d6@vC#P% W5Ћpfh(|>M(39l!gli\LјpDF:k?,+w etŭ uVg\PTgPgg8}s&|欬Ѓ4 ŞS@i݆?$:p =A`W}!b|3B kF_bȜp!%'`>OSoAp0t@$c~pxCDI` X߻}տ/B+oęT%^,|ޓw0x?ov^͛7x+{÷>w 7meppA9No;TN{Go ;|ɢgnx\ܡocxQLl Ftoy*c y*Pr*8E`ⲽSnPu u}zo>=9vޢm79|4~>p0@8;P/4t0"rC75QHNНe!g ÔЙ}P.Ed?8A ƄN(8bAPlMޜQBĄC61ZG514ac6stݠ&s<3LhZ0k3[aFyF Ux>XaCtD`9ɜs!la03l%/K4!l‡, 1bErQjQc@4>-"5s.{7mQPSu~l0 D@b̀ YDr<>^1Dx%^nf.Aa. ͉FC:h1Kbv 禍Aa%SjĀ=AB@F}m98gmFj~7nd^($ 8|6ùr*qKPh˩#+h"yD} 매 {㌵pWKlUWCX O3Q!0kb.9o3{0OҌ+xpF=&/.ckmp;qcq4 ?#F`19Bf (-#gk|Jys(F }*_йmnz1;6#hێ}`ryͶ |6eBr@ V >k%|N3`XJ={l4g`H,]|OYfJ03!YDw[$3/T@!c)REp~1/%-BVNa ԋg5Ooiۢ8Iً18+J[ /L_؎`#Őt pdk &晛5MZ3b/AŪ=j P8y]-`Ӓ;>-0"(E f.w0h@b1b)\\yJW\Mf$`.?&S(Ec7c})̺䠳ExuFVK~gɺj--ip P jhsf5kjxI 3y@$إv4 i5;c1e}lޜoIԻA h~ ݁X6b׌əfPePv ȀR4(L9?3)0pH>0@PMl7*NlqI~w|G~uh(0!JfA AxK{jC4c;Ec$vX;@9{! T1Zc͊Lkǟˈ]\b O+gHy303g__Pw‹] b0 .[)@4/ә5mh<),*U!hZEjLEPu~GFs JJŹ(5qFjNA#R"-6$FYca(NSp֘r?kcenVBϋ`3#3B'buhf): K:GVeAcaD!fQQ]|*q͢`F!l[\WAN6@X7*űV9,*/" @]ke3-gnizkqUZmG5 m{0zΖwz(k#p<; nrM) LRޛWF3D଻38#e Ѳ: y5ϧ!o)^Ȓmm$٥<Rdq8h8+{WΌ'펣0mᜬNnb֕ÌIA((l\V-y-f&MRGB3anMZ{d]ۖfl8abuQعWE3Ǽ1_5Qf(;&Ê5O؋o(iXUA{`a8ֵVce;~܏~~p' ^Q<<0R2@s(zbvC댗//_w~ ү3 IDAT*_v;eË}ë}þm ˎ}۰]6g }ktw*3D5+ LU]HUΖu5Yd RȘU.VO\- K_ƃ33h)|;^~񙪐p@ Qdȴo7]^p#,`aҁkP {o uq ,OӒ\farI %Q%x &`uZ% 33f,ym<(wm=\2cf jb瓷:,Jq, #ۈnKg%8 J{VBUF&Z{wCY.ι%*f#筼H\Pwqad邻K63hO$,Kk'pr;%.E3I "ǬN6&d\g8Swk-hXPYuAH5L0y6,ܴ4Tkdd#X VC OhEaF)cu':`2n?j;Bow$e˫8c~8P9V(Vu'sͼl.iH}=V YyC:K/Ϲ@ VJ2-Hl(g%gZĖP0؟PHNIaFO 4k+Tی9`c$q5,Z.2|fejR51L<Ă%q?H(˿i|w~;q]o779^| ~x?߈ߍO|+za*1cĠ|x z0Ֆ>?M䄊]ʮ>L-T#ҫkn,lakjެEyȐb**3jМ 8%Ts8I@NZ"iL9}O*$V"h9x6ɜq ́@g.㼝=Hg 3ms%HgJըhXϜ52`LZ%͋kr#GKtLfĜ/ף!&곌 ?Δga(e!Ye'%YkN-i0v-f\&3k(5SyFwjd`SZ[@[0i S0iCȜJjJ@hL9x| GP(MOL6>?L,V1~j)v+59{Tfp@ɲr LʃfTL/?Z{\6 ۦ(9o W S]L `, d~$KY=׽:ܿ)Δ+S D|F=)94A'^!FS,:_`0`ʵh#5}PTRy- [6]e1[E<7J }QMukG;+ڱI&rc.݈F3TJS~_x=NQ|;?O|,e掑"3Og?GS-||S» cH7);ǹ@@vSC\ҼdU]dB M5>++GQv '" )eXbCJSv@,-Q{ƶ%X * M+)G7~"c/CgsW̢M(3-PugLE>Y;ӐR9ّN(y,k:g^6 5dR3£}L;GM&yUF $! JA5ELӑs jm!dX967@Q˔ҜL\ElrcK !Yh-d,VjLhhQ:GT!`|(P?o% 8aSg(ewbF`$ d"a HGt`%]52)d,"4 gq!- 뜅LkKCBRKF3S5Mе֦E6n3kg>l{P|'F!Vg8E֙E třgUQa!( i!芢$.;'W?0 "FFap0*dSD-"RP2gM-Ŕa26&М,  x 4$Ԅ>[̀a [̃jΣ#siWc!Naʛf@[g>Ww|w>|o4^^.85c6 ¬ ;3IN&ٌJ򂳹W/f-D9Ee xTDQO̚+JM"?%i.Ub>E@H{h|AU$$aX qI+PN@M.$xiZZ%q?Ƿ3?S>Oӟ${C-"CK'77|ⓟ߆?W.> b)'SEXjMb)`O#d-7YQ0盒1JH,mϜ a><衭\]` l)c>ك ,X2EᓳuQ5WB+,#Jg%Io:הTa\iaKg,hqN7CٴZ[#,AYJ?ҵV2UI0E.cdx5iP" XZ @iBnsL$,!6jX?3J5J*b-.0:50͵2ggV֜jϒ gAOlݼ60LR5RL7\yTFKL|n3%sӐc5Ak|{YU/dkY5̪e I 8*jo1(%.ԝe0gx9oco:H2O6>s 463WhJ-q?V<~sٟ<>OmÛ qcw<ݮ?8~om|w~_;~309bs%,JCiDeoQ4q4y93Vp+ lΤaJkj!*j19slt,Ci:k>`qPǵfK)t5ôD_YTLldfa&UТy TLZ&֔ѳ9 DRVd,,@*X,kY[Rrsa 0OQ̼I0.|*i&=sI-E佹,_}n9 ~4|5PP.)JrkD\!M+;0$fb|oy{- S3Bj)*[30KļPbʵ"cQ@ $gˌ&VN44: 6[m!={C}T->єǺSbaL@Ya\lxq?D:tzV[&8owI3in6֘67s9%B@9h/"{bT1:{Dh54:Y0.QV8X> {6)Y8Bo/(7v 'H#,3 79v4bMNKO2r4Ry111ٴ\.sB!eO"nFlRbE#%˾51v[<2LeJ!Ki$ьV𙳛XR]cwf~܏-vyo~8#q,>cwo~+>At*x$Yncҵ9K;Z Dg&*<vLeΕvJ?bMDe6Eens$rCSWnvVf)4$$CwGu]%)в(<`"3:y]f|iB7af($(MweUov~).nRg˿i2|'e Y*DLL[S!c3,3b}pFAj3&i>2zTM&sF suP0)l($^4 GbbB{h ]}ssT1({?oσ~Z>Q8g6zzxmz %GCit,K$PXQ*H9GQC̋3IX^ni:ZGxJ%p.k4Ue嚁r?['ȱcQx2K9e7 -ӎ, "hg /M9URo' Hvuviώa5k&!ҔH4د̬M>PiF#jr ʲ='=ta"8X6 of̜) dbo[de6B!P4: @RiH϶UJ,M 1 WעXꀧ;NT9Ҝ@">VGAo1eZBK7Yr"bi-y%`r EYsvU6!.ղ"xq-l[q\LK+ ɮ=$5ŌS| r|UH3:6q" )zEłL]\cQn:Y(䈗"|"@ . ((%u3(rYEv[:Hm-Sz QI Q`,9-Zu3nP25nL(= #@TUdSgХA#`[$绛[?Yo~t)Ul[q<>=~?"~w ۲/ V'P)u4N|m!6̹'HCNƢBZHP(3gCW*F4;fVYYJfTeR+JYy9PcXYJ896Xekɧθ4SUmVt2YE2TΖ9>}Rsh1(X(/dfadtkaN3$ʸBMGy?q1@c?_V*(=V'\4^<)S͘L$-: 月e-,֥ЧcDItaD+yмӄFU4-fNd*9 dLf4gW̡,-᨟w\U6̚7A"=uY}G !?Ȋ @$W0fdcM6% ʠ+#5Ee$Fo 'kkǝP)%Nqa""A IS%Vt~L: k>9Myk IDAT[HlpY }>˙sJ&ɴ@,/Nך!Xg.khr0)ϧX=Q("l~9U*kuHgO``Yb_,Ms" 0I1Fk/%w΍ےy~܏_Woya'^YO+Sp!??OO_w +wW NX\7 ߬I)kJdVԜ%!d_yp "j6a9%%3l-C+0N\큦$fv!c _e' fVVA/E>^$Ԓ9r1RO^ (2А%K&qar͊uZLi? .s4؃H+ȁ h& fQwT+)H\"Jw*m6DQ2Oy]FJygmR{6),nMdkΪ(-ӝ1=sjlV 4y?/ \m[医ȒpAs%@j:K4Bx1k9HYJ;)T ,>%7.4l9}{vJ! 5:ýkNSgCOz 9&l,,g;dٖ_t6c)9"Mgj:gr>Y}FJHsj<b;T҉B[lo2(զu8~{x?z|o~G[381udva\p"Ig>~o>|˿?bS)[V;R RIt+CISv}+=+Rȩ.e)ks $hdIA.MZ};kPu6zUY}4Jdy)$. w8"G0]bsʈ dQE*ElF Cvh ԗߛνI(R$CiJ(P&RxhԬkZƭ58ud1pyaÀ$)1gQ# 5T7}_C'p6 tRޔR'ץEFDľL1Mlr6%1ךq6-4gAHbs/& x>fQ٢i4=eZSXTL.T'\*` WIQ%(哾3 CYN5鸗N\Idgֆ9Ì&gh֟^Hc4o\ϛ`Ls?' t$+O%`,8h>C9T30f|-nf\KQs/]-1c 2Vݙq?ǯCD%뻾L5y dґ銧)ğiG=׿)]7xDk-:QT~$M9eF0@bԦu>o!tSiɎ>-La5ϗ'%HCpiTuN^C)\ŊԷ5j;Zt̕^Y'.e瘅%0íf"۪xEjMAu gP+72!<Cս zk>KTdfKU Mfȵm1br]d=}9% ТnD+,Q.ɮdLw=_W4֜=>'[-5#P)sjݿ- L17qwmͮZ\rN**\쀅 x!O CO,%Dl Hl/qٱBlSR_yhؚ5JGOfZ^FD S# PN޹YFOH)6o9=Y51eQ(;a(,*k #15"m_ s`Gϓͅ架gR꒰\"R~܏6^oxc#;p<8^} ?~~ __//}cJmd #ΰbF 0!G(6Uu` lFSf'Q e$i4 `/)aM 8fV^.'P/ -Js7Dd8hWИIƔ4/oQؼR?` j˜:؜.$V0=َ7ORAlkC$LEӦ@M)YM)*TQNwt(#6律Ԧnŭf# Q֣< x RMCE;'HW~[xZ6ȷ|ygtCHZ릈T󤊃T-vy/u}ĄD4VEkb*hmDczi{}V9Wx>[ņsRN3?OD,n ^h_pxPEI,.4`s=M:EL.鉷M 3:D6>@RQ~ĸO?kDgRyV-\JHw{eH;Iֺe#F$aƥ*T\b IA^ ޏq??|7/~Wtρ<]7ϟ?k'< Rn#c @ɇ$f$Pջey.d$2*PdRm]zCsWX&o4@dKfizYFo|L֍eYcE#a.BfClw6ruWjkӺ/FCwb;lh" s^C ~PLc';SLGnBP3Rx,^7({eY\ m;_GJO9]5/6XC©j a oy*Pw!uDYRzT+d:Fݪ]BF@DgFi{9@IbޒHVb6%GA ؎&PK cwjW_8Y1BʏH&8+e6@F>`X0KˣKM+psBJm!,UEI;I<×`Į:epaji0DtER`{d+SA[A?o79ydE -X5bh9?>]q'O,]y_EGlTf# {*~|?v5,Qnw!ϧZAj\䣐A.LH9"/6Β 1RT,F#VĈz%{7B\'Cթ гϖ`8sZ b&ih6&|©5u0#s,ׂM9'?w0z'ma;NK}ʣc^ ޏq?3?oWqc%'|v W/_Ͼ ~ }6c#LKV@\!y1\h,[lM(hbXܕfiYG#薛0#Zbbe *1`03|rBTh\V8XN  RBެZc q L VԾ` 8ÛW_}@vp%5K8?o,xW Xgv,kb(w::Vs*{ZrIzGfo,n$Wq^# ?J ŒܸCLmX iJj(c:)*Azʢk?YsÏZ>}3+3,}Z-|0CeG4Χ{=Szm@fa̙h]՚3{ x} ^<<<׿ oYo@ F.ؙ0ݲjw{+jʫ2UI+$&WnInyŰ.D3JGh@'m\uE6l1οshe9JYFĻ e+\s|XgiT} #]`h".ll6bw®ު?nSl fReiz5*R0h TGO?sCvGQ3$br[zz{tr+)^|_;='(FR,;8Μ@A܀SH Q6ީ;oKILO73XeQJS!f- y3kN:a!|f?Ž"yKEDijZl©8>~܏7>=?]8Wx8+!|W|G7~׽˃f_JbƍXfMR&ImɣJnv*с"Dr sz}3ΚF9hwXo&wQzgiFlNv$h$i.k+ ɛNb=7E ހUVE@h{U!am~oվNG#ỨoWdB c Z*K:/G-y[­9.m7OLg^_3k/OĻkgA!Y~lic{&TŢ2`,yѢK)#[ D2_fg1QAnQdԞRXhL;/&Uf]5N\0`ڡ\szZLsr%ˋR[~B6ԼijAMo246ͿeyyPr|Hʢ~7Qcs$/Z^2U1 f鋊 ٢R5ɨ$^M % bfkzp:2JxȲ:-^& 1 %QGA)MjlX%!_ 5Ȣ) GOuW 8YǂkI"Ǩ >Y="ݱ~h:̂zR8pL[plXxAuIjBJTE^,V*b\N:v.8.u]ナg̑ZiH$2GK1?`.ᙴ.7e0{Ue5CzqC5vE䳤eQ^]q\<} .~~K<]DH|+57P1LDx%؛$)3 to^Nҹsڡ3<#Z: aFB1Eau-YeLAWu&4Hl:*BʏMxI0<\KjB+u-U,1|vL hSf(llF꘏EHd^Z>g,D>$zI'[ 9!Fň14,:K,UhDej\R"zR# g/~o+ Gxx2)!lj.0NaqS ]-%lzHsMo-"Oe#x7Phf.s9<˺Ϙ==GK 02}n2oӤK3ƵHå WL;8Qʎ5G@ԀgQ+3bAQkrY[=pH'|G8&bLlړQڧd:Н}IҾ/W Wh/"4#]7Ȼ!E Udɯ%o-7+'Bgw^;=p|nb5)e0t]Z, kY]KXWSăUн U֢KMR%zr^3|+/"_n|募GS<>#<1Yd"\0GgSIEA8Q|N7;p`}O6|YQ[^@ cn̼b V=WTƄH3n| j`={`qCBcLMZ9=vQBwcXw/lL|۪bĊd vS淰|ssl\HuʑbXrLF* 7]]7ԴCmUkcgc=@kơWG Ȼ)>p|F9xݡ>iJN/gͳ rb*o=Nm\(0$vsIE/D4E S16t ظ(sk(=,4\ ׽( B; VR'S"z$La"DTt`=x9՟~?3_k~?;|f} {j&y٢ ˢ2f4<#&*ګ$F -U eYŵjdٸYn}j -2/ץՓ=FoZÐRƃa%:=-]D7B%]wZͿk#'5FNeyK< "wNdQl!܄V%{E̸ ..ZQ"+b"״nfppv-E~܏o}!Wóc]2u0; /_?g #ÿy6Y5*Xq E.ar>&8 Alk|,Ɯ>c+ 0!%dسR@hu,dNZ R6RAM@.M񵃙u+˯讖~PQ=qC7l&>GN7I"8}sô*ɃJmF~Pa-6 o6 >|a{d:&_lԒx@uͣM&^2Vc@Evg GyQ@,f*.gz&FI!fO&*P*Vn4A$3H]M[ABf4SkuM d,eCŸ,&Kyc&MFNKWgSr]tQ,[oz^ax%y睚k֌9"RvhzIXiU4H"J9KP9Qc!+ʕ{X#"I QAHEoͯ x$cO1:PuT XM[jX'}VA# UfrJ{XC12V:ʥgCakatpdP%dkU/j\6VjEÆAC]bRu [$oۑk_ƖGnZ0 ~6{1x?x#__>k ANӉ◿/xPa.Z̀R2΃^#:A0]k6\J0Lcn3 1I(ۢOʿB{qt]@4BQu7!++zSmO$h/ 1@4:b3_1squPwV_Rq*#WM^V`ƉQA0(dQɨ>}C<䯋GPgP|AOPJx+9,TRNh8-,57v5'KA@Gh!񛛟ń,Nѳcy"}Q|ǜVMÚ"ɖEK,9&5~8QF`84hO` d'h &Os"Q^I!wb'ʏ,5jmXykFQz3?S~,gsg\;̠FlҞ2[H8zD*U4J'FttqN* Jhm".r޵'ٌS1%L;?=Vll7e]A3C_ :JR{8=ݨVӹr`cMkd$8BR=0MA-T8-q{dh,pw^hoRϲq5hahЁ}A~y]%T7[=`֘ZK gNS~G~/wdǧxz^O27"MsOHoٍ+e6nn؎whOL0F5xZgpͲ{% Wa1򟒋K9=` + J:Y)iRUpgјTn,RѮ յ*鷨8.ЕS)dc #{c`AwsOE.ȇ ( D'eY*sJVf ȍEO:ϱޜ Fm[CRfI]55zI%" %p(Z vp E+}Egf>  e%u,'.Mfbac#Be 7QC.ۚT /na"-Q|=NtI+-VXեq_M% F2T}3`³_^@W"{JU`M#3Q{Ft8 7;JXS/Tǐ\c10'+5yg-5n|żԹ=h U^mw <~竿>~ΠS8 7s)^~*Gi&o5{"hwM2)"lP[Pu:25M]xB89Sv n>~@Q:J/@~9[̽3B|FS5_:0aI!o#MŠ㨬4m˫# :6Jĝ1s*^*+P1`kN4=뉗8^]ذICU ,NgZz7Kӆ4c8֝Et X99fy4H{!1/ɓkM.E]c>H9\D( k-._ySD Ei,׽ EBVH$/'6׋1 L=%#P+]4%6ӚbXEcT.NeL=n 0(bKm#*f! "'/JNHMJƭ $^,깲l |lPEV*[yw`iչ5Kf'Ef=p\̫E(볯҄4Nz :fEFX QF:f lD[ebl{gͰlp cTejCꉦXb>=m8s޶h|f柇$PkXensb%;M/`s1D:Rf8jbh<+%/`KZhJ)#HJ'D«l/k#<`f [[^b8B!C܋q?Ǜu;~|o^q8 l8.\ )7Wkλ>Y{5d 1Mӥ&rα\"lE. KpHnifO*, ) 9\o׫)իqQaՀ`%ˑgՙHf t`; K`ӟaimɱJjr| rjy!1dBτ)o%COɣ*jd4^ҭ P\sn,7,ȎfC=h&ޡ)7SM+}z$|2qֶ)):g0pcC)5=9 H5֨JM6\^ g>H6l*6Φ[eM\88]Z-4n4]bN_V{ʜjy~JI*(vfe*d<11GjAŽ8eQOqݣ Ūိ8mFWtЀ֖D^I"&[R^jd 0[,$n 消(顓Dsby&qT3C`~Ng)-HU8.; r4T"u.Q;-Sf'. ;7ͫ lxy-:GsJu22鿰 VM(* =0P63l(D$u|If%,Iؾ1C_<ݐbL5,$M{1x?x?|ű.x8.7y^ ??>?o _RXIW0P޽ky߿(R9I%l(2TPz_#+(;{(h_*pzyvNZ/]ouY-"(Znw廙oD UTkQT<gj,r+vQ IDATk7x[}fTs1dt'70rΪ>%ciʽ$c xi3K30XkNW7,Q@K1z$1[DN;I&n<ҳ.{MCm7 (f=]7nu#ϘR@f&Ex1%Mu>S'wÒx<1SSޭ{aT)O$S>KP :3(H5'>X Ooi)bל`檗 ;bLS2 O0֢{;{(79n>uM-2['#ires]h8/rGzOek`NjDTurY@h;@~܏F7pyc"ϞX\ύs^_`[)uQ\(hs8a)ހhI oݴP'{gW]P &[V )TX,I`@K5g`t;e;y7zp˻%G|(U1r ʌ*>=g6mS6vfsׄZlM2Znd~" 8J:SXKp6r =#̼ʹ&v㦴v.ʬ4>_**..b, hN ޅRQ9"e=v jx>]g'I4q~C,̮wr3$4mRw=^4v7r5_Z6 rbu[0QH/ҿV6}jsYZ"Jެ^*rQ+2PqIDwVn 6 ˃,Mj l: ƔχW95[0l,*76 eyXk"E oRuޤ`]\q78V wpioNF["[;))HJcpǥHkq>* dԲ!P);fKeRΩvNBDU%UPQOIZJFmlx`e!ެPoPC1~~h)9.j, 3,4q?u~7q1\|X-x| ۯ ={ 9O ZZk3U5֚&yEPh78ahoPDcd}IPǭd]S@ >C_2pKӁ#R.NwNhDcsb:Bd>WXE8ECl̔BLMND/Av<F( qm]aGD/)^ί~^[w洏GSv97Po}T".*}ǽI fDB+~ ]%THwpd<'Q0X79G  afUq(25DMRNQʮfPvI8jS+Qxe,@GwPrq[ H.[^)]&D ̮D\4*H- T[rᒣ`dV\$Z(Z泵]A6?QϣQI&d+.1T6Oy`0&AAuBBrhȧi\+r1$ /rjmUq{M':0 o=8#h:E9h*/{ T>}yaC/NFP ]^&1MvNk5+}^a"IySWFdQ m׵[o'ú!gk1p߯q?x#G޿/].8ϟr,z?r7Ë/٥~3g|6KfmMhֆ@Ee#[Z Dc $Oh# ;W&*؎. N#8CD# rd@1.e2֟Ia8M ͤu`Xp3vV&)׽ȺmrYG(u ,vޗht0C-N1`u8S}(b~܏>#|?g<]p=Ogr9pqa|~ sK䣀ӑ aK3_Q5 Tf`7O!IkPuZ28D#L\!J E,Tٞ \>w" /c <}ojɈE6L)0[:s=/7Iu.d7%**qjhs jIsOVhures{p6TUwQtM+tN %$S|eD2k7&*o!O5*=9}.gXJYgDF0Z.k+=QT1 pMq:mhTDfq<+kzlYy(elEQUMJ6-o2%Noy5da\Plh(Dn*Z[瓨 Y$j^ScjT`Br R VgPj70O*H<hr\+אđ p8 ^m=V̬7ˬ496NͧAb,;͚yI2El؇.b zs Ilkao춦*^6â*s0;$ƲHzwK@]@ZDSjJ&:HL Щܦz9!nDRFm',L~|JI ?:K΋U*F$7e٨=J&bQɷ0^Z<0]w,E-AB.UbaO昼Jp-{- = ^B6BS+w*R0}8b$aZ^!sYL_񩉫6^,5S YnO\•${2ad3M8o/:4AW6: z#j>IN &qx23 8ca$ISͩ^9yar}1lxgHQ7e &ccLQY=}p&(j /L' gj0?eSN\#+6l]?B}(IߘA:_;:pc9Odm}2x?xco|x xoٳ(i[Dz^?3<&yV 2 O~EԺ`e Ol 1n\M5A8!**_oA 0N @BQFv[k =m}!ȕ=BJswTբ0WnQGɐduP7'z&.Ԉ(ܬwm怭CH!3ӯ:ȟ@)eFVք:7E /f2cKy523IҤ>ZMΗu]y70aanZKRMEJX廊З=^ P>Ěk!=G;iԿ l)S#kWm ݱTLN˓Z{VY/F[>De# ؤ @{Lrr9A\zȫ:Ȥ5h/ymZH$ׅUD K%7]5 "rZk7qs>h@*䆆M%>Ss1,<خ\Py`3+e`X39r ؈Ѻ@Y;֘reAzpMvej]2YYQ@HkVPzLkwUSp-F\RN~(s+;IXy'I KFib~܏f7/_yb=ٳ'wۂSUyF CXmRqfw53vfö&sڀL j&bC sblH%aC]/KtTKN/]A72WK-#!O0]bs?]t2a*s7A9y\u-\єrCym&VEvw2 M3/@MR;l *h|E=8Єesj#˫L|s-х옦U pS,txr͜2 VymG d#jZ"KtmX.iz`ZE B2Z|hVa,13#90f(^`]]unZz{|IH\VL<nr|4@Yi1FS"ʕ9ᔶ7Q0Mü=#jGSe `YCYrr 2ƜYYʚ ,J>J۠_,  cԼ^+ ~ tqZ4`+nr,AMVQŮYD"*n XQS:Đ{պ1u/}RD'|EŐ(к ˍg鋍Ei J#Ėϣc=՛ )tlvwA "$S}m#嵵;DZY 'sE]zq?r<=>?۟y ^?[/bgqsw脡+Wמws aQUqnDF~RC]_bM]P) ANXHjP{ѣ79q^Wot69L^SEj;۽+́;X*p(HS' MXX}MiyWx\zݣCB![-tʪ Cm|"F༣AGLFW98{td1%j@(G~/IF96J&|QeUq~ QĸMoT zots`]XTn:L!hi`+>j_̸QlVP `L8BG2/jS8wC>e'R 7 Xhf,E!V̔f)Zσ!l&GD6EhHUt):8[A(z zV^%EIE+&8^;54Б7276l kMr;{Xkx O[}xΌ̪,9$j+"[aEN]HƔH&N1*]lڲl-ncxw&5YËZ&R*^6?kV9R 3\S8.~ZrV\D5>J49oqm${[pT>/[~Hާ5W4AЯjxZU%- \=@++,u5E`>3L Eȏmf>S7\-h'\'kֱp^q^D~^q=x:O쭗w} K//8ì&qRQd;*ncf35alfU'rJ4[-Ӌ*M IDAT(B9j6Qv,壂07~ I_$1-nEIqDG9ҦgAKSZxMTE  f[QۊQf=̘Gbm 'F1q-'b͂G2aQv)I"v#'U-?OS9faULh?ǬHy[Jz3E3 /PӓgW>p.Yk48I91nƠpn Vp֒ )f@Kx{Df09+*&qɧZ~ ;{xNXpפ55En ɞB{0\f9ڃrmb7ki8ڂU`zzʍzN`e+Ba_[XdXH>5(h#Ŵh ' SşZ&6w;RO]e u׳,VE,u]ڑx~K?Crfʎ3&:7:gXTs{3~=Ae=eFm? mt~n)f|DR#ݷ~܏7 84<OG0;py8WxxeLX6|s!ϐ V:#T(-M|; ٭ I!1׬gfDuژv =لkUĂYH D8Z|hv#]Ey\~|eHvk,󪲃.#<7Ik`#@ߌuќ05PA_P \DA˫XYd'›uOW%6C.]WI fT SAȂ$rҪe;kI4/d"]geۑ c e[ fa%kgUU@Nm$ !K1̛>;C`1gMUפ=|kލ2ZK ]T2ӚR(:agq&6MrfYVOc$|>+?u;ȸ*S$4*4}SEʗ5\k|OS*$C R)I2L.,,z dhcQ^R}@s묏&C krҞz>vH7ɓY\UVWJ WTcjTT öz̯  ̫UffMP.5(<+-`Ncʍ _wx8P1۴Q[ݣ%o׈pgW)m|xyGKKyTC̖2F0} ?˙ClSW!68 į=~/}> vؒL2 HGՃ뿈.(~S%8E%Ӛ:^MѱՈWҘْViǎhCXf!^;{Iڂh4J`SzvDdjlIp+4FLӶ>]-EӖ=&Yx~ZEMZ\"c;|MXKdC:HQ arP@;t[:KN}y(`IqW$0Ejncf^@[(Vk4GRd[&0vlڠNդZIDχs&9o-xD53e8jDN^0n)t]uk0#5Ewͧ#XݯessՖ2QG FHc _qEbhBX[7Hư R3$bR-Jhw&4: IkU85,V(:Z~ o6tK){=[jMActg&2熨t(GYн14`tȭ&[~"#^9IugؗLdd~ܰ`#L$f7)=`` f4<cʯ Q4:2"$ N,qܥMbA&U k|^cxkݛ)6,b8*h%e6Y6PtӡS@p/*A%PGF? i}DЖ.}Y`8AaTcz8o 9{es=ގ5gpy\^?-FFMۥKrW"x湜h؅y if#KME 48VQPqZ1& }MƊzqָ4MnԴI#̣iVF@u~?S-#/귌CAu5j[J}|X}|=nTe'scPQp\|(v| ll*JJf<ܻ 67+,IlsZn=d8}$Bh)6=Mԛ`HGWB,6E=@}(_`HE,Ms/ڙ`h_|FuI-q'㢉ˡ/ 1Y4h[`؄幧ADkڡXdEKS47c쏇q ;wfKòYpPW6+{c~ ?3[k_~=YMf$\ni/ T h\x#e 0!V$P6^tc*߰[WSNy zIͧ%1Q֭ʼ2.iIi!-Dn`Fx![g) kĵ0XqwF\2rʖLqƶ2[V-I_P!,{R"k@q* A/IVC 'ln K 0vY+lJtgPPƖ3mp ?,Cɴ&~)OfH6Mpf(kB@]/P; do4uKU *8#z|ǿj4rN}1F ;gmT.I]T 'ce2}nytzTir@}LgL v:&[̴f=8Lj˜XKfț ?%CҍSG"JN 12͹|erQN.eT&Iv*ꃝJʔc^fF:ԝAt2Ӷ#.G͈砵rX441Lo E}z/+:<_/.Ž܅ 8iNxt-j9ߗ*shPf(ZG(@Tk5g^v]Ha* "ZCo*.2Tt*AfS6_ evAEEp"iRHz+x|iI'KrmME,QÙUȊ41drpsͫE0c~VV,5%OBX牼-Ir5ecȅ!`'nsj{{a(;Hz}fg~G?#|>̿D'߿sӵ]9)Ny.a3"=; p`@uAc<4[9<@p.^?ċ_b||6{?>p9AS%I-4 Aks@LSg t6\IjdV]pvrxig&2Sࠬ9 !s$¯GŭLհ7B,޷95y3]ZKث<[9Prcbd KBM_M&$" {͏[!HyZk.-U OoBfWn*D0O,Юr3%Dq rJ #i.YDgȂ)ۃQ/Jii ieX>]TkH酱`L#5Z?=xJ%>H=L sWtC_U臹y ͈X""M^=Kp]uc.MZ">Vtl$pc3PRUT6 qLTQ75Up-)Ԍ_cIkunRb(ƌӟ*cj n8sdPtl( VA2^ȊgЛm5BNI: >NٰaF4E5Fyܔ{Z"len opCX 7ejW4V㢕S P/(vq~d^h m2r uG])}:↠t>A?1 l6yk 3FÐQKܑF5PP0}% gFcO 11BĔOYe|hSdR) yNzX͗~b\9#h]K@fCz-?8_lx#g>9x/"Kk'&Ϟ?=Ɲ {>yo+i9ndOc{]$*z#ހK8ϊ)IN#ID7fqz 1 i&fN~B8$6٤zLG|`BUVn/zjHeʍf5mɦ()Llb^0  12Λ}w5"i[1"h)iH,Љ=tX)=cSZz}gGyYۊ#4XM6boskX񒗼?1٭8{"ZÏ%xϝw&jP[Xvm?w_Ÿr=_gᵯ=nkwxswOx?OZb9]ًWpםw Oh?<>?#/k8<$2 ʄh%vD|(L[f uc4`'k{-KJui2 ^p+Q;);Mf6>SFV)7BϢiL5%j_. 7V +"ÓÕtt$u82 dڟׇ̜a8yy+Vy#?RmaV4j9oNC gF2Շdfk>Oǽ ^җs>¿wOzvYxoxW}^qOz"˿{_e,xڧ=wU'O|">/O?g|G{G= px ΣݽV$?xpG7p5\8vȨo+XH4&6V=͌4iB !dy(ujeeN4lLQbiT0kqVSq-XS0UYʴfHz )0Y `I0ZUO/HYƉ>ڇ#O+U \1X-ݣLh3K' `ӠQWˡcRtl IK6ZC :|_#J H%=^k$hHmsyՎI t5\_[X5k7+K4Ulpalh?PW/_El6^pwGK|ї}ڲd3XkrspE\zfTW̹s軎e0?WpupGGGxSG>1x{q[w;lgucD 9Ţ-jFEdiL cV ^sQh e@rSTdE6уkOյeRnEaBvVTD u= h 0F3 N6s2QsJ4ZṦVt^s^N{1_ĨӸ1SGٴ^'L2s &ΐJ,BJCugQ.%4jv'ֻP#^qQ'a3<jn@d\2OdF0+`sd`ZgFFQ:A0Szv:)CowFkt2'aCnN<1bG$G7~xp?|~.>//Og z˿wnZ~_/!яW73?я} 7nڕpu= j*on.<D Q7(%'6H衊hF=XP9Dب` 2IgjFUFنpng بEH7hz*"3e6 S bi2չ1sYOtE܋2Zp29FJaFBy&M,uA:6oum?Mf>^ÎFД9:!FA V;JrVM,Jky܎;뷚;07s+N1 zjI憃 䈍H< JJMEx6~nhs zicsj~fz7sإ͌I+k̡g}&zyFI1)~xp6-ox[Izi ׮^g|oxOx[ނt S[~7^㮻{^K Qp4"mmVv}T1Ov\IK}"³WE'7%*B&}Uٍ3z} o$!YDRnئ6i io*r `gbHoŎC30\0&VD s$4M2Gf*Y3sr9p.2É$[gpyшSQۜM=e䚲le\OO|F4UɜUf9$zO!貁]Ca/$Y\!W+eEQ|&pҰ(3̻oʤ:;gl9nF Rc5A78a!ub[MuB"C+Lxcim6!*w.3AK34qH92G̀`-@!p:gΘgR-sVD1n4[x>Iy;q7yRo6[O\o6U<3fEpu[ve@ݸc<W!Ο? q+G[|K/WoַhG3لVd ih tt ]xd0Q_TdkCS,}RH efK-ucD >ӑd3zxu8j#0N]P ^RZN`f6)Ar*<\I˗c0["] /͑RTa\d}Y7f,5*^&+ ҋ)x3g,(y -t[ C0d] Bଡ଼\YOG(tP9 0 dd#rFM7ZB́EePKE Sψ&^A[dN Ć2 k`DZf>O WPc"|6(cU6g;0V d\'[;vR6bT9d6c Y$Һ2OgPT9 f,zZ˲JAnCpFrnY`{tWvg7+d/۾c<c7߀a ?׀_/9_xcpt4lm4,,2r&M)a)h} 9MH<1/tr bNBy@s4^sNB0!Hx֑&V 4iN i3!*2_W]:6r >ћR%2lF\Kӄ9,:C8ʴfR֤QcMN dͅL\+5Oexfn"Lx2b]pU5->p`gEJh 31ll'2%IS˅3 e6>}У@9p9bPw f %JԪ2ƌBz٢F@oI2&Oƪ*59J:#٣Qz}f'+QѮQDިe8ReZ {qp=ݻ]+7mҮdё4b`<MAv=1e&6Mj|c ,M)^Dx:QR}3?x^, K[`>)O8گ.ދzG=o{APКTe6 ΄'C UACcC,5#[P(x㷷f8 nogqx\IAlͷDanFhFQZ0g1mZS~-CO7TrE1Y=筵N09G2R7$щ# 6ᴈu` F(ѼϪalR? ˧es\@膌- A+䔲fV< [r-ΧrBZ(XDwa?B. ZKwۅhq.Ԇ{o%?,^|) "09v@ 3΁$J-dH9|U4l ~Wt5ov4otnPT%yxա3lKse02'8e~|u􋿃&JSjv-ZA7Sc-w?'77XZ!wr~3E8B x _+y1+=2#N-U֩ *ww۱Ku(Q;wRQ5\QX#≛D&&}]FMF{Td: 93=4=3SVf ;JjNmK5鵄 ߺTBKlfp?Ξ9v|Y2<я?ě^|K_߄sapiƾ" xs"I4m҄-(P@DmUlΖSȶҌc(Q tn!LpHYW H]!8 gh0;62f/@N:MSqNծsf V~*M(Dd0Y{f˲@;&-AD+j!CH޸ЋnG`B|bƯw2 ]E0n1S!f?+ +[}N 9zHVT|Ǒ1cSc#'wE6VI c Ub-8cYκ;핁{5Y i){gZl,Z=j^4!td\:-cZlA?a3!֡#W8 1 jW߇Pu,ދQӄ֢f3̫kstB|wnF8>SY$rj2RP2dWl$ T͸!}4It.ZX~f֌[btMhuɏmY2_wj"'WbZ{R"1x׾jy+r&ò,s\*z,vdl0+w`:ere|2kI-5uceD[lǹZ{K4YdNǣ,P,&t$xIt)P?bj]lb4q8%!ʖJHF 2XڒZr̠/ӃgF6cJ{ Q˟&k|GeTː֞Sئ<YlZ eE5nkz7i65*xN7JN)aWࠑ>koim.\FMy } LdVVaRSɢ!cqmƶ1އ*<(lie IDATh&5%4ٍWG*Mjh8c#{a? mGF"D^P~ʄ"ߠ%To2qV UAE:H륦޽ky[+tj׈#L&o d̛(u+FX6Vg}~%$?Q(zߕ,NcU B`QǶ׎My>?lZ9`0I}ue? I5/PO1('Il9P:*esP{R/z!ȮrF^&;6kFqSlkWTznfK#d 4c CZ9ٓW*Lth{ÖLԿK 2዆WYKI!ɄI$v'3jqc<ȏ6 W_ݎ+7c=nٌ @!=f"&hGj5"}eѐIC"=IƦ 8/7Sbْ >VyKTa8r U3h+7mk홎R (O?ɋ6(4/z41D%bQXǸvcIF nHҪxLMySh37E5' M!9 #19>6!L%)S5" 3&svŎ9D!9JŤYM*@}6(j%n2qP 5h9)qM]U{*s,fTgu+T@(Ò е<گA ^ a!"hYc)b tV!HB&FL4nu+&f=UVcej2a묎W L$0%u9SD4tbb/m4[Z4WPb-#-/~ڲ!y׼ D'3gඔ`"j(]S%PFɦh2{TT287d͔SD{lr֣&2wr(֗!ք4sw|@~?)Ƴ^Y|V!J%gs5tډPuw]YzdHC Q@Fc¹ssfbP^ḣX66V#⎆lB=7Np]4 S!82"9)X!ANa>2Fk#z94Agl1o`:K^#A] 4MSdT[tE353@Ĭ֑:m e DWYp-̀hGSV{vsZ9щ8ƤUedF46Չ!C LSUEa&k40Sfn0PN1(4nVu-лb蛕Yл60hrv]ݳ9GeJL6[ePwqh@sj*E\?kH+KQ]0 i %cJ2$`\P0kA_/R:{ƞ2c<E=3]7|?Ļs~~ W_{]8w,J!͐r)bܾ1w)xԣ#r2aEٯxԽc?y&j/϶Nό6iH)e{ (I}?x0f78<<@3#x;x9O·~۷\K!38Ƞ1fFnՠ,ȅU{0n0cAjx1 VS=qg`n܀hmKN@ T\ "6*١- yQ ZZȏ\8% ةI $ {*lI,][x:UNe V)ӥ[8B6.U1 g<$ӊ/UMjd!ؤDL\B=N&7DSc(ե9+hr wp$5HWs}[3֊O{UdEِI/(dzTH(Mnb#A8A!f8vQH/Ks]5l Ҡۑ;U\[= &ь6l{E&.eMR˦XYg\:B,N#>+ztkLl⤚IgFk;DԼQVYXf({VS(4(A-i{N{d03@CipWڗe[Z"Bs:zN4;;bcB}]u][#DU5hwG B*=(͓Z6 S:Š#.ΜRjq ?獌Y =9G|^l=!4STc<gp߽`kbt `{ Hkv,5*n&&#ٜ]o†Z6wІNQ-Mr2lnfDl)@LHef# =Uq7ZYMː&9-F̽4] 5b͋P \g"0UF]ptQD Ȯ[0Kqop$3x0g@Q LUF4 Xj%Em~6Ě["s4MHʲuW69Hz%¬1)&* %q$L8baM]hQP1Hp(Sћ0֘!BS]GTla-:QQ7fl8G4a|eV\ 5AÅ68ZWEhndy֠;%dKcj/5y@`ByJ0(T 4ۜ-+&J2bLp83SqKJp *LT)2Xeɫ8ۧsǓ!LX!7:eYpL(ĂFq@ ^ i˒cxZ2!/:! Ƚ7>s;uoцӄ_ʶ#s(cא潁#I4QF]ӣ |3cdmB&X!Vn*VFFAҙc/nƍTbh#{<~\O=wyӁUä -M(qNZi6uSϏlQIE\ ipk$GnͨPD/y+h[|^EJgdڢNLc›Ýv, u.O4aa3>4+)?ң0\Bc͞Zu ̄dg<; ]BYN{4gV x+ˌ<#cПi$&?xP;X`{Mo} 7|ӷ?o~]_/²4;{82ݤ6xE5miAsڑ`iK*u ?ctRS[p zM&|KتII'T` -t2Xf:i&U-ڲ?IMVtrj>:7.uM5_O{O]ghEQLX:XJî VEh"! &K +8(jYdQ1JʡZF/ce&nh<!ӎ^0PxrUVs.#3-|E 5 D$8猿d\IsoZis͹/JZ;SK5ء7c<؛j{ttkWp=bzǣp #$LcQd^,)O)T^)ǬM UŠ%m ?,i0BEбLVB dW%J"'J5OB?02TQZY^P i9Hk֛]\3r$=b UZBG]i(ѢhDLv9?տ :T;q#gڎzcouB-CY˫Z K- O$%=CtޙyŁwkBgskҰ(DwS|}}%|i\CS!IHǽ_Zt*0;IJhR|GE5`Wk|TZqmBcy؃3ATJ0hxQPG//˪c&D* r?ǃnnqtt=i񎷽 k IDATy_Ю8{@RTMM\ n!yӦFZ4wvTK.nQv .\‚ڣ.'edaXhMf!C2ͨX&rʄcrO1v}iI5QiMyqˋIJ|8Pd1AfXaDMm8~ZRGu\agFwO̚9$JuӚ#jhY\尖ze&٬黮JJްO:(d0(fW D%njF+Ig4WO4ōJO>ՂA0S4('& Qcm\(N"ADq:#*IF d-f N/H06M IEdpjDH&):!y9Cuvn,4"v}Zwe ]y5ٵtqV GrQ$]7sI9=Rci8SDM{ "";]uH)FYd75nD;̖|]5ӤcoP{dp>Im4(nG>1qw}ت?8cZ .wCn2ȻHdVkyZLvX )8~!JyD !2M(((#礴|DV҂ZBYGPK[YAEl#S),QYjDgmx-H'azJ4=թ I@c0BIADiQ:E-(nn:a9519[+Z1\ `C&}9#'+ 7tTDմCB1:"[rFb :+r]5>t*A/& !a xYJL"p5-{4N{_j R)=Ҙr&J^7Q a.#k-ය!ܗwk x(ft#)ۧxZC;܈v# rtgݟ1XaG1F"FED4ʴg 蕞.6@51cTY6vDyOEPg;E `'i#JMޤۣ!&cQE |<=5Ðo<sT@M( TLjXDc{|f [2^A{? O[8c->8m}: w<9H$iYZSF-g,v;}1$ghbc9HÝGqIY&BAL!~im MsrkwLJyPns/՚z*ѣr8ޏʓ%uZt&UT5_΢eIeEMTG{o'С蜥u-uXk-"pr57!Tأsj^YxbޔVGU[hS!h&r4ʵ^z=[>$ W???¯ߏo~3ͯ ٴ\N0wwQoMEf[ѕ\V '9:@RCSբ: t -jWV" nMP2nRL<U+. rd WT0wyF{7>Ib:#}ZQ zo  B;!M-|g A"srTףw@8gFsL:<`FP.T!:J˕MҐɴck')A(佒jJ4lP%m-rAA_to6nHj;F(kf\z5VN-`9 $/*@GLR' J]&8^s7]V$氊#aIYqV~/ZƖ LL'H. a&jW.MHOs3^:DkRCC'!cB:"z, LA R-3CV}aa!J3)<~ҌL9r6R1Zלu3~>y!Xwg88o&3xsxCܝoq A ]8NtӲ4eHi8hVmQ{oI:sȶvO;@;irJF+OF!HE3@k820F @V@.򎁆Ԅը^5=(hiz2 ̶<iS@OKpMDj͇Huj0 mfL\2SQ F׉7RGZ7 L|oGuk YWX*+ɢQӋ@u\ebCH/"B ΢; {Hpg9.Md۷tٲ=;4z<c|n#:6eDeq3N~O:*lN;3轛z;BZ>ƌzs2s)94(,^,ζBj5rHph.oHevSÔ2Y+2)j-L04NxOz VAB4 )haNNq/u"oɐTn=^[171d%5u>J2/SpKB3O u6/9*Ѽ_H]u3}ʓ`)<~o;g?¿'!0<|p`nĊ" @b-VۚmAQ@Ф.G3HQFL4OI6}%):de_zK`P8!.=Zrpx*phm?@ݴ.|Jt6x"((WM=(?dÂEy]GQHz֎8j]N ^rq?3P6iʁpnM,#45n֓&9p֪JkB$dpQ\Ƒ10,:!bZ NpW&>lvA9.z`YD̋Hr+z;4lU'J^_ʼnڻ~9D:0C7y+ϳMH=Mn(yAEya{(m4[`gMI9E\24h#nXU e| PDj5v"^fksOY!̘ufz]#t@̓x#8w}~W|?z:@[`7wa:ִB2Y8+'~V*3)jVbt&{ZTlwl 7|O:(#zJj')3EX01P#<. gPuP05uzNWvqsj Eм8ܓݤ "}uֽu>5Vȅ=G[QN/tq]t2/!~SHBfmjva9(/QQфƎmwb*A,L\!(TEnŸHTV!z?h1Rz6G0VgQjm"GL4զ\6a;%r̀h ]5'E@Ԑj+ 絚`Ea ɺpETA q5ͪj@5F>uP̱S:iLoDTk! fI*&125ؾV=#=kJpdjAiJhHkxH9(t H4Zgk!^͆)H;Qp}Q^5z]gz-n6`[fx㋟^:<~O@V@9iDgu1nOژ ]QƆ+n.Fj4mBB&rS*U&}V4Dn I#X(IK\L͞tS5J҅k5Qq] $kڎ] $*O)sڮN4Q:V7U wujOw =ޓM6ŸtLZfSB  K-X{d@l( ?'S倅PWw:=l hjpu( I'D-ͤ._;8/2 `GOd5]6Qբl JhV1ni9=lu/Z/ZRYHő2i\Zt/&L#2Вz丯+2MբLǩ7jʍlKP1Ǧd!R4NALȡb *zinAI[d3 sJ#|2О l/%9U~VJNMA$h;a9QZS='0 ѳUs*yΐ XS(g iʪhRbeRsOz,JTp(&ﮐPG!-9CU,ƨhG+=g)9Otù-6|\XEF諝aiR w(]6R8)Dz*d5MjYK9~ +G+zl:a&B{2m̺^0b=a>擝È_eh{7cjރvFk+BYsnj.Άfc` Qm>F4IR%Mcvr@;V;r@rM+F~oԺXh0KёߘVi[ܨEP1Pi’*9U οM#K{fBNh :KD^u{w ;( _y?߂'O^{EK}3=8`#0a]."9uf Gu T8ځ2̬5=B{:\KlΫ,nTΩZO4$f"9l֫B˃=|EXHohGld'mjTR6j&s!7W&ՊbV&1(>ӈ艴Q.r ̹bLqATGq̖q#$\#[2|ʹz>}m^+}Ps?? 9=?_%gs$q%B`N:}ȉ{F J\5@" }( (D$[uq0uZ,grY ütwA?Q /z]6*40{֛8]ܣuO-#.VS5ڶϋH)4k0_*MS/D=rR'Amr\SevђюYls&Ѕ w*Թr@+ U+*4Zq eC 5"Caj-ʧ3[4 Kx٠U@z03os!B)k*e. Ȃ6@?NҎ,Oly[j^E=Uq~1JP~~j ؑQ4Bzz8#YpZFTîX`Vh4GI\E5'X}߷H4Z+t7u!v˖zIqR8R&Ζ!]Ӣ 1HjQBE'=6D/I>'믭\s=r*N YC7mC:8q6.2O`qu^z=ۗnNnx@/<~xᵯ/˟M&f Ȣ0GcDClg&`z~U|K6m\{_YR"yh|FiBrGeNZKgfgE'fs[ y!U e AZ a+~/];椘O[\$cLk.*cBa5 9@iL5H-PFlp""clȒƗMTB fAt7abrC)\_TNCxcn1An.[A54N)+KN[h55L&C ̦)15ɍ#t=zXچ:q8oS Ռ8 zO Sb5^ m!RF%Y0g(٦GQ: C3P6\0rBɓ5el5^&Zsi,kU J# v8LsEgFM2h< ]e(U6~AMu6C姼_K+/\X^M=5XVtnv2I#t&F"ȾrMCP5CC Ե2s0^h٬P}i\c_ՙ5f#{kxs^mpwwӍ=y|f/269dOak9MՑdmώN`^|o0BZ4f*D ۢ4ǵ9g?T :Yuߢ0>?QEFAߓ-8=6v;GtfevR7Hi`MP*$2fA:Z"l"M3*0(j2l"CvQU۬l#>_~#Ud?sfd["EqHӳ623*kІACDNqT7yJS[4{Ij-V\G0~3mNۙqw5Hza DJ${ n]"Sjދ FVL>Y h .UKCP*DoGbֲ0bkyVDЌhS¹{,p5~>RG辋R7#%$ɭeb|!zlCRλǭILd$) d7=dA`2r ;+ a@Ivhu.hb7J2 \)TT2oK곇r#H5@.*W>J>#3JߛYH+}u^z=Ƞ߭:X=z;}_{__v<=#<:2=aGiWV(qA*w 4Ơp?+Gwn۽P\% 1zA@{ji&щiWtxgq^h!Rz) bR6E*0psscЩq"]^|w&stó pɪY@u2\۲ d,R}ҁFFdK|!' 9_)eߋ6sP-1PƟM|UE |7u̍ Ķs!\GaG4DpPHrH mE8!_徹 |>J)Αc"{MLKS~J.5tƏHZѩ{p5'Rq(3}4e([F,Li j0c,͔.ZMǏg5FSͮFV9ƀ.Sv*2k-`C E{F sEj:ys*fBblACmelRsDK*]g{cD7B #z%R }ۺ>*QŠ v潲l`<׉!Y`K30j}#T4u3|;G0n?O}3Jc9)>??nzڞ%nm54,&\&بljnVLgr,D<&g[у(*AgQ{rr2ZJ#d'i~3j{{C.6ݪ:S2 5<L|Vê̯+1ȶ1 NN"^10,:]dۘ(GIvhDkFVI+3 (~궾9lFV9f6JHgLR; T;MB1TG| Y^z=Ƞn+DY8x 'y/n|;\nkvn.rV11%G#1bp~ {)F-B謫P1D(vM޳Hs,;{az)UqMv;} A,%S.c`MKfN(ܜr_ky -FXb*`ZWI:/2*I}*uA5 ^DQvr;"=YUTzyBպOp Tu 3bv4f4)JNf36 ii"^# 8S8321 wi;Yz>7uVG#Ȥ7AYvt2p'd>]FIKL^Vdbfߕ}E7g^T|)gsy?%SKw/ok}߅Cc&X 2MJVÙ@)W fuPaKh@ȥt pU`f49X2ƽ0{/^l [uSsySDę)$vbӈ99\ 4n(2aShdlPxflMk$ ^uf=pw>t7ox+/T<X.8L09oyM17Oʹg"P,OF=At;Vۚ́sd93tYH@p>'E쩫EQhfeZ'#T]eWnlY)` !\ H 4-7xRvO44vct8#_eK4$)[ZNhEj x"C2aP@Fdy]<FSf2])vEsxQgs rӠٺw4Im֚TKkt&%iaPЙź̚|GT34Τtv7^(s.i=FêXMAH6Yٝͤ>^]h9p臭2)3e^ Se$d6Bbs=:AE#̸nM3h{bḽf7.SعI 8<3]ˆZhR %]κRCFZw:R_MnU 0()G@J`J<;TGqhcJ¼EFۘC4˵`c](e2=:w ۟8BKkP5l')Wr{5 O2Fǫ6P.6 3ûȻیP;/eE(vb=r# M&'d ;6Rk4Bj 07"JH.^vw拑%jdL kQ18:RʬB*M-ڑz `#a˵`k5@z!l:XnyRQS^cXZYru i( i2CaEMEf#jC3h] 9mJ'uܬUuƠgHW[Op,2hg*ԭX{hF)^ ,]/2BCGT}fM\E4Hd4 {kV橣=(t,sPD=5HV뿁>pi; JSfhE]ꂚQ* ۼ \ ^! ׳/@!b\('99E1U0㦄7]R*USC*5EP Pq *?4:d=ZMs|M5fFX~9.e PR7Z":ʺAL:CnhYq.$DS'Dak"E4@EFꤔl˛*IxgCf+izFolZgւ#t5͈u˦5y\3c'ͷ׫K*y -Dd&b ZHcyu5ԂNL D' _hEaKk"(O睨@%CW!D;C&j֠K!h7:Yjqd R~Vc,?yPcK/_.@X  -s=05@ :]F#R L&%D[=3ei!c,JK=txP. L6\PnrAlLp4\`j9Ҥ+݌)~mc5u=$/5t[HyEØc^FSfX33 '^‹Mxxs?3m*Xt\6f#jLS4ljD Ī2 eF+dt-KhZ2=c3poƖF"\ٱ܈uI2EڀD[۵lmUe]%&Dž}4<[ˉqyfّWFhT8+B.-".t6ݓ&(B05>CF-C*9jBrTً4@:tj$Js[m@V^^&He鵤 O@7*%nҸ ,oatbeR#M5*PTt pifE9ZDkh kq\Ծ"5k sP2+YJk@aBOFL|ÞskfL7Y* MX6zPGji=Y!x.YW4:{US=4 ڏFk@hݐ}Fwtq0 %C,5p҄i'Fyf; |j̚Ό~eF `34v~]6sS?zju9 BgI1=̆wZƵQh ! cr\iz]gZpب8ߍ7 ~˯)#a~@*rJ.zJ\&d' 8,c%ylj)&q6rs4_F htYH!PB-DM+ g"+*tkԏB xkoB3Ƞt' JKlE~;D@^R LD7bZ21@ȁP3STLɰr9%aI6"ϑQL/F2RHhRLtcP3Ŀ+t4lfMS͂4shN5.t0Bi똇Zf"'dTjƎC F: McAj.x~hW68]|>PZǎ2h-\#^ 3UZٌ,[J َיF))}.DDMt,E"aەJF|%1cmvCiӫ2"!m =2Μբge>3ΝQJȽ(iz,ZOAj%D:55Ȧ ) BS71YȈv͈˘( Ys9'ʩLV3?frߵk3xzve0;$xx=y?/wci{on׼ʍ8}#tͲb!VOm@1҉,-Y"#J#~"]MO4dGyWWfRZj[RX_H Jy[I' =thht/S :GeÂDQL0.aCґsQ ָZFPPziVfZQڽo8 Qʴ:U$Ӊ&QRPC67MWgS.  =B,=hLyꞲτܺ)\F>#!Ϧl}AB0A߯eRvF,{?US#rϥ܊K]sB['F}FGE4VۙrvdRWn'QԨ!A{2r23)zV|!]tٟ9Ίh0qr ckEJ(iebfE]fskms'䍔pmPua507ۼuN(n^/s"uߘ, !)Lr:;:t~c?֡BcqoGzGOz]ufP[g<}z?Y)lC5G;xE\`:rϙZΫRˊ!QMEZek3xzvA;d;N;=O^,~~^<6>c? &fO:GMi¢PR U:pL -IxPQaE&4ݷF6fs7X<FhIY MTHՈ# G䋆JU+#TS<;Òyb4\JZJ.|EAR3h$OFؙ/*87p~Le.L+Ls/QcTְ& ݑ ^{5M7Zh*:#S~J=j(i2G7*XKPAST2VV@Lnf*E0vkXCk ϱ%M<]BAOLʧpjb/lӹrM\y-f#l*'=\AQ|sT]b< 9\FFT)M&xY>XvɇH@shaAP$GY Ò!T셼WeGJb-Q16e@>+j\@%ܧ%}ᔓNzNYJex{& GP32 Ij[臭#_hƍ#A٨:8_u3{g6tڮ׏>O6ܜN_etm% Ťq+Ҫ8"w>9n7 S JvS"HUwj~E4>!&4JەGw\6]trTedj:KRi:k *$#^P@+ࠄ:˸ژc/3MB9z0CŲװ jKm[J?J?ypІ{98O;-x:|7d@F#DZnSDD. ,f7X1.(OXSfQBi TBOk1hYi;{# bbaDlcɔ^!Z4jD5a:~BFH@S7B!ShdVFyG$:oSIZ^^0ȕeF& HGnJ&E2oefeSDf8gcA%آ2#In9e0t20c*h[eJ {J6Z"7XxPLQ"4]C鄚JD^Bbp >uoxg|w|Eo/} >|ۧŃCs;B uު-@mW=BgYN΁Qc{Tj@AC V'C@(@\p<#tv]8 vyY]TPF'(팹BjMEmIm{ҺvB.LK|n0@f70MK`TIC"eGei7)̻L3kA%T Fx\Ԁm!\FIhEh䬴+;c+)=\*B>;į9z]g:)ˏ苾o}oǧ?>~|)|wӅe;pP4hP kxmthMM#뎢)TCv>};vN.ZdZ͞O<Z Zx(yA'ҵ.:ҡix-yĕp[kP Ř[MS'$[zT&r{5Sx$>pFI`֙>ڌ!T־7;Җg(gqʓ+Z+)]B>%6//XktX zm!\@8l9o}ߎ5{ 6fI%B%ȋ㪶C`:b2rwϠF0Y;0e4Yez LLs WI]uCJ=P0rj vןQ/vs| N6nњ5PQlTP/5륜1==25~uO6|Aa'2yiͯtPhR8;;9i #Xٓfe3 jog!PCVmkUwk "0G#䳠5[:30A!V(,inj1( mokPux8!{׹jKIJ=7sŃ33lOsbp1OA2hrƕ&zzۻ;q:)n__G~qKf 8N gwL\zna ®[[r&wݒ!$W1p0(ŭGTn5oGC\8T]giz4v:gΓxtA4?38ckQQΪgS+ pͅލ8Eٱu솨t,|tzeiQHe;r`|g#Wjj- MK4jm !]#WIHa Lp~)&H>uSSW!?SKg#)ӈ뵍0 㗤/2(/VӔv,c\P@9myz78J .ұGer& d#(qD̓K~JzR 7dEQDJ+Xa9F²)_Gt#ȟ0 ݄6O@S[9CabȈ^keN'MF(Fc }^?ǿ ?nA>ڮh1 EhXV!<ígArrU慭yCFMe4ΞMIMf8vU(.jb~c872ŸS{c.TB_uYZ24*ؓ \4Le֕`v Sr͂?PCƉE}IQ`FS$+ J:*FE)IHҔW xV1Pt' oO Y,.Xa](Ŵ i5QrBK3|AYD,j$^VF}jmPj L؊e>ڰDil7?v^Dre$1_zk3̭cKn0FYDxKhթeUX@*=3&cUUg D(/IQec6Jhz>T)bOKf~7I5$[{rj!1l`|4Xo26.>O29ȑ:菲)ËWkמ#!b]F/ynFr45Ni1Bmk߮*&K:eJ6^#kAG  i'IڎfqD4[pPG"-_\iz]g}Z[|SWk}~‡ʏ/u<~7 MM i!;ԂJ4 (4q8RK@,7^PtJ_p37aY;avC)^(ˤR֚E>M03%`% ' +[%zMB& +]I5tb]}*끑%^_k&ޜJCb;j;M2cL9r{ZГnOl4)QRj/h ) c;=awP1i~V?g4bX,IS`D09h(#*#TټwB`sm^p3x«^o¯-_ex=Ňpso|qslρf i2ѢFvGcW74-Hb|LN`~@̨Myq@W[Qx ꧯBpay^J""٬ePZȒkIW6o-C٪#{ w߼'BJ|/CU, g̰D}+M@/yң`!hPVvE_sƒ$)8&5Y.e屽$#p`$!uz={'B^.Bύ(Sh=VkZ}YIl*{mu]1#PilUŅgMek5B9xVvyzh_r5ۺԹ~86Ri9Mx|c`FJ=-VMq*La Q8DyX\Cr>ν7Ε4Adtl ?}=D˩ N p*ˌLJv^ϊLDrä ~9EmLH s,Xt@DZf8/rpQ[VnFK7W{FTThrviMY1C衹z&=:v2N&ށd{J1|zLl#^{O\RG4M7wUpDV )3|kyzf]-+O~-[O~ߌYi]8Lifmd,}Q dnzi*(N#Q.D588F ui!ĠDEUf!b2=^뙽nol yki|?~#/AL94wSI@ ?Zk$G]NHǍ+m.ls01n`q ]wHkb0 2G=!K0FN5#B7ypCAvH56c [鵩1)g-]z}GӲS2:νhH2åh%qhhDJEsYHhƳF4jw31m\vjN,ׯY06 s/ȹ NzOYWût8ifz]^v{3;ܞoq>/˾_o|߀گ xX[_=/=dU 轴&aU&؇$,F5H@6D*+h G̼:ԗuoӦ )6cjX8,r4yYT^vmSJu?JNITKs2@f(%6q)( )^sn#nN[ݹHZ@P 4H6} )R]#^EaOTȄF&^G6Q솅|6n J*Bk1_"TMK ^338怵!ffsY֚A.Uû%l@:KݜF>\kqqՊ*B,'n6DD5t뤛X!L`ۆ/-n]ZIڧfaET.RCMv`NZ% ,̅4EkgCn $ ӭ#dSaeDI֡iYZkP=c0I2HHLޫ@R=t TdB1-k^뙽nw{//x.g/_7m ;Ғ`ऊ9_q~& '̡5t*eH94ۍ/ڍ4}vM4*Bܱ|yrhH]}P( ê 4B ~.Q:n@mKNkI GF#: I\km༂vl,D4,52 yPIɡ:(F(B5F&RcZO;[{f-X[p##iMi*A٬) >i57Uࣚ?+5M۳f(5F{f)` }I-F8mlB."hՔҢ# r-m*Ttۂ-2 B,\FLo&3iX(Φ3c%Hbf6El D|Y:4u@ya1i$s@1.ԤcWRgZ1,Qv]yEcbvE6P@sW4L0s $I.w(Qs-I[u\.m3bb]qz̸ლ{d҇\v2_iz]g]9pOgo}[7 {8?}|bJ{|5];peVom%ZT\"7GIL128`M@ҟA Q#@5I'*TF4)cJ^YPV8Ibeu-r κ+ƷS*5H(A#!]nbjĕzihʌB\9&_!Z,l8}[#"?tfxՋ{ڸxk@h!؂GD:r Wű!OI \w&g#Gr/;vEՄ pj,+[˗<J+Ci Òv*DjN⹤> 54Z!~AHiXpx YbP(%Py&:5 h&&q"5gcfٲA_!ʤp<ƒǓn~fS<( hĥ}R7j>QlDG&@l_`H0 ~DOr>`j@^-Yf؋RjmxkFt bֶϳ#y'"#_)%@UJuN)Uͪ4n@2{d@yL_+RM%m01(6e\=#str䀆s>$s qds%Gh%2`ČmRmFhe`G@Wk"mHB Z-J)]&)"[&rzr'`f úi&y>뿅g?7ƭ Tm/C袌$j"Wv^16ꏔ_ l }43͋lR6dEL$`Di-T3,bF!\$vD a:o>1mXb2Nի(uSVy~Bt4w4nԩRd%uP,$nBjN[ɎU3Tg bgԠ_KqtO H[SD^Np.ѱ5ē5iņ5,ڴ` YXjz%xslT$6P>gܽ{LzqXd:)~EɦP)o>X)"(b53КƮ5G{4A/EaW龎K6C985ADM5HV`Jp6f(;Jhӭ 5jY7ɜ-OKG+m;XJƂ M3Z=487 4WM UZ#yݯ:ү-u밺O!늠toaYTS %ؚJ1"t!7qů6wi&!r3PCj̀RŁ:¶7TUE|f#b .KTu{iQ?qA94o1]*a@  2xr'c X.GS[ޏ}7og~XɏR"h漘~ ]ltVYJ*J4hPma8btXj6)TCf ZM8JC\]v33mzLvʖy[G5Pꢢ$njE"#g`_i0'F;5O#UF3 (qOY/%pmX4#֘$hk! MYTui{.z['R' 4bue +U#uu+Yf]+HL9hb(1gBг%隞h|=)SS)GȮԁ6u܋HHsb_b2tXGq~TLBikJH'Y$P*C+a~T*'qrA39|G%L& %RG INl/g[i=_dð+ D ~qn?SFb0,\JžVE[%P9z"1R u02Wl"$*+K[ BQ99ۇ֚aP6\jA|(T-^Z߈fhQj1 Hbl&JR@I `Gg8::a7_f$v ^7|7gh<~7[.@lz'vμOoܹmAL&#| e5ob *󩎢ESj:k3C8FYaAq %0t^8q)0t:jtómb@4rRySFcy~nhkӲ6q2@C W pjRj U 6Ҳ`. MƓR@8cJ9Jɫbs"AfmMcFbT:2IPVMJ`[h|)|PS898l&mS}@ XK#zKRjgt`^-~]X1Qn37=h\6ꂋJ89 E~/S=0hK[sp1+prEشCPjx=G5aGbUX)-01 85=խ!eu>M.M x[B K4!phaButVm&if!Ů4=iXQVZ5R(`,X0jlg'1 C9%5Ki{{p,6HqeLKdHhϝ xК` X0B^"BY{`y{9`%\Rϛ`GVJ2Y]7+@|4z+[Ch$Cp{3xCWY@Mmqd%֘aSI3xr'`>c\bXx6qܺy wۥ1aocPJ8U1 Yf(K1vh."R|GY,>t 3s -I2HAφi v>4 ${͍M${69wQU^J 68#3U5;\_;SɾGoZ@!j pw!ZGZe`E`IpnH+;PlLR]GЧs!ܙρ7fKE9F4k\VƆ nI"b. FG Z8 ٓ|0tHm Sj/ِP_zjFdpmdC/jz'4ѓCs,Knw;wp5\r׮]7Ã=Mg8Ͱ/0_,\.NBSѨ  :n`50:p1=>ė&{y̎qyAo'_O/ȏ0H'LC̗Ktg_/˗o_+Wџ IDATx7]BNAbEFGQM>WjlKA Y)jڤ6i3L6[}m((а1CȄ֒;ZG[zEHjKO!.*W J El΄)NDԽ˧ncb78Z14mxȊ&Dp9Mu2K 0yDB7 4]C( :^LIPԡ2sݨ'4)C:U5s6c@ A U\@6ٴdȣA2xHStʕDc + =Ȟ%[|FDՈ5"3 $>}+B5|mޤ7~)тDܚiv{BMu09jJ[͆J4 pQjW4[iM]rd_D zXt% BQC2hQMC/}C~Ɇ J@sQ>uҥDC +~y/ ޶!YRMVlDe6+16fV EuL# Η!j 5IFC:֨txDJh{#Π@%eX"{̭oY.[Lm ">]Uh@"+f-眃.Tǵ0gh\ImlY6P&_BY%Mq:Ѩh{XX6]+4G[uH%dhdzNf< f5k] 3W]%xP0'l 0p &wn30Ό3< 6-VasMh+s]7K8=,TR#Kqt| P>о~&K^֯)t{CoFiba幥% 9p+M A~1X'qr|8ppxÃC]ܸq^~%ܸq {MX  #FF &X[[66711uZ`B9s s;l\%Ff.x\i7Px4`47W/b}7nc_bco?W_7ݧqxei=4]ׯ~—>=K_ݸ ]:*ߩlȇBrؐ2]RI9TNLNƵO=/?ps=P ɥjHiR1kF! 8F)3QZ\x f(IX":W@uE:gu䠡HuS訯L/hsDKf[H ˀ2@nrEVnBexV! 559[sȢ$(^ "U&fZ3UoE!9Zbx6F̕G;ztB3a)+$"rh0{tJF SŃ Ua) b! u§,i2ۧ9tUTd\֨\ w,^s~Vr3|&8,  a+W8u]*ۄlωj9nANhE1Y̩-Q[7|!w#&6k:rB0";vOmf.hfQhۨj!o\ '|nkwl ΌG|-V.h-y!'"8=ynELC7s@#JD`W&6iK;3F vBVFef[3x{n]KOh'c1c`ׯ+ʗ_ŵko`wwwe}'':)oncc}k /gFȜ~:wI PՕR)|YA@]P6^}ᾳ#'c?Wēoë/}?/ _ȣxۓ[-8];';woB8cڗ0̪ap=s؄ ũoS(אD)"UkIoutO?5;ä#虂GtbV ZM#KjF玞`1ib|;͓q=D8GuSUo*-/4'p2.ܙ1n WD JiQv`vțB(j׌6\p7x4t?F< "I)K^b &)? ay>JuӺCTh-&`Au U̜)!,.'~)[@ϣjv3V.؜Li4Z@]HW)j@V-CFQMPϰ#5^KE9P;9};ۧx`s#%}?C8QnۛlLV ո1mtbƵEF1??~\~as};8͛xhprXf|{ ӣO4[7O=p]*P ųDK^z2Gl?aͥXNc( !< dhPTTR2M({QC[lEt;MԟR8>^ɮK_ꩥWw67?mR5c0  qEy3S}n'h'ZGP+šy%#dl4fqX%r ;DэTǀtƑ5FRpc|WrE1CCOmyJf_S=:E~̵.&u0 )ib3;dFS F,͏F Q`&H(sEprxjTOnXEA+(4(; ങ4;QaCLjaT@18H^z:M7%Vr=~$j2(rMc PA$e2xH;>7Js0 X&B/KuB݆MͲT/ a|ݜa\6y|qAF!1$lv?~O$z<$ :ue 8*=5mCd7\CON^Pmx|]w=395eTymC& 14OP�cNSf'rF7Usلd?r|ʫ7@V{hN|l6ǝwpzu\r׮_k/ƍ{{8 " 'ƙӧqG 10>ϱ\,gahc-X_$4yjAFmnĆQER[1d$t}} ~mx쑇qM\"TSPT㷢M-Ȉ185NY%a ɔJZ>loK!iAt E͉ t+7144h3C ;ۜ1Sw!맦@}ĭp D'ժ6XsׄB2RK=3 9{ nՁU5I&pa\KwJ(AR(T}Ntœk}.sHМjޏ+@nPDLaIJEpց 4TS٪MKA0> eL `n`ILZݠh]_% ]]ưcJɻS䱫1BNl2ڸHjAn Gܗyz$^7E0uu,%[sfهf=k2뜬a}S 3Q’3xj-xj1$¥q"ѕ!+2 ٫ϓo,ndKz{ ;gōzzT$έVۊQF,lql\?f\7D]4rAkS`[ (~ ÝSS@fSk58lX'X.MqܺuׯK.ҥqK{9kulnnb{-lom`2Y{,Kpkʩ6Җ֜T qEEsGZk|8a0)@0HqrLNo0\/~>Oᡇ`ss Ky<k۟Ω &[M藽E&FM+{|$ PD/ILK?J  NEs39}~99F[Y eצbEːb`SL@O-L.^5g":b8 tphVtliDJFXW6Z;!#@1 +[,6iW-j(s ~ T.ZA"&N45h0Ȝk7yӜ7ceXƁ!CEs?<樥7ឤX-%XX{ʔMh:$H!ayR -\%"pJtGC e ZFM;ƨk{U)JG-Bo-&K(]\Ă&Bre7<EޱaY0*CÌh@{D@f uJVsd#[JpGGH3c\f%16ʨ'#e< gtS'O_DhuIڞDfEmqF/ťUZW _8`X MGkm|B3?À0#a 7=q A[t6o5jmk2x tpYkMęq4f7Q/~ 'ˣ{L?8ݻw/K_"^^| M!BFOֱ33gp}8}zz%ˌ~l>9BɁ I,]Z4ߊ'畓7a#kt($C \.,X[D01ttٯ ]3W>_ykkG88i|3oG^bq4ٳ`=L#lZC ]*.[v1葪 LbyMf:ie]5P.nzGȍB*4hE)xh\#Өp&*k~[jtaPc!V*L&ʢ4uUd{[@X%ͻsHNAWrgOQ hJ\`BPF iMGJ@3DUF6j^iBѽ&75p;ބF'C4T؛%cfHHe}fbbd@[)*XђȚKB@y !bYECfQPz5|3ꉮ08 5 5iD2jU3q`5*DS=#M؅&Ji"=+˥Sq86r7cfGK#4~-a&=:`ܕƜ=GJήJEJdXI9DT\.cAɸ'N0c&Y,H#E1qWhxV+5EpU-؛S.ـ\8?̘*LȘAAcP)ZF _wv¯|zpz Sj%zREE]iu!Yt !+QUAcq5>ܴҘ=;"ܑ}Mړf89oE?qM\zExKxWp+eag,=Sxۓo.ckkAy_\?-TT:,4,Pq(I/;'jVʢYN#͂U X,X_/`6%5ܼy(DRf9%=Ν9ݻ'ct 8{,8/!t_?]_5/2>]G7@<JlQ BBjAF:f,[$6rCI@\ UE"ˤ?{P@9.1-CEZ\0-HP! T N}K+[нәjL2dYCS 馘E`B؅YbnS,HVsͶG8G;!/8ňTPEgfk/UĂ5 ﺚz9<7+U9H TW- τo}!(b Q M6w@6wËtutQ4 XU>OT @cͥ԰tsYJc>Jbw$EJj$Ռϓju(-pjZ#Y߇ۚ%}w*SU 'XTܲ:cρcdl/A&u)MX tsV4c4. ᢴ y0˂v:ֲ䛠w]<Ԗڿ.\;{ 318 s!|:8HnT]ꛆN^"HgRMӰ6A~sWpf@![)cDѸ6d>8P'`yL_L6]i!렙E@MgŸ&ANٓuUֽ<9NjD\._.˗/_^"nܺC ={xy:{X!`3fsݵޝ8r$.6v 67|jd,Slj")b[s!"db9éSx'1/H#<=a0Theݻ8mF ?QD\{B`JúP7*f]%)BЃC3 ^ 0zϾ;n,8湲O:֜!3 g-B_@єwJULD= L6dNua^ L2'tm_vl+!q9_ؾ9 8,ﺯ!mC+;;4еXĥ2YLGKXaNQD@H'k|1FiIT+<9N`f3ܼy׮]ë=9\|wvoxhӧws8sΜ9-qCj4Y^A;j(K7\qE-`uR~Yz Y9>ck{ OcN` 3ݝ̴Qc4@GSolaskۧOcc61=:ؽ{?_Y|~c4 ( j爅qkmyOjtZߣbS9D% O s'\Rq:զid)B,Nt u3DImy-9@P K7VuiNaST+TK̸uQV=`-dpBQאg_[hs|D1=$jFPRjX޷ /t7Vͳ`(NOsNL.54^ 3Q\.dOow3 {R9Lh iˋT<&-Nb'&1=^JM(Ĉ t$YTXoY=h\m{ %EZm.g]2⍌31 bJ߮몶\ZĺO d aԳx˱IN:bYtJp^-:ς@6,HhoHSоj(QK0fXm!Mb/f4)51\K K̦];޳i~:\;jw|\KBx熌ܡAtOH04r|<k]Hr??NuV Y*1s͗4zjA0˂=}Ci ⠇EORd3<+ [X \ޞ%S((i.M#?Ww2jk _WēfCy038?ěo|3g?Ͽ޼v :lnnasso{qxE:s ]JwުEEmt :3 d(^%YdԵ=Be~O lJօ 􉣴F,}h4c=4 ̧A갾=LA2EiB$3`eKHTz$X[&vG8 p_~NEF}Lɩ8lYQ?B.5 fCNѲޏu6;RR(8qK0QzW6gB 7Ƚ5#f'ݨ!hc5ڸ:hQA̪&NKEpUGRgv>dʙhNc4EkU3\hc8'ZSh(fϐǶhR*SmÒ,uW-5 FlRm*Ts%2#0D*#_/44f:82qyjՄ+dy2>bydE{'BȧנRZCgL:^\]$e}rQ 9y<ٚԫVW^[B$ p*lN6P`wf5=(wQ@"F*RhC(m&Ct}I 1I#QV8&FJ Rk$Il+lz!$4,i%:V,Xp0nMbl%ƨ6ð"fD<&<73֒p&T=:9[Ӽ{`_A*)YmUד)s?p^ SE9F+  oQ#F:u. ց !#hXcCY΂hV(=!qT5'[.88<^>Y<{ᥗ^ׯbDL&lon{>8.\wFu:îClVm }VL656:YmPbCtjQ:d[|'6e02 "GڝD7R uʝH!C\Q.iPt=T Z"I]'ϝ9sJ ̠.UDC@OJoӆ6:h5 !\e\(*PQdYp`hyqQ#M9hˌ@w,A!~0Ad7g#@NP`> [ tfu5k<ܐdbMg]A$6lCHMEV՘ƩT)\jb`gE*d!03b&kUtwW HjJh,Zyz3-U;),*EĀ W1CJSH ?-.c=WEh7)uBx 7+z K=qy@!;ůs)b5#=;ND/AoG4SN#Zi|YqnX)cê BX-\Tb{'<0\[$\[v8[X-I|7=7ٰ ՇX¸L?3EeP[Ɲ3uZ #0ZD7l6]WwH!j#ֺ"N dNxi%?_t ={xҋNj/Cp'8"}ÏܹӘ X1)ӣq.:3H2uɵ:i+."@8w>3_l}]:dҹ1LA҃i L#QwrtS>X6Ą)%1HW_yׯp<?'! ׉7̘ Nq簵xݻa}ß߃͵*58"UQ:q\Ч:ӜRU_ܪ5!МwiQT\ב_NY`AkȅcaDHoi3FD5.)"13PdIWZhFI.#FSBuPDR~O=Kd9S!@ό͔<תѩXx9KЯ;]JR1R6wNely]mr#Ga]C zm #*r@R23IJϣHQs z4;b>2ugeOͳf*"bk |Mf`g< iX0{6階0LIGxzƅ^Ý0NAl Ś `) 1 &CASe5q&C){w)8?&|w 0K$nφiyTM?!^zRyDG ŋ`]^Qh\mKg%rI3xrG W^ _}ܼyƒ=oxxxr)g/JlZLVguUu No(J TΌbCӣ)g9%760- 'r*f_Z10yG<&u*&IǰxnTٔҘ(a>$X_[C7_q饗qU fs&I 0;Չ/ kXǃ^D/kkLd&Cܺ~ _[]_gXΏ1=Q )ji<)xY5k2ĢU6Q1a]\֮{NHP3@!l6]Bɦ$!h' ( Kw 1jR}{ E8LT݈!]`hRBSy &EСK)8lj%/zp5b/ZN[JMAyV#(!jhhf@*rLnLR];:E1+-!URzO{pR]5a588VTE34Xzzj)G]4"(ِҰ1[;MQT:[ {).2lȦ4=[F5!5FU0whߪC=-Bqe4!TDAB{j@, *WA(,|-jR`2 9F mUg`6KSY1ӲLC+Y_xMhЛϊg!<=Yc=M`|EP8!0ĸ;H_,Y˜!;P 7F XKa`# T^[l^ L;= Uz}xpBxYCgU{i&TRیL"`JgO-U:ij DHi%8Lscͧ'g*[ io!Uy'N+c_}=>k+8<:)U2:uuH@af.A6S+V|3G]bEiji/)=Λhִ!L-CT#u]CTp.٣ 7jWӋL^8Џ%MnOl\6}ZXnc;Ɏ^DEk & ]B:!D{c6=VfBdקBEwdHS^) 9$wSDs$gޓPQJgd85MȨZC,pj֥I=K o2^JY_} C5-h!wE7CaI레z:)47T/uVt43W=nr`ynkgcDE/aiX 5BSM̆ו 9;ms2iJ I$0u 7 #XdϮ BX0yB)d)p.LG$qepPڗh M#)i/#*^r K fW^JCR|~mLN0'Np~P~)ƍb3$#z:=) 0ϪU`].j(]Qӧ-Rkfb={}|xҦ^ѓf9>{ >3o 1f8:>[7iOrәMLvτ)\k e}bwo8a1[`.aq4;d@pEOp.:Hθ7a.% 0@y=x{ߋ#3 A0d>CeW *jtTL( ιifAo8X0 Mf%xtx¯J6ۛX[_SO=d 0^[G63?OM~|wny>&z$+Z[b,[EM%ׄR⚁U_MfR:%>+jB\L("D]BWUdLscz.(R* =?,J>R#hB{Co=FD'",-䂜jiNrn8B!'Ӛus`-Hꪮ b:Z,K3펹XNJv(͈iIy4ٴDhÚ+e: T[iemFU+M5 7f6)YŎuhB^m|Լ&PunP}Y V ~KQGR͎D@Cm(:uews)74å IDATE̍E2ڪ?X`tr& KdQ)"N dgmkXhсLFRV֒1ppIQ@UoɈ P,П-no|pi,8&G֋6n|0}$$ `l,U]<}Q|`s1wV,`hژ0gBW. B/L;twGFo 7Q'-\PEܞ07{#y<1"SH9D'Q40I$Öb Anc-A uU1Ҋ6Ѫ35M(N+ {.>я/}& 'ov<猣C޹SOяSu +ҡ[tS],A̶LVIùDI1m *+ fBl[0a1J@ Uq@U,hV!,.E E}wY&|ggQgZ}:LB*IcXaTKW Q** "-d16q+*PbdqdO( Hےmڡ}alqy*5tCL[e8 L 1s‰.>YbYCĉzMǑzx TAQ`v 3 w"ϣ@a7C6G( )%E1)HFNjkDD˪& $6$2 VNXV%sjȑEg5od'PՃjZd}hE%9Vx:i(=7o@RRzÚ w @)KA(I?~{L+pJ%>b2JJ 3I&pK2cZ>\cUͣy-8foq[fl/BoY2bךԼ`pBgU=K7 a U8XN^|0Ѩab0,sa`lN*; OMI|`XfGs:UE&KͷHY1'C-/Y>1͔=̊z+q|bo__O> 6^~}XY^1qx@6=k4Pqs6icep=x5Džͳs&s\vϿ}aX 100k8yϟ/`9,ceiUL:l6l^.*8o3HI%Kꃤfm+H.tw t cd@]T)akgn3tEsЬll ]YQpK8Qs|@f 6 VjhHht4Yd;B S+sDWPqXd>EdmNM@J|mANVjG3Ew*s֔b`:a{'Q}]*d@5E d 9L3Y}Vɲ(gIQoyk@p‘cK:e`?$ liU^&i\լjBi5}s/ Wr±| rXY.xdyD4n06Y7zg 1޲>NjLrR-$ޜcɮJ7d!RoTل03c%2; h tX@6/ۤ< 3,MD-jIB{- '|3xJ~ɟ?SO>'xի((eݝmlCN%?Ok5[lB.iO}X8Pq-p1=>agq.^@-H"c~)c:;ƣ>c,- Xd\~ ;;&K&K~W/y)o^d肎:uDBJWct5YRѱ̒tFѮo ^@%#f*]~gK)PfR>SYYػ%(0zQSIB<uVTiht)e j1C {N(  vPR2(J!уn]_fI][)t . ]~HْOֈK_B׀D^%*Q'9rV@Bκ^k!ėtOHF5Or-}v56CԄ4KT'"jdy[B "U[=\m{b|BT:8S iC>lsPj8L.bAre)aϰ:M( ⸼;$'~{/_m}:rdT3\HQ95/x#a0VD޵ZqnB8*)u0bH-#| ,FǞF$p7Qc"+c54±6DyT:/DàpX#ƒ*ppXs\NÚ[_SgG{qU9wOKH S}b\O;^o~́Eqvp?ٟv&_$E|cfk2 +ު ,DPU1iOٟÙC?^}xE,LDib n߇zL:ΤԮ& Àz 8]_),JAJ&KX^]Kcey8s<6ϝÙ3X,,X,0_1ݞlC Ű[,1I&MчT]=+r_j7NEu\GD1J^{2%cRZZdͳg׾y[7{pgX0nw~?ۿ%%PNM2۳uRX >) ѐH *&ӈ1-]CdFզ] ATILjYkmY) ri#HܹjvQHu)JƼ9BDm=TO'N,w 1`36)GɕsD8;$߃!u0,M}¡#LAvN اwH6}Iee6V2hk`!bdOdH )aZMJI[ (AaADF̷EN`9%}׳T:*vQ Kn٫0;ętZc:SjH*!c3W5Lk)9YC\H ^T)Mj9gRlj.bE2=9GF@$Yի~p[+8KQehN贜=?.ꦌ_a3I(^=&Nz ̞'gH2R,BbUTrLkhOۤ(|Ji2%Kw^%}Rzb6[xc}Vإ7+HrsĸZa,'nx"i$ڟ̹e M…%q5 ,=?y6aH?-\#[dM7[;Js !Al!<,KSP(ǑYm =-O__Q{??|of|wu{6<5=nJqJz ~/U 9[P/ /߁.pas&v`CK=$_E2Ҧ'.k~b<5yc:e$o& Ah6٪\ ӿ XMղqSgmA:s&6ܸq+fJ]`{{9ﶴceL@95TnB2#I+"πBjm6ɬ&Ck©a/˲sD@D}޻^3£MDΣbQ Zv6Y*s%R.nɤ`&s6V ١<(f@8M!qRV7ZI*E9Mۙm\hC-S8ɿL=ȶRx@@Y> 6OTvãO-X(ND& 1];dț1ƅm,q(.c23LfXvV c xxgq)S akP0 !?gH}HkreL7JS/_%ɾsik̲:hj˼0&If,Q( \RuaNM65ɮ:V" R0Crn̄IVxŃzLہP jp+|M F <Gx+Tl|}GG5L ULb 3m)rNB2l\ɠ~gs,-3!CI(EG`Qk*S{x1K.!Ã#,--cؽqXZZFNX`3ɀ<<$9y;)`O,2:])O25y9)lBB((`w+MhUI:!t~ '^EhT A-րR4!ywǏZRȬ y)L8"$ [+ 0F3Eٰ51 |wz7cOCސ@Uxyj ׂHi"+i!rxl8kE4LX,95.mUqVڤ5X r'LvXiRN4Rތ_OaBҐImngpPǙtt^ l 3@6"IҔm>qI%ьQlH?;[i¬` <{ Xy]p]Ҷ!łT0)Wp<eb?xlVVcȝ,.p<ҳh)V (ը;\ +{ MZX]z|_{A yh|nDԂ7YtEA2&56294׊WשIJX׋$Fzeg*\/0cZ':{>Py~E V%[9D)9] !K)N%`SclH[っ&Z"Ot@3 )%tH)lw ߍ":Y(y8ʔ =T*?CB_dǟ%D?yxEfv0 |4 oCm?7MxU t -<(0ž)jaJZdNId>V|o L>-Ŧ:RNi EMUҍЈj>ғGϸ6hoEoQ#C9߹+HVFjT8`QK աE^0K>ؖш!2!S^H!=PvAXNq8U\RC"3䊵1˷(!BK^kn '>Cޓ+L`*1։ØsiLO|8/ka=rŬק+裳5Q7F֮^Z{iM%8躥;SU 7yܟ}&O=/O_|wGzvRqب"K0WC/kUE &e^ 2Q) {fUV`%S; t?d(yI\&)QT{%#B2YudQFvasטSI&QrꞍ8΄g>G39s@n#?ݝlQ0ΰŢ /8{v|3V>٢"'m~`YAvP _/ԯ 4t0 l Y 1ahg#5 |:M!d]-0 *^_Si0Bt~IdBnv'Z*Rj? Fn]| F x: 2b eNBa5ODP28t[&":Q6b?ӧM*4\|z lGY*몤H->0Y0÷BU0Fs#_9[1TΫ=C)QG,ZPfj GQHt+qȱ  2pR |& .%E꽭XɈ#]7zvuULO$RjТKXk(_9):0TNm='ĶbEdSvX"R ȣi0`PlG}k5qFjma)j );Cp?|FX˹v܈ /Fy5zIL"̴h 쭐 dJHhj*^*6bJ+4x t@+Hܭ}ns`&'E~;1}B"sD04+SuYm|DS??sA ^Br)4 gZdH0Ep_zw㸿+80'g'׾-.\8|$U/V}&곁'*/t;= RC7&ńA2v7tm#{!٪]MzTòfpڹ0r-ݸiuddVPc8.QPQ!X&{#Žއ^c IDAT%`}u+/`X`o{y dmȃ/ÿ?DkUHh!QiHtU'gr5^b!W(SȎ0 Peր" RnkQ-B`W>FdaHZb,/M?2dUr ũXd+ etLFzɷR\Ѥ4*RY@15s tiW偰:%S4Y Rx4PZdeΊFS'h L'R G_d΄!UlfƬShQ~+ʴRB]pD@̪U5K3 $k\J"YIwl$ H9AYN)c!y3;f|bpR|. &w۫^u1j|@ɤ햹iDQV3$eF6O׿ׯʯo;ߎ߁} :[c =[#A_/+|U2g3/6=d7l.-͙CNЦwDAVj8*l2:0p<đKXL"ka;LU_2uԜ4JRucArDdUgϜA&ƃ>up4/̀$f`muΟǬ,01I)X7̿]ܲA5dr`xûvdSngh2Zimmh 1һ\ HQ=o eg_U.-Jwe1"xZ\n]+hIlwX|d^(`F  GV3-/N*4S=vE]įrN' _XV &+~稓 On:9!?NF@u]lZZx @ѨE@;竦  zGR4qW,pO#.G'AJ8%L$Ch8p5i7 JԂ5$ʏ1RkuC{ڡzz[N$wEg3z.4˂4$R20RVrg!l3{/ 8O=i5V2 +rMۦ$H-nW'L=&gҩ6dRŢJTܦ|XN$1yт0YiamQDžp\ G Ba!xQhRc-12lnA&b#3Vqf`\T5XJQE:Y$_Z1r,'h)-c;B"2TsJڦk3h`1!rb`9Sn@F>v|*3%ٽ̵؅U//:ݚqao$d&G1g 6%4׿o;o|_w~[ٿlf!e{my+. F4I2WQFw$ ɢd%gmdª&C4%0U &/X9LK$)䷺o'Ȱ؜a:ӭxHޘTd `;ϸ6%\&8M18*$)L}@sNxߍRA X"jb\Tle+ SOPR94|U[.',d2F qyy "Yƕ $!x=?qɪg'C{4W<}}_y{#?<~۷l?rl-j۩=@,\х3d&pkmQ$A)%_ G|J?Ï<7[˿kX]_kGHPHD&r+ ݏ(WFOjӀVK4R"dI\1G+$j׫@Ȕ5K#v960I v;Bԃm24 ]Erd[Jk=IFVn*Ehk>)L1*w,ΰF@=eKEtMIlRZd:BA- 0^e͖6IN9"#3oW3R&eG$~PbżBy腐6ƣbWеO,>&}ѳ *U-Y3dFȕ|0-QfJQ<6٭1ׯ8=TmQE2I5=GYCI:7, *[h %0ʐL;H/uR,D\[R+ӌ a8\$f0$`MI"(:eZ0XsFGD 'U@+>:t@&Ҥѵ[ό%A,ďRF%pNQnYIT06qH1C0ȾF4 89BMz4-4vO)V2 Nj"6L6^HH7{Xqz Ytz4ZhiQ<2I'0Lxa4}¸qsG9 {G9zя|oy_G""mxOj(r&Lʝ0Pȫ'U5h6 +Q F̈LkX㐽{*G`S JSJ>]EKdc3xtF0WZ@0G%VuzQJi FLC.sZ]f@ըKpYdDA,U!M 8DphHkdܦE ly + ;QH #jaIAByy`dx΢"ƑWU2qOlrH#GZN45x$ֶA(>&s|ܪ7"9 8-Cbm BEGStĉ++Srta`%3X՟,W'"CxLaH]'p*F6k_-vIHDmz30p1˂ R%ĽYaۦv5$JA?%+Qqrk,r2 WgL+a/NeH"-Y"&D^,&yi;%l8~&pqR.<2 S|b=3ʸ 'G>.XcQL;hlbSҹ>ɫktZTh2nabQt]gAD9z^)/ĄQ8#`3*9(R'JcNO__l6?GGvt,$56pۨT=Rϼq;SmRs P0r0*Zc5=/S׳K5dY}N1n N0M{KnUlI_g0 X n(L7=e%{>b)OsF)G!qx|Ս38{,&pK>bްߋ[( c>=I\S<܅ m̫*W*Yo>l9*`2te/LW'vj%RE!Y@i'Ee-E/9J;[7SY6IY5 aW&>`tsp7m#yqe7Te { Q׹CNAA:RdO'Q:%у6ǩ s8$>+gSʡ[M^$4=.%=T|x!Gʎ=B\o45=' ̎Pt>I0`QQzHdW)ze!$TMA$|;1>lN sgCw #9U)M)T$(b3fOKht6*]U4q-pygDZo 3n /P{L*-ZL2 &k#$6QƆ%djIќ1˞=kIG[6 @bZÌO BpfB0a7M&14zf\%: aWPb3 =aT2#v9 3VRF46a{ܻx/ MRM0z⦲1ȡ PMSB6@iDrg[be{ c6;rFɝAi_8.)VZUIFr8#m7۳X)7[_b2Ѕ_I0uZA$2H ?yO1 HiN0PY a!ׂc簨I{8ycǼTu,8b 77a{w.p*$$S@cdjK0$kGCܬL\U2h-A&d*F\M}C, z '2\ȯ^hhKՅX6θy-cK" J ',MMl24`L?>(]9:dSK#9G'Z'˯ˉ:8S_C]HW|  h/9ΣL):JFĘ Uytr %~(U:3/VۡWY\ d=Q+wgFt:ňt*w O4,bfji#@,)+]KQNNo5!@'ɚڜpLM+>d!BhՈ. bzt)L@)˄{bMR1+Vtkt؞PiYQ1Yƙyei%xA_$Q˶; ڞ'VsG㚱F pi ~pFɵPg 6TsQLȣ P ?DV0։w wfc{\*fco9wGWgxJ[.+iSĂˬ<=s4ǃª'L+;U gOf{.9yTt*%p'Sy\U(qDU ߵ´OTdJ[1F*ak?<}}Y^OSwތ3r Z;'Mj4>[LpbR'*!Y.OXT ТBWh\b\PFdp !˰vM3ٗ% \;K1kdG8?9!O&&Ki [6a^ nwn`o/x;;ץ`ȘOqP"|ыWeB7ppޓ{}.Xf6gAԙ|Q5L3%?*aUYźNE!WPB!10%sD$jҀd '!tclagw[[ǘ8><-yٽ`yhzuq9ុX ؾq W+W?!*0 1LThC`в[W#n0jW)XV>c&K<+RML7- .AK}S'g؀.6_<<0^" {r(MHU~&ن}ozo$V*įM/$>,QLc(|٤)gI](JA Nhpi`OtXt T*2]ˏr)u;T+;4KAj0Ծ(!ܦـўSY[mP}F%Pr@RLEs Je3>k_U2yS $1=/|Ng*SR߳Mn^-`U";lNz۩}ytT]biY{xp{-ywJ'aO4Ygֶ7IL*ZerM9Δ1(>Y@04(.z/.<.ȌI d˩@ E"#I+Su6L049btqqy{S{;B:]V g v01s{DXs%F09 rOחm\"u_  T~u4dBX'<@Mog0E#nETw&/EXR*ePp:{JBpMǭKs'@R{MىhçB2V&,--T)c>7w}7pttt#pWp/Hvvwq]wȸt229JS.nܸXJU ۸KE|Yk+b3r+6iJKfXP6M ymes2$ʭ r{Ɏ֤܊;1yF`JvPTыLPJ=lBvQC(uLTo4!;3D)vsP3ܟ`TI:\i@OݔJ N )baIHct֧f*&80 )~ :y` J rj1iBn)LV%8vcטփ(xtI$$YgM]<?c8 ;㒰Bae2 -!l!2ڻh.W/~>p e4J tLa" !BL31%qT>vW^~ן=+fYdl/,,p aY>5_¾btNEŃ1 c9=&n%SĦeC=oG?6jcvk癧ui1x^zo]w݉g}){T XxM .^$,b3C-X`4&a h o.G*B-6e.6)TvIA%ZGgfx#eۄR0WL-c>[..>㵵5'>wWacu/Xl:$/zի1dQ{/;?@ J#{.λi·|0>6L"{@A'ʝ6ГIpeTbEZgdؐL3PrXKX6_ E.,:R䈨c!2BO FsS"7HOIjҚ-G '$onIO~HW!R= /6el]=sGZoT$`ʞ~%H.1{WfZ$y BIk-KQjVDr̦(AMmROo{ztEw " p`+`ET7 [%ܘN˛d.]cYF\uR^MH 2Q;B.1D)3s4i-3mo|q߼ugęc<:v/iTġc?0zMb4R$d.llnVVK^+=`D@) py^j h4v`Q|-dj bV[Myc1jR_Z,d'Nח߰}spczKCLN0Ɉ`Fj*Vke+!ԀD^Bb'E`uefGGbPeD*mjBׅ HT aC0Y 2f )3l6s;nVUMo!w#0 _E}xO'~eLRJ,JA&X湳xWawweQeP-Lg++sEEKO~S@?၇^Gyjm=jj%+LY*R9T3PAD(Zv|2In:/$pjmøgyחN{dJBA ޴ HSHNX'R[EΒ>`[UަOe&OAxQfDqn$ zN HtH""[a"g H >idN/g$&fpF12&bP]&N- v}ߪ nL֩hzurd$赋v4IJIaW'Coj~u8z49] xϊ8s#F^h(PqC[z'_(e9J1I10ddeBtGqs7w}Elm)f)LJS(8яo|#>^'>Ȯs8:>By{&.<sbW]'i1oƷVX߼ ,O|`DlVҊ슨E8jl故]%VtX;pe(iq)x'9LF1M NoͭK.M)&r{GD1ehQ f5)ΒY\IcP'yڽo)qWQWhdPkqZ֑_4Cz8AN4km?FLt>@YH!Pėki "5!+!˜{EBe2KE)y]>#Ϙ*i4 uSe޳0\BAxxώmDK d1~V&i\mɲv?'Q\bsUA@ ab ?P[=Fz?PGi6d|'pwfh Z$S,m-Wz4 &LmT)!^$Y5'D:D% 3OOp}Q8̤IALRj4h- /ɒMn]ek0[-ucFE!+^GR# d䊊cs. y޷7m-p*#i'ZsJeMbRmĭ$<j#Zp~\=ao^qsl뙰b.م]s ) 1s 6s`mBQ 8FSzqOחUk??ի/'MP y"/R8*84%=UiHHMj~BaM NErCNX'#}k R.țO,K@Oo0-׊qVOql &fq8VA5 5QhH[,mg  cP XM Zp>gED9W"X,7DdFhJ{^=k'6iS' ^dSDAwB6 4L* 5Uce'6]vQBij#_7ܘ[`Črf6Abn>Ԛ'JէQʮY%ʵ"mZcX݌/Lp\j_r<^ٌ"wE2LhW(S {c_xO-LpG`6ŁKkugqXn, 3Qo#)L k8KX2gOٳP+{vZyr٫+ڜ5c\>}6qvpb'59Ae~]8DހΦ`sk@!S hhKQ7L 9?h<}}I^7oSO=K݆ k 1F[M8)pBba  ҵj\0Hvhu 6QXo&KBÀaX0}6[7ag&ͦ8ͭmbs}Y^<ØL&X]]|mo{~~ 9goą | ߀Gym$yO4/.\>a*>O#ߺS_R9UۻZPslxե!bemOX3\vD W1 ̫pU<ɊRj6o~tKVq+#ҨOx4ε"0U)_(E&q֕Ly2nғm "$hmJ9}ɦhQN*)*"x{`f!?J-ʣzN(H(gP *9\L/N"(Qa,[95df-EF n79a}Du3źXo cWihV~J")"^6 oQq}>TO־}+&g:!]*]i@Qf~gU̵Zo}EQ >D=I;* Y4EEeꪠZ|)N ] ln.#X<޺VrfdƕO ~<`c \.8 :֊LIERq">LvSF.N !Hs1Σ,xǜd_n Vݱĸ=^2>|xo;{Wf605^&ND} Lkۧ6c*6b, v- cV]J0r*cVDt]˯:|xQ73yc,71wƿ4,0,`¸#JD~U KG>k׮ޞ"C:A݄S%pм!LQ8&%fȔ}+}xyXM#Lg ulm6vwNEQ_.\~bss'1LO~o{p5]z~\rO oxV<H)ilY{srVݪ{%$$,D`H6%!  3aC&alHjM u%zQwrLD$DuVf`c|4,R[$*Eu+퀘h hSRrBW Tڼ" Φ]hEcߣcg#;b%fPL96(lS H7%@ME`VRY P.!W:Rް[II4rLUU#Y4B6f䵥%6)$~t5 VzA1n-+P_aYW PZU #*qU(Ŕ较Ғ`f'6s^ة8Pdh?+(b4r#'z fpI10*f"ٙjPzʡ ^㍨嫥"7S@Ky N4,=lMng:+,[UaG MiürloIoq^{RZ-M ^ŮOA)>gy|kGs~%N6Z)@.u}~V!ƌ f,D+f" 2 hJ`ut:nٹy67.8|d"Ř~ϸ"lQȩ5A!(6o%9k`cO-UKjPdJQeҊ =.]f{s\Pe}}=񦧧{ĉEV.s?G|WW;xg>>p8hp-p/|/| y|8h;|VIӍ)_gNNEiEiЬ7(hwEԧ9w~5~L' lPJT@ c@JAz sssQ"}}Qpw?)._Lkn7xq$qe>}ם<3S`G#CfbMYƛѨloԚmjXʢVSrhL\чcjf~LMM:T2(52h* UqRlLl[8ʱehI=~Udt*Ub2.Bq/6] tl,VωAQ1?Hϒ/T-7|M6 㯊RД2;u\^T sByM&JcJ(08yMC^y;4'dZ3FhjWt7b9@Zi4̅ȵW.P9{<X V=n/J?Ũpk5ʲd0pFQg9:,[X8k}V<,X\37JiN ߩ'z/wʘD./KPmDl`-:IJ؃8R)4J 4kրNʔ0]@/V:_L,1N3cibkQ+3CPMXڤ/(97]#٥[̦b#߷FtF@XCC=3([22c(?,Xi!Un6AE$+[g3K?.9Vf"W iXdgk35Jό1u0{ٹWxVCZ)Jf/vag1g iLbI3:JUB+"93+JTnxrwzɏolShJ!]2]*@Ӧ-T+JKZzq >Դiř 7-hτ XŠ"dx&дJĪ=%-vuf~cxk_%ӊGQe"zFq "R +&ըs1=v:VVVX__eeu~OЧaks^o}N>?pș3g[W‡>(_e8~8VK.q(뮻xYYY!soE0}ؠ|| nGyj 퍂S|a9PL`ng8+,jg2V`7 7e7(`8dmc044n̈&~ba~/?;oF皕ɔ%ό A(aS%hs!0< D\c0Y%Jg }PhէPd !5(! y<1d= *b%90+l@Ƥ#2rUR׮RBd)~~4d9G[p{d%,kmr9X &瀃st g7p۝|kOsXv7?nos4 N9Iv{`yꚓ%*\=G m//?a}eO|]o}3. MUP`3?lsG%Dڱ=71QOW1 ~#-yh7lV9P.oB%B( W:.2ASzAGJLgCbJʊ&Šn<0ɗn˩x:WU `O&BU{ =('PSFnQA{zçOvs>}W9DQv=-_bhZ\~&mts m._e4shMNr2'nݥ`qy 3*>{AXx KesssD TE#CK AFk8Ӏ[pkp6y0; \X4[@h<zճ` )PZq a41 jCFhyM={IwO g~-y')\π|V0Mo +1V%c3/)5"Džhs? m-J/~˟3Tn֕]Uo-PAG8 [? MY"/6Tj  }Po-bڤpcX R4ޅ #|G,rw{<կsInxt ^LsƵ5MW.\dqLn7cwԁYZm~Ȳ1vdkh7>sFEIj,^o?MsMsrBa$ȇ<UUlu/\{Wm0xBwEsB݈Q*%o&@JI1SIk g즗P=-8LYƒf)^@clb貕+!N&kk:[Js~}/gg?&wG/_O~rȵ}Jq{p[k%'%smj9LNÁCtr4ۋgY;tSR4&<ț[r6%-kMNrUzaͺ 0&9v(kEҚ^ufZSbLIMgP1eA9*hjw F{Rs)z}+"{Rl/щLYK%i0[}!F: an]M$PáLeQtnx c$MU`cRȮՔRT\zv.&/#},cUU[y ZLӢg.0 !Jߢ2T i3nyZLLcԛ OQ9ɝo~͕U,5o$N#v&ϙ°(VRLq1{aR Ka,&NfעTA!tS(4A /m*Nh&5jy]1%~M6X_cekk+vv )c=?5~7~YEQadQR8n)iuoĜE/Vv1]Q4j怘9j=&MQL,C-H(S!S05P>2`b:iZݰ^wcG{ތRx iwQ/>,e1dӚnW1 sEA'v>FkȸNq+Ǐr9Nfy59[9tt6pK^ĥ_lp)C=,~("SZ4I\hV֦@F6A{^$$aFJ@6:-V:;J%lV:{Q%'*qzay YĞSk4ӆT"lM'-«sc)VT,kIu#<ȄIhT z|=L,+.± PUSqMiQ*lt5#+-DnRs82~IXlwrk׈!h*=p gk֥-;CZ(xo~]{C[a]N,chʔk,b[~4-> h) žTSC;(hfYPQO䞿8}<ǗӨȕu!*ΰҶ(B\y/ *G{;p \iU -m/r>r [} )Is{̑Mh@b{t l<§j*?_:etunrKlbr-lO J"_y[{u0x<ʲůR]ZgyzA&nGg{KJKcggU2#5ZpkcĝMX.a,pm9<c|Nw(,1]WQvoDq o_|EW68Fl"rEQV:Ң&mJKV&oq[}K62>ܢqCMb%8:R Q9Fڥ9T62p ROfXv}[݈\C|t!(^cŁ)F&ɤU+BуŲ4uƀ\qHSd$P5vk.Z\~4noA{r/l\s._IVZ]9fZK~ c,./]tJ.bpJ^oa\},vS5-*4A,,04S;oZbP(k{OJET;[;\tu>[^ccm?gZgVc#?2-Fɒ2,+8FɉV$42-ك0l)8Dc2Dž IDAT0-^[iM[ Zc69Dybwhrrk|뉧ćNEffgi.Ȗ+~E7^jT6#?k-|iU9$M,Q&ْ0$2@W)f=<»$}I9Q.=jRCkcD)2CF1pdF#v(;7h]ȲDS>Br Xj-b1#/Yn8B`冞9lNuvlnk&'^ߤM`;/nΎ[s-:[lQkԨ7XkYr6}P )?z T`L6 +6D)d#>?h qM"S mDV1.Xqo*W]ΉCL;e<*m]E&  >jb0f><%k6J/Ӯ1vIil$VcL>`ѪC؊MBq5@1ǓnQ&*| |nj))Wx'ZW'`YX421eHru{8r=˨+xbF+LdT{h?K?*UQjh,^W;Ƞቯ<Ļu|k_g1W)>`[ES\ċbBMќ^ұEKcbr/ė~8}< h'E*Po(Qk>^dw`#eC QT8*x?̯'Fl -f"W#`{UJ UiUz2,CY|~JUR+}d);4}~-H.-Cc})`/bM=1p)1!5,|zxv9s,[[~n$~2kkp>z*J)~_Y[[ :_#3, ˝MQ;YvY3@sp0,epfgz4YK2wӫS[틓ML\֢2_5*cLJHڂ%\n ˔[Q Ε^0jAvޯW Vpa7X{BdLe+ո!V.<(-BBpq=f3vʅ8p^R9'Y iKdyNgqH7(Y;66O&,y,f)Qx[%eY*##ٞq6WN!+ZLIa0T.,Tlaƚ$CJT)*5P O&9^8NZjIUmf4QGJggX \3ɰ2MeފN1B4sTb}~86!:w{#T nj&ąndYIᓿSk]"3-T<j r/XJU5543;/vrk``ܿ}? Puߙ,cwCܡWٚ@_Z#_ GOMw{iG19E#nښ̈́?JL%F`>hZ=fp?k:nol2Yervc dR{{v(c3թRF-7KC|{r֠* Cu_-5pXZ:*HoH8Nl[X0][vt tY|lLJ0 *ʆpL)_*X\]: ?!v{`N`,kk|c'kK;]{ѣG1p%n6~iww'x .vQJ?LNNIO77FՀ38s-kC{Aáp,t[)&N-`g&2-3aMIYd ̲ϰv˜tZV{V4睒a9s}]PT1C]߅2(F6eJg t-  h吵579IKu"yA>m)7FM(1~[x.Ak5/uj/QucQ}~tr] h#|@H\݄ (Uo*JކQe+qYUzB9KVDdlїq@ ̨6Jm6=Jc336z+})$iƝjd-lLL$Ɛ78Fp0=INVG?2}LǸ'5yP:  A!֤p 0~O1){EKB4Mוd PV&afF-)h{c,OY6CUML$ ;Lp۸)LfSiEXBJb SK]̂M+( @rlLZzِRQxm)Kȕ[Y8kǿV-YjgP°އhdVƅ݌隊@0Vj&D^ W XuRtv69r4o,{*2E3ɧXte&',\ 5]gs^`}ZN-ˡ(iT BURlmt:׹ySc]cG>z,QZgFm 52;|=Ly3=[[(x`0`ss;3~ӧO?j5~￟#> sZkWgZ[ࠁֲ驂9h/a<Ka$Lmqi(p{Lv0vزdTq 70솄f/,K0{bq i( ^ +ww?~VEY )B"TvOT{)i ʼnz3=7)E͊`bRäE]7*yuSRZS )Ź|ij%Vx/n [YKJбJْ&:?yQǏoN9a3>8OOO1??WO}n{w__]|ӟfjjcǎC_8x k"+++ûəhhnnJJXRp7O(YI>[bFQe_'L)ϔNY!=Sn݁sǻqe0k<طysZ8%f۝mNVC4 ._:%b@Up#d䛏=FK5V1woyo~Ő _nFO Pc(@X D^ 77bba|)&VDVQQ!OZ"P6"F CcRdRI5V:"P~#}]_ӊ30KԐ4P+.UrδåR"f0SML:uJpEGϫxq %p8J阭Wĉ^]Pr|y++:E%8^=4-;"F[]Jb6?mEZTTm#{VJrmW/ A>&H Oq+jMH*J3x: NNk@h0Ab8H8/L^`֕ +~~`ɲ,v ,K_r]D6$%@|20={$ i^1_&+n- ʲ@Qcnn~JA1$YMaCi˲,e7^\֊~kxOpӭTM +C[,| X6.cZ ?õhR` 7fGdߒ@OII*i!q"Pu66Lq1L˦)9ILVJrCuD c*cB' yiJ"5REư Mr'c [zڃPO, W01\Ɲ+*CY1`iz4 tjLvՈv+csA! 0)F'sQ[F:/`)%'bem (_&r#;"TŅ8Bo V6-$IzOl漼sF_^MIu V.]ǞMx'jPw1G)>Xxyu#FE*Zz6;8 ؐv >[}7/umX=ЫcVU3glՇ%XkmK( sִe>>P1P~9?\mK9sA3S\*6 h(/5b1 JtM jeY,Y+X;>bg ,'cXy}'u0x|< KZ^b8T:Z,_*333-oQ.^}{g>]w݅1f'> ](Jբ_ƫ3[N7,7:ܜYN NM$ `n2,x#o#gi<İަlԨeN9Le <b*0>@ZgJF0L? /VEpP/?fx])n\sO?4ʖ` vҌn`ksѨd0`Qltss fg8y8_zzAV>mYfcso}9_Bg:Sh L=h"!Br1Q%0jb{;&LƋJUaUL[t^B!54 QV;t>Q2 rdu{g5I"@IІL|*U=1wE`qnm~t[wdf(~/חFs8JLE~Gc)R " 3|+ Rce)!/ۆo^HY`U#Q)ҁC2Z,P@<&>hLPUKǩ2:JJ:\}Ո C[=~J)S^J]("B['yD!1 Ochw#*\9h, :._PYlibf-iutr) +|J[}鞖9 Νت^N;؊}M`"L ڬV4бNJ7Q;?s?As&fg U[ 5DJ5l`eGtFdɆV MI) ǫ/]\o97 7Jސ-a1ܕNCmiX`b@ ?Ï}/~w})k(nmR3ܨaÙ@/.>3|fA6ٞ9=t|n95"vayڔJ=5[ arR㌋[ǣWwJ&x|p-A "*֚CSdZQ˦P,-ϞFיʵU3hu8slnnb4>>s8< O^&M(7h7 C`Ûٍ@p^%u(V{LIuN@Qզ^4e1S5$- ֡mC-GʈNMTX@/UJB1 H*ȑm AvucR{)N%$k胉VJFc@E_L 4"$'u%@bV%Ĥ$V0*cC1ue1EZ Tr/zC͊ykgN\}-ic Jjl%ŝb?S[a Q!`I ƳfV{.ņ#Rrv&HeIEȂrDPD2!fl"HcyJqp^5&3M+O*W3 WnC-lCHժA*9V{0rڱўD5 RdWʾQR7_*tz}Z;n^{*q?*yBˋr0N]h7ӗhKfSD>-[}92y5 m)h 5-/`V!MӢBE8IFE\<+Pc>9s,Ύg /Ovu]>q{u!(Hka '!09qn||q^"@8$ٹOy2D腗T,aSa]V4a8`M|_Nr}' ɚ@(k$X4Bnfo| 0\8_ a:!+9)M r[R<},&52d]}δ.""IZނ5)|dMFn#Kq6q7cR/F"Ov# clFx&,= 3Į@8HBc!*6ZTک bÙKv{\Qַ\zDNP'q@i,!3{(JDi*x6"5 Gzdn6tXȅMJu%t y>t.huھ]~l>/W8! 33+24Ajc8@hWF8W@L||@|aJ an4@wbe+)Sp(;lcue[p㼀6ps شiIB(l߱&vځm۶)N-3U c[Ρ9UCQ@/V3>ERh}pLhX(2ZZiB3G\* g Ŗ^P9 ÄrC/?s_(wUe)$+=DlJW 6' |ƥ&*/DFAnCB<<2TcdMYx.‘$@"Af6ցزIPbʅ0LjA/)LlY԰;oH7&NJOBEW^Lǒ 0 Q ʉPS)MDaymL^8`5Ol |O_T!mk3$&-+&\n+,T82$HBABb*50D^hBy3fEi^ll4S~AxbBN@P>:w^pX<_>$F>jB&L,wibbPOWbTm0 sP>~Vy7OU!Z`ÌchQII=|ҫX;~G_? 2C/ W`Ӂ9Nd`x<),_a׮AK֗V /?#ؾs_^wo?QC:;?]97ϖ#[)an_i aa +q)vɢ ]>FDŽG GX`'i _uT ,w x:6"BLE Exx k- LKf+f?⬸At8w K!%jC ůA_}6xO =vDFD&t** !Y؍ggt3։^- >THMK)H`#3"H]J-%MQH2Kc[4EV8GM5!f 9\ea\uB0b9sh]0.\_rC,; -̺O8Eki"(upxiCh&) PO&d ܧ^EN2ʇA=*) 2xRqٺU]$ ' cWMb&;Zk;3۽}7~~kB*e.2ň4Tr1WG45 RD/@IMU,#T0cGhpק ?r#i/;ƃ1e PŞ"R), 6ƿڲc%֌U+,S#fUOΙ$$Ѡش12h᝾DrCb[@C׈(dK&V(Vz*zߌ13q~/igOuv0ظ é;(7n5 uX4l*C5tYKݬV .!9R p7˪_UvFϜI/94 |1(a1 LIydI P$񩦓*t:Xx <ff6@S66 ݷk>y^@)sHa8v5r8Y5VD(tP_ʗpn4<;1t[ǁ$+g[ 4"^-ZwQ^CHBφX+1 /牃O9gw9iP8HIpPqE-uNkH,qhLF+cB~hOdjGkGS/Sa×!23#6I-UgX:>SR`ADybdw@ZM2ʌ%AABuZ&|_-!FN~Nz})ykMO3^I YDRU㎑5ʴ;?(i(kS9/K/)(z9R{ q݅+S00[[9Ck{3mpzI{a/do^[t>!p^]k,Ll65K+:ʁVaj ]OQ^R-s8hۨcDa2lk.A5G.I9AFLi`|pBV\3ITɓ/I@= O~ͩ֕ݯOA025hiߗF8>& t [D_ ˙ $!:| `XP$KfT;Tb=Nו3"+KP灥0}W?6 _ӝfpq؋*vc~uг;d@Sl&^G0ec8νln0c)6$%xbf޺*Й''?2S a !9jR@U1c7(Ȋ5@-KqߤB='3߽fX6%qj`?8zg R)/6!滿I_,Z2$F`%Bb.K_ E'ʡ& !&<zr [jD D, RY|zin"/ 1>LuvW3O$崓NA[+:1xoT7!4E;pwewG?g>*@s-$ga4^$ I⤥Yq}P 6a#|߹\4R Myaϭ1R(AApuJ^SAI')Y0ZFY/MT#A*p"ךxcytWt5X~: Yd`Z!{vRTO2؍dRVwR\]Q຃ m.W.Y|᥏ӓbV) ~.ޜ~I\7zX-`KVgƮؑi\ nV8=R -5Ie ze٦Lc}$apfY&\w+d]>bnGoU0x[8 .bvnzMpb0 w>R΢v@b,O>27U٥f333xDZeu]X]]E^R +++(YMHJ<4T2z UjUjYnIhe _i&ݪUUwR$*"eD&ؿ$}c+h48z-̟>[n'xށN;7׀H^! hm`cՃ*6$7c$!_CA5UO<-OtƈBk)2r!%3~)9RQQ5Kȏ3^"ic;y(=;n!-T \qn{"@T08JG 5/J)<6"o7".V^BK8Utx?Y,38"@ 4\n4K46~⒛qr&F<łܤBh,!]L0# gKLo%e{76tH)N  N%ZEH֕,Վ6η)0~e$mJx'O6(R=D;\2ر,-&D[(x)C])4BbBO@_!&h,BxEԲZ{AΡQ{"Sv7yK) )@fUIk?/`J!LShzKlpY[-$ )&֋jZJBUeb$Z7 _/ !C薄uT? d]Le{RլXRwaCbnQ=Cdw !qpwn~IʼnL4zz75z),..  ؾk'i/j2̤Z.K1hZظq#:[J7x:.y_>zYu{\z U֍[U %c֤Pf4^Y("2X](?,TETUQl]x\`Bg&z}CILS?xE{jSn:?z60e,`(Aq]h; f:NIi|2kU4mJB CyI@aV3%NE Q€T8ч Qr0,5QJϐ`y4ၱ[xC^ut%Ug( VN^UeAHSü/\y$ F[lσeD*eZz!X=!;a;B>cu5y4K-=]. \Ǣ?kpC2X d:G,`X^&&AՁWC)Uȗ>eNTa;̺ǃW-\8qOӕa tŞP[$IXA[JP28'.! m 1QJ=/x8T`MyuA ՗$sBRz:ʝo{ J"RT`.2`Hfk;um"}&zU[cueEteYY#]gIF*eSS#N^f*N_{KYNǧS$-Ǜ)ruuC9ٶR 7 <݈?_A-Z~@]a2z620ɄH;O>";+džhCN4еG*`L@ IDATͫajЅ9qj'MZǖ_]mee?3h6|hk}m`0@lbӦMhZ0ԩSX\\H$RӘ`Æ 8vq9sfFgϞEŻヒӧOxGuV| _ދ<1#T-<)5LDx Mc &GKh4O3O|_ 00yɪlUJB,ǗY^zo6f:m/q뮭b:رcvrmƣ1iϾz{b4VCQ@Qo_ ~G; LHUN$$'C״-62tle,ADNU ._H _37/3[6a<sa˞'0{^+5]ɏa {-d)e-?O,8ad Ëzlߡ/K'] ژH^IrRrf[*S">B V10ؐ[q-IgG1M^PZ^HgݱK#o/3X 'S2 B( W)-S~K]cG,ma .]_=SB$26Hya| jK@jvn7^ =ʟxh}]jKudIs6_-=%2$4?a:FXM 'Hu ݏ/#@!L%x?< uHǁ  )4Nh%[} 2pcķVx%NAc$P^XH#:?xڹ9$sa*%d Χ5JP|:8*x2 g,s]0ЦDquFNs'#G055凰,055,qF~{^ .ˈ, 3c9L wfuaB 8PKr2j&iLHeɮ֞Y?d*E[l"$HpK1IJ<>۴06{[u YUGmo&5+#}Fl`PRoq>A2>/bB0 N^dcI`H)$AE`h+G,lҍA4OA,u+H<'Fhl1vݰ^|x=vvv?4ޅK+xG߅߂eZ7y;vELoڀs'Og>kn܇c/w_~ ~K5(GK\XD[tB%kQ"fD B} l\ǫg ` -K)!iDȁFCx`*׵(+,U|G}Ut@Z@p3z rL2cJ#uO.0|,U<Sݑd(^8"HaQ"%kR|dpLq.d;ϔ%ȊKD*(50.4IN)" K]ĵ jン@NaA 35e\NN( zRG3sBҌ?2$Eb/(ȗq@!d {B-nM(/}81yؑ"qݱ] xQNY-GnG)aA^ѣϕJ-38Wq؄E&iSeo)$ {SVJC:;x-9:A;5XaʁM#$DCxUfvxG=bDiGmq=wb`01z "o6ߏ]vazzO=~i̠ng籺z =ٳg=ԧ>c ;vo/&Z-8tկ'? x (Iv*`O,^5u3%(j3EOf.3! UJ^#2v^p%9sǏǩSsŋX]] 0efff0==NFM7wOL5 6n؂Fصs.^p8GQX[[?y|غu^y5t:#~ *K3 z5<e>)|qz$Yl,08(Kq}0KQHP* _sк 6#"R T$ W I~@/%F$5(e̛tS28LvPJFe7Dպ,uZqra l|KU0 }F5.7omy8N6n>a/v݃^Ozn#~Z'޸3ߏQk6pǃaBvO%:C`{Ua:p1N܁R8w4^|Aم> ޅc/= ڎCfw=l۳߀Qߗִ2>+[TbzGZHv=LB 0H^S]:YA׈%$$[LQ1ڠ,!?DZ/Uތ+%e!F(QڗDՄ@Y0iAhȃ .*)R^j-$\T4xS[5ރEMDǙ?c/(Qjˆϳ:XEV [p`cfϪ*6u!:ƣ"&uW}wdyX,Lz\^8OgeJ1M@ՆmM()G'wep=9B~-`f%Z[ZnwފzsD{4>cm7c8 N-n:W~ ܁qi<9^1&y^xo ՐF>HhK\wMX<3$I_]0r|%,wvxv/Kϝh[5a/νw*Ms'Na`mxG݅q̼(0(- LtNO`40ɂy5(!%VZkw>5O'5=Om|Le?HayWR(Lj\>E0:"|ŀ\芟M{lb'Cy{Rb~?#{{mXcfIkEq`s]ra,b3Q9ƝK 7 2T/'gB̈́2#Dq$E`KFi|uwm|[6b4M$/&E3A<^隊]LHRԓP%7?T)>ˬo2@[QP w_D>QPJ>Gi;!B-ɐY !Td86Z\dGh\`DZ&yo5D,j}%; `]0A1TjYRZ@9)U+ޮޮpxh1qɿ8|0o6N>ٵM6|I:tN›oE p>cnn/fggϟwߍǏ#szzX^^ƙ3gpY<#XXX'> z=?D`"UdLz$3'fJIbgQ&xJ`Vajj u7hs4ŋ8{,N<Ǐɓ8wҥKv HV N{ tjk Ǩ=Ĺ%[hOխyF4MPKnqQpcHT wu:k&un#f6T.\%G2r<#_X?bizME(aS<ˏiRY Y}A EL&"HOl^쟯JQ-\o)aG"B(8gFBȃ ~VuQEA!J ZA_et;_EbR5'e[Xx h6ў8ر:p-?xV_Y^,Eszi"ϡK4fFa hP94?)oocj v j53]hMa ;p`Ax1k;6ʢq>~ay̲> e#u!>)1AtOd`J%<_08g=܃]9] g´`83Cy6bmxQ!5l^ -"w1gu (|Q}:B…`t'^" J^6 SBxK@T2x @o쪱"GR xf cT^J@FX2Nga1L)$e*,!!M,0(OQ MIqlh0 Dw;rA5wHHa&)q\uZU q^dQ%UTΖƧS!W2BL#XRR>I$wW}n.=WovKjłTFj~ǭHh48s ,>1l۞={onkw]<'?=cvw^R .`nno&=o~ؽ{7sϡ^/}Kظq#VWW}j' W u,d0>?`\UY;cqjp8) =||Q>BrU٭({,@=Fz1Ӭ(TA{amXY]`88ϭ^xgOc 7ݙƏ ڭ6PxGchmq;К0u;ڝ6.]z-[@)Bs$hD[}^8R MzW (ѳH7(0{fk.*LP&cm ]Z xf}JۮMB?3[BKُi$,DᷚTH"^mLy Te#hQSwñH 4d(;xGa<s|k*WaNaf lن7}S6/ >H @cj k.\Po6ADX]'Na7|o?ޅ{ }~N0CS;q .Nu ޼;]w^y'<~;?_{Ewen>ذy SM$iE)* TCn M'އO5AnBW.C >>Y9UV%q+3\gyi,Ԕ{1ץ̧uTbm7݀btٱZLDyM1|P.MK),D>Pؓn{HHOJ?P=GL ʂ@n~Y/dKQ>o﷓**LTؔK!zE`Qǹ3xsh:F/'Lcd"E ѓ,&zD,Ux#I di.͓\$Vϟ=PT8rBo^6-\8u|x  IDATȏʅ5}H'R "4p<ߌ I|+GopW;G*W%R%@YՄDQ M2`0n4ʦ/~ snZk<Ѕ]]D ^]v4 +سg:8dffN~a/ݼJ_u(pi&yAy]v8o>`۶mȲ vyceeeK%Y<ƒOjH:?fY9xp_R'uizgݔle7K_)J2T& 3x[ܙs+n}[Yp~Ο(J+K9y|YwQɳAnkAQ Y!1j஝8uq2F:rU$H&9hρAA{+f`yGlvz.o{ ZڲnƂm2%!T~(~]Z D/Rw>)Htz32:MW.*RӐUպ-Kmϴ15vC@{ cOnv.]1+.@k-x'i˫eif)}=Lu0`ὓ81lބ`'hmƑ?c<kwcT?^_q^=,4 'ADxv`mev }d:~EDZ0e3j:Z'OcIԧ\#y~?oĥ*7mQY)63VJ׼-BOg*BI紐 bi$-ǁ*E,ĖDJY86:04#<[uOY-Ip*e?5TBQW$?1j}4U@$I4AK/K']F#ldAT% JvD6,(f xdDH4Z5 ɪ60\ş>K˸p,+L/**Άz=3Aٗee1B$ "?492? |#I\h`~\Mz"}?Kg/0 + _}/>4.-j!IzǬ6W )Bu8( )S/gv+Kf tfַwLʒXTFkPr5}Sd{Aݬn6 q27Ta}-uЁiOaiiqI|s,˰W_}+%8Çcaa+++9zl޼^D $Cxǐ"7򘩅_1|^ P-û&L;K0PؒY-?' DG"Y/oU%IRHk5Z끠Xga&쓎PC@H뛯ƥ+WNćmބ;g"i+ZƐrASwTFG3ՠU4-PYLjl\ /1"WU_aDөb#ck#E^IZ 4ӹ^D / S*b:H#0/I"x$W λw[1 ]$@Ez7^jwN wg,..}aii {A*"ZYv>euu՟4Y#dOpU's,6:~4P=f9Іmd?ǩ)!oCYb*; kJ8u8f7nU33Q9v\s v/.-`4a8A9@ | \w?oóGC2EV[Yu }#$W8< C?@1О!dށAPqXekP(=8, M.E XAy_vTq@t6w7VN]wTc]]CRYJ=ҫev12\&L,:Cb$3'4)y`OTy_${X̏tŹCoMXx0+v!?Yj[D!LZ;ǿ$ozɯ2ʕ$Tq!ɞKTs[o5rqaL37J:ށcH$F1ѕL >&/tQE@-HL'aj"̓\ǮwLx?LKx{(W(UB|c+w! dM{,)^΋'tɥw+'2-KTdkEEj<6UD#v$6\dۂFj_C(~& ^ ;}RUaFkJAeB#=,#R>ZBh'W3W 3Wzʽ)T&yA&&VB FkvȰ95}2CChGB0z^B3)Vp&-yL3:?y jWK8IPϬG] *ۜ J88fR{ ޮxbCwmItu7߆;n=p].$ѣGaAM`*>#2,//{3cl۶I(+$C&%2=^&|q 1XYY^o8,C{?|e6!7 {wuC,Ms3HsW%,Td!LNBP؇B2fٕR?`Ɂ&-PU(fq qԾR>1@r؊7< [YAlTt9׎2Nz^@`Y H^x %Qzf{ yȫػ3Sf !`O I(6WdQ-q.t"b/Rk$$z_(j87Y^p݊(!׫^UH~#=Qo[~d;%%ߏpf)"z!T.D.+`2z#xC-vR4)?:\PiNeI6NV}sOԡc"Ӳ%|%aadd>TI sI-q1&8a>jW*o*rGE0 ( )0j@aT. RȨ/)J>ud9tKF1)\d£-}eq o&Q$q,l!Md F u:7>ZjZV#Uf_f`g7ZHUSl9[Ȯ$Ӊr; 4dUiw>WQR^o;0&4LH!$F@CaP$E\2dݿ ޮx[YYũSm/c6^aiiKWVVp7㮻BшVݮ,l^/v1ơ.r1h&6I?>0Zc0x`&XYyP%zR)Ad&I9Cij9a>Y`-6?/ } :ӈd`DZ%T߇Rb,U2z]94wKs7ni$8 r 18"':3ʄB'pͦ~R$ v]Wb}ڠ{F@i^RN% iP._E|' ebXriO bϋʝkLPP=`hWzjЩ%Y50#n0,찞(|_B>9](Q]\XWo`-32]XJZj3DPj]*W;9\_wVu"9p*&ޯZ:%"; EB8GXJ+ ^(4FLq؄[j =.~=( PͶ +2.7_0Zr @s ^]ѣXZZֹu)h<q3ֳ˥Ve d ?w!t>eUDL*VZyԍej9G_Ǯ3>d[9} VWWQeK~Gc5;52eOpV 5lپzF#L:~ o} o|?:V1 g`t݃^C檒ksIe!]יط97^׹h4"$E=fҌdרƣri4Qy?䢦j$U2Gb)FHhtݯ_񜽗^VI ~}ù眽% ɔS.o0^B)&^ Ȫu!PGX2KqՃ Ȃ#ͱD0`U1sJ;%uzVS+4pLtqפ_E0Yu)j<&m$3 J-!V61Γ )]i''q`j1 .Kn>\H_L=%ɡMK{j0ׁ:[ӕ~:OҚԓwOfHcTZ\KXwWУ!lb|J!v~c J^ϸ_QaC1Xn2 udDF92OK@R]7{ C|p0\MB&c8rU<'A4 jJ*8fpsȂB=%b*X)bs}Yޏf9l@.TL 3 'xz(00JC眒թ!8$L%І5٠J=;~# O9z'i`]Zsxt왋x9L#Bb1L~|?FmP'.NC9#1WƄ >`bD;#]"sE:2'|˔9)i<\Hc86LEVkB_g}4 3Q7g8qx"ql9RbHT=E<*PX˘>HA)`?6՜Zp&XdoOϣcLCL@E rC0p5tɡÓC5btҲy H4k@ **P.c ʒPDj6gy-Lɨ`Kp'L890hn֬ǴT72%SϤHlS4ȤGPh/"zoBeєt. 7dbRyZLFTAU|2ua\Z̳Vl4 g g% aMisi|9ufQ iKJgF1YBx草EE¿`cǙ3p޽N$a] <}<+Rw $S0[777QU꺎N&,ED9M3ӟa:$B}$ *@KdٵQ_jiNb6oZ}Z檽Z XO8v(^?.FٳS>QhJ<}yx2{ 'OٓqQll\A; CeU]2biSǎhc5Q%\5AA#ù&Ğ!z_\ 2flL(KF`KK"^>€x8$BJa,aiaoo"JH$^R T76bZJIbLQLlR7lgeYJ׋"ajH gzBRхwNPj[GKd= &X+ߋI(sw%sYrv[[5Y/D#y҂$)L6g"B)>FAf.2΀xcS%`\0Ǵ:DEFep&cr ՝"U0./=f|K.2px(-/lJ;OŽL(f9Ze%TP^dp1dA 1ok5^{;fԕǢڥlս "[ gkli0.G j@[$3 o}8xO}{Y5k99zF\|Vp1( 4l=Iο-yJ%\$VN!TV(c?[x!BN_ô} l嫀dV:vD 2f4hX\!6\)3+ qnB8SЕ=*K$:1. ic,ZBur:H1A ןzxCv IDATL=Woxŗ0WdL;wsu2ZVAUUk"ZhfNR0'P>]ߠ}z:TF+h[~¤*O,zS.WXHi'GS 'LЪQ' l6cͿ} g.˾]-Xf/Š2VpuX]`mQM& ן* cGמ[pن)w;e70c2to.8r _y|LJރofd^Y_"I_.DH^ڰᲺmb/"W rz± -& :&zs>vCK3Dy)㹀  aɀl2(RS+4k)"ОuJ")>?ak$k3qEY|+P~.l1 " ZedqK~xǪ{ BQR03䗘B}9ȞכBRQ#XCz1˴d 󊔖 j"Tٷg p%igŁb2#aNi1X&.2S8gqZ^g ɟL9uO hOxPXXGUcfFn0@p`/T3 烋{UרSё38/PAV|LyZTl&amo OtQwiOuR=4yߚx*eR'oa 95XӕGA MMWͳ1͌/0C>r?|iQ_YGl MyV_; pn\qƱ807 O N Z( - I|ZE|Ք/5+%FR;K2FE]2Lc&| Gh[Fqd07x`]d~A%[Pؿx=}it2M3`}F{`J6E7?+TۼRy1^yY$ra7 NG WVVP~?/26}~`g/_djuPւ1Awac2̙ ~ 0nz,-qY'uxAO|+xǰk^z (x; y2QcE bjq_p“_*>by$ 1&QPO @Q_Oq.%HwF/I$KpM|R%|b\ӼK3)_Eh aIqzUr% 9pӾOdER6H|.]LLҬQ{(˥x,%eљ):)`E 3ϳfd9vܚmd 1 t bzƩXra'!.ޟ kʇs.ƻbH8lRQi1NL#+! zVHŰS< | \m#kDgw~vy^&VdA"CHF {a:NKMȆW#*C/G0X;IJu q3OZ|.$w-KU)vMPQ׎I 󦊎1ƿ֐ څ١QmE^%?֩j1 p}Mw߉z2Ag@y*ɹ2RDhsPiU=4laє4QN< ۘxWk[CVL5QMqL~Yr20|'v_w_?gGg7˰$2IP gp_w -1v^Rk`'@ z=Hmpn ҫ;BUOl "8v~~?) >?^{09+1Ftb<auu5a0Z$Ҳ,yiH=E\n6(v;,@dlYe􀯀 1"CeOy}^SNW@4l6dsp \~`83j`yy 7t:nQ:MTAFQǿ -p+5xÏᗿEc,t֗Q_5^g0EdܳkTWU3gN3p)^NݿM?F[L ݅~p9' {iiBYv ynZ(@|2D+&=Xqe3r&h9TP&GYu%X3AbLMӲ@N8@G@V)Yј$ףDKN)F"pVR7es!)DSFm] ;1 t][ŭŔΦ(/ 5Mr¸MNZ*T@!6EJFZv?ҰII0:MeExה&/3N)^GW<:,[$&)DodD_CQùkC&0cշ ĺ9 aD.iLүI_a(BJ-ǰ"^w> 7%{fcޓc̡XʇITlddKjgbHƨ V3V61[ӧp):|'O_īI /BYq{EVrt=~~ wàg(@Vw{~w;w>x UWR6& 2طZ[&JT5ŗ_FwayhZh4XXh{sB"l5Ʊ×q .]( E)CT &B_"&L $1A+Cp:f]H+`N>L42q15J嬄]|G-J ofĘ9s~&H)\_'g>߂&*Akq`Rs.QtAZB\u)k,$|XzM4 u]h0S"c< zf1 آio~Ӭ4  yPJ @Q7kF979j倮IǮDNS~hn}9LxZsQdOCx]}`5ٍC X~C6IXw[861$,XöaTfGǚr3SyQDlt`ccmm |ƣ1"ļGE\㺃ce.]%"N'`j*ݟe8_p o6h4EfZЉ?Od):\bQ`VţX|ϝëѣqY c&cmLs-x@ml(X>S Ye:y+nh76q󭷢ລV&ů|_WBWNcss N<pq+WU_gP4JS[oʛ3?  #9nvzxKzOs&™=K(A"ʤ/2Fh Oce7Ͽ.fLp( 5ɝ8B t}ilF5N3&p<|*ĩ l\t(FaH 9k#N$J5d]5Zv&]hfvSU.a1q,ǍLh~P%z*=ϩxvɔy3R["Lg/ U* [4/teTL:ٓAYVތ莯 @1h%J $O[TYQD'p)H'č0u09ub,T4'<$7X`Q  e xc,&Jr%uXg-@ *n0FA T^9t.oĒOTp.W?'Ra.Oc<a4ױm6d' Ձ"Oq"y9Mk#t-[TМך{H5 5ij4 ,YInvKWbDlt}}i-.`*>NoWΞGwyi8Ik_ICγN8+E˄jB̈́rA-\^.L8(xQGFb p\~=^W3~);z؏p' WVpݷdO嚺o;p.L K3s.f)QNwW3T-#fRBhcN [qI:q'Nŷ}.7k\pxy[^f oE<+ 73TX_.4ŷt`0[Ku[Xlq+{' k-=}fc 0pp sx;n ̌'՗_?A]q,,tP#8ZL&,܁[^O?ŕULX͝!#dp !\R|$KA6NV?R{(Xyv"q7b] Eb(c8ѫRwHG|2Q40cHCSTj@IL82Y6 ؜&XJdYHRrL%'&xYO٨)6>4]CScz1IH;;X1/Ȋi 홝و%6ɧ'Lx0K1U1MWk7 ͦC\dRl:yo X@ک= !tEE~B}Ȅ51)H?X'Fu5$q J2Yb.ኤT>CJ4 *]UirL(ԪQ3e0ˌa Z_Lu~bhU}ϡQa]4%墬jBhboa [Ic=y YAL=KI\^{K tsTn7[ܨ4IըkhfWaum>2ƃ!}tbϖM{a4`n^!: C Ƶ "x$nUiKqtX{HC7bu~ NiWG7ݻvbey qڽX[RK]_ȴ$T 'O].`t<O]PeDM m[oqugÑ#qY?G?+#~2N]X÷^Kk} hw+;k,lql=C)Aj//v yt:+;n+/_<[PcvWpwF7ǰpX9ؘ47tÎ]qwa}cUU8XYލ{y8*@eNY`o ^zS?8zzI<l5|X |q,R62t9|լ 0p)`d". )3> 509ʤv& 0 >#S<)~(T$l) s_NPzYk!̣3& ->SdIg=dt'%9Ռ)0V9C Iq.H0pzom fߔL/ '@ &%cP J\aR+瀯,0S׊ ݂F*ɴf*ZD cIty85 lvy*0 9p!]Ed"U5N\!9YDP<ʼ~]2Oڅk2 X- , + Z%?ec Mb(I_`)(hG~]7{|]a?VзP)Jv0\{6l5&jg1q]wlKBK صk 樚LP:8u$f GYc bi-/ 5iΨ-Y S \ħif` AE&JMDW-ɤjCé H xN\\ޟ|U3SY"|_)B(JލH{Z0MP((` *4ij)T@Ϻ_1$'.XT&VFF%`5"pُ nA3;4˲KgazcoS7^@SXW :F:$eP5[)VΒAY :;=@GIGp ^`MEB )֏cN iI5i,8i+%!t &WC_١p(hB80R\(+YUtXGqtZ:ҐAj/3ED@ v6mMFAY?D΅c {S#ڇe5 ;VMCMþ7օddC87[ &4Ġ֙$Օ:'(FUl< i!OI_ؤs^}zkV9EEe=f汆4 - < YGse(ɠ$VΑ]yjJ)AezRC/6NWĪ3 Q11@6Ep^5F}m ?)e:*rhLCH՝HdZJ(3r ^}dI$QṐH %Hm/wďE@IDuL0zjG1F^H=5n9EOsqDwP@&a1O8 fQ=W\sIO&HqyRPps1$UPMK8s&c٠}2EdE+ w_RYgQʹ_6JiAH NciFlCI?2i`%!6OqSxᔨ\ddpH&xB ce,U& :X}(huڨ  岺=Abd s0#fX< !ֹ<@ Qo86>1p(qu"7RxP肰thMcmmO|I,,t+jp:~=wށ5tX ާk pP3TИB$ʿӠ1Lq _OgX? ܶtz;{ ڳ~# Txh6esL@6`'R :(wRQ jlM~,0s?](O~8{<#?@cđ?,`BYoؽ m+;[1cB<L/amm8Oቯ=}oFQ;o{[b 2dj7qE|cg~c| __㻾^ "0quMD7Ssz# , SyHY$?2.JjTA9Dƅ)^afX|TZMJáL%2!l{YBZ^WG"Dd\THN!ԵEo(OTRFٯ/iyrS81%d(+kdsA2KLbjRI2uӁt{ZZ<L/+6N2UUC"& Tr> !U#bPM-@(.YHҘ5 y{IKɘ ȕ.ڽ6P"I>)1K8 <ڈ@"ސFN,\(#}o,5$0IE3a1)[Iv-ٱ>aL,*0b"p1!Tj,kAthIZ7 `PZ0uy eM3\6p:*dRB{R!#4a iP %0b䌖fՄչbL٥č'47e6J6d9x_^V3-3T5, !SqhAK1ti(00t1C& kx,Tp %9ߛ25Ƅe-9:H 17%cTQ]Wqq ,//+_4 Lwޑ%E,3Na"rF mn64ML&/IH Vn۟?_+MGy*Q%O 7C@,jEpv7^#w݉hBGM9 8 \yVAnV%ǹȜ rfHJ2:br_L>D0 4H\_C|d/(y+)GEGU!6%ϓ'E 0RE_,3 *vf Qq!j SiJ#D0&8MN&߻,b౱A``Q{(J@4b(`L 坌qi{A=d:itt\F*85Aٚn3dxn Yrh*ER~uט7J \m[)2`uk֕IZAeRոr2z+h;FH;::YeM4CAU4e!9|.'dT߭đMK3Tʻ)ҋp]@8X6Je;+-"Np"JWlTڅ . F5aAo fiV)KU`oRV :jȘebLa2\e g,keg e`8U0VĴB-J596XWD>6O<41mۆf?>!m}co & ̟2Ơn粬Zk冡^ª0LPU+v'x s1'cwfIN n?/7k@ke%.Pgd<(<+sTǰg:ECH7qHYM&v\F.^y},hKKKx|OD([(7lۍkðCGQ;ܳض+3~c0Xl[ށB>x? u= @p0؄A;A|3Ko,Ǎcha2gCC@bz-e}.FIUz/Z 9&kx%J-ɌLH hrW?2ԄsCfT "h(O@C3"4DoM͈=rqDm@Q`V=NgV4-Y^> h3ąg4m7A {i:LgIs/Zs:1Nd.%Շ ϩI @6I?R$P#C,|VYч'ɒN-+rx$|ZD` p1{(0⍲6UIfczΰ = f}# fGV^Ę#%&@DvS}$|b6o%K^yV0CzAW ?[Qp0Xi1 cM` p|4Ț32xX1ӯ Sf_!!OQ[9s'Kw!E-OJi|K'&er)M3*vޫ? 6}gJ0{(\u3dW>|O xv/^!:xiK" p\rd6dhZJ`&|,aݕNV"0޷rf,PRqu >1g.7y\UX޾{3iUsn\t UUa}}ϟ 4EYC,Q6Xth6a\ʃGDXo[hw:U_sعs?~מNYo\Ӄ6v^P/ `086>\TcX=6e  ]ʀl_zZػ ,å#A?-_FO>c/Qvl`>Ƕxo`2X{css`k`׮e<}pLOjlnc<NjXL}r-&Ο>{T[|?+;v{K=?}.\mԭE'#N8t0%(X3 1i!Xq3",eAg*yEO,T2K4'izur}T ̑Bؐ($/dRR|BM5' 2!@N>m)?8Hu- :mX)c@fn]gP:XR %koD:j"%%u561D-9I"#'?%f=]Lr<ث̩}/֪viPYđ|zd>y*[NyBuՅ?lgJ@0ʳw@LSA ΪEm! <4%W~}=\ tUFC,܁V% ]cpxmƱq w4Xe . 0VOk\2^:b5'8JyiZ[Jʱ #­u_|nNv;\Y{߉h4=ExEkh6h[mt5 󋈵6lZI?L{((Ca0դBDF]ױ*zc ~-pM'}5mWr#D5<tA2Pcxyi .6z.:` | mI5hq;Kt/o=WB{Twm]Ɨ%QڈDvS0L9z0z8 v& Ei&U֨ Q W{vΑV/vر$[A/Qmظt>/S|_>)<DJ}>)S0F Pqn༔)d`u| A[3 6 ]㴘) s@3F7>rBN&\RB.jW{V¶dN fLT((&0npC EmfSwRF?a ~6kڀ.孤tV .YCE5-9~ ec<&(-n89Ād8¹sS+{vb<6HCZ(Z˱ˑa35${]&Z<QmׄIT3+֖bI r9dxiRTZ9SVBy4ffNuAmB"F^)Ot 73D=cevҕ亙*'EIjr(MWR_a TDB8|XV!G/vr Bd^8 qU5qfbʡpWpvdp*↶tZd-I-k0nuq)|onԦxpl߳FYQprtb9r0yWTL왐d)-hEԱ&J {j3|f}/еE%ƶz:gYtDMx0n/~ 60~84pOs\IKqp]zAX$F:`3胰$Zxb>a{pYڷQWu!4ձC~!4͌.,ɓ8~86ߟMc9Xg1O|Կ1)Nn~| 1z|/pS6)*6! b'ҨV5?hiUNln`Wo>:-^`~֤0Eޏ?GZ|kOKo9y I z X\Zĭ߆p01@@UPA-vx\( u h!M%%>/ǥ3g c_[G5]x8`cL@oi E@llb<mR€)mU8!npձ=2>|%$]N r9!G;HIB Tu·^E65메G]ddH `:}PT:td` Ya)tĊ;N-cM|cbL?Es\7UjbPEgݾK IDAT,):S#,S":$pP@y8(];TH29OV)$,6|(fL)UuX(5}pڿ}ۺۧtVh:r^x `sYVzVɩ)N<4yy+~4ՌP:Y*s6LGU,ǨaAVQbdk8C[1&6~|\Z ]|F~elZXy(j[X#MV8g*}f 0t^?=W J&ˆ! 8λt 񔼝υ`JC3PK_ XYYK"`C\wxQW(]֢ѣ8v(nF8p11jDLڄj|h0k 7|mTW%ۗq],~k~ ic` A]TQ8svO''q0=ӟgk(͸olnbhwk^ݵ.C`0KL&=ea@➻;hlaJo춰sNF:r m\ր|B(yFۊ!^պE!HF9EÈ,T|pyP) 6('/JitC ԧd:;d($uj&[E/FybY7aY'N24JHrV(J$"HEV??qn81 ظ{(ۃ3um2ƣ/w3P%f\Z=_W^X=knNE]U 0;pߋ+.j=v;|ETq B~4T ,a5r M.M O1f3P81K Qz>S$֡TaڴpYڃb%QZ?s>27n )1JNy֜s9llUEe}k/<3rF#E?u^TZUNUhk+|swpU>| _+k1E*m\TeV`Hm/h[j"Dv*Ĉ R?I00_CIXj?Lg/1z,.V$cg7Ibaۦ>cPQ1Ix Ir#&)}1KIZl8^J ht@Y>|e2 4=|_r_ϰ!< ^e.}kx͏|/C 8 y/eZB;fNg>o9ܳoUWr+/=ocʷ_qu?|0#ә"kD~?-V!&lLMRiu-lRSnH:MN>(Ry@ӼEI ,WX2xsId;T{DFTiyG9b zeB8k8> e$8bЎF?7*OOV5$ IE* axFiHko<0( yuս6׼<S:Ϫƃmt\NGUg)rsFUG[>&v|:PN{Ly%m%$F>Ḯ)AjDȔV2$[e ɹY>,7zN:Lܗ(\YS%f#ZO( Le͙PLѭVŅy=0~yF SSS G#€< (ˊ;v0 €9*`q8J;'WgN:Xfnl^3O?oV9,4mTTUU4sK8&l ?rQř{hLJtfțbtSY>'{5"UI7x?9{2+}ܿ+TpL1(DaHe+ ӵ2M$R&(T\Oc,{cjJF{!:$M `Pc@a݅XB5G)!Žw7 JKa.~Օ\ɗ?~=VgrT&_cw<8Ze?Z^VG9ﴗp׾2|z|E\pŜr9uoʫ板a 3m*uB ,SuxDijƪ!10ޱZ@H O߫k"γ ZK_q-D!:x傧RW6Eڭg[53Ƃ8hfOفLz+KiCc_.#"2b20R099sig9x F'-~2IJcqCKA3wH 'Uˉ ^]YJ! 2E",Fq7Ö$/nџjlR& y)vÀq 0j$Tу-*KH$$QJcؚQ&F%2jK~J|X>iwos3Ϣ /osmw%A=.WOcTSU=|}wrMG<IVc4A>N=\F_f^?xcn{`<1=4R[ą`pVX$][KR,U=Rk<亭 Kjw|NQVbMPR lXgJڌҏn`kMj|JJm =nnJ򝵞.>4\9|$!4l׫~R"FAe"zI5ɿ&^1V+ $Sv^0J91 Ihbznއjnvօó\xlqENqSPJ0BB \x||#e֊ \$ԿJVZI]Ma%\__SיiS%=UoSlHNUc.H g\nȣou?#d:9'Zqo`jmvњ^7P~69s233r]Xbnz5< @пSCAS%5B[U9'>Ex@\"ް|@-nv 4RJJ5y$BogdkҎA2I r"Wx4z:ět*oyOp4.o<$%E4[-^=D;O~oyͽ_o5?ρ]yկaۉ;))ٵD>kv/?cN9,<vFm,_^j~yAşc2:n;jo=9FRQ?+IeD%)3Ln(8Te$݄ok{5G@\}^sśv(v džM]Cϩ[ȕ,.@$OE0z]Z^rɉш9.輰h6:t5-,Z?3=C۹f8hLOOoy[MX\Ƒ#b i6,--q>͑#GW%^&pT ntR{#49|>8qƂ<:* ޙr@k\Y+\+w|<}` Ukrī=~;B55΅y 0裪 %&Z?0 u9p(ckߦonc~7{{i{v|BnN٧1=]r zt&YyK_`8bmu^C?`зu0* ,CLaɧ}> BŨ,Q(Fxu\z9p*CJʋſkΠB1]REzFA&Jĥ pV֣ccu*^H͊i!I$AQ10|d(vI'VEPP3m V4tȄ4ay$Jv|,0ӚK}=ows>~뺟O})~W~xGYxO7_1ݞh5V*{?ĿCg>VO=c'>00_gx/2s9OSJo&׾x^a:̬&*2&ʈ917r*ޝlKPzÁ\h!0c5J%}~xqÐOM M=$3P0$.}gHiwH[K&H&D/wv0QecT{>45LlyPF6)C0 ɜS cPqlQ+1ce@$-2Mek5Jm t7ʡBk2Q MEAF==D$٤v^YE6h>3Fdc a(ZC7P\:#h  r@w.SJ=ݮkK/hTrW*vu菆უ?J^za$s.S L+w#UYreqgp}1kkYlr)ˊѨlpƙ@gU2 /r2%=&&OM-N=$^h4 n(Hv6`7 *q,FFEG(a1q਼DoVA{ܔQ:.}h-V֟j 5݂@cbp >Cl}e w ;/}דH^e[DTTbYgMj,S:y ;aUY2=73j ڙ08+ Fޚ!3 L9Tm߆rǸnӚNTNe,.8v0x8 [37b]cgæU`y=[擙k&IP._1Jت3b63 7#@b}D%˪ WL[0]UY d,>|O'd6 iDT FuF)ejWC-TEDWϐQpJ >n9ukh dKQl\~/Y)k8TqY4㩠B [gg8*]|ޣkMm%L#),@h&tƣBڸB3i'k ʂU3>%xhkm\yd)F0 ;>*5֋qeGe~s|/3ۏ]l_`XsOsJST<Ų ahvh`1@iJF]em,S$;.1Dq*9.f!T%"GЊu-9bJ~EVBc;I ζanO>s'ĀC,m1TS|kA\1hJFyYg`8dcc`2z.SVlzdYJNuXXXO;B|]ihd854'ڔȎF$REQS YGDqlV歳AfENcx1Nmu|]3zTcb#16.Z-L&O%IRQ 0 &{S(HU} B?dnSot ZC8<0i5N]_ߥ֮۲/{|J |_%#cfqf\2tf,6l =ǭ'kKz5TnRb k0p}#!c+WsXYY =NO oш;,YZ^B)䔓O.l5y}߿NgPMLLpÍ7n.|K2S'')N1C88sAqIb JDPD^DEdȒڜN$Fzz$a/\MJD}ЇG ^bftgPHM)]FдB"_Y_r)Wf_T. hͯ=̄K H"Ǿ4&2TyTH/u4oih;hfZkZD)֛c!}O>%ْ Y|K $ āmՀJ-5:+`SaB |[w'1ok=0I]VZó2ZU]֩ JnJSƾލ( Bp~YcH&\"a5hwm::Z8,B_,0Tg=pt(m2yaL[ q3^%&\c| |b7<,6=)LYh/ur=K+{RI=eвJ4M[yvmqG3ٱn`h6LMN/}[yrŕWrر`A(1FAyGc\X)hh@<{^(vcѱBpo1m=sVLtt˞TU7׬[cܥRQHRJJSdIn`( (_)F|৮q* |pg?%&gwH{w{O=:2ԣϑ]0Owc49Y?:zF 1E]֩}kS2*GmZJ be1`¸t^ܩ|<kV>X^>D?`V F* vXT&gԆKwY"S 3*;v˅ іQZi!5fL IgPA>%z[ Z!6 2*`v),tF Nt=* ؅Op\} dI keޮL\Bϝ[0X: `&rw" XW+b:e ,bNˣku@SĦ:Z( 0 R$d$FG SI*o7 :p_߿P-3є$V҅cJB[%ZT pm҇4ƨMl[r\@XꃹA; Rk-ߤg # UMc/QMcF(:Qz: 2K`P^.} RaXU.!߁ 2p,4{|ENr/Iƅ=W560i3P Eq*״Pb]P0ʂH2"bRk1b 5AIU#ڴ,w= nX]uP R\鹕Ec Y8_K)i .K_zvmL]]a, yh}>;gfZ_/=s|zU<(5C[h/YnLOu  C*cOePVNH`4 Ӛa5bzj388K(QIYX妯<¶x;ʑ㻏q湧E Sd7d=Rā=^\J/ֻ#NTeA\@`w4JeQ+ j}`O:ew "KBDicH0(>T%Ez$ ^& O1ϳveZRڪ,, wQ$eU"^9b @Ĵ˨`0:8WBDPaL{T}L++T *&rJ<T4E K`^5{W!^Y c{*0 <Ƕ2[ $Hbc§]U2ȩT0T)&nLF [b@nCQU cJg#SvL%i '$Ȓ:B m=Ne|mEdΩD)C2!xy+to!LDl)#[!qW|c P79Cd_3-%3*MeW=܂/LܭxU-2AUa 8UUIQ4`b0;Qԃ1vǧWebJ$LJԯk#™+煛X0SMX[.bd @\^7ؽ{w%knƷ\ KKKa8wLOMQUU(EP)ʒD9nv>rK^5o~ҕYI88r(2l۶O=gԔ upy(X[Кhy`.1P|=VF5 #swVt|<< P8DŽsx @M/Mm 1Qtr^y;rK8FoK1/CT5Ln6*7(4 j`CEJxq7t)t"<$gFiVmp^ Ozn_gg0X34ss$~2 C-QUE12v1UϨ%V0geEAUPd p8&J9` 3FB9 aH^e EUi|~Q%RwM"vRv$B"SQu ^h,R tDg { ]b7)2H?e0#5u.X"uSB(w+ v!E^XkL7ݪPԿ 4b$* \%'̥r7^:?m}8}Yω!:X|`呼nٚ4Si$VP~A4*wA"L凨 Mr;u]vJgHeRE^DYRܾ_1NY$n[K} 8fiNI k/8B>1n8t ؅Hcl_d'T)AX{rAJBĹQ'qio6>d T0i߁&z|HUʻf6{W{Kl[8^N'yldy? @EAȖI]T,`ڣז({PWx^5mkrc* {o;]m]|@Z9@ro0977iЖzӃ)͈zDrVE5oR[xF@q<Y,gqzQq_F;ʋ`wsLO0X`?Bca6~U׶Z m۔UY+5γ#p8n33=wɧ>?<~'2["2fO}o_K/GrAv)+*AVLv&C1N`ߡc>Y B#S rJR>^,2*t} ldq!RQTԴ0ipEL7n?9v%rd@eɨ"Ϛ4Ce4 ZJ3B"RE|WJ[  w&&xx>Ξl3WY3v !zn.rkwN\ripًE)*U%T^GwcѨ)TSig}uH}x͔W=̧Uep~h&w$let(WʧdBGc7eg~qI. r nTHZ0X"M`c{D6UKatR% =^&W9Ra&v{m[$,*)}>gs2tE]9[hd9KabbjW1H%7,a3TSěl ,,&>-ISԺ?d S6r' [uKߓAu?Y-Ң, !U$b{J=^żk"Ü&j$ $|.DF:痗S4iMF:YLS!!$tZ $'lKLv!-=Gx0s>faS14H.+ bA](J>[/#u?tUKE G¨L1ٰ^%k{o$LvSL PS.b04 j IDATz\x9킳Y>|uÍ[l1j $)qd\fȖ95z]tfl AuJr]M$ts4#حShF02U/ǫF#LUq;崗^=7~'D'w9;'Eۀn5E^q ] 9x}hhH0jKeUI֢/~@1v)&N;0ncK+94_oY$IJ2[W`kˤK7'?y=]t!32EN/|37|3ojyӛLLpх\d,)K_boԙ011aI 3'3Z9'\.lτE r8)g9m`&=/4LhaB @S e2m [^>_/920 I )EΧh6'12B0YAeuc:X9翔]:jz 9e~+:g4A>ۘzvΘi8l! RLNN.;0b C;U犗\|wVU6G*_>'cp($!-FPѣ]~Ũؾ@~qeF5Tځ2j uDd( h\D:)WHጄZW%}Qz^4KkD83@J|a`C0@kI!L2FV#2w|*cc2rH FY*(mmeFYx`5{'K00mʥ94AU䈲IVvgjwUWΫ\)آS_Dibu_ J#\9:Jcsg_v?gc ƾ&QV_*0ZQ/Fb!'yW"JQi_k11tG#l>쓹((VjlCA[*ьd[7SŴ]I/4susQ DD쁩 rIҙxfY%U-VcU΢ -u#W4\CYO=*QNX8b4!55+UYL7O^*VKIÃ%% 5LRY$?+}{ɷ"UK~8Uca'c5<ꗧ[<ۭ䯌679n>HL)xll,rY_|W{h I=$ԙLT(e H]Y2\zoOvUIgMzʌ X֤R#L+ևxf'a[Hs.SO$]b0 I?\r Qt8H!F7cj|N 6ۨQnU#(Z Mh@fR/8c8%iq05 % bm??{ U+W ŲyI|(}iKUKné ZٻO`%wDyK2L7"0nX jjƞ>[^sug * %c1[C>:]) [/e7Uβzb,.+LU<.%T[M^cIfA$LIn_-4;yO0'^]|NʴQTkQs餒_5-kI̵<oJq4<&f"#/룃h_1Z 1%_z|}ow>vE99y=a768SR󜵵5RaL\SNncLͦYM;kUy"|wjԘ^H_ʇ3T-<.Jk0.*F|> :8G1KW1ǿ0 Qu%Ɔ(,Gx 2YWJUZS#Si|[c#j4hE %*4TlebjHȵ\Kql1UH5.T%LP9Ѡ((NQg|IwZ0U80(n}fѰ5J1ģj@isՂ$U%9w}.2>O?Tg&ʧW(`%36 ͦk(4<,X]jh=MǁJf'TlèA$o`q)C1#5w A)7T^B8E#Lbje kGy*K=LOT>iwڿ'N:_>m<{7y.k~w3&,+m)'Ph5,c4쁌h'A6 (Y]Z3/﹚pl?l| 6oLQ <=*%SSMs6;<xRSuNQUZl۾f9g=~ +{cJ1dYYg`vEp VW;M}9z`ዔeEY)n$Xu`{k>-_`?.$:xA :\}t{Z^FS*Ixڱ&x7Q bXs^ZRB͐]/"s!< .#!&MDb{ƴd7)Fqb=OEli9L}JI Z C1e*'5NY仵ܤ9nU qvV15J E O'4sLg:&Ʀ}1ULLO Đ$`!NKjz07>V$L$cI33/֙dgc-9}/O3L "@$HHBEzMYW+wm쒵UvIZd˶,Y) 94&73/?No̿h*7o9wt9.0w˜ш`}:$3If-7R5Fǟ):'!/4up D.atF> ut׆ ӼEs oQ˼NU?Z嵔>i@}TV"Ih/>.Шzx]HF\^c DK'Xh-!m12ͽ_y.ÛXY]B{0~J(tf7:xnTa^K~OAsl_YnuH)lu;~,3sQziӣ))|Oեvݱwgya#NsҔNk"hЍG@QWGMk[F*gz0wZ! "fJGw?CУC}{ 8(v: U*Ȳ4v8yuRb`QJI3AMF ĂjX,X8=Y7ekXij`ɨ~ /ʞ'D dr8*"QBvADF| 4DV/_#8Ӕw+.#i-.D=xe(Miu1Z)jVk7,..vɲ~?jR(:wZ Hs={v/Xmtq#ȉ˜9ug4_&ZKdk"A*D$5wpZO/N&  7OOa韈Rp $y^NB#:3E0p<M̩9:Pk!$}ghhlit`T}ضtV*+~6kqPVx(iRXfSՕUjRBC)M^gqvr]۹x<~.+Klݵ2q"AL$c)lݳy: 8by~(ذm#nj:[vm(i5:Wٸc3r":Ӭ,,20dݖ \:uHF[s8Q$ikw RQ+ fi y.Zn~z s;bڷtfy=tNQ+JIL_g&I85pA7ʩ"l$]ήXchzӤs+mÉf[U撠j5Ւbveg)9Ї|iy뭷R R Ơ(޳7E?(\_Le9RF4|GxW,ID [-7,J}:^ &FWʫK/q޽<M N3-O4MQr%V=hTbjȺ *Rǚ8DR.҃ (Z!Tjj'GV-Xņq( I}rum&;!Tz(61߶;XYJkZӧ8kN\tX=*Y$ FF@B۬o6t2TFaݺ[lR[ XgT2kl "Yh@Jsct|~Sr9vJRJ@eRVWP*ўU̝aẅ́II}qlPܫz:p qVfHfIidhtnfs5ڛEa(Ptq$1'{9Qg;#On:>@#/o< ǖ;RrcV;G#/cͧ~CUZ˼ͧY_T-̦][(5̜}{4"O3(˫KcnOKO>Mo/ރJ4{/o>47V? I<ՃS=[.Š=΋P$4K`. h2\`_]g^ҝUq6J?_ kR)b*W:}ם  2d"q ]8`ɻ'{?'?y\fjzӧOoCi4diJ^gÆ t?#~{9z{?)_K4MVTD)r$I|$QH&LpdPƺdC]3Z.KFIPObb[IShI{hC$෾sxoRT7Вj@I/믘j;*JjMTa:߇fK47M[n&Ҝ>e=pnnt˃uW8?3ǔRLS* %m\U!(;bdt׳o/.)VmڭY֧Yk§Jm[``P^߼8+%IN3:SgB+hEй^&p5 !@uS IDATE X;*/0: Z*E9"aF,ފ:p2T5!BJ12]kV[K9h+) h<*rѹ)7Z_4 iHK{nj7PE]Af7[u>~cGJ+gq'U]R=ɺRyʨMEo yV1|B? LaG*C? y6Ņ誧\T]k0wcQA^CwgQG][+oBш5HP#7$tp{Qd u;9[PNAH!yFe 8Ȇ!zo C{P(2JYawk:rgVZ܍WWdZ:! :Kju@.KT=(g@k?RuV4NY e~9E/]Z2}?/e,W_m~WN$cJ=$ ~?cxݨ7sdso=O8>n͞[q%JstW2Q,?E^yE~3\g~Gn_bx8W9+ẃ#*x7xOry~UOygɲRdhy(_ <>" O}I>ϳCo.?'w!_~L3u=#[ֱ<};@">v*>_o?vg|'>Ϧo>} VWZ*$Y}ESMU $-k'@!%]k͍rZr"J/76+`KUYIq$!f&) y(w'B| Oui._`9H/~Go2uNceSٕ\JJ,,.2diiO,Nv*_+?K$*MΏ},K9RJ* 7|3{vf֭ӔEd_#Ԗ2")0ڬZTTi!sceW(.:@紥8(6x6y*?߂W@Fn5aQB%4nHbjI\2.-Pn)r"7PtO2Ь7OO36y6'=#TKqʼn<穀5ˑh?}G3V[nݔQ*2C#Cp͑)=VVV3R4CjA ORKvl5ʡTQ3449}4zi}?ts4wTyJygY0 0z'evszZ80!avvл5d>9lYXt箘Ez*ⅡfIXx}6r9vyJDV2}Ȩ\$A2C>/Pw!MTk5v+G_z4˨Ԫ,-@YWJt[AcVmr%$ Qd51j 47O^#֨mwh%j$)ZeT9a a0@(zZRsM 'ϔ5͖1]Ϳ{(-̩LFAT)6,d>}eAu!}JTCqصbs,}C݄pKxDPl],1h]N=Ӣu.F~e?SkBHҙu ̣\ijRFsr6#$q`18r} Umt4_q7@8 {ݰJ0U_5:v⣋5n"6@PTe3Ig~`G8Fl|?G)SҦ\w`7q.q'ص/24U*l^Ǻ 8 }ʉ$?]8Z|ulf Z_b}ՓC[W`Z䀿g\8D [B #R2tE\J=ǘ8"JoY~M.V}0ZK)/qvDNs:|;s u,=Ewh3r)6mq342Ķ4%lټYv)% sLOO#``I^#2VWWI[/>RL)Ic M^+Mؼ Rǂ(.j;k/125ƇLO'}ZzGiHзh-l($4/݇yov۽[67ԾuCccQI69e)z 7عsz s()~*NtFN[$.%lۺL3($}!ZP7ng'yy'S.gNgrN!*WHڙK]T!6SeNe Et?ʠ"2ZEWz#_kHr$Q@6ш\ȝ .#:&p &+r*s?+yy`"#3$7!hrϠ6xB]n^3)Y]^O_gL]]ۉb˞ < CZe͑!J ^{" laW(t2vlg Y;>Lj%^?h@wa|X\;1)ĵ*ʞ3ALA6ɍerq\Ye4Q$ xuUAwfJ0B`A'pkGTpt&h.L념'>T: 3jixgJ _| LM`CN6Qh y Y}`OlH!XC"$3*JSjz{ rͩnI&2bϼc"<"/:|gxm: $3nV"nVFG_{ 2ă?_(*8$+T:_x{ 7Mʵmr@o :2@ ^z9JQ cʜ:zc<8\.S4ye~f[IqDDFSUfZQtXYd$*%̒^Gm ͡!xcE ݣ=V]<3{-۔4FXZY.F~/ܦڬCEVo7WNtZ)1HMl:}m^fw\;歰q1?Hk> ':1}kn.n8XW6qiMpJheJ(@ʕQ"όeӟ$I6uB*2e `uuFE6nXOZVRՈ{hE)K Yh)JSJ!#4zQh"i/^R/1dKAlŜ"A`ѤhRδ&Ӽ@6L>Ji85*e匧$"RZ]E/Qk4HbM&#$Vx3) E@.K֬.a:n:e5y@J=}]?ǧv—{"/޳Vk?TL j5i6Q8p+++YF?Mu;}EdJSIb~l ǀ:68'Y\\Gb|b* 2TD֩R`wSk h;&S4Z3kX@/-!ḿ"-: 2ߏ^ YY s+r7C  {ar0 ދ]@aH O!u=LgIz˟S*ek(\hWʂL,KS( m9NEZ壟$Qȥ3gQiFkyn3ٲk'v㯽1nG_z3'mi6-vSnQپwJ{{lfp|!o"oM;O~fm䑢A-2g! s1-q!!g ׮.U/hrAƼF{mP !57v?DF8*ksZQKBʇBK3Wds2o`ϋr4СO::f*0H c-rH uzZa%*wRҾ JdJϠ$"-J!DAD Yu4d&v5TD8^Α"]Pp@(>EjswR2qSt]\4K)+{=Ugru3_<w_|G9 gϳ~?D Q O3.w?x[xFbWw&JQy;߿ OCƪv\*Қy.]"4{~Wmѣ4*xoP%FajTNyx/Q]OL|觿ϑ4ihPmN}5P.=5:uN+ E>M&B[5MPb "J7RL$zfu9q0?ã#T`9ZOŐ`Sf'‹f&?D\.3<^ !#}1D MHDP=biJR)^hac)6 D/3@AIh~GY~# ؈c؞p ,J2i>oܺo?~gh"6+^<:rŢ]ިmVV[V82LR%@$Rk,C}Z];wAab R1_Q +]Z]$&cqD13ea@gH RF2Mୣ4eR`28QYNZȂM"֪T0V犲h$DB,VXW"RD8=)$s%m5k^#f5&#:sTQ[ټ!$$'N.;Sn[J)4G\t!;j"JbnV˺IzEy>y7> LgϱnFnYElٳ)omOsyGG;tV[tU뙛YFR'uap`^ fJ+8ziuQU@3Y:(ր2ˆŞ"[ |yz'm/aúe ymq2kk2h J5{tT`18=]njmHP ׭8Mh:Z>}c "`ð [O0Dļ+k3GL/Lqh:StTK| L-pYs_YG{yBolxWʙK<Ǐ2cM9QL_fyn{&f/ λ&\tXl@zFZ\Qsc0]y59,~Oկ0eǿ0_̱494ǏCR5`o> ;nY~ Ml; '^;Jsd r<ӌY~So A;qε6AE}C3- !HtD3\k,דEqNRs'9щHUl힥CxMzJ2hJS-3@^e1Fh A˿˿a7MJGi/a!o~v)1qj΢h'Q1[Y]EIƀTJXZ^BIE,,,099(~zJ0O>Q148ĥK\|m۶yM+6jrB*SS,ϰqdjz)&>RdJ!xںsFڔ2APѿg̝}r-\24LgT ̨UK+e$/bq" )$ךv[34Gh! "ST_lۺv]J7^|]na:>wl=u'y!z+$e[oc-q!N7^}-;2;D`li@SC\6)LpPc# Bi:>wh,65.(L"3Kk/mm0iOѾpqD..{h _!0I~:-iSvOXdZƁƱP@S) mGy6O*"e$I{Y*b,S4M׍ңOrY6 <݇ٶg*Mz3'[-~V?A\{o>9tW{߼2'N226F`(vnhg4G‰6Orq".Jf,WE"ȲʽHs?5ho kMAWB`آ-Jg,Ճ]hC]K8 KJQ@;=ZKJ'0z!~3E"<)*h{R*l SS=hc+52kE4ݧ~fR։; "IfK M-JAz$"uiŤBRr GPx n"83*_poءQm( 0"8'2CI߀2;Ki훸|2UNg$ Uʩ㧙<9A5$1_}J1wm#f Ng;6X[`$œ)TۺK'Σ`M^?{{/E9(aeeq8}Mt)bmYƕ3D\:u'/ U昿tSo>>t{]&N eGs z@3}MJ;6M\=sR3yf7ҩ xKNۙV֥~0 g5B$C#LpFڟ)4%G7W->*iD:@Iʑ D:<nDWHA-L|j(/R,z`!2CuE.^@e6)IsGH3ݧVf+eNcHJV[- jSӜ;w[0::˯BkMnb9He8++ ##Cäi cc4 6)% v6g$%* Nu )3.P+EıBmȭCdFg̉SlĂ$ӊ ?;OSVѢ@sGDhD$(I D"QzERTYY08T{hA3RLOAO+DRKRۚ,έV>vd~Д[DFAS(ΣV\:"0r 3۷qܤֿ.l"GZeʛ$ IDATQFLK?5(t;]$M~kWۃ8Y~ǿ7҃ar*^sYW(pTˢgXf苤ȋh%tfI6%CH+Z !/MBCt=YST@CJ!gob@㥣3^w2İcpSL-4(@"κ>rYv!.Zz1CgT:wNu.vBmAj pN.n,3ya7 9>W]`Pof+ij,134EEkʼn7e8}˗7,Pm4XcJ).>Iӹ>λj BY= J!t¬,JtÍy!(xB7XC}r T>wu&CNGn.,j(B׬YhPGIMXiS|O)E${.{.EohL싣= >ṱ9\_&ߋR˱vT@rkZszTomRM9k$đY7m@&t!+2զy6M4 &SfvDά@oiFg-J2\Q=92$\FX h<^yyTiZF\aeng(1ՊuO}22Ai{ JbWx(I)!A2ż BM:rs<(3<ԫA5Pd* BZ+K U@MENıNd󭵍Mk!УAkjT#*_Y-T/fGpfKe'xŅ9FFFq,,,pӡmTP)C݌%rfަ^Zk$I8s(ػ\ +++>s736>Fej5:6;wdjjAn6ɲ;u~>{z[t4q%o&h>MSdTbn "c#6˺IUasmG9G*ME C댡FXH1lfT+1C5fgWY^lQH^7H'T$I +uM|Td y>rBUhMe,--{>/3}um 6ܸ7c|/eyQ䭰22zZ®YmwhwNvQiR(͟iEie-Hb!EDf2{M7}r=jdbMn] t`A^Tʚ imMK뀈G2e( Rb>͡'LI|=#umF5ZdHqcAŲk RkWuά Ma7W`j('ȊINqNn!Rǘ&j:Fh!B$n'(U+@z=NsZN%Nb&'&E1;֚^KQʱ_c`hɋL> nxRLݦVopPh\+)u{Tk5.BZ#&_̽@G EE(RzMTk ":\?i bͽixʼExݷ7QDhr(344&Cz4\,Y|D/h kwrQgvyW_gx¯YϕBZ%3S \L kQ t)n].|/,*i{Tup})ij-UN+`kNW\QHARo< s3 4 k5a̠:²phA5۽&'S)IĦ&ʍBF1BYс1IJ qyaz*}9R$f|x0֪qaHy4ޑёjJm]ncF֍k&de97:$~I4F@ݾ}U!93@Fn CC,P: Å`we)[L3 36LӐيGhBt."o: d*BXP^rRGu0PCNVoSsD++w#R"d>LV}PkS,,-r]w/pIV[rwUOxErF@G@?s IRY'1QT'J;.j)U ֪ЦQG)EZEUbYuАJ^ç\z ]Z1Epi5(¹LLE@{S#zga"G273NrȣV2sc6!ɳͳ6^g3eQD8OKÌ0F{ aEn._ TTF W.5py 5~~-*}祢%Ž".{mS7Zʹ_X93G%.Ih]p [Ⱬ":CwK0̼zPCFHM.ʹ""#Ok)8e 0l'kqaU^zI-\Wy|f0'Ӟ}=͚NXߺGukdk \kX^kjs gkq`U›NXګ.-R ;5{:=>g~}*ƭX) Ҝ:-Tjj,4YҒʝ'z3TP/%`Û{)E,e' R曶  ~9s^"P>AYG;t|RRĹs_%,T*yfWVX^^ƽ{&bxW8|0Ü8q3gϲ~@hq&&&&ؿ*QY)jj:e(z+U? A- (kF!v(9 ͤs|ѷ'ys܃{VعT>J DR:>$^Xb2NKfif1:MUIAJq4iflHJD%ty>wݶߡC3334Mn#vk8~,'^{zD$z^Nj: KK(mVj whP`41QJiMnx<8~ɫd2ِ=CT^H ccu/0Hl =R#hj\ɔuްCa΀A;m,Ma) gD+8L j0s]S$DQd<ծͿ($A*oT hSJ@!1Bnpac3mHFʵw*VAxd6QA#7xQAB qp͵ZɀR?zod*SӁQHP)4Bi8Z񺡄,ҭRBnk SUm`Puks-UT #iU 9 6}bE`!kx8@4"4ZA4u"suېb3kDQ׫Bm8l<̾('5YᶈG_7 詈H!98B ͙9ei*Lj$$t=g@"6Aɻ׿+|/{ogƒk uFoi4~0%.O뽂<4GPBZ]E_sE4 4k-E5%q 3x7Ynw`PƙT!y5!2:Rp6xy5f/i&Hg]!27J3&kyCNǣw@02TjH X7|vv -6RװAt]T%gMi;MTedl0$ 0"HqZ-_fd3qûE(㠧%JK_(%J 066*Ft'=hdYV8CC5BtM_pK(X^]+3o38>/@#N#K ՚5aL!׳Ъ=zACk^]ntۇuN I# |z'[e-o\Ï"AxBf9d(˞FԄ3exR@, Dhɹ4Ts1T+v;GXhWu9lIVeuZ%!2C511sid6N:t:]nAS8v;,3ͤDD^GRaff6n|!Nh066Nc||[-6#$,.- I4NNG4\M,ɴ}`T9^;z\a\2;mu'[U{NoLQ$%Kn%Yró#r$24|? $HH6'NG#dk )"%R$ϴUjվRn " Hw~lp/ٳxoW NV\X`4蜇ZƂapܠm .]y؆zFO&xo0a‚=N`L; >SFitU}KJ^!!sQG'_|dM+a^awmx{q ֫.&=0fxN'Ǟ&_!`^a6 7ߺC=#b1mU"cJ1Ip[2\jM{u5 dII("DhRsHB.Ift&oJ/R*Ϭ}"%v5-2{]ЫU*$QKc%9T~CG>1C}3DٷcX,_5w-2xT9V!&2 [iـ 8hb0+_HK7sabTRCNT91wa,WL!DLIވ.\a@My,c&y#KCP,WOq9%,OyX Rb9S*^|3żjX$׉EI0yأJ)3%է&y#PukoR_oaqgpyjh(]vX!SR#}Le8slJR*szѰJE?:o+;WW: .`:b,mrFU˒U[0ZU?䅝ڸ!H#u`ԑZ: Z:.QbyCu~ɤlb/O/OKtg'fm{𦳹m7Tt (g,lF*̩sZoO~{%f Mxj?}0bxՖTpGE;ias>'aj>VeLYH4]ef#驜^1=@js6pnYb3Otx3]$=."ڵ}=ƵV[\ٙh74H[`p؟L1k@6'z}17qޠ1M#O|\ x[|O }"Ou0n9%)uc6ן6^z9&y 8[.cggx No:,gAhжuڇӴt:}X0Jc_](3D!Rnr؋Q&oάNo$NzDI\!Q@*֞fog\nx,\R7). ׁ|:;>8 &y*)3RW&6"o8At$ ,0E{KHI9 (z)Ӧ98?M]e0{8F4w74܇ꪒSV)1Np3S NQq"C9#.TYf"-G !<jF)DE,%^8PJ^qs=pg1T GH+wRO7Nhm]G[&Jxk:E3M XלdZs@>VcBiCI9(9R)A}M!]ea| Kpqa5iCBc9-ErP1ԞblհZp1S-u@-gz l5Oo,:&H \ 岸U=2 d 崼\IEgtP>|=̳/`Zcq*t֭C? }!x>CnXq{ѴmflZ' s^ ˳PիWsH37~-\Si3*pҍަ? IDAT_|)p 0ۯG?VCN80sIYq^ajstÎi1ۀ@6  M-(xB|u7OOw1̜Kcj.dZ(RR96>"'ػ/9G}sX6Xobbb@ 2Y]9c#x6zϾ|1O8Trǽ5 21)Pd\}e|/^;LѶG .{6ɐf agbkq<;s6{0!Q1$qN ؟O#f.)&ǠnHr},k_+̍&QhA^C܃c]cMcq/ֹ]?&F)`}]9!} Kkxg~3?Ut,=L MKcSd%6'tq̢$$L m#!F2q faT7 ϳWDo Y CAL^)- c 9lƅ\={ n(`t\w\s>&z2HTsaT[-穦# U#*PByj6c =Va%>=D;xg#FCTKOtpe+\|"k,|\ӹ4Wk ."9tEFGkǑFRRbu ՅJ*шE/״ 7W 1T Z6y!F&vx}[FП#;D͹# ` %IV@ LcaEet-A,eQtby$֤s|aytM#(R@Tjm:3YaDyi~sׇ֔!QdP1ed r1y'1C= (k_Iy0!Z+̀Ώ>u xZW,{қJzRWD JoNyi(~D3_[Xa*yd8]w߅Zk^(!M7fIC@'ކt:åK3Lg1z}ZV XXt}l6O`m|ڑFV #/;88\4[kWq0 ;Y]J 6>~nۮC37X&o⎊)X'у7g?F.0 YN_k< 爐&JiNOpU"|0o-X,6pn@wX,ΰ=\ud  ;o9060[{_|[lw EjDI4I7/sSIC$ ϠhBC fdik %6LQICl)7) S'gd}2#IjaDHL%$$ R.EUeB!ѴB %@%S}=ֶQ-$yxԾ4ꐛ=sZH1(,3 g%738yAV6ڬEP)yHt#mg?)݌)4|58USt%XH<"o9%\iaJu=EA@8J # q#>D72.Ϣg'Kyq  Ìc0UqYR+_jCo.:RSTpA(~%%rnJC{L%^Hq͇)/| ;D18VuTf\w‘aVN9x۫xD|^t.*YoC9Z-:ITR*q80:g3F)En1N=pc6FIE Sx$8UތVR(h9;7`=u^y{GbO+<\*$ʕ|Y"/l&Ki[o)郾ཋæ5FӴ9Zƈ!KPyOg;xK^R.l oewB/)E'+<-ﴘB;,:L1_[(x 8]| 3Ű^E8 e12B4 [|oq_%U" O^ }ޥ4@p]wރ=<#Qb|t8=;æ30`Ld!CX|􉏼klؽ߀Uġ1qÇ,۔DcR)exu4 4HUa=ef@<7a ʐkIf5pޗ61jmlT+CF*S5JٮHKr*}i 8oVB|JR[)~.1:{8(٨OD:9RJI2jpKDdE@d4,簤Yj S, | ~LDQқ(ysb(bc! f 9By9#ɞyHtb60pimNW5&&ܲ ؉ 6" }(?X93`?L [e+j@;(UI\tp>΢af 64QBoRnUqi%.*~LevH3sw|A|p#^}&BY<)+?iUo 딠*~:]T8\|x8(F/Q[||?@^SV2BPsi'ړQVd),˛l]N2 4` W=Jc`lj't;T`X^ cVRdZ:FJVݑܓ{oo}d 'ہzo/b-b2xL,[&c#6MyJmᜃs.y՘sWo|/ZIra.~$qG0`ϑ `wgo~U|{8hg;Ww6N[xĘOsZ\zh20îi3"tLh9BOM O=>%ڲbJ9~{gS8OaC~8| wu/8<:ºXtCc:!Pi6 ׯ]^{s$>1'@Hv(ziDS.|7&mؐnP̦\T`HMa*1yP CDqq#I u vF9hw0\TFDzbOhL HTŒw#1U`$!]&s JU1w^<#1NY%B%I9G{ MB5W cҀn%4J1C\Tku#J^)ŐC$˵&6KD9I%3 V6˙NbekOpHDluB[߀!\$|vBHT갖.zʯQ[T=)V s`UYLJJ$ye׹rKʼkӀ֞2Z;Ȫ0B B0v155a+3tpqm;ƪS 8MU592ok%8l ,h]}\}Fɫ[VqH0챬XXfGTI]rM_a )QeGUp jr*ׂUqǬ׳F.Z֝Cd< fߖ{-kZ&x<=m))+('] *`MYJzp^`{=Wz.Ve< dp|xxCnA;{{>-;#oM"i"'}⼋[4UKYy/m'8:|`ke&&mfTA\ ѯ|ۯdL 6 Wvq.bld!z&` g7O`v'w-ڶAO@gK9ƙ a2M|[GЇnc܋_WlJIBʣm33f|[׾W8o@hSl6=c؝O^%g'"@֢m-vwpgMm`<ǟx?cHJ¦^.Mg(ASe'Xx4؇u]mRܞ|In-[ȐX&u;ϱ/PE c},RY*#MIAyI Z TX=#3c@ G.WTH]D.-́0dr}vЭ%13sW=|#HJK\΀Sa6l‚\ǡB$ė(LJy71`"{ɔA$Va>>lN$i)tPæJ)B*(ASbDŽLˀ\i$t܇QjVA9W{fClk89Lp>JJ,*^XP}IH.??*GIursIlN;&Y13HPĜg&&`bJBʻ z_3(^2ڣ{^fɕԳXSgn/5Q j|Q1S@_lJa^ On^?\.:>#%ʈ@Dѹ`T1~h.1 9`"XĖS uQydWR)"EM!vP#x{kg:Lس'/v,S_jyq%J9G87{J}N;/Q2#W_n}٬s}6]G2β|RL7 pawl%Qj s.]e/0|`pITb9{{T'9^`l4BaY9ξlNoboobͺ} }4o6`Zuxf)&D@QbI&lGLC/akh@>QT __3XNpDXmVqi~>\-X.cAާei$5x#KJ;X&=| ^>OO$~m8cZ`RL瘃ixF3t]?)In&5ȍ3D9dH\웤WR}bԇk2PEc3<`@fiE2bauu}| H1lXydT fTTrGȟu;xtLh(k\Ttp$WDi,)G 8sFLT 00| tg}0yodr7ˤY(-l۶ u74MrƣJX8wPC?68y׮]g(r9.MCp>`{4&n= `ywj+Ǹuap|}w^t2nSv<1Z0cY!v34 ~bZgڒrC!5Ɛ)]VICzo0-Fxmi;bDIRcuX3XN`&. FPo5uWYS[F[!k+TŇ cH|Tf.P\Ki+sp5U2ZbK?5)V!nP* Js.O\μri,;u7D~q Ʃ7lMw>bCo"KTqwxD~[*8nS+uL![,^PTi%YJ}x"s|^G}(1M!Wli* 试Ên`ӲQ>y.k-% %ȻA MC2J2\k >`9S(5İ:矿ŀ?40XDf5v︊@[FbMҮG&[yCOΥ*K3QAxƛco\aÐB`,+tC^o k=Aŝwގwt@}Clݗ^?ã7bx_)J|)́0kɧ MTݤK<. dE"r t 5h (RГߵ\Qǝb{xPdt۟ P%Ogm\/9~(gcVыjX=.=˭m9\yL/ ዙժ#pϱb/~؄u-#]wo>jt2zVzmט1$͜4s0nvK~>{q7a&m9Q,VoerK%1%[?~Y,L'{|rG~']N h6_\$iJ^R6?)P)̟^%VǘL&0aL iHD`9zyk0LYo8w^(0y`M' &zg yм &+SlEb!4: ̰`SɆlk`ZJDq0KG$Qor@$lAVѓB ' Ăr#eHs1v~Z1IP 9g18Yu"jYȂxQ(D:szC5 C9SR|JJVtL;sc\&Z8˺1&j8X@p0({ <"}Uڥ\9}8;:=܏ ?Qfx تA J8֯pʕb&5{M ~W9wkU)c;pfpPn:sw◅yi Ҷ{;N0)F_C|VggɌ *?CFτ ـPX*V~;S &/0=aHRT˝&O^^}5l6CޒU@8<:ŧ>p%, H_/cY_{}af[uuLwM1s I+ ]@ <a aq갳3[7 '΃ƙXHɓi$ݍFH )}*X#$y5Ρ:"w$;1kL FOGtT#z#KQt%Ka_tm@2Px1Qy@TϕnΟ  uzFwgaȞΐp3^dh`ν,^~hM%Ѡ xT!<~0>ARh$04;Lȡez:QQ1c8q0ҕ+p۠MN8T]^>un65*q٪$R@ >6s"ocKt|ݨ4=pÆ0akkS:t:)v/dWmA$z'@c% pVK3kc |#/|v~&JuMTM`/⭷t$h81cB4'l$$ڦD- լ^9"ՀQ{㬵M[7^p!z4lm#0ZChĠ<{lz? -":M,^z>wF= ?yYLfXYѴXl捷I tX{8Pڨ;2DpujiHI_?|M}X4Dr& } ֓׮\+W},h<0mmض _ /mC6 IĤ V zFDJLB\$T8֙P,"tCB6}=] (ؔc jD-&B  o!mI'L?s x a+s|8d3:#g3=c*&R޹ɔwAu5a\e9U1v:HycG"3 0(4|<O|S9/(1v0T/.Ie,ƤG,HE75plK1˦b̡TkH?& xT*F5蒽A5R x ۂ- 䤙|F | (ȂR)]da \H] ΆxMlHK!2A߭{րYk%[eRAR } |ϿG?1+|7\\mWɬ4EQtJ _kwb^d Ŵ9Z'M=D 9^fϽv?oj[N$W=y_t-?eL3" `XkxpvvappX-W] {ئC#9y%0i'5 جv2 (kՃL5i!). 1%YQ<+˫Icʠ),ʵK(߉ R i rxH>+`x2=' (F2}%P2h7dYHDY/RgR@I~JࢀB'{Vg1_U^7+)d!n :T/kYP 1ʟifV&+P)Pd*<9bkEhRj|JKyK)L`%e@- ԫ(xIGHƎYPU X|_Z:('\W/3^~RQP壜jBr(--d}|40pL8^FV&' ŞyL $k&z.׋->~M1Ow,O6e1vڿ\x$cjHo} @h#EJc  [Kj;!lޣQs뼛bf T,5є4U(\/ T5J׮Mۂ +_S?֫cў'Y lVi)k=nKmL'L y©Qa! >mLu?3dJoo,3`TBw-}?_.޺y 2ƁRC" ~ k)gV~:Z ƲDat`N_"sU*4uH&̌mqrtcf/tba '_ܔn6Vށ=@0m <Ť1iBɪzѭ50 }z;Wn|W`:Bv ay'v>fF;` f+@8]4TV?)(Rto ^xEf`s9 }vI;w^89=w6CԾ;Z. %1x6O<#94q< _~}=L/.`\8BԢbeCGf/013^4 gʰk,V^,D̯5N!7Q2HDi%r\|^KyCK*ֲ4!2k-c/K#pЈ 'Iā @gP]wㅊ$$j5%"\mPq£$ ;R**4 %ՀN^: `6wJӔDKA<&3H>%L*3w!*8T,夒ث2E-׻P|+=U8k'͔V`$Z j&S}/+PK<@PĐ2piI}*?eT/2IY 4F'Z4;}&&,\:cP37+RcpyQm5=f9=0M;SycU%Xf^k39ys8n Uwg^D T.?rc.Vp_]6pG4K/Bo1Ɠ4JEp)T8]uÈhd .vׯ߅|RНC AAb-\41. {v "ؔoTM̬ >JE:!%O=4Np`]bp5|Gs0J# O2Nͮ.G2k'`p,70q*nwR, t=g,Gsl7a0b&m+C8[8]x lN.1%` -gpd9`@s'-.~I٤govGSpCZ}Q,M_0202n<ȣh aXwq''.v>`r^C?#9-Q. 88pzxW=flP*Tf)+d{P{ N5$ȑnT 6JȔ&zؑIZ8/(\,Z~Ma˂b܅Oťݖ:{u CGtaCHL`Ca~pz{1圁b@\(u[K-d%#7 +aOZp+4C%ǐA1p$`xLzJjaz\"E8W<>rk7(U* fk ^XCʹs 'Jj-ۈƑBdDtX%hˀIl}G=: kae٢y&(tjsպ L8 [ʔǐ,)0S0zt1ω%*)+N,lȀS[jrH7Zex >sx`Za6q7z[xGq`TN !xCP;yǯJ0Rl|qf gk/mZ }ڦŦ88: =0hNɴvl pX cpp`p5 g`hZ ̘ρv:p0sڃ=v5sB+1`8;9_r-+*_縎C˶m0 ~mSG;0=K{ۙGbC[8"x `=xʇABVx IDAT=N`y!lcM8u!FPl@rvI q2\Lfi!ZrñD{bxb4vE~B*!L2E(K2&^lA*KyB%q+/BދB3w!owy UIɫƚ$LIx"~,U-¦X-K|%0'a[59?::}=큅Hc_>Fis}*EgRblc_VaRq%.|@ʪ"蘝 ^kޚĭ*8΂ŧ/mp{3gcHcƜjxO0z&|V@` 'Ke| }32t >oa1˿c]חMbjYQJ)ߣ<-A-egУ}Mc^.ptraSI o,| v0Sz`؁`>`Oxǭbpew  ;6`4,}%,︌ 0LE\i;k7Oawa݉&ѫfb?Sb<¯4~zu6>'j7`^/ ol PeI0`owwyv7~3cp3a~3 ?;gf\N|3?*~w^iQJLSڗ3帙$VGxBCJf8EO ,QL!  b3B,gy,+ҿF6G-%Ւ,-S7,ICx JPJYg֌#x,%e|nYB%r̖=(Xľ4"AQ7CaӋ`S@ !(Q[ !Na#˝k\ILVbJग़,;FHPfCZRgA9O:sNJ!o;WaKq|{k^'m!1UFPhX?JʼnBha1(e$)Jm9PIWC&M.Z" -!:ez RIBd}NPazEAOiIE.$Ml|&6CbnM5ւef,p 3RT,eE ɴKa,:*x -dHޙxaMZ (eUICW1s!/Hq KUٞ ҍӉC,:j+ưQ͖ő@$*#GsBtXK D7:iZ2orj |-Vm +Vl1Y.9T]L 3?o?n޼7:~Vջ=3XHp IDpeZ# ->}rKd;q(E#Y-[EAR\ ܱ  0koKս7Tu|!sw?, =pwu'x~J_dR` ca1hFʏ?QnC._ƆPrP ŠP Jtڰ;nk3/S+{JJⵍ nOxW.h9 U4Qerle~1S+Y_;e~if5v{$'};o<Oj`Y&vd>}e(֓O7aJ1^-'oW*FetZ?4Rό/VAmfP}ϛ~`wClK~ʪ9 Nc\Q 2?K(@QITm|<%}*G( ۍ*st8&RJs3p(!6k=hζuNeYrMo636>﹞dSC}~Nt79n^gcde`="x1f7d1R)ԉ#?#[phIr·>eJ1 ԨZ3jgP~(R(|A=bpaid_ 9$1JUWlcph0+0u!ngwo?EYf6C\b"xPSk(2E1(>A 0?3~xyv35}PR׎~Y`l0΃",AɠՖє/5w^=A .+ YC?tͰ4RUc:tөaC4R9tTP;Cΰ\Fy;,%~.:0EqsS TNQ+'o9ɠS7qJ5dYXǩ&H/؛I 5*E[E~_z:p[E2F CG7iZ%!8v-|V$,ӸQM&IڝИuli k$+"XVI+7nYIYBLUP+|'Q3;!KU .sN9%M?!}RHOg׆ Ĵ9VJl6WS9!*='3-o?P_"·^)Mu%v*oIE ]]KA~3AB؄`:G[]a.?IHA8M/ ,D< OUIP:x縔ZpL'ٲ#tD0IڬcXTV?/:4ұxA:*T,wBc} s=EcJŌ¾cpIe>TUKaZ a0t AZPuaY,"{bSdKER?*Ng;k;J|lmlsyK2P@&Z'EQ?1CM&mmS% pF(x}K`لJ. (ݨ4H1Ur"TEBک@/&.+ dz6Ae9Tva&G+KH}"ySOk΅A/N}Yv@يYmdvE86)Q6%y:!dhLCo 9n ] (AElLNͅ" 祰:Jsc ^Pˬ6%dxq(hUUBl:l%.u㥠J-{d>isCǮ>יt JF3  [|둯2̱v8\EQư̓ !i3aP Z?c~"鄝M#kELDXKs2=Q;wb*#4AkF;,- e쩃0xCCR?y-vJX\pH]QRٕ+dW-! PSX;ȣ:w*й#3֓[P=f)UYb-GV^IBwIӹnCWp!%Z ʒ͏gqywA}F1cFci #o_l7҆;(Vcj!t"fV~Z2ܽ_o_;K }\uwuGZdC0!ASP2Q] iksQq|LodEj`(fPä6Oh\BWP*%c؛P Lfl썹z}n\܅13Ǯ3jpE;Vh.m`&p*,r\;jq|S]Ϗ? 2U,NA͔ǹ?/O3WjTQ&3X\\1VWָqwk_cowi Wy7!]]PwkyiN\}*?!g困l(.P8K}h pC<VC↮"eSYڼ bUJJVId!N*(& l /MkBNFÆ4KeÐG$DD+Ȗ$d_<~!}^Ĝ5})p׾|#awcp-|S6Ԏ{vVO}I=g&g{?/><#cqeo}.lc}䇸ʫ<Ǚͦ S|_dkT>{9#Ɠ1rr/?;䏸p,·~`5f^E޶(E8e9w':&nl9иP|[`d IqNC< I maA'?Eoe/+lL% #Q6Yß7N-'2 @iP6H:%_}QFP*3ܵJۘ-qs][R$T+!;-2!r.yq]P(&^͠ߣi UQAV {R1FMw9yz='|d%0xr-!TИX,T?R+SQ]{ *H(#=qh/LlCmߏu2dͤWK\81 o^z42SXDPj/ ~l}{v9 mɱ  IDAT`+rװRwad-G*Q/! &3j!OC[e 0.AhT.xOp ׳.$B"*>6y2\QLA#M`~3%ayP(5(g8ŴzmedPzQ'4u~xq͉c f} 1=UЫ?(^pačo=wવVW\wU|FùMukX.cu_y[Yϗ)7ko`0r71Tv 5ao2(4M]TZݠ0yӎ{aA( cQa2fqysY,GCqiCO_,NI:I`湺r4:,zM79 @ (a{2;l\t4~8|0G?69RDIAҶ$K.RbkyWCË3Ʀ͡N6lQRY(+*dR'+%<9ѓO=|EQcwa1<1~>^F_ ?AF{,G>Gq11^>KcV|hw*_g/rmwS'_gn{8@~-ev1u;BJKc:b~?u"j]TfyDCKڌTQ*do{B'ˍ p^j 6 fT,Vł.6TE'!Dΰ} ;yϟ(םwG_%UWuXpAA Us!;RFNKӮ4Z$T.alOx4>̚;DBji'j`kxa?b2ڣ%4{@BO<{m̌הksOdP ϺF/>He/ zawܪQ⺊Tq8yo 6(u: 0:'dqa k(mz}xY*M{1Aՙ%ؾt1by٥_[|iXZZӿI&#Q4[{c(N-u-Tc06쏦&ꅅ{{x邪,tמXcmm z%~A) Xﳾ Ulݝi$ڧgJ,_7'x܆>;׿|ąi99Ñ#{=O&FXkkl2a23 ,MUYT9q*~`0H\Lӊos-{Iv8l1LQ3#څr |$TĔ=1m*w)E794:ʬZ9=^D%K\hJUSY;kEg&/ eLn X`-@YxhtW Cop6r$6iE@Ej 4ee!(X`w/[5G8v_~I?poc6_1y_Ǽ?¯_b \w`e=$_OEoݤ.hճ/1!}:$T>{xїˀ=!C28!QbjY#bZ*YR9zwqc΁Rց.دX6u]ur?@?طyO}ǾPͷ\b2960gQaHɁ$?rQ+l]{x\:[dj;\XZ_׿ϑg~q!'dwXlPp\n4u}}vN+`tA9tʖ<# Nk_M:sUZ(+bDV1()g/7k<}ڣi0Ri+4o^(ʥ=rw3Y\Y7"pT48v&;-&HJ r66EB[hM: *AU#S;s$;:*&E>]lhM/ꆽ]>Os{9zU/C|8wO> z{ eUanaxAU?Ɖg%n} ټp%藹p-ܐܐ\$םc020%v;l6c\{M|_`4_S ISQ(Ρ,3#K]xHDk]%[kCL`AX]b=#-tH?uY$_:eL DRT+ZbL1Q^$Jmb_9>;!2;p)Y5bXD8r!{ sF1+44V$կMϟg,vX`"Kve>ARh]b)ǗR*WQ G`/>YJJ+T /Qơ=ו~"nԌ()Qu%uuVr- p󲵁YvAθѸ|/z.|n2G4Qmqjuk/gu)T|Hq3LsV>.VJzMxr\ܤ@;zOxUDQif:no('7>,JygSVO nk $,L2R&Q*h#5bZk666(˒!)KY&,"g)9vvw[fWbCmZߞ|l҃)ex6Mcބؖ_R)EKYVP ΋/mRsyp~v7݅s 18lBҠ.bZKvۭ?$fЇ$StYQ>[{,rXg0M(Qѱ7D6{EF+/a]؛#/݀B kf\f.`mI¦\ZSI9ITiS*irsstŜH+:&SH*Ά(SGncC`+ qa\M`,ˢ`q~3Ͻ듼?nw'mO{~'>걣| L/5_ϰ236N9N?$ KK>WDZksm^9< KhsE7M392<<. ʧ=eU/}W3r[_C6/\[Nrߏh-1ڞ(cS?sftBO Og͌ݽ}z勗x9.p֥K\< [לt#sXtZ,cZϸ՜6._03 (13C: gA9 ~|WZQiGT 7XZ>‡>a^~4[p~x4^(d>3x'rrw)^^Uư cw?iHAM+V}rn:1ܒp!vt[Bh2KNŽ`bG` ` MKS <,D0܊"ВSߖ-9̦3V֎x<_0c|of>/% VO׾Cn@QaUgKQi+&JaGrd*Њ,Ǭl*jct^:u@"u;T|;tn`dHUCCjSd" 4&)+:1Xp䠺|&[!;_6lvC3X|Dl2q`FN7U"T)i\qf 8~qiv)sQa3*|^DN4;Niu<ұ\)^; 6qyGGh@Fz>;z/c }1J4bt{Z3,I)ddIyuad"+}|EO>NI`)Cg$r;R dxNW6_ψ v#pﳰpg]̅m.?{|sgx;۸ބ^0j|1N5TAULaIXgO',e>ظįʝ_`oSRԔ(g= (j#*z7{~7ysh/Q0KeՅ,H u q(p6%`yMtRY:&)NDշ2%*o@Soξ1c4Lah[}rJCv`2A{E򾔻?ПTVV15(X=Ϭ6ӰtdWE%IʑPbAT6p4S |d-ok j0冪W7Cπ!kQ?Ô*6WISLUyE{udz B >O9E)uBj8 N )T4R{u(p&LbMnd;u"͝c`R87Bu[ -#їN\i<٣q"j3>;mSa4PCJߏ <ʴ" @tyg6kb8O@2T(+U'SaZy0f+%Zcϻ+ڥfN IRo5N;1VhY^g$##PY^Tj"S,rBCs-U&Fslsqk~@HɈ~Ykf^~E&ә5145uLd7y9uy 8mj-gw?o$V…fr ]Pf-NM͹w ay Q m"(-ٸ"'Z6 CL+n?zN̕Е|"0J*8} q &Q XdrRT8x.D#zt9J}MF|]!$kD&d'MtVYNf)*oskS.ڛ;r+fۧnfOvR&S`\iF6/XJ6DBk֜A`VM$Xݝ *q›F7&~?$mU t 50bo3Lwvw.1:MW(ǻXG};`H(f},Ǟu?v5_X9[s{⓿?+ -2!qn~/_~1> \S̬\ulS/n7,>oo`'#zaAYTeE]X\:Jo}%we/},[ێS.F %аUǯbqi[ok wHC9-5^>]C FPI|YU}Uy^= o{-,/-{i(O0ryQN jN29~ H(I7 ( 紲,ʧjKk'7((tJiIG1nD lKZQsisb鉒Qq>m* qmDŽ sƴ"%{Nh2 6n*k܈ H#rhszS#2',JJ$@}a`1p!ۯ3Nt\z#z8±˵5Z{(w({%Ʉ`"TXwaQEk];ʪoI&^á\m))eN…9-|{Rrv~u RPWkmBi똊TBڂ(% hl=N$qұW`O񗵖ш^L7/؆m~g9s RJ33ߋߋA4Kp}m1?7`~+\g,;Ok- ,4f/Yc^O74MÍ ѳ nlrÛoalɋ}AM4T],*@0-;NEMrsNX?9-` cEwe1ˮ:T QEHu/$dFMRZoe O-jMcc|<7Ċy(+X+-a@ёq%TȻ8ѭ/M-T4ly8w8AYD!(S[.hIF) CVt{̹'}tXl2v.ۭs!0Ή~!VLL_?7>?Ʋ+sT.J`C2q^"脜N+uZ*bϟ;5ǗF[ry{rʳ/qE$+G)˒nW_:@&JCY& 4NK6G=0G-7o޳hvg`fvi=,Y6}Ě`6.%f0d1FpD^o7豸wvg 3Sy d<baX8 Dž(0 d?)P]dFlz =Ffؔ}{)S.1ѳc6n:)4PFȝY;VLBڸ}W!+t 1jXA1qf"n'hNVi"cBI2a( HDN[^C>x5mFfX[^2{me1F&kRNt]ֆBqVe%Y)%WK,7PH@U*葶 +Pvڄùgy優 0eniM''R!Z`8[4 qdiK*3I9?.wP1)MFpMϩj=V|_GV;~8r׽Pk X{V* 핧 1 08ӥsfj.= =kX?l^>OѭW.=hv\ͅYaҵjxYGiPtn؀!KotE^i6۔>BSԑyNVњОm6UUӔN}(>"PL#1 [xߝjs;ʢ,4[}i2w))es-37;7 JA-#D2Jy{=wSi^~G'oaQxFcDkf+gҖKym(PY(7DUxKLBhIRį{[t.&]eTcH{n ^oaq?ߤ <#{%$ 3q,ҲخS81IoGIYt Fu' C)DZ<|V&ao\XS+72~F$p3biIBTe׉MĪqz6_?CT IDAT|F٭wKj'gNUv|g*ūs :/{8e-JHކ4FSM@0} Ǻ4 i2&Lp6]Ѭrm&Rkovڿ'PԚO|&L 7 تV J,3'5,3jBӑ:<=LT2s)*v~E ׃ԁ[ *GE`foүsUE1 ex4d~nwXf"~z@ 4T.G/;Mȴ8jOo_}> e5`ư hOpc9?hl^8C?_2s osS:?W ˘A:7A k Va@>;.(7TI5!ޗeYY-")&eh"'d^L0WRi!x jv8KY2QDi A+O_{u7I0 1 VNâ<Dt+sF Dj҃ʝK~9e0<2myb*lndB%IHLRׁrǗE&D~ C7å{V'ɼǔ[O4  I!9:OmJQ2w*d>%.MD~mh5;Řghf=}bkk3\\2M ۠* QQNl=@JYBJ)<T=??8+_-hNAwFs?{߲yWA#|m(?o2l|쟠Jo<<}G~_rlLf3\!nv0^6^oĵ& 1ooػ)Nv,lnn$.#%>Ş̖sԄv&w> 2W# ԜՙffnxճPi{FH}+>B"QY: gP8ycv r=k lRh0M+RX N!Syfx`눰A'yÚ7, vOPy=i@}\9+|r|zXTZQ ڿ!!xgҺ?s>4D&Bj 2)]w F$ &I cyYkHu8RrL6*߫]$K=,-1dOQcDkY=/jG{kt"M 3TA#iM03KإqFM)34ұ{/k&<XW4rY-|h$W4z-K %?4]pv?ZbY3F9=4$׉`Laz,NIU!&<bY! '쾞G.k:/4ڡ4p"va+Y`;|<{빫oOЧfB^\'-L=be*@CUJDDMvA]B&=~b^W5a:2=&zJh\$ݜA\,Wi6F/*"%^f(Y|RJMyoS{Sw eY C_o~Cm]%֛Аךy{Q˟G׾|?O}~g~|8w^G'0C0m:*_j'E= Cx13yğ174fjMEݤ3ӡ6!3{q>Mӡ֨١E //hO3zg~e˴%_s%,}#(s(S"̐wްK 14˘QfcICQ9• O(,k IBtDk^R韇Hn2ː2CkӔ09VÃ8EB  13!:G)<gD]t%kO%6ωg䦕~8N_)CSvkR7&B3)OU9f#(2nQѭ,=M[cH[Z%CTc@9a t݋IN` {M'$B%Cj ɱWi'k3&%iz!aFRV*8Τi}J]?Le2ȧAtG&c-,ׇp}((M z kRP$yH4rA]z`SP"*. RP>s-j'Jo]z&aOf ".T=_+(P ةܴ PYh}zrM]:&cJW"ŪȔIJNV{`,+3\s7ܳ_5 3~oA&wc?K MۆӍZu˝0<.gEŊxM=1@&t +- {y.^TAw݌ǣZ< K6ӲwzHwSl)1rR(<B?NOOY~)vLk.h!32{g=·ax]_|A/?Owq4vc<7W^a{G3K>[)@hnSc4C>bjN1=۠^T!itOq] H;RtA.?_BfԝJ )n~nVGr4h%KhMx1h{JN֗ТFdI1 HzIL ' .!C 1/Mgzu)1xWM LI-qG3#}^ p%l(s-k' @!${3wly&=o8>0*L5Ѷr['ns;]I[1t]h.gKPwK2-MrNEbj!&ɰcKg͜H>μT@e"'-RRj6` LV%j2zlonrdAoX7(6 ?N'AWy7?ψfRYeb)&([mE!FL<+Ll=awl_waH]`Nv (@5 hezjz֍Fă l%jF ù;g%0>s?'^9Tj%/Ic:j\PK6JAx5Tcq`\'Gv,ZFB@O:IQw" 龌1|ˏPf5.†; >n > o^[P .id`X~8?/Mx??䈹 S0.WՀRAv6j/gO>n[p.ܶȓEn ߣly=U zM}Wp2fcQgڑȄeXn~sW4'bXÁ;Ӡ=%4s{ VJОiӚLwivjX)Df9f6 {f9p?9O+ghwxiyHd [oe~~#oլI&%*}Ԅb B 7ωK{T`8{E/ٗNO7f 'WRW$3ao&$\&mRߓ 6!jj  j-$B-̢}zhPciPSW!0W)`PM->!-Fَc~rlO҄'$;؇ LRv!t),Uhv1U&#K)\'8ٌ`ITYA{s~S< C>&,"0I: dDsDƑ" EøT _l~Oo%@{tW9$5uRP9DńN=- >3W?i{=(y$WT=!Q *g:K&EĴE%vN?oҡUJzġԸ-t`B.l@iRSHTcT1II'}Kh Vc^|0*<H#[L l*$71s;;N.-YAbQn?n R;;5L 4T`du8trݪȫM/hƍ׿xR2 zq},>ȹٗQ+N(kvdbԿkRa[c6/pA DSqlxc19xGrYPz;cU^IVH&!|_ 6پ9{V'7A1voQL6$` ~Urr.eYN֤SSS\[];B6ȆT;!#(  @w_' '̸knܥaOo»Ni|2lZ5nty=|7&zMi ,CYH!ܧ>`] J3TiMZyɠ:534t>Km)F1v)%۽>4bz)~O]`gV|zxu8E{x4\Po6r=w0.FXa1UI/Fkh<}o&,Hg(e\`FX~oHݦYӬ7T/B-n*Cw(qU&3y@-ƊKiL,fPq},tQF I] I}22WMP,faBb2Ըh#}1+;H/,\TJGʌf>WQclL 鱢-&1)TiMDRvY[TIʣM~yr`*"A r'M} lVZ,˕\|Xn$0%iDu&=]66@'ҟXh]eg΃jnàb藺rm9/h[LcM&xorCB4Q^=h UBeN)d2%e.2¡ڗ`-2RTC6np=pa@&]/HIծrA$Z'@#l1՝f4l i]qTJELW^&0~5=Nï"BIMĐ.'4iK,}* 2Uxpp0/.q9>O]f:3PF/HCM"zv׆j ݩM:MV +*f'*LCS54r{60;9`l#DHR$D+Dz$෭(8,J۞ǟʵkW 0ɸr{{p8yp2t~j_/8y@ȴ0 QJ@%F|Y l&oagYaJ=K8%~o%J=GdRYa ໖є  y 8\}ΠDY €h_d3ٕ{u. {`dnfN\zfZ :ynDػp}Ȧ4[Wޠ6f:S3/]P22ULdHٻ EY G#4pUS ` F'dg =eNV˨3.~rwq^—yyڝvH3F8q~ ibMu"d{`ll9 뉱Uw#nˣR^a*p1TDAPiwa[y "̳y SFFpP=\:"R%qp=HXvPL`B< TLsA{=z=LΠb40,rEqTQDc`V}Bd,w>2G=nRNF qպ Rr QoHcG%WVJ})+Aҋz/_kx0ꊴP=]"Hs0fsJ37Ȟyzֶ$epX0B+jD)*B~ ƺD+Š?3< ||Swh8 2W`;\ۋ [ad2>hP/R/:ƞeEuV@:L!4&jAw/$1n.]ޥLU* .35IhqLܖ}WY(1E5:i2?.-Pv.$MHIokC'q{ud{s`@1,zlom3Y/֚~Gs3 }al70{{lolR%B ƣmQ}ڏơ;/7 d N'1  xf.^E"H+DO {r^xAo%P`bxBr"C)۝%;,0LHCR LO 1I )bIog8aa Q:O2~ υ򔾾BDtl~h$+ClXD&Yq:D~B/&NJdzp2f*45t}m*Qd3$!N&VcHkM5ێG(;[U"Ek4J *IŒ \dH/9I(vBO]]t4~Af_ |s_`q2aX(Nl++AaYn?Jk%3sޚ&JS[HQXTdAaf8(+A >^ClOWڎFxNN$}7ݹBMMnpf~27իW9:&Й88=Ў@ZVCE3)1M{I6ͩ9zPNB:Oy_+…-%n05*5Ynr(|كAZ.K:ZmSedW,ezYO?aアl8Y֑ym"3TYШ7wnSN1  RJV:Rȼ%SIӜ @OR:/"л-cYj:Q( 4C8/D/}*EI"+kEn%*mJ3`ᖺ(ƿ5ɕ<.hg_j,Т܉ZbWС+6u?6$OIL||Ǐg<HRFwܨvNVdMI'5_a\z*40cuyS e)ѝ> Ù`tMYl|kOlppy-66\]71o `d/<ȽQ8?A}j[I{X g6`[#M{Jjl֬QjCf2yN&%րyzRt:u_AjkdQ[^cɿ3={g[j6JN1Z#@pDwzF.Xڳ}X]**)E?(V Uj7Ԇz<d&Q%qTzQ eQJEII$ 1Hb9$B8pHa=X^fgz c)E`Ӆp2&$ݛγ4GJ`񤣐,I!#I uEԄa;''Ϯq@.`"x0-/OK#x+gYڿ/;Xܷ믾mS|}ٿk.s;ᙯ?NosiZyY<~V8wefgxYYڷLQ z}Ǐ/2_Z\'5y-x5>%n\FciGt4uB%KGs ȤL KC% o, ,l䁈O3}߭;2V`2 USBD5n]D"Ǧv~Ez ~CuRi*M! ]`2(*R'4~iFH'mSud(81c I1{!v2Iva毣RP\mN Z3ikv $s9|^#%r|i3enVkf@sɱ[ ]L@(ӏ|[>reZNgb81k'PT2!lh;TIP 17>;񷒑$3 {aX>ew{1GV֮^F}> RwݩQ6/ #>떿V6~ s `&7憕RUF *(`O=_.(ÎQEz ;wMTN>5A2ODopģ~)2QΟGXUb-{1m "#MDɯrݏ!q]WtrsXw=}%ުS}|V`t/Su(n׮3`aVjZV>[C z=8pp) f}+}6oЍgxOSV:ӔEa7zCwswظxξ5ɍAvڶ ^B>d^k7~8BhM Bʜb{jM;µXYٗf^ꅋu4B*%d Ztl $ \>M a/{.\"ddD# 士|`T%>G! 0Qm`*J1/Tm}1r Lw+4%zGp Z9Ŋ s%9Q̰O|w÷g>2iVZSW*W xbޱƧO]>kcLT . c!}xg!%hKtfܰK+@)ޥEffg)F!qh<,~ʱU:6M`zt͉nsQoAah5k oT2[OCU:D@K]$|A^CL{2R,q"}a0" 0?{փϥp7(tJ\nUԸTh"&8'IiRD &$ xc}\YsB* I|~$xa41c`0l7,Xf4.Ҥ|DFѠI-nNWo0]ajvVqx^fx,fag{={@3ϲ[Ka8Po67^˸zNK,]́ ɦ*)~^N~X!MNMKq ޹[*Spߧ&}#H;vsDBZ(TH[;X,%BiE&3w-dy1q |1X^: *JjL|J_q*\ga\qdr7U`&jUΟQG)D@{3&q.:&wt25Gu@= oDflE)nnS3ioĈLɭ/Jr]ڲZh\Pߺέ8s4YHSQh\'\x)1<3L+d;^S5 zPѻ|?c =}BK CZ?Wo0,hicZԔsx81fyzm-H.ۣ1_ lc65բ̸qc<лc}GڜS<'/:N bPhܞff35a(;xǚ`6Hz,]23=-qce4E1bssQ1&خ>!3r x}w[YMl4PeIYdymrhz)cu3{hw}Dj_'r^d<./QƵ\yw7,/+XXa8h6ٻp=lom9u=ł=RiC=A6:Oރn"rC4=*lO{ZtU/c4i?OLLP&j022m/%D/g껕BN@b 2?ǽjddeRNM*+jeF_ 5i{PǠaB¸$1kll2W9yp//]hL]`R;᧛I z0$ҧIng*t5eb}b,>3╗a"`lRY}L& $6Cէ%=]gF,fU\x3ә#a9!4Mý >uz:kCyU4.!V; 3Ұ4#m{W@AecS_#)ߓ`^0xc OV _[[< 6IGۺNÃ|GeJS9gI/rId*iw5Z\KCmzoN-ɻsFd 3Aht`܇Gq7>fÉ.]NW6ϭMZ9(̬ cmcd ul4f9JnˮlK/u FYnh%:`iyYNOԚ eٞܟ>~xgיڳ.ЉeT5y$g?%Lw%}L}@ױ%͢ci~zӧOg-䊤6Z. FSjZѨs7yQsj(5 {}z[="ˑYF. -"z֡9^ d]J# }LHW><\Ԝ537.YI$a+ ef 瓺+c[:H-Af6魋A01Dv_'ieƬr:%sFQ) 73V w^~O%FsQ= i4[ +W3]ϠJdR0=5˫Ͻ@1cc,9޷23=ӳo"9N-v,GeCc"@#@'1 F(r@("Eqi٧{޻k}{s=}U=_" LvW꽻! ;5)i%>\8wkϭp dPZ_gcuSJ e 1T,^1֥,z|yB*Q#jkaHdbxoJF^̹H^DD~?iLcc?\Ax* oz/jsИYgf ,ک5c qG'AoƟ YSX)\RZBL4,˿'qAn =CR5A`;}>:kzZo<ߠ£^]ORqhp3Tcfh$-.f|2dhRkD"-0[OZKՀ,,!ZuDH3ֶY><ωZ\sk51ؒmlt)i<ЃFc&)ZLd\n_sUz 3,Tpؑ"MR27 &<胠 /0ui!4rAYAKÕLk7z`0&Aʐ%-0T`#ܦH`p)^!:[kF1ʔ%LS dRDǹphʩVɘ0(Hj=6n1el@$UγVz)= s .y"bDJa!nY1}(C i2jBr岋V#Rwuk&4-$E`@$\|<I^&1FVd4BkM`<!u +5k<%}Lg%{13 A&*%J%u*qR&ycME"B%!T%2<ܥrfN!L"!8`(Uo&Ȝ C!I42>7[5--tj3btek!駴 W98B.ܢ(Rg|@[p66Ćevw)}DV$0ذiOU;qsW$q*-8+>Lw@Uݻ+4Y\Y>]a%x730j[$Qbx歯“p<>sK)p!tFMwQˌ_* ]c;,*cݢ'zYҡ0sGr"_poS7{?EA f|R3ϝ;EG>ci}`z-q@?Ork IXimnU:껥Ji"*i)_ *SH5g0ޠ T0++v]RfqA{u`|-XΘRsПCZW !;dzk78}^VX젙 a8΅ 2P5ޛSTƐVZ^_5oςvf{`5[Wi4d**R9e >tݠD:s+4 ο=+cD`b _|[ $Ddc||5gv- 1D$aaV ⭷."$!`<p>U$.űy1soo͋Z &gYx81[8+V08]qRTn fՄD;BG^jqRe%b~䗚A1Ea;>tGxyy_fT;uhF~D$&uMG"J,Ͻ*]TH1"8iZD$h{V Lu^$Ǥ'P0RĽyT CYc\,cqUgwXY^/Z^̜Y垣xcNo|-L $+{&VGzx5^%xe.`Q܆ q PWA*i~͍Pdl+8\ghk4M~W_|7_z9csDFpa- xi:\-W_9oY'5.c"^$L03@owXJ ]߀ ?K)1 .>`5y K _ַ*HaXO=ő#G vQP꘽xW]D3w7Z')utюYF5y$^o?ljdw:IBZި4ך˼_3"l{8 VaKm!ɥM`VAe30XMsndN3n:] >yA}sa0^XFl}\Fi>|*;Iu/Q,;¾5ZGg3ZFMt d͂ƑeP`T}(l;[ߢ=C"0X&{Ax֚Blv1{5TZኩg % i јN}C|`leΎ1RPDy}-Ɍ&.SP2ҸH©ѡm^EH[& 1:/oPt^i5%:r2@qȂywbc"LT\9DM/:[86O"iXET*wID$'byccH3,sdgmܚ`BITt DLQbq=n{PescIcd`|dehA.QO3QDqi%v8Eϻc jO,z(%5,1*m5AA ϼ׵UK$dz\2xm'J+H,2Q F"腉uDz'O;҃0(]R?\ʚ+1r'{h;Mtד쮯0 -d:sfNk?|?ze'F]c9>ZDLg@{C6ag4NGމUC'֋[:ȁ:eѺIy},ɍ`S׋j$rؒY(j!V-dH(&/mRRnegwO( {%dحu^ Ӽ=~<+Kkl17`|s=EQTa\IeyY0W0pكea9aԛ73цiq[wcnѻM:5Fu ~ݿ!iį  e[)ԟva}d*$kzW_b:H{2dg2 )א>yg\BHy n 9LH87YzĀih0ie/sGX[]e4QZ`D>Sx*PB@jӧNTXߟƯ|߷ъ<# ex{@u; 2lG24Fy/L;LDb ,3V$ ̄A* @he#0~.uEl&b]W@ND}knM%)2a7[1l';~UёJW9cr׍(AJ"R`!:ߘEsHu-k,y;e4:KJe;63.6,wcnR&hUv&[sN, ow5d˄!D} " .\Et,!!( MǴlX zuTyhK RE"bӬiK =Y?, Q|En 6@d{(+,۝O%T=TfD@ոD{` hR3+7FE)&ƲRb}`E2:KH jD2 [HH=H+RH=c[\xolQ[y^oqF9Ȳ$H]Y5xd/)ip:Ƽ]̙L4wQ{||i._Q92I{Vzv0]ZV+$i@IŻ>}!s?ݜ3`괫J]nY\6+gFÍfSg7$]b KMG= kb mf䤷gÝ4cࢪQɡ@&M٧)jV_<}x@0J_xu_{gp+s3x_.]ʕUR2m7vr|#d<W}Y kjj`;47}9`u3&*n:ڝ}IB(tB20&1d\ij|5y5 `Ԡۦ ZnmB}N 4a9rk$/sMG9F'*yg΃w䏿RuZmοVy?e^d#~ jinoS[^&/q,$1]Ի4pK/ew31fLTc`$9)l WHU,xgX޷wMV7>L`OvwO!qQe HʆG~IRlZk\~<ZOS7y=ۡG! e趓K"mO ;}LQzݰj*CY'|Q0|4pIR:<(KJJ}V*m* ~"Р}K u%nn!I-R"oO=sCt  ?p+dRS_ 42(B*Lk`qKCf\<:Yu-U.jYVIf?PF﮴^Km4L˜J/Rkv"5}°,T=JB6nмN}qV;C-=+ "?@v.`0Cy?0Gd !C&Z*x*Clè 3O=B$o) oa&F(:Hy)1-e. sK|홗 I&/ $cia,͸瞻 RLpx<.eb\HV:<#?Ge!D#I.,/<;Ou-H`$҅.6Vt6q~ iY3^^(d HlHBA2F(& >ILEv\ug; ]m"H<)!X(+*SM:fov/R+4Qݴ>`vA1%ﺆXD_$m!qP6r?Ț)@m*\{(TFeʘMţ{uSzv]pvRE+eUc9'-ӒS63,| p Y& 13aDvycE~s$+) +ѱm._)fq)B߿X=qrr E)φZ҆%!\&µ U)HHu1!Bh[D]l|Ȉep݄NZDq4enAJDQbkHA;3L RI! ɰ~*²lorh}2 F,؅bhuo76sì?D@PT$Hd W)r73?˨ GIN7F>L}Y~#"I ū$j2 ;\TM2AڔhDYhѣG9tb+0AGw8A)t Em$M~0X9*AZ&]xMZy8~|2]"tNcG gGQ؛2D@z#w ږۡ_X5ewݡLA 3yi>LADh6\*)-嶄.#zyR/[YL]Ê'?*m{A-q4Xء5c'$M{)FFl=K("0R!WIי{%zu4|DkB)hu|s%X"/|hs›ug$SeBץs?+7^jcʛz"yZۥtpC!)it~WhgF`nM@B{bʴQA;hSNi(@/]rn{u4( HSW)7#D1QA_'%U)ﳾX] vޅCbg/A) LiI5j$i8{XbcWeOCUD:Y-, LxՁ3܎5s >lBDCLM kj$ !RA4,ށ^WkCQ\ԇrv"+/ bE[!rX*<% {t,{iɢa5UWe6S]I&u`ځkLEﳉHYJ,M!vy(I"_ jD:* }(m2q!]_bE&k13/wvR]nXkִDAGD?Ra*nQL7rʔ2c0*,Mbw,bo䗖1V+?O+X[ЊТ^cRfW.__׌#,] I?G7XZ9F t6q'1 tm~JntYΟǩ]zƠŰsZ#cH8`zVIޜs%8wֆp7|KѿM)~'Еɨ0ܾJkǨop0d:ڍ`20 $SLPJSXjL'ijHO87Ǘ9V׶/~FqsݴVDcJrLCh0Ldq -ˬLp#"aeŠ6& n aCnN",{)}m1) zтVx R+A.(CG :g€z4S-e20E(SpC:HKE@ f,'#! WDJF HET{}hNu4DP"b,QJ,ߖLi[(Q*%\m-Mڗ$BIC"t`2-jMVV?嵔ΐf&ISYdjϊ ’g ] 0F~yz[d, [ڛX7fEŚ;v)0ϺnlGq{*%lW p;7)Wc?07Pj6-XHdcχ򘜊Ne9a)NPF 3lrɦBp|Cwe'EI+^fܱ)/QwOkmmW_}%޶!O,[{=A[QeAɒͲ1s$kp~A "8g_jM~&̝L>z7 Ks-Ts& SP'7 ~_R0QEHKM G]vD@΍_e_!kEZ,D(32 Izwh1꿉,!hU#!9 h5s#~dȊ-nzWR=^*)d]Tjlj$"V۸:(m{+l)f%g*Á8lR-/<'Y2_Kees i̱>H< d3׮FJ~JK ];Ṭ"jyxD9XNjǘńѾ'UFŰ|@ |+5/hlM%T == hWY`P< e7T:LScKT k*&f3au &!GI jhzۗ䌯iqTQ.E;`'@&))rkm~?Ǐ^/h!29_; $(0IRÍ4>(f2W./ɏ(RDf[I1(S̨_O߃Nd5Xo3nto9kؗ/bM6Z!nNlO~_\jqioZ$"OhG0z?shLqLȖv2&.p^G1<^|DœW5iEvt/2ČjvOo8@m)W^ŗK EZK0XqVG肳G`GiEY $( chZ9syOE>z~˵kk;L-c{eTrTDYK$AzyC %cF{~5FZ(p ҮJ]-pZL<é|1)͠D d3112z9SvQD>9b_Бo% *P_F[ƒا%bX^8&N[{?DزlAsxqOE^FlCm]AT,?3kCRa*Q;tDJ8VF { #$*񊮘].rlAlk\Tic,C$Q r %|sU*bWcх\yl+_RxFHTvxoee}&0ne:&0B9pRcLa]#_-ڃ{8ǑY#}ϙݫ6DdˠD@a{ *e|"ZX(9V(%-;9"_"܆><g L޻RvDK:Z*f(L! j3yQ3vnŪ"5D@^X9\)Ưc=O7^0-33=KR$”w;L`E ׏D zں5Yr-lTdBESM6U)M9Rus#RH T&'^*?in/JԲ}û*$fk"uqb{c/p}{y߫UGf5PL IiCL>ZнA2gpyMSl{ M-gLGhLcޜr#49=.[F=9;S6)zVkY*zt=O7X~ 2_0:F}Na-j+מE6謜!_>=0J"4=P /\gtk S̓:t?WxA.nF9*'K3ڝwh2ҞNdRB1Zh;uNg\I iVGEtP`Mv< [SCi(b6A*!څ4H{qw.4CU– !BNnPZt]DZdnkco"6[OZ(hF@dVB  >wI+M q̅m0&i˫CYa+eC@ZI CE#L[p5ȜP*{@f, "x|S)g.Uʶ5UGb@S%5.Z$ljrMr`mQ& Ou4QUcECrtߪr$ḣE[lW)SdRz03Kh22L<`p_zXP9eAaV$]o}/Kbo*GZN6fp'+SBij&t"U?f$q0!"Rqu_A'і$Țq/L)# Rb<;c #}.FоSȕaaבJSa4E-:Gkqk+ѪIDVf=0e*ϣIY<{f!3SDn tXT5vXqP4ֻ)xWZhmZ3XNW5ET|/THSGo.4aBX`[A%WȒc$a-QbGNIPϲxis c~}WXZX9r GV"/ 2߲KyԳDS'Y^^bS\,lp%^=?4ٿgllO-KzCKV~ڃBe;Ral56,>N-XV+iz)$Ȓ3K/ QO9]2M<$#n"A5cϊHB _AYo0Bխ,Xdf&OM,;qTVq*+֑F4) E(z!">BxeJ q6J &"\B7>P—W奼TR:/I6THS0h(CP(ǘX:X2h IURX5pcQJuUzYJ# 2:j8?g*k@.7*(%L jy85\^R9FcLB`RV"gcz`0\eyy#鰹5a2i5/'Hl".Qx kVAL ЙIfhp[\5wK'k\$w3LJ )&vm='v%΢[uY):.zZ0TTxv^SY)Dt C^ΰsz=;`ogMCa8T(!$[[|077NwK}1 ebyS^E9RJ:~M?OMTCd "-G\$ 'uoSG8|h;0ݥIZUNu|p&9r-1Iã:;;>S'۬9;ܠe "2g煿ddhM287~O)H:Fd9AF/zO@4&b IDATFS#Ǩ-`fj~1QdedɄ:f4Po(MQPHYZj ?3ui]ǜ>s|Wˋ`he & ߹f|EEweMJEc -M@(\PU5 d8%m}K U"ܶ?󔇉uUOR)"").(&n |S]`C,~7C8(j, ͨ>"t#=7N BL""0`~WRlejΫ{~*A{ĸ:I<)J*iXN,JԞ% ɱ5u\*((ńA*.s'Llb+t.ewL7FSe;̈́Cð-d^Gx??W#QJ6(;dJ/TZyiY(c]д?||//Ly.{Phh&. 0e@]!Q4^))_Aa ZIa3&ghL|II&]/.27 $Fl<**\1n hYǽ0t dލ=z3{ Gar5g~_AL}A&ߣy>䁣ۊB{Yk|SBgY8\ڝy;{dꇶnϰ'2uLJDZG(F4ksޟ-0h 2+kuF._Ha복rG,Z|ߍHxu PjH6!mMq,,bq`b$2Xm2t`XF-~I`˭,ud-i dKVeBm;&0(څFUs3!PYOaUV츰~cBK XRL ST{)~ޥ˵t]ׄ˄ R-FP hؔ~'KD!0!dfs}N{Emɭ[})h6P1$'59D˳1QZ"X1+%z fq:Vincdͥ1Lӌp(?kf2gUǛ̄ؾM1~gKϱf$\,2t8 (ceN.P][0yH*| ֵaCi)"V_z4Mrlo''g<lxbc,x6!5XvnY7?~n͛&#똹}Q,H}j$msܹDG\(2jsKu.%Y+9CK m9z`e )g~(X9!k ƈ~ -jr̚L&7 8r7"OI2fGaatz]8I( tɇ/g͂-Zk=@ t7@ RX$hQ&ʒPVD8TU*N+RrQr$ۊhE%EH# bhhts=k}ykM? z}d' kq7e̼?Mw֗_ax,/կ\m >&Y`kwnp1n9u3oшia{k*cI+ Qszq7VKmpG,l9rͬ׾ֈ DrB %I/=tvHѶP#4Tn""+e9cđ*M{[ZS*vB#} KQ1݄ؓ+Vu˵U&Ę\2.M*FAF S$U[ 3=r$IwK#i#eVfMtf^ Pom<"S0H4Pف!$)K(|ҩ.Hʠ]@v{<\d Z 3,2x)t0ґ)lq&kv.-=})HKXуԩ)3yNMBkThʾMFaKJBjk,'X %ՐVu hB-eLC<:FrX؛zKopVCvgS|S3ɤ^}7)EL.DN0z u6lOWJm؏~|ט x0ad?Cz4+?@rzgfOcfkkE9֗Z„ G0Nllsg1wF 3gjqiMC㌰{szMd^s3yLŶ*BT(6JԠ#;SmNc:olL[ dbj񴊕 K0rBY׆HrdTܺu*|W2W2!NK3?cU/Q:rRo%M({/%ZP;е0-b<(kr -܉r(59`"CN89ɌAsݭdЀ,$b[E#^l~7p MZpY],M!Eg1)%I6gl,C?xӝ뜿(簽^51l&e&nOYX35UǼYKTTP0g] V= T# 5-X%Ϣd_woKuhϤkwGjכ/ƅK1ix^N&{):w+<8{ex1mng:8M7w}>X1?=orN6_| #6_ɔMǽ0ܤo:{&s ]f4S\~2iLop{0YuH_^`.`p4ӷ^Adi:dƯ.U|'xkm텴2> ,,]wc{gt:%dxJS ~$̘s@*~5z=T:Ҁ+o]S|_ _}=D!JH\$z;,香v>D6N20l Lv RK{N5DhCKNyh.ÏKOmM7)jR#ɣ*/􄔤\8(TՐ mp7tQؘbǓT%BI$#1M`6cjh,񾔇{ yZ$8;/B`.AR][hmI4ocl!'Ƈ"J "&~8  Ԁ$1yvC ֩$}VG)ʪt~6Ja.*&n+ԚAB+4XzqmP DPh4e1RdgA'l.@7{M;54S|~ǥU0àI_<{>Z~C-rOd,x, $V-C+Ca慁XOAg .j[S)hC *ԥ=pfܠ39bof4ʐkkphC6w1a8pS38bւXf1SՇ[\wx5Hoۯ؟R* oM\/x،Sl3x`*Λ݀@-8BP7JVL$fOm(7}H.A i [s),9]d+U5 AL~IrAĪxH+|?0߷'x흝aRl]rOOp]w12K.f?u 2^G]:&{Suͤ2v&o8R7^!,z'y/aBG̛_?]/̋ :%Lz4O09J+9LwO}) ^]>ss6y}>EovӫO`"w7 [O>y@=}k/ X;3L^z_b̃:шQG7hzx]x16?µ9aL=j{0F8y$OқPag4f:B[Z7MBMU wq奷5Sot|Ao|)768|Z"H8'Gᔨ mJ .JB{v| !v=aɶQCXuSG yio4ȉboEY%orx#@? SN5’T'/kƖdYyx/ƨpcԹmZBbXX!qsLݫ찱ڑ%](3=I [^gRyv1aׁ]ϡٗZd0 >?zzǎ6p7.}'@ܣM,isc?낽}Z]}PrPcW|E0))f\9ư^ #8lǴ6YE(C},-->tbՕEui>0~@(cP5׷],fwrDVҟiFR/?E^z .]Lw\7v4bAv!43|kN3tTy?~ ;U3e[o~Oӌי|gh.*1\w>owWp9~v;ec9x=lٛߦ韺p]<7c@,=n4åu׻pְ~Mxovf5M3Fz;s` X++8W/or{!4vm2h+|2 >>ri&2KN.A#O:"?i`oABˌAYd '!Eu$wdDyJl02)O +&RCAZ`U":W-ltMYPk\Ԙ0$̌jie(Jv5>zϻk '<3Ђ@S%\qiٴ)8VŰbZ?C^:E5-P,eGۡOcPl~()cǞA2RȽa{TbҴ5$wҦKE]Y'swiαw[/ }&I`ԭx3˧aBs$i}ZW=-`PkF0NEb(yp+տŊq[Į`;\nQ~ Y1lsmz Wxi.0_ap3xOs?4Gع53̀G\?sM votaYZ7, T4*ncޙ;}I>7=J\ctOY~Wϟgoboq l^I1yXTKµo<ù<;oW-b`-~޷݉ؼ~o?@p IDAT}a~?|Mg̜<%fdqm%zD ^\i,`0u 530Q A8$I+)]*moQ"#<:raL?Qcf#IW@ˬf~tetR3vk>|+p>UeTpYpj1b^HM/*9U8F%/>Hn- g"h]Pgbƿ| PZč) }[0) Tef{`ե%C3M ZuSciAeVԈYp Ix=8wx8`9ٛw1Mx"kGkj3?_,+FX2Bq&Lb1N0L8A^I鷯saW'0HjNJФv~P kLo4|d+fU"<ݴJKrY#|}?[̨@]/7VʀKP0&IUU1;̢Y@QΏ|0wߧ?1M:s&{Cgw: Ϭ  Vg#X9;E;Y 1xn"VN3?WA;a}[zU{Í8Q `p^w֙]1KCYczÏIUڡ ~hپ9f?f?nܭWdn) wڳ_fz4\k|% c2#mG Nbcc7߼HBxBF;'@8r~-66h x׹3>|myݴ?d'8o:7>O^ 5y뷒qJaEl0eY(3-fn o cP JeqbKw'1~DO=x y)QT_Q%iY\CiZ-B<{bc)^CYL7>wAcEF)qؕ\J@M.Rv~#$KhSxHӤe9Q8}(B͝^QqRR\%yp[N}AyE3^ɧtR,)Ci%ҳŔkCXd>a}<,;`{֥Km16oBӰ>}l م4$=-$id>٨fM/`g OSxk,{ɋ 1v*1&Lw5 Cm<_4gn{az'>+\ǹw5Oѿ,Qn1{W3slo{_zmn1뜋mVCpÛ?K'@eS\%/&=w6.?d)#K{saa勘8}~u,oyS- 1uӰʰgY01 c`>t2a_G9aeǠg{޶׎0.`_xg <{+qTbڛ +m}( oJf]@@x1s]eT2@mYБ%2*J-V)Xߕ44iEA.^O)[1E:*veX/>ό#Р!62*iMDXa1.WuG%&$ue?f[vhIIٸ5k=f$Diu=ӤRhT:f̰dgU@V[5;Mвacya<d=ak΅f'.}F剹=SɩF5 Ӹp,*{}=XZN/լ1aU&fε5׀ThQQݿ( }$n$ML 1b% D/KX:,7f3}җ˗1ۙL&zw UK]H8(i?O*}4MC?/J5==C-UXQ h@8rLjݏ[ϡP]g^G~m˝C.8|qWԁoݫ׿{ӝO_`#s,? `:c*枎v9'J0=&٥ wauzwQg=Ek.-al`dflo#f?Ke=zpn8Vpi_e51^=jVW8yۙffM'Sv pV%v:7߼M z}Ν=v^|CxBf9q+ .rC{OCdDlF({IV)qЁT舉/m7BOQu$'R -LNHL:S>C Ǩ[mr]k_Rg8Ӓ-eKm?c{؜\ähˮS]%V!rJyMTwLӦ4PЄlHH4u |^5,s50.Vu *\5~oC92`osqj!ctցzh|hBh/",Zicgelpr`q'Y\Z=X3s3MmkZX1Bw{M ,~S\xzi EJ:$uŖרw|i`sk0PR"QBV%QU76':qA-E7L0=j~`,M >t6%c>V'e' y{Q*E5\ J4Lu=ZxKsω[[OUyJ7G6noMƸY_g?b)\b#|*|s&>'ac2~Ao2uM^\czzC!cz8?[?BUM_Ȼ"5isGނ ?Gcϕij(zJLi|ɱ*bhSJ[Y[_қ!0=׮]c:׷xvXZ);~z񾡙'GŋO/}1ϴ[&Jͬ1.4CzBR` j܂MYNj-2<MRmrdTV/./Хm} 6KLp=1R>1M> R(N_^!3!! UN,2,[Jf ֓(.#=iSA:Di^| as/YhS?sdvn(Id,[X&X2hQ,:?כ$Pg]R@AX$V:!&{MnY\F6 h\$T`e0j(=b+/PlgFPOȡ9/($BWtiDKAUߢwbCEh\;JKzbbay[(BNY޿8O*rDP_GfKk+JY:nS:V%uR$u@-Z8ܓ܍B8Glk/̽b<E'Ó@tIM,c:+ o6UXe>zϝK灥ь4BU9Uu7`c:"eX:}ӳ[%Gϟf|:c4k%i WLRL!ϲ*}2;_"GS!7_؉+ɬ}txe&C#W"6)_o*>s}I^J-!yzxK~vm9f妹7O|e_ݲnL +&OȊJ$cww:-?sV.A0^Ŋg6\~#.Տws)VU`T+q#YY, LfڵU`9?X%҂&$|SQ)r#_SOܾz!>^c_{9*iZU?{GBhXZZº{.Dd s0SOaxs۱OUEBs~57O_~OG?p(Թ8xQ}y()2jt$"n1N,dɩ!Z-B s/aGGJXIYiKC[Xx候$pfJ]Ί)%PW?RhLriaw) AR*k=8kDB$l*R=܍X^%̏})pƩ#RD7 ;5 BυTn6wudxHOÕ:I5 TeVL6XTsȉQ93s 3/]L)Ґ墨"&׉3.w$%.0.j\FYQ흎DTZ-qp˲tދ鼇 C"k&bS#nrM2c%&R\O2Z l¡ %6̃aIH4F$ĉ- PQ2 [h756Bk:MoMN~Zצ@"k͜{^z_|ݮ -kӦX:.U!o4\y*ͦeLd]dYAPZ<"(M/2'}/{OElqlt:Cu'X:y{85\oOYz!uIуQ>XĴ*Ojjf`F̛ݷWUB( { ޳յp@NZMVWVx5οk uLLsVVVYYYfee)KL30^UaDxu?cu0XZ殻x{^k$fM U[o?p~%q' 4(vPB> Qgڈ]LWL%iݖP" e趚ʕ - &I7^%K`rENBt)?hK#Ȣ|!BIpԾYc1T L4JKǥhϬ$"_ 1j$c. Z\EfpnG,ǔ(2'Ml ޕI"U2_0mLZF! ,a+"_ (^̐+B/g:GM"AVuyCD KZV/гi:p1 UwO:kq!lS[P,SeI $9x{0Qe´"]&W ~i Xz~ʖ&7B$wC꠰vi:uiXr7QcG<Ob# ҃ˎ~,~.TRG)OT]=g KCAݢ΂m_j>0@wT83Rֲ+LM[S^#Ӹ%g/N.)! )S?]=$-n@P|hJLAӝk~I9 $)h%~5ARr y*53}I2,}sYiJF@w710Y$w)2/,,*"A0=_ pBBHJIQ+YN4o;c)ұ4Z]H D TONJ j849DEЩ~7zHlȷbϝ:FW]hUL$쓗&b ¸z?/r@,ҡөH2 >#z.OI%pF ^(rb,:CY=1!'. ڠ  IDAT};ҋP}PrYmvE1BK2e)g޲Sa{%Il;,f\ C'G.Soia& FڮvjFSё Z|Кg ϠGK ?;B޷'&%D쒲J(4 dɻQ>[YH\TR9}RNokU~/OU)Ͼ2'o:c ^;x4`7/}VHΡvc"EJb NYY؃v0n IEN2 Jf͒<- bQRz$,f p$BzKE,Z@!OC6)C8m8S1^GJإ,DY  @ڠ:LכP8YH !3yCk:i 26ʅ\{(!$Ā 15+G mQ$Fy 9hKu{-A/ʑ}\Z {\ߛYeI Xy7!og-iD5ܭBR\)}xXXTM0_"- Y˙Nąb2U zuLJu\1#9\q (tOJ#ZB%jɾ܇b؎GtΘokD5̃,p8KDô,A:,⠤R#!nj1a 3D:yhO`PxQ&d2י/ʈ B.&ª`B!":Lk oM ώ-gtsUhF\F`NDӟ{t~hݶ@Y|5Œ"w foXKGQ8P{/m!r\ǥÂ$E!qSN\F[ss^0= !oaeu^8s4.ix p1ds졇 זbpՐ4~ƿ3wŏ'?a2x~E5( { %JLH8s6Gm1Y 4ID *$ i 48a6[ HI'Y64ۗ$rN7\àƶWvӦ|F+ gct}SX (/ ~9;2CǢM,޽t<\L$A1>ARxa:u0 $zGs/ݽ|NLղ $@SQ\%}-n].O׌tS!XlaaKcƥD*&G9JǢf\SЈ1+%4Y){c:ԩ_(Y7y 준CϣّV% Zg͠-\pj!ST0}\ +3k0_+g+i:@GaNEy`yhu !P$9)隒@m ¸i圕+ ̕Tr~0PU &xuKy *LY ̍0 HЁh cԙ J{5`U9 he}S>c?̙Y@1RvpS*Z YR{?ڧ2$iB\d Z, ~p{\٢mǵ)al>=ɽ&#YXĘM3] z ~.]zg*ux}_pI7$JLb4 _R4ӥFI??~yC<7tkkko2@\,/};]+r#z=zy1̄Nʁ Q%?V]x,zlfYR+p~JlT:h 9t ˢM~i*rk4 Y E͕%is?/b*soN!]X\eh+L,9$E?vcmX4XKL,?$<` mg 0VZO0SNlT"u'3VfCk1K-ja+͟ Zm WFdͦWNQ˂[o3jzt>}hf[Q% Dt6]5JL,7 5mepl/sW#_֘L^'-TBGGZ\W]RZtD;`{? k M]g\=>LҬy- 7953%LXq% i fI,wQG}ԾŦi:-^+Z1~Lr[ȼ|?I.-iZ26 iH&{OX__gk:}+<\ʵ-fW8rV9z|XkL>tpsw u  3lol>[o]Б8瞻:r*3bҝag4i>h:O=>PGN4[`LbQJCMrж0{H Plo!j- b%`M煀H${׈LK.߯# -{5Xoc>ߓ >oQy˻+J9bgȠA_[St דWW6Ҵ|P=-Q,8!c[g)1dBA {QbXiPL V鼖 2@ZgP}./m?!6vD-5Xq6~Ɗ%1EQ&cҕ-VQ,MCZbԦVj .G  +N!.&t)d&]v9SaQ>g0rdОMI&Fը/pn~s6\ޠG߃ d+UK0i3&9ydV3؝ٛ؛NF{9Mۛ7M/tu|EiVVYZZ_gqQy,08r(gUV?/1߼$|>emm sgf2Ù5쎶q?Np˱uXFX_yDѫz7L~>ˏmo7ͼHy_X[][|m NWgyHR&К%]i7ˤ{ JjZr4Tm(iD,dY_Ƃk\AMR2PRb|b72U_mQrIRЛ{t{F>#v0C)d-;5Q(L <3fcTA8t:$tYS0ٙI2iS cFa']uF7yoJpu9m*!#+A,IzE \>F,,-bB>߄TR8uqt:UA4;Tµ<,lG-SYqѨ ~R'I/%ěgܫ4Ddƶ̦ ZuPR}rNd5!E.(JR.fJ3h-~;~TVK߶޼%mCP-‘EY=*%-tO [Ws%}\c&;e0Zfݰ‚u lyk_a`&_RF눴ACYQn]~8\8LgM6qlˀSNFK](t:U4iI탈-/T_碨k,"Lŕ)YvR5T{lxA-r:KQ :\_yŗݚd C]Y_[lt?JjbU^cjo1%:jy}ӝ۫`}:?0ڝ3fw2e23d>g:Mg̚6n3cړ~慹Qfڛ<`+5b- k{Ag3y6{䮛wOrׯo\a-Y[ O=~?NG3awIUx__zv0"L~4UUq-lꫯ~oo-)=_6w̭7s/%c-ހI3c3|?l^oqbeml Be&%v˥Bs ))Ηg!&qеA*,Ʋ<sVef[Ud7siRHdSh$ah4/8 `A5-A X#KCHHі8Zfz_z=כw9D~?8O"ͮ{o$H ($,6)J5æ`0r]LQD-h I@.$\2Ikr5wil$D Jҷc ͘$ep ̂j&cvj.7 ʋ#gΪK՛G]eB<3z4UP\qAI 2^A豩)Ǚ\4]CnY7êaHF\R<و&9 4;m D4ɧFuX5pR&ZdzΉ*Ez(WVF5YFIS}`Utd*b Q,Kb0A![N%r,"k'ł?ZSs憲j3 +jub+#` ߣ)'S2w Tؙ82dA׳ v.9&:hbb'!JĢ k`Cb"")x`xXvBku "ݘДY}{Js/ tJk/w 4 ք 'G4&&p_@ g-DٗLt>'e+TMp {@yau ~?.̉dQMG>?Of)}Lu4=)VMQx`\= b:.]d YI+a# FUkuѠƠ`u0p8h4pX j ZHY#d5g]>~% _7 #/^|K8z۝O&;p mqmeMEe|;ئԴ-laei ~^xߡmpv&}NB`PYx%Tuj?  0Hm5 s&xE=ZL\2D2LƣSMр#!l@;l ϮP4e-'Tiʓ<`LzEtZW<\%$jmkZ)ub1ʘ&VB@CGm|8i}KscsJ|J'H%K_d+qHl{}?Jmeh!܌LETлd{p#HSy՗0 喛YAʱg!nн;B$uB6TF@1kc M%)FNqw\D>j(xiP)A$J_ X5X^;:ajLBH/ק!VƐ.?_oA<2Z!;Ztk3)/REYqM"VC)- KGYPB{<O❙w+gכ.OSڦKa\H\]53TSQX:"L"x*T7.\k;hԣ'h&t…ިOǏ{@6c4evF(z}@!]y ^{ T04NY3/@DALBߴ &u]4q1:mib4tgS9kرcL&&{VBV@U'_x {u<;E 0\XD=h8ufˣa0[ 0T kQ[ MRķ0YL] J$nR{tùV\/z.g0v?ǯo.O=pa$izlDl<,ߞX9ChdR5u< v" V(k3*tƬ\O"|@}YFS&( aM{Ϧ3߭y&4zɔ3Ǡ(( ΌVJ!ͶLm8+Lq:"pj,|pG=71 |X\Œ2fDi^뢤ii]IQ'µkؚ&} vƷ"B3 7ƸOciTcyeM;Ul]sO| {7⎟}מ9] `17:F!.\޹m|[;cǰ'횗 % C$ݓ*c贃dyE 4xGbq”ÿQAQ]t[.0!6}rc2 UOQEZh$8&`a_mcDz%+ gAs5r$NR dJgr" 튉HU(W\̍Eϖ.TAP26h^#)!j:{g,ʘ }[Q >\B $ MgP%izfXPJq Xd:)ȹH[Xos줙J?ƀԻK:6$IDDDE!]kU*ES .ġ}vL  E -ձ$:BHC@lz$茌hjݑM3Y&$e)djNG" V7uR [dGr^RAY¾`òeA !M\BU른jQ,q [K>uA2B9w z4S̹Jmxel[X:,U=j 2`T ]Ƶ >Eߨ[Q4&j y/96~:; S[`Tm9g߹i{W\Fgf% ZvfV| E3u֗RS]|җs h.L SIs&~g‰0`Fc .]w}]Up$cd"\P6*0 }[UGݟ !ƒ>NP_=4?zGޅ_/ дElA} pC5S*^V.#LDAk5=3tYJmX*ЪPCǿz /bs 2z>|W;?#qK'1{2L5u= GC\8m`:k;.8PZ̺0p`a G>W+#4vu΀<9`au ?31n] P0۲32cwޤ`>2bԡلiTu`̠]thHbYLeca%S2ı̛JEѴD8]ŝVtE22p96 'QTF I#lx.l%w4&M#AHMJ=ZrHt`>7q^*<,v FS(;*Ec: 3|6y'i@W|Iϔ~MÇy[̈́(I؛KfL#S{L k,HN|jMPj+2MұB*lY1Kڜ0pZE$ BUl4ye 179vC=ZSBIX*i jVw&z((SF4 4~&RLSQh*,n !G)|x8X2m[f[Jk^ u {a)s=HED}3fcQZMI˨ucA09t^S-ZVQ\gEDO6Pi%U" y葘/7A ,"B1NHG7,cfdƁze.,%L*# |OSik~ֺ]#߄r8M ?0}x7Xh[3k;%m[:7n_(!'p0@](59)ހ.~v;lJ.cQ E{﹈[1hkxzpg1ٟbo<hgl 501Qs`PhɮZ-뙑p#GmԁŢ0q+]|]isuDG#sBLk1㩧G;mpGzN7jC:H{a}[>H $ePNɜzs6gM=& *R`uɲ+ShPLtL2 @:"1ˤW f b X92du>XE]?^FWYdB>ʺjKo|(QEtqYVD{5Bmr5#kP&zhxYr 9,Zj۝ćaڌ0$``ə:I{` =a!nu! zsGwr+c6(W|$ h[0"0џ|rY.3j2H̿rqccK6 !t̸m?l0wLJk@($*}Vem %z#$7.bNdK΄7G鳗ϱ4ΩCV%ӥXYE$JnZ5JKK$h俌bu:ިRѼz2_84b.4°(Ig PMƁ +_n9VF) A`R4Y=2 6[cdž=i94LS + &8T1_9p!̜H1C8àKO<]^QCv ,;UN%vQS6?`ܶ=c,:!g,#EqYzL"(R~5kBO^4?zYT<;,Lsdiww9z*&.R< 0(jbXq՗2?o/+,~f8S V1}MM`>Z޳i0a*\x& flڶii{;/G1u~ZR{b6k} 0Nq U8[lmRP8 Y >lZl/3Etd[ 'ԜHkr ?4Dbil/t-fBI2bc{FgUZEeCGQ{'.H17gVJUfw`_g$ 0*[ ~`*ԔInb=ՓHK p8xiYtFSl`Dh& Қ^G6u(V"B~_ϚISMNY§1Bt2H='qD *ؿw P牺z3HEԐr  /L DԜjWlb` A 9Mk&!y_EgP;KWD_Meld jD/《Tc71MqJ.l 2u<7%4,,U {˟3J2i1gTS뀽6ڨak,ׄ)O> 䳶 k?6`DX0 g|>ߕ))ٽ)J!1~&"ܣʜFr]s`s%!>ŏe q_d* [xkJ/[\i"]55k)Ƚ`*dnve&ˍ2V iJ7nH)B(ҢQTmbhGp*?4?g};{lE& N8W Oc|mI`IORTSQ)"rM\)q{ zrX$P505]/4v& !/Z&mA{ m&ZgbGÕ2EnNJRڙ\zR"~"#^W(ui@¤4Rn##(T gkgWڔ[-|ϰl䕿?Ί*iVS)Wrl%簚td$D\tgڶT)c$SGX![BGә$ 0A(8xe7xB*h: 3ϘYCv7hF*NcPϾ`I02L:, ^5:0(]GHhşFW*P~2RJN)M9 6.FPn;ӫ;JEFP @ ޑs~U|9ipcdJFrPPQbupb~HkA[0!|_9<FM@v~wq;[XX&cqm73A'޼=K98& -wsjX9r\tI0+wqi ={]TزkITCĆqcɓ``<,9XUH15#Y/E`Lar}m]I6pW_j7u7Gj.{Cwh)wXmd*,XƵ[lÇQ 9r}`d2]w_ɓsϠ?qTtwe'VfӁcq05trpM !f+@etx$dbѓARPL(,B.s-U(| ))A2PM <بu)bMQv؊B%B%T@{ST`S!`aP"#Q=L&%Ec>Kc/Yx`|,MF&칅ab@6OB%|.!,Ңdt@!5XDK4;ftQD= Xp}L--\^B_"FJ)qQ"Fi'&?0p߸wFOYE}N6vo5 c{:-;^(shkdM IDAT"& 'SMh9q`׫0xsps.\0 pBiv"%M-Yf .6 5.S' C^,5 fJgk(p_hqцiZ@Y/tB(7 SvTEER2I0xa.%4HO^eb̀2K%:O#`zd^ 8I)?IdBFV9*htIoHjhn [F$'2Q RʜYߖ^WNZ%{?K'`4IQAeX)^WR{*Q_4:`nnVPPY!5\9*,2@lSC c8TcQGm=*{#D.rSZOp0XgRv9i!!<6`v@~ùzKh=(9`7 y1$Kӧg+H3ggՂ=ӗ6F# HG]U8vz8M6Ƶs^(bA4h/^Ҳ 04umq=Nch%,@REC?YS̺R; ^N nuSSܼWWZ >M&F^:885 05눲q!1˞RH}knO#-ttV:P;f6m{'C1$IML/+d5YnIVTSGlza(RULF? ںz@R-@jK˝IUZHVQh8vTWdPۀ{ޯ1EԤQeDK'gu: &`z b`=fbcm1c%|hL[P̨Y&E`EgF u_<ÌDҁ]ϩ"ڭiT zV9?4>{>Cpy7  F69tc8f .2z2%8&{Dʽٚ%e<4ۂR2?t:s?iV6-O} OΎ C\t L&M%!YLR@(BfzNZ.0ev蛼t9vD R膸ÂM3>Ĕ`k"u,+քI"s|ҁiU)]hn.x3hgnMpE4.”:PQXSq$-"^iV5ZE aB2KdD3dv$f3)|%+@QiIvt)v%kZYu#L/wPfʨA&\LVg҉).+|ݩ^Lh+4WX ,0"o2gƩ gcrNJN0r`h V?]gj V]ClX1hbQ2rR1&rv]^3EāQ~iu:-ZVFE оptf֠cB$@XFޠu0U.$ kN̏I--`>CGGMdr${O[#b2˝,G|mI0*߱s; 03.!&.dRk24u[I>@DͤBXP|%dMo+_E5R/x6p>O E4ڶ3cmphEplMw~{^KKKx1 _5;{}{ **T6ܮ`0ĭ[0(ucwgu]cccŔe6 hUޱ\>ec9:҅Ё",S/kbj6Uj?(d2 GLxXEEqc>'`sw_sȄcZ^|ؙq㭫X_4yi`lo;X^^O݂ |&ϟtlboww-y70Cy{}_z0@yX(7]Õ+{qxAqASZUE>] >}J^,z50NS[\~T'aRDhFf˥hZ)4KQ*ڝ/mW3 ĉahCF,5G9$کiAD@X:DMX璜#}.L|{ et(Ǟs1e~~3 ._-Ktꁍ?BMJtM^!sZPD559!3O;f4JS,!rru=uأWA"8\ Qum)RLFWFQ*QtW w#CCHe ,5qPyYj\H&A|ώϕφG1346~{>!/kZ }::`21=ZG0 c";Of()$M@m xზ1:h9'[%cV+2c~rwQ4|1!!kHExqb#_n7z Had "L(jM {e~KJD4ގBù{Lب{2yf}h> UWɨo2@& 訐Ę!:''g{Q2h?דOVZ,ciq o ?2Z 7]TU=FW'o` p"Dinޥ'l8@*6jl5!"CE1B%LXƃdS Bp@5u!: 1ǩh3dSן <^η17wq~KˋX<õh.@`0Nq$OӧyH6&S=H 1ޣaD>c@ @06Z;~d,YB1Lp._>"oB MPڜ0H$gӛ} GdRyE"P%Oz e$P{Afp̅yXQ }ᶦQ8⤯3E)${Fb"w/+]f^qe!ff8?&+6hʎD o6o]L((QiR3 !BB[>giR̽Bֲ#i#JEF=# fs˩pnf)/\ЂiGO39VMxJ=\Lp6lrŀa @0$"Ajvr "m\D[ e@25a#;R^&eWW,$J9SA\>]\.0'Dd=}O>10 KTF3]>CU5ʥdPMPl."h{bfV4{1rNT88A)#Y4i-KrvZh tb8<YsmѨhf}\cGl8m 6a<'>tLɂ s9Q NTXuqQ0mdV,Y0,ZmL,X1] 9G΅<捔G(J[rY$BcTLڵ>JI2]FKጔ R--Z.{BTW,˩| e%N&$qd s4Z1|( ړxPf0$q9H Td$ɔV`T_ bXk/O".92eC:e$,n$HOjA@X!a9eY/$0UBU :^B4r=F5d)84f{@^FA;;1!9KZ/a46Q3]i6R[?IUPi3wV{eL3=5F뵥q@1u*> jl%JFӆ*P}StP.i%Ƭ euQ9: g)9͊z]ɮܑRzV.='<,ė~MLZ@j`!>]Y 1 c'v߾1NYa=S7d3`W11e1Yk7އem  Gc~mÕ lH@m=&F>w(|2IHw**}4Iq3 Xf7J@QA!D ?%߱'1P6A'8u1V|92Dz2|}(޽vnw{>q7qasC-b6GyTf)׏c*;07h{9&M׆PCÇ}sBP[gN]w| oJ]+cS^+Q8I D1&dl^a-螽 %̣BEI$oGʲR T/FFrNܡ 3fga(]eY,Ѝ)vqm#Tŭ4u=sP6ŨJ罥 *(N (Al(3DM2fF'N JгԈTy̸DBґG=7[ppC%Me `&*gIQ".-+)bPHZڙ[UAGfKvYC)5ϔcNP9Io ,(YFa1pqK#8qMÍ!f)jUu`]y*\_~'O=܃ljŪg=~?$_2d2F(X4Mkk fRH*Wwp1870c ߀C]Y͒.e=s0B?9^M>n* ӀJ_#(&F &J<3fudߘ\&'=OEND8GbzCgU亦CUŸ6CB^eřQ+υ/NI=ዏQ>: 7b$pFSM9|ʠi}_"/Ldy̶JuMMu`XM+Ja(\ (RFdmnpYY +EE3@Quc E3=) T_IѢ bftZ"r˜ IDATTCQ0Vr] L~ޅ{ɺSMm;6 }ॱp~ تǙJ Lw}ou1C/h XA9 peJxj-hQy2[,LyJVt(/uс`aV捣khH38asx*%F'at _[*Bt8NG8-\R`dfޠea{820Ę{ @h#G|hp5N8>|wpc8q6^p8^ jgp Ds<= n.ThTcwof=)v7QYKk  2m3sg{h= . OHG )FʱPB#Q/XSCJP4):I̊&̳>Wў8y2XA˔$[4- e9뜃ySeVΣTPSHp4iȉp[^^~]nUӞK\DkGHef@V!^zKtku&-ϥ#)dl L-zj3)1Ei]odEl)!216vAN**:,l"JU~F~!664 JpCWӺ-Zy4LyJ#ͥN)0exV)?OºR\|@vc:` lp@>JY|% " #RJmC#VG'3-ۄS k5p"cA5yE݉?QCӗClbM³+3pe,q,|E6ʑeBu92sab( FXiZg d"v3L zPh[# %H4{nނ1@cA[,i@斖$AgHJ0|V <3ksԧ>d))4ncii ]'<=/N>-ɖLpa4Mh;ڛjQlat6J?l) N51x>3*bi#i#dhC`UK7zx(4C6~wܰxzk8w0CxWQ;WI{?W<hXIP)ZىMbLoO#J"%@$@›m_U]>s<'O~H  ܛ7s86pjLq4x4pM S׀B]^Yh4 0>:BvA8< vj(;;;gY#"T:c`*]\{ ǖzxp~kH^6\XoViҐs4%,l)܃ Ga6Z\NNjbDZWM@Ew$&Q+""H\/ aaW!D_<ҠȤPMgMAHRVFt:j+Hs:ch2@7㦢GyEՕ%*c8Z=%!R`N+ qhѴ&r̀&}QRX;*HQ葬E$I4SCbH4fIכ"2}AUfz ()/+]y6` &w(iˤϝ~LEOF@v=U ڮCeLoݺ?ߏ1dBe 9rɜ)AJs>! ǎ{]?C5lnm3*[aqa_~{xꩧ#;&TU.iLYK6fD/bh Ga kCbH0y0gK n` 2f ^#X,C/iɄ)R aȴ"C jo%?!N,x:~maf6w+M=[PNg{qr8>#L'38p&`㜃3F!ZX߹s}&^׺j5-ݏ^y?*~k_ţ?m8w&>ς 5 (C.@`6l!Q6.R*laȅ 61Tt=fRv W$#I(L08iP|ĢrqœmCDڤX+ SH|TBPO:DZ5(~HT*6\).1FlJA@ȹҺ5Rgjjv& )bIMSZ4LMse- ᢩ)tK%APjX6QT_5b\TV Ƭ?߮C+}*hΘAB#\>&!uѱH0$e3&_4'Me/t@U`hR։&hV6+4HT='4lQe5c$(##FHTPQ%-0IpL#6#`V 0qx\O6 G5b0~yxe+ރiժ2xʄ2v Lr<r\V,0.WSe^XYG] 6aHjT:_91Ԓ#+CAv4yp拘!pdjĎHS^oZÝHe?3mf cZ7ŸW^~;; ,@wF#<ŭjkX\XH^c-Oo/?;&PY#9SZ,//7s{1|k EHBӵ=hB0 X$F]5<~XxTX jc}8ĬE-Qpyv{S4cxSvl Fj ʹa)҃bJ/87ksT ^rh +ZA#ݜ8r(h&(>4DVKB)|畆ϫ:.҅955VyPW.VōŠ>#,L1VHY.ޣH+R(& /[înRS:?kJ0JYFT*};#I;:AYE;vԤDeMwƉQ\)=B #r([NqQK,ǂA $ ޫQ8=_S#B|U!GHYKD"ǟ͜©.P"_gyPr\qPyMkL0ǘTyՏk{.dfe9>)M(q IybW\; *LW5*a]Ы9QݨK"Ы\gn* T1IվkphfDxvֹ!H t-k`vSX9 ءˆQ94pG-a1]t\NPlFkHbD#En sB ,*+İq8h G Z lVJDimLa;vɏl#}ƒ ߐ59 "=0 0,Ҏj~0$kdLgs/ y3/z*^y5,ƬiԨ`o/*P8fl6CUh‘ZJڶ:O=nܺuKu!Z};XVlebFZ`!E23TTHM悒 )b6Xs>0daԹQF앉>DDT@IPڱkb"Rj 5Ĺύ'BH> 8-/ ݸ* xz\L o{ ТXY%(c^5)S`3T h%YQϠ(I Xu]\Ϭ8Ӌ1JEJ45r:O-eՌ`(o)XCF@$Y^ UWPghb& n.$tR75Q^\>`u"jJ&SA N͌ 7AOسaeuEfr{6zŒa oɴD"ԊQ7hzf;0{Y_桦!ڱ @CLFV2=4iFc Z0( ՒL| tBbs!*D ;WD>d>^#2["!Nh暚m>oy?x㍷19/_Dx_C=x"_]{A_LbSz>y<#O?`}}[bKnU>ERO t"LV8LiSc9GcV0nIdX$>ډ161P9Y{b0~xb,SXP`Kytfy>BJoSFYV4 .յ&(#`Ԑ PIge9/Vy5kU2Q,4E1#Mv,&N%5\Wrmt I{j`FG|63}%Z>ÜVOBߖr~_Z]\m!p H[3,Sq K˧F>}!lh8rJ2|Xsv)$\.809еhRc^fQs5B].GM:n\h ׈TaSEkA8%Lp',*vÖsBmH\AS5!`#1a^gpЅ=6 R]߳i$WAjr<$I10yU[$NO1I˨,|rN&SL_ϑ+/K|E 9fdo|4MYpmӠyW8ygk-oSu??_ŋA]UXCjs{= F 1 X狩(8@!P| r\z6Ȥ2M=,iMpo}f4lC؜gtΡ裇 pa8$>n%l,nnl7^;+9dm $irxnݔ~(e:V$Gd`l2a/%  ܔ49>*|;Y_V23Ч&RLJPnIÑ2&sf9r`wASbVz@AXLQrD79hf(-Sn++ʌR@w]D(|3B5ajYfWθIXb"N2,L%TEfm*#Qw7BOq'aPClt V>HaY!ERtEMqN kW_:(*X;rI-x)q]ڔ ~@#Ss񬍔QM u.b+8w'mc2,~C~ XK+挽|9ITթ|X+hhF&Yg4MPQ(Y|s> \Ŝfn J*~,?LԵL񼳭6~I'SP)RXzPPH ׇҔ7_ slOTk,5ٙ-Ws+QQ_T(zXȆ>%,TA_;1+,U}q-"K)lTЪ!yzr<ة9uI-Z:s{W,:ᑨdgU\7&֒y0kq̞Ц.FцVi"[RY2( lOHκjhF!Z]ȹR>\ PyeM@;GҾo/:$4P/> 6P y%0B/RSg8/yOZ g8<`:m](vE~ga6ϫ2666k\_w0}85B3ef }᭷ .\mzaL%Pwk $Lu0&0 0ІIL99G1{+[G޽ip*zfQۙɣ/Ii׉Eq&Uܼ\49Ƥp·bȓ>owεױ{c{xl珡;?ʼn5`:Mh.VSw􌃂q48vld .\E\z981i:lƴ ?OCh ɡ=Y<أgSU!{7@`6kOⷿull⅟9~Yc">= lJ"8LKb"!LeV6b qX O] "|2D(d)G? *ʅK:WTH&:69 ~C?I&v'K/J= iʱO"{I:$S1ins %#u9a?1(9";l 3!#Rμja#R%Z,2Hgd%)L,dOOשbh 9T~%Xc*[ T UBF3SStΜM,ȕSsf_xEL2Q7nviQ3c#6vp{qA}aZ]dI[So^i Qؼ=&QR-9"F%Eˉ2pB ^ް(i K:kPE)tUCP8 HjƢQ) h##-&ٹRhJR7WZKLᡩ^ `u=-9p(Lb..(\3GaVd丑,H#37|P* =g 5Wζi1̔//fT s铢;ʨ3Dt+M i"VMxn$eȦIeSsZuR{6fTOdkB IK(^k@_x^OZTք);;۸_l6 '8D0-L/_| O> \psV'QUqQ75?xwo} |;;.gsUh,cv19bui=k}.$ИLhpugŅ>^_e6dv:|Djކ=@%F?kdP3"=4YQ{X 6~ckKh;' quX]]!7%LŹ3 A7łptA6X_2&}"*kq E< ckƧhY(V'Kʀ -WL9ٖ|ԋ5+Rϛd&d L/j)yv̏N)#(sN}ڛrN0A(b! Cr6;])ha}?ma Ѳx8vl {{غ˗sCz)nzE(6n`2s8V){c2<'Ϡ`eewy{{;Nef=ME׵BǍG|P0Dr& ˫/=£u vwQA8i?Tqlb+(bx ,=Ȉ 0BDB4blWpXhNICª$&W5l 0WX iQyI^ Xt Y\XX>Ϣ VT(( d|^w1+b/ÿ.CXF>f5F?B#NHiDi";!2+-U* (aLJOѡD$ܨG#v*fqg':0*|:sWlyZ2)&?49 PSuhUXr(t&8xwvl 9%"NF5$S es?$Оa~.@3Me t(#n^|3#,N=B:k0dbC4Zs%QyQd"C+a.}g BK-q45S-j*4+!$sRP*3gJa⠨/q(kVCùۦl =d({OZkQH qv2SY1?ʍ$ͅgfn(%sj&Cj̅/+[ SxyLXaρvc ]ejIf65oh#qkgJ sKA+@R 'Rnx뭷4 f ͬ x3g;VѭcvHM&i6MAo}[X\\@* ~gfʂ=cii״~{X\\ a;;QOi:@;TU^m ۣ{%,$ <mLpbipZٕn5LohMG`Ɉ!.'("{Ik{Bned!tpsybC&a5^⫣%@,D 9͋k!+>\*$3=3_@ޖ'.VF0I=IlP$R!*L;r∔ŽP9b&jLY[\ès /ȅ!O BQ5=3! X>?OTg`96YWSlT[c;Q.X%9R2PB4%Wۤ2ɣ.7S'm6:NA:>K " J(E5tj "j55( EsZhug$ɨ}N#ꔸgy輤[(f>N9-P`Af^a>D=;cd} )J8*3#=iJÛu;&JKPgKbsU_Y+zsBHƈ?KD2($jXƲ~Jܣ+FNrMHeJQ$ mfM%0fY!DAܻs<#ygvDɟ7n/ 95iB·-<ύ\tM8!dL'S8/XǿͭP14MAzҼ̚6t&)lv옢*9 =- C fCUUQ@ҍ .4XTFܷ:q. f]ȡYY8O,zx}wew; k 1k &*& >>U,pxhs5-fUX IDATat. p*fF=%\r,g=l._o> tM0iWao#h"`:AVWx·s5o`693 N9|ؼv5aP@;.mX),7f5>j-(A}t%g'XBz8# PXHAz<-/]rQ[6HOH+]*H]:$@ U%e*t]> -NhoJO ?79ڀ`u"5^\8P3o\ 2VaM,(\ A͔}hiU1ҍo#:NR4lrh"ǁN)R7uM%N!Jj=NhU\R>z!\ Q i- %u^aeC\HYߊzQ&]lB850'Y\sJJ)fNhz1Ҏ}L{8D(ϕ)SK'q~Sm=/xWV9B6PE"H,gO4+ԱюpL!|G8لT3T"ѩO Pu4d$4c! iHM9/Hvr8%M '^|E7~>ea6mk24b98vA7gm0HaڶvNfUYMUht όpU]…0{wŋ#H܋ WacPYAFe<уS W12f;ֆo}YABm/;ֆX[`{Ѥywr Yð2w-N,0ܼz WFؓhTuXY0 5>VL~Eg Op2&c'Fx>to\!&7;yNqf+x,]:DGq=`ai+8s4vѴ-ڮE6l<10y> E\|ε9X[M,,-$uXDP Qd.rN0I HuظM^ˌ${žiVs&` 42Km.fɈ"$O!)q|ԺSg'Q*Fϲ7B܄Ḥ02•`( |}LBb 3sJ\ ِ[ 󲄪9p2=I]jIeq~xuqcLa(2CVzИ2av=>?~:Ok J0x5wfR;NGf>EdJq6b!g<>°?Dp>.\x7B/vBڦF@ {O&8::~DЭC Cԕ666v֎1LPW.>N9-({UUE${XXZDUo^d'*<~2gazpekW5xr} ;x&`)pO^k -έ/a}m /~~a, jtsyJ!mTz#XTRedڒl!ڹpSM*»QŜ*1N>,'mHd[ӵ)EYF|ߋنj"Ux 'WZm,ay=\lIpe-亊$;DQ~PA.t]U xpVLy&XZZ躠~ ͏HEW6%Y7(t`,3sZPG€đh40*]R(ܸy4()F9r( sI:kBT(MrZgA&EdGZOqTTijQQm'()9.%4+a;yR=P;R#g" MJ;tTPUsxavʕęo 0{Khr̪(rfˈ܆(g*b#:; r2y@>8׊Q<̾0,)KQݴB9 X>ԟKo_yfyf"&ͯ8<Hνjrvқ}"lGQ6˴V%tJD,S0td=RZD ghOz&iBұ+ ڑ)Z<"א\og1Y 5G{QTuU \WQ⏍~^'64>RSJ¿F.k(+M*1!͑nG!މ91):gGtp|2q - yL< pdMHx{j\_s@D %269ncZ//ɛ4>i@V=Ǵ8'X!ٹ;lxYAE|>wQD_~ uBdzUG~XnFUUBl=jn.666pi\z {xG` |wy'apvVWV/} ׯ_GvÝwމv-omԩf]`[`o~OAw7S# knM0Y,*GSg/VxsC Fdž->>ؚ\5ӷ;WG cei`q xd S;ltxe\ۚϞJw롙:lp2mNx镏f[{3襏s`^x5/]ÿqqG E96.=.mN5Ǘ/oU2m&va;x[-zAn`m G{1 p uY\~ AU8:8x.tlj͎>! jl7]c* p;&޻q .t 7~c's4x!Ykd*^4B@% M~sxBnBy4"ЉBйQ&yLCѺ*u-Hct\,$}|m P 6Lɣ392E* "^C R=W׸p~(5mKRzq΍P%)(QI(،t(=Q/-MC2ztv$BNLiE$o|\,l#J9/pF #YeCvsnvwsZ*Cg\yx)H{&xiTS)~tf60V? P%l2`X?SXszlL"BknKcԬ;|DGʾ,\lQXER/-gwAU:OQ؊(5yȤ?{D_&NY?  B̊ 4>H_peedSf25F6ҟ/8N`("+Ͽ^EN"XL@? /*4;56E`raCq6^&Lam}797arw/Y!-1IUvcECܸq_K#L'GhN^ͭ-<#x/`:fmSԠu] >hN:~+x_z*{@x' z>x ޮ8.-/?xk㩧2Hd~FvE8+[x~󑻰s]kM}}M29=Lk3=aqvxo{wTXXhЃéN/q*ZGX\^™ ᛿0;܋? Ͽ8=;{3mYQƸzx?lwOvgXΟ޼1F۵8k@:O ?DZcj0v'|t Wؐ١9tX:=Btm˜8uΡ-:sLpA\יwnf^hlXA9ܤ2EɴG#1c#OXvh{ȒǞЌFiDI&%Il@b@7zWm{=7fC"ݨ~^or,e@J(ȡjc 9娪wUZL'nm[opjA(-P=ϾeR;5I3RC2c_B R ȿh`юU v >iCJ(#2Esҽuxk 9%'ŲWP(J5c cJ3#d<\ $6\2RJLYTh N$Ki7Q͐P]24W5Kל\iž5vㄹB-w^9Lj$Y0n8"M;/l23v00Jdb` %S;/ R !)XHN;_;&X!J: 40{D6l1uPp4] i9.ހB8r`9$)(ATP f AtfoVNZd8b 1Av֯p** mp;7g>,ȨQm͞Sψ\ XDŽkéY);LёIqI)*%[=9vIgrʹ*]~M DŽmuFP b8zi*ZX$YyUpR"՞FR5$\Riz1\N~I~𝮃k|+%:^?>:aURŜ&cccs7|)lXXX=܍m ۸{11pY[nSO?Q9rpF(9ä"\ppu 2K9Zc4PYW0l5%YagkW\Fk׾,ν ho?o%v1w߳8t{S/m̴z3ZԡfoZ~fz.lN1*3-qoOЭ ve^c-zXWƻ+v#=.L*f0q(Q*{#;vh u^-mč7~m!sԥes0yk0;7ÎŇd{ Bdgݹyz0&d`XVc )ه%l`h92PflrEgj:+EH" qVRǒmլRI}ub)o~B6. p-^C~Yҳ \;ܿR ;LE@Ω$WUBߖхӻ<@|:) bz3Zd'J# ph_U5A7$g P= a 72 =k\ױ9-憗0nJe ?p gE]шW]ȻBBube9ᤒ!IDLM,Iy;ÙA8n-~Dcb0dgeWԷ>R/>Da39\ZXp9Pb\˴xgyxTJ P5$աNϑA&H.CkV@>7$u.MXX-xh{- Iy>9a%)+1,"4Pw& hdBQ&!k: g"3yZ#zȌLsų5* 2сK]F)%R`UU^yu3d L%,/K} ÝNEgr㥗^cʕ uwS>v^ѣGq xw? ;,VWWqi<칳X^^BoWwe'ډ(3pmcrm sEJ0%UJPM G2̶2lMK +o vZ/]w> ~.^^{ 8]7.bdvN Scc4lK#t38vM8{/ ˃-m-ܴw-FMLރ7 r լdJ dFZ@'̀Ǚ~g1oLw9Yn@ B5_XtGGPȨCUb?RV1+NB"8m"4DPl(Hk1zz%L'[4\e ). dM@W(T M&xm$?$mqh=+#\:vɼYsNJ O>)F*A%+98֏ *a0H쫾rucFrF*T>(GEX3h¼1-0amU~Ƨc t0OM!Hlgj`c*5S$+V:2KSź 6JXaTJߐ<2LZ# 04| E$y0^ŋu3?ȅ7|3vvv!BU!QUZ 7x4?^dsss;Qٺ^;1pXo VNcǒ{ @ӑ+{.V7q ,#sSplNC3_pr_k[a 2LŶL{r 8we<՗뿇n 'h\_8X`RGTxoS_<9ܾoG8qϲġg+dN0gVpD޽I]WBHR7~`a._Wc@tIwQ$oLmFk 506AN}NEK AڋHrhq $@ @rw)փLo_GKb=T3E]8Hj9QU+A/ ¹vg2d# YR 5< \.C&vy *ra%OTo c Ԩ%;.%!@gJ.MƨoZZRԩJTFz^xW70$_<|UUa4`Z嘛GU`aa9L'B3tf}HJx:6ؙ>~a , ؔط(#\0U7,8O-l9wf%.U۸P]Yܲw?upm-^\[<|9;8?{t#sxmq~Cvv yV f; =̠İXh`rTAzο7vfF|bS],ϲ nWb2 Ępb'6ћM'c{: MWMDeR &pe..`؎ɾ6P- +^:s"^ %^bң|r6;CKā9r0Z$\˨=m@$MMҮ T"T@ T{~v*\&N$3)SZj k޿-Kvg\HJ C>R:,b4൓bw=R_aP=30 (Gߧ~$4)QF.ܟ>50lFIi*- xp" _50P%YB|G,ץfI.&%/t0!h($"Hu@= f"Pgu7=,I 29b_ñYAB¨Ughg9aU@_iLZCoX@2PqUHљaaq`@+xR[fM]ٖ9Nq*=}">q}]_f%OJHacZmF!(vRcNk4 gfi{'8nV!=za.oV˞hebsYX>V+Yp% ɌQ{X^~嵺t@۸ď<kcIEUUyכxy?*#Tr:ae(~)C!& 5`T$7d`+Vc]yQ=TUkсB x\lB1"l 7=~+,ȃqɛq|p9|Ocw".c*AnE|CڋoXLq6#=lm]A{iV6}|ī8}iE"Xt(@on Z`/btS.XXX[Y%>XOkvd]6K38IfF28Q`|i3`=a5‚ t~yb/ɩSN+ŋQx%LIf7DKQ?u@FfMӌ +Y:K*!!Z"7z-)f%>"h[d]ßU@.&@#{"R~RfiBPI N=n Mr:)ƵlcgT}dY&.a!p>XNjGil꿗2v3=PfIv;o p e'-|xn9ƅ),O7qXS#8tdV617S`گpGg5*8vn|pxo%Ǚ Sc3o [,1m2\u7bت,p]1{5oc}c]dp#nut[<oHJgώhO}q>wt2V,K]t!B֚/7" {XIDR0,Շq}vSC"dRasv9Rfq6Pha JTDGƣaϚ@ KM2|AXNgTm\NP6j`4< 1gq_|`a=3Ќ+)؋O^+ȟɦiT jz&d U4"ҽeȤ^M!1͚F$Yt0 NxB' FR:)a!Y]dWnz q̺.T)o)T=NdzIsFY "Qq`%ud_8Ti .1&2}Y3:\U6$ O`vUUFXf'5 GqT 뺉Y1s&D?5+K:%IueV='rU¤E?8r/~]JJR`@Sʔ#e$W)/.V<4VX'?kZ^>p2| e*GYõ43_2RVj yp&B.ׂ8U!ňr&x:-3&fؤY>"j⁏Op^k:7Ϡ,+lP ,C*}TcqѴ'--ň[}oN=Bي~_`2`27;өaVJ}{1rl t ^y9O;;_}3X٩,j,Eb9Z&@gv/6Ab g 1uCdl\hm sՍG>S,Π )<=` /]FwsnVXx7| fQأb]'LuA1Hr\ bQjWZU~"+F| ;fR`j8d(d4u"/bY5:ߓ(V1I֋6xQPD+H&IeOzk:p Mz=lv5y3'M˳ək! ~<# J*Ei!)p"I3"kQyr,Ǯv>CH>0 KO2THa29U)@oK8TƳ*Vx<5, 샦}5HiN -ʯ)_k%2(c]; 9P' kb t(R]HKj@[>O?wF_VJٞ(dNx'w'itcɺxo1$W|} OXjy|1h^4lȪD`$yTgtV'xj:0CRi ^h5%F\*J 0iÖU PFwq;H{Oӿ~ 9y6r{[DZreCEN5r+[%.;_`@9^ʰDus3x;qC46,̷Dk0b`KZ-Ъ6W܆펰]`0py";i 2ڽl*ccZa{2ƺb8by|C(]_%|駾/ԗwhn}_sO>Nb% zsp֓YQ} ,+k(K l;zm~Cjfժ=y&Xe`eX\xᔣDX25t3Fq5kVK>2_S~{m|8P UIPR5${<qQUs kH @T`9L6.IaPK$tf!JU*d g")*]o71Q\Hx (ȰAb_s/%vj1h뎑[!vI`g0VxSό&()/(+ːIA0$}6) HHIX41=tmS*=Pw'ZNJ]VgYFwԇe}~b%]PoMXX'QZF JhK5dψZP)SL\$gkIJ^tr7J'd?H*-Af D%1S?bM$QXFe/ (]˓,%9y~ IȍOW\%pYgYC5SKT ZY+(z I-Ѱe46MHŐ?]-_׬>VwVȂS>M%o]K6!>qYV9|AYC똒_@ IDATu0`ss/2Yb`<D'XZ^?\Lb<tZY|1^E8e?d2,(EQHm-NpX]i0&ϼo|. W12sx` 7^]G+ϱgҠfdM(ޥy'?{>et:r69*jJ=,r,6Ю82ڋsңe|xq.άob'Q>\@gy\٘b0( oοw?{O[wE"4=yc8*cjj&hɃx4ۏ??}:G[\:6n&LcTDp[>B|dUYdY/|%v gFEw?=wy\G}yLrǂj >0XA[1%-2|*@0,,,Z(|WDK]bSVJ4+'et1\-PɧNw;O ,5n aV,0P4@KMPDQ?tIGV(yĆ* (?y@jd4W=f4R@ 6%Q) 1՞o%_WkTdc2kTWvK’~Yg#OxIC]rDJIchkGmșrOBE:$>N `>p XrTaBA;j/Njtpztzl,L{"BN0"d*=\mupj,{m9, -v~#O~WQ"OukLnTVVV0P#Uh.=`O+o]`[(K,/0Opz^<ćxc~KӷB7`I ,F]Cԃ?]I+ GLFsU k)U⠓Q(4R e{bDZOIr &m*#pHϢ,4-gH+3& /GL3L(RA4$ճyNv@Q U]Qoxc!~ ]GW'@#ne!z/ԉH+$V.F")}2Z)8(WbL81h&5Y=$Y4IE`b=!ygnX -οv Dt1XH;${09sDS'! w ƾF1BRY/H5aEg6GPk!ROC]VM&2pγ !5HPu~$ m VdHF#ubLݪ>YB'7ţ(jFUỤo7\ aap^%.ot_D?_vC/-^=9=ENGya>H5"d'̾.w .$y/Jy!ՃK ޔX+SҹErrsK#:3Y^xvFY} P4%c<a2 3e<, PL~N,KYZvU{KL]PZ88K93z1Mћ]B9c•XFZO3z@]!1~ |7_~;>uη}س<z?n;O:Awقj\V*?8%*R"5E8eLVт$4Xh@T_e0 *- /LK&96a@$C$]PokvUM׆epP";V@H(`EZHҔ ϏL 9rb{qʯ^1~02ʛ3%E? %Դ.7>hϱk(!V 'D8#1&*0o5:)ѣe" 3 K~7!NmRQj:cX27hiq:mFkc }IJa~%Ÿ&vBƒr)dE[]]w߅  Ut13t:`T%`26+I=Tl&v9CN ,{Q ~0kN 8BL !rT`(T"$2zF"00P)ojC#z4vtU"A:X<,!!d{8Y8Hǝ^90 ) q*2AFdj@ 1QIQF3 i+x.bj riA` }fq<3'|_xK%7@R/¢5l33$#Q^3>KW뇨1LkM,?`KVYX }|L5@sh?4):vqX9|+W{bp+n)@&d!Gi ow`rqrZ'<E㭝~7%h&c}.֛hqfg뇉0qpaۿ{GCvFCyCu'S t]7ױ=W~ב5 Peѝ=8]{|p nZ=.3 UQ[|G,~A.oqɐ<5Qŧ`=CI@Ӑlj'Q0,ZxV*ӣELEtɍ{^.)xGIʪ?tNF9eT!dqBwǨJ"F}# r|@CfK=d *>1X H8Qi`HB:P,t,(%fld^DV,Md?KbY\VCi Gz!I^xBH& UIVsl oɼL\>S̋Y9! rQ Y@O3*TbM$).zFb=/XףNiqqi uRצ.FĿ ݽB:($ϳZ@~9Vv >V 8fY<ꪣXU?c管nx$Yd.)@OuK'$V6HTVYXE`K7B\2X.) ֑9E5 j ,e^R*i7H:En09gkѠfcQhWrΡR%ExWRb~pggΜҞErGa4`~q ??AMYS<"d[<#@f5Q{ ̲ .kxwqX!+ lPN];xUepA8/0DŽ--xM)/?!z']a;E{<5+XS|~Fӳx0ry@9 Ct-Lg,a:ZDrX ՟Uלs(P%wʢ ٷn|w3V,pY!<Q*k+W0{:WVC1 /'/|g^?'^ ăhwZu|;5T0D,`'o3PlG"#3jȒp(g䥦 c8_3QJE ~/qZL>0Bdx" (_s2ɗtqp eW&a',;_(V4c4ImKvSq&aq '/X쥙qӒ9^$ JZh4R^NvB:l엄ӡ)*J=bWZO u 2,B GR}a1Fu '`BIWR2BQ0%QNlsRUm_bIyܔw~ V M+f DFZ×B >2a~Қ+9’ĤY~Yfu2' 1bN` TKW_si2Fo]&ߩT5Jvc;8;n DٵZ0gbG!%aQ"s/ 1`kCO1:57>Vů~xu=7A;po?ڸ0Wx7<ޟb`vKX[n^s[3v6u]q;}pv C10k:ضvyy92tZfWx>)PK* |3 ^Dutz5JcN opv #2.:XvOm#_.j@]} }yǮ)&w$5VXLi,԰nQS:lD%ߥ$Ad$úiPlDյjx͜$̩D]3B;#G2XVb(G;C@B[{RW+KPa4JJ)5kT°E1 oL)m V-D80#;:tL.gC*UoQ5F{T`{ĝl/EV5ĿUp&Jc# C!dsN|ӤpM#U6+-U/֩C䤒#Jq aߴ?T F͙m7y+!9d&l _\hC%~JW9 륛/Ua< 6* 2b؊dW=k6()?Z0ŗ^UZTjˏ яރՒriɦfūk EYB@H QƯ sXr ޽n% '#`dEV'X,/Ϡcظ|C 溋=_9 VV.ag0@ZX{v£[,cϒZ| O >/~:Jnrk;BիuE;/¸X[W_Ao~~Fw:>VkW{?5sO( ^d#GPCX\Z¹s*760Aa0JP.VW`̀ YLXI"5m/U؍F*4f'Z% X:U/wEDm;ࢯ5*bQ$ʩd[QpK&tR* - $0h,zڰHG9 IDAT_9ɡ%$ZJ/>RFR `8)zsII*(H!P)+Wu^?f룴=~L~>g[☼J 6*IYN)R= Yº ^YYgLd`2A lpa)m9yb`f5سkv+|tb*s3̌Ɵ<^n?&Uia1vVv*؍+X\^x~. 0w 9#tƸCxc8!+?wOAw Wѻ3c7>E _'^1؋[rNtpem s c?_>ӧDN2NY397u|g0C1<vqSx4s@Ōmof !+ _]e|GVU>U5Ż#Gp]wsg /GՆWQ byD}#=q.醺bVtF`n0rhDž!d`Xd  Fͩ4-tjY $U}/CRh!98Y)f'Y[2"_ vAN"%6C%$%ʋ3lƟS{B1qxoV,4V=kE HߝEڍ>@~aAp>6!csq>dK[:J bv `%LxgCRdj58iG1yL= 5bg0"Ł a&4ۘxEu!Dr4\Ƨ*TĉL l6*BAH@b @xҤ0F4$N]̻$Ӝpl1s%?[YOV˓c4ЈP1CxS$06q\^K#g1p -)&;Sᣵ1@: 3Yrԟ+-`/wz+)T9J)q⁦fh_4J%25FʬmN Q5*JkHڇDz{ jZY+ς I;ʔ(2a'zL7ľϝ\*YE,RKdI$vda6cF 8h8NF%qdfH"Yd՛;W~}^տ"`U}^k}SԀbGT"(cDs(z/(rgj# mt!2i7G仛IÙ%VUE}6M.j"%J Dɵc@y{ȶK-IgNɵS)5>bޘ!72حI0G9*eIBKI GXE쨀Fe٣pZpfu6JLeCfWft~:yW_tjCr% JAkrjڤdii[|I;wh1%)GZhܭX2Ø]EgDU2\"3[CZ7T!{639 sˮ3i@) ϴ9-2)CW^FYCꘌڸg:S26il{#ZX5}l&{#,T2Eϭ=XbDD.j$!ƌ0b.yĖ2,BpTwPm~ޮ)E_Fr6 loㅳ/amcU9)+\CgΜPw]h_kB>FMMtJNxbzTq<nB4^?op2~:i1ۃ=LK 6;.m`:I`0KvqY0 ,cx`sq_gs?G縇?~oW_  /7\F[_~8q>9NGc|+™Cs:ΞN=-^۟믟c.D!!Hj6EL?~hX ?Б[An6,זQF`\VnkAњK(#ff`eUDZ(9 xǻ6^|E=v N p$1P*%+5}T'PK#E=(jzDz@HS¤5`oٮ,2FIOqmKs |F_'z\Dl)ũ }M(FyRW/xe]PԘU clZ;ƍ&L&ݢgj~PCXkN)SEjQ_#pz3[Y1հϑ7hp5&n D1NJȨRQ/j9'5+uvS7CR<4K 8QcY'7d葅j6gcwRhc4$RK-RȡA!ݬTpLHvtX]Ϥμ>o4x/"{Ap.~"iKTepev!sfĈ> k^ 5cAק~K15(*:k .>8u2b !3G&lg^rB"oB89xv6T ?/^5sU7甡 daI\R#oj42MSV#R' d> hYU\\<2i aICPZV129g4lAuWꫯ 66G`3uqȇnR'xyx5PF(d gMb móSm,̞6w?qt0.&t{ؼtkKqqc?:pٗ_'xϾw0O)+L];ݿpW#ݍųן|+_-sX٪0@ =ѽ3J=rn [[}\~سw/:w2O\/e)lllى&01Z.n9rvS'o`06ZGbp@%6qY7fu ` e9N.F5as{nĉ@n"ZI'S4F6Lm^+c6-18O0XǵWfZ)CP%`%lߏݨPO#9'$5>'t 4dJE E!Ԧ{ӵ5h_a-~z&R~ukƝ]%hwWAk:ReFi #}FtIptI˲XgUYWHa1JmfNyʛ)6iҤ. 9r<'b6 ekt(dSo VD%n Hf QdyflsMTu%Tb.iʖ%ny`FKM(7@:զTHb.ՙrk&7v|eCE-4ڤwWH)JKՍn( 6v0!qvPc=XL *V%e+Tm3k|k8vHk^rOKHgh2UIm^L%HkJulҜe]TvFz}muhJRlMjz5@IDܐ5$.\,Ͳb)O.KWxFF7/- -Xl *9xʰw}}"];E0}<ݤE@ nF]5#1PGưЭz.]OCR!9s5=$͟J2hR?BoaqY߇~>puc`e{՗ǟ|Wo} 2 X9DPBAd{׿~@=>;UAƊCFjDdEEFuGG }hЕkB`-z "ɇûHrZ H/ӧzDGFe\i^8EeH24ʜQRW=PVzH ?"8Ču JIaP uw,v{ `B)3ZX hqn)3SbC3g43fhYAÜܕ8"rJ6h  0x'E}N ʴ`,f MK^Sfk7ےlTz7Qoݴ" PFJ渎,B6b3Z{5&x4újϞ?~_֨$ݽ8UwaϧFoW|NiTB$`0cu,noc|} pz}3k.bNaz~bf~"'RUÍul'(|*`s>VPO Yx@)0G@n?y ],-]MPc,..as6Rg@ XY]F G>7jh(N@+i'ְ6_7ILLamKSeh4pܐ!Ѭ˹Se+.QٰUCj԰#$zR"`;CcU$4 OAҪ,-He/Oo殑\qyce1j R%9 5~­-:>QE1r3}fFEm\H\.m0҃+L!4ڄ`r:b3J-R@E1p:9E8tB5#Mj4@O⥄ 1lH@iMG-ah Ȉ9fQO3 OmRC 2M )2ʶ7CQ <)3aZ6iHL1ŮU?Puh kG.|N6m(wP4'd= GbސuFGi!^Hg*"ΐ:|ia3s5E Vd) YW.B/GѰc j2F<ʌ^WtORJx,rmtהdBfFǂs U9"èྗ4jeUEAsٮm 'h ēObI "@ Μ9~ۻ2i=P@ z3ʟy(^~O! 3czf?zG/8勸5vK}?&f ݇V~e|/-ֶX.1/[-tۄמhčvN%*)B 0Ae_[fSxslĉb}x3?ĩ0"=q{c/_šYln 11Ƶe3w}pt8CAr+v,ЕHFM.温jJ;p-&D!Ӊw(ŽS qN.BfZ5+^;<\?zXeE*S)PL;u̩lyfh Z G5kQ<2=pr\YR 32 vL^kRHב7nB~+oC j\.{gbc@#f0ifzcP bHQYh"U!b.R!Cޥ]+YcBp)iȐQd,؄ґd"{2wM@%(stúά8bQ@.9ܠ.3,Ž]|RM3o%3g'eȽu9c`f="6jN?TcXX؃k׮e/^'wcڸ5Awѽ&M78Pq/$N܃LJc'q"/_7.bvFS]`s  Ea3St;=Pdnoưm"bvj E~\^z/}|Oq%LLMjazj n9ڠ%V8zxjMp,9~ͭu-^}~wׯ^hb U7`Qڨ{ma3sxsa۩y>v {qa-c4*^HfBU(V+zunv{?l|XU`*-:*TbX ӚѢ @HdIH4W)l5% 6Hz%ijB,k}mPb4!t`<਒܂Z8FhMHth-fS#UFT%(P*L |{CY|e/)7TzM O3-]1dwt@6&M5(,(ӬXp594.df(RFD3 IDAT5m5 ;J *9|2 ם::kJOKBwPV?饀(UBZo,U: 2c(8cHqT m ]`I^=Fdؙ;SPh5E8uz59Z7ήaR6!wMhN"8i}Y 9zn;(#Cܩ!t e4p۬[ hMRw}+Tnb}F;~/e ^z\˄ET0wЗA9c'CF$dS̃ r+rR;#3ZF*gUFHuC "|#[m 1Vij$lAyۍ&իװXıv ݻw/zu6ffGTd0iZF#5C'5.P5n}:I\92GFi#88E}h>`C\(bz~BLeb0#01E9胸^ 6&[S= g p(~o]wZ] TcDre ոpjd csk {q`^Nkk[LЛpQ,QRc'0 wy˲DUUhZwH\Gv`c}{&jBUq-S'1=õ/ZDtÝ>jBѨ~@C1VXvO~fdg먩E¥e|Ĩo -TEԌ"5(HIVzĕ9s3$-+^tz,vvUB-LvnaM7ԕ/euqD$t9kF+ Z{bl6 ca3&r:5jYj9R`Lh89LNml}M7Ftp2Cg4" ") `h^hS혳L[sͺQLcrO {od6՗S}eu#4F- m\}(ܷ,bpc0HQ=nD]upy"vVXZ!)j"r4.?1]sWvEgb"5:}7gdŻQ* z:uk)i%ξgb+ jhgeXPB5NDhIq4tP ԻwP i!PXȹ~6Bftuz\6״D4->H (o[3mVA픣D((ȺLzLs 7lAM39aAz5vQZvyJ.j p+nH]:K|Ez>)3B==" >L9jicO`euךAP0(ׯ_#vVVV1E6Co$ &&M#iZ(/qRBEzZ@^_Ewj*Zz6aĵ:ILt;赻5q[ u\t)ܿEr&yu_c}N݉KO} \]~a] 3OAȣ\r ~L4,ܥʿb/F7F )O5.s,^}դ ޜn{š4Q΍+ResLwkhZ0qsr qˑhCͭ!/+b{OZ F"/-akk ObjjfBQ,!HWˋ8}r|3XXC9 :=] \je j`{w"`VH撩H% QQF8r)o]4*t>QWzHUnaЉB4v18ˌdA-9a><[]AQ45ءfHaYJ1!N)IՊ8 y:"!S@#l>Prnw]^ܴ{o-9 nNͶ!Ng+!B/iNd#f36\( SToo8*E3~Ill@Ǚ7P}8x.^R}o>i <2l}#(>*7g>.!P8| L3sQ&Zcv3&Pq[*nj!*bnf(@ЛhG;ɉ #ˈPtڠt:wN DF{\EN je&zPE6( +t9_K,T1pǟL/9133 'opGG FpHCPEX~Oގ?siE\Z-qǏǷ-\O/ c'@erũ J4MC{kQMzBԃBEX'"`Z3 ei|}@[ˈn lRAZ">rԴ`.4X`fiҤ:]CcSYp~068jVCpABQfGPѬ9wSHkr6S)dt0ېoN]DFRnݠ 9{yu ·3,2dZ!˨+vBVxXjt ,(ӷjb WË~P0aɽ$rz@4ˇ3]D eIMf$L*55ۤةјJޟ`OPL󾕒Jz͂ s-\dh `E}RIFŴɜ "jԌ *rmQ+؀Lt8yZStF[M#qٻ [pϠy7 H -Ec[PkfT-5az8ʈ᠏qq?KKK U`uq kFmBbׯc}.#Eo+pЛ_s?8wG/E{K 0d!By3}m]_lH29-Pib.e#dV!FarsAʼ&167;I-_ЊiMb`\SDW0dMUtVТ2XaJ1Qq 3La,WBA%ʚ'es'~8FIe@QBEAIBF7UzjD2WxYkkMdYSʲ5@n7r5$ȫN 5۲ءlUj "2);# i.\5MSeEqn|2ĴHt g&3P t55E3&-/uM^Z Vi򸵦%mMtTdȯa5sυ8!hsct3U좯57'2&5cE* v71wRc# BP(Yɟi*@]`BO5rDRH f ֣J 9 8)4VX!ȮǷCDO<&&_^DYSFdחC~{֠ݨ*FZn6o0Ó%=]Olll& ano`{{ nn @h[kWbbr >4NC XYZǩ;o~n?^_x zUU m4N0/dJX.ɶLU7% \F4敬4Ә6Iٌ2)GQ"4 9%t D73'Ն^Dpƌj':~J3ͨ ]fʔ6@<԰>;+`S!RT}Tt{V7yyFA6:`pdqU-}8e "áujM%SMwRY'6-'s 9-(ϻn_r\үk&rw 8ᆭ˝yAn1悳746C+)x[LbKs*=dמBM bt5 6t7L7"GgϻyUG)SstMC,sWNk~b׬F}Fɳ*w)i+>i8s$]Y{3 $=kL?ܽ+'dQ&2xF9c b5a̲?FGlzrps,ojsX3XX*zlXPhJO3g LSr]rmLsI1 ޹) kOMs| 3b#I)LETHHHfCv M}!vcLB?_d~Nݫ|=< h!f\'0U62f *x 4dfk\3KxqYH`LJ>Uy z8~8n喷~/^믿y⋘ɓ'3ࡇ‰'~)4ߧ~ΝCko?p`n*^j[݆n#Gc\va5mn]PL*VW0 _LLn. N:DY*FFG?gێo;8sN Y\d0z{QFfwL<#uJXHhBLa<=>8:'; *J`fX&v89*#gy\P }n_~ IDATc w:'!YUrtF:mǶrT(W2ycWt{r0fQgs|ZmPsE"EqBrГh"Dj)H5f3Z/`k FiagJdqt#:Й3&$[yU~28O99P:zc%ϕƚE玻(,B=nϗ_QNnXgD͐f߲ڌZir13dag TJ-oɎȢPG:8(mUNtSAf剱g!Geg#5"(ʠ̬(աdF6ʦ*MP7ѱ$E(EUel0s$յޜ{AY= Fa*ks @c7BwTjdtyN 5GsfZ035Jlz`b)Z|A"}jsv ]G1hZN~uݘ!}N{{`1Lr&>>H܃)%6NB`: &Yt #,=w{AކqqU<ǽgYuk_VVV033ݻ^y,'y;w>,>Wꫯ[nO??6>OO/} ǎooСC?c\pǾSO?v.f@Qh8*%ej̈`.66xfgg~Dͺ*0199F5g?Y9v>ꠊ(%LL,YЯdHF&N? 3PFND`gf|N 5VL/ ً•1*Nܕ<22c37FfC TIJAe2ɚN!w}YRᨇLP7Yk5XɮfT&r" L?YP {nJ&mTrhyi]U2يn4fad/F6!a5lЦU3W:d+:T)eI1X1GBAbaaΝñc}}LOM$'c<`aaSss*FbU!յ5-0+ױ{9o4Ӽ&zIE6~XػyxWO㮻OԍzBDhM.9Hj2 =X\D%߯)nX u jΨ#&.3LwVMut4R0(jS#TfkY7 db>3L! Wkr 6Ƥ M&r{u1w}JRVSҼʍ̓Cb!.:wZ;jzg'f! :HbCsPjHBq3/*ٓ{C\_U_ɤ(C䩃pzZFb:iNAV?BM7\4(=bq$uQ)g!!z1g 41R+Fю6n`}c#ʲ ) ሜ^觠wAwFVZ5n \?;-9r>Λ666pg/o9<}uu{ފ]{1<8{,:^qbqq׮]ŋ1==gƋ/ۏ?=3*qɻgnǏ ν|eQVxЪ=.Z* ,__ _S'" wq .^BʼnnGoʢvf(i͵CjRƉT9EH(LQ-@L%a5ɂµj"dQnlV HS2C:V] V.))jAqQmM45"CT"Fv6UQ+\jKzUE[hQFaҗݡ Ә4 XXevwce/ص]'F1F5JkVգχ{LA%#\3jᨥ 'Z6rLS#Pu1|;Pp֣p 3>)!RLki@ӄ(&wv{UMͭ那JV5fH޲kykV ,,ݴfq7~r%qsM\S驡`9j: U=Q}Ip!߇3A{ O9e8H4x\|IYang?D4*YSmgD7 l`&Q݀vSrդϮd.@(p]wA}nPzw/ pGr1Z+5R^ \ zdXeuex-7@|;d,DpUطn;A&>&._YG>:xf7Dxʕf {AQo|2&&>W_} o=;~}|{íފk׮accn7133/}+(҃4.YZƣ!Usrť%e +R@(@X]]2ۋC7OFdOU}8M!"ܹ‘#GRDi NuTKev}I(l.@ݘBƬ٧_bSe{ep r Ҝj*V@lLߤŤ dgF`5^ 5BGEI vZ2k"+w!z!4;tz&Ga#7 ÄzDH2 4BRPj|zϘI’]jMTg@n-ADh_=ުO:sr,((ؖe&_2Ň5tzxٴ*sϐtGE "6%<4oQih~jԥPpЙAHHÞ1:41r5ay)7<1 QUPxU1 T29}vpEyjEYަoJ$z7<־5AOQ=7p 1 zݘQMFsB>XDM2͊BNtLN97i(\?B>khwAGOO5ϖ@K_s,M*ٚ682t|ǛC70bggOK@BuɄKOެ/jx177K.1\^pxGpm~w/}% \EzS3'?󯾂/ុϠagX"rQ0'Î-8{ɲ+ $s;d(Qd\c>DXYOYBJTR,6~,F>DL0%OJ#CY]Nı]@#W0sh\ ']!H<]JH)9kv\зݑR) Qb0:d3JNM)f;̭2B aFi]rfr؈Pӿ+6rf\ 73e*hF LD.M<$A, 0qf%mޑ!yeֹrybN!ZtSClmt5+! t(o< LSi()/ҲFH1Ga,L>iE64,F5ZvWr+RތXnH Ԍڨw46C|sÝ 2N΃˭,@! %KՏ~.iF>r8_ܐCX֟rqcLFG!4œc3ޭ,uT-ޡcni(hM+<=mL35tcv}5X*zzsn#ߛ SM>fYL%;TFzşMdp<= T0ߗiNv+q̛pq=F#>gyھ .bm`rrO~ ؿnnVu]6?|U˘x8Cћ[15He,c8Yx:ckskkhԧ>v}sAYTUȄV2V J<8q>_>p>F#Īnʪ8dxgh9jVfa\BPg2FyXb.Е\js]ѢrM]T w>ˉƌ_\EFTW"ub1WV8;q_`7d_*]I.YOO2;DqlsDKً[Gt$ 3F[Wؔ3 (rJ@Z1K] %$~2\ ^Z6]W8h7h nӁ!Y\.:AvȊkR*f1 E x}Lϱd Z*xtӊlD" 6.$!`sWJ1-ba31kJBy3.pq1EGeU WÚ왊 +zF2t_LZ`&s"4Ex+:*HFn\HZ`#+Ej+ETcFmO'c7bsi;3.x#;3b6V.fNFWԜL4K=uܣFy׎rv 甭H'f::k,5SBv]9rb?$ՈYklN~d'DRe ^{KK15D(^B!2>|zϣ(7}tEQ7$[@ƭ݆~>bۛ~}r#B.x}kk8|>я\Pٙ3Ft-:m֖WN\UZfɎ#Pt"4޳kklJnD3(&ch$Q= TbdWeBMU pL}RWJj+< "9 ٦p,Rmu\V*ssY$922ō*mŌ2YQq1dhw54 rnA5J,g4\#3ȊtW(w;ýQeŪ2؅,͵d01$%fHsu\֢\/YW;prTB2'CCHbpPY$kE-W;J12|ih4p6HkZ!ɔ n(S=N66w^ipO3n@n""F >=n):XEx}S%LS2k,oUa}4JE %_PS?; `#w\3 9/c)h{ԡUڧ)l(:%u~uw5ƑE#\ܵ%YKE=6xk.G*u124\[ӕJLA-@,iFX ٳb3\\lx'Pr1Or`{*¢$߰ښ"iVb7Mlnoj-@N_Yeܹsx饗p)mw}5<8qj~o C|k_5_oED>9z=t]W̪!}Y>'h v(od!c2@Qh# ͣf`qw:kHfnN<#1 pdϙϘ4g\YYSO?M&:q"iii zx^«|;Շpmm x{NMM'!Flmmȑ#e'yu]|CK/^>Ϡ͖^ՙ{͛sR9JhDBr$@]]?п_:nGU*`02CbMn^>) *O$s}z {8uo|&iݵR7n'>ӧO[ܑfv`^uq@{ؽs.z~׹sou\ȳy|?};+OAmTjb΅/EA f3R`r1wCH^ ronC⟹B@[Q 8]rɠRXLoi2uM5Cm.2({+,ki Ȍ0IHFђd~[$H>XX 7Z#BA4zq׆i8f(4 [eg45!DCG(')+Ew->j}7O v#YKAP1,<>=Ѹ`UKFQ|2іaD-;kJs;{L v|?mj0.nT)Ac IDAT}wR)kz--t\ ŊnDaP۰UhKY-?*IckE_:73XYm:nq],I 䲟LĘ,`YQx&]< Z%TLĐ&Рeネ},jMHr]ZM⠌2Oa6T ~" 5Ho%Wʽ0Y|Q/>Pd P=]XYm4}JfVCJtF:+ah EQrgsP/\s/b7 M]O=\L?ٳ6P o-:~c|Wl.6'tnMDiG%?j1n8 >ќr2)`D4l 3cJezus'&UVc~R"IwWx*B h G~) 9}lͧVSО(+MWT- QՂ?se%Fuh^c2X?6]?Sje3c5jW Ru0I:-dV-54GmۨfoZȴJ.DlLsݳ2ELh4hh S,+awgKZpӨtu,#OߏbD)kJ!9`r٤siFI ƬsP=cMͨ+5NO!%"~ "^Q93E EkJLoIa m6`o%LDkͯfHE;C3YE -:}hum!Z FWJCd ']Qgu QHdž)>gc TO#M? H< nȣFTܔ8j>a?3BهrZX ^Dq8h觽Fut(fޱ{"Au{/T3xtt/~/0 c\)O_;;x @>׏xYDGΜJ%.]kW=۷na"&߽ݽLL/ЖG'p]ܿ e§>I\zEN> NX`og_/+_>/>3g`nI; +t}A!]G-(ݘΦ4H1ENQm%ʄNdpY~H~+V8f*fRi@t T5B5@)*ٰDT  0ˌFfP0ō%Qx>o ź]H.!NClȨΨBtp ) 4Y*-V@X-5M+E JI#dwi "Jߵ"HtQ.6A"iHA}bwOb?s9zRj{_ 9iux#ٰZb77@A3 V#ag:XsTŒyu:F9/a"[c-Hny:k? l)L:k!i4C7A7cg QRzI`hهf176qb0);LgߣjH$RI{J J__f{o`NsBxWq _׿u\p eH.]B? fTz֖+w. 9Q7mKs{E^[['qeYmLXwϾ^ /'³78:^aVl"2 Xx[.Cb_E* bt ]Ḛ3ht 50i:unCR4\DoSP{$1u j5gڛxS?7C ܮlMwZ͊O\Cw蚴 7.BFqthZ8΀lHzԊ g)zCdzDc\J50m\cKF%^4̨)W3((U]cy kQӍfu*.Y4 " Xbs̭ӡx6<&]2_ jShX+tm8454Tt!,ƨgHKXQQG%,?π2Y@:\1ru*fUNIe RKچrr&JA[" ,j< {漉 )V.ڇQ>h7ukK)m("#.Z aMY=P'.y(BftGRai0C29'^E@5LxjftD CB ; 2`N]"$c_)ޤyRp@kŢTQ@1Z$GDH3wd1®gA`׾78<:[[ 3o|g|凴rM;znoo"}wwxbSdkkۅgϝ嫏b|٧qժOܾrbs%T^LmȼK/}/~ŇxM?uقO|Ο͛7?k׮{PmXL6P#Y>dhR4fzQ#36="^28ER@!{Y7[6a- ̣Kuİ ḧ́Z dE 3 B!5GZ,2 І,&&b/I ;MsyH᎖t*Ě@Y@bA'h^/ui0q Ϥc➘Z5XFCXY$]O:ZSXsdʆ}v#b ;* 1'0ɔkM^3fAGZqCRhOԨAJ "TR%%ȅ[5Y(1'0(<և5( ȌbN^|q `LP@Eb"I7T^0B]S_J)v^+fzTc%5*dQ쟥g4Q2wĘ(f8DQ-CwMH OԔ0Nꃞ\EEƠԢ Ҍȯ[s BsQ.5a’U(KbJOE׿y_j‹/iM#<;w7rf/o6ܹׯׯ_j۷O୷¥K03{={x饗~C6{9ׯq%;xGgΜy_pIh88\ڍ'[X]3fӔO<ϸ{6p |X1_?uom!؜޻SxO>o7[v0M8Q:hYlXMAq Bzt%Nt'#hjL!u&b+9lXhf >4@JX,X;eYѼ3PDc(0 ID~畵,"fӏc7~@t7'[zli ,кaOTp.+IJ!8aZ yM',X0iCӅr7;5VP.1[*/ݤ B}Д'Ƭ5Z wȃۙmּ2{3H- } "wT0bU 2T'sLO)c2F.:SH;Ra$5DUBڴ?C UEM l({I6paצk<_H:-] A L=7&u1[6 dM-s‚Nz^[4O XP_3{P9M)Pi& wB{|ža cXS:.Vnό.Zsh+q/tiiĂ]BϖHC}Xl@I~.D4gjHЇTNe6xIR s<>t֠?#[{|0čd>,t&.ٙ<aL0zpAJDˡ0FYE5[wJ7&JAS 4^bViKqq8i; ` #VK3I틡Yӧ7|(M 5_b=3 MٽyGFHq,&g%hhʘm>yZ2f(oÅ !lEgovָp3CrovɊ-(s"BdH1٭5_&s,mM%jR+ܩ-AԤN|3yX JEdʘ*F UU% rW} 3+aV: }Ap(f[l^ot@1>O7s=CN:z GGG{/\>??ë<38}|ϛ7oҥKWU\x.._;ww/7x~pcy pE\~"Nnᩧ%`ۻ4bb~cxatzQ%VabbAWK(68\JA?: ӋX.lT7 &4N L%~yF$ypϑR\)cq ½wՂ5eQdSGL]O`aiGȯFM^Tw:FQd栚&sњPQҤ2əVҭ1[4G&׽X'#E:O1ޙf!VJh.FEmzqǽaOb}pUNsT7* 8i@ԛoo`ygm:VCuՠ,p̌ITk/JK26Dh)X5ާϮ d͖<f'.h1>.ݕ2Je>Z>Bk;V΀B1=qO q\ߧI&K،†я^駮77qU\pjڌr;NSxmgϞ?y:pa}G.= 4 d"^H6N::>­e&*ߨR:M8 ~IP0Bv"5/$QٍaT9 ׌t;펝hPoK^񚫫LtdDhy`{/G|=xCid0̎ 57ԋU62-M *-DFH(F*#itF ٔ]#IWDH1;L#R%[瀆F, w2˟"P0J `UBCؾ{CZs1%Ѱ"ja6Ċ?c ?7M&ЬJТW(z!ִjyb4c& -hoPoo2&E4ЪqAZL6~H خ<ͽ&;S"̀pth8c$({50~Obh "a"|NaK~ި\Fvki1&Hc+z\g[ ~ 1mP{R_& D$N[o${ߝ5} ӧP Dخ]Ml*=&q drM؈sx T*kWѼ0U_vSlYB&gie:j3Lfe!(nM4=}/Aːm¿w/"O?M\v->OQh`}?~;wgϞř3gBW_/ҏ|˗/i?&Cիzo=o- fiX3Oc /yy!6VcL h/ loF4s>W>E.]X&MZ@"pb1rZף*D&2EE5V IDAT,QC4нOmACuQB9iD|'$wӄB#(fꇈȘqd@&CLOV^Gia}b)pBuh3l&6Iގ dTɵյ"M1k.o*@D!F6bŶ6,ؚvS9պMf)ܔ>,ڊPt)L}Є~ )Jf$ WҪQtF-6dzIX(&P@̨ZR+ksP9Kz&͑`MŦqӊ>qӖFD}VJ#(% [K,~џ uQ7(qlbjv(:diT0Lɨd}0>:?aS5W:X%t~ތ-\{IZ+@w1j m,"Nw8F/ٺ!&5ښbaz9o[A JM q`A2dHnDEŤ>%;] M$>)M?+. jYHq3h™r!Y!"*-{mؐ[d*jg|±D9v__aw'XL966;j+^K΢3X.gx1lll8{1 3 Zt}n*x+4#W.#j9{aU;PL8>  )b+F%⃈Џ/AVM,P vOI(EHF/A< >&+aE@:Fn†I}nLጪESGu}:6 PHytd} J]JAծzȁ9Mj i &h&Tljw*mШO]ߩzCV]9RF @2E,a@DΛJQk̸6#Niڣ䭻D"C)~/7!کli0ž~JQ]#(1קu:hA<_ivd#wSdegB]"ӥ!D&@к3VÔNoъUgP%gPE׶~7 uVZM[HB* p3iPlHWߓ&A)eFZX0FqA;k4YlOmy\ A!1u.ߛ% zGDk&QTcHG[hlFkC u^ v]ߗm,1|Pi"atz?jӇUEdhdTHv(g⨔Tgz ORTq\2iE/-:!c):l5JI 8ِ ^4uZEZsRU|+`>pF\rw9g=~ `kMHG%_ Y'N=ȩgx #p rkY}:ݱzeǤwo|8L?ZÉ[xӄ0ڼqaowjSә vwpp_ŋ/s)iO3?6Ny‰dE\[#az^)PKuhQht[0S3QseJ/6dCfj1½M÷́))t,!w Dn.PA/٢Җf45WDJh $=uMBYIA1hʘ4uM Y%&RfQҍhK~Gdʢ:zj2y\BvOp=[gn]3܌,`Xrh9y瞣j'R/ڤuI58MT:7͹;.O3of%}j[Qe'fd P-`Dns\/:7uT6u= !B]M 7Cąх`sCF[b L۩ Jho \c,XrfI @I7\IRԚNuʞOE(ܝ ԨeSyFWDQ=\K\hu^W̸#\<%? 5X,Ic4Z}UuO}]SR Bg3`9(ȱ>j98Ze/Q+f({E~fcl+r9wxBARb=H S\!F DC:%ڛ>lqMuuSG)T~Cgp}Sf [( b*d,6ynӠ Ld.o;8w,vcjqqrًr v3O-criڝRVj> E"\LTT,SJQDZegQYr@taM(IB>M2M#ĬaŮ[ɲ{I6c;gP ԅDb˷;:30 /^pOwoaG ޽m̭&bƄÃlor“O|+xع^?'sրa4 L(a塩`Qf9gAq GW|C,Ok]=~ P(ւ8kX;(CѤ~Ch :mirt}zDχkajvbNAPAQ9M*lvSj-B 4|R~W?x5j\vD~ k%mϢhbn<3jgAz@"2Oq'=Tf Z_GeڑWoܸ! }l(&+ashxkdŨL7KVi5I(0MʑH.vO5͖X= Pd"toAgAzT:布=rٰ%7"타ĜFe 6&h f0(^F#8ӣ-bjD.ͩ垙)vT#\:Ց2^o1Xb1Uq2iZp-hzjĊ 8:#XXu iҌuybⵍG(p1{x6gyB]kQfB4LEj T-$̘ b[r$H7\W:oE0F\pk 4K xDݡWY%jXq@@/TK ԇD9uz7^+1q':,~uzm,W X@enI (!w!"ibW,PNe]O@ lEp2i T3dRQô rk.8!lYA6̑ V.t2GGx+AW6Y0`ffWXl0Ξ>rm )^3O ܾ}jgm`{ST@]a11~|ر_yqM\zVMX08"- 9g (TnnHQ"3N\jC JJ ;q$PP[h"C5_c:-8vy-MJ"*Dt ފa#źO㦖=jV(w 2P 64(WLqHd(qUåQ i5a<9w #)3 AUxQ7 tGxᾙD, S\^MyHvn1:d>en\ aD_-Q*LH߲5]'ATjܳҌG"xBQjAsk-:RM1*qEF-4pJJA/+j1֓ Q 4*fF@!F@N*g \l7C.h ȇ~}.`<%!7+s8OeoXñFsji V5V"gvx6uȼN<:] ;d5dxH V9V½-B1E .O$ /'Mb %}/ H$al(Q&4tXFi%Pf9q/[4U,u4}lnS<8O'0@:%^6~7DHt4Qo_1Bf8{>IKA` ܐI*PMйͺAࡂ)bQ+8R0z?՛ H1G=b; u eZ`nA v+, m2#ʴڰ;9:11I "30RϊwagŦJ.PHE("U]}چQ|V]3>2(1U E@ke[-Ubj >\@szg昌ad!H[U {WΩn^Q\iYkju6lA[-hx,ζg|Hɕ5{^i-0S1t^_81ȐZ5+-"fv7sIM#UJqZb{w2P34 !CTIp RTr+CQdDxYϐ|@e~SJY:Lk3k{]m2"2"Fxч$o!xzZL=稈Q`a^Sbٴ=4hnSɊi#ucGTbݮ[m3TDAt]8b\?CZLJ? S|GPMw;. GJS=vovaqQdž}:s79+B f(H##Tz11 1%X$9Xi’dע .4["rFsIG9SiyaKcFXP=e-,L ~Ƴb0cdGb[fXDD͟C%$iS)r:Ug% jQM +dV-[3V#HTR"}JZ8q$zC`b<܇qt|܁`j=8ZkK 60 Οǧ>I\vaS~9w/Qx1dBc6N,@D['ø#AHG@bsݳɡ 1wӆMFWp L@+أS-yRCKu`E±Pmj`‚zHzbԱqa:G56+f~zAz3۬xIiFJ@ef6mF\DFH|ClQ#nmND aͯ^)!Z9[|+2 3v!^(Gf =/Όbh kgO_8OtBiY+q o;"ق{ZZnª38[sh`':Pu2G\kYz8A׌,YYzNߝBz@ODuG^)Yx?JV+-L.a "1&3P] m!̑^yVd踙@h6"߃zpi'$EM"`Q'GcoIb 25c-{F V>Ɍ*~PMidU\Ccr%u0ln50$A,T<,łi0sсrEe{ԅ84B]v*18?̹Xc CЅhDsl}Q%jGM势I (R%J^ /5GK{^7Jh t['򟰚Nl<1LtMT#GM{ZPT5 ^+\R=̦ IhbE~偱Pp IDAT{cY}zV 3K8i@Vٴ?A% gO 8f.E)m1J7ɗO.4,n+n7y$\Ċ}|8s]w~{88:ry{;aMц}Fk />O[~㳟ABel!׭4T"&ly*U18h):5(=\F-Yv$ xËqdt%ٴ)tt9t}D|#SZPFNsn>ʆ5p*D-Y|+6)57S48Di+, wcB5Ek%gޒ7״u@q4^7kߓ4)JBܴ Oh!'0'I3k];{2ܳy^PIEUZ|f`Ѳ5* b*̒anf$p՚Y̆A89dj1)l&MyX<`*#hԳ}/@UC1S0^mu'3D7R||îZKrX3i+Wpt'V~]̫c`w 4Ql߻\pԧ3O?~FDZ1`f <ϝY(=Fu;,uS'[m&ʁH LN~b8&ЛJ-S 6s3VQS҃h쨸ićLk֘q9HE@bQ!;f}܄uW&KlR>M>4xAW Ż{LYMHIӄFtItDiQ"LS["LZc&4)8=( a>& )!]:vn6vBE7((YE_xD|V:$]w 1(q`#IcdC;52M^,Pbs; ⇠\,gI83ϘX[GT4pжk1m LQ1q& kѽ ZPa+ތsn4 5  ktm. ( d%8Y L81>fũ [x5 =0&1DRfFMja4I|"ixgl0шZ%Tr3&MT͐ʃ ɦ:7|d L I!zrM"\icFO65yNwZܶ86t[Ί#m{1~( 8jvT-aA1('>ԒRqrvZJiU_24]<~vv̓OⅳK^-`<Mk6ܿDOs,66I^<, M,PZ=OJ!m,3Gǜ< 8A ly}9QӪW.4cu4RY1Z=(SA\ bC' "\muVWJWߗ4hMk%<[VvZT\`!]aQ "BfŖkNݵZSj3]P4efrf9+K5L{3tUFE}AE"HtmCv4:1ʙBq.ZoJ(}Eݓ5xbTI6mSVyx)ɣK.kiCM+Cٖ1h&CH u74%S:]"F"oB$IO/B+v o DfN_YHE|-1Ѷd֏34K-7ĚhN}il!XJ8Ql#-4&qCw"U_-EAkz0~nX@FVy5MxFuס\&Mlհ' šNJ10IYckhZ:`@45i  t Ms4|=dTUqCfRmkM 53!'t3 A\5A4fs$NSDGS G=țqC%Ϭ=J^4Z~jzѿ Ɛ-GIpa&c-~^A㵯|'Nli GG5Q@sEdn]7a]…G^gxQ|53F`s  Xl,ʌؒb{ՠv+Ŝ7FelQBc ] m3Z]8s2 RHzѴ7d(\sHDL =[CaaޖŝR[w3AZdRh m05aAi!tD&QE Zcwjԥ2Jh@EH E8i ׇ:Bᖜ aF>)uuȪG4)uMNdٰ}GPO6!v0Q@^}'/MhR|& 1T pvP,ٴ1f1JsF GĔ/M2S"T (T؝N_%?"t='Q W's$7mu~a#}?YF | dVNk|xOV;8rYIG=U ,:?vlxQqHi6h*۩qfvJ2`N)FQyW҂ e{ޛP)Ne9[>`ٌbuS"t^\4.HЙR#Іz"+~ak5TYT2u` +n* 31+#%Vf \Zh2C^du@#LRN7^HHJ IBnv-e()Ɍq:ﵛiTQdOA>ڬ͛8>:Ɖ Hk.h j:BRX$!4r|!oufa MrcC 5]hT PXަH?}Y4uJBM{ΊͩWc(IQ,G9~TR8P@-(^EԴ`wo}E9{ [nappt;q:McgkNLwzW{L f07BӍpM ֩M7batTʩA N˓Fh:gOB`.ٝ^,e6TknСhz$i`(dM91Ad0#7#.kט:"omjH1HFjlj ՈA&NY9:f4MdLZxdƊ&iIS+V }VwpBl hCo ג & h%-ܥ{!FFn@5GPr64;9ř;l lbMK %@`g5N3˃Z\#^RTPuD$gnLq4%b1C rwzIq03;Ol}N9ZȿcB1b G-oe"t *e4{1p}s$tmJ^u@"GT}7DjAF֩}3BB\ki$z/ Xۿ DR$>\(ARI`9Л-72d)L.ۃx@:JYN ]Bvj>C){?ed$D?QM㧢 gj;FQ /n='j9ޚ w9FbZ&Չ rHO:!sYH˪ wsR )x$ 閄+Nj7m;p},x70-`R/4u{յR,%Mtp muiQPB4@!cM+8NʛQ2)Z>ƨ2N= (\gCl!/q:w8֤gi̓PqVRc&';qEKNj^aooG]'moGqֻ888~ױg\v} ?쿇深sgMCU-oAaj8s4662q-r#2HQKq3>!ZQrߤ5qHV'B]B49I"AaSNb;N;,Dw"oXOI誴Yɺ TUL*y Huר]XNC}0Ԑ? 6LRa t Z } $&{X5j07S1t:"AMdƳ TS)zkv!*p%N^ Dzf N 3r2Q+fO@rC^4k:-$I&b=r2 ,-]Ρd͂\z XVWhrsT@{!nJQI2dsrꗫ-BYqzl8`1d0xb)$ΦͣK va;y1L=vg蟄f޻Z}}?k7g{m' `Lj(!i *R&HIRQUDmET()4*i&Clc1`wۧwxӳ ٌayu3V{-;tH]%7lwl6[;/ 7ԋ8{TDL%|pdI%\J6!J88ƛBL5B5/MVdqHXsAbI<(J54k %[ScF*mK' ھ `ZQej82 KR"َAqy4 6B)e6VJp #!# `hxN BHxk1|M%j#89܅}-"yVfvŗN՘4Kip[SS#$-6lMV% 5U8k?liWQOQ+,'} @Rz@c*E?\qo|ӛqϽw'D o݂fC/}n .;z!q=|U%֪n muvaXd*vI8=9J-?K_B,B4eNu[#lJk STX p0O-i@8[.'La+0mJ]&5٩d>RLhGɔ`tp| &pȎMGmùFmҊoe֩A3w|۶M'O$Gb,)`煔X8CuB .PyqL$J̍RX> hƭ\sI;\v',ŤڤYDc4EnhV@8:[OrQ5Y-l4i QM>&Es Z dx/Qvu+@+Pఆq6&5f %!7ɐ1T"UZJtp \[ bMlh,unrFpcT,[&GA3qYԆ BkQ`JLvAZc-ǒ{EͧTSJ3^dMeD3[ư6?e}"EvZ.ԜORz:eɺbRyQgu}3JEܕiV>R!$Jh5(kg*.ɑA5ɜTCo>/p  X9q"zg"ąþ(vxsOU<{|)lw;l8=='Nq-%rn|o\T׿q…ݗ8?']\= vYpU4 q%pz|L'[fejRKz` IDATne '5̳"ݣӆ⿒vr/eQ͡˘')b_ D bg*qi9xif$eTdٶ}` oGxZ^@[!? MoݙufM.Y;F@#eC%s%0GS@0&ωTB/~EPH9\cw*csUY]rXϛzCgbQ73Ë3l S$F2;'K)xQZ-x BXǙLc)?o/f,Os||vOҠ>U+,UB)ȱb~b*[xze $93^:b} m@"ILdԤRcTZ@45@4- ng0&*,DBG .SNnxqx;މ> >`͂ӓ-N6nO==[#Kn?)z?#?'|/^|o>_sR< Wq۠Yl3EݲZҕK8<$36{ЕT(%xy)\Y=NN@RF9TbdmgoEPD1 z,bR@*Ǟkk5Yݏ9%I}J'kkM_c3w>jmh02\d^)rJAdD;zt&jzHQ ܟ=HA0 lFt'U6),kLV^DՂ  zy_rFG{xr=oTы|eM%eέ߇bjS>/n1iU)~IMQZ&1<1$ƪQ#N (hsqI 8Xx ;H*ޥ u&%óEk\eiЌ* L9m-}:ֲMY 5 +,#2Ċ1>z i&M)7JGr2 Myҫ ?r(2dk"Υ:SS S!#rFeCP3M rQ CCˆ6, o1 %(Ň n4~4SnA rϭ[9=vKn^%)ByhLa ևf)RSV_*Ir†Pm2r`@L8JuJ@ l^y/,c{h2b`CSS?p(-ܴb[1n|=^l >k\NqG8>= qx;Y,;lzWܾn^=|~/^k׼_9PLfSԈB9Qc!b1pso2&'XOfWX gۀU(3.]zEuqM.7ouοͶ'PP)T-h&3( -砎wⱉQ.GϞPxC![ BnmMo Mp}9]`BgA-Dm4nH³ u΂m8hĔIЩzF[ *[6bX2S/p .%Քq"G-`.L̀;˃%w 7eFSAzyp E}V8}~Ki6(6oJNwwH ,urKmv‡#Sϓ%ۤe$! mOјօ'?!hYDmc(,zޅZ=᪞MÈg(!g)LAR- uVTԸ9)ouy|-]ܚՙDE(. SuPz^2kN6;o ŤZF`damLn(p=ln;21SVml u_K"ϝ)b@cr#QQ%lG/K_,c3 /}wbo_ȿ /lOwXvlv}t[/vvC_m<˂7<&[|~~,v/;Th_/Z}?í[++:JƳ"G[$3[\t/3\8IIh`"z#b8Hn%Y!ij+r/#"3(?V @gP)d[.:hFuFIV! ~VrKNxm\48LN,AJb)R&-{oCU_jKVHJHL(8jSn!6j.$ i8] oqQ] o@IIႦWQQqE* Q]O #CSFZi񇝉BDeU|^[J/qq64?# 4Qw吝&7ԞV6CwpJrržp9}W9Zb bYh-Aj[dcc׻Ikdy{?AU7&Ƴ,H[P-?kur'b%#ո7voQיY6H Vg׳ 8 fSQ Mgֹ?q _nN׽xsPl D2.;B_ij%0ܷ.9e Ǣ CzQ"W"GP$XHQShJsC0\MޤjQHunY4iZGBzr')d\)8>d*q-8ӿF %4ȐN:E H \ͽߧ~l"sψK^T4eOPiwex#. &xZc745I4Y밋}:ʼnDX%?DTZ9H9”EhU|lyBnR0-%hX zsJwiOnLFV^R}asy޳#4 Գ` oQ] ْD\y.SFHW7jJa5lc}7xV3DJgA[RwDVk:j UK_0*L1*9O5U QQzU@XbiDi M2'EI*Zhl!}4mJ50f N̷u.Mh|FVY$Qm^y׉@S](e"b\ESI )t!% /Hn*·d$#?N"V n^[oc}>OV4ұ '68=9 N6[ޱ, vן!._?Gyo|ӛ^/ <3l4*XnEv+/< ﯠ`,,_u 76! + Wh,"_+sD93Nt4.oj, 1C0Tg`i-{.0MٺHAsE*x*Iri͊f!^|aqQ61L}H=v8UrRr钞@dqK[+ w$|/x4EaOy y3sSB5=Ƨa.=t߉= žeᥫ)n,%gcH‘oF pg6a.Ils.'grHA[0: rad^c]q|x U鍞nơAT|Qə?RˆGւ"+[ gLbطM9izs7uԂD''Yl#ZmN%Hg4Aqv="yAK&Ne>z5 Kk]{LJ<}įa[V+l7l7'X[lv;lONa` ?9W w{qꕗ_ Mxy'.n ]؜;܌GI}Ծ2 55l;<r2G-~}Jg؉]y1C*PƬR刲mHyӪ*bQr0{^)5RCR*͐4jWasl(CI\!E H ?aË&ـH/>E隅G<zBFGn\7nVc7]+WHb(JcTݗFg/"1Mnxk6sQ%JR!@eJc+שſOsu=ȇb!2HH s&J>_#qH .R Piz vIQfFNCmf*2[Ag|={ovmES.匕Y~*Q~FNLX ,PRxr!dZiWE 9#侈khl[RxDMj&HC=U{FVܫѴ:O/k7bjz\m c 3mhyedb/9bCF(YkHH8uB/,]U۔3)ҠQ)V2r^J; 0kDekn@bJ"xI5.]w߃+W/۠֊DLe+Ihp7ϖ)ANgNkLQ9%CpOP+GcYc%ֲuVAb<Ċz@6 %B4fJV4=7")S,nw8>9t 25K[cO~G{}:l?=,v!>=Ac-e\r]fya)%(ij |5q\Yr؉.UrBN_WBI9UEǐ&we#E:Z Tm\.mV<>3-8.RW Ajd|UKu2t{HĕIH$T~opY3ɣAƵA^uR491Dih`ˎcJo>eG G؎pNbJ!tqDٶvb_ ~ +.1I`:͞Wڬ*Rǐ?(ȕ#_2=`ŰT5`3v1g&1[< F6jb$k4XQǮeB6ԀԸ4f@ (圉rmXaԣ^!UvIB 9ĝf8I2uTbӓQFtee'1 Me&|-$#8%IqXGGM{ޗV6X7i.~6mr}N> ?a^FC ܠP(|`/s6ݜҎ4G Vm{$ xIAf]m8٭M-CR8*NYF,O={|/~/e`u,],['Yqn@q|x݂oWG_DW{]?<as4[qH!ʔ7u_a2z6}@1=XpdT`Uq e\OWQ 5Ay+X<(.]=+w̻2jCirb((eí4(!ehB{,VYZ]ϥβ/\=+ti"nN{~Fob .Ja2ZbLKMAve;HfKd.q%|I$8/<ǔ1-M*r8Ór`ZFޣ!^˶9O\JjRiE99ަFn3msHyQךg#ZbS+1` U6$~V.6JD:fIʷ`@qSϕ R`W i92@Lès*  B66(8Ȥ~^L9j`0ڎ',7ER8 IDATѳ)A& o'S%m%l)EZ"6y"+۞ ͤ i{0irG -f 0dڽ_,R!R#+cFSǝ:nAT'JQK2V3j)DZr)ֳ,̚һ05Ged5f^`NV\b+gQE^Bf14Ԭ)؞Q $eCZKZ' lZ!XT3SM";  *q QJV%U1HhEl9@X1ӯcÖ'E}wV9A_X"]TAy퍌o($d34D3v1y/n U{&\< CG~[+##҆<5a\d_#?q6gW( 1bT (F,]J T˘x+kPɯ?LXDK78.]f]liBtΚ+B1oQ$-I*_3>Dٕ$"9$5mr8F2dP:ĠB_ƶ'ASΉC26-ǹ֐F!#QQS?%4<8=Mw36 x ].<3NNNZlH26* 2"CV%Kࡇ?~/7/p^iwt,ːt…sznݼY=0j9 'An9qAU /!_dݥHs}"FgI.@%p[p%[# pot:ۖT]b%-P `(%T(!3f-IS'(Tv#Q?кqh'MR :!.TUIdPRQDTȲ %I\RhlE@3#ejQ=ɼd{E։1xVٳPdzMݭpK嶛rk1O0(dDI $'QOZoj.'leC#D"*ki6lKrYIK`yjQ`AǠ.GɄTraP r\@ɹ2"6nkϥQJ̓^IFsB>!mZc%LY)8(r5Ui\RrxE&,E)? g ^w8(ke9bpM.J1SɓTߠPv˲$>D*@.uJPYH2C0q};.-TqZdmEir~j2y~_ E%>9|3W܃~䣸~:yAv;HO˜F3'kY X> gCf%T)JfA φ@S# *U2oKJc zRޒ!g2w0gT`?bR[\ x˲>/xի^{O|ħ>mn d650mn65Ɵߏmx[߂zr#Ez{?q=wa_U{4B ]w݁[/ .^0r*JQa, @'<%c*m*6Prȷ+W~,&chFdLT8 G}S¼|U?{nЋ0TxnFN:c+_Λ"*!MOb T&=<ec4OzEc:qVT$`ECFzVdylJ vi{dM.O?G%@,2͇.cpXb볢-r3{CVSC%Ajud$a<,̝lgSVӬIS#8,CSY0͙> }ʔcPlVĵPgf\f w`lz@qga毠}v)efmԉTfQ%Ê|AXty>tƵVZFGg#W,>\W9@LS v&(0!=3ls|?jj %Led7ϓO<>|?v{];&"&B6 ve'7\L_kT}<(4iAuCGy{ vOM++;B)EJLµWtJoYZߔB z Nu`U? _1[GíW~#>gyJ Y:[vC7W<{}x[ߊ<(^r#k[O~q\p.pQw#ҥ ubXDM>f\cR(ܣm*!1Y<Ƅp DN@iPTFMiKY9B)jH T[F{A(Nw}RyTXc؆LԞtNψvi +(ϳS ›^~f )[=ҩ3'B'ryHF4ElQrZkٛ!2y_S:fqCˈGXT(c^u .^sNF!o捡*i$\7"N#,6ŜPNW60oerZ1 .flM\p'r*V!J\-Teh$FG$9!uݽGuk/}5g<`UK=JS5Q6l⹠TЕgF~(`]? FUm"z qQD  !*Z%qfRVDɶهsbF]<ȞSjqCJSlN+EY@!z ʴ{nV#Z% pNf;2~E259|/QƧ!ʧ]Hy4h;|0 jkQ${qz#k\r'7coo6"cs5V!pFo"%27K$s{ڇ[)g'G*vCIϘvpg,) QLyU;$+G((&UxpW=t \D1 @giJ;d?n#lNјq+>uUowx'>'|ǧXRgu< 6T7wx7x5_NDO;..\@9疼B[1Zk8"~\t cƛ-ZV$Oi(FScE4H0vJ)5d,Iyizxf@;6{[H4.1HH $ߥ]黝o`磭 "@H؂RlI)&l =)!狧k+)]*6ZSݚFAl6M~gx\( FlIXݿ $Xs`zFLG@ih*,Έز IfѐT?xZCilyyFSDXYDnJ})v8K56j {ZRM6UMPnoI~0՞W8<)S^J.x<+: ygpY}RQEjý*S3;"IgOOq&B:|vb+*ZC|e2,2|(F-=M3k`SdK" )Q6՚?7WF}zMJVj5zV]nOUbxs;R2CWU(glwEF~>⡇_pwo~=<Vmm7-,'+MH~rz> n+d\JclYhGr>JN7=2U>ݝkH̼*'i+hP,Fa4vS֭[8<R=w߃W=^75{wsO<8~㓿O'oNVkq+xL`h`Zxo8_nK|"^۔Ϟ7$\AlM_CUqFsu-QS6ρ&;.>&-FD*=CXՋIP̀ Īs{1o9C"!ebVeWjP dnY, n. KpΝWZÍ7q5p.}ՈJo8~b#|bnfū~zիq+_իWFFЛu3>WohppK:sp=W==SO>zKWKIRwXBVAlJCYVHv1:54ÚǰLV!ugc>R8ޙl,6>;utmm!32R/Ic,X*)?w%*dC'1$M3k,gS|/jvh+Yap}$r~x3Ob9+P˓sʦ3GFIQT0а .دoDC&Xw'nE jJBkzL|6l`XJin3|Q cI)6okc`-vz "dמqSNqD]KRAQۖZpCBl"U ߝ 9 )⌀>Pբd'S B4>y K DR5O)>s&*,7A KyƧ-YMW|hh SSdBס颓|<dIA=ZRkr!D >fƳ>}iWptW¹q얎'O<8n|'[Hpc;8>Z50YH0σʖ?$3!Q4eD ao]=DUcspH/!IlS@ N0Ow} +lX-%_Em:6~(z_}hܰ^Z{8<./➻ƥ˗@ ,}x7?nѭy_ U+s55fKO%l\=W <#x[ߊ3?8I K|7|߯?U_q07RAm8_eӟy;Uq A,F* zN)AU[ 3S2ώ!ڨ)ٲݐyAs5ZK4@ \ 2ʞ Xtݻ R ފJ+ dPuj|x /TH?:8TmI5i\&^3ƻv C̯EN[{Ԩx4 Qq\QpBzrOl1,-(`Z b*Q%a(Eu/{wP6Щ-T I!iwnhCrJa0.bfծ7THq\I8xnZM{( fH3et>{_lC.Ҥ >Yt=zx\}4g>zs5辚)i>71pI E EJ\K ` jA*YT'5H2'B:mFzW^/: CbPq8óڸDƥ@1䏡 8ٙcRJx6kضsԳTQ lMWlI"Ha0ߧνU8ܒJDS6&dFb#(m&3#Z0ǐFdg>X3GYF6_j{>:m#"$( IDATOy)/_Fkk{p^?"n#<5ܼqnv.2f*7j*907:!J~SBzN2#S=n(l7SN3 HDL@`|@}W*!˂"[ fj@KX7⅋p.^Z5N;1n͛89>7n^[8lnfk:%V s\z.];v=ƿ}F+~6_knd:3T忊 zŤmxo1Dz:p>nܼko`W/_t[ 4;l`ij)O(|l^L/Cz8 v b +&J\`)p6&D6H[N baHjxz}W Sy0j] 6m $ vo\iYccAx( e˥B-\nYZ XvqI 0r$+C".ϾPg"4k4dIdų yRhb)0z1? I58੖O"v6NJJI"k P4ATZn3}n0. )j5?#D!pТ|J?L@CkFEAo+aw ;ew&+הu QH ]tikJ(Ba,?e'ZZ22j Ԅ2 (]k2iBU:SP ɸ/[#^)Z< lcj`d;KMCBrT^3oK(ZZш@< ''nNqrzۇۜd-16ШsRP#CDѽΟ;@[p߽=o!uZXVcTįDWRj΅:}|95g~_K Ow`[bְj+嫸r"}i\ykePu |s6^K,e4.߯7!C|$*R~ y&T"e rh۶BF uJ8O 9 rم'UQ!A> Qh㥈zm)fac`lOj4 N=,(V-E>XJX!@m<~]RiYDYRCΈBdtԳ)w f9qi\. KOKpJ؋bhpiEAsP~ƪ)Oߪb[q.jf6rGM#ƚn~10Ɍx)nh}z)D>T"#P=#RrL1_kqIC۶*zwIe0_-񥂉$767j4uZ oo7> O4Շ?qH8ٶV^`/^9c`6n)wHBa`]u$RnT֐!PSλ0|4cVdFǔX'5*~mj ZC^@޽=coƄ;w0ds1X;a,X,`srnvv, 6}Az UPD&(g)f+t";q7_/ij6}_;V| Yq~7~'|jk?&)Yjj{/]מōp¹sԎ.jB=RNp + F#,T#8|*Aa$ehjhH)&J?B,Ana/G_~Me #5$ήfjTKh1BᒋdP<F1fG^F2~)JC0PyO%G_(E6MQޓXlimC*2?V&,CItmJN)[SNy&7'MlR%MYȉ{h/k S#/>l &OÈP膇fՑH8k ;LzzfE֐KE})[%LKI&IEbq.tp``a[h)~KM2ųaR4UgVxi-+臨đ`xJe,GLAWmQ6-ʶ0QFɤ'Ȋ%:W:w){:GPk 2"d^"V٤sTS3C8|K9HU|]]dw/-Q$ZVߙje9VʜZDӰ+i<"շYc85+3$ֈkυq~|#(|x:.PagDTSaYEnܸÿqxt C~npVnk0nV5.\Xj+k@kv !D NOO,5? !N.PX$Rb`b)XC9b2Zkhm> 6-X;v]1>eò9;6e&yneNvɐj3GT:X9B~KqU;oy mƟ j5{_-}KWzfpU-?ҥK8::p 8V0 f __y?7n<7od;0b2Z78EDpYv;GErD% 9A^g!u@*iAAeJzC&]s?vwkw ߞF(w$izĦp.3 tB!/c">Y%(fکbaoR5fQm>agaq sSc L5@zqInP&]ITg5%$U c۬D9 Cue?{I QY9Ԟq|/UɕN`>ʚz!$+U3{]Ô$"<$1As@jb)2q4109 h :-إĂDCf/msjr,Qpj/"RjffSz^[H]웢ОnY fLMbS[8׭Dk [ 1%foL|j弜^R tنІ2+9B0Va[qi_* H(ؾqـ&q6"5'Cp&J3ЖQCgMfmZr,CK?)[˦HnM;>Ā(ab}[8ŨR"/VPnrߋwN??o|O} GGS bs[[[Bm;b^7TnXj֫5{`SteAk7RE?6lFzl!LJV ̌ӓS D K@Khv6Ѩfa9jnv~a;0v;`ٍv`[q˲` wkz!~ÏZ5:yN4)#^.BtQD@̸x"N;z7 o&|w}^7|4_FkJÿy{fp|Os~?_?+XDp!eg ޮY[yN۷{f̀` /ARtI~pqd!AF)M Wws2r}2G:snU<{Z?yw}vx)5L፫\#`)\aP=9\J&YiԦR/7E>qB(y}IW kdiB+;^OHTJ&;}FfCn/CjR*dRq9!R/Llr#cTS%M!ʔEQY9 N5 h$052b3-V k,(4df/]]Feə<\n@ϲIsœžs]wF,ԝIY*3iI2i(Wp8s鲩 t2F )6Fx̂Iduo?E6J~œϹfަu˒6쾨Zߘ^dg4 )oƢSŠ8R*Ms|!(cqzKw8; YDYCJa&nee>42Ei"bPNdiPi\{p4^di2~1SQ$&I%; ,"3c]Cj QYrGÈ`LVe, l% WCJ@ZMV,N H XZ2 :ޓ?^ʣl*96iIwC)YLMQX ئ ʒJiR=-\2sZe" x!sկ~{? WO~S|u l?`Ɯ(HB+A(=q.pw=}zsl.F>;,<z'ngtF0}t/H~Gz߱,a?q&ЏNP =q 8`C ?#!xυNHR *$DdVSUXuM?e|t- cY<|?>| ַ\%O9v߽{kӨuf!Pq~m<}/w?tȰK麎=| ]>@nqs|Ǹgw=:PqFY Ę":4JfV rVEfT^)1:FيفfNR p& s(xY"x`wvLxz`ɦ6.BH\x~MVĄ&e{ne>x9T#ɥgYeFG<U2wӱ7]%`vFBIwT""}y* BYv $]XѲ* bD!Q%VE~()2(<P"2k=+*Q 8g=x)(:A7rʬYWـșlߡNͬtXb(%p6\ Rpb IDdBC9Js5!N29ٝ8dBB8rCkMs($4ʵёfD 5P7aN,lz)ܿ6Agiyସ2sYL#NYPNP Xg) ,RRT~M OqVʵ<. 'O_>G}>8$e4і72{,O1(L] Wf(4u\P璢M!9Yed:,B JNh<N}l9b&W;dD k&l SeӜQ:VAgM3U5X .,5q^$%\287guII&EN)NT;MMK͐Qi&M)g.N'yrhÈsd{2jU&Y̐k `Юl!z@9S9ɼp%9<2rq0ؕ?ycpApD؀qADx?O'c?gOqww[|',@4@G%G3DPJ#`m #}yaC0֡c'bkcMlv"4>1C|v3hDz1fM<`p*9US If1,36uؐ@M]Oj@e,HtO~gP\$l΁ TL@y62 :u5 ʴg$e$D c'&2DF=@1! ҵNב0mrX{$ծR̉~v'f<'@x (;쮫P LM$k!3%)נ_sQoL3H)ܤL;\c'LlaLOSIwAɑ}6Rtқ#2R2,>AH:t&1HH%IM (%9^JDc\Sd'WX2yLw KE~O Dnt͋xA07| OyCqH0k&nDFjiF T IDATs{"9 jW;vJK (Xalje(Ɍι̗\F?F'7b2 7^$i#IJ_ŐtcgsFy1/D&T4uLq`f`\2!\2huufX IK8x1~~ 777я~??_|!ןcv?"1d ?R+"#:_tfMr ڽ{-ˡG\\u7O)7~*oëk9Oъ|-`!L-_ =?~wy~ۿw!>\ZDZ6ْd D#Gx7wx./uW;Q>>qD؏0FJiٮ!ƨJla-8z{;ؘBisޜA dSf&riIݜu&f"2y#6O'AQNGJdiP ĸ"准zADB&Rl`INʼn}1J\DhrX@eA5S t~Ua&,FC[~WW"2cUWٸ5^ î1$̂YˉhNϳFMuZx;Tmd0ɤN%ՀL1(bc#r ^lZ$Qx"K@n؈yev\$&늪k7~ube}dv󣙢o K0(E^!JCy7g}??G|X? BaLt0x㦬 XpkJsvz3ݯ(̤2 fMm<GkfEk+5j<jy5ۓWrCqqyy.vرZyGo&?yҧ%l_X=Yc LkpXu`XAk%0 ?}љY`vg]. o\\^rwwn.0xx w|4l"Q,0XgX|1^D ϾjM D y.E,3;垭jX.mH#Gl`}6KHOgDdr7> 4;b99^:Rzǜϐ@Ȃ!M[YaC&[K3̞tjɠh e$jif騮CR mf-`Xvua4şa%ٳ </|?/_WOcT\_v]ĎS, L3u43ud'YLcsBmKDP9=r  ϞGӢkT&I*ECpa|7xgϞg?o~O1wC4h]CRjt͚.{}ˋz \\t03йȨHy;ca2zMGF=g`!`*C#MvjDlVcցΡ5_Wn-f A-8>)@{/ϟ>ᅬ?ϟ=gO٧bFw:3X|emuBVgN?'P:%{{O; _4)OK!;޼9%r$xt;n1 \л9[\~>/5(.b{LHmkwzcX2KKـ&kFXAQ$ɲu׋lT='? O?+>9F@xPSNyJH.ecc4X:r3pcz\vE":Z]^!ߣwQ#x]8?ml ;GŮwck]w1-p] ! {L~3aa7ny}a0w;8p~0G^,d$NJgv<.Yv DGEHW,ePba<15AdT% $;ߓP?4$cóg~@^鶥qC_ARr UpDɝ-f01acf<.\[3X\]=@7:w;{]p xy}BU[P/y-K`p. ֕u1YAvkT-01>TD3X@DPXAquupssO?|}!>#<} ?}k5www-ny}IBf&Yah?ŖҔeQ<KJg- &`2J7Ьu0#u,л ׂZt] c>}=v'dۮ1;~s1ꃥ9}pn;fO'v}dx֜#.\( ,G@ƙ0D0% 7 4.qr: L-1{1dpPZMKR5Go G RCV{4J}|O̡XM䨘 jbG<:ab ^ˆKlHy]rIV^ZYM,_L3xqtIH~фFusaȠsBdl*cb{͍ ɖ kLIW+"mU=X|I$hU{d"!;@#IŘfhYLf]̹RSuNܝUV#d'$'4md6g SaJ(PRe[RNnmM3FA)O>AsќBglrZk' 5Uݗ-)c!ր8^0[`)9,%O q ]Ge-Q;Ź׾G׹P~0c-nb-noopw{,a"6Y0c\7|a޳F,SA LR1UP8!$7- MC5,E3 TZuΤYc]\heyѸk-X9Ha v6BZ~90vQ(aD.;>9Z  1;a`t2Mlg<8=zcG8sNĖ=0Ţȏ:gqF`Ec̲3ѽˆ%s~aealFx0!KP=qn/nD<{ߣsuFvZ4v0p7".;zSx?`q: =?GYG}./9sYE8ȀuB%W -gҴðXN@cqcj0xnHp ]0>zk-w8zqh{ۡ/9T#^Y&:XPۄ,1`0FX\a(X"9k  mzIuQG:D#7ˆ׀'t;1fxڙشqb yZF^ 2%;Ф-fe`22Y 6grps@dca뢏`aj366X 6Ng d"4b\'#G8l;vdkYU y٦c&b1l=O=f<b}]AWM#Ⲍ+}S9D)89I^B:6/Yy׃"{9V~p`1Q I; ƬY"ߋ)6G`,"q$=(]FQlWqFFK^VXg.%nl8خG R Au=GtvG E@YH|)fHx~0R1>.-ώXs;հ5qAll75O0/#.(.̌k+'ـq Y7aC2We.&Ƹx<.=KwZ6l@6ےİs]碌:X!_C]6 l)8[\4ϟ?0zt=ŃTTX3b.A~̌ Y6޳(Gxc1`#Mb 7QUYI#޹"|0IX{$f8C4QN~W6~ azc\\^ϟCg,¸l `U& 0#l$lkzk08>ȳ"qw\?1dzd0r +4Ffqxp}wzps7b5:5EbsLq=*&ba1ޣ3s q+s\laIøGg:>>0&"3r4l .*2qւLl3d %1gS׀~ϩ< ԅ_%,At[SӅrtˌapaw{f9׊ ~ǟ<q7@NHnXr C=6u.Y~aw h"CtCGow.?~ 6+fh2x1Z$0Y CJ(!1 VG q  Kǁ!>lgV6PlA1gY[c>r=ޒ,_^ԕNAtlL6bQs9F!'(# y#Y 'uI3,OG6J- 8f\ ^tDW,,g"ܤx^R9ѹ>Jl@n9ͦ: @ʖiT$A6saI!Q2|Rib]<Ȝ_4=ŗXˌz?HZ2esi1D5 i`ys6#)83:r35fbAu;*3B{XqcŧNO>κPV2|$:G m݊>E9_#|F9jIRW"[x9(짠Ƃdxb<]Ɖ@&"c)ͶidSʩL R[0 Fy Gs<ˬgB>`~aŅ OӒl M&lRNMfMT׍!6()g&֘ Sh5V:Du0(ϺȘHY-1lrc8e{e*Bq-icA "&ՠdK(k;KKCk3k(=TL\n@w{s(Ï>'<ŧ?pss4H7]8qųpnwG*i[%../p./.q WWW =z<%zvA},|cy,X9 8DƔfr*p8woySfkMƐ`-gIVg w?d ڐS-;MmPGH3XeInrsqvux4IhšIڇrPb)O|H L`S>W0ɓg+P?۳Σ# G0r ipS!$#('?*xVSU k&H˫#~ 2;t5a8R-(f$Il<.z&Ė!ęKg4 s;w!Gقpl\HAFlEoXffw0&ALJ$ZrΞ0ָ 8=ix7J53`M(RanH\ hg699z⴪]H3m!|JYx%FA8S$1 i&0u Ck$&3vy2H96EIDn0@i_4HEI;*.9҇-Kj@EM`JGDYg_]ߣ/77ˍD$HA!8!xDʄP\dO&`\ <+7]SP9)X=3YIIYPZ0 ܲ˧4] ~7bB9\r#}cqJ [r}668LSE 5>)Y KvLY:%yvO@ &'iƞ4)s#/%'i\D+Lj O'H6 (=S8s|ecZdPwI'1GQ.Hd j Ս@Ivry$A._ i2o8L,l.2ɓ̒Z(z2i;`;z6e)²hR4/X+b&%1TKs=5P-Ӳ іYqN EbWc1Ȗ}%'68%j@Q~|t-(l55w Z` nqm,д^S麲|JC-F >#sNƣ m Tk"{<(1r֠J =X՚#}5)Û3DgZͨu3w_W[K5~2(Rkb}nkҲ]&0bnyQ%}Y ;4kU kdT^(Mk@l>~zkMڵܬ ԔWן&$6N@f٧6 N" %1fAzܨH}ҥ1m(L5M3X3:HdHES_8眫(X>Co6 0*OLqp_O=*@oqn`þdZvk`)T85dt(ɱys׃Lڑi8d }t1z]D]t\V3R w ziN* B05#ʄURyޯgs+Kn&{c2SϽ~/D5iG[[$AXj;@Yc,ϯ} sq,'={Rhg!5P+ v]woqwh(%scٿ5Y2ܧ5dZo-9F%tL6\9'bK}%@^t|TϠk|ցZ1oyk著-^ʱb)]_bjW[[j &rimʵqzO[@tР) (Yl8f<=\dnQfKfZcy6UݚKO,k(ORm!׺;-VjJ9K)^~a(u ,WmW\g5 Z]ٯuJ&d4xה.UmiC6TcyQܗO-b,S>XZ%c٩@W>4bo)BQUP>Qy5IOV-oiW6F"YPF?K-0 @AF[3t(JV6s xUj=[klefS0%/}뚖JA6֤aҭ.e-XpowuͤϤ@KgjY'S& iҳ]znptQMje>-sqK@aj쫙\O*}rx1~ q}XӵAT[fXbn9c -ϜkfX249庤ZS.T ι6[3k*^SR 2ƊPXU z7amQ_M97{ؒ浭H95v,tKf4'L\_ XRM5YfM>%W;>OY ^oWk!")mݟTBޣA5rn )EV3&Y2* u+7b-79zvQ_7Y.-I/Ml6ãw"[T=rZz9iRŲ6v6YdUvFeNr[k,5uZ9ZKȶZ㐁Y7}M ;9vd0KϜ7Hꭵ=Vݠwy?yֽ^wjJW[k@99wm?g%kzKS/Lst`ښh%Iila[5@ŖJ"%8XN-ojRvY $ޕkQt,ig~Nl5kA9 9j3X-35ߩZNjR+:wϖpc+iQj:VKrN;epeM=Jyf)LL=pR}HͲLz>PV}Ziq[GLÿ́9nŬ1Uky-Jktk&/;`jik5\\d[/Y{5k%lI2#Zui1jpֳZ-I-f|fe;_{i`L{kX2/Bv1%d@.IKe[56*aj3K,ǜL),AP 7CM2Z(ZPc!kفs99 ym4kVҲ8]ֆAAȹH5UV`jF>=p];s<zJsT>y}jSpj کUf[ldt&K9HKϩ֞tZԊ&(g%56|p!KktՀ6Q[@Q^3*3ت|\)euo*h5wO6l ^fA]ﴉT4{:wO8+zP6Zr֯RYܓsL@us7cK^fq벷̴z-7~-7[n?>"[1+jn 5Yd Jr$n5XޯfnӒXo:h}EܳKR%r-5dw95@g-{i(g ZԵmkny_b[ ym?k ~hp?u%eSV11,l.(j]  4;Y^|vlPW3cYsաQl.Zv8=F5Ub"%V,5pֈ%[{%sVo1m5c5#\slRђ5@Y XSY2\cZaLtXΥT&98nkuQ2-s~k}xϖ|+lJ/-leb~gf4,ٳؔΜs&$-mSA[ Q%.VWs ymƉUhl~ Y[:\\ւzQ E.֝i-tּ~k uijs\ԏ8.&-f3j7U[EFĖBzij8>CTk-Fe3f:YbE.V9HTѝ9fBc6;LJr͹: 2Gt5\6gLjcR2[ic]M|0AYk5L5AKtmҹkZ)S-f[j2,gYOϥ:C oIN& lt/f2\[` 9 NL^]jf2-5R/V^I1kh@5X׶m$KL}%VccX˹׮1Y:Fsc9THâdq-ٲnkR~n#lzρm͂)3U]kAs˿s5 ZfzlŶ]vT{MÆ6Xb8d릔yVS\4DzkY9VmX<[GA^vINԈԙRT#G[i6 KI5=&UMUZ}9ZJ;WOUՎ˽e/ k%W5Φ5ݳe3?[)5Ƭ8nδBk)>YԺ׬񶀝-z-pe&1[#$N [,[m)[NKpY,~KRS5[+9uq;v|sς9T־/Ks=ify9ga椕4vLY "XCM$M6W-t6-5{ .[k5j9~-\kbך1^3Bt仵kLg^[,5[Y%bC&C_;xo0*cAXԚAKOݍ`0m]y57hQ@` H7͵]́%9HeW-9 ݭtmN*n(kƒ[ֽih*vVik*t~́zpa?4}KrCͤm?sʜ4 @g pm&4,֊i58[ҽ^nſ{M@Oa3~1f1&AC欖wؕ9lp<+5rAM*\ϑ9`NK2Z^M oY8Znnnq!?rl嫭-tZ1"K- g `[~l. cYەhOk]kLX-YIxl)Sg,|*]je$8=̵M%\M[lz[e6OfX q2[αZ=Y+_j5c7NoGԚY-nܭoQ@mُ5s$D}זƒjyI@CAEv{s+;ڥ͒Ԛ ~/@G[:Ɔ=׼ւv-[fd5Yܵ&xFZ9FK `m~q]inm]\%WU:plZ؎%w;fC}F&ѩ TIDATkܿoj2i`k~(h[JiKN}9mU;=VZBwl.ӹ8us+ Z籍-S45͂}ye]ji]jmnTgI%g+_`#wBqCk5oP.޵7R BE@Vx,X}<\Kdsյei{>T2-w px95/\c:QZ\X+'";k1 Ou,[\ b JZ3kcÔ`T@~tu߭ňbnٯ2ޤlyms-7ѥ895ښ+_@xJwyF װ5I[ı-9[B T~4cޚE_6|fdNhLss8 uF&ifLr-l5Nžm[3-Qss}y>ڠ/ZUpcqJ5ĭN/yq_@"F:֢K=g[ F+ }?GU&^G}e_{ET ʫb`tAlZ]{&{ 6> -iR}`MJzxljt\mU̹{1-a9p: j-4tk 095{s_$2ssM Wu^\ߋXO1?*vh_Vt׻v۶5~iYBUZcPW;Z;J>=haވ/S[By;om_%u:E`l1Z I =UNy,3cq޾kyv8g0x ؏vvy;uDmu3. # # Author: Zoltán Balogh # Juhapekka Piiroinen . `dirname $0`/functions.inc LOCAL_DATE=`date +%Y%m%d` LOCAL_TIME=`date +%T` TIMEZONE=`cat /etc/timezone` adb_shell sed -i "s#.*/.*#${TIMEZONE=}#" /etc/timezone adb_shell dpkg-reconfigure --frontend noninteractive tzdata > /dev/null adb_shell date +%Y%m%d -s "${LOCAL_DATE}" > /dev/null adb_shell date +%T -s "${LOCAL_TIME}" > /dev/null ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_hasqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_ha0000755000015301777760000000175012323167147034044 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc PACKAGES=`cat ${SCRIPTPATH}/device_developertools_packages` for PACKAGE in ${PACKAGES} do IS_INSTALLED=`adb_shell dpkg -s ${PACKAGE} |grep Status|grep -o "install ok installed"|wc -l` if [[ ${IS_INSTALLED} -eq "0" ]]; then echo "0" exit fi done echo "1"qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/click_create_target0000755000015301777760000000316012323167147032762 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller ARCHITECTURE=$1 FRAMEWORK=$2 SERIES=$3 SCRIPTPATH=$(dirname $0) CHECK_FILES=("/etc/schroot/chroot.d/click-${FRAMEWORK}-${ARCHITECTURE}") CHECK_DIRS=("/var/lib/schroot/chroots/click-${FRAMEWORK}-${ARCHITECTURE}") for FILE in $CHECK_FILES do if [ -f $FILE ] then echo "The click target click-${FRAMEWORK}-${ARCHITECTURE} exists already" exit 1 fi done for DIR in $CHECK_DIRS do if [ -d $DIR ] then echo "The click target click-${FRAMEWORK}-${ARCHITECTURE} exists already" exit 1 fi done click chroot -a $ARCHITECTURE -f $FRAMEWORK create if [ $? -eq 0 ] then echo "The click target was created successfully, installing required packages" click chroot -a $ARCHITECTURE -f $FRAMEWORK maint apt-get install -y cmake exit 0 fi echo "There was an error creating the click target, cleaning up" "${SCRIPTPATH}/click_destroy_target" ${ARCHITECTURE} ${FRAMEWORK} ${SERIES} exit 1 ././@LongLink0000000000000000000000000000015300000000000011214 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_packagesqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_pa0000755000015301777760000000052612323167147034054 0ustar pbusernogroup00000000000000autopilot-touch qtdeclarative5-test-plugin gdebi-core fakeroot dh-make build-essential qt5-default qtbase5-dev qtdeclarative5-dev libqt5xmlpatterns5-dev qtscript5-dev qttools5-dev qt3d5-dev qtmultimedia5-dev libqt5svg5-dev qtdeclarative5-dev-tools qttools5-dev-tools qtlocation5-dev qtsensors5-dev qtpim5-dev ubuntu-dev-tools debhelper cmake qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_chroot_make20000755000015301777760000000177212323167147032237 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller : ${CLICK_SDK_ARCH:?"Need to set CLICK_SDK_ARCH non-empty"} : ${CLICK_SDK_FRAMEWORK:?"Need to set CLICK_SDK_FRAMEWORK non-empty"} # : ${CLICK_SDK_SERIES:?"Need to set CLICK_SDK_SERIES non-empty"} export QT_SELECT=qt5:$CLICK_SDK_ARCH /usr/bin/click chroot -a ${CLICK_SDK_ARCH} -f ${CLICK_SDK_FRAMEWORK} run make $@ qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/openssh_connect0000755000015301777760000000213512323167147032175 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc PORT=$2 USERNAME=$3 IP=$4 #$SCRIPTPATH/device_portforward ${PORT} 3768 if [ ! "$(adb_shell getprop persist.service.ssh)" = "true" ];then adb_shell setprop persist.service.ssh true >/dev/null 2>&1 adb_shell start ssh >/dev/null 2>&1 fi x-terminal-emulator -e "ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p $PORT $USERNAME@$IP" & ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_detect_qmldepsqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_detect_qmlde0000755000015301777760000000370012323167147034033 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Zoltán Balogh # Juhapekka Piiroinen PROJECT_PATH=$1 if [[ -z ${PROJECT_PATH=} ]]; then PROJECT_PATH=./ fi if [[ -d debian ]]; then OLD_DEPENDS=`grep -m 1 "^Depends:" debian/control -A\`echo \\\`cat debian/control |egrep "^Description:|^Depends:" -in|sed "s/:.*//g"|sort -r|tail -2|tr '\n' '-'\\\`1|bc\`|sed "s/[ ]*//g;s/,/\n/g;s/Depends://g"|sed "/^$/d"|egrep -v "qmlscene|qt-components-ubuntu|misc:Depends"` fi QT_INSTALL_QML=`qmake -query QT_INSTALL_QML` REGEXP_FOR_QML_MODULES=`find $PROJECT_PATH -name "*.qml"|xargs egrep "^[ \t]*import"|egrep -v "\""|sed -e 's/[ \t]*import/import/'|awk '{print $2 "\.*[0-9]*\/*[qmldir]*$|"}'|sort|uniq|tr -d '\n'|sed "s/|$//"` DEPS_BY_PLUGINS=`find $QT_INSTALL_QML -name "qmldir"|xargs egrep -l "$REGEXP_FOR_QML_MODULES"|xargs dpkg -S|awk '{print $1}'| sort|uniq |sed "s/:.*[:,]//g"` DEPS_BY_QML_MODULES=`find $QT_INSTALL_QML -name "qmldir"|egrep "$REGEXP_FOR_QML_MODULES"|xargs dpkg -S|grep $QT_INSTALL_QML|awk '{print $1}'| sort|uniq |sed "s/:.*[:,]//g"` echo -n Depends: \${misc:Depends}, echo -n $DEPS_BY_PLUGINS $DEPS_BY_QML_MODULES $OLD_DEPENDS|tr ' ' '\n'|sort|uniq|tr '\n' ','|sed "s/qtdeclarative5-ubuntu-ui-toolkit-plugin/qtdeclarative5-ubuntu-ui-toolkit-plugin|qt-components-ubuntu/"|sed "s/:,/,/g" ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_flashdaily_bootstrapqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_flashdaily_bootst0000755000015301777760000000264212323167147034041 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc if [[ !does_device_hw_match_image_hw ]]; then IMAGE_HARDWARE=`device_image_hardware` DEVICE_HARDWARE=`device_hardware` echo echo " WARNING! Device image hardware version" echo " does not match the detected device hardware." echo echo -n " Device Image Version: " echo ${IMAGE_HARDWARE} echo -n " Device Version: " echo ${DEVICE_HARDWARE} echo echo " In order to flash your device, you must do it manually:" echo " ubuntu-device-flash --channel=devel-proposed --serial=${SERIALNUMBER} --bootstrap" echo else x-terminal-emulator -e "bash -ic 'ubuntu-device-flash --channel=devel-proposed --wipe --serial=${SERIALNUMBER} --bootstrap'" fi ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/local_get_cordova_runtimeqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/local_get_cordova_runtim0000755000015301777760000001502112323167147034047 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: David Barth SCRIPTPATH=`dirname $0` CORDOVA_PACKAGE="ubuntu-html5-platform-3.4-dev" PAYLOAD_DIR="usr/share/ubuntu-html5-platform-3.4/" CORDOVA_CACHE=${HOME}/.cache/ubuntu-html5-platform DOWNLOAD_DIR=${CORDOVA_CACHE}/download # based on the blog post of Andreas Olsson # http://blog.bogosity.se/2012/11/03/fully-using-apt-get-download/ setup_apt_conf () { mkdir -p ${DOWNLOAD_DIR}/apt/{apt.conf.d,preferences.d,trusted.gpg.d,cache/lists/partial} touch ${DOWNLOAD_DIR}/apt/status ln -s /usr/share/keyrings/debian-archive-keyring.gpg \ ${DOWNLOAD_DIR}/apt/trusted.gpg.d/ ln -s /usr/share/keyrings/ubuntu-archive-keyring.gpg \ ${DOWNLOAD_DIR}/apt/trusted.gpg.d/ apt-key --keyring ${DOWNLOAD_DIR}/apt/trusted.gpg.d/ppa.gpg adv \ --keyserver keyserver.ubuntu.com --recv-keys C7122F9B 1>/dev/null echo cat > ${DOWNLOAD_DIR}/apt/downloader.conf <> \ # ${DOWNLOAD_DIR}/apt/downloader.conf if [ "$ARCH" == "armhf" ]; then cat > ${DOWNLOAD_DIR}/apt/sources.list < ${DOWNLOAD_DIR}/apt/sources.list <. # # Author: Zoltán Balogh set -e EMULATOR_PACKAGE=$1 dpkg -l ${EMULATOR_PACKAGE} 2>&1 |egrep -v "no packages found matching"| awk '{print $1 " " $2 " " $3}' | grep "ii" || echo "The package is not installed." qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/local_install_emulator0000755000015301777760000000141612323167147033536 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Zoltán Balogh set -e EMULATOR_PACKAGE=$1 pkexec sh -c "apt-get -y -f install ${EMULATOR_PACKAGE}" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_read_bazaar_settings0000755000015301777760000000227112323167147034030 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen DEBEMAIL=`grep -G "^DEBEMAIL" ~/.bashrc` DEBFULLNAME=`grep -G "^DEBFULLNAME" ~/.bashrc` if [[ ! -z "$DEBEMAIL" ]]; then export $DEBEMAIL else CMD=`grep -G "export DEBEMAIL=" ~/.bashrc|sed "s/\"//g"` if [[ ! -z $CMD ]]; then $CMD fi fi if [[ ! -z $DEBFULLNAME ]]; then export $DEBFULLNAME else CMD=`grep -G "export DEBFULLNAME=" ~/.bashrc|sed "s/\"//g"|sed "s/export DEBFULLNAME=//g"` if [[ ! -z $CMD ]]; then export DEBFULLNAME="$CMD" fi fi echo $DEBFULLNAME echo $DEBEMAIL qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/i18n_update_template0000755000015301777760000000250012323167147033015 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen SCRIPTPATH=`dirname $0` DISPLAYNAME=$1 PROJECTFILES=${@:2} SOURCEFILES= for PROJECTFILE in ${PROJECTFILES}; do case ${PROJECTFILE} in *tests*) ;; # ignore tests folder *qml) SOURCEFILES+="${PROJECTFILE#$PWD/} ";; esac done ############################################################ echo echo "Creating po/${DISPLAYNAME}.pot from" for SOURCEFILE in ${SOURCEFILES}; do echo ${SOURCEFILE} done ############################################################ mkdir -p po xgettext -o po/${DISPLAYNAME}.pot --qt --c++ --add-comments=TRANSLATORS --keyword=tr ${SOURCEFILES} --from-code=UTF-8 echo "..created!" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_version0000755000015301777760000000141612323167147032012 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc device_image_hardware device_image_version ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_removeqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_re0000755000015301777760000000154712323167147034066 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc PACKAGES=`cat ${SCRIPTPATH}/device_developertools_packages` adb_shell apt-get -y -f install adb_shell apt-get remove ${PACKAGES} -yqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_hasnetwork0000755000015301777760000000140212323167147032505 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc device_network_state_connected qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/local_start_emulator0000755000015301777760000000145412323167147033227 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Zoltán Balogh set -e EMULATOR=$1 ubuntu-emulator run ${EMULATOR} & set +e adb wait-for-device adb forward tcp:9999 tcp:22 set -e ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_restart_appslenseqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_restart_appsl0000755000015301777760000000163412323167147034061 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc # -- actions -- adb_shell kill -s 9 \`pidof unity-applications-daemon\` adb_shell bash -c "/usr/lib/arm-linux-gnueabihf/unity-lens-applications/unity-applications-daemon > /dev/null &" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_make0000755000015301777760000000133712323167147032322 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen TARGET=$1 make ${TARGET} qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/local_search_images0000755000015301777760000000140012323167147032743 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Zoltán Balogh set -e ubuntu-emulator list 2>&1|grep -v "no such file or directory" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_reboot0000755000015301777760000000136112323167147031616 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc device_reboot ././@LongLink0000000000000000000000000000015000000000000011211 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_qmlproject_click_createqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_qmlproject_click_cre0000644000015301777760000000000012323167147034014 0ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/openssh_version0000755000015301777760000000163412323167147032234 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc set +e ssh-add ~/.ssh/ubuntudevice*id_rsa &> /dev/null set -e adb_shell apt-get -f install &> /dev/null adb_shell apt-cache policy openssh-server|grep Installed|sed "s/Installed\://g" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/functions.inc0000755000015301777760000000616512323167147031574 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen set -e SCRIPTPATH=`dirname $0` SERIALNUMBER=$1 SSHIDENTITY=~/.ssh/ubuntudevice_${SERIALNUMBER}_id_rsa USERNAME=phablet function adb_root { adb -s ${SERIALNUMBER} root &> /dev/null adb -s ${SERIALNUMBER} wait-for-device &> /dev/null } function has_ubuntu_chroot { local HAS_UBUNTU_CHROOT=`adb -s ${SERIALNUMBER} shell "which ubuntu_chroot"` if [[ ${HAS_UBUNTU_CHROOT} ]]; then echo 1 else echo 0 fi } function adbd_restart { adb kill-server &> /dev/null adb start-server &> /dev/null } function adb_devices { adb devices -l } function adb_forward_tcp { set +e adb -s ${SERIALNUMBER} forward tcp:$1 tcp:$2 set -e } function adb_shell { set +e if [[ `has_ubuntu_chroot` -eq "1" ]]; then adb -s ${SERIALNUMBER} shell chroot /data/ubuntu /usr/bin/env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin $@ else adb -s ${SERIALNUMBER} shell $@ fi set -e } function phablet_shell { adb_shell "su ${USERNAME} -c \"$@\"" } function phablet_tools_new_syntax { installed_version=$(dpkg-query --show --showformat '${Version}' phablet-tools) dpkg --compare-versions $installed_version ge 1.0 echo $? } function ubuntu_stamp { adb_shell cat /etc/ubuntu-build } function device_hardware { adb_devices |grep -o device:.*|sed "s/device://" } function device_image_hardware { adb_shell getprop "ro.build.product" } function does_device_hw_match_image_hw { if [[ device_hardware == device_image_hardware ]]; then echo 1 else echo 0 fi } function device_image_version { ubuntu_stamp } function device_network_state_connected { local NM_STATE=`adb_shell nmcli nm | head -n+2 | awk '{print $2}'` if [[ $NM_STATE != *disconnected* ]]; then echo 1 else echo 0 fi } function device_reboot { adb_shell reboot } function device_reboot_bootloader { adb -s ${SERIALNUMBER} reboot-bootloader } function device_reboot_recovery { adb -s ${SERIALNUMBER} reboot recovery } function device_shutdown { adb_shell shutdown -h now } function wait_for_network_state_switch_on { local RESULT=`device_network_state_connected` while [[ "$RESULT" -eq "0" ]]; do sleep 1 echo -n . RESULT=`device_network_state_connected` done } function clone_network_setup_from_host_to_device { pkexec phablet-network -s ${SERIALNUMBER} } ############################################################# if [[ -z ${SERIALNUMBER} ]]; then echo "Please pass a device serial number." echo adb_devices exit -1 fi adb_root qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_run_click0000755000015301777760000000000012323167147033131 0ustar pbusernogroup00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/openssh_remove0000755000015301777760000000142012323167147032035 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc adb_shell apt-get remove openssh-server -y qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_shutdown0000755000015301777760000000136312323167147032201 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc device_shutdown ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_deploy_packageqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_deploy_packag0000755000015301777760000000445412323167147034003 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc PACKAGE=$2 TARGET_DEVICE=$3 TARGET_DEVICE_PORT=$4 TARGET_DEVICE_HOME=$5 echo echo "Deploying package to device with serial number of ${SERIALNUMBER}." echo "Using SSH identity from ${SSHIDENTITY}." echo USAGE="$0 [serialnumber] [package] [target_device] [target_device_port] [target_device_home]" if [[ -z $PACKAGE || -z $TARGET_DEVICE || -z $TARGET_DEVICE_PORT || -z $TARGET_DEVICE_HOME ]]; then echo ${USAGE} exit fi # lets make the ssh port forwarding back on, as the developer might have rebooted the device echo "do port forwarding" set +e ${SCRIPTPATH}/device_portforward ${TARGET_DEVICE_PORT} 3768 set -e echo "done" # check if we have .pro files or cpp/h files, if we do lets exit, as this deployment method is for QML projects H_FILES=`find . -name *.h` CPP_FILES=`find . -name *.cpp` if [[ -z ${H_FILES} && -z ${CPP_FILES} ]]; then echo "Detected: QML project" else echo "Detected: Hybrid project" echo " -> This deployment method is meant for QML projects only." echo " Use Tools > Ubuntu Touch > C++" exit 1 fi # Case lowered due to bug #1213902 PLAIN_PACKAGE=`basename ${PACKAGE,,}` SCRIPTPATH=`dirname $0` SCP="scp -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P${TARGET_DEVICE_PORT}" SSH="ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p${TARGET_DEVICE_PORT} ${TARGET_DEVICE}" # -- actions -- $SCP ${PACKAGE} ${TARGET_DEVICE}:${TARGET_DEVICE_HOME} adb_shell gdebi --n ${TARGET_DEVICE_HOME}/${PLAIN_PACKAGE} # Commented out due to bug #1213902 #$SCRIPTPATH/qtc_device_restart_appslense ${SERIALNUMBER} qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_click_deploy0000755000015301777760000000517512323167147034052 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen # Author: Benjamin Zeller . `dirname $0`/functions.inc PACKAGENAME=$2 TARGET_DEVICE=$3 TARGET_DEVICE_PORT=$4 TARGET_DEVICE_HOME=$5 TARGET_DEVICE_USERNAME=$6 if [[ -z ${FOLDERNAME} ]]; then FOLDERNAME=`pwd` fi if [[ -z ${TARGET_DEVICE_PORT} ]]; then TARGET_DEVICE_PORT=2222 fi if [[ -z ${TARGET_DEVICE_USERNAME} ]]; then TARGET_DEVICE_USERNAME=phablet fi if [[ -z ${TARGET_DEVICE} ]]; then TARGET_DEVICE=${TARGET_DEVICE_USERNAME}@127.0.0.1 fi if [[ -z ${TARGET_DEVICE_HOME} ]]; then TARGET_DEVICE_HOME=/home/${TARGET_DEVICE_USERNAME}/dev_tmp/ fi SCP="scp -v -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P${TARGET_DEVICE_PORT}" SSH="ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p${TARGET_DEVICE_PORT} ${TARGET_DEVICE}" set +e # remove old files if [[ ! -z ${TARGET_DEVICE_HOME} ]]; then echo "Lets clear the device tmp folder at ${TARGET_DEVICE}:${TARGET_DEVICE_PORT}${TARGET_DEVICE_HOME}" $SSH rm -rf ${TARGET_DEVICE_HOME}/* 2> /dev/null fi # make sure that the device has the target directory echo "Lets create the device tmp folder to ${TARGET_DEVICE}:${TARGET_DEVICE_PORT}${TARGET_DEVICE_HOME}" $SSH mkdir -vp ${TARGET_DEVICE_HOME} 2> /dev/null # transfer click package to device echo "Transfer the click package to the device" set +e $SCP ${PACKAGENAME} ${TARGET_DEVICE}:${TARGET_DEVICE_HOME} 2> /dev/null if [[ ${?} -eq 0 ]]; then echo "..transfer complete!" else echo " /!\\ transfer failed /!\\" exit -1 fi echo "List all available click packages on the device" FILES=`$SSH -q "cd ${TARGET_DEVICE_HOME}; ls -1 *.click"` echo $FILES for FILE in $FILES; do echo "Installing $FILE to device.." # note adb shell and adb_shell are two different things, adb_shell comes from functions.inc adb_shell sudo -H -u ${TARGET_DEVICE_USERNAME} pkcon install-local ${TARGET_DEVICE_HOME}/${FILE} done qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_chroot_cmake0000755000015301777760000000231112323167147032306 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller USAGE="Usage: $0 targetArch targetFramework targetSeries cmakeOptions" if [ $# -lt 3 ]; then echo "$USAGE" exit 1 fi ARCH=$1 shift FRAMEWORK=$1 shift SERIES=$1 shift #architecture specific arguments ARCH_ARGS= if [ ${ARCH} == "armhf" ] then ARCH_ARGS='-DQT_IMPORTS_DIR=/usr/lib/arm-linux-gnueabihf/qt5/qml' fi export QT_SELECT=qt5:$ARCH rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile /usr/bin/click chroot -a $ARCH -f $FRAMEWORK run cmake -DINSTALL_TESTS=off -DCLICK_MODE=on ${ARCH_ARGS} $@ qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_debuild0000755000015301777760000000137512323167147033017 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen set -e; # -- actions -- debuild -i -I -S -sa -us -uc -ncqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_buildpackage0000755000015301777760000001161712323167147033613 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen SCRIPTPATH=$(dirname $0) DEBEMAIL=`grep -G "^DEBEMAIL" ~/.bashrc` DEBFULLNAME=`grep -G "^DEBFULLNAME" ~/.bashrc` if [[ ! -z "$DEBEMAIL" ]]; then export $DEBEMAIL else CMD=`grep -G "export DEBEMAIL=" ~/.bashrc|sed "s/\"//g"` if [[ ! -z $CMD ]]; then $CMD fi fi if [[ ! -z $DEBFULLNAME ]]; then export $DEBFULLNAME else CMD=`grep -G "export DEBFULLNAME=" ~/.bashrc|sed "s/\"//g"|sed "s/export DEBFULLNAME=//g"` if [[ ! -z $CMD ]]; then export DEBFULLNAME="$CMD" fi fi . `dirname $0`/functions.inc FOLDERNAME=$2 TARGET_DEVICE=$3 TARGET_DEVICE_PORT=$4 TARGET_DEVICE_HOME=$5 USAGE="$0 [serialnumber] [foldername] [target_device] [target_device_port] [target_device_home]" if [[ -z $FOLDERNAME ]]; then echo ${USAGE} exit fi if [[ -z ${TARGET_DEVICE_PORT} ]]; then TARGET_DEVICE_PORT=2222 fi if [[ -z ${TARGET_DEVICE} ]]; then TARGET_DEVICE=phablet@127.0.0.1 fi if [[ -z ${TARGET_DEVICE_HOME} ]]; then TARGET_DEVICE_HOME=/home/phablet/dev_tmp fi SSH_CRED="ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p${TARGET_DEVICE_PORT}" SCP="scp -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P${TARGET_DEVICE_PORT}" SSH="${SSH_CRED} ${TARGET_DEVICE}" RSYNC="rsync --delete -avzP -e" DEV_PROJECT_DIR="${TARGET_DEVICE_HOME}/${FOLDERNAME}" CMAKE_BUILDDIR="build-${FOLDERNAME}-device" echo "Rsync command: ${RSYNC} ${FOLDERNAME} ${TARGET_DEVICE}:${DEV_PROJECT_DIR}/src" pushd "${FOLDERNAME}" set +e if [[ -f Makefile ]]; then make distclean fi set -e popd if [[ ! -e "${FOLDERNAME}/CMakeLists.txt" ]]; then tar -cjf "${FOLDERNAME}.tar.bz2" "${FOLDERNAME}" # remove old files if [[ ! -z ${TARGET_DEVICE_HOME} ]]; then $SSH rm -rf ${TARGET_DEVICE_HOME}/* fi # make sure that the device has the target directory $SSH mkdir -p ${TARGET_DEVICE_HOME} $SCP "${FOLDERNAME}.tar.bz2" ${TARGET_DEVICE}:${TARGET_DEVICE_HOME} $SSH "cd ${TARGET_DEVICE_HOME}; tar -xvf ${FOLDERNAME}.tar.bz2" else # make sure that the device has the target directory $SSH mkdir -p ${DEV_PROJECT_DIR} $RSYNC "${SSH_CRED}" ${FOLDERNAME}/ ${TARGET_DEVICE}:${DEV_PROJECT_DIR}/src fi if [[ -d "${FOLDERNAME}/debian" ]]; then echo "Packaging already exists for project." $SSH "cd ${TARGET_DEVICE_HOME}/${FOLDERNAME}; debuild --no-tgz-check -i -I -S -sa -us -uc" else if [[ -e "${FOLDERNAME}/CMakeLists.txt" ]]; then $SSH "cd ${DEV_PROJECT_DIR}; mkdir ${CMAKE_BUILDDIR}; cd ${CMAKE_BUILDDIR}; cmake -DCLICK_MODE=1 ../src" if [[ $? -gt 0 ]]; then echo "Have you enabled Platform Development Mode? (Devices > Advanced)" exit fi $SSH "cd ${DEV_PROJECT_DIR}/${CMAKE_BUILDDIR}; make && make DESTDIR=package install" if [[ $? -gt 0 ]]; then exit fi echo "Transferring files from device to host.." $RSYNC "${SSH_CRED}" ${TARGET_DEVICE}:${DEV_PROJECT_DIR}/${CMAKE_BUILDDIR}/ ${FOLDERNAME}/../build-${FOLDERNAME}-device echo "Building package" pushd "${CMAKE_BUILDDIR}/package" ${SCRIPTPATH}/qtc_fix_desktop_comment $(${SCRIPTPATH}/qtc_find_desktopfile ${FOLDERNAME}) popd pushd "${CMAKE_BUILDDIR}" click build "package" popd else $SSH "cd ${TARGET_DEVICE_HOME}/${FOLDERNAME}; dh_make -p ${FOLDERNAME}_0.1 -s -y --createorig" if [[ $? -gt 0 ]]; then echo "Have you enabled Platform Development Mode? (Devices > Advanced)" exit fi $SSH "cd ${TARGET_DEVICE_HOME}/${FOLDERNAME}; debuild -i -I -S -sa -us -uc" MISSING_DEPENDENCIES=`$SSH "cd ${TARGET_DEVICE_HOME}/${FOLDERNAME}; dpkg-checkbuilddeps 2>&1|sed 's/dpkg-checkbuilddeps: Unmet build dependencies://'"` adb_shell apt-get --assume-yes install ${MISSING_DEPENDENCIES} $SSH "cd ${TARGET_DEVICE_HOME}/${FOLDERNAME}; dpkg-buildpackage -us -uc -nc" echo "Transferring files from device to host.." FILES=`$SSH "cd ${TARGET_DEVICE_HOME}; ls -1|grep -v ${FOLDERNAME}.tar.bz2|grep -v ${FOLDERNAME}$"` echo $FILES | tr ' ' '\n' | xargs -I FILE $SCP ${TARGET_DEVICE}:${TARGET_DEVICE_HOME}/FILE . echo "..transfer complete!" echo echo "Transferred following files: " echo $FILES | tr ' ' '\n' echo echo "@ $PWD" echo adb_shell apt-get --assume-yes remove ${MISSING_DEPENDENCIES} fi fi ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_create_packageqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_create_packa0000755000015301777760000000326312323167147034007 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen set -e SCRIPTPATH=`dirname $0` # -- actions -- if [[ ! -d debian ]]; then ${SCRIPTPATH}/qtc_project_packaging . fi ${SCRIPTPATH}/qtc_project_debuild QMLDEPS=`${SCRIPTPATH}/qtc_project_detect_qmldeps` if [[ -d debian ]]; then awk "NR < `egrep "^Depends:" -in debian/control|sed "s/:.*//g"|head -1`+1" debian/control|sed "s/^Depends:.*/${QMLDEPS}qmlscene/g" > debian/control.new awk "NR >= `egrep "^Description:" -in debian/control|sed "s/:.*//g"|head -1`" debian/control >> debian/control.new mv debian/control.new debian/control fi #sed -i "s/^Depends:.*/${QMLDEPS}qmlscene/g" debian/control # Detect if we have QML project only set +e H_FILES=`find . -type f |grep .h$` CPP_FILES=`find . -type f |grep .cpp$` PRO_FILES=`find . -type f |grep .pro$` set -e if [[ -z ${H_FILES} && -z ${CPP_FILES} && -z ${PRO_FILES} ]]; then echo "Detected: QML project" sed -i "s/^Architecture: any$/Architecture: all/g" debian/control else echo "Detected: CPP project" fi dpkg-buildpackage -us -uc -nc qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/local_create_emulator0000755000015301777760000000164412323167147033336 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Zoltán Balogh set -e EMULATOR_NAME=$2 EMULATOR_PATH=$1 WHOAMI=`whoami` if [ ! -d ${EMULATOR_PATH} ] then mkdir -p ${EMULATOR_PATH} fi pkexec sh -c "HOME=$HOME ubuntu-emulator create ${EMULATOR_NAME};chown ${WHOAMI}:${WHOAMI} ${EMULATOR_PATH} -R" ././@LongLink0000000000000000000000000000014700000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_writableimage_unsetqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_writableimage_uns0000755000015301777760000000150612323167147034026 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc WRITABLE_IMAGE_FILE=/userdata/.writable_image adb_shell rm ${WRITABLE_IMAGE_FILE} adb_shell reboot././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_click_createanddeployqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_click_create0000755000015301777760000000224512323167147034014 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc FOLDERNAME=$2 set +e echo "Lets create the click package for the project." ${SCRIPTPATH}/qtc_project_click_create ${FOLDERNAME} > /tmp/qtc_click_create.log if [[ $? -eq 0 ]]; then set -e PACKAGENAME=`cat /tmp/qtc_click_create.log|tail -n1` echo "$PACKAGENAME has been created." else cat /tmp/qtc_click_create.log exit -1 fi echo "${SCRIPTPATH}/qtc_project_click_deploy" ${SCRIPTPATH}/qtc_project_click_deploy $1 ${PACKAGENAME} $3 $4 $5 $6 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_chroot_make0000755000015301777760000000167612323167147032160 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller USAGE="Usage: $0 targetArch targetFramework targetSeries makeOptions" if [ $# -lt 3 ]; then echo "$USAGE" exit 1 fi ARCH=$1 shift FRAMEWORK=$1 shift SERIES=$1 shift export QT_SELECT=qt5:$ARCH /usr/bin/click chroot -a $ARCH -f $FRAMEWORK run make $@ qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_find_desktopfile0000755000015301777760000000252212323167147033165 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen # Author: Benjamin Zeller SCRIPTPATH=$(dirname $0) PROJECTNAME=$1 DESKTOPFILE_COUNT=`ls *.desktop|wc -l` DESKTOPFILE="" if [[ ${DESKTOPFILE_COUNT} -eq 1 ]]; then DESKTOPFILE=`ls *.desktop` elif [[ ${DESKTOPFILE_COUNT} -eq 0 ]]; then exit 1 else # do we have a desktop file which has the same name as projectname if [[ -f ${PROJECTNAME}.desktop ]]; then # found one lets use it DESKTOPFILE=${PROJECTNAME}.desktop else # it seems that we did not have one, lets use the latest desktop file. DESKTOPFILE=`ls -t *.desktop|head -n1` fi fi echo "${DESKTOPFILE}" exit 0 qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_reboot2bootloader0000755000015301777760000000137512323167147033760 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc device_reboot_bootloader qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_service_ssh_start0000755000015301777760000000162012323167147034054 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc if [ ! "$(adb_shell getprop persist.service.ssh)" = "true" ];then adb_shell setprop persist.service.ssh true >/dev/null 2>&1 adb_shell start ssh >/dev/null 2>&1 fi qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_is_ubuntu0000755000015301777760000000153412323167147032343 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller . `dirname $0`/functions.inc adb_shell "su -c 'test -f /etc/lsb-release && (cat /etc/lsb-release | grep DISTRIB_ID) || echo \"DISTRIB_ID=UnknownAdbDevice\"'" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/openssh_publickey0000755000015301777760000000322312323167147032532 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc USERNAME=$2 function check_key { echo "Checking for keys.." KEY=`cat $SSHIDENTITY.pub` set +e PHABLET_KEYS=`adb_shell "cat /home/$USERNAME/.ssh/authorized_keys2"` KEYS=`echo $PHABLET_KEYS | grep "$KEY"` set -e echo echo "Host key is:" echo $KEY echo echo "We have following keys on the device: " echo $KEYS if [[ -z $KEYS || $KEYS == *No\ such* ]]; then echo "*no keys*" echo deploy_key else echo echo "The host key has been already deployed." fi } function deploy_key { echo "Deploy the host key to the device.." KEY=`cat $SSHIDENTITY.pub` phablet_shell "mkdir -p /home/$USERNAME/.ssh" echo "..key folder created" phablet_shell "echo $KEY >> /home/$USERNAME/.ssh/authorized_keys2" echo "..key deployed!" } function generate_key { echo "Generating host key.." ssh-keygen -t rsa -N '' -f $SSHIDENTITY -b 768 } ################# if [[ -f $SSHIDENTITY ]]; then check_key else generate_key deploy_key fi qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/manifest_description0000755000015301777760000000024712323167147033220 0ustar pbusernogroup00000000000000#!/usr/bin/python import json import sys import codecs f = codecs.open(sys.argv[1], "r", "utf-8") obj = json.loads(f.read()) print obj["description"].encode('utf-8') qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_click_create0000755000015301777760000000660712323167147034022 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen SCRIPTPATH=`dirname $0` PROJECTPATH=$1 if [[ -z ${PROJECTPATH} ]]; then PROJECTPATH=`pwd` fi echo echo "Click packaging project in ${PROJECTPATH}." echo pushd ${PROJECTPATH} >> /dev/null echo echo "Searching for desktop file.." QMLPROJECT=`ls *.qmlproject|sed "s/\.qmlproject//"` DESKTOPFILE=$( ${SCRIPTPATH}/qtc_find_desktopfile ${QMLPROJECT} ) if [[ ! $? -eq 0 ]] then echo " /!\\ no desktop file found /!\\" echo " You will have to create one." exit 1 fi echo "Found a desktopfile: ${DESKTOPFILE}" # lets check if the manifest.json exists if [[ -f manifest.json ]]; then echo echo "Found manifest.json." else echo echo " /!\\ manifest.json does not exist /!\\" echo " You will have to create one using the Packaging tab." exit -1 fi # determine MAINQML MAINQML=`cat ${QMLPROJECT}.qmlproject|grep mainFile|sed "s/.*\(\".*\"\).*/\1/"|sed "s/\"//g"` echo "Main file is ${MAINQML}" #------------------ # lets copy the original desktop file cp ${DESKTOPFILE} /tmp/${DESKTOPFILE} #fix the comment in desktop file ${SCRIPTPATH}/qtc_fix_desktop_comment ${DESKTOPFILE} # read the arguments to qmlscene QMLSCENE_ARGS=`cat ${DESKTOPFILE} | grep -o "qmlscene.*\$\@" | sed "s/\(qmlscene\|\$\@\)//g"` # lets replace the Exec line sed -i "s/^Exec=[ a-z0-9A-Z\/]*qmlscene.*/Exec=qmlscene ${QMLSCENE_ARGS} \$@ ${MAINQML}/g" ${DESKTOPFILE} # lets build the package cd .. # copy project files to build directory RESULTPATH=`pwd` BUILDPATH=${PROJECTPATH}_build rm -Rf ${BUILDPATH} mkdir -p ${BUILDPATH} # read .excludes file from the projectpath PROJECT_EXCLUDES="--exclude .bzr --exclude .git --exclude .hg --exclude .svn --exclude *.qmlproject --exclude *.user --exclude tests --exclude Makefile --exclude .excludes" if [[ -f ${PROJECTPATH}/.excludes ]]; then for EXCLUDE in `cat ${PROJECTPATH}/.excludes`; do PROJECT_EXCLUDES+=" --exclude ${EXCLUDE}" done fi # we are printing also a filelist to the stdout which files are going to be inside the package echo rsync -avh ${PROJECT_EXCLUDES} ${PROJECTPATH}/* ${BUILDPATH}/ # build the build path click build ${BUILDPATH} > /tmp/click.log 2> /tmp/click.err # lets check the results if [[ ${?} -eq 0 ]]; then echo echo "Package has been created to" PACKAGENAME=`cat /tmp/click.log|sed "s/.*\('.*'\).*/\1/" | sed "s/'//g" | sed "s/.\///" | xargs -ICLICKPACKAGE echo ${RESULTPATH}/CLICKPACKAGE` echo "$PACKAGENAME" else echo echo "There was some failure when creating the package." echo "See /tmp/click.err for details." echo fi cd - > /dev/null # restore the original desktop file mv /tmp/${DESKTOPFILE} ${DESKTOPFILE} popd > /dev/null qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_launch_gallery0000755000015301777760000000223312323167147032644 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen echo "Copying ubuntu-ui-toolkit-gallery from /usr/lib/ubuntu-ui-toolkit/examples to /tmp" mkdir -p /tmp/ubuntu-ui-toolkit-gallery cp -r /usr/lib/ubuntu-ui-toolkit/examples/ubuntu-ui-toolkit-gallery/* /tmp/ubuntu-ui-toolkit-gallery echo "Opening project in Qt Creator" qtcreator -client /tmp/ubuntu-ui-toolkit-gallery/ubuntu-ui-toolkit-gallery.qmlproject & echo "Launching the qmlscene" /usr/bin/qmlscene $@ /tmp/ubuntu-ui-toolkit-gallery/ubuntu-ui-toolkit-gallery.qml & qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/openssh_install0000755000015301777760000000157612323167147032222 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc #${SCRIPTPATH}/qtc_device_developertools ${SERIALNUMBER} adb_shell apt-get -f install adb_shell apt-get update adb_shell apt-get install openssh-server -y qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_chroot_cmake20000755000015301777760000000235112323167147032374 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller : ${CLICK_SDK_ARCH:?"Need to set CLICK_SDK_ARCH non-empty"} : ${CLICK_SDK_FRAMEWORK:?"Need to set CLICK_SDK_FRAMEWORK non-empty"} # : ${CLICK_SDK_SERIES:?"Need to set CLICK_SDK_SERIES non-empty"} #architecture specific arguments ARCH_ARGS= if [ ${CLICK_SDK_ARCH} == "armhf" ] then ARCH_ARGS='-DQT_IMPORTS_DIR=/usr/lib/arm-linux-gnueabihf/qt5/qml' fi rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile export QT_SELECT=qt5:$CLICK_SDK_ARCH /usr/bin/click chroot -a $CLICK_SDK_ARCH -f $CLICK_SDK_FRAMEWORK run cmake ${ARCH_ARGS} "$@" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_fix_desktop_comment0000755000015301777760000000244612323167147033722 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen # Author: Benjamin Zeller SCRIPTPATH=$(dirname $0) DESKTOPFILE=$1 # lets read the manifest description and set that to desktop comment - fix bug #1223388 MANIFEST_DESCRIPTION=`${SCRIPTPATH}/manifest_description manifest.json` #lets check if there is a Comment grep -e "^Comment=.*$" ${DESKTOPFILE} if [ $? -eq 0 ] then #replace the Comment with description from manifest, if it is empty sed -i "s/^Comment=.*/Comment=${MANIFEST_DESCRIPTION}/g" ${DESKTOPFILE} else #add a comment if none is in the desktopfile echo -e "Comment=${MANIFEST_DESCRIPTION}\n" >> ${DESKTOPFILE} fi qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_writableimage_set0000755000015301777760000000151112323167147034010 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc WRITABLE_IMAGE_FILE=/userdata/.writable_image adb_shell touch ${WRITABLE_IMAGE_FILE} adb_shell rebootqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_flashdaily0000755000015301777760000000262512323167147032450 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc if [[ !does_device_hw_match_image_hw ]]; then IMAGE_HARDWARE=`device_image_hardware` DEVICE_HARDWARE=`device_hardware` echo echo " WARNING! Device image hardware version" echo " does not match the detected device hardware." echo echo -n " Device Image Version: " echo ${IMAGE_HARDWARE} echo -n " Device Version: " echo ${DEVICE_HARDWARE} echo echo " In order to flash your device, you must do it manually:" echo " ubuntu-device-flash --channel=devel-proposed --serial=${SERIALNUMBER} --bootstrap" echo else x-terminal-emulator -e "bash -ic 'ubuntu-device-flash --channel=devel-proposed --wipe --serial=${SERIALNUMBER}'" fi qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_rootshell0000755000015301777760000000135512323167147032342 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc adb_shell qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_writableimage_has0000755000015301777760000000152612323167147033776 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc WRITABLE_IMAGE_FILE=/userdata/.writable_image adb_shell cat ${WRITABLE_IMAGE_FILE} |grep -oi "no such file"|wc -l qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_bzr_info0000755000015301777760000000134412323167147031465 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen bzr whoami bzr launchpad-login qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_reboot2recovery0000755000015301777760000000137212323167147033461 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc device_reboot_recovery ././@LongLink0000000000000000000000000000016300000000000011215 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_cmakeproject_click_createanddeployqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_cmakeproject_click_c0000755000015301777760000000253312323167147033774 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc shift FOLDERNAME=$1 shift TARGET_DEVICE=$1 shift TARGET_DEVICE_PORT=$1 shift TARGET_DEVICE_HOME=$1 shift TARGET_DEVICE_USERNAME=$1 shift set +e echo "Lets create the click package for the project using cmake." echo "${@}" ${SCRIPTPATH}/qtc_cmakeproject_click_create $@ > /tmp/qtc_click_create.log if [[ $? -eq 0 ]]; then set -e PACKAGENAME=`cat /tmp/qtc_click_create.log|tail -n1` echo "$PACKAGENAME has been created." else cat /tmp/qtc_click_create.log exit -1 fi ${SCRIPTPATH}/qtc_project_click_deploy ${SERIALNUMBER} ${PACKAGENAME} ${TARGET_DEVICE} ${TARGET_DEVICE_PORT} ${TARGET_DEVICE_HOME} ${TARGET_DEVICE_USERNAME} ././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_set_persist-sys-usb-configqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_set_persist-sys-u0000755000015301777760000000142412323167147033746 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc adb_shell setprop persist.sys.usb.config ptp,adb qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_project_packaging0000755000015301777760000000617612323167147033337 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen DEBEMAIL=`grep -G "^DEBEMAIL" ~/.bashrc` DEBFULLNAME=`grep -G "^DEBFULLNAME" ~/.bashrc` if [[ ! -z "$DEBEMAIL" ]]; then export $DEBEMAIL else CMD=`grep -G "export DEBEMAIL=" ~/.bashrc|sed "s/\"//g"` if [[ ! -z $CMD ]]; then $CMD fi fi if [[ ! -z $DEBFULLNAME ]]; then export $DEBFULLNAME else CMD=`grep -G "export DEBFULLNAME=" ~/.bashrc|sed "s/\"//g"|sed "s/export DEBFULLNAME=//g"` if [[ ! -z $CMD ]]; then export DEBFULLNAME="$CMD" fi fi set -e PROJECT=$1 if [[ ! -d "$PROJECT" ]]; then echo "Project not found ($PROJECT)." exit 123 fi cd $PROJECT if [[ -d debian ]]; then echo "Packaging already exists for project. Skipping.." exit fi PACKAGENAME=`basename $PWD|tr '[A-Z]' '[a-z]'` set +e #detect project type H_FILES=`find . -type f |grep .h$` CPP_FILES=`find . -type f |grep .cpp$` PRO_FILES=`find . -type f |grep .pro$` PROJECTTYPE="" PACKAGETYPE="" if [[ -z ${H_FILES} && -z ${CPP_FILES} && -z ${PRO_FILES} ]]; then echo "Detected: QML project" PROJECTTYPE="QML" PACKAGETYPE="-s" else echo "Detected CPP project" PROJECTTYPE="CPP" IS_LIB=`echo ${PRO_FILES}|xargs cat |grep "TEMPLATE"|grep "lib"` if [[ -z ${IS_LIB} ]]; then echo " - Application" PACKAGETYPE="-s" else echo " - QML Extension Library" PACKAGETYPE="-s" fi fi set -e # create packaging echo "\n" | dh_make -n -p ${PACKAGENAME}_0.1 ${PACKAGETYPE} --createorig if [[ ! -d debian ]]; then echo "Debian folder was not created!" exit 2 fi pushd debian # remove unfilled files rm *.ex *.EX README* docs popd # add installable files INSTALL_PATH=/usr/share/${PACKAGENAME} DESKTOPFILE=/usr/share/applications find . -mindepth 1 -maxdepth 3 -printf "%p ${INSTALL_PATH}\n"|grep -v ".user\|debian\|.desktop" | sed "s/^\.\///g" > debian/install if [[ -z ${IS_LIB} ]]; then find *.desktop -printf "%p ${DESKTOPFILE}\n" >> debian/install fi # check if we have .pro files or cpp/h files, if not then change architecture to any if [[ "$PROJECTTYPE" == QML ]]; then echo "Detected: QML project" sed -i "s/^Architecture: any$/Architecture: all/g" debian/control # update package dependencies SCRIPTPATH=`dirname $0` QMLDEPS=`${SCRIPTPATH}/qtc_project_detect_qmldeps` sed -i "s/^Depends:.*/${QMLDEPS}qmlscene/g" debian/control else echo "Detected: CPP project" fi UBUNTU_RELEASE=`cat /etc/lsb-release|grep DISTRIB_CODENAME|sed 's/DISTRIB_CODENAME=//'` sed -i "s/unstable; urgency=low/{$UBUNTU_RELEASE}; urgency=low/g" debian/changelog qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_run_app0000755000015301777760000001064312323167173032641 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc APP_LAUNCHER=$2 FOLDERNAME=$3 DESKTOP_FILENAME=$4 MAIN_QML=$5 TARGET_DEVICE_HOME=$6 TARGET_DEVICE=$7 TARGET_DEVICE_PORT=$8 # potential prefix that should be prepended to the target app path shift APP_LAUNCH_PREFIX=$8 shift EXTRA_COMMAND_LINE_ARGS=$8 APP_ID=$(echo ${DESKTOP_FILENAME}|sed "s/\.desktop//") USAGE="$0 [serialnumber] [app_launcher] [foldername] [desktop_filename] [main_qml] [target_device_home] [target_device] [target_device_port] [optional_app_launch_prefix] [optional_extra_command_line_args]" if [[ -z ${FOLDERNAME} ]]; then echo ${USAGE} exit fi if [[ ! -e "${FOLDERNAME}/${DESKTOP_FILENAME}" ]]; then echo "Reading desktop file from manifest" DESKTOP_FILENAME=$(grep desktop ${FOLDERNAME}/manifest.json | cut -d: -f2 | sed "s/\"//g" | tr -d ' ') echo "Trying ${PWD}/${FOLDERNAME}/${DESKTOP_FILENAME}" if [[ ! -e "${FOLDERNAME}/${DESKTOP_FILENAME}" ]]; then echo "No desktop file found"; exit 1; fi fi if [[ -z ${APP_LAUNCHER} ]]; then APP_LAUNCHER=qmlscene fi if [[ -z ${MAIN_QML} ]]; then MAIN_QML=main.qml fi if [[ -z ${TARGET_DEVICE_PORT} ]]; then TARGET_DEVICE_PORT=2222 fi if [[ -z ${TARGET_DEVICE} ]]; then TARGET_DEVICE=phablet@127.0.0.1 fi if [[ -z ${TARGET_DEVICE_HOME} ]]; then TARGET_DEVICE_HOME=/home/phablet/dev_tmp fi SSH_CRED="ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p${TARGET_DEVICE_PORT}" SCP="scp -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P${TARGET_DEVICE_PORT}" SSH="ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p${TARGET_DEVICE_PORT} ${TARGET_DEVICE}" RSYNC="rsync --delete -avzP -e" # get dbus session addrss from the device DBUS_SESSION_BUS_ADDRESS=`$SSH "cat ~/.cache/upstart/dbus-session|grep DBUS_SESSION_BUS_ADDRESS"` #read additional arguments from the desktop file echo "Trying to read additional arguments from ${FOLDERNAME}/${DESKTOP_FILENAME}" ARGS_FROM_DESKTOP= IFS=', ' read -a ARGUMENTS <<< $(cat "${FOLDERNAME}/${DESKTOP_FILENAME}" | grep Exec | cut -d = -f 2) LIMIT=${#ARGUMENTS[@]} for ((a=1; a <= LIMIT ; a++)) # Double parentheses, and naked "LIMIT" do #if we have a relative path, prefix it with the target home path if [[ ${ARGUMENTS[$a]} == "-I" ]] then IMPORT_PATH=${ARGUMENTS[$a+1]} if [[ "${IMPORT_PATH}" != /* ]] then IMPORT_PATH=$(echo "${IMPORT_PATH}" | sed "s;\./;;" | sed "s;^;${TARGET_DEVICE_HOME}\/${APP_ID}\/;") else echo "Please use only relative paths for imports in the desktop file" exit 1 fi ARGS_FROM_DESKTOP="-I ${IMPORT_PATH} ${ARGS_FROM_DESKTOP}" fi done echo "IMPORT: ${ARGS_FROM_DESKTOP}" COMMAND="test -f /etc/ubuntu-touch-session.d/\$(getprop ro.product.device).conf && for myenv in \$(cat /etc/ubuntu-touch-session.d/\$(getprop ro.product.device).conf); do `echo \"export\" \\\$myenv`; done ; export ${DBUS_SESSION_BUS_ADDRESS=}; APP_ID=${APP_ID} ${APP_LAUNCHER} ${ARGS_FROM_DESKTOP} ${APP_LAUNCH_PREFIX}${TARGET_DEVICE_HOME}/${APP_ID}/${MAIN_QML} --desktop_file_hint=${TARGET_DEVICE_HOME}/${APP_ID}/${DESKTOP_FILENAME} ${EXTRA_COMMAND_LINE_ARGS}" echo "Going to execute: ${COMMAND}" # make sure that the device has the target directory $SSH mkdir -p ${TARGET_DEVICE_HOME} $SSH mkdir -p ${TARGET_DEVICE_HOME}/${APP_ID} # transfer the package to the device $RSYNC "${SSH_CRED}" ${FOLDERNAME}/ ${TARGET_DEVICE}:${TARGET_DEVICE_HOME}/${APP_ID} echo "Starting the application .... " # fix the desktopfile Exec path $SSH sed -i "s/^Exec=.*//g" ${TARGET_DEVICE_HOME}/${APP_ID}/${DESKTOP_FILENAME} $SSH "echo 'Exec=/usr/bin/${COMMAND}' >> ${TARGET_DEVICE_HOME}/${APP_ID}/${DESKTOP_FILENAME}" # run the application on the device $SSH "bash -ic 'source /etc/profile; ${COMMAND}'" ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_close_all_appsqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_close_all_app0000755000015301777760000000265512323167147033777 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc APPLICATION=$2 if [[ -z ${APPLICATION} ]]; then echo "Close all instances of running applications." adb_shell kill -s 9 \`pidof qmlscene\` else echo "Close the ${APPLICATION}." set +e IS_MOUNTED=`adb_shell mount | grep proc` set -e if [[ -z ${IS_MOUNTED} ]]; then adb_shell mount -t proc proc /proc fi PID_OF_APP=`adb_shell COLUMNS=1000 ps -ef|grep qmlscene|grep ${APPLICATION}|awk '{print $2}'` if [[ -z $PID_OF_APP ]]; then echo " *no running instances of application*" exit 1 fi echo " * application pid(s) is ${PID_OF_APP}." adb_shell kill -s 9 ${PID_OF_APP} if [[ -z ${IS_MOUNTED} ]]; then adb_shell umount /proc fi echo "Application has been closed." fi qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_network_clone0000755000015301777760000000153212323167147033175 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc clone_network_setup_from_host_to_device wait_for_network_state_switch_on echo "The device has connected to a network."qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_screenshot0000755000015301777760000000157512323167147032510 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Zoltán Balogh . `dirname $0`/functions.inc LOCAL_TIME_STAMP=`date +20%y%m%d-%H%M%S` phablet-screenshot -s ${SERIALNUMBER} /tmp/screenshot-${LOCAL_TIME_STAMP}.png eog /tmp/screenshot-${LOCAL_TIME_STAMP}.png qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_fixmoc0000755000015301777760000000325512323167147031145 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller USAGE="Usage: $0 targetArch targetFramework targetSeries makeOptions" if [ $# -lt 3 ]; then echo "$USAGE" exit 1 fi ARCH=$1 shift FRAMEWORK=$1 shift SERIES=$1 shift SCHROOT_PATH="/var/lib/schroot/chroots/click-${FRAMEWORK}-${ARCH}" SCHROOT_LSBRELEASE="${SCHROOT_PATH}/etc/lsb-release" if [ ! -d ${SCHROOT_PATH} ] then echo "No target for the specified architecture and framework available" exit 1 fi if [ ! -f ${SCHROOT_LSBRELEASE} ] then echo "Could not read any version information from the target, it might be broken" exit 1 fi #get the chroot framework major version set -e MAJ_VER=$( egrep "^DISTRIB_RELEASE=.*" ${SCHROOT_PATH}/etc/lsb-release | cut -d= -f2 | cut -d. -f1 ) set +e if [[ ${MAJ_VER} -ge 14 ]] then echo "Skipping FixMoc step, building for framework version >= 14.x" exit 0 fi find . -name AutomocInfo.cmake | xargs sed -i 's;AM_QT_MOC_EXECUTABLE .*;AM_QT_MOC_EXECUTABLE "/usr/lib/'$(dpkg-architecture -qDEB_BUILD_MULTIARCH)'/qt5/bin/moc");' qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_search0000755000015301777760000000163112323167147031571 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen if [ $1 -eq 1 ]; then adb kill-server > /dev/null adb start-server > /dev/null fi #adb root &> /dev/null #if [ $?==1 ]; then # exit #fi adb devices -l | grep -Ev "List of devices attached" | sed "/^$/d" qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_portforward0000755000015301777760000000173212323167214032672 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc shift SSHPORT=$1 shift if [[ -z $SSHPORT ]]; then SSHPORT=2222 fi echo "Forward Local ${SSHPORT} to Remote 22" adb_forward_tcp ${SSHPORT} 22 while (( "$#" )); do echo "Forward Local ${1} to Remote ${1}" adb_forward_tcp ${1} ${1} shift done qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_chroot_gcc0000755000015301777760000000250012323167147031762 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller : ${CLICK_SDK_ARCH:?"Need to set CLICK_SDK_ARCH non-empty"} : ${CLICK_SDK_FRAMEWORK:?"Need to set CLICK_SDK_FRAMEWORK non-empty"} # : ${CLICK_SDK_SERIES:?"Need to set CLICK_SDK_SERIES non-empty"} export QT_SELECT=qt5:${CLICK_SDK_ARCH} GCC_BIN=gcc if [[ ${CLICK_SDK_ARCH} == "armhf" ]] then GCC_BIN='/usr/bin/arm-linux-gnueabihf-g++' elif [[ ${CLICK_SDK_ARCH} == "amd64" ]] then GCC_BIN='/usr/bin/x86_64-linux-gnu-g++' elif [[ ${CLICK_SDK_ARCH} == "i386" ]] then GCC_BIN='/usr/bin/g++' else echo "Unknown architecture" exit 1 fi /usr/bin/click chroot -a ${CLICK_SDK_ARCH} -f ${CLICK_SDK_FRAMEWORK} run ${GCC_BIN} $@ ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_cmakeproject_click_createqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_cmakeproject_click_c0000755000015301777760000000507612323167147034001 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller USAGE="Usage: $0 targetArch targetFramework targetSeries projectDir projectName" if [ $# -lt 3 ]; then echo "$USAGE" exit 1 fi ARCH=$1 shift FRAMEWORK=$1 shift SERIES=$1 shift PROJECTDIR=$1 shift PROJECTNAME=$1 shift echo "Building package for ${PROJECTNAME}" SCRIPTPATH=$(dirname $0) BUILDDIR="${FRAMEWORK}-${ARCH}" INSTALLDIR="click_package" #make sure the project was already built, if not build it if [ ! -d ${BUILDDIR} ] then mkdir ${BUILDDIR} fi cd ${BUILDDIR} #make sure the binaries are up to date and installed in our click directory set -e ${SCRIPTPATH}/qtc_chroot_cmake ${ARCH} ${FRAMEWORK} ${SERIES} ${PROJECTDIR} ${SCRIPTPATH}/qtc_fixmoc ${ARCH} ${FRAMEWORK} ${SERIES} ${SCRIPTPATH}/qtc_chroot_make ${ARCH} ${FRAMEWORK} ${SERIES} #cleanup the install dir rm -rf ${INSTALLDIR} #install the click package tree ${SCRIPTPATH}/qtc_chroot_make ${ARCH} ${FRAMEWORK} ${SERIES} DESTDIR=${INSTALLDIR} install #make sure the manifest file contains our arch sed -i 's/"architecture".*,/"architecture": "'${ARCH}'",/g' ${INSTALLDIR}/manifest.json set +e pushd . cd ${INSTALLDIR} DESKTOPFILE=$(${SCRIPTPATH}/qtc_find_desktopfile ${PROJECTNAME}) if [[ ! $? -eq 0 ]] then echo " /!\\ no desktop file found /!\\" echo " You will have to create one." exit 1 fi echo "Found a desktopfile: ${DESKTOPFILE}" ${SCRIPTPATH}/qtc_fix_desktop_comment ${DESKTOPFILE} popd #create the package click build ${INSTALLDIR} > /tmp/click.log 2> /tmp/click.err # lets check the results if [[ ${?} -eq 0 ]]; then echo echo "Package has been created to" PACKAGENAME=`cat /tmp/click.log|sed "s/.*\('.*'\).*/\1/" | sed "s/'//g" | sed "s/.\///" | xargs -ICLICKPACKAGE echo $(pwd)/CLICKPACKAGE` echo "$PACKAGENAME" else echo echo "There was some failure when creating the package." echo "See /tmp/click.err for details." echo cd .. exit 1 fi #back into working dir cd .. ././@LongLink0000000000000000000000000000015500000000000011216 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_buildanddeploypackageqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/qtc_device_buildanddeplo0000755000015301777760000000277312323167147034011 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc FOLDERNAME=$2 TARGET_DEVICE=$3 TARGET_DEVICE_PORT=$4 TARGET_DEVICE_HOME=$5 if [[ -z ${TARGET_DEVICE_PORT} ]]; then TARGET_DEVICE_PORT=2222 fi if [[ -z ${TARGET_DEVICE} ]]; then TARGET_DEVICE=phablet@127.0.0.1 fi if [[ -z ${TARGET_DEVICE_HOME} ]]; then TARGET_DEVICE_HOME=/home/phablet/dev_tmp fi SCP="scp -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -P${TARGET_DEVICE_PORT}" SSH="ssh -i ${SSHIDENTITY} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p${TARGET_DEVICE_PORT} ${TARGET_DEVICE}" ${SCRIPTPATH}/qtc_device_buildpackage ${SERIALNUMBER} ${FOLDERNAME} FILES=`$SSH "cd ${TARGET_DEVICE_HOME}; ls -1 *.deb"` for FILE in $FILES; do echo "Installing $FILE to device.." adb_shell gdebi --n ${TARGET_DEVICE_HOME}/${FILE} done qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/click_destroy_target0000755000015301777760000000345212323167147033214 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2014 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Benjamin Zeller ARCHITECTURE=$1 FRAMEWORK=$2 SERIES=$3 CLEANUP_DIRS=("/var/lib/schroot/chroots/click-${FRAMEWORK}-${ARCHITECTURE}") CLEANUP_FILES=("/etc/schroot/chroot.d/click-${FRAMEWORK}-${ARCHITECTURE}") click chroot -a $ARCHITECTURE -f $FRAMEWORK destroy if [ $? -eq 0 ] then echo "click target was removed successfully" exit 0 fi for MOUNTPOINT in $(mount|grep click-$FRAMEWORK-$ARCHITECTURE|awk '{print $3}') do echo "Unmounting ${MOUNTPOINT}" umount $MOUNTPOINT if [ $? -ne 0 ] then echo "Unmount failed... trying to force" umount -f -l $MOUNTPOINT if [ $? -ne 0 ] then echo "Unmounting ${MOUNTPOINT} failed" exit 1 fi fi done for FILE in $CLEANUP_FILES do echo "Deleting ${FILE}" /bin/rm -f $FILE if [ $? -ne 0 ] then echo "Could not remove file: ${FILE}" exit 1 fi done for DIR in $CLEANUP_DIRS do echo "Deleting ${DIR}" /bin/rm -rf $DIR if [ $? -ne 0 ] then echo "Could not remove directory: ${DIR}" exit 1 fi done echo "click target was removed successfully" exit 0 ././@LongLink0000000000000000000000000000015200000000000011213 Lustar 00000000000000qtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_installqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/scripts/device_developertools_in0000755000015301777760000000163612323167147034065 0ustar pbusernogroup00000000000000#!/bin/bash # Copyright 2013 Canonical Ltd. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; version 2.1. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # Author: Juhapekka Piiroinen . `dirname $0`/functions.inc PACKAGES=`cat ${SCRIPTPATH}/device_developertools_packages` adb_shell apt-get -y -f install adb_shell apt-get update adb_shell apt-get upgrade -y adb_shell apt-get install ${PACKAGES} -yqtcreator-plugin-ubuntu-3.0.1+14.04.20140415/share/qtcreator/ubuntu/menu.json0000644000015301777760000003637312323167173027241 0ustar pbusernogroup00000000000000{ "ubuntu.make": { "name": "make", "id": "Ubuntu.Make", "parent": "Build", "projectRequired": true, "group": "ProjectExplorer.Group.Run", "submenu": [ { "name": "check", "id": "Ubuntu.Make.Check", "projectRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_project_make check" ] }, { "name": "autopilot", "id": "Ubuntu.Make.Autopilot", "projectRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_project_make autopilot" ] }, { "name": "install", "id": "Ubuntu.Make.Install", "projectRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_project_make install" ] }, { "name": "uninstall", "id": "Ubuntu.Make.Uninstall", "projectRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_project_make uninstall" ] } ] }, "ubuntu": { "name": "Ubuntu", "id": "Ubuntu.Build", "parent": "Build", "group": "ProjectExplorer.Group.Run", "submenu": [ { "name": "Run Application on Device", "id": "Ubuntu.Build.Run", "workingDirectory": "%0/..", "projectRequired": true, "keysequence": "Ctrl+F12", "deviceRequired": true, "qmlProjectRequired": true, "saveRequired": true, "context" : "QmlProject.ProjectContext", "actions": [ "%SCRIPTDIRECTORY%/qtc_device_run_app %SERIALNUMBER% qmlscene %FOLDERNAME% %DISPLAYNAME%.desktop %DISPLAYNAME%.qml /home/%USERNAME%/dev_tmp %USERNAME%@%IP% %PORT%" ] }, { "name": "Run HTML5 Application on Device", "id": "Ubuntu.Build.RunHtml5", "workingDirectory": "%0/..", "projectRequired": true, "keysequence": "Ctrl+F12", "deviceRequired": true, "ubuntuHtmlProjectRequired": true, "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_device_run_app %SERIALNUMBER% %APPRUNNEREXECNAME% %FOLDERNAME% %DISPLAYNAME%.desktop www /home/%USERNAME%/dev_tmp /home/%USERNAME%/.local/share/applications %USERNAME%@%IP% %PORT% --www= --inspector" ] }, { "name": "Close Application on Device", "id": "Ubuntu.Build.CancelRun", "keysequence": "Ctrl+Shift+F12", "projectRequired": true, "deviceRequired": true, "qmlProjectRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_device_close_all_apps %SERIALNUMBER% %DISPLAYNAME%" ] }, { "name": "Create Application Package", "id": "Ubuntu.Build.Package", "workingDirectory": "%0/..", "projectRequired": true, "context": "QmlProject.ProjectContext", "ubuntuProjectRequired": true, "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_project_click_create %FOLDERNAME% %BUILDDIR%" ] }, { "name": "Install Application on Device", "id": "Ubuntu.Build.PackageInstall", "workingDirectory": "%0/..", "projectRequired": true, "deviceRequired": true, "context": ["QmlProject.ProjectContext","UbuntuProject.ProjectContext"], "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_project_click_createanddeploy %SERIALNUMBER% %FOLDERNAME% %USERNAME%@%IP% %PORT% /home/%USERNAME%/dev_tmp %USERNAME%" ] }, { "name": "Build Application on Device", "id": "Ubuntu.Build.Cpp", "workingDirectory": "%0/..", "projectRequired": true, "deviceRequired": true, "context": ["Qt4.Qt4Project","CMakeProject.ProjectContext"], "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_device_buildpackage %SERIALNUMBER% %FOLDERNAME% %USERNAME%@%IP% %PORT% /home/%USERNAME%/dev_tmp" ] }, { "name": "Build and Install Application on Device", "id": "Ubuntu.BuildAndInstall.Cpp", "workingDirectory": "%0/..", "projectRequired": true, "deviceRequired": true, "qmakeProjectRequired": true, "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_device_buildanddeploypackage %SERIALNUMBER% %FOLDERNAME% %USERNAME%@%IP% %PORT% /home/%USERNAME%/dev_tmp" ] }, { "name": "Translations", "id": "Ubuntu.Menu.i18n", "submenu": [ { "name": "Update Translations Template", "id": "Ubuntu.Menu.i18n.pot", "projectRequired": true, "qmlProjectRequired": true, "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/i18n_update_template %DISPLAYNAME% %PROJECTFILES%" ] }, { "name": "Build Translations", "id": "Ubuntu.Menu.i18n.mo", "projectRequired": true, "qmlProjectRequired": true, "saveRequired": true, "actions": [ "msgfmt po/*.po" ] } ] } ] }, "ubuntuhelp": { "name": "Ubuntu", "id": "Ubuntu.Help", "parent": "Help", "submenu": [ { "name": "Getting Started", "id": "Ubuntu.Help.GettingStarted", "submenu": [ { "name": "Go Mobile at developer.ubuntu.com", "id": "Ubuntu.Help.GettingStarted.GoMobile", "actions": [ "xdg-open http://developer.ubuntu.com/get-started/gomobile" ] }, { "name": "App Design Guides at design.ubuntu.com", "id": "Ubuntu.Help.GettingStarted.AppDesignGuides", "actions": [ "xdg-open http://design.ubuntu.com/apps" ] } ] }, { "name": "Launchpad", "id": "Ubuntu.Help.Launchpad", "submenu": [ { "name": "Create an Account", "id": "Ubuntu.Help.Launchpad.CreateAccount", "actions": [ "xdg-open https://launchpad.net/+login" ] }, { "name": "Register a Project", "id": "Ubuntu.Help.Launchpad.RegisterProject", "actions": [ "xdg-open https://launchpad.net/projects/+new" ] }, { "name": "User Guide", "id": "Ubuntu.Help.Launchpad.UserGuide", "actions": [ "xdg-open https://help.launchpad.net" ] } ] } ] }, "ubuntutools": { "name": "Ubuntu", "id": "Ubuntu.Menu", "parent": "Tools", "submenu": [ { "name": "Showcase Gallery", "keysequence": "Ctrl+Shift+S", "id": "Ubuntu.Menu.Showcase", "actions": [ "%SCRIPTDIRECTORY%/qtc_launch_gallery" ] }, { "name": "Take a screenshot", "id": "Ubuntu.Menu.Screenshot", "keysequence": "Ctrl+Shift+P", "deviceRequired": true, "actions": [ "%SCRIPTDIRECTORY%/device_screenshot %SERIALNUMBER%" ] }, { "name": "Mount Device Filesystem", "id": "Ubuntu.Menu.MountDeviceFileSystem", "keysequence": "Ctrl+Shift+F1", "deviceRequired": true, "actions": [ "nautilus ssh://%USERNAME%@%IP%:%PORT%" ] }, { "name": "Add Cordova runtime to HTML5 project", "id": "Ubuntu.Menu.DownloadCordovaRuntime", "workingDirectory": "%0/..", "projectRequired": true, "ubuntuHtmlProjectRequired": true, "saveRequired": true, "actions": [ "%SCRIPTDIRECTORY%/local_get_cordova_runtime %FOLDERNAME%" ] }, { "name": "GPG", "id": "Ubuntu.Menu.gpg", "submenu": [ { "name": "Passwords && Keys", "id": "Ubuntu.Menu.gpg.seahorse", "actions": [ "seahorse" ] } ] }, { "name": "Device Control", "id": "Ubuntu.Menu.Device", "submenu": [ { "name": "SSH to Device", "id": "Ubuntu.Menu.Device.SSH", "keysequence": "Ctrl+F10", "deviceRequired": true, "actions": [ "x-terminal-emulator -e \"ssh -i ~/.ssh/ubuntudevice_%SERIALNUMBER%_id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null %USERNAME%@%IP% -p%PORT%\"" ] }, { "name": "Close All Applications on Device", "id": "Ubuntu.Menu.Device.CloseAllApps", "deviceRequired": true, "actions": [ "%SCRIPTDIRECTORY%/qtc_device_close_all_apps %SERIALNUMBER%" ] }, { "name": "Flash daily image on device", "id": "Ubuntu.Menu.Device.FlashDaily", "deviceRequired": true, "actions": [ "%SCRIPTDIRECTORY%/device_flashdaily %SERIALNUMBER%" ] }, { "name": "Flash daily image on device (with bootstrap)", "id": "Ubuntu.Menu.Device.FlashDailyBootstrap", "deviceRequired": true, "actions": [ "%SCRIPTDIRECTORY%/device_flashdaily_bootstrap %SERIALNUMBER%" ] } ] }, { "name": "Device Package Management", "id": "Ubuntu.Menu.Device.AptGet", "submenu": [ { "name": "Install Package", "id": "Ubuntu.Menu.Device.AptGet.Install", "deviceRequired": true, "actions": [ { "queryDialog": { "title": "Install Package", "message": "Package Name:", "value": "" } }, "adb -s %SERIALNUMBER% root", "adb -s %SERIALNUMBER% wait-for-device", "adb -s %SERIALNUMBER% shell apt-get -y install %0" ] }, { "name": "Install Package Build Dependencies", "id": "Ubuntu.Menu.Device.AptGet.BuildDep", "deviceRequired": true, "actions": [ "adb -s %SERIALNUMBER% root", "adb -s %SERIALNUMBER% wait-for-device", { "queryDialog": { "title": "Install Package Build Dependencies", "message": "Package Name:", "value": "" } }, "adb -s %SERIALNUMBER% shell apt-get -y build-dep %0" ] } ] }, { "name": "Android Debugging", "id": "Ubuntu.Menu.Device.ADB", "submenu": [ { "name": "adb shell", "id": "Ubuntu.Menu.Device.ADB.shell", "deviceRequired": true, "actions": [ "x-terminal-emulator -e \"adb -s %SERIALNUMBER% shell\"" ] }, { "name": "adb root", "id": "Ubuntu.Menu.Device.ADB.root", "deviceRequired": true, "actions": [ "adb -s %SERIALNUMBER% root" ] }, { "name": "adb devices", "id": "Ubuntu.Menu.Device.ADB.devices", "actions": [ "adb devices" ] }, { "name": "adb shell setprop persist.sys.usb.config ptp,adb", "id": "Ubuntu.Menu.Device.ADB.setUsbConfigPtpAdb", "deviceRequired": true, "actions": [ "%SCRIPTDIRECTORY%/device_set_persist-sys-usb-config %SERIALNUMBER%" ] } ] } ] } }