1 /** -*- mode: c++ ; c-basic-offset: 2 -*-
2 *
3 * @file Tags.cpp
4 *
5 * Copyright 2017 Sebastien Fourey
6 *
7 * This file is part of G'MIC-Qt, a generic plug-in for raster graphics
8 * editors, offering hundreds of filters thanks to the underlying G'MIC
9 * image processing framework.
10 *
11 * gmic_qt is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * gmic_qt is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with gmic_qt. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25 #include "Tags.h"
26 #include <QAction>
27 #include <QBuffer>
28 #include <QByteArray>
29 #include <QDebug>
30 #include <QIcon>
31 #include <QImage>
32 #include <QObject>
33 #include <QPainter>
34 #include <QPixmap>
35 #include <QStringList>
36 #include "Common.h"
37 #include "DialogSettings.h"
38
39 namespace GmicQt
40 {
41
42 const TagColorSet TagColorSet::Full(TagColorSet::_fullMask);
43 const TagColorSet TagColorSet::ActualColors(TagColorSet::_fullMask &(~1u));
44 const TagColorSet TagColorSet::Empty(0);
45
46 QString TagAssets::_markerHtml[static_cast<unsigned int>(TagColor::Count)];
47 QIcon TagAssets::_menuIcons[static_cast<unsigned int>(TagColor::Count)];
48 QIcon TagAssets::_menuIconsWithCheck[static_cast<unsigned int>(TagColor::Count)];
49 QIcon TagAssets::_menuIconsWithDisk[static_cast<unsigned int>(TagColor::Count)];
50 unsigned int TagAssets::_markerSideSize[static_cast<unsigned int>(TagColor::Count)];
51 QColor TagAssets::colors[static_cast<unsigned int>(TagColor::Count)] = {QColor(0, 0, 0, 0), QColor(250, 68, 113), QColor(179, 228, 59), QColor(121, 171, 255),
52 QColor(117, 225, 242), QColor(188, 154, 234), QColor(236, 224, 105)};
53
markerHtml(const TagColor color,unsigned int height)54 const QString & TagAssets::markerHtml(const TagColor color, unsigned int height)
55 {
56 if (!(height % 2)) {
57 ++height;
58 }
59 const int iColor = (int)color;
60 if (!_markerHtml[iColor].isEmpty() && _markerSideSize[iColor] == height) {
61 return _markerHtml[iColor];
62 }
63 QImage image(height, height, QImage::Format_RGBA8888);
64 image.fill(QColor(0, 0, 0, 0));
65 if (color != TagColor::None) {
66 QPainter painter(&image);
67 painter.setRenderHint(QPainter::Antialiasing, true);
68 QPen pen = painter.pen();
69 pen.setWidth(1);
70 pen.setColor(QColor(0, 0, 0, 128));
71 painter.setPen(pen);
72 painter.setBrush(colors[iColor]);
73 painter.drawEllipse(1, 1, height - 2, height - 2);
74 }
75 QByteArray ba;
76 QBuffer buffer(&ba);
77 image.save(&buffer, "png");
78 _markerSideSize[iColor] = height;
79 _markerHtml[iColor] = QString("<img style=\"vertical-align: baseline\" src=\"data:image/png;base64,%1\"/>").arg(QString(ba.toBase64()));
80 return _markerHtml[iColor];
81 }
82
menuIcon(TagColor color,IconMark mark)83 const QIcon & TagAssets::menuIcon(TagColor color, IconMark mark)
84 {
85 const int iColor = (int)color;
86 if (_menuIcons[iColor].isNull()) {
87 QPixmap bg(64, 64);
88 QFont font;
89 font.setPixelSize(60);
90 {
91 bg.fill(QColor(0, 0, 0, 0));
92 QPainter p(&bg);
93 p.setRenderHint(QPainter::Antialiasing, true);
94 if (color == TagColor::None) {
95 QPen pen;
96 pen.setWidth(3);
97 if (DialogSettings::darkThemeEnabled()) {
98 pen.setColor(QColor(40, 40, 40));
99 p.setBrush(DialogSettings::CheckBoxBaseColor);
100 } else {
101 QPalette palette;
102 pen.setColor(palette.text().color());
103 p.setBrush(palette.window().color());
104 }
105 p.setPen(pen);
106 p.drawEllipse(bg.rect().adjusted(2, 2, -2, -2));
107 } else {
108 p.setBrush(colors[iColor]);
109 p.drawRoundedRect(bg.rect(), 15, 15);
110 }
111 _menuIcons[iColor] = QIcon(bg);
112 }
113 QColor markColor = Qt::black;
114 if (color == TagColor::None) {
115 markColor = DialogSettings::darkThemeEnabled() ? QColor(170, 170, 170) : QPalette().text().color();
116 }
117 QPixmap pixmap(bg);
118 {
119 QPainter p(&pixmap);
120 p.setFont(font);
121 p.setPen(markColor);
122 p.setRenderHint(QPainter::Antialiasing, true);
123 p.drawText(pixmap.rect(), Qt::AlignCenter | Qt::AlignVCenter, "\xE2\x9C\x93"); // CHECK MARK
124 _menuIconsWithCheck[iColor] = QIcon(pixmap);
125 }
126 pixmap = bg;
127 {
128 QPainter p(&pixmap);
129 p.setFont(font);
130 p.setPen(markColor);
131 p.setRenderHint(QPainter::Antialiasing, true);
132 p.drawText(pixmap.rect(), Qt::AlignCenter | Qt::AlignVCenter, "\xE2\x9A\xAB"); // MEDIUM BLACK CIRCLE
133 _menuIconsWithDisk[iColor] = QIcon(pixmap);
134 }
135 }
136 switch (mark) {
137 case IconMark::Check:
138 return _menuIconsWithCheck[iColor];
139 case IconMark::Disk:
140 return _menuIconsWithDisk[iColor];
141 default:
142 return _menuIcons[iColor];
143 }
144 }
145
action(QObject * parent,TagColor color,IconMark mark)146 QAction * TagAssets::action(QObject * parent, TagColor color, IconMark mark)
147 {
148 if ((color == TagColor::None) || (color == TagColor::Count)) {
149 return nullptr;
150 }
151 return new QAction(menuIcon(color, mark), QObject::tr("%1 Tag").arg(colorName(color)), parent);
152 }
153
colorName(TagColor color)154 QString TagAssets::colorName(TagColor color)
155 {
156 Q_ASSERT_X(((unsigned int)color < (unsigned int)TagColor::Count), __PRETTY_FUNCTION__, "Invalid color");
157 static QStringList names = {QObject::tr("None"), //
158 QObject::tr("Red"), //
159 QObject::tr("Green"), //
160 QObject::tr("Blue"), //
161 QObject::tr("Cyan"), //
162 QObject::tr("Magenta"), //
163 QObject::tr("Yellow")};
164 return names.at(int(color));
165 }
166
operator <<(std::ostream & out,const TagColorSet & colors)167 std::ostream & operator<<(std::ostream & out, const TagColorSet & colors)
168 {
169 out << "{";
170 bool first = true;
171 for (TagColor color : colors) {
172 if (first) {
173 first = false;
174 } else {
175 out << ",";
176 }
177 out << TagAssets::colorName(color).toStdString();
178 }
179 out << "}";
180 return out;
181 }
182
183 } // namespace GmicQt
184