color_palette.cpp
Go to the documentation of this file.
00001 
00022 #include "color_palette.hpp"
00023 #include <cmath>
00024 #include <QFile>
00025 #include <QTextStream>
00026 #include <QHash>
00027 #include <QPainter>
00028 #include <QFileInfo>
00029 
00030 namespace color_widgets {
00031 
00032 class ColorPalette::Private
00033 {
00034 public:
00035     QVector<QPair<QColor,QString> >   colors;
00036     int             columns;
00037     QString         name;
00038     QString         fileName;
00039     bool            dirty;
00040 
00041     bool valid_index(int index)
00042     {
00043         return index >= 0 && index < colors.size();
00044     }
00045 };
00046 
00047 ColorPalette::ColorPalette(const QVector<QColor>& colors,
00048                            const QString& name,
00049                            int columns)
00050     : p ( new Private )
00051 {
00052     setName(name);
00053     setColumns(columns);
00054     setColors(colors);
00055 }
00056 
00057 ColorPalette::ColorPalette(const QString& name)
00058     : p ( new Private )
00059 {
00060     setName(name);
00061     p->columns = 0;
00062     p->dirty = false;
00063 }
00064 
00065 ColorPalette::ColorPalette(const QVector<QPair<QColor,QString> >& colors,
00066                            const QString& name,
00067                            int columns)
00068 {
00069     setName(name);
00070     setColumns(columns);
00071     setColors(colors);
00072     p->dirty = false;
00073 }
00074 
00075 ColorPalette::ColorPalette(const ColorPalette& other)
00076     : QObject(), p ( new Private(*other.p) )
00077 {
00078 }
00079 
00080 ColorPalette& ColorPalette::operator=(const ColorPalette& other)
00081 {
00082     *p = *other.p;
00083     emitUpdate();
00084     return *this;
00085 }
00086 
00087 ColorPalette::~ColorPalette()
00088 {
00089     delete p;
00090 }
00091 
00092 ColorPalette::ColorPalette(ColorPalette&& other)
00093     : QObject(), p ( other.p )
00094 {
00095     other.p = nullptr;
00096 }
00097 ColorPalette& ColorPalette::operator=(ColorPalette&& other)
00098 {
00099     std::swap(p, other.p);
00100     emitUpdate();
00101     return *this;
00102 }
00103 
00104 void ColorPalette::emitUpdate()
00105 {
00106     emit colorsChanged(p->colors);
00107     emit columnsChanged(p->columns);
00108     emit nameChanged(p->name);
00109     emit fileNameChanged(p->fileName);
00110     emit dirtyChanged(p->dirty);
00111 }
00112 
00113 QColor ColorPalette::colorAt(int index) const
00114 {
00115     return p->valid_index(index) ? p->colors[index].first : QColor();
00116 }
00117 
00118 QString ColorPalette::nameAt(int index) const
00119 {
00120     return p->valid_index(index) ? p->colors[index].second : QString();
00121 }
00122 
00123 QVector<QPair<QColor,QString> > ColorPalette::colors() const
00124 {
00125     return p->colors;
00126 }
00127 
00128 int ColorPalette::count() const
00129 {
00130     return p->colors.size();
00131 }
00132 
00133 int ColorPalette::columns()
00134 {
00135     return p->columns;
00136 }
00137 
00138 QString ColorPalette::name() const
00139 {
00140     return p->name;
00141 }
00142 
00143 void ColorPalette::loadColorTable(const QVector<QRgb>& color_table)
00144 {
00145     p->colors.clear();
00146     p->colors.reserve(color_table.size());
00147     for ( QRgb c : color_table )
00148     {
00149         QColor color ( c );
00150         color.setAlpha(255);
00151         p->colors.push_back(qMakePair(color,QString()));
00152     }
00153     emit colorsChanged(p->colors);
00154     setDirty(true);
00155 }
00156 
00157 bool ColorPalette::loadImage(const QImage& image)
00158 {
00159     if ( image.isNull() )
00160         return false;
00161     setColumns(image.width());
00162 
00163     p->colors.clear();
00164     p->colors.reserve(image.width()*image.height());
00165     for ( int y = 0; y < image.height(); y++ )
00166     {
00167         for ( int x = 0; x < image.width(); x++ )
00168         {
00169             QColor color ( image.pixel(x, y) );
00170             color.setAlpha(255);
00171             p->colors.push_back(qMakePair(color,QString()));
00172         }
00173     }
00174     emit colorsChanged(p->colors);
00175     setDirty(true);
00176     return true;
00177 }
00178 
00179 ColorPalette ColorPalette::fromImage(const QImage& image)
00180 {
00181     ColorPalette p;
00182     p.fromImage(image);
00183     return p;
00184 }
00185 
00186 bool ColorPalette::load(const QString& name)
00187 {
00188     p->fileName = name;
00189     p->colors.clear();
00190     p->columns = 0;
00191     p->dirty = false;
00192     p->name = QFileInfo(name).baseName();
00193 
00194     QFile file(name);
00195 
00196     if ( !file.open(QFile::ReadOnly|QFile::Text) )
00197     {
00198         emitUpdate();
00199         return false;
00200     }
00201 
00202     QTextStream stream( &file );
00203 
00204     if ( stream.readLine() != "GIMP Palette" )
00205     {
00206         emitUpdate();
00207         return false;
00208     }
00209 
00210     QString line;
00211 
00212     // parse properties
00213     QHash<QString,QString> properties;
00214     while( !stream.atEnd() )
00215     {
00216         line = stream.readLine();
00217         if ( line.isEmpty() )
00218             continue;
00219         if ( line[0] == '#' )
00220             break;
00221         int colon = line.indexOf(':');
00222         if ( colon == -1 )
00223             break;
00224         properties[line.left(colon).toLower()] =
00225             line.right(line.size() - colon - 1).trimmed();
00226     }
00228     setName(properties["name"]);
00229     setColumns(properties["columns"].toInt());
00230 
00231     // Skip comments
00232     if ( !stream.atEnd() && line[0] == '#' )
00233         while( !stream.atEnd() )
00234         {
00235             qint64 pos = stream.pos();
00236             line = stream.readLine();
00237             if ( !line.isEmpty() && line[0] != '#' )
00238             {
00239                 stream.seek(pos);
00240                 break;
00241             }
00242         }
00243 
00244     while( !stream.atEnd() )
00245     {
00246         int r = 0, g = 0, b = 0;
00247         stream >> r >> g >> b;
00248         line = stream.readLine().trimmed();
00249         p->colors.push_back(qMakePair(QColor(r, g, b), line));
00250     }
00251 
00252     emit colorsChanged(p->colors);
00253     setDirty(false);
00254 
00255     return true;
00256 }
00257 
00258 ColorPalette ColorPalette::fromFile(const QString& name)
00259 {
00260     ColorPalette p;
00261     p.load(name);
00262     return p;
00263 }
00264 
00265 bool ColorPalette::save(const QString& filename)
00266 {
00267     setFileName(filename);
00268     return save();
00269 }
00270 
00271 bool ColorPalette::save()
00272 {
00273     QString filename = p->fileName;
00274     if ( filename.isEmpty() )
00275     {
00276         filename = unnamed(p->name)+".gpl";
00277     }
00278 
00279     QFile file(filename);
00280     if ( !file.open(QFile::Text|QFile::WriteOnly) )
00281         return false;
00282 
00283     QTextStream stream(&file);
00284 
00285     stream << "GIMP Palette\n";
00286     stream << "Name: " << unnamed(p->name) << '\n';
00287     if ( p->columns )
00288         stream << "Columns: " << p->columns << '\n';
00290     stream << "#\n";
00291 
00292     for ( int i = 0; i < p->colors.size(); i++ )
00293     {
00294         stream << qSetFieldWidth(3) << p->colors[i].first.red() << qSetFieldWidth(0) << ' '
00295                << qSetFieldWidth(3) << p->colors[i].first.green() << qSetFieldWidth(0) << ' '
00296                << qSetFieldWidth(3) << p->colors[i].first.blue() << qSetFieldWidth(0) << '\t'
00297                << unnamed(p->colors[i].second) << '\n';
00298     }
00299 
00300     if ( !file.error() )
00301     {
00302         setDirty(false);
00303         return true;
00304     }
00305 
00306     return false;
00307 }
00308 
00309 
00310 QString ColorPalette::fileName() const
00311 {
00312     return p->fileName;
00313 }
00314 
00315 
00316 void ColorPalette::setColumns(int columns)
00317 {
00318     if ( columns <= 0 )
00319         columns = 0;
00320 
00321     if ( columns != p->columns )
00322     {
00323         setDirty(true);
00324         emit columnsChanged( p->columns = columns );
00325     }
00326 }
00327 
00328 void ColorPalette::setColors(const QVector<QColor>& colors)
00329 {
00330     p->colors.clear();
00331     foreach(const QColor& col, colors)
00332         p->colors.push_back(qMakePair(col,QString()));
00333     setDirty(true);
00334     emit colorsChanged(p->colors);
00335 }
00336 
00337 void ColorPalette::setColors(const QVector<QPair<QColor,QString> >& colors)
00338 {
00339     p->colors = colors;
00340     setDirty(true);
00341     emit colorsChanged(p->colors);
00342 }
00343 
00344 
00345 void ColorPalette::setColorAt(int index, const QColor& color)
00346 {
00347     if ( !p->valid_index(index) )
00348         return;
00349 
00350     p->colors[index].first = color;
00351 
00352     setDirty(true);
00353     emit colorChanged(index);
00354     emit colorsUpdated(p->colors);
00355 }
00356 
00357 void ColorPalette::setColorAt(int index, const QColor& color, const QString& name)
00358 {
00359     if ( !p->valid_index(index) )
00360         return;
00361 
00362     p->colors[index].first = color;
00363     p->colors[index].second = name;
00364     setDirty(true);
00365     emit colorChanged(index);
00366     emit colorsUpdated(p->colors);
00367 }
00368 
00369 void ColorPalette::setNameAt(int index, const QString& name)
00370 {
00371     if ( !p->valid_index(index) )
00372         return;
00373 
00374     p->colors[index].second = name;
00375 
00376     setDirty(true);
00377     emit colorChanged(index);
00378     emit colorsUpdated(p->colors);
00379 }
00380 
00381 
00382 void ColorPalette::appendColor(const QColor& color, const QString& name)
00383 {
00384     p->colors.push_back(qMakePair(color,name));
00385     setDirty(true);
00386     emit colorAdded(p->colors.size()-1);
00387     emit colorsUpdated(p->colors);
00388 }
00389 
00390 void ColorPalette::insertColor(int index, const QColor& color, const QString& name)
00391 {
00392     if ( index < 0 || index > p->colors.size() )
00393         return;
00394 
00395     p->colors.insert(index, qMakePair(color, name));
00396 
00397     setDirty(true);
00398     emit colorAdded(index);
00399     emit colorsUpdated(p->colors);
00400 }
00401 
00402 void ColorPalette::eraseColor(int index)
00403 {
00404     if ( !p->valid_index(index) )
00405         return;
00406 
00407     p->colors.remove(index);
00408 
00409     setDirty(true);
00410     emit colorRemoved(index);
00411     emit colorsUpdated(p->colors);
00412 }
00413 
00414 void ColorPalette::setName(const QString& name)
00415 {
00416     setDirty(true);
00417     p->name = name;
00418 }
00419 
00420 void ColorPalette::setFileName(const QString& name)
00421 {
00422     setDirty(true);
00423     p->fileName = name;
00424 }
00425 
00426 QString ColorPalette::unnamed(const QString& name) const
00427 {
00428     return name.isEmpty() ? tr("Unnamed") : name;
00429 }
00430 
00431 
00432 QPixmap ColorPalette::preview(const QSize& size, const QColor& background) const
00433 {
00434     if ( !size.isValid() || p->colors.empty() )
00435         return QPixmap();
00436 
00437     QPixmap out( size );
00438     out.fill(background);
00439     QPainter painter(&out);
00440 
00441     int count = p->colors.size();
00442     int columns = p->columns;
00443     if ( !columns )
00444         columns = std::ceil( std::sqrt( count * float(size.width()) / size.height() ) );
00445     int rows = std::ceil( float(count) / columns );
00446     QSizeF color_size(float(size.width()) / columns, float(size.height()) / rows);
00447 
00448     for ( int y = 0, i = 0; y < rows && i < count; y++ )
00449     {
00450         for ( int x = 0; x < columns && i < count; x++, i++ )
00451         {
00452             painter.fillRect(QRectF(x*color_size.width(), y*color_size.height(),
00453                              color_size.width(), color_size.height()),
00454                              p->colors[i].first
00455                             );
00456         }
00457     }
00458 
00459     return out;
00460 }
00461 
00462 bool ColorPalette::dirty() const
00463 {
00464     return p->dirty;
00465 }
00466 
00467 void ColorPalette::setDirty(bool dirty)
00468 {
00469     if ( dirty != p->dirty )
00470         emit dirtyChanged( p->dirty = dirty );
00471 }
00472 
00473 QVector<QColor> ColorPalette::onlyColors() const
00474 {
00475     QVector<QColor> out;
00476     out.reserve(p->colors.size());
00477     for ( int i = 0; i < p->colors.size(); i++ )
00478         out.push_back(p->colors[i].first);
00479     return out;
00480 }
00481 
00482 QVector<QRgb> ColorPalette::colorTable() const
00483 {
00484     QVector<QRgb> out;
00485     out.reserve(p->colors.size());
00486     for ( const auto& color_pair : p->colors )
00487         out.push_back(color_pair.first.rgba());
00488     return out;
00489 }
00490 
00491 ColorPalette ColorPalette::fromColorTable(const QVector<QRgb>& table)
00492 {
00493     ColorPalette palette;
00494     palette.loadColorTable(table);
00495     return palette;
00496 }
00497 
00498 } // namespace color_widgets


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:55