color_palette.cpp
Go to the documentation of this file.
1 
22 #include "color_palette.hpp"
23 #include <cmath>
24 #include <QFile>
25 #include <QTextStream>
26 #include <QHash>
27 #include <QPainter>
28 #include <QFileInfo>
29 
30 namespace color_widgets {
31 
33 {
34 public:
36  int columns;
37  QString name;
38  QString fileName;
39  bool dirty;
40 
41  bool valid_index(int index)
42  {
43  return index >= 0 && index < colors.size();
44  }
45 };
46 
48  const QString& name,
49  int columns)
50  : p ( new Private )
51 {
52  setName(name);
53  setColumns(columns);
54  setColors(colors);
55 }
56 
58  : p ( new Private )
59 {
60  setName(name);
61  p->columns = 0;
62  p->dirty = false;
63 }
64 
65 ColorPalette::ColorPalette(const QVector<QPair<QColor,QString> >& colors,
66  const QString& name,
67  int columns)
68 {
69  setName(name);
70  setColumns(columns);
72  p->dirty = false;
73 }
74 
76  : QObject(), p ( new Private(*other.p) )
77 {
78 }
79 
81 {
82  *p = *other.p;
83  emitUpdate();
84  return *this;
85 }
86 
88 {
89  delete p;
90 }
91 
93  : QObject(), p ( other.p )
94 {
95  other.p = nullptr;
96 }
98 {
99  std::swap(p, other.p);
100  emitUpdate();
101  return *this;
102 }
103 
105 {
106  emit colorsChanged(p->colors);
107  emit columnsChanged(p->columns);
108  emit nameChanged(p->name);
109  emit fileNameChanged(p->fileName);
110  emit dirtyChanged(p->dirty);
111 }
112 
113 QColor ColorPalette::colorAt(int index) const
114 {
115  return p->valid_index(index) ? p->colors[index].first : QColor();
116 }
117 
118 QString ColorPalette::nameAt(int index) const
119 {
120  return p->valid_index(index) ? p->colors[index].second : QString();
121 }
122 
124 {
125  return p->colors;
126 }
127 
128 int ColorPalette::count() const
129 {
130  return p->colors.size();
131 }
132 
134 {
135  return p->columns;
136 }
137 
138 QString ColorPalette::name() const
139 {
140  return p->name;
141 }
142 
144 {
145  p->colors.clear();
146  p->colors.reserve(color_table.size());
147  for ( QRgb c : color_table )
148  {
149  QColor color ( c );
150  color.setAlpha(255);
151  p->colors.push_back(qMakePair(color,QString()));
152  }
153  emit colorsChanged(p->colors);
154  setDirty(true);
155 }
156 
157 bool ColorPalette::loadImage(const QImage& image)
158 {
159  if ( image.isNull() )
160  return false;
161  setColumns(image.width());
162 
163  p->colors.clear();
164  p->colors.reserve(image.width()*image.height());
165  for ( int y = 0; y < image.height(); y++ )
166  {
167  for ( int x = 0; x < image.width(); x++ )
168  {
169  QColor color ( image.pixel(x, y) );
170  color.setAlpha(255);
171  p->colors.push_back(qMakePair(color,QString()));
172  }
173  }
174  emit colorsChanged(p->colors);
175  setDirty(true);
176  return true;
177 }
178 
180 {
181  ColorPalette p;
182  p.fromImage(image);
183  return p;
184 }
185 
186 bool ColorPalette::load(const QString& name)
187 {
188  p->fileName = name;
189  p->colors.clear();
190  p->columns = 0;
191  p->dirty = false;
192  p->name = QFileInfo(name).baseName();
193 
194  QFile file(name);
195 
196  if ( !file.open(QFile::ReadOnly|QFile::Text) )
197  {
198  emitUpdate();
199  return false;
200  }
201 
202  QTextStream stream( &file );
203 
204  if ( stream.readLine() != "GIMP Palette" )
205  {
206  emitUpdate();
207  return false;
208  }
209 
210  QString line;
211 
212  // parse properties
213  QHash<QString,QString> properties;
214  while( !stream.atEnd() )
215  {
216  line = stream.readLine();
217  if ( line.isEmpty() )
218  continue;
219  if ( line[0] == '#' )
220  break;
221  int colon = line.indexOf(':');
222  if ( colon == -1 )
223  break;
224  properties[line.left(colon).toLower()] =
225  line.right(line.size() - colon - 1).trimmed();
226  }
228  setName(properties["name"]);
229  setColumns(properties["columns"].toInt());
230 
231  // Skip comments
232  if ( !stream.atEnd() && line[0] == '#' )
233  while( !stream.atEnd() )
234  {
235  qint64 pos = stream.pos();
236  line = stream.readLine();
237  if ( !line.isEmpty() && line[0] != '#' )
238  {
239  stream.seek(pos);
240  break;
241  }
242  }
243 
244  while( !stream.atEnd() )
245  {
246  int r = 0, g = 0, b = 0;
247  stream >> r >> g >> b;
248  line = stream.readLine().trimmed();
249  p->colors.push_back(qMakePair(QColor(r, g, b), line));
250  }
251 
252  emit colorsChanged(p->colors);
253  setDirty(false);
254 
255  return true;
256 }
257 
259 {
260  ColorPalette p;
261  p.load(name);
262  return p;
263 }
264 
265 bool ColorPalette::save(const QString& filename)
266 {
267  setFileName(filename);
268  return save();
269 }
270 
272 {
273  QString filename = p->fileName;
274  if ( filename.isEmpty() )
275  {
276  filename = unnamed(p->name)+".gpl";
277  }
278 
279  QFile file(filename);
280  if ( !file.open(QFile::Text|QFile::WriteOnly) )
281  return false;
282 
283  QTextStream stream(&file);
284 
285  stream << "GIMP Palette\n";
286  stream << "Name: " << unnamed(p->name) << '\n';
287  if ( p->columns )
288  stream << "Columns: " << p->columns << '\n';
290  stream << "#\n";
291 
292  for ( int i = 0; i < p->colors.size(); i++ )
293  {
294  stream << qSetFieldWidth(3) << p->colors[i].first.red() << qSetFieldWidth(0) << ' '
295  << qSetFieldWidth(3) << p->colors[i].first.green() << qSetFieldWidth(0) << ' '
296  << qSetFieldWidth(3) << p->colors[i].first.blue() << qSetFieldWidth(0) << '\t'
297  << unnamed(p->colors[i].second) << '\n';
298  }
299 
300  if ( !file.error() )
301  {
302  setDirty(false);
303  return true;
304  }
305 
306  return false;
307 }
308 
309 
310 QString ColorPalette::fileName() const
311 {
312  return p->fileName;
313 }
314 
315 
317 {
318  if ( columns <= 0 )
319  columns = 0;
320 
321  if ( columns != p->columns )
322  {
323  setDirty(true);
324  emit columnsChanged( p->columns = columns );
325  }
326 }
327 
329 {
330  p->colors.clear();
331  foreach(const QColor& col, colors)
332  p->colors.push_back(qMakePair(col,QString()));
333  setDirty(true);
334  emit colorsChanged(p->colors);
335 }
336 
337 void ColorPalette::setColors(const QVector<QPair<QColor,QString> >& colors)
338 {
339  p->colors = colors;
340  setDirty(true);
341  emit colorsChanged(p->colors);
342 }
343 
344 
345 void ColorPalette::setColorAt(int index, const QColor& color)
346 {
347  if ( !p->valid_index(index) )
348  return;
349 
350  p->colors[index].first = color;
351 
352  setDirty(true);
353  emit colorChanged(index);
354  emit colorsUpdated(p->colors);
355 }
356 
357 void ColorPalette::setColorAt(int index, const QColor& color, const QString& name)
358 {
359  if ( !p->valid_index(index) )
360  return;
361 
362  p->colors[index].first = color;
363  p->colors[index].second = name;
364  setDirty(true);
365  emit colorChanged(index);
366  emit colorsUpdated(p->colors);
367 }
368 
369 void ColorPalette::setNameAt(int index, const QString& name)
370 {
371  if ( !p->valid_index(index) )
372  return;
373 
374  p->colors[index].second = name;
375 
376  setDirty(true);
377  emit colorChanged(index);
378  emit colorsUpdated(p->colors);
379 }
380 
381 
382 void ColorPalette::appendColor(const QColor& color, const QString& name)
383 {
384  p->colors.push_back(qMakePair(color,name));
385  setDirty(true);
386  emit colorAdded(p->colors.size()-1);
387  emit colorsUpdated(p->colors);
388 }
389 
390 void ColorPalette::insertColor(int index, const QColor& color, const QString& name)
391 {
392  if ( index < 0 || index > p->colors.size() )
393  return;
394 
395  p->colors.insert(index, qMakePair(color, name));
396 
397  setDirty(true);
398  emit colorAdded(index);
399  emit colorsUpdated(p->colors);
400 }
401 
403 {
404  if ( !p->valid_index(index) )
405  return;
406 
407  p->colors.remove(index);
408 
409  setDirty(true);
410  emit colorRemoved(index);
411  emit colorsUpdated(p->colors);
412 }
413 
414 void ColorPalette::setName(const QString& name)
415 {
416  setDirty(true);
417  p->name = name;
418 }
419 
420 void ColorPalette::setFileName(const QString& name)
421 {
422  setDirty(true);
423  p->fileName = name;
424 }
425 
426 QString ColorPalette::unnamed(const QString& name) const
427 {
428  return name.isEmpty() ? tr("Unnamed") : name;
429 }
430 
431 
432 QPixmap ColorPalette::preview(const QSize& size, const QColor& background) const
433 {
434  if ( !size.isValid() || p->colors.empty() )
435  return QPixmap();
436 
437  QPixmap out( size );
438  out.fill(background);
439  QPainter painter(&out);
440 
441  int count = p->colors.size();
442  int columns = p->columns;
443  if ( !columns )
444  columns = std::ceil( std::sqrt( count * float(size.width()) / size.height() ) );
445  int rows = std::ceil( float(count) / columns );
446  QSizeF color_size(float(size.width()) / columns, float(size.height()) / rows);
447 
448  for ( int y = 0, i = 0; y < rows && i < count; y++ )
449  {
450  for ( int x = 0; x < columns && i < count; x++, i++ )
451  {
452  painter.fillRect(QRectF(x*color_size.width(), y*color_size.height(),
453  color_size.width(), color_size.height()),
454  p->colors[i].first
455  );
456  }
457  }
458 
459  return out;
460 }
461 
462 bool ColorPalette::dirty() const
463 {
464  return p->dirty;
465 }
466 
468 {
469  if ( dirty != p->dirty )
470  emit dirtyChanged( p->dirty = dirty );
471 }
472 
474 {
475  QVector<QColor> out;
476  out.reserve(p->colors.size());
477  for ( int i = 0; i < p->colors.size(); i++ )
478  out.push_back(p->colors[i].first);
479  return out;
480 }
481 
483 {
484  QVector<QRgb> out;
485  out.reserve(p->colors.size());
486  for ( const auto& color_pair : p->colors )
487  out.push_back(color_pair.first.rgba());
488  return out;
489 }
490 
492 {
493  ColorPalette palette;
494  palette.loadColorTable(table);
495  return palette;
496 }
497 
498 } // namespace color_widgets
void colorsChanged(const QVector< QPair< QColor, QString > > &)
Emitted when all the colors have changed.
void setName(const QString &name)
QVector< QColor > onlyColors() const
bool save()
save to file, the filename is fileName or determined automatically
Q_INVOKABLE void loadColorTable(const QVector< QRgb > &color_table)
Use a color table to set the colors.
void emitUpdate()
Emit all the necessary signals when the palette has been completely overwritten.
Q_INVOKABLE QVector< QRgb > colorTable() const
Convert to a color table.
void setColors(const QVector< QColor > &colors)
void setFileName(const QString &name)
QVector< QPair< QColor, QString > > colors() const
static ColorPalette fromImage(const QImage &image)
Creates a ColorPalette from a Gimp palette (gpl) file.
void colorAdded(int index)
Emitted when a single color has been added.
void setNameAt(int index, const QString &name=QString())
Change the name of a color.
QPixmap preview(const QSize &size, const QColor &background=Qt::transparent) const
Returns a preview image of the colors in the palette.
void setColorAt(int index, const QColor &color)
Change the color at the given index.
void eraseColor(int index)
Remove the color at the given index.
static ColorPalette fromFile(const QString &name)
Creates a ColorPalette from a Gimp palette (gpl) file.
void colorRemoved(int index)
Emitted when the color at the given index has been removed.
void nameChanged(const QString &)
Q_INVOKABLE bool loadImage(const QImage &image)
Use the pixels on an image to set the palette colors.
Q_INVOKABLE QColor colorAt(int index) const
Color at the given index.
void colorChanged(int index)
Emitted when the color or the name at the given index has been modified.
MQTTClient c
Definition: test10.c:1656
ColorPalette & operator=(const ColorPalette &other)
static ColorPalette fromColorTable(const QVector< QRgb > &table)
Creates a ColorPalette from a color table.
QVector< QPair< QColor, QString > > colors
ColorPalette(const QVector< QColor > &colors, const QString &name=QString(), int columns=0)
Q_INVOKABLE bool load(const QString &name)
Load contents from a Gimp palette (gpl) file.
void insertColor(int index, const QColor &color, const QString &name=QString())
Insert a color in an arbitrary location.
void fileNameChanged(const QString &)
Q_INVOKABLE QString nameAt(int index) const
Color name at the given index.
void appendColor(const QColor &color, const QString &name=QString())
Append a color at the end.
QString fileName() const
void setColumns(int columns)
QString unnamed(const QString &name=QString()) const
Returns name if it isn&#39;t null, otherwise a default value.
void colorsUpdated(const QVector< QPair< QColor, QString >> &)
Emitted when the colors have been modified with a simple operation (set, append etc.)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:47:33