From 7b701435230758e5658c114e9bf1144c53074e55 Mon Sep 17 00:00:00 2001 From: Sebastien Fourey Date: Thu, 16 Sep 2021 18:18:12 +0200 Subject: [PATCH] Add a tag type, tag2filters map, and a tag selector menu --- CMakeLists.txt | 6 + gmic_qt.pro | 6 + gmic_qt.qrc | 2 + icons/color-wheel.png | Bin 0 -> 3652 bytes icons/color-wheel.svg | 42 +++++ icons/dark/color-wheel.png | Bin 0 -> 3652 bytes src/FilterSelector/FilterTagMap.cpp | 151 ++++++++++++++++++ src/FilterSelector/FilterTagMap.h | 49 ++++++ .../FiltersView/FilterTreeItemDelegate.cpp | 12 +- src/FilterSelector/FiltersView/TreeView.cpp | 2 +- src/Globals.h | 1 + src/MainWindow.cpp | 6 + src/MainWindow.h | 2 + src/ParametersCache.cpp | 2 +- src/Tags.cpp | 70 ++++++++ src/Tags.h | 59 +++++++ src/Widgets/VisibleTagSelector.cpp | 41 +++++ src/Widgets/VisibleTagSelector.h | 44 +++++ ui/mainwindow.ui | 15 +- 19 files changed, 505 insertions(+), 5 deletions(-) create mode 100644 icons/color-wheel.png create mode 100644 icons/color-wheel.svg create mode 100644 icons/dark/color-wheel.png create mode 100644 src/FilterSelector/FilterTagMap.cpp create mode 100644 src/FilterSelector/FilterTagMap.h create mode 100644 src/Tags.cpp create mode 100644 src/Tags.h create mode 100644 src/Widgets/VisibleTagSelector.cpp create mode 100644 src/Widgets/VisibleTagSelector.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 93119fa2..0f52ee3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,6 +332,7 @@ set (gmic_qt_SRCS src/FilterSelector/FiltersView/FiltersView.h src/FilterSelector/FiltersView/TreeView.h src/FilterSelector/FiltersVisibilityMap.h + src/FilterSelector/FilterTagMap.h src/CroppedImageListProxy.h src/CroppedActiveLayerProxy.h src/FilterSyncRunner.h @@ -354,6 +355,7 @@ set (gmic_qt_SRCS src/MainWindow.h src/ParametersCache.h src/TimeLogger.h + src/Tags.h src/Updater.h src/Utils.h src/Misc.h @@ -371,6 +373,7 @@ set (gmic_qt_SRCS src/Widgets/SearchFieldWidget.h src/Widgets/LanguageSelectionWidget.h src/Widgets/ProgressInfoWindow.h + src/Widgets/VisibleTagSelector.h src/ZoomConstraint.h ${GMIC_PATH}/gmic.h @@ -406,6 +409,7 @@ set (gmic_qt_SRCS src/FilterSelector/FiltersView/FiltersView.cpp src/FilterSelector/FiltersView/TreeView.cpp src/FilterSelector/FiltersVisibilityMap.cpp + src/FilterSelector/FilterTagMap.cpp src/CroppedImageListProxy.cpp src/CroppedActiveLayerProxy.cpp src/FilterSyncRunner.cpp @@ -427,6 +431,7 @@ set (gmic_qt_SRCS src/MainWindow.cpp src/ParametersCache.cpp src/TimeLogger.cpp + src/Tags.cpp src/Updater.cpp src/Utils.cpp src/Misc.cpp @@ -444,6 +449,7 @@ set (gmic_qt_SRCS src/Widgets/SearchFieldWidget.cpp src/Widgets/LanguageSelectionWidget.cpp src/Widgets/ProgressInfoWindow.cpp + src/Widgets/VisibleTagSelector.cpp ) set (gmic_qt_FORMS diff --git a/gmic_qt.pro b/gmic_qt.pro index 9a0d1ee5..d36d65ee 100644 --- a/gmic_qt.pro +++ b/gmic_qt.pro @@ -282,6 +282,7 @@ HEADERS += \ src/FilterSelector/FiltersView/FiltersView.h \ src/FilterSelector/FiltersView/TreeView.h \ src/FilterSelector/FiltersVisibilityMap.h \ + src/FilterSelector/FilterTagMap.h \ src/CroppedImageListProxy.h \ src/CroppedActiveLayerProxy.h \ src/FilterSyncRunner.h \ @@ -302,9 +303,11 @@ HEADERS += \ src/MainWindow.h \ src/Misc.h \ src/ParametersCache.h \ + src/Tags.h \ src/TimeLogger.h \ src/Updater.h \ src/Utils.h \ + src/Widgets/VisibleTagSelector.h \ src/ZoomConstraint.h \ src/FilterSelector/FiltersView/FilterTreeFolder.h \ src/FilterSelector/FiltersView/FilterTreeItem.h \ @@ -357,6 +360,7 @@ SOURCES += \ src/FilterSelector/FiltersView/FiltersView.cpp \ src/FilterSelector/FiltersView/TreeView.cpp \ src/FilterSelector/FiltersVisibilityMap.cpp \ + src/FilterSelector/FilterTagMap.cpp \ src/CroppedImageListProxy.cpp \ src/CroppedActiveLayerProxy.cpp \ src/FilterSyncRunner.cpp \ @@ -376,6 +380,7 @@ SOURCES += \ src/Logger.cpp \ src/MainWindow.cpp \ src/ParametersCache.cpp \ + src/Tags.cpp \ src/TimeLogger.cpp \ src/Updater.cpp \ src/Utils.cpp \ @@ -390,6 +395,7 @@ SOURCES += \ src/Widgets/PreviewWidget.cpp \ src/Widgets/ProgressInfoWidget.cpp \ src/Widgets/InOutPanel.cpp \ + src/Widgets/VisibleTagSelector.cpp \ src/Widgets/ZoomLevelSelector.cpp \ src/Widgets/SearchFieldWidget.cpp \ src/Widgets/LanguageSelectionWidget.cpp \ diff --git a/gmic_qt.qrc b/gmic_qt.qrc index 8cc2a899..1795db93 100644 --- a/gmic_qt.qrc +++ b/gmic_qt.qrc @@ -51,5 +51,7 @@ resources/gmic_hat.png resources/logos.png resources/transparency.png + icons/color-wheel.png + icons/dark/color-wheel.png diff --git a/icons/color-wheel.png b/icons/color-wheel.png new file mode 100644 index 0000000000000000000000000000000000000000..657caccda6ed78752f9bb1d98e539adb5ac2785c GIT binary patch literal 3652 zcmV-K4!iM*P)EX>4Tx04R}tkv&MmKpe$iQ$;P64t6NwkfAzR5Eao)t5AdrrB-Ow!Q|2}Xws0R zxHt-~1qVMCs}3&Cx;nTDg5U>;o12rOipV2qvfPq^eu;%vG+Q;bwkfE-UH^9Lm zFjA!Kb&q%VcJ}t~nO1*4i@kEO@Uk&`00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru^$LS^lf>EN)QTE0G9ediKErSb7@SsM=1w`p%Y+4`z(!tYhLx2FvBA`y& zATlGew4hx9(g7`&F+m_KfdC0vt5Q|JJAYI$l1f#js;J`hobmpb`n})p-TQs_-R1jU z;79rYEfVVqbT{#sq$2bKdLVQ|xe=iw%AOCCX;S4LluCtipcE)o;gGSP;?bjV|DOXu z*J7bNgD`jkzcSZXToKGut}e<%R7m>V!z1`G@D#jpUlsIgm>l_LCRbSlR#S9jyG49_H4Co+x; zGyv&WBx)%Z5ymtbTr+qL?~Gg-f~Um-0L^3oun%Dgt9b;Ne+47=qGctFF@)!v;y63> zBObq^0O%w#fh|A}?@w>DlSRP!D`0_It@G5``25wdk{eYD*2S78hXeJ9#76S2? zJh~1WSqQVQ!1B-BTuuSvqr1W5L)TJ_h8Ne2aEzxtg}|f$L$X-SXAr#z?MKQt9$}LR zg91G7J8T{Mv$I3D%Lv){6jmcV5oB0AHOxkt9>cvq<#;_Cg2zaHx}zrt25u!TdLEEM z9*_~j$dN3j2G|(``>l%)kN|WEVeD;|v-~wG0B9ytfUGdm)I99G=2?vBiOXcF%M*J- z^A_cvq3ih5WdWeiFc5eQO05e4&`%FZ*#5GF)Y<_Z)Je~+ue_ki{c2X2i}>2`d@1mF)*SpE55oT4D& zvRyFTNjw`C0Q=!~+aeke9s-U;Sh9}iV?G7W22suw#SHSia(x+_fPN7g@511v3e8^J zdqqyykO6SR?}0D&FXZXczc31T3$TY>WK}W)H@^)AlPN&}fa#|ktc}ojw$&yK>3X_8 zCqWvLN==u{3JHL3p^v~&Z%+NCqk=uQ0@~D_pdavlm@Dve3ONgW6TnMMAs_%HOG-#V zxi+jRg-UH|clW9KoKNbjhVN5lwx>1MM}M|>Znste5O~_>r$k`t(NFp7w*~BRxfll6 z!q^JA)bLsWA5jV50Zx-wUGdBaeHvVD!+7arL(b&Wt~XYT@O$98OA9q4&h<~Ldpu6+yOl7^ZUAWN!U@w`Y5$}p^YS@#dv@EAn@tg zhH0~0w4Vvw7i4&4qN9D6J(DIm{d&Mp;1|J+_bS)VWoL_R5ko7i4D)V_){35~6p`mA zj%bS@C^VMTkdMK?gi!39Y;rv?u%bSv&PDq#TQMG>qod7*Uj*9%zYb%&jXJlNt=|@K z*ipxDpd`rHBubc!C%87t0;UfDqRcEh&dOH0x<++%9(%GO=l!atftwH>4LMD!j=c2G zIG@$MFU&}rEbwO8Do&_{H&Vv~FdMku&)COU#|Scb61c(ZzrHcx*os5gG*JB^sJbnM zmG&9?Of2~#;RQ&q`1gQ=9;I%KEalS$H_L1VJX^MgF#*$N6|-

lT}30fm?9-Mkkd zx?9iLr#*byKJ#u9%Y2B)c!2JGmgjY80e}nci9*?Wm;C~pZ3Xl^y_Z3L;zM7S5eHZ= zdVmTp@3SpS4w446^+ETn-9G%GQw=%CobL9Y0KG0(Nt32De=#5}dTl!yXRUm`zkma- z2JQ#GzGU{_afYdYiD0VYKyaUR@P?Wmn#(H=SJU;+RoG{*t~Q5!jE2;Xhvu=S^z|15 zZY8?XR$=C$6_f+NNu5YOLN3saKl31&tN_#ihiUTe$ED0fun3r#@r7p`Gj_XGW&jQUV3}svDzfs(~0MlyoYDjeQk&fi7&n+ac5IHu;{PRRwC zK&(XcmKIw;pj(XT%z=*c?AX7M?$rkw%n{mPAs-t{4%N}A)-m|5(~UVtaCcY_(le%- zC^xmJ1Z^^iIm3PCk9dvTF{`tus&ePoDPufVjyh&l1Dc_sVzv(%`We zPr3^d2SVmvNMFB|n)+Nme8J(Ctm~T2)O4~o{MX%c>KfagFo%NvEylW3`pW`kK>rv_ zb^_#em{1L}6wh(m3%jU%MWInt&9=^}7tbVIH(x~OrG8NVq#BaFCo4JMZIK*e5}c*X zp9dU_@+=LWk~rfrm@ppX6R+`Qf8>Z&k#RsDExX&Fh-ii>V9J^6THcb79Sk zh|G+DjcTnDI_wXCZ=#6s2Dp6)OzaFP+d(dAvh?LT%v{ghB4Anoi$%>jz_d#~^0T-) z<3G~p)%3n)vwaxI`%%!P zl=4+@u@I3J`%>#05Hh`E4j*fK)8kG}{we@rdrsrz?cL8OIZeaJj<6&Aj?uT@=C2Y| zU-UzeCSVRcG7iQ+2bN`lQ>iX5r2K&&jQ4ne&oTEc-D;2BuPUnp%y+H0G%qc$aa^yZ zjbjmV0u@_9TD1*97$FJgIBPTX7y*;6hYlNnK0(ITeNNT80{`Az7ZJeHoFij;in}V$ z8$<*2GTJx!ynAE%yxP<*yX_-DH-=G(tPcXf`HwEmkpbioT=lOoaVHGf2s$S;i-k5?Ef>g(!PU+butETZ|Xvs*H%>vq?M^t`%V3H36X*6$`%P;K84kQMgCg3P(V z%YI(20wWj39EGIW&0RTo9q>nvXV%g5sh^%;-QL?9?OqU@t&=m}70#hdNHXTh<~h(KM;W7RO;A28N{AgjraT>EtG*|&+2p9nm6~s9w(c*a0;ZEF4c&Eeh zKvvI{&Ii@vdcNqzt3by9&Il%*T|({4G`~w2sU)SCC!SN4+z8%nG7NL<&Yc5l!v??u!d*LoSHhgM z{124x78n)9{_XLb?1y&{{$-8lzyA8(uY%KKtyYd{?|>ABp7zXF>u^T<#;7Eij@&rW z*TQ&bhSi#0&^kXDl9XkFd=$dKopU+bK1kZT9O-v+?SHpXmF*!^h-3Y&5cuC{RAps-ecQ1h8Z`hsAPllYZ3eI;z|>3L z=hQ=Cl&+CTr>^$HBZ0*Mp1)I6boUcBTWZK1VpzAug+VSMZ34(7pEk7SKRLGqB#Rh} zz{{Q8rwZ|&DR{*RjJI0TUjQ+~`JNG(5_cAOS)GgY@>?a;yh@liIU|&WWc!6Fz{Rb0 z1h~&?O)re(V@BjFk!FSXz98B2Il3G86<1Dvb#r~`0abY_F3#24YE6%rMmH|c9sAS^ zcfMuf{#KA&qRrk0pfp5Sov7x)qN4uGgB3X;ZmH(PtHTB1CR+{oY;;4$+YQ zYpfc04>9Mj`exkWD8`iNOEzm0+Mt7gUxGXkgg*!dfFkS{)$OLrmTE`MhR;f~9MRTQ zuEd7T<%1rI3{bekd-UBI_=zCfN_y2biOK^CX9P+GY>E~;M&Q(DJo- literal 0 HcmV?d00001 diff --git a/icons/color-wheel.svg b/icons/color-wheel.svg new file mode 100644 index 00000000..3a6d6ae9 --- /dev/null +++ b/icons/color-wheel.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + + + + + + + + + \ No newline at end of file diff --git a/icons/dark/color-wheel.png b/icons/dark/color-wheel.png new file mode 100644 index 0000000000000000000000000000000000000000..657caccda6ed78752f9bb1d98e539adb5ac2785c GIT binary patch literal 3652 zcmV-K4!iM*P)EX>4Tx04R}tkv&MmKpe$iQ$;P64t6NwkfAzR5Eao)t5AdrrB-Ow!Q|2}Xws0R zxHt-~1qVMCs}3&Cx;nTDg5U>;o12rOipV2qvfPq^eu;%vG+Q;bwkfE-UH^9Lm zFjA!Kb&q%VcJ}t~nO1*4i@kEO@Uk&`00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru^$LS^lf>EN)QTE0G9ediKErSb7@SsM=1w`p%Y+4`z(!tYhLx2FvBA`y& zATlGew4hx9(g7`&F+m_KfdC0vt5Q|JJAYI$l1f#js;J`hobmpb`n})p-TQs_-R1jU z;79rYEfVVqbT{#sq$2bKdLVQ|xe=iw%AOCCX;S4LluCtipcE)o;gGSP;?bjV|DOXu z*J7bNgD`jkzcSZXToKGut}e<%R7m>V!z1`G@D#jpUlsIgm>l_LCRbSlR#S9jyG49_H4Co+x; zGyv&WBx)%Z5ymtbTr+qL?~Gg-f~Um-0L^3oun%Dgt9b;Ne+47=qGctFF@)!v;y63> zBObq^0O%w#fh|A}?@w>DlSRP!D`0_It@G5``25wdk{eYD*2S78hXeJ9#76S2? zJh~1WSqQVQ!1B-BTuuSvqr1W5L)TJ_h8Ne2aEzxtg}|f$L$X-SXAr#z?MKQt9$}LR zg91G7J8T{Mv$I3D%Lv){6jmcV5oB0AHOxkt9>cvq<#;_Cg2zaHx}zrt25u!TdLEEM z9*_~j$dN3j2G|(``>l%)kN|WEVeD;|v-~wG0B9ytfUGdm)I99G=2?vBiOXcF%M*J- z^A_cvq3ih5WdWeiFc5eQO05e4&`%FZ*#5GF)Y<_Z)Je~+ue_ki{c2X2i}>2`d@1mF)*SpE55oT4D& zvRyFTNjw`C0Q=!~+aeke9s-U;Sh9}iV?G7W22suw#SHSia(x+_fPN7g@511v3e8^J zdqqyykO6SR?}0D&FXZXczc31T3$TY>WK}W)H@^)AlPN&}fa#|ktc}ojw$&yK>3X_8 zCqWvLN==u{3JHL3p^v~&Z%+NCqk=uQ0@~D_pdavlm@Dve3ONgW6TnMMAs_%HOG-#V zxi+jRg-UH|clW9KoKNbjhVN5lwx>1MM}M|>Znste5O~_>r$k`t(NFp7w*~BRxfll6 z!q^JA)bLsWA5jV50Zx-wUGdBaeHvVD!+7arL(b&Wt~XYT@O$98OA9q4&h<~Ldpu6+yOl7^ZUAWN!U@w`Y5$}p^YS@#dv@EAn@tg zhH0~0w4Vvw7i4&4qN9D6J(DIm{d&Mp;1|J+_bS)VWoL_R5ko7i4D)V_){35~6p`mA zj%bS@C^VMTkdMK?gi!39Y;rv?u%bSv&PDq#TQMG>qod7*Uj*9%zYb%&jXJlNt=|@K z*ipxDpd`rHBubc!C%87t0;UfDqRcEh&dOH0x<++%9(%GO=l!atftwH>4LMD!j=c2G zIG@$MFU&}rEbwO8Do&_{H&Vv~FdMku&)COU#|Scb61c(ZzrHcx*os5gG*JB^sJbnM zmG&9?Of2~#;RQ&q`1gQ=9;I%KEalS$H_L1VJX^MgF#*$N6|-

lT}30fm?9-Mkkd zx?9iLr#*byKJ#u9%Y2B)c!2JGmgjY80e}nci9*?Wm;C~pZ3Xl^y_Z3L;zM7S5eHZ= zdVmTp@3SpS4w446^+ETn-9G%GQw=%CobL9Y0KG0(Nt32De=#5}dTl!yXRUm`zkma- z2JQ#GzGU{_afYdYiD0VYKyaUR@P?Wmn#(H=SJU;+RoG{*t~Q5!jE2;Xhvu=S^z|15 zZY8?XR$=C$6_f+NNu5YOLN3saKl31&tN_#ihiUTe$ED0fun3r#@r7p`Gj_XGW&jQUV3}svDzfs(~0MlyoYDjeQk&fi7&n+ac5IHu;{PRRwC zK&(XcmKIw;pj(XT%z=*c?AX7M?$rkw%n{mPAs-t{4%N}A)-m|5(~UVtaCcY_(le%- zC^xmJ1Z^^iIm3PCk9dvTF{`tus&ePoDPufVjyh&l1Dc_sVzv(%`We zPr3^d2SVmvNMFB|n)+Nme8J(Ctm~T2)O4~o{MX%c>KfagFo%NvEylW3`pW`kK>rv_ zb^_#em{1L}6wh(m3%jU%MWInt&9=^}7tbVIH(x~OrG8NVq#BaFCo4JMZIK*e5}c*X zp9dU_@+=LWk~rfrm@ppX6R+`Qf8>Z&k#RsDExX&Fh-ii>V9J^6THcb79Sk zh|G+DjcTnDI_wXCZ=#6s2Dp6)OzaFP+d(dAvh?LT%v{ghB4Anoi$%>jz_d#~^0T-) z<3G~p)%3n)vwaxI`%%!P zl=4+@u@I3J`%>#05Hh`E4j*fK)8kG}{we@rdrsrz?cL8OIZeaJj<6&Aj?uT@=C2Y| zU-UzeCSVRcG7iQ+2bN`lQ>iX5r2K&&jQ4ne&oTEc-D;2BuPUnp%y+H0G%qc$aa^yZ zjbjmV0u@_9TD1*97$FJgIBPTX7y*;6hYlNnK0(ITeNNT80{`Az7ZJeHoFij;in}V$ z8$<*2GTJx!ynAE%yxP<*yX_-DH-=G(tPcXf`HwEmkpbioT=lOoaVHGf2s$S;i-k5?Ef>g(!PU+butETZ|Xvs*H%>vq?M^t`%V3H36X*6$`%P;K84kQMgCg3P(V z%YI(20wWj39EGIW&0RTo9q>nvXV%g5sh^%;-QL?9?OqU@t&=m}70#hdNHXTh<~h(KM;W7RO;A28N{AgjraT>EtG*|&+2p9nm6~s9w(c*a0;ZEF4c&Eeh zKvvI{&Ii@vdcNqzt3by9&Il%*T|({4G`~w2sU)SCC!SN4+z8%nG7NL<&Yc5l!v??u!d*LoSHhgM z{124x78n)9{_XLb?1y&{{$-8lzyA8(uY%KKtyYd{?|>ABp7zXF>u^T<#;7Eij@&rW z*TQ&bhSi#0&^kXDl9XkFd=$dKopU+bK1kZT9O-v+?SHpXmF*!^h-3Y&5cuC{RAps-ecQ1h8Z`hsAPllYZ3eI;z|>3L z=hQ=Cl&+CTr>^$HBZ0*Mp1)I6boUcBTWZK1VpzAug+VSMZ34(7pEk7SKRLGqB#Rh} zz{{Q8rwZ|&DR{*RjJI0TUjQ+~`JNG(5_cAOS)GgY@>?a;yh@liIU|&WWc!6Fz{Rb0 z1h~&?O)re(V@BjFk!FSXz98B2Il3G86<1Dvb#r~`0abY_F3#24YE6%rMmH|c9sAS^ zcfMuf{#KA&qRrk0pfp5Sov7x)qN4uGgB3X;ZmH(PtHTB1CR+{oY;;4$+YQ zYpfc04>9Mj`exkWD8`iNOEzm0+Mt7gUxGXkgg*!dfFkS{)$OLrmTE`MhR;f~9MRTQ zuEd7T<%1rI3{bekd-UBI_=zCfN_y2biOK^CX9P+GY>E~;M&Q(DJo- literal 0 HcmV?d00001 diff --git a/src/FilterSelector/FilterTagMap.cpp b/src/FilterSelector/FilterTagMap.cpp new file mode 100644 index 00000000..adf87ee0 --- /dev/null +++ b/src/FilterSelector/FilterTagMap.cpp @@ -0,0 +1,151 @@ +/** -*- mode: c++ ; c-basic-offset: 2 -*- + * + * @file FilterTagMap.h + * + * Copyright 2017 Sebastien Fourey + * + * This file is part of G'MIC-Qt, a generic plug-in for raster graphics + * editors, offering hundreds of filters thanks to the underlying G'MIC + * image processing framework. + * + * gmic_qt 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 3 of the License, or + * (at your option) any later version. + * + * gmic_qt 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 gmic_qt. If not, see . + * + */ +#include "FilterTagMap.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Common.h" +#include "Globals.h" +#include "GmicQt.h" +#include "Logger.h" +#include "Utils.h" + +namespace GmicQt +{ + +QSet FiltersTagMap::_colorToHashes[static_cast(TagColor::Count)]; + +TagColor FiltersTagMap::filterTag(const QString & hash) +{ + return TagColor::None; +} + +void FiltersTagMap::setColor(const QString & hash, TagColor color) +{ + for (QSet & hashSet : _colorToHashes) { + if (hashSet.remove(hash) && color == TagColor::None) { + return; + } + } + if (color != TagColor::None) { + _colorToHashes[static_cast(color)].insert(hash); + } +} + +void FiltersTagMap::load() +{ + for (QSet & hashes : _colorToHashes) { + hashes.clear(); + } + QString jsonFilename = QString("%1%2").arg(gmicConfigPath(true), FILTERS_TAGS_FILENAME); + QFile jsonFile(jsonFilename); + if (!jsonFile.exists()) { + return; + } + if (jsonFile.open(QFile::ReadOnly)) { +#ifdef _GMIC_QT_DEBUG_ + QJsonDocument jsonDoc; + QByteArray allFile = jsonFile.readAll(); + if (allFile.startsWith("{")) { + jsonDoc = QJsonDocument::fromJson(allFile); + } else { + jsonDoc = QJsonDocument::fromJson(qUncompress(allFile)); + } +#else + QJsonDocument jsonDoc = QJsonDocument::fromJson(qUncompress(jsonFile.readAll())); +#endif + if (jsonDoc.isNull()) { + Logger::warning(QString("Cannot parse ") + jsonFilename); + Logger::warning("Fiter tags are lost!"); + } else { + if (!jsonDoc.isObject()) { + Logger::error(QString("JSON file format is not correct (") + jsonFilename + ")"); + } else { + QJsonObject documentObject = jsonDoc.object(); + + for (int color = (int)TagColor::None + 1; color != (int)TagColor::Count; ++color) { + QJsonObject::const_iterator it = documentObject.find(TagColorNames[color]); + QSet & hashes = _colorToHashes[color]; + if (it != documentObject.constEnd()) { + QJsonArray array = it.value().toArray(); + for (const QJsonValueRef & value : array) { + hashes.insert(value.toString()); + } + } + } + } + } + } else { + Logger::error("Cannot open " + jsonFilename); + Logger::error("Parameters cannot be restored"); + } +} + +void FiltersTagMap::save() +{ + QJsonObject documentObject; + + for (int color = (int)TagColor::None + 1; color != (int)TagColor::Count; ++color) { + QJsonArray array; + const QSet & hashes = _colorToHashes[color]; + for (const QString & hash : hashes) { + array.push_back(QJsonValue(hash)); + } + documentObject.insert(TagColorNames[color], array); + } + + QJsonDocument jsonDoc(documentObject); + QString jsonFilename = QString("%1%2").arg(gmicConfigPath(true), FILTERS_TAGS_FILENAME); + QFile jsonFile(jsonFilename); + if (QFile::exists(jsonFilename)) { + QString bakFilename = QString("%1%2").arg(gmicConfigPath(false), FILTERS_TAGS_FILENAME ".bak"); + QFile::remove(bakFilename); + QFile::copy(jsonFilename, bakFilename); + } + + qint64 count = -1; + if (jsonFile.open(QFile::WriteOnly | QFile::Truncate)) { +#ifdef _GMIC_QT_DEBUG_ + count = jsonFile.write(jsonDoc.toJson()); +#else + count = jsonFile.write(qCompress(jsonDoc.toJson(QJsonDocument::Compact))); +#endif + jsonFile.close(); + } + + if (count == -1) { + Logger::error("Cannot write " + jsonFilename); + Logger::error("Parameters cannot be saved"); + } +} + +} // namespace GmicQt diff --git a/src/FilterSelector/FilterTagMap.h b/src/FilterSelector/FilterTagMap.h new file mode 100644 index 00000000..68e85776 --- /dev/null +++ b/src/FilterSelector/FilterTagMap.h @@ -0,0 +1,49 @@ +/** -*- mode: c++ ; c-basic-offset: 2 -*- + * + * @file FilterTagMap.h + * + * Copyright 2017 Sebastien Fourey + * + * This file is part of G'MIC-Qt, a generic plug-in for raster graphics + * editors, offering hundreds of filters thanks to the underlying G'MIC + * image processing framework. + * + * gmic_qt 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 3 of the License, or + * (at your option) any later version. + * + * gmic_qt 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 gmic_qt. If not, see . + * + */ +#ifndef GMIC_QT_FILTERTAGMAP_H +#define GMIC_QT_FILTERTAGMAP_H + +#include + +#include "Tags.h" + +namespace GmicQt +{ +class FiltersTagMap { +public: + static TagColor filterTag(const QString & hash); + static void setColor(const QString & hash, TagColor color); + static void load(); + static void save(); + +protected: +private: + static QSet _colorToHashes[static_cast(TagColor::Count)]; + FiltersTagMap() = delete; +}; + +} // namespace GmicQt + +#endif // GMIC_QT_FILTERTAGMAP_H diff --git a/src/FilterSelector/FiltersView/FilterTreeItemDelegate.cpp b/src/FilterSelector/FiltersView/FilterTreeItemDelegate.cpp index 6d67a9e5..b9657154 100644 --- a/src/FilterSelector/FiltersView/FilterTreeItemDelegate.cpp +++ b/src/FilterSelector/FiltersView/FilterTreeItemDelegate.cpp @@ -31,6 +31,7 @@ #include "DialogSettings.h" #include "FilterSelector/FiltersView/FilterTreeAbstractItem.h" #include "FilterSelector/FiltersView/FilterTreeItem.h" +#include "Tags.h" namespace GmicQt { @@ -49,13 +50,20 @@ void FilterTreeItemDelegate::paint(QPainter * painter, const QStyleOptionViewIte Q_ASSERT_X(item, "FiltersTreeItemDelegate::paint()", "No item"); auto filter = dynamic_cast(item); + const int width = 0.5 * options.rect.height(); + QString tag = TagAssets::markerHtml(TagColor::Green, width); + QTextDocument doc; if (!item->isCheckable() && filter && !filter->isVisible()) { QColor textColor; textColor = DialogSettings::UnselectedFilterTextColor; - doc.setHtml(QString("%2").arg(textColor.name()).arg(options.text)); + doc.setHtml(QString("%2 %3").arg(textColor.name()).arg(options.text).arg(tag)); } else { - doc.setHtml(options.text); + if (filter) { + doc.setHtml(options.text + " " + tag); + } else { + doc.setHtml(options.text); + } } options.text = ""; options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter); diff --git a/src/FilterSelector/FiltersView/TreeView.cpp b/src/FilterSelector/FiltersView/TreeView.cpp index b5bde1ce..5a230342 100644 --- a/src/FilterSelector/FiltersView/TreeView.cpp +++ b/src/FilterSelector/FiltersView/TreeView.cpp @@ -38,6 +38,6 @@ void TreeView::keyPressEvent(QKeyEvent * event) QTreeView::keyPressEvent(event); } -TreeView::~TreeView() = default; +TreeView::~TreeView() {} } // namespace GmicQt diff --git a/src/Globals.h b/src/Globals.h index 15e5375b..b2f823be 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -40,6 +40,7 @@ const char WarningPrefix = '!'; #define SLIDER_MIN_WIDTH 60 #define PARAMETERS_CACHE_FILENAME "gmic_qt_params.dat" #define FILTERS_VISIBILITY_FILENAME "gmic_qt_visibility.dat" +#define FILTERS_TAGS_FILENAME "gmic_qt_tags.dat" #define FAVE_FOLDER_TEXT "Faves" #define FAVES_IMPORT_KEY "Faves/ImportedGTK179" diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 0d899bb3..8d7e362a 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -58,6 +58,7 @@ #include "ParametersCache.h" #include "Updater.h" #include "Utils.h" +#include "Widgets/VisibleTagSelector.h" #include "ui_mainwindow.h" #include "gmic.h" @@ -225,6 +226,10 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent), ui(new Ui::MainW _lastPreviewKeypointBurstUpdateTime = 0; _isAccepted = false; + _visibleTagSelector = new VisibleTagSelector(this); + + connect(ui->tbTags, &QToolButton::clicked, this, [this]() { _visibleTagSelector->exec(ui->tbTags->mapToGlobal(ui->tbTags->rect().center())); }); + TIMING; makeConnections(); TIMING; @@ -245,6 +250,7 @@ MainWindow::~MainWindow() void MainWindow::setIcons() { + ui->tbTags->setIcon(LOAD_ICON("color-wheel")); ui->tbRenameFave->setIcon(LOAD_ICON("rename")); ui->pbSettings->setIcon(LOAD_ICON("package_settings")); ui->pbFullscreen->setIcon(LOAD_ICON("view-fullscreen")); diff --git a/src/MainWindow.h b/src/MainWindow.h index a7143dd0..a72f7627 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -56,6 +56,7 @@ class FiltersTreeFaveItem; class Updater; class FilterThread; class FiltersPresenter; +class VisibleTagSelector; class MainWindow : public QMainWindow { Q_OBJECT @@ -166,6 +167,7 @@ private slots: ulong _lastPreviewKeypointBurstUpdateTime; static bool _isAccepted; RunParameters _pluginParameters; + VisibleTagSelector * _visibleTagSelector; }; } // namespace GmicQt diff --git a/src/ParametersCache.cpp b/src/ParametersCache.cpp index 7d2d31fd..8c11c792 100644 --- a/src/ParametersCache.cpp +++ b/src/ParametersCache.cpp @@ -111,7 +111,7 @@ void ParametersCache::load(bool loadFiltersParameters) } } } else { - Logger::error("Cannot read " + jsonFilename); + Logger::error("Cannot open " + jsonFilename); Logger::error("Parameters cannot be restored"); } } diff --git a/src/Tags.cpp b/src/Tags.cpp new file mode 100644 index 00000000..9ac12deb --- /dev/null +++ b/src/Tags.cpp @@ -0,0 +1,70 @@ +/** -*- mode: c++ ; c-basic-offset: 2 -*- + * + * @file Tags.cpp + * + * Copyright 2017 Sebastien Fourey + * + * This file is part of G'MIC-Qt, a generic plug-in for raster graphics + * editors, offering hundreds of filters thanks to the underlying G'MIC + * image processing framework. + * + * gmic_qt 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 3 of the License, or + * (at your option) any later version. + * + * gmic_qt 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 gmic_qt. If not, see . + * + */ +#include "Tags.h" +#include "Common.h" + +#include +#include +#include +#include +#include + +namespace GmicQt +{ + +const char * TagColorNames[] = {"", "Red", "Green", "Blue"}; + +QString TagAssets::_markerHtml[static_cast(TagColor::Count)]; +unsigned int TagAssets::_markerSideSize[static_cast(TagColor::Count)]; +QColor TagAssets::_colors[static_cast(TagColor::Count)] = {QColor(0, 0, 0, 0), Qt::red, Qt::green, Qt::blue}; + +const QString & TagAssets::markerHtml(const TagColor color, unsigned int sideSize) +{ + const int iColor = (int)color; + if (!_markerHtml[iColor].isEmpty() && _markerSideSize[iColor] == sideSize) { + return _markerHtml[iColor]; + } + QImage image(sideSize, sideSize, QImage::Format_RGBA8888); + image.fill(QColor(0, 0, 0, 0)); + if (color != TagColor::None) { + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing, true); + QPen pen = painter.pen(); + pen.setWidth(2); + pen.setColor(Qt::black); + painter.setPen(pen); + const int innerRadius = sideSize * 0.4; + painter.setBrush(_colors[iColor]); + painter.drawEllipse(image.rect().center(), innerRadius, innerRadius); + } + QByteArray ba; + QBuffer buffer(&ba); + image.save(&buffer, "png"); + _markerSideSize[iColor] = sideSize; + _markerHtml[iColor] = QString("").arg(QString(ba.toBase64())); + return _markerHtml[iColor]; +} + +} // namespace GmicQt diff --git a/src/Tags.h b/src/Tags.h new file mode 100644 index 00000000..6cf5e915 --- /dev/null +++ b/src/Tags.h @@ -0,0 +1,59 @@ +/** -*- mode: c++ ; c-basic-offset: 2 -*- + * + * @file Tags.h + * + * Copyright 2017 Sebastien Fourey + * + * This file is part of G'MIC-Qt, a generic plug-in for raster graphics + * editors, offering hundreds of filters thanks to the underlying G'MIC + * image processing framework. + * + * gmic_qt 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 3 of the License, or + * (at your option) any later version. + * + * gmic_qt 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 gmic_qt. If not, see . + * + */ +#ifndef GMIC_QT_TAGS_H +#define GMIC_QT_TAGS_H + +#include +#include +#include +#include + +namespace GmicQt +{ + +enum class TagColor +{ + None, + Red, + Green, + Blue, + Count +}; + +extern const char * TagColorNames[]; + +class TagAssets { +public: + static const QString & markerHtml(TagColor color, unsigned int sideSize); + +private: + static QString _markerHtml[static_cast(TagColor::Count)]; + static unsigned int _markerSideSize[static_cast(TagColor::Count)]; + static QColor _colors[static_cast(TagColor::Count)]; +}; + +} // namespace GmicQt + +#endif // GMIC_QT_TAGS_H diff --git a/src/Widgets/VisibleTagSelector.cpp b/src/Widgets/VisibleTagSelector.cpp new file mode 100644 index 00000000..b43f213f --- /dev/null +++ b/src/Widgets/VisibleTagSelector.cpp @@ -0,0 +1,41 @@ +/** -*- mode: c++ ; c-basic-offset: 2 -*- + * + * @file VisibleTagSelector.cpp + * + * Copyright 2017 Sebastien Fourey + * + * This file is part of G'MIC-Qt, a generic plug-in for raster graphics + * editors, offering hundreds of filters thanks to the underlying G'MIC + * image processing framework. + * + * gmic_qt 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 3 of the License, or + * (at your option) any later version. + * + * gmic_qt 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 gmic_qt. If not, see . + * + */ +#include "Widgets/VisibleTagSelector.h" + +#include "Tags.h" + +namespace GmicQt +{ + +VisibleTagSelector::VisibleTagSelector(QWidget * parent) : QMenu(parent) +{ + for (int color = 1 + (int)TagColor::None; color != (int)TagColor::Count; ++color) { + addAction(tr("Show only %1 tags").arg(QString::fromUtf8(TagColorNames[color]))); + } +} + +VisibleTagSelector::~VisibleTagSelector() {} + +} // namespace GmicQt diff --git a/src/Widgets/VisibleTagSelector.h b/src/Widgets/VisibleTagSelector.h new file mode 100644 index 00000000..ae352a55 --- /dev/null +++ b/src/Widgets/VisibleTagSelector.h @@ -0,0 +1,44 @@ +/** -*- mode: c++ ; c-basic-offset: 2 -*- + * + * @file VisibleTagSelector.h + * + * Copyright 2017 Sebastien Fourey + * + * This file is part of G'MIC-Qt, a generic plug-in for raster graphics + * editors, offering hundreds of filters thanks to the underlying G'MIC + * image processing framework. + * + * gmic_qt 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 3 of the License, or + * (at your option) any later version. + * + * gmic_qt 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 gmic_qt. If not, see . + * + */ +#ifndef GMIC_QT_VISIBLETAGSELECTOR_H +#define GMIC_QT_VISIBLETAGSELECTOR_H + +#include +#include "VisibleTagSelector.h" + +namespace GmicQt +{ + +class VisibleTagSelector : public QMenu { + Q_OBJECT + +public: + explicit VisibleTagSelector(QWidget * parent = nullptr); + ~VisibleTagSelector() override; +}; + +} // namespace GmicQt + +#endif // GMIC_QT_VISIBLETAGSELECTOR_H diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index b8839696..d234a089 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -114,6 +114,17 @@ + + + + + + + + :/icons/color-wheel.png:/icons/color-wheel.png + + + @@ -610,6 +621,8 @@ pbApply pbOk - + + +