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