1 /** -*- mode: c++ ; c-basic-offset: 2 -*-
2 *
3 * @file Tags.h
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 #ifndef GMIC_QT_TAGS_H
26 #define GMIC_QT_TAGS_H
27
28 #include <QColor>
29 #include <QDebug>
30 #include <QIcon>
31 #include <QString>
32 #include <QVector>
33 #include "Common.h"
34 class QAction;
35 class QObject;
36
37 namespace GmicQt
38 {
39
40 enum class TagColor
41 {
42 None = 0,
43 Red,
44 Green,
45 Blue,
46 Cyan,
47 Magenta,
48 Yellow,
49 Count
50 };
51
52 class TagAssets {
53 public:
54 enum class IconMark
55 {
56 None,
57 Check,
58 Disk
59 };
60 static const QString & markerHtml(TagColor color, unsigned int sideSize);
61 static const QIcon & menuIcon(TagColor color, IconMark mark);
62 static QAction * action(QObject * parent, TagColor color, IconMark mark);
63 static QColor colors[static_cast<unsigned int>(TagColor::Count)];
64 static QString colorName(TagColor color);
65
66 private:
67 static QString _markerHtml[static_cast<unsigned int>(TagColor::Count)];
68 static QIcon _menuIcons[static_cast<unsigned int>(TagColor::Count)];
69 static QIcon _menuIconsWithCheck[static_cast<unsigned int>(TagColor::Count)];
70 static QIcon _menuIconsWithDisk[static_cast<unsigned int>(TagColor::Count)];
71 static unsigned int _markerSideSize[static_cast<unsigned int>(TagColor::Count)];
72 };
73
74 class TagColorSet {
75 public:
76 inline void toggle(TagColor color);
77 inline void insert(TagColor color);
78 inline bool contains(TagColor color) const;
79 inline bool isEmpty() const;
80 inline void clear();
81 inline bool operator==(const TagColorSet & other) const;
82 inline bool operator!=(const TagColorSet & other) const;
83 inline TagColorSet operator+(TagColor color) const;
84 inline TagColorSet & operator+=(TagColor color);
85 inline TagColorSet & operator-=(TagColor color);
86 inline TagColorSet operator-(TagColor color) const;
87 inline TagColorSet operator|(const TagColorSet & other) const;
88 inline TagColorSet & operator|=(const TagColorSet & other);
89 inline TagColorSet operator&(const TagColorSet & other) const;
90 inline TagColorSet & operator&=(const TagColorSet & other);
91 inline unsigned int mask() const;
92 static const TagColorSet Full;
93 static const TagColorSet ActualColors;
94 static const TagColorSet Empty;
95 friend class const_iterator;
96 class const_iterator {
97 public:
98 inline const_iterator(const TagColorSet & set);
99 inline bool isAtEnd() const;
100 inline const_iterator & operator++();
101 inline const_iterator operator++(int);
102 inline TagColor operator*() const;
103 inline bool operator!=(const const_iterator & other) const;
104 inline bool operator==(const const_iterator & other) const;
105
106 private:
107 int _position;
108 const TagColorSet & _set;
109 };
110 inline const_iterator begin() const;
111 inline const_iterator end() const;
112
TagColorSet()113 TagColorSet() : _mask(0u) {}
TagColorSet(const TagColorSet & other)114 TagColorSet(const TagColorSet & other) : _mask(other._mask) {}
115 TagColorSet & operator=(const TagColorSet & other);
116 inline explicit TagColorSet(unsigned int mask);
117
118 private:
119 unsigned int _mask;
120 static const unsigned int _fullMask = ((1 << int(TagColor::Count)) - 1);
121 };
122
123 std::ostream & operator<<(std::ostream & out, const TagColorSet & colors);
124
TagColorSet(unsigned int mask)125 TagColorSet::TagColorSet(unsigned int mask) : _mask(mask & _fullMask) {}
126
toggle(TagColor color)127 inline void TagColorSet::toggle(TagColor color)
128 {
129 Q_ASSERT_X((color != TagColor::Count), __PRETTY_FUNCTION__, QString("Inavild color (%1)").arg(int(color)).toLocal8Bit().constData());
130 _mask ^= (1u << int(color));
131 }
132
insert(TagColor color)133 void TagColorSet::insert(TagColor color)
134 {
135 Q_ASSERT_X((color != TagColor::Count), __PRETTY_FUNCTION__, QString("Inavild color (%1)").arg(int(color)).toLocal8Bit().constData());
136 _mask |= (1u << int(color));
137 }
138
contains(TagColor color)139 bool TagColorSet::contains(TagColor color) const
140 {
141 Q_ASSERT_X((color != TagColor::Count), __PRETTY_FUNCTION__, QString("Inavild color (%1)").arg(int(color)).toLocal8Bit().constData());
142 return _mask & (1u << int(color));
143 }
144
isEmpty()145 bool TagColorSet::isEmpty() const
146 {
147 return !_mask;
148 }
149
clear()150 void TagColorSet::clear()
151 {
152 _mask = 0;
153 }
154
155 bool TagColorSet::operator==(const TagColorSet & other) const
156 {
157 return _mask == other._mask;
158 }
159
160 bool TagColorSet::operator!=(const TagColorSet & other) const
161 {
162 return _mask != other._mask;
163 }
164
165 TagColorSet & TagColorSet::operator+=(TagColor color)
166 {
167 insert(color);
168 return *this;
169 }
170
171 TagColorSet TagColorSet::operator+(TagColor color) const
172 {
173 TagColorSet result(*this);
174 result.insert(color);
175 return result;
176 }
177
178 TagColorSet & TagColorSet::operator-=(TagColor color)
179 {
180 _mask &= ~(1u << int(color));
181 return *this;
182 }
183
184 TagColorSet TagColorSet::operator-(TagColor color) const
185 {
186 TagColorSet result(*this);
187 result -= color;
188 return result;
189 }
190
191 TagColorSet TagColorSet::operator|(const TagColorSet & other) const
192 {
193 return TagColorSet(_mask | other._mask);
194 }
195
196 TagColorSet & TagColorSet::operator|=(const TagColorSet & other)
197 {
198 _mask |= other._mask;
199 return *this;
200 }
201
202 TagColorSet TagColorSet::operator&(const TagColorSet & other) const
203 {
204 return TagColorSet(_mask & other._mask);
205 }
206
207 TagColorSet & TagColorSet::operator&=(const TagColorSet & other)
208 {
209 _mask &= other._mask;
210 return *this;
211 }
212
mask()213 unsigned int TagColorSet::mask() const
214 {
215 return _mask;
216 }
217
const_iterator(const TagColorSet & set)218 TagColorSet::const_iterator::const_iterator(const TagColorSet & set) : _position(0), _set(set)
219 {
220 while (!isAtEnd() && !(_set._mask & (1 << _position))) {
221 ++_position;
222 }
223 }
224
isAtEnd()225 bool TagColorSet::const_iterator::isAtEnd() const
226 {
227 return (_position == int(TagColor::Count));
228 }
229
230 TagColorSet::const_iterator & TagColorSet::const_iterator::operator++()
231 {
232 while (!isAtEnd()) {
233 ++_position;
234 if (_set._mask & (1 << _position)) {
235 break;
236 }
237 }
238 return *this;
239 }
240
241 TagColor TagColorSet::const_iterator::operator*() const
242 {
243 Q_ASSERT_X(!isAtEnd(), __PRETTY_FUNCTION__, "Should not dereference end() iterator");
244 Q_ASSERT_X((_set._mask & (1 << _position)), __PRETTY_FUNCTION__, "Current TagColor but is not set");
245 return TagColor(_position);
246 }
247
248 TagColorSet::const_iterator TagColorSet::const_iterator::operator++(int)
249 {
250 auto current = *this;
251 ++(*this);
252 return current;
253 }
254
255 bool TagColorSet::const_iterator::operator!=(const TagColorSet::const_iterator & other) const
256 {
257 return (&_set != &other._set) || (_position != other._position);
258 }
259
260 bool TagColorSet::const_iterator::operator==(const TagColorSet::const_iterator & other) const
261 {
262 return (&_set == &other._set) && (_position == other._position);
263 }
264
begin()265 TagColorSet::const_iterator TagColorSet::begin() const
266 {
267 return const_iterator(*this);
268 }
269
end()270 TagColorSet::const_iterator TagColorSet::end() const
271 {
272 const_iterator it(*this);
273 while (!it.isAtEnd()) {
274 ++it;
275 }
276 return it;
277 }
278
279 inline TagColorSet & TagColorSet::operator=(const TagColorSet & other)
280 {
281 _mask = other._mask;
282 return *this;
283 }
284
285 } // namespace GmicQt
286
287 #endif // GMIC_QT_TAGS_H
288