diff --git a/core/include/DataSource/DataSourceItem.h b/core/include/DataSource/DataSourceItem.h index 4ff7629..950d3b8 100644 --- a/core/include/DataSource/DataSourceItem.h +++ b/core/include/DataSource/DataSourceItem.h @@ -11,7 +11,7 @@ class DataSourceItemAction; /** * Possible types of an item */ -enum class DataSourceItemType { NODE, PRODUCT }; +enum class DataSourceItemType { NODE, PRODUCT, COMPONENT }; /** * @brief The DataSourceItem class aims to represent a structure element of a data source. @@ -21,7 +21,11 @@ enum class DataSourceItemType { NODE, PRODUCT }; */ class DataSourceItem { public: - explicit DataSourceItem(DataSourceItemType type, QVector data = {}); + /// Key associated with the name of the item + static const QString NAME_DATA_KEY; + + explicit DataSourceItem(DataSourceItemType type, const QString &name); + explicit DataSourceItem(DataSourceItemType type, QHash data = {}); /// @return the actions of the item as a vector QVector actions() const noexcept; @@ -49,11 +53,16 @@ public: int childCount() const noexcept; /** - * Get the data associated to an index - * @param dataIndex the index to search - * @return the data found if index is valid, default QVariant otherwise + * Get the data associated to a key + * @param key the key to search + * @return the data found if key is valid, default QVariant otherwise */ - QVariant data(int dataIndex) const noexcept; + QVariant data(const QString &key) const noexcept; + + /// Gets all data + const QHash &data() const noexcept; + + bool isRoot() const noexcept; QString name() const noexcept; @@ -63,8 +72,20 @@ public: */ DataSourceItem *parentItem() const noexcept; + /** + * Sets or appends a value to a key + * @param key the key + * @param value the value + * @param append if true, the value is added to the values already existing for the key, + * otherwise it replaces the existing values + */ + void setData(const QString &key, const QVariant &value, bool append = false) noexcept; + DataSourceItemType type() const noexcept; + bool operator==(const DataSourceItem &other); + bool operator!=(const DataSourceItem &other); + private: class DataSourceItemPrivate; spimpl::unique_impl_ptr impl; diff --git a/core/src/DataSource/DataSourceItem.cpp b/core/src/DataSource/DataSourceItem.cpp index 16e0c53..81dc552 100644 --- a/core/src/DataSource/DataSourceItem.cpp +++ b/core/src/DataSource/DataSourceItem.cpp @@ -3,15 +3,10 @@ #include -namespace { - -/// Index of the 'name' value in the item -const auto NAME_INDEX = 0; - -} // namespace +const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); struct DataSourceItem::DataSourceItemPrivate { - explicit DataSourceItemPrivate(DataSourceItemType type, QVector data) + explicit DataSourceItemPrivate(DataSourceItemType type, QHash data) : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{} { } @@ -19,11 +14,16 @@ struct DataSourceItem::DataSourceItemPrivate { DataSourceItem *m_Parent; std::vector > m_Children; DataSourceItemType m_Type; - QVector m_Data; + QHash m_Data; std::vector > m_Actions; }; -DataSourceItem::DataSourceItem(DataSourceItemType type, QVector data) +DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name) + : DataSourceItem{type, QHash{{NAME_DATA_KEY, name}}} +{ +} + +DataSourceItem::DataSourceItem(DataSourceItemType type, QHash data) : impl{spimpl::make_unique_impl(type, std::move(data))} { } @@ -65,14 +65,24 @@ int DataSourceItem::childCount() const noexcept return impl->m_Children.size(); } -QVariant DataSourceItem::data(int dataIndex) const noexcept +QVariant DataSourceItem::data(const QString &key) const noexcept { - return impl->m_Data.value(dataIndex); + return impl->m_Data.value(key); +} + +const QHash &DataSourceItem::data() const noexcept +{ + return impl->m_Data; +} + +bool DataSourceItem::isRoot() const noexcept +{ + return impl->m_Parent == nullptr; } QString DataSourceItem::name() const noexcept { - return data(NAME_INDEX).toString(); + return data(NAME_DATA_KEY).toString(); } DataSourceItem *DataSourceItem::parentItem() const noexcept @@ -80,7 +90,51 @@ DataSourceItem *DataSourceItem::parentItem() const noexcept return impl->m_Parent; } +void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept +{ + auto it = impl->m_Data.constFind(key); + if (append && it != impl->m_Data.constEnd()) { + // Case of an existing value to which we want to add to the new value + if (it->canConvert()) { + auto variantList = it->value(); + variantList.append(value); + + impl->m_Data.insert(key, variantList); + } + else { + impl->m_Data.insert(key, QVariantList{*it, value}); + } + } + else { + // Other cases : + // - new value in map OR + // - replacement of an existing value (not appending) + impl->m_Data.insert(key, value); + } +} + DataSourceItemType DataSourceItem::type() const noexcept { return impl->m_Type; } + +bool DataSourceItem::operator==(const DataSourceItem &other) +{ + // Compares items' attributes + if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) { + // Compares contents of items' children + return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children), + std::cbegin(other.impl->m_Children), + [](const auto &itemChild, const auto &otherChild) { + return *itemChild == *otherChild; + }); + } + else { + return false; + } +} + +bool DataSourceItem::operator!=(const DataSourceItem &other) +{ + return !(*this == other); +} diff --git a/core/tests/DataSource/TestDataSourceController.cpp b/core/tests/DataSource/TestDataSourceController.cpp index 24429e2..3e58487 100644 --- a/core/tests/DataSource/TestDataSourceController.cpp +++ b/core/tests/DataSource/TestDataSourceController.cpp @@ -30,9 +30,7 @@ void TestDataSourceController::testSetDataSourceItem() // Create a data source item auto source1Name = QStringLiteral("Source1"); - auto source1Values = QVector{source1Name}; - auto source1Item - = std::make_unique(DataSourceItemType::PRODUCT, std::move(source1Values)); + auto source1Item = std::make_unique(DataSourceItemType::PRODUCT, source1Name); // Add data source item to the controller and check that a signal has been emitted after setting // data source item in the controller diff --git a/gui/resources/icones/dataSourceComponent.png b/gui/resources/icones/dataSourceComponent.png new file mode 100644 index 0000000000000000000000000000000000000000..38a2bfc5efe237b729acde561bbf5d965026ea99 GIT binary patch literal 2150 zc$@)d2$}bZP)FtBGx`My>H~)LLV_KB%=OUSHIjsI`1n7*!%1?=UQv;`AZgDxmjoJ`Hk^S3WY+UP$(1% zg+ifFC=?2XLZMJ76bgkxp->n)#*Rc`M3{|tVio>|!$;z;xD{{5tlCyrNXDu7D0cea zrXMdJ#)oi9Eh{Zl%IWwd9&zH0?~YygIOb+wbzxu@;Ir7P|BdgCe_;jA%$h-AQY^xk zvESeu-yQq#MLa%RHie#9g0JI%>NmbS4&bXeD@S65iCKp4VqE%-?~ZYN8%vXCS@=KB z!!7b}`my2=et>h5W?TRlVYT`<{dlno%adh4!n^=$)xW{L#vQmgNhL;zFffMT zu@&z)lKaRq8&_ky`ZuJmcnI$`VhZFOd_-@`+^EDzD3J4T4R)));7yI8R3I1NI-#o7 zUEsFF9-%P=4Hx1z^>0k-xE0T?rewp(xmcC z;YFf%?dU?T6SMy*jz3cHr5NY#bsT<;I4*Am(?r2G>#xxFN;fw@83l5^_yDI+=4P7Q6Y4G@pfyr7njz-h zw;JqGn{sZxqd@-Lu}>Gr@iXa^xkuyu!kBuH8f}p7!#OFI<3ZK^y*(^i$*vMFb}5*H z^Tm6}W#i*RQ-3=)@YLk95GLo_UqTfqRDhlu7oON5Toi|V{^7_j>8mr8b5c7 zw)1&;(i(^=jjB%+8#CoJAy32arBC*-IR3p>Go8CTT1BpL_}^%d*p$21Z=Wdk!VI~c zh$qQA4!>3yXEu`Dy?zITRJ=Gxa$P)COz0l!W4(jKYUxf#pKs@{}oO?$*OsqIYnGxWKX?4tG{)Rx zu~X;*r&d(6p=7SGOC2V+k?o=zDwVi3l*|zZ%58QVc~Ds4&#bsMBgHIXsoo~Hk^4lq z&-4WK7+I=nI!PIu@H%N)+zLmSCfdigsDHydu?{cOjBiyV!&Gq*Q+GFQ&iJJUD|4g5 zn7EqlPWd)|wa^9%J#w;mY+o<>>r+{tT`Zh8Qf>S#LJds8DdIrvX3@?*6fcmo@NO|t zb95nhNP9=lb5y55rdHmKfWTJGPh7%1Jke1L8CjQ z&%md|Mh^10{Wm@@ox#Fc_#FP&^?MJA#@1`3Q|78tKO1Kj{c?kEe0Ov#R-Tw}-Lu38 z?Qzonon0zT|HCe!Ue?N(w1W=^g~`&Bb0t(EgS>zA8r!pFGXd+QOYrDN^iA4fvvxjy zB7IE`i?6)3GauiVC*i}QxEEx}tUsP7hD&qQU>x7np!Wds`}#G-YW0QqwLCd@<{%o~ zG@9GjuMV^2DR>2bS79C##eOjf)v61+a{Kz-BfZ`FNqD`yvyj(`fz#H~>xoxY@dvy? zwHGc-$6IiJrW|&QGl@1#L-)))d2bf`6W(gDPUD&4JiclJjN`>lVR_fc)4r<6eY4n~ zg&_5)KGrx}G;t1U=hACz7Z!IT)ij#J*YD`qAq1+4TCz_QAI@B+liP%0RBei16Iz&N zhz825#j$K^_KQxQ_2Pdxp=F$nXG!B!*3JFGKBn_+sbDm27TY97&q~wi1PtTNV!g~I z7P=UQo5j}Ze=@mn3@+8Ko5gO|GCP;HaG_@3EVfe1?OfVIlWrCp$Bl-}&ZR9Z6UDFN zX0eg5b7>1pA#figELRC%-5BSM)wJ!=MqN*Ls3v5qoV>|BO` zer^^kb}mEAY@xob5+hd!#SFqWVPbiuV&_sQ6bgkxp-?Ck3WY+UP$(1%g+ifFC=?2X cLZRjS7af*m;0qX4nJ za0`PlBg3pY5)2H?BAzaeAr*7p-rbue5-8FB(OuZEN$SFigw$l^h)Tgpm#i;1y;m@Q zAUebE2)96v>W!sg8w8H@d#!PC?LDSo7%w)tLBj0j-OBSbjjQL$&-s>`_I&>Lxo6Lu zYf$l=go>OknPhxJ!drK-=`hZ7VmH^_FHg9?&4pLALY79 z>L;>hzT^M(|FxmP?4sqr)3g%bvOcIe^y~2sraLTt46k=*3*UHGFk9`K_^$um?|(iJf zd;yls0haC#PrF_)#4`gGy0RSLyC4e`c*8K&m|{JOTO}!cJg~-!&mRknx6MMzhJ5MQ#ihY(=-0R7!bgvn`l^=-qw; zhQBEcTHxPVk7@Z(y>{Knr0 jWM`!_qbJizDj&rSvfD~;Rqqi1W*P=hS3j3^P64nJ za0`PlBg3pY5a)cA zZ4hJ))H!m<%_ChjXsN#<%UY&D7Dt}IEdn}Q0*d!Fx<(v)uv_MYs^PKANh}Y$-n@Bt z#_so<&%X~8oPBrhPkP;*JLk^T^Shvelsqw>*KsWK*yb_hvFe%Tc=z!>NPZyjVP#?T zo!x9dIDQ;Y{3%_rvS#{`jSPGG|2pvLo}d11hKAhXx({A|)hhNB+;927_N_U5)gR6~ z!P}~zy_bH&zAoh_^N!6K{Jk%Pnyt1=Ux~at^?>yfYsqpQCIk2DjPIGO*GgZS$`o+U z_WP zh6kPr#-IPBSADyxV|s%>qmzMQ&y31{tPdv2)tY+qeq)Z(Vqjo5T3;x3)?vNo{j(9%CPKcxY}Q8|#8KyqBa7UY9(6k8uxcOxRXeU6F=Qb$EhsyVC=Tfh2 zPIs`)GXeVH`X;jv#_K0dYrg%;(r$yCxYQf=E&i3251!YVE$;h#U|ZwYlBA7^3l-na zKmApsU{k=|^$g$nEb4iG%rS|mwQ=~(bfNdaciZ*%XSU~ht9vfgeE8+S=kmaM-TEtr z7h@d?-=U zH;DW(_%O3nxhhI&Z+OL~_q?A38uTR!n_XDbXB04)u(CW?WKjLi+>zT46LQGnqs`-&5XMHECe84lt?l@VNeKkFLSO>6L<@!|2Eg*Ge;p8RI~ zHRH?YKMNriO#96!)_9ut_4;#%MG|((C(M-m|BGFo@j_ig7tmut6PX0&;6m+76HfnS z$i4Gk{DT0)YalD;z4!$Ypg4oi&%X?l|NpC(<_|tFEC0k_Yn;pc z>*`d|2ik9}Yqe6DZ&w4HTz*Y+EXIh*s2oG@#= k-^hK9R}ckEy!lgnZ_2fEkBpSB0?Qu;Pgg&ebxsLQ04T8ua{vGU literal 0 Hc$@Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5&!@T5&_cPe*6Fc02y>eSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E-^MlX|MGF01`z>L_t(|UhUlluxv*W2H=OgySsaEcXx*h z?yfaXP4-g9PpdRqSO-O;5> zmo8npbm`KiOP4NPx^(H%rOR04u)z_7qXx$ejuRX|I8kuY;N-z6gHr{k4o(xCb_@I- z_;Y{v6v4@YlLRLWju#v|IC^m8;P6406^o5NR$wE~5nMF5VsQQ7w!vP(!-FRV&kkM^ z>>s=_czf{P;Gp0`!AFCSP2eMe-+zDbuHY@fYlHoQ7X(ia_6hb5?i}1CxMpzK;DW)K z1Il)^;4nd#0pu9LnS#p%7W}?}&9$*M$cB9}_;&Ea;HSYagWm+d5B?bZCHPzLkKmud zzk+`U|Jee+2majO`+M-$;LpJyg5L$d3Vt5^IQV|>jo`Dv`vS_cZ$L@z9qbugGN7zS z3c5@ohYQXSIMI&`ULH8Pp9n0r#s6(kHr6KDu&tZ9Do_~8LcxlnP(F(IwSZ-LbHEzi zEx1H*f}mT72{}q|zTjTL0l_DOZv{@9MJ=ayJ2!e(6iec{SrOLgN5R2?E9jZQb%GNI zuCLmQ6ExjvKYPGYb9Xx#7G&Kv zdm5DMgO&S5@Ydj_fyhNfvo_*hXX>sRyfENAIq73E>8n6dhA#y73CX;AK^G$&ice8Tb;B5iVzV;Fwi$U^Bf{bs~oQPwE zcT%Rchwm5$Uk}tjnoA&^JCOS9&faptp;ix3ooq^O5J-2{9=c;V$QQgbP`YkPZWDB` zfBBF=`*?81pea$0SE;K#bjNU@0Fp$?h18NmieNl6zC48|TG=2dq7K$1q@JS=;7# zgP6V-33S*nQ?-ZhSPTk5PQSLbCPly89GaTtU;l1V;#zhF=%dUZi6_ zye2qnFbaYw4aILq5YYrtd!df$pke0j0Y2d9TFNwcYLe6^*RO=xz>m@Zd!As_jUxO4 zt=!KEG);E0=+5Dg=n2qq?BF;+Ytu-IGkD(M(ZL4;y>Xk~DB|5gi`-WOCtgN%tviT0 zF{tAxWVmgzTKet(6l{V*Fzv!Q>?tQ*?&Pk45Zd&S(Qdp4pXK2>ibk%SCBSmMXJGKd zrvt+t^x3aNN0ANZ2%By2&EVYu#b@HrA8?jMPP0gpN@6^USv#}74518K$#}ZBZdVEJ zAG|EkWFp1<-JrCPx2hBhH7uEKUoGz%J&l`rN^r}-C>isIWKB7C^K2w5VTgwHYD#D{ zb7pSNBHb$%h2yCC!OJ=!PRb2~2L>`>TB#|<=L6$mq(?3MDl(9iPr93h!h*)r|4d-E z(CdR|1bQM}ar*wPh0U_zizaX!vfBmE3r^=ZS`yBSdyVElHjokY@-}l(ljYxAJn(rs zkaW%Z85GZSk;eqj4UCmBuZNN_w;u@fE4W%H3~Tb`fYT*BwSoTY*M46!tGijrm6GvM z-Vqoyr9V%L`;&tQ2X_pNv$=S{`WX=A`O32{`rbZ+;y46X2q>3Gs(C(uQ)00x!qozc zvkC{t;u{lZw3`zm{JcP5Hjg%SSIad5<5{j3*gPlIf3F){JGgpqr9gG_!htxPpTcpa zc%qqQzlUp7Bp{<|IM&mGQfVC(Aw(~mljmeIT^9?Ch8cBYV~OIB7&k{r9}>JFFdS?0 zY8xFRh&9mX?nM+co*I}9WX2yYALa0a0mY`v@n0*rUmy}PD2u7DHQA1q5;o~PnF8j1 zHa<-ZYz`o^y(!ATS1GlOWnEEp$;b+}L< zR9g03yDAaUpl~tm4+vfwa4tEY9A{VMv=Pi&D8M8rgO_6NXg`JcTwsCB7LpI(uyMvD zj#vqbQLvpd`5eG&_k22crM+(y=;v1&7m3(#A#2(2U7hruVeJ&421)^CgxdFluLNFP zIL0d$Yx9tK_sppw&*Eeulkk(rPGJ;Om|U^AlgNwbgck6)Cx7kF{XKu*{Vb~RIX0Eg z;;O>PaiT>Srk`nyeOU1PK*-4P6;@JaSKg2*?q(IhB6!)_Lk|UuXfas|SwRIQi!8+| z>!!$LLW%iAtcNS*@xdbkNhIUf9hTec}(|EaCMlU+}wNscXa0hE+1+ktePvXDKW?HNrBT+d+?57 zpeQC=*<{GfF%r^sE3h26e&kMs$W4k+NXb*8XFKo7bwu(0o2vqD6-scnK-#x6f`&whmy4Lv{|#iE0IjOa`4JPh}C_A>A>9MCOAM!!phvE z6%VfjEKgw8Ek)qWbY(a+Y`P?uvHFh+q>@*`p;(znxw;lq{`3e)l}fa1^7Y^lNLa}v z%3?}y%kZuBSI;S!$hXVitBi3L(Xxz0cjuKN$+}qx@8i8#KhCj}&a0QM#)@{wkJ{8b z;q$zJjF#`$lc&c5#uJd&msWONNX5#2jm=VcUg=|24ka8RrhJVYmhg=O>D*aa)GULd zm4nojpfaI+p?1&vaH?>sTqF^UBwidAFt&_*eG3$Er#3@9nTx$MMO`P|n%l=Us2gWz3HYGF~se|W=gsFtOh)|;PHL-f)eI_#J9Rhqg zC1DoBiNYOVPA$9*U|!3YOxm1zoK7d0f=yN)RsV#wXyCrJ)b)i5jwviZkJ5GP0P(}~ zBBd%(OOr2pr@JDQzEvl^cayYm3*~g$5am>KX`bv*;^g=|b$OA6MUZrIvV@x=4I7}` zYctg7QLdQWX9f85`U>rCi7qx z3|1=NByQ8nH-|&{)^Oh#K1nKZ@_Y_r2<5ZEoLG1FvhHE;!RMB^*BHdmRsOTfHlNtv}Uf#+8WicHVQBarjFxCAvli~MyMss(vXP+!4tn(aH&99w59PW zoKQ}t>?Xy%RUlLqP1tNX0jY2PkkYQubl$|)S}MR+PzVcD2%czW;(AFSSwhzb$I|FD z;Tjh2%>!2nsx}2-IYb4EUMH-N2mlq_2CHRgCY7jSt%R0}T-w92p$-n@3p{TjlTz;8 znf7VXv;qiKY7adGD211&7{F|nRBOpU@GUI9w5t3ed%6=9H#6qWlk=hw{De z|9&mOf>LfnDVXq!!nvPaQ=Bu_Nyg6xdtX+ou!TLBXM|Z3Pt(F@H<<^J3DnzGd+1fb zg4a-##s=9aPG|uIDk#6_?>MoO8(RBZs6EHB;h8v%P13@hnC)7aO#x+Xk`^wWm;N2f z59p{vEkaG8$xvCy^NN5Otv!6lV&Lyctv6Q*oD_G{eu2BQ_7WZQ!Fnn!s}VFWiZ4Q> zSrQx_JBM|YS6H;fzEa^6D9>u`?$%&-aHe_u!ce&fS;f(bB#Ok0*jk9lgY{Ci7w$M@ z)17vAy*!3fuXfN%#&a(5@U8^eGsza&GVB^zvThj;*>p~`=t<+J1eB_vIf!GefmEd^ zf-0C!7g;x1I+j6heADs=l1)nFGK>cXj|;GkFq~#3ijGd?=&^86olvb*0i|o1J?YhT zvTtk!`d zn{i~r5oU#P_z(Dt3Rbdt)@_zM-rvQZZcbS^dsw?Tbn`eZGFuh{r;kFYp;HLmGKNd; zA83?R>}m1Ju-U8^lTLX#zH0vns>bCS25D_rKZ-xk8u>Sfu($=v&rJz7t}>-5A?|q_ zxk$Rw%lh{;os}?r!smKEYuZ_Z4@ciCmo((VJGpwg8lkeo`Ha8@y@Bu8C zFOMt}!_lROc4{nWu@q?8SjS>ze0)}eGMf6O+o(+YdP0CZfF7;{jQ))xUZ5n5z`;yo z;&RF;nf5hI9y~^5O;%1TmnImUyA;!Dl=oO5Z<3rTfys&xNK1o7@!26t*p zM9*c3lWx=bD*TZW?usC6`tDNYqgH@PPzEoc=cJ5BjVk$iw)<0i2Y0B zhbTfc!74fs)}gjWHLQ&S)IcdH1Zubik{Ogh5nA%XQNlTEoI1{(@Q|l0e_)|kCB@O? z7`nm`G^DvXj>0qHn)$<`4*d>=CCrf%a@I`yv{-8e*a{0}!Gx9;uk_%%I-DfMCE=zk zQKZB{Q7`Ezdx&kdF%AbX;3)SaNGtCnxExo+F(DQlDfMWIoZ>~ zyL+bQ5e zgcFZD$kZdGAkx_QRi?L>E+v01?J8w!NHUI}u_>+xiI+|B6}+cNNyzN98zaMK@|C%Z zQt3t^ltIX7ZXjL&ZXa&EbgQNj+&fCKE($@pSv*xw>0~Kt>1T8`G&VJeQQq-G2s3A% zkHQT?rKSlyHZ!cJ5&zl4=F0ioT_Aw`hFi;EJhie zsETJQHWn~~CxT{~x}}MPVu&tO37xRoMl2f?l42TOrC_A!q^RT`m#|SWq}0AijSqwh zH_9f@?Gn}jxzlyQN|edr!b?O`707!8OerQW0;SRN?+MC)C)2}~keOe~BAaI86nM%; zx@stq-)E{-75OGeDrGu2YlM!?bi1H*3f|h zj>u|r_Xun-N>|xnMH!~tM$3Kl&E6()eOP=70-P$aDL`pvLHT#(bIRxX8Gcs3ySsGh v(xpq6E?v5G>C&Z3mo8npbm=l0*|Foly1oncxkThT00000NkvXXu0mjfI$|V{ literal 0 Hc$@ + icones/dataSourceComponent.png + icones/dataSourceNode.png + icones/dataSourceProduct.png + icones/dataSourceRoot.png icones/delete.png icones/openInspector.png icones/next.png diff --git a/gui/src/DataSource/DataSourceTreeWidgetItem.cpp b/gui/src/DataSource/DataSourceTreeWidgetItem.cpp index 07b8735..22a3cde 100644 --- a/gui/src/DataSource/DataSourceTreeWidgetItem.cpp +++ b/gui/src/DataSource/DataSourceTreeWidgetItem.cpp @@ -2,23 +2,28 @@ #include #include -#include - #include Q_LOGGING_CATEGORY(LOG_DataSourceTreeWidgetItem, "DataSourceTreeWidgetItem") namespace { +// Column indexes +const auto NAME_COLUMN = 0; + QIcon itemIcon(const DataSourceItem *dataSource) { if (dataSource) { auto dataSourceType = dataSource->type(); switch (dataSourceType) { - case DataSourceItemType::NODE: - return sqpApp->style()->standardIcon(QStyle::SP_DirIcon); + case DataSourceItemType::NODE: { + return dataSource->isRoot() ? QIcon{":/icones/dataSourceRoot.png"} + : QIcon{":/icones/dataSourceNode.png"}; + } case DataSourceItemType::PRODUCT: - return sqpApp->style()->standardIcon(QStyle::SP_FileIcon); + return QIcon{":/icones/dataSourceProduct.png"}; + case DataSourceItemType::COMPONENT: + return QIcon{":/icones/dataSourceComponent.png"}; default: // No action break; @@ -28,7 +33,7 @@ QIcon itemIcon(const DataSourceItem *dataSource) << QObject::tr("Can't set data source icon : unknown data source type"); } else { - qCWarning(LOG_DataSourceTreeWidgetItem()) + qCCritical(LOG_DataSourceTreeWidgetItem()) << QObject::tr("Can't set data source icon : the data source is null"); } @@ -36,6 +41,54 @@ QIcon itemIcon(const DataSourceItem *dataSource) return QIcon{}; } +/// @return the tooltip text for a variant. The text depends on whether the data is a simple variant +/// or a list of variants +QString tooltipValue(const QVariant &variant) noexcept +{ + // If the variant is a list of variants, the text of the tooltip is of the form: {val1, val2, + // ...} + if (variant.canConvert()) { + auto valueString = QStringLiteral("{"); + + auto variantList = variant.value(); + for (auto it = variantList.cbegin(), end = variantList.cend(); it != end; ++it) { + valueString.append(it->toString()); + + if (std::distance(it, end) != 1) { + valueString.append(", "); + } + } + + valueString.append(QStringLiteral("}")); + + return valueString; + } + else { + return variant.toString(); + } +} + +QString itemTooltip(const DataSourceItem *dataSource) noexcept +{ + // The tooltip displays all item's data + if (dataSource) { + auto result = QString{}; + + const auto &data = dataSource->data(); + for (auto it = data.cbegin(), end = data.cend(); it != end; ++it) { + result.append(QString{"%1: %2
"}.arg(it.key(), tooltipValue(it.value()))); + } + + return result; + } + else { + qCCritical(LOG_DataSourceTreeWidgetItem()) + << QObject::tr("Can't set data source tooltip : the data source is null"); + + return QString{}; + } +} + } // namespace struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate { @@ -58,8 +111,9 @@ DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const Da : QTreeWidgetItem{parent, type}, impl{spimpl::make_unique_impl(data)} { - // Sets the icon depending on the data source + // Sets the icon and the tooltip depending on the data source setIcon(0, itemIcon(impl->m_Data)); + setToolTip(0, itemTooltip(impl->m_Data)); // Generates tree actions based on the item actions auto createTreeAction = [this, &parent](const auto &itemAction) { @@ -80,7 +134,23 @@ DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const Da QVariant DataSourceTreeWidgetItem::data(int column, int role) const { if (role == Qt::DisplayRole) { - return (impl->m_Data) ? impl->m_Data->data(column) : QVariant{}; + if (impl->m_Data) { + switch (column) { + case NAME_COLUMN: + return impl->m_Data->name(); + default: + // No action + break; + } + + qCWarning(LOG_DataSourceTreeWidgetItem()) + << QObject::tr("Can't get data (unknown column %1)").arg(column); + } + else { + qCCritical(LOG_DataSourceTreeWidgetItem()) << QObject::tr("Can't get data (null item)"); + } + + return QVariant{}; } else { return QTreeWidgetItem::data(column, role); diff --git a/plugins/mockplugin/src/MockPlugin.cpp b/plugins/mockplugin/src/MockPlugin.cpp index adc3bf6..f11ebbd 100644 --- a/plugins/mockplugin/src/MockPlugin.cpp +++ b/plugins/mockplugin/src/MockPlugin.cpp @@ -23,8 +23,7 @@ std::unique_ptr createDataProvider() noexcept std::unique_ptr createProductItem(const QString &productName, const QUuid &dataSourceUid) { - auto result = std::make_unique(DataSourceItemType::PRODUCT, - QVector{productName}); + auto result = std::make_unique(DataSourceItemType::PRODUCT, productName); // Add action to load product from DataSourceController result->addAction(std::make_unique( @@ -42,18 +41,17 @@ std::unique_ptr createProductItem(const QString &productName, std::unique_ptr createDataSourceItem(const QUuid &dataSourceUid) noexcept { // Magnetic field products - auto magneticFieldFolder = std::make_unique( - DataSourceItemType::NODE, QVector{QStringLiteral("Magnetic field")}); + auto magneticFieldFolder = std::make_unique(DataSourceItemType::NODE, + QStringLiteral("Magnetic field")); magneticFieldFolder->appendChild(createProductItem(QStringLiteral("FGM"), dataSourceUid)); magneticFieldFolder->appendChild(createProductItem(QStringLiteral("SC"), dataSourceUid)); // Electric field products - auto electricFieldFolder = std::make_unique( - DataSourceItemType::NODE, QVector{QStringLiteral("Electric field")}); + auto electricFieldFolder = std::make_unique(DataSourceItemType::NODE, + QStringLiteral("Electric field")); // Root - auto root = std::make_unique(DataSourceItemType::NODE, - QVector{DATA_SOURCE_NAME}); + auto root = std::make_unique(DataSourceItemType::NODE, DATA_SOURCE_NAME); root->appendChild(std::move(magneticFieldFolder)); root->appendChild(std::move(electricFieldFolder));