From 3a6e4982c859d4e7be7016db464b1de2f0e17236 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 18 Mar 2017 22:36:33 +0100 Subject: [PATCH] WIP: more functionality for Salt Package Manager --- src/lay/SaltManagerDialog.ui | 151 ++++++++++++++++------- src/lay/images/salt.png | Bin 0 -> 16551 bytes src/lay/images/salt_icon.png | Bin 0 -> 3679 bytes src/lay/lay.pro | 6 +- src/lay/layResources.qrc | 4 +- src/lay/laySalt.h | 8 ++ src/lay/laySaltGrain.cc | 65 +++++++++- src/lay/laySaltGrain.h | 71 +++++++++++ src/lay/laySaltGrainDetailsTextWidget.cc | 148 ++++++++++++++++++++++ src/lay/laySaltGrainDetailsTextWidget.h | 61 +++++++++ src/lay/laySaltGrains.cc | 10 +- src/lay/laySaltManagerDialog.cc | 113 ++++++++++++++++- src/lay/laySaltManagerDialog.h | 19 +++ src/unit_tests/laySalt.cc | 32 ++++- 14 files changed, 626 insertions(+), 62 deletions(-) create mode 100644 src/lay/images/salt.png create mode 100644 src/lay/images/salt_icon.png create mode 100644 src/lay/laySaltGrainDetailsTextWidget.cc create mode 100644 src/lay/laySaltGrainDetailsTextWidget.h diff --git a/src/lay/SaltManagerDialog.ui b/src/lay/SaltManagerDialog.ui index 4ad0a109b..e369924c9 100644 --- a/src/lay/SaltManagerDialog.ui +++ b/src/lay/SaltManagerDialog.ui @@ -11,7 +11,7 @@ - Manage Packages + Salt Package Manager @@ -55,7 +55,7 @@ 0 - + Qt::NoFocus @@ -88,7 +88,7 @@ - + Qt::NoFocus @@ -108,7 +108,7 @@ - + Qt::NoFocus @@ -131,7 +131,7 @@ - + 0 @@ -160,6 +160,12 @@ true + + + 64 + 64 + + true @@ -215,42 +221,101 @@ 0 0 - 218 - 138 + 320 + 204 - - + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + :/salt.png + + + + + + + + 0 + 0 + + + + + 9 + 50 + false + + + + <h1>Salt Package Manager</h1> + + + + - - 0 + + 1 0 - 200 + 0 0 - <html><body><center>No packages are installed currently.<br><br>You can use:<br> -</center> + <html><body><h4>No packages are installed currently.</h4><p>Use<br/> <table> - <tr><td width="30"><a href=":import"><img src=":/import.png"></a></td><td>to import a package from an external source</td></tr> + <tr><td width="30"><a href=":import"><img src=":/import.png"></a></td><td>to import a package from an<br/>external repository</td></tr> + <tr></tr> <tr><td><a href=":add"><img src=":/add.png"></a></td><td>to create a new package</td></tr> </table> </body></html> - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - true + false + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + @@ -264,7 +329,7 @@ - + 1 @@ -299,7 +364,7 @@ - Package Details + Details @@ -321,7 +386,11 @@ - + + + true + + @@ -335,15 +404,6 @@ - - - - :/new_folder.png:/new_folder.png - - - New Folder - - @@ -353,7 +413,7 @@ New - New Package + New package @@ -365,19 +425,7 @@ Delete - Delete Package - - - - - - :/rename.png:/rename.png - - - Rename - - - Rename Package + Delete package @@ -389,16 +437,23 @@ Import - Import Package + Import package + + + lay::SaltGrainDetailsTextWidget + QTextBrowser +
laySaltGrainDetailsTextWidget.h
+
+
salt_view - toolButton_4 - toolButton_2 - toolButton_3 - textBrowser + install_button + create_button + delete_button + details_text diff --git a/src/lay/images/salt.png b/src/lay/images/salt.png new file mode 100644 index 0000000000000000000000000000000000000000..181409a285a589be0c54877ee2ee28d051f75d4f GIT binary patch literal 16551 zcmY+M2{_d47x%}$FUc}l$C9lnvS%mzmNmvsmPYn{E3zfBX9^*EWC__xwvc2Cl@JmV zLI}ls=J{Xmb-nNNOjDO;e!t&+-{(H(d(QdX-8VGQq@iS`L?93}+FEMH@cRJ%7da`s zS6Ni&!EdCFx|(W;Q~du=JIXTPCluaV7(WE!yafIifk&CxNBAL`zqYgZ?KM#uW+*~tR~S&Cd@236(PeW-4M0ey<6ykEPP zw+V@hUL(~Otmf^le-P$kb|_lavc!FE%Zh&`XJ^nvlJby?`BI@`dcVl683Y{}AI!YU zS9%td-xOqSW**d<;lFoM)c}8-4%nLCJ=q+g`m>lQ^6LM6)5VMiolwdV^$q5;!Et{O-&+aA?Sm!H2!SV~?}Zql~>jgzPn2qeo}y`cdPpnvOtfM5FtssDSmULzZr`f%_Ty zIZ_T2rTU0SyT6Mpx0uuqUkWBnClod(tb};8ld&?g_v<4_Z(C8YXDU0+?8jL3``BY} z$B#W`Fhg}GJw8wR4}N~y{qrV?E!Xa3=h2^TmRDcxM7dD?nkU;_r)TE>ypjG@#P#o) ziP>Z)6)~Y5&bdX1o;-3%h6O31+)mabn#xBJg+d^xd%W)=5a=Nudh+JCcEXwMQ$>po z7~H|hZk&Vs@A7N6e+ZqvJw#l&#Ju$CcvJ4G(ZhR;>MhD-%I%qcF1)55JWXbMy&u+W->^0>H34ee8ubXXK8m_J@d>2%s zyQyf8e0oHEvrBJp9j(`#-icZT-f*oP0q+UfM<#Ha+GsY*<=_b z3Z{@ntE65vVl*eXAAmYoyNYuzHWpGVGJ@Op`@HsHS2K#?(?%dBBxYq|dU@nWq8*UP zxXWE6VcUHy+dD%dJreqrn0nGj*1i-l#Z{!YAD6CKo|%wv$mXYvCG>6i!nN6PFqgR1 zvckEtKjU>E@`5fkYbZBp?(m|S*;ZNC85nQ^k4!Sr$nM$KDnu@)C;$GO9CU68|Cuzm zOQKuwGtA3vYX$3mx%1OD7B@f<*$tVzr^UF>%_$WkcU>&0pEPD zeDiH77#kbwt3$KR|NSogkILq1@F}Ay4z6U~Bl_;2S{62OL4SHYBBLL7(JJnF%_~+S zBBFSWqUOIlLj?BenFVx?Dq3*~?9@H4>(GCHn0Knm=Ejv`$zxRqmVGb9Ti{}sWHMfn z{X_1_$*LBNTCqucT5s54xlrN^{XTcr_4^G(JM#M5BdDSx**u#G3Iz?Gg^g}9Rt>yl zDv0(u3dt^2p(lQUPBbnzmDHD?oL`=A`q4K3Z*%4JWb5?g^pE)r*}%(hr8%BQF&;DQ zxlD!iSDi8i$c)_T947)OdqiLRd?B{Cz^PxTIJW#86>Njv`9$6G_20p~reeOPon1cL zOt4AU|mHV&O3h`{vM7*koNlsGAF+9U|Y$LI4NE% zkWO5-*&8$x&ivKGbwV%F@tYx`kLP-&#of|U{?%5+a{k4R$pDTLV~Re{5=M zn#TOT?6fc8yTi1DGUXMNum_Sfz;p^KgiXyz%AaQF;iToxYctSt$i}!!C8{Sfb91J& zsfds4k`oi!W2VgPy{N@yWa9Psqc=A_f5|Hqpe$&pA0B^Gye^!XI5*=Ao+{3Tu3vnRlG4^dg24%Vkcl_;WhWb|8~yw_ zVShgmrb)HnYt)+3$&%79Z~~~D;lk(7sq9XVrpIPyH}34i`fOQp=}&lXbsRV@zs;P$ zO5Sxq!psb;>?oK_^=+W~w z^FnRlhUF8#_g7XoHu`@35{`Sr%SFs+IPJHTrCiPVfmQ^f^I(?82-gge=>poS6t+poPol17; zp8HJWa1-iPqNKv77Y;of7cX8sZG&sJSkuY{{*3gPky(Cd;=Pn4UD(vbf)EuIjf5D) zK;5H^a|SmAucnP6FFtN+j=GU-OgveFB|u`v?a%>fcc^&{)_JOuQYPVo>WFVmRc0X)PEPLp{8&rm_3DtHl$4a;Y5Mc$&o6?v9S7>DwbSiq zq+mhQwD>#+T@LO#{;z4q9Yr{QdRAg6|%FnqDHv9!NG&E9mO1_xc zOh`1f>Kk|2dXG-^%9*MsJRla#w4BkO=mmor0}IWS3v#r#N8F?3=zewkm>-h`*J*5& zdfC*}wkuFvp(G_0=PygsBl?E$Ze&F5Z7Q)1#;wWi;J>HN7-lg4jg5`wowpZ!-kfu# zXQ8g?Jdthmnol+rj`f$_Xcc=&rOr4tW1!0APj~%1m9bERZq%Kcfw~8Vf-zcrgcw{` z9hz80SriFz1k8|^mshK7;^wVeJp%&+;s{J2-{+v?Asy^DQ`W0RAy!Scykd{N12wk|A%R6+-P(d}+268~mza6Me6iwrbvM`PAI+ch zom_X75e0?=Gzr?Wji$mX(|Z&`7%#g=EXZE7-N3UM$b0gye3y05cCXlna2InB&#vC1 zU08l(_a;vv43;fbkADoTFfWgDI=0>;>?3%dL`jbph(biquU82N`ujJlE6y}t788pK zn!n8g+pemrDqfApQ^(ARF}`p$Dw5sbEJv|jKQ^;cv&0jG&l$?tUkh{*$e~9fLHTxq zjQBly`*`1BBu@dRT#JtZjOwPBSO0j4?(E}uXACtRT~A%55@GZ9IykD=(R7OB5s`1n zwDb?hQtregu}LqQcOID?42g7xKW%Br+WPUMJC24;R8cWGnvBkI<$W%alk?47N7!W< z8S=c9u`gfnOYSZ60A?Egpp5!jeZ*I!)_>MNE`gMSBV`o9J*CE|ZtdMg0*`~_;_4q5 zAgAS&hcVq%Er|4&O>z>Wz~J!91^&Cme$IGiwnbjAYQSr=J}GZ!IvEAMA~pMtB7LR)Y1?O8-W>R)=moS2;Fj1pAVQGle%}5XG4SGRm9%p1V}rAwGQX zM4YTd$Ud?O%&K8jR6dC~{4{bW(14HO@NB;iej7f;vdYTIU4}*4-uCHT@(KUb!}Uf} z>B#6=#gC)I5ru;%Gv&|MWofw-AK>qklERy*Q(!9Gvb&~cbpQF)YYgM40`cp`lDWlc zlKMpbK9>%!@-e7rYLZ2Dp+Fy)o3pgGwc#Jx0!@l@uJxFaVx%O&$A*kS`@J8Nf|)u< zR@NxN1c(X>34MimIwgvs{TxBuK@bHlF{YGvZ z@h<@MA-pOr8z@)u!m4L{cRrY0b8vTeH~y)T3?UZA14{YZZb;CjB6wgSs|g947o)wj z@*^-qFuJ;@sqYwZb}&) z9sL45v|(_ak)+F>K30{W-1Ns3_~WG&MP=q@`9EKy?cChljv~OxTzceZ(f~#RJ73Mp zDrctT_~dx&2G~E?SbU!&s62~0r~A5uD;_+R5=mOpB2yXP_ej@>)xbA*t(E0(w%&eC zc9H-1V5@&~wry;FJ_SZoTYDLzQi<*(c&cWVqp>1Q_zOCmvkhWg^UA>Kj!n?)-UvL( z)9@v>dF5NT*4NUszKQ7T>u0#|zj^Zp6#dwzPxou?>^+Aqhz}Wo8=qr4|1OKjcz;De z*asa8VrKSZG~=3<-2EW;N3`Q>UC+v+{C&ZUA&&z8IW5M1#g`Z!OH(*g_0prOVp(dn z7HYR{T?h>ev!NAPoJ&ehcJ%h9*Gy*55}j8~wihLja}Wj3p~h3Ifm;sh+^h0BL||_2 zM05SMH-|^0?51Dj5Yz!j?CJRieB^dh#BtM2ESBJx3d}#()h&L@Da%;GphlR%zwa z_Ga%Nw%?d-W4WvRlt*SD^5e&kNDWQRpxLmkjxtC>?heA-1?c$s?dDBQU61KmNI-D= zF~ZEjLdhI_@$(r|XK7J6TIjjA{dac+OsPwh8ve5flY~XqDlrEAbhZvtJfIm`-){4& zH$C{cX5az&pfwXEiFDviH#b#XT`KS%pb}v#*i4JECPg`82UBQ_L%@xW4b41Y96$L&Gal*xz$mh(Sos$Lg)1Jtr~~P3NxAG zpY^r=YsTRVRCceYs;ux{+Ia})FjlC3R*OMP<3i4Gt4;+r+X{1F{5KUDEg{FyYK*}_ z1~l8z>Sn;i`t)Qx2{JMef?Mr02n$8E>D(GFN zrw|2cw8hJtMrLnOzN5@Bfi1#J)aT;5&bdChD|u@Q1r|M`Ut;W;YT&Za-`_vW!$U(n z-l^^;J}320jb|Zwg_)AXr{Kq66p0p3TJTIAI{b%8ez&ej$G1`w?0mk%V~Q^E@_0I0 z+QQCGt~&IMt+@`*Aqt8Q_vOx$ck>a(x>ezgrIjPk;w9daCG`0+w10l8Cxboxu`@zx zd`-f)<%yi9m2js0%s#Pw>f@N^JKvt(DAD6z3KSB^(B{h++_*zshgcTRKh!HMD-+o7 z*t$)pbb2^)CZ!+p#tvTtnfOz?K)I*utya_a80H0UWX$30^T?R2+~g}29)(Ni@ABSl zEybRV@;5dcS=k+M62r^w7Zeeq!>x-KDMRTnxHN;Z%bbN**ufLYGn^3PHlRzm;E^KWL+W!#E;?|77}=Yt!^g0BSync|xcv8!^jz=_ z6(Xmuk?6l)$&?1wpaYQC{}6LKvLV7XuqY+Pd_NIl-f+ zD~j$jffpY%30jng+E#6JSiatL_Fy3{C|oWgdpSo=--#Dt*8vW-HYS!Ja2taLIW76G2;aq0c) z>P!9s0r*DzCRp8$%9o8kV~FMcC^c==Ol)5biabSgg=zN>#TI}V3qhMh$mts;#> zMLtzo6|JZ1Q^_Oz>0t#ehKU zni6;mh$o9IoqtGhmuw(F$Ke$fY#y$+%f2%;ZJV-OC@THD+xwsHy;nN@Ta%_|D2nu# zNxlI=#BSku{!|ekSSVxh+2_dZO}{@sU6m3+(6{e@z7@P))%3!3gtMt5W;4Eo$gAJS z`i0(P#3)RiDO(-fu$edz-esay{ zKwtZM1%X`Tq=<^_=ZauYk>4So3t8a^N=X4hh|lX*a)UUp*Vt~9Vl*{0UUp1rb>Rv3;g7$fG?!H>1 zh;2LauJY?NzWWZCK-DkyNYdcE{%V`HUmtIzEJ$}A(ioRNJXS2OxJXW@T0kEf8u}Fb zna_JvZY+IrzDqwc|A^#`%5G+|Dd zH?0Bdzt*lruwJ-c3HkC_;k9qambhh6>K=RoH|VtU&ic~9zN&vcb0x_q_-x9fi&lYQ z@|;18>JC~=xq?hI3=CJ}3*$FtnwC0G);oVe5WE4?z%)OzP8+gBEE4i0C{e0aORH%p z%*sKyPcqYKZM>xUYZR3?1kQyA;_tn?G@_&4hf_o;C#1gr^GBvW>|pa=b?c7`k~No$ z7LoG1@5Hm}M-=6r2~zS7?Zlj>bqUmnjW;cuF+)u(7+>LgCqD8O>UUQQ3}p&Bb&VJ+ zZ97<5?7}aDS%&|Thh_bCefs&`C<__Ow^)yry=l7&Zg4q(1&d3TQ1{Gi6RZy6LM z-Tw7y$#}vBiGi0_&5ao;aZyo(b~>a$+mHY*yuM4ciPyn+<@ac4`0W85X*6VrSK)g& zG$sn9ygdxeqQQ;Hu@)(zkN>&*%$sBmIk%{&ch5}EinX0Uxiv3rZ_>Q;)u_L-3NvNU z*4*v;rP$T==N;<#(z!a040V@XMUiSKddL`KoiUfF-eO#HW9#3`4tZFWEzxu*<_x>c zo(M6Bq*~nV6)Fx&_#LcXWCR6*YuPLXHqXNqw;Ic1RJr{F1G_~ZXg@`H2$^W3=uwfK z?2&Y-u_zG89vvMW_&K|5R`U3|FDsujr**%CKL4X3ZX~tAfJ{hG+xg6Z@zW1;bGDK$ z&(51*xEV&kB%5b=K`e_>FTG)DsB^ImfkAZnutRmQU-d&KNmI`UC>@PtmxfHZDjk0^ z$r$8=gy84z-@oWa^HwzE#U_s~F{B4a zy?dGJ>6k6p#u);x0X-p+B|ajb5wbfhowC2bfAYPmY0j59{S{hVf0_BUp7VUiNd%`b=K1;MsL4@IGeGK}jd_t7=KBewjE%RdxLolQTtE0!}# zlOSQgdJGlDk#ckP{;v1Aa#fDC@e>AeNkZ2o1N$5=(?%{66{|QyI{<{GQy6S5VwFg2 z_Uiij4Jd{@;gAcIf!w!(jPE^J>#@r9`0K()jm#Dm1hKvJwyIY|MBDeyZY|mJkWWag z2Ufuypb%UMcL4vI?5N{hyzf ze(&vFHo04r?OfpXyy_!Vqgc^=SJlrBglKxKJE)cO@dakTO$U)_;rter%t!P#=F@_q z;0I#V7Ey6+$pv=WM5i2=!eK6<<&CEHxQ+X7>IyQtx1HA*!~~QHPm8D;f6htBKbv<-z?v-kCzYw~j30 z@YGrKae$|`NF>gJEtfQZFy znVwyFhWjyo?Oi_Yy;SMO>>~%_vdveK)?fu#NC8(o)*zXn1DsL%nINQ#Xkfo9^MgIf|5B&pM z#`|ht5G}?z>LGnjN5{tj7+gq?D0`16(iny2sw@Ku25KTGd3RAG{<*QtkX3kBc$5Yckv8;0?G*PnQoRVtKII+$IWMetOV z`YZ`O|5TUH6Rj(6YO!_X3=yN~3pi($bUxzfu4+TUmrvcesVGs0;d!^P*fs7L&zGGW z0rhX!^k>#RA3mR=-R(MijzQ~@bc+KN4;94379Z-AU`S{WIX{%jp0}CSEyX6_oG&9N z5q!x@umdW-HT{z3s?=a!IA2*bxFd*a5$8=P{0$|QT?^%gR1y;U35hEhoLop=zNnh% zu;zhSLa+@BtNij5gR$BZ#1rH4UT9W?`TKtm%G9Cm5%r{suc$z0DHkgxQY&DyU0Auu zU1y|vL?66~KoQ`aiHa@OWRmqR-0rw-o4h15H?I*LZBgdy=OW0NBAwZ_N>n@sExYUL zMoud95Uq-9&5s1jBG0k1X9@!`Q!FIS!;R`Kp$5bdc$6GghHJAm$1kdpfTQ0M$X z#IlgOZaSX^J+W;%pRJi$;mfF?y_&vcV>0E(I(=8YDw?dR&Jg@YAb-JvInD%{iz2@b zzLA=&BwG0DtdPBQ{<=52tEzLWu~Et$+7N}TQykymeT^bLjHrY}FWdm~LYd^AsT(vd zgp?y!vR)v9iTsWA$s)aF-Vs_D!enKBcSe>;QY`}y|PI#!CQCiD0Eej+aV>+yvj*TJQz)5o0mPiV4?G^nZ!zgSYe z>^5n+yiPJ~?b0FG7&>))+<}W>q#9~~W=N7Sd;i6X>*@yy&X`hZ(yZzoea-C^R`v#K zi8zNRI<*g^C)p@tQRJ#yQ0$W7LecOa%tt6)AXmKxyN75*r|XIl<%GnBW&P(&>*8|j zDmUg;H40~Kj+(ILfIh7+YLlwrkrL^U=NK40H0b`KLRMymj^7y8((hN7#r<&-F3J0G zLXFnyL&m)F!Y~Kt-K(fjxO(+!J6$SiI`m4p)3jbB6ru|gV@#Za_)Q;|8Lxgyxb`EU z&y8epf`FAHF+?f4dXN4RbkBM&hx!G=fCy3z1&iO-eNp>US%wYrZP{)3 zL!T`3`hv&#!>^@{4ZLiGu{{oH&Yw8(gQD*7FRu`uGEo;Hipdgw|5)FAJ@^fet#_KN z-ubWNST6)LywE+O8{ka!+-E$gNTb;mv{%gxN7#wiIV@yx?jPLSEbD`9g$cXaBGUY> zSI45k%h-dLX{xCB8gfU~-crASqu=3NoR14Ho0-@1xAzC!LkJd0UIf*NGTe_`YPQ8c zhWy9@DTrxalM&ta2kR5V8v4tHlSGwk*ZW-=Dj%^#YtPpkPbwg(RT=x#n`Q&qR$#H6 zKq!9=nd5j^G3lZjP-oeno|H{-)5Y;hatTc=?f81gD`yOpjtUH)X_}eMk!eK_d>_tf zQAUlbTfQxG6BjCz+$cYK;YQLRo^;K?kb2Qn2Rp&>wis(fPb`=)E-oSQ%_>zREnIP= zyyElKgcy?+i{*XKFyRZA%ej6+C;5LYfQk9K69L(Vtl5#lTo%hrqjs$*dtzTUtbP3B z(m@i!yV_>ILrW=K)01SckFwXiV^%<#d7vKL;Vdt`r^W5Y25OV1r`T&!iG?;y_{Q!Wh?+7K>V zJ>`F4d5?72Ou5_idGzRk5JL-z2^B^VI|rV?!coPo#rz@9i@jDYzYVwH%)MuOHW&VJ zy4BIcq#wZ*#{uc&xts$PTpv>=nL0BdR;u>0PO|G8?!RPmM$qOd}kPutS}c%#V= z%s^Qt*{ZnWM+}WyDdl*_L=0TFpEdspD)L2xo8UKGb6Gl{irM6*z32d71S_hfCFIKF zS2ZuzqKEjLd?o_YTv+qe;YbZBofLMLOa&f2E(x*h$MUs zgzpwHtj3d2#Huc;K8ux*R~~rEII=5wG2S({N&ES+yGxP5H)<^fOr?%ZduBqcGftgW zIfpJaiKgNJ<*`oR>rDU*{G0*Y6D zsdbg8S3(~elm2>Tq^hM9DUxgfl}Y#g)W;2nNOIgbV@L;8%VQ-Zl=-w1hUzMVZ=o6< z)`o9yEUAcx@@TPE7(JLG^go}B#yL~;3^H(`c1_)9HjT|P%PwkF{WSaZn4c9UWE{L?YPrZ7BHQ6a30FuoT0Q19%N8%q8CN6WK$R+ckz8)V{evD^nF~YCyX$O}Rlg@&pLAH&5pcQRzBuH2by}5`83mgb5%b=D z(l`Gtb4-q>lv}Grk;z{4u*8sA4V8JpY)qAgwM{wgqD*p|ofhx^{mN3awg>-Q=6I1H z|7^VEquKWU9}FCcd(VhTTRTcEIbs@LviD2=wbr^y7{mF{5!2}TzwPjHLxpz~ri)dG z`8wgfAQg<3A2$sZ-s6)J-sMkT;{WY1d8W8+BF4nIsFW%)qaob@A!fD#mA<#NmOXIu zsXm@)<2hC>j)cWc&#=Pg8Uy0gcJ!{vzv~s*w0SGA|D} z;M7GaT6qZmHg!;_5^(A=Vk{|G!4Dlh6nG(lkQHSz9F>ag*2x+CP{&%&l>aVjvNAM6 z*gLJf+pV*R_5Kq+ZTz%aL_&Dh<)>J0KrLtbj7uyGYKY4|x-?}PK)++nFyX^KJ=%~O zM@+6DD48o9dbsF^9+I6f+CNkiw;bxLa5AfCvHo_LWJ`tBicD1zf}#qmR>vMezfW_h zO>qkt@`dy`w|w<|;o`Qi3rSzcM})|J&{+NVX^s+PT-J4(7`?NcUfE-AUvuE2tjxXT zOwqwM)v=;1881NS2{Hem7 zKNC%!#s4J9{X_U;f^EXGDGk|7W@<+jMs@7RmQ)S>-BvlBG^#61n5&;8qnqfSkKNQL zL+A`6dykbCTXEtT8Vr6gqtV8u2ut&)mRqk-^=I-woV{vl^1kH-50^WQQUFJ98@Ys- z=5?@|rDk=gzzR!cSWd(UM7g}=Or1O%KTTAvGe6Rn`k^9vbS3jA%XmD@I8l6%VL~8D zsc-$;YGha;R>M{I2T6i7ec3wKw=(Olr(pd4t+#E-v+piX z9!M1RKmKC>ypJ?rZ?kiY=|9!EnEnRc_q|cUX=v`wE-9`;q9(Lt{WaHkxibs_N ze=XZMyPKC3WXw{crq_Q=5@rYeZ2Ww; zg;R`|BV)>4Ib;4xO-K}AS&?yF&`4Qo^sxKhW+70Xs#2~~)VNpqGqaSUEOa)!_*_-L z@O7el(-okI0W*LuB_#1sfDiY9bT|s`V<_b{_l|^+AV^c_bJT}&6uY+H6w$L!;DNOb z70o>a=LU6a8up^1{dN7=fonq`%AWYXjfFCjDHlqh0Immu)6;k1CYA9u4q`-5J60n_ zvfgatMDMlP35WZ|MYkiIGX^k&9?>tm?M{OXmyy(WJY^|}fu$Q!H|$yP79Xq_Eq=Gx z%+ly#)e!ah2FdUsUuL9nBZ_HFv!j})-^b952@1WBh9FCW{ytPK-@ku90tLQY{av9G zOL_#f&)?mY`22m?eo}i1fiRnBPf`}Qbd4L@w#?KSBpavB23kS?o)adHPaAUnbr(z{ zchp`Sp_UB$iG@5T3<`QW(DZ$N+%SjjK0Et3mtFQQ$cJqRb5KWh|yGtA}dMvsq;G!qhKCG5W?7Vdw0l|9HzT0a?QT;*nPB9Oqt zsIJ1F0k5poWie`^LO~uzN=dyJb5M&an<#+FNB!G2PH0j*tFUCj5Je_DEb4EwRJ0+f zDU(&q9Vt4{E$dSKQn?d%1$w7i{26B}R*U%^p{=UkmB4g?mB+#h8TqmCw#%(sw+tce zBqWfoXP}JzalR@p=tg%&mW#jC#rp!chfFOQ-%=-t>YrU&TFPjp9r)P^bQv)rbmlby z7<85P{325my%$HIC5rsZ1wDTd;#_}4aq41O#3Q?@eAx7K^Xz2a9%BRC3c+v(~I(Kuo$Q6|h z-2a|Q?q70Emnd>TR(n|sGNul@sIVe$IoDd?mfc#o8my~sl$@&~8CY^xu?U@uc6WGW zPzI!hO;94D`&$@zy(a(PCz5ikZi{oloRiGGG8Rjob;2ljt;O z41dSJ-EG(dmkeEUiVHO4m*}O<=!v1X%);*fPK78Yk{Hm=NM{USo@Kd#pWA7t*a%Tw z_P+{&%9555V0mOM0T6|v;%0Rm=RI5p9r(|GRT zGtzjsF47$ z(B_t1x~3Q;?EUWi@J-3j6HCrnS(ex;K? zH-QNNjMEvjx!*f^{mM`s&?o%G;zLV~?p4_CwMZ8!2zmV2$K6q)d>1zZa!Yp~J0Lwt zPJT~ZV_{Oy3W5QV{%1gDW+DmwOZ3DJ-LJ1z*&9ztIMsimK-HpkzskHXXY$fxk*H^) zdPkytRdOtVqtT-cyM2RzqLzofzo4v)3?QQ2YMMK?M9|ZV0mNo1T@@$&xN?~l4{h#- zG|7CINyd2WJ1BzMA(A+1OMAfB?*kR~-q7q)3IGTqO)0xOQheB@g=o1?hyH8h0g!1? z?=sv@HMJtCtT!QFUtcfYy(@2l3z%X5(ejMC=c%C}DpN;gIsgh3`kCFi)z1Trt-p%V zL)DQ_+mMk2O8046#A7${J!jZvz;FHAEHS>n95ToMI;&!Tfo62A9~##9+VuYlnKWQo ziSsA>O(Zb2DyC)~c*-ujw7^i%9w-AQn@Sy)3}+1ZApHqZDJjytl`FEOSzZ!FFWLJ3 zLut`NhGvr_Pz=-%WQ-~l^z_QCUI%9a1Ti!us%`_Tr;IY3RyA3>TsHtE1a^f`#=FXq zrc+AUgHG3v5LalcubP`rk9o^bCohQt&zP2$Mv>&dcl55cdWO133repSXC|YzmIxlK znf4EQF%T2LbxG6!zN)B5bv{=p2>owqeqatg*R>S$?^Uk@f}K#PY{b}f){;I(d&Nz5 zj~?s;O5thN{XX8Gv1Qs(sGEw)$vp{&4K=qn7EVr1e2f^=2A!a5lF+wU%;Z(^q1XXg ziXu;S&Ki?Q!oLD?Yte}XE<8xfGdD?chbr|NVhB9WlOyAuQ3?78ASj^iYh2C+8o-+S|~fK5!hL@GLg#K1OmsxZpR`T4QF$wEQuy;Ik-laoXgZc>mDRW%Fug zBge&+iA&sBg?uEkM~w`3gBrF36L_EkQ;L01QPGGZfAENQpzU6KP%SE@WC9DMFEFX# z#(^4Izyr%`ej^I^bT75^k_}i7l{~Ud0KD>h5ZAv|O)oDuw*(p*8enPlcLtx|jcz7L zUit+oph^`s8)BNL_t37q7I(Vf`I0BpxraMW-A{H-UELjTo(LJ|pyXR&-2j(DDQ9iI zdjbrw*}t(A=A;aidNz#t%gy~((y*b?;b zXm173Bj{4tS{xOI^=o2ZL$@%YP;fLstvM9CctuuHhn0)M$C7C}{^t3s7b+h;@f2oB zY}P5(Fe2UKLyc0s_OC*A93>XUTVEoZkm%a|8?zY`sv;&Y{{R97bb0{L05IGSn2?lV zX^va*`Yb`4Us?i!gPX1BW0Ha20=UisEhVJ*ltA^Q(SuEXWTtq%Y06F4(l~x=bNN2c zE9u+$jWWHG69KtG2QgQoP?78}+td`x#$ENL6QyQ<$kpQd9Mfp-^++jbY0M4fZ1bjE zNhZ>tco76+!r_rH=s@BdoLHPQSH!n8O>gL693!seL5#ig7ns}dUEsZXR#yd~G!3xU ztW0q>6So>s6zUf-Dznk9$R^iqu|ewhdc4>e0&PVSS8RHt78!rxI-2>`<}I11a*p>mhCDvLScp9=wW7I9xAQIInhP{Y znxIU}twN9IZJfj~<_Xgh`f~K--fCGLG>MbeIJYMala^m^dBkDvd?~PLvCNm8be*nu zz?K}838`!URLKwzUT4pYe5A+k^Xsb$;&q+#(Cc0Kz|Aiq50{z+z885)5-V4Co`l91 z{#gRnKOwPy3H$}XK>4E;HdXwE>#ZsYF1B2Egc(*WFZ}j@*czT+e$XIJ^4hefWcFIR z@Kivq17@nc3^OiDjc+^x%>_+&=wJW~@g4BJ9FG2wU(og(Zl9=%^RDF#`*|7hrwMwe zf9>=q*wgvSdDFD)ot%hsb90#}Mz#I|+0RB!Tx$9!>*b5-ij>hUvucZLiDq+bR>N_L z>O?Uww?K<(;GA=GWK1&wv4QOa84pb1nb+*jn8ufP{vAcXBDvDVL*88zaXd3G3z4Ck ziJP~1^1A7SL9NK--QRJf%Rn>j4!yKUe2W|_xZFs`x z(xZCdsm>Gq84RB+k0TghGPi~d@lLDjNS?ujL<;CskTV4Z1=%V>h>T)vN?%|0eXFaU zSe?Rh##f(DU6$HLUn&)os)=Du&I>|=C>l%|AR1`WfldchWks;xM?bq%;V02I;-QIa zN=bm~2SqRwb05Mv8QIy{S=g9lwCvvXmu-cDwm)Znd6s1nlO^a;qHyL`$B4D1c-_s^ z*eHKym=hf2gvVOY^7}fF#``sd6Nqf^$+43wn{~U$+f)TAQ9*R{FJDqrGzD8C7&kj3*BStteri0M!gc zG;o3r2b;5+SCSKn{(QQ9FiQq1>%RMJ>)uQh%A)gRuO=7IScZgjlWSc7>Z6fQ`>*Mx zLF-nF$!v~mF^TH^sNP{7KdEBHMVcRU>@q-S(wLd~ycH^=uT#9$pUgoRxp=g<9uWqZ zB0j78b_;qtjFd9|tE0t@4~)x;&2_dpudyWRD2WSv?&E2a2uK%9aPo}XcKHmnIc!iM zxu7*nYG!7HX2z~>FCSKG(NLrUovVl@@BSqcaj5J1sm>V@3Ct`6S3N|$1Cma=Q_kw3$z$i44k;RCF!8kmeLQXy?$lV9<-Dx5P{WpohS3*kxycL*Ge7{ zzFq+ozcX;HRS}t_0r!Nh)Z%(j z0KRybR^SZ&%bd$Hmo{bI&z}Id0X^RgL*O$o_$loqRtern)8zDt_mT&t0PGSo1;OKn zef9hyv$kw!*)a^-i$9V0hkxs|)h@X5n2T>h0e4YHq`;Yis;zkd{XtV-Z~0O29P!l; zy!?+T2@g@`M3o5%b{TI3fW4%_iJpA&X?ITj(XU~RGG+4yaSVL3Z2(X-eXj+2T$K8% zRSL5T{i~NDyWitRi{eNIfJ&98wnx^y7+!C%L}2?i&t?nH^OwtvQCUP^S+F`mxo6#=>)% zKrKen{m_;R+GGdCXVrP<-@l~dtJb_kPQdPbZ1F3*gI68kYOTVCC8uMcL<~XzrJc^4 zq!Cg#Ca|zxRr1oW;Nfo^wR5AUhS{X{aQxn@19yxZB4afTwhA1MqQ9>O)?oAXX10q0 zV1(#?AL%CmBZS$7u9d`%adT2B!x6O|C6TtDbzV$~eO=H7uLf|qcmn&Xt!<`FL_`04 zMdRD45f-Az-XD|CIVL2|rEktQ+?p2c_qo~xhczaW zO6AbZ@$rShyKtJ|#vLHmAtx!t?yUK@3d^|6^i{Y_Rs@ZJRu30<|oy&hWw~jy801#t>sW6EOJy54M3}iObc&?CZS!Q!>Z+)7} zO|1hX%KYu^g&JV-rRCvxfv=aB2%Phv_+$;ZPl4g%QOC>XcW!rVU7kQs=|u&1XQvN3 zdH?z4fIqTO^Xf?0He{LU_rXEiabb|Zf2x5EZb>G`0eK5n%aM2ZMffjVm+jSkzW<}AyCPw|)C zXzb5SJp`l<*jvDXfeSY-|K{udUo8sHu>neCa!r8=R6DT1a8M+nPzDa9AYC#0VbWi` zqi3Im*4rZp5&3_=2>>&G+5j-$?flcfD_MXO-OT>Jqjx?-8-I}JZ9zqa?h!O?o(jI@ z)9ASoQ0sQLn3;b4{1pFR+tzAcK*&=Xc4qp>A$^hO;;-b4;LGpXRi3WfNuF*9Oj80e;T}WN&qTP z9dyDU+vws~H{uthFAylf8kD`I)EA&FH}%LDeuFZ(`#+wD%tt_*jl$s)cjr9|y*etE zkV_OFFgSf|HV(K~kHhdgH-m#^e#*RGIbF6pA;F`4JwK?UN%->*-?_q>rbz%VHhzJv z-l#(Z5UQ0f@p*jQ_(A`Yjtu*IB5#5WgEE^^m7zLoUm5Lm>*WNEB68AbrYvTxVzsu4 zJ;sOtAEuHWka|{DRQD;19VODO;@QOszIL@WorKhX=_l;Sve) zeXjTb_~fNe>;$4CyU_T9ln$^gc#nyAEWv3!&+ClTP@Q<$=vXUbDxCS5riYwCnf|j$ z`ls;#I632ywj{%Aclg#ET6YzAANLvBzqqllPw7PL7q^28T3SAl=mF12kTLAyfQ-wb z;GH=OAW*O4W$8Zxkp;5?H6&OsuYBb~02g95sI-)!7-gLF$oW$PZJJhZm4C(oD&{lJ zd2hXy6YeL%oEYbTOeCi-m3^x=b=vIE6W7KZmHdn993CNBH!1(Xtewt?!PzLA66ngO zX+8a!-at<^@#&M0h}|oBI(rHNYRsnqn|_eF0GL>_-21uD_`k!U$naW1%cg{%^LF|aV zDNz9}55P@2;Pe&L&Y;Eu+tYJ)Azk+p{yfnB*8EnfnYM{N^y$4QBA6RkwBGtWiNR)j zlwxVm#f??3hrYlqP9JeGJ?o?aPEjONr(|Ul4*L=!+Tk3MMMvmf)HoFvY7g_c9y0s5 zmBS0_Mt@UT(6-*Db+YMvNpBo$Rrwf<&TD5Q9z*eyS2G!vKf;ToF6`)-9ga7ujbD;6 z=yb+#&ol-s5n)V45ETj|jT=DiM0m5Wgv2@6p0sryw>7OknD0D2?i5+QwMFDa>I=M= z9VFjK1BLo5q3|0x4|xd*;vUh_sVP!~P`?iY&bi@Jqk43iqs*Ox!R_I&*&>9&V~rata8T-fWrRAkb}Fm`Ce1#!23$aVg)?%reU7!y z)r{KJ=wku^$q#9@7vkcj?s-vb@gU8)#U80~t%JayhAK^3-!I1*GqTotat{t-?b__H zdA4mx$^Ra`deZlsK*Y+07vIaE3tOL^h5q;abH2ay%w`)_YL zzeMn@BzwP&koNe!o9j>ny43QGp$r5fQ)Tb_y0+iOwHAMSE;fA;Tg=yo#=8i3%cYXL z%J#V^^89Zyp4-5>!3oZ%Ii-hD9y2pKCF6~FuC^v)<+MlXFVSY}`lZv}!#Z!mJ3MgG zS^L|dKxfBrCj3(Y?D&5dAm4p&B;o%*pFh<7@RZJnXDgr)@Kg94LR;NHtyi+-) Cm@23M literal 0 HcmV?d00001 diff --git a/src/lay/images/salt_icon.png b/src/lay/images/salt_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ec11c7ac02d5280a8cd406b672817751117889bc GIT binary patch literal 3679 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 F?tdV&+v5NL literal 0 HcmV?d00001 diff --git a/src/lay/lay.pro b/src/lay/lay.pro index 7efeae835..572c78a0d 100644 --- a/src/lay/lay.pro +++ b/src/lay/lay.pro @@ -49,7 +49,8 @@ HEADERS = \ laySalt.h \ laySaltGrain.h \ laySaltGrains.h \ - laySaltManagerDialog.h + laySaltManagerDialog.h \ + laySaltGrainDetailsTextWidget.h FORMS = \ ClipDialog.ui \ @@ -142,7 +143,8 @@ SOURCES = \ laySalt.cc \ laySaltGrain.cc \ laySaltGrains.cc \ - laySaltManagerDialog.cc + laySaltManagerDialog.cc \ + laySaltGrainDetailsTextWidget.cc RESOURCES = layBuildInMacros.qrc \ layHelpResources.qrc \ diff --git a/src/lay/layResources.qrc b/src/lay/layResources.qrc index 3c2e3bdd4..883bcff82 100644 --- a/src/lay/layResources.qrc +++ b/src/lay/layResources.qrc @@ -113,8 +113,10 @@ images/upup.png images/waived.png images/yellow_flag.png + images/salt.png + images/salt_icon.png - + syntax/ruby.xml syntax/python.xml diff --git a/src/lay/laySalt.h b/src/lay/laySalt.h index 39d5c2f02..19d21145f 100644 --- a/src/lay/laySalt.h +++ b/src/lay/laySalt.h @@ -96,6 +96,14 @@ public: return m_root.end_collections (); } + /** + * @brief Returns a value indicating whether the collection is empty + */ + bool is_empty () const + { + return m_root.is_empty (); + } + /** * @brief A flat iterator of (sorted) grains (begin) */ diff --git a/src/lay/laySaltGrain.cc b/src/lay/laySaltGrain.cc index de0eccf6a..80292e6f1 100644 --- a/src/lay/laySaltGrain.cc +++ b/src/lay/laySaltGrain.cc @@ -41,12 +41,17 @@ bool SaltGrain::operator== (const SaltGrain &other) const { return m_name == other.m_name && - m_version == other.m_version && m_path == other.m_path && + m_version == other.m_version && m_url == other.m_url && m_title == other.m_title && m_doc == other.m_doc && - m_dependencies == other.m_dependencies; + m_dependencies == other.m_dependencies && + m_author == other.m_author && + m_author_contact == other.m_author_contact && + m_license == other.m_license && + m_authored_time == other.m_authored_time && + m_installed_time == other.m_installed_time; } void @@ -85,6 +90,36 @@ SaltGrain::set_doc (const std::string &t) m_doc = t; } +void +SaltGrain::set_author (const std::string &a) +{ + m_author = a; +} + +void +SaltGrain::set_author_contact (const std::string &a) +{ + m_author_contact = a; +} + +void +SaltGrain::set_license (const std::string &l) +{ + m_license = l; +} + +void +SaltGrain::set_authored_time (const QDateTime &t) +{ + m_authored_time = t; +} + +void +SaltGrain::set_installed_time (const QDateTime &t) +{ + m_installed_time = t; +} + int SaltGrain::compare_versions (const std::string &v1, const std::string &v2) { @@ -128,12 +163,38 @@ SaltGrain::compare_versions (const std::string &v1, const std::string &v2) } } +struct TimeConverter +{ + std::string to_string (const QDateTime &time) const + { + if (time.isNull ()) { + return std::string (); + } else { + return tl::to_string (time.toString (Qt::ISODate)); + } + } + + void from_string (const std::string &time, QDateTime &res) const + { + if (time.empty ()) { + res = QDateTime (); + } else { + res = QDateTime::fromString (tl::to_qstring (time), Qt::ISODate); + } + } +}; + static tl::XMLStruct xml_struct ("salt-grain", tl::make_member (&SaltGrain::name, &SaltGrain::set_name, "name") + tl::make_member (&SaltGrain::version, &SaltGrain::set_version, "version") + tl::make_member (&SaltGrain::title, &SaltGrain::set_title, "title") + tl::make_member (&SaltGrain::doc, &SaltGrain::set_doc, "doc") + tl::make_member (&SaltGrain::url, &SaltGrain::set_url, "url") + + tl::make_member (&SaltGrain::license, &SaltGrain::set_license, "license") + + tl::make_member (&SaltGrain::author, &SaltGrain::set_author, "author") + + tl::make_member (&SaltGrain::author_contact, &SaltGrain::set_author_contact, "author-contact") + + tl::make_member (&SaltGrain::authored_time, &SaltGrain::set_authored_time, "authored-time", TimeConverter ()) + + tl::make_member (&SaltGrain::installed_time, &SaltGrain::set_installed_time, "installed-time", TimeConverter ()) + tl::make_element (&SaltGrain::begin_dependencies, &SaltGrain::end_dependencies, &SaltGrain::add_dependency, "depends", tl::make_member (&SaltGrain::Dependency::name, "name") + tl::make_member (&SaltGrain::Dependency::url, "url") + diff --git a/src/lay/laySaltGrain.h b/src/lay/laySaltGrain.h index b86a0e0e7..063bade20 100644 --- a/src/lay/laySaltGrain.h +++ b/src/lay/laySaltGrain.h @@ -26,6 +26,8 @@ #include "layCommon.h" #include "tlObject.h" +#include + namespace lay { @@ -142,6 +144,71 @@ public: */ void set_version (const std::string &v); + /** + * @brief Gets the author of the grain + */ + const std::string &author () const + { + return m_author; + } + + /** + * @brief Sets the author of the grain + */ + void set_author (const std::string &a); + + /** + * @brief Gets the author's contact + */ + const std::string &author_contact () const + { + return m_author_contact; + } + + /** + * @brief Sets the author's contact + */ + void set_author_contact (const std::string &a); + + /** + * @brief Gets the license of the grain + */ + const std::string &license () const + { + return m_license; + } + + /** + * @brief Sets the license of the grain + */ + void set_license (const std::string &l); + + /** + * @brief Gets the release date and/or time of the grain + */ + const QDateTime &authored_time () const + { + return m_authored_time; + } + + /** + * @brief Sets the release date and/or time + */ + void set_authored_time (const QDateTime &t); + + /** + * @brief Gets the installation date and/or time of the grain + */ + const QDateTime &installed_time () const + { + return m_installed_time; + } + + /** + * @brief Sets the installation date and/or time + */ + void set_installed_time (const QDateTime &t); + /** * @brief Gets the absolute file path of the installed grain * This is the file path to the grain folder. @@ -261,6 +328,10 @@ private: std::string m_url; std::string m_title; std::string m_doc; + std::string m_author; + std::string m_author_contact; + std::string m_license; + QDateTime m_authored_time, m_installed_time; std::vector m_dependencies; }; diff --git a/src/lay/laySaltGrainDetailsTextWidget.cc b/src/lay/laySaltGrainDetailsTextWidget.cc new file mode 100644 index 000000000..ab44d6d22 --- /dev/null +++ b/src/lay/laySaltGrainDetailsTextWidget.cc @@ -0,0 +1,148 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "laySaltGrainDetailsTextWidget.h" +#include "laySaltGrain.h" +#include "tlString.h" + +#include +#include +#include + +namespace lay +{ + +SaltGrainDetailsTextWidget::SaltGrainDetailsTextWidget (QWidget *w) + : QTextBrowser (w), mp_grain (0) +{ + // .. nothing yet .. +} + +void SaltGrainDetailsTextWidget::set_grain (SaltGrain *g) +{ + if (mp_grain != g) { + mp_grain = g; + setHtml (details_text ()); + } +} + +QVariant +SaltGrainDetailsTextWidget::loadResource (int type, const QUrl &url) +{ + if (url.path () == QString::fromUtf8 ("/icon")) { + // @@@ + return QImage (":/salt_icon.png"); + // @@@ + } else { + return QTextBrowser::loadResource (type, url); + } +} + +QString +SaltGrainDetailsTextWidget::details_text () +{ + SaltGrain *g = mp_grain; + if (! g) { + return QString (); + } + + QBuffer buffer; + buffer.open (QIODevice::WriteOnly); + QTextStream stream (&buffer); + stream.setCodec ("UTF-8"); + + stream << ""; + + stream << ""; + stream << ""; + stream << "
"; + stream << "

"; + stream << tl::to_qstring (tl::escaped_to_html (g->name ())) << " " << tl::to_qstring (tl::escaped_to_html (g->version ())); + stream << "

"; + if (! g->title ().empty()) { + stream << "

" << tl::to_qstring (tl::escaped_to_html (g->title ())) << "

"; + } + + if (g->version ().empty ()) { + stream << "

"; + stream << QObject::tr ("This package does not have a version. " + "Use the <version> element of the specification file or edit the package properties to provide a version."); + stream << "

"; + } + + if (g->title ().empty ()) { + stream << "

"; + stream << QObject::tr ("This package does not have a title. " + "Use the <title> element of the specification file or edit the package properties to provide a title."); + stream << "

"; + } + + stream << "
"; + + stream << "


"; + if (! g->doc ().empty ()) { + stream << tl::to_qstring (tl::escaped_to_html (g->doc ())); + } else { + stream << ""; + stream << QObject::tr ("This package does not have a description. " + "Use the <doc> element of the specification file or edit the package properties to provide a description."); + stream << ""; + } + stream << "

"; + + stream << "

"; + if (! g->author ().empty ()) { + stream << "" << QObject::tr ("Author") << ": " << tl::to_qstring (tl::escaped_to_html (g->author ())) << " "; + if (! g->author_contact ().empty ()) { + stream << "(" << tl::to_qstring (tl::escaped_to_html (g->author_contact ())) << ")"; + } + if (!g->authored_time ().isNull ()) { + stream << "
"; + stream << "" << QObject::tr ("Released") << ": " << g->authored_time ().date ().toString (Qt::ISODate); + } + } else { + stream << ""; + stream << QObject::tr ("This package does not have a author information. " + "Use the <author>, <authored-time> and <author-contact> elements of the specification file or edit the package properties to provide authoring information."); + stream << ""; + } + stream << "

"; + + stream << "

"; + if (! g->url ().empty ()) { + stream << "" << QObject::tr ("Documentation link") << ": url ()) << "\">" << tl::to_qstring (tl::escaped_to_html (g->url ())) << ""; + } else { + stream << ""; + stream << QObject::tr ("This package does not have a documentation link. " + "Use the <url> element of the specification file or edit the package properties to provide a link."); + stream << ""; + } + stream << "

"; + + stream << ""; + + stream.flush (); + + return QString::fromUtf8 (buffer.buffer()); +} + +} diff --git a/src/lay/laySaltGrainDetailsTextWidget.h b/src/lay/laySaltGrainDetailsTextWidget.h new file mode 100644 index 000000000..bb25a0e48 --- /dev/null +++ b/src/lay/laySaltGrainDetailsTextWidget.h @@ -0,0 +1,61 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2017 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_laySaltGrainDetailsTextWidget +#define HDR_laySaltGrainDetailsTextWidget + +#include + +namespace lay +{ + +class SaltGrain; + +/** + * @brief A specialisation of QTextBrowser that displays the details of the salt grain + */ +class SaltGrainDetailsTextWidget + : public QTextBrowser +{ +public: + /** + * @brief Constructor + */ + SaltGrainDetailsTextWidget (QWidget *w); + + /** + * @brief Sets the grain whose details are to be shown + */ + void set_grain (SaltGrain *g); + +protected: + virtual QVariant loadResource (int type, const QUrl &url); + +private: + lay::SaltGrain *mp_grain; + + QString details_text (); +}; + +} + +#endif diff --git a/src/lay/laySaltGrains.cc b/src/lay/laySaltGrains.cc index a40bcea64..9c17944c6 100644 --- a/src/lay/laySaltGrains.cc +++ b/src/lay/laySaltGrains.cc @@ -112,7 +112,15 @@ SaltGrains::remove_grain (grain_iterator iter, bool with_files) bool SaltGrains::is_empty () const { - return m_collections.empty () && m_grains.empty (); + if (! m_grains.empty ()) { + return false; + } + for (collections_type::const_iterator i = m_collections.begin (); i != m_collections.end (); ++i) { + if (!i->is_empty ()) { + return false; + } + } + return true; } bool diff --git a/src/lay/laySaltManagerDialog.cc b/src/lay/laySaltManagerDialog.cc index 5876a1c7a..9606164f3 100644 --- a/src/lay/laySaltManagerDialog.cc +++ b/src/lay/laySaltManagerDialog.cc @@ -30,10 +30,17 @@ #include #include #include +#include +#include namespace lay { +// -------------------------------------------------------------------------------------- + +/** + * @brief A model representing the salt grains for a QListView + */ class SaltModel : public QAbstractItemModel { @@ -71,6 +78,12 @@ public: return tl::to_qstring (text); + } else if (role == Qt::DecorationRole) { + + // @@@ + return QIcon (":/salt_icon.png"); + // @@@ + } else { return QVariant (); } @@ -81,7 +94,7 @@ public: if (parent.isValid ()) { return QModelIndex (); } else { - return createIndex (row, column); + return createIndex (row, column, mp_salt->begin_flat () [row]); } } @@ -104,10 +117,29 @@ public: } } + SaltGrain *grain_from_index (const QModelIndex &index) const + { + if (index.isValid ()) { + return static_cast (index.internalPointer ()); + } else { + return 0; + } + } + + void update () + { + // @@@ + } + public: lay::Salt *mp_salt; }; +// -------------------------------------------------------------------------------------- + +/** + * @brief A delegate displaying the summary of a grain + */ class SaltItemDelegate : public QStyledItemDelegate { @@ -152,13 +184,22 @@ public: QStyleOptionViewItemV4 optionV4 = option; initStyleOption (&optionV4, index); + const QListView *view = dynamic_cast (optionV4.widget); + QSize icon_size (0, 0); + if (view) { + icon_size = view->iconSize (); + } + QTextDocument doc; doc.setHtml (optionV4.text); doc.setTextWidth (textWidth); - return QSize (textWidth, doc.size ().height ()); + return QSize (textWidth + icon_size.width () + 6, std::max (icon_size.height () + 12, int (doc.size ().height ()))); } }; +// -------------------------------------------------------------------------------------- +// SaltManager implementation + // @@@ lay::Salt salt; static bool salt_initialized = false; @@ -172,16 +213,76 @@ void make_salt () // @@@ SaltManagerDialog::SaltManagerDialog (QWidget *parent) - : QDialog (parent) + : QDialog (parent), + m_current_changed_enabled (true) { Ui::SaltManagerDialog::setupUi (this); - salt = lay::Salt (); salt_initialized = false; // @@@ - make_salt (); // @@@ - salt_view->setModel (new SaltModel (this, &salt)); +// @@@ + salt = lay::Salt (); salt_initialized = false; + make_salt (); + mp_salt = &salt; +// @@@ + + SaltModel *model = new SaltModel (this, mp_salt); + salt_view->setModel (model); salt_view->setItemDelegate (new SaltItemDelegate (this)); + connect (mp_salt, SIGNAL (collections_changed ()), this, SLOT (salt_changed ())); + + // select the first grain + if (model->rowCount (QModelIndex ()) > 0) { + salt_view->setCurrentIndex (model->index (0, 0, QModelIndex ())); + } + + salt_changed (); + + connect (salt_view->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_changed ())); + + // ... } +void +SaltManagerDialog::salt_changed () +{ + SaltModel *model = dynamic_cast (salt_view->model ()); + if (! model) { + return; + } + + m_current_changed_enabled = false; + model->update (); + m_current_changed_enabled = true; + + if (mp_salt->is_empty ()) { + list_stack->setCurrentIndex (1); + details_frame->hide (); + } else { + list_stack->setCurrentIndex (0); + details_frame->show (); + } + + current_changed (); +} + +void +SaltManagerDialog::current_changed () +{ + SaltModel *model = dynamic_cast (salt_view->model ()); + if (! model) { + return; + } + + SaltGrain *g = model->grain_from_index (salt_view->currentIndex ()); + details_text->set_grain (g); + if (!g) { + details_frame->setEnabled (false); + delete_button->setEnabled (false); + } else { + details_frame->setEnabled (true); + delete_button->setEnabled (true); + } +} + } diff --git a/src/lay/laySaltManagerDialog.h b/src/lay/laySaltManagerDialog.h index 42e59a993..24b55a62e 100644 --- a/src/lay/laySaltManagerDialog.h +++ b/src/lay/laySaltManagerDialog.h @@ -30,18 +30,37 @@ namespace lay { +class Salt; +class SaltGrain; + /** * @brief The dialog for managing the Salt ("Packages") */ class SaltManagerDialog : public QDialog, private Ui::SaltManagerDialog { +Q_OBJECT + public: /** * @brief Constructor */ SaltManagerDialog (QWidget *parent); +private slots: + /** + * @brief Called when the list of packages (grains) has changed + */ + void salt_changed (); + + /** + * @brief Called when the currently selected package (grain) has changed + */ + void current_changed (); + +private: + lay::Salt *mp_salt; + bool m_current_changed_enabled; }; } diff --git a/src/unit_tests/laySalt.cc b/src/unit_tests/laySalt.cc index 2d761ed62..75d7986ca 100644 --- a/src/unit_tests/laySalt.cc +++ b/src/unit_tests/laySalt.cc @@ -72,7 +72,20 @@ static std::string salt_to_string (lay::Salt &salt) TEST (1) { + std::string tmp0 = tmp_file ("tmp0"); + lay::SaltGrain g; + g.save (tmp0); + EXPECT_EQ (g.authored_time ().isNull (), true); + EXPECT_EQ (g.installed_time ().isNull (), true); + + lay::SaltGrain g0; + g0.load (tmp0); + EXPECT_EQ (g0.authored_time ().isNull (), true); + EXPECT_EQ (g0.installed_time ().isNull (), true); + EXPECT_EQ (g == g0, true); + + std::string tmp = tmp_file (); g.set_name ("abc"); EXPECT_EQ (g.name (), "abc"); @@ -86,6 +99,20 @@ TEST (1) EXPECT_EQ (g.title (), "title"); g.set_doc ("doc"); EXPECT_EQ (g.doc (), "doc"); + g.set_author ("me"); + EXPECT_EQ (g.author (), "me"); + g.set_author_contact ("ac"); + EXPECT_EQ (g.author_contact (), "ac"); + g.set_license ("free"); + EXPECT_EQ (g.license (), "free"); + g.set_authored_time (QDateTime ()); + EXPECT_EQ (g.authored_time ().isNull (), true); + g.set_authored_time (QDateTime::fromMSecsSinceEpoch (1000000000)); + EXPECT_EQ (QDateTime::fromMSecsSinceEpoch (0).msecsTo (g.authored_time ()), 1000000000); + g.set_installed_time (QDateTime ()); + EXPECT_EQ (g.installed_time ().isNull (), true); + g.set_installed_time (QDateTime::fromMSecsSinceEpoch (2000000000)); + EXPECT_EQ (QDateTime::fromMSecsSinceEpoch (0).msecsTo (g.installed_time ()), 2000000000); g.add_dependency (lay::SaltGrain::Dependency ()); g.dependencies ().back ().name = "depname"; @@ -105,8 +132,6 @@ TEST (1) gg.set_doc ("blabla"); EXPECT_EQ (g == gg, false); - std::string tmp = tmp_file (); - EXPECT_EQ (g == gg, false); g.save (tmp); @@ -269,11 +294,14 @@ TEST (4) // That's the main test part lay::Salt salt; + EXPECT_EQ (salt.is_empty (), true); + QSignalSpy spy (&salt, SIGNAL (collections_changed ())); EXPECT_EQ (salt_to_string (salt), "[]"); spy.clear (); salt.add_location (tl::to_string (tmp_dir.path ())); + EXPECT_EQ (salt.is_empty (), false); EXPECT_EQ (spy.count (), 1); EXPECT_EQ (salt_to_string (salt), "[a,b,c/c/v,c/u]");