diff --git a/libs/libkis/Palette.cpp b/libs/libkis/Palette.cpp index 4e2044031e..26310fc2ca 100644 --- a/libs/libkis/Palette.cpp +++ b/libs/libkis/Palette.cpp @@ -1,166 +1,167 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Palette.h" #include +#include #include struct Palette::Private { KoColorSet *palette {0}; }; Palette::Palette(Resource *resource): d(new Private()) { d->palette = dynamic_cast(resource->resource()); } Palette::~Palette() { delete d; } int Palette::numberOfEntries() const { if (!d->palette) return 0; return d->palette->nColors(); } int Palette::columnCount() { if (!d->palette) return 0; return d->palette->columnCount(); } void Palette::setColumnCount(int columns) { if (d->palette) d->palette->setColumnCount(columns); } QString Palette::comment() { if (!d->palette) return ""; return d->palette->comment(); } void Palette::setComment(QString comment) { if (!d->palette) return; return d->palette->setComment(comment); } QStringList Palette::groupNames() { if (!d->palette) return QStringList(); return d->palette->getGroupNames(); } bool Palette::addGroup(QString name) { if (!d->palette) return false; return d->palette->addGroup(name); } bool Palette::removeGroup(QString name, bool keepColors) { if (!d->palette) return false; return d->palette->removeGroup(name, keepColors); } int Palette::colorsCountTotal() { if (!d->palette) return 0; return d->palette->nColors(); } int Palette::colorsCountGroup(QString name) { if (!d->palette) return 0; return d->palette->nColorsGroup(name); } -KoColorSetEntry Palette::colorSetEntryByIndex(int index) +KisSwatch Palette::colorSetEntryByIndex(int index) { /* if (!d->palette) return KoColorSetEntry(); return d->palette->getColorGlobal(index); */ - return KoColorSetEntry(); + return KisSwatch(); } -KoColorSetEntry Palette::colorSetEntryFromGroup(int index, const QString &groupName) +KisSwatch Palette::colorSetEntryFromGroup(int index, const QString &groupName) { /* if (!d->palette) return KoColorSetEntry(); return d->palette->getColorGroup(index, groupName); */ - return KoColorSetEntry(); + return KisSwatch(); } -ManagedColor *Palette::colorForEntry(KoColorSetEntry entry) +ManagedColor *Palette::colorForEntry(KisSwatch entry) { if (!d->palette) return 0; ManagedColor *color = new ManagedColor(entry.color()); return color; } -void Palette::addEntry(KoColorSetEntry entry, QString groupName) +void Palette::addEntry(KisSwatch entry, QString groupName) { d->palette->add(entry, groupName); } void Palette::removeEntry(int index, const QString &groupName) { // d->palette->removeAt(index, groupName); } /* void Palette::insertEntry(int index, KoColorSetEntry entry, QString groupName) { d->palette->insertBefore(entry, index, groupName); } */ -bool Palette::editEntry(int index, KoColorSetEntry entry, QString groupName) +bool Palette::editEntry(int index, KisSwatch entry, QString groupName) { // return d->palette->changeColorSetEntry(entry, groupName, index); return true; } bool Palette::changeGroupName(QString oldGroupName, QString newGroupName) { return d->palette->changeGroupName(oldGroupName, newGroupName); } bool Palette::moveGroup(const QString &groupName, const QString &groupNameInsertBefore) { return d->palette->moveGroup(groupName, groupNameInsertBefore); } bool Palette::save() { if (d->palette->filename().size()>0) { return d->palette->save(); } //if there's no filename the palette proly doesn't even exist... return false; } KoColorSet *Palette::colorSet() { return d->palette; } diff --git a/libs/libkis/Palette.h b/libs/libkis/Palette.h index b028627198..a19948c433 100644 --- a/libs/libkis/Palette.h +++ b/libs/libkis/Palette.h @@ -1,204 +1,204 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBKIS_PALETTE_H #define LIBKIS_PALETTE_H #include #include "kritalibkis_export.h" #include "libkis.h" #include "Resource.h" #include "KoColorSet.h" class ManagedColor; /** * @brief The Palette class * Palette is a resource object that stores organised color data. * It's purpose is to allow artists to save colors and store them. * * An example for printing all the palettes and the entries: * * @code import sys from krita import * resources = Application.resources("palette") for (k, v) in resources.items(): print(k) palette = Palette(v) for x in range(palette.numberOfEntries()): entry = palette.colorSetEntryByIndex(x) c = palette.colorForEntry(entry); print(x, entry.name(), entry.id(), entry.spotColor(), c.toQString()) * @endcode */ class KRITALIBKIS_EXPORT Palette : public QObject { public: Palette(Resource *resource); ~Palette() override; /** * @brief numberOfEntries * @return */ int numberOfEntries() const; /** * @brief columnCount * @return the amount of columns this palette is set to use. */ int columnCount(); /** * @brief setColumnCount * Set the amount of columns this palette should use. */ void setColumnCount(int columns); /** * @brief comment * @return the comment or description associated with the palette. */ QString comment(); /** * @brief setComment * set the comment or description associated with the palette. * @param comment */ void setComment(QString comment); /** * @brief groupNames * @return the list of group names. This is list is in the order these groups are in the file. */ QStringList groupNames(); /** * @brief addGroup * @param name of the new group * @return whether adding the group was successful. */ bool addGroup(QString name); /** * @brief removeGroup * @param name the name of the group to remove. * @param keepColors whether or not to delete all the colors inside, or to move them to the default group. * @return */ bool removeGroup(QString name, bool keepColors = true); /** * @brief colorsCountTotal * @return the total amount of entries in the whole group */ int colorsCountTotal(); /** * @brief colorsCountGroup * @param name of the group to check. Empty is the default group. * @return the amount of colors within that group. */ int colorsCountGroup(QString name); /** * @brief colorSetEntryByIndex * get the colorsetEntry from the global index. * @param index the global index * @return the colorset entry */ - KoColorSetEntry colorSetEntryByIndex(int index); + KisSwatch colorSetEntryByIndex(int index); /** * @brief colorSetEntryFromGroup * @param index index in the group. * @param groupName the name of the group to get the color from. * @return the colorsetentry. */ - KoColorSetEntry colorSetEntryFromGroup(int index, const QString &groupName); + KisSwatch colorSetEntryFromGroup(int index, const QString &groupName); /** * @brief colorForEntry * special function to retrieve a ManagedColor object from the colorsetentry. * @param entry the entry * @return the ManagedColorObject */ - ManagedColor *colorForEntry(KoColorSetEntry entry); + ManagedColor *colorForEntry(KisSwatch entry); /** * @brief addEntry * add an entry to a group. Gets appended to the end. * @param entry the entry * @param groupName the name of the group to add to. */ - void addEntry(KoColorSetEntry entry, QString groupName = QString()); + void addEntry(KisSwatch entry, QString groupName = QString()); /** * @brief removeEntry * remove the entry at @param index from the group @param groupName. */ void removeEntry(int index, const QString &groupName); /** * @brief insertEntry * like addentry, but allows you to pick the index to insertBefore. * @param index * @param entry * @param groupName */ // void insertEntry(int index, KoColorSetEntry entry, QString groupName = QString()); /** * @brief editEntry * Changes the entry at @param index by replacing it with @param entry. * @param groupName the group at which the index is. * @return whether it was successful. */ - bool editEntry (int index, KoColorSetEntry entry, QString groupName = QString()); + bool editEntry (int index, KisSwatch entry, QString groupName = QString()); /** * @brief changeGroupName * change the group name. * @param oldGroupName the old groupname to change. * @param newGroupName the new name to change it into. * @return whether successful. Reasons for failure include not knowing have oldGroupName */ bool changeGroupName(QString oldGroupName, QString newGroupName); /** * @brief moveGroup * move the group to before groupNameInsertBefore. * @param groupName group to move. * @param groupNameInsertBefore group to inset before. * @return whether successful. Reasons for failure include either group not existing. */ bool moveGroup(const QString &groupName, const QString &groupNameInsertBefore = QString()); /** * @brief save * save the palette * @return whether it was successful. */ bool save(); private: friend class PaletteView; struct Private; Private *const d; /** * @brief colorSet * @return gives qa KoColorSet object back */ KoColorSet *colorSet(); }; #endif // LIBKIS_PALETTE_H diff --git a/libs/libkis/PaletteView.cpp b/libs/libkis/PaletteView.cpp index a7df9369a6..1725396125 100644 --- a/libs/libkis/PaletteView.cpp +++ b/libs/libkis/PaletteView.cpp @@ -1,84 +1,84 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include struct PaletteView::Private { KisPaletteModel *model = 0; KisPaletteView *widget = 0; bool allowPaletteModification = true; }; PaletteView::PaletteView(QWidget *parent) : QWidget(parent), d(new Private) { d->widget = new KisPaletteView(this); d->model = new KisPaletteModel(); d->widget->setPaletteModel(d->model); this->setLayout(new QVBoxLayout()); this->layout()->addWidget(d->widget); //forward signals. - connect(d->widget, SIGNAL(entrySelected(KoColorSetEntry)), - this, SIGNAL(entrySelectedForeGround(KoColorSetEntry))); - connect(d->widget, SIGNAL(entrySelectedBackGround(KoColorSetEntry)), - this, SIGNAL(entrySelectedBackGround(KoColorSetEntry))); + connect(d->widget, SIGNAL(entrySelected(KisSwatch)), + this, SIGNAL(entrySelectedForeGround(KisSwatch))); + connect(d->widget, SIGNAL(entrySelectedBackGround(KisSwatch)), + this, SIGNAL(entrySelectedBackGround(KisSwatch))); } PaletteView::~PaletteView() { delete d->model; } void PaletteView::setPalette(Palette *palette) { d->model->setColorSet(palette->colorSet()); d->widget->setPaletteModel(d->model); } bool PaletteView::addEntryWithDialog(ManagedColor *color) { if (d->model->colorSet()) { return d->widget->addEntryWithDialog(color->color()); } return false; } bool PaletteView::addGroupWithDialog() { if (d->model->colorSet()) { // d->widget->addGroupWithDialog(); return false; } return false; } bool PaletteView::removeSelectedEntryWithDialog() { if (d->model->colorSet()) { return d->widget->removeEntryWithDialog(d->widget->currentIndex()); } return false; } void PaletteView::trySelectClosestColor(ManagedColor *color) { d->widget->trySelectClosestColor(color->color()); } diff --git a/libs/libkis/PaletteView.h b/libs/libkis/PaletteView.h index f0c81e7d56..3f3909befd 100644 --- a/libs/libkis/PaletteView.h +++ b/libs/libkis/PaletteView.h @@ -1,98 +1,98 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef LIBKIS_PALETTE_VIEW_H #define LIBKIS_PALETTE_VIEW_H #include #include #include "kritalibkis_export.h" #include "libkis.h" #include "Palette.h" #include "ManagedColor.h" #include "KoColorSet.h" #include #include /** * @brief The PaletteView class is a wrapper around a MVC method for handling * palettes. This class shows a nice widget that can drag and drop, edit colors in a colorset * and will handle adding and removing entries if you'd like it to. */ class KRITALIBKIS_EXPORT PaletteView : public QWidget { Q_OBJECT public: PaletteView(QWidget *parent = 0); ~PaletteView(); public Q_SLOTS: /** * @brief setPalette * Set a new palette. * @param palette */ void setPalette(Palette *palette); /** * @brief addEntryWithDialog * This gives a simple dialog for adding colors, with options like * adding name, id, and to which group the color should be added. * @param color the default color to add * @return whether it was successful. */ bool addEntryWithDialog(ManagedColor *color); /** * @brief addGroupWithDialog * gives a little dialog to ask for the desired groupname. * @return whether this was successful. */ bool addGroupWithDialog(); /** * @brief removeSelectedEntryWithDialog * removes the selected entry. If it is a group, it pop up a dialog * asking whether the colors should also be removed. * @return whether this was successful */ bool removeSelectedEntryWithDialog(); /** * @brief trySelectClosestColor * tries to select the closest color to the one given. * It does not force a change on the active color. * @param color the color to compare to. */ void trySelectClosestColor(ManagedColor *color); Q_SIGNALS: /** * @brief entrySelectedForeGround * fires when a swatch is selected with leftclick. * @param entry */ - void entrySelectedForeGround(KoColorSetEntry entry); + void entrySelectedForeGround(KisSwatch entry); /** * @brief entrySelectedBackGround * fires when a swatch is selected with rightclick. * @param entry */ - void entrySelectedBackGround(KoColorSetEntry entry); + void entrySelectedBackGround(KisSwatch entry); private: struct Private; const QScopedPointer d; }; #endif // LIBKIS_PALETTE_VIEW_H diff --git a/libs/pigment/resources/KisSwatchGroup.cpp b/libs/pigment/resources/KisSwatchGroup.cpp index c14af5e76c..3a17bbea51 100644 --- a/libs/pigment/resources/KisSwatchGroup.cpp +++ b/libs/pigment/resources/KisSwatchGroup.cpp @@ -1,122 +1,124 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt Copyright (c) 2016 L. E. Segovia Copyright (c) 2018 Michael Zhou This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KisSwatchGroup.h" quint32 KisSwatchGroup::DEFAULT_N_COLUMN = 16; KisSwatchGroup::KisSwatchGroup() : m_colorMatrix(DEFAULT_N_COLUMN) , m_nColors(0) , m_nLastRowEntries(0) { } void KisSwatchGroup::setEntry(const KisSwatch &e, int x, int y) { Q_ASSERT(x < m_colorMatrix.size() && x >= 0 && y >= 0); if (!checkEntry(x, y)) { m_nColors++; } m_colorMatrix[x][y] = e; } bool KisSwatchGroup::checkEntry(int x, int y) const { if (x >= m_colorMatrix.size() || x < 0) { return false; } if (!m_colorMatrix[x].contains(y)) { return false; } return true; } bool KisSwatchGroup::removeEntry(int x, int y) { if (m_nColors == 0) { return false; } if (x >= m_colorMatrix.size() || x < 0) { return false; } // QMap::remove returns 1 if key found else 0 if (m_colorMatrix[x].remove(y)) { m_nColors -= 1; return true; } else { return false; } } void KisSwatchGroup::setNColumns(int nColumns) { Q_ASSERT(nColumns >= 0); - Q_FOREACH (const Column &col, m_colorMatrix) { - m_nColors -= col.size(); + if (nColumns < m_colorMatrix.size()) { + for (int i = m_colorMatrix.size() - 1; i <= nColumns; i-- ) { + m_nColors -= m_colorMatrix[i].size(); + } } m_colorMatrix.resize(nColumns); } KisSwatch KisSwatchGroup::getEntry(int x, int y) const { Q_ASSERT(checkEntry(x, y)); return m_colorMatrix[x][y]; } int KisSwatchGroup::nRows() const { /* * shouldn't have too great a performance impact... * add a heap to keep track of last row if there is one */ int res = 0; Q_FOREACH (const Column &c, m_colorMatrix) { if (c.empty()) { continue; } res = res > c.lastKey() ? res : c.lastKey(); } return res + 1; } void KisSwatchGroup::addEntry(const KisSwatch &e) { if (nColumns() == 0) { setNColumns(DEFAULT_N_COLUMN); } int maxY = nRows() - 1; int y = maxY; for (int x = m_colorMatrix.size() - 1; x >= 0; x--) { if (checkEntry(x, maxY)) { // if the last entry's at the rightmost column, // add e to the leftmost column of the next row if (++x == m_colorMatrix.size()) { x = 0; y++; } // else just add it to the right setEntry(e, x, y); } } } diff --git a/libs/pigment/resources/KoColorSet.cpp b/libs/pigment/resources/KoColorSet.cpp index b6a0c5c5a8..e33ba422bf 100644 --- a/libs/pigment/resources/KoColorSet.cpp +++ b/libs/pigment/resources/KoColorSet.cpp @@ -1,482 +1,480 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt Copyright (c) 2016 L. E. Segovia This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "KoColor.h" #include "KoColorSet.h" #include "KisSwatch.h" #include "KoColorSet_p.h" KoColorSet::KoColorSet(const QString& filename) : KoResource(filename) , d(new Private(this)) { } /// Create an copied palette KoColorSet::KoColorSet(const KoColorSet& rhs) : QObject(0) , KoResource(QString()) , d(new Private(this)) { setFilename(rhs.filename()); d->comment = rhs.d->comment; - d->global = rhs.d->global; d->groupNames = rhs.d->groupNames; d->groups = rhs.d->groups; setValid(true); } KoColorSet::~KoColorSet() -{ -} +{ } bool KoColorSet::load() { QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnPigment << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoColorSet::loadFromDevice(QIODevice *dev) { if (!dev->isOpen()) dev->open(QIODevice::ReadOnly); d->data = dev->readAll(); Q_ASSERT(d->data.size() != 0); return d->init(); } bool KoColorSet::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } saveToDevice(&file); file.close(); return true; } bool KoColorSet::saveToDevice(QIODevice *dev) const { bool res; switch(d->paletteType) { case GPL: res = d->saveGpl(dev); break; default: res = d->saveKpl(dev); } if (res) { KoResource::saveToDevice(dev); } return res; } quint32 KoColorSet::nColors() { - return d->global.nColors(); + return d->groups[Private::GLOBAL_GROUP_NAME].nColors(); } quint32 KoColorSet::nColorsGroup(QString groupName) { if (d->groups.contains(groupName)) { return d->groups[groupName].nColors(); } else if (groupName.isEmpty()) { - return d->global.nColors(); + return d->groups[Private::GLOBAL_GROUP_NAME].nColors(); } else { return 0; } } QString KoColorSet::closestColorName(const KoColor color, bool useGivenColorSpace) { int closestX = 0, closestY = 0; quint8 highestPercentage = 0; quint8 testPercentage = 0; KoColor compare = color; QString res; - for (int x = 0; x < d->global.nColumns(); x++) { + for (int x = 0; x < d->groups[Private::GLOBAL_GROUP_NAME].nColumns(); x++) { for (int y = 0; y < rowCount(); y++ ) { KisSwatch entry = getColorGlobal(x, y); KoColor color = entry.color(); if (useGivenColorSpace == true && compare.colorSpace() != color.colorSpace()) { color.convertTo(compare.colorSpace()); } else if (compare.colorSpace() != color.colorSpace()) { compare.convertTo(color.colorSpace()); } testPercentage = (255 - compare.colorSpace()->difference(compare.data(), color.data())); if (testPercentage > highestPercentage) { res = entry.name(); highestPercentage = testPercentage; } } } return res; } void KoColorSet::add(KisSwatch c, const QString &groupName) { KisSwatchGroup &modifiedGroup = d->groups.contains(groupName) ? d->groups[groupName] : d->groups[QString()]; modifiedGroup.addEntry(c); } void KoColorSet::clear() { d->groups.clear(); d->groupNames.clear(); } KisSwatch KoColorSet::getColorGlobal(quint32 x, quint32 y) { KisSwatch e; int yInGroup = y; QString nameGroupFoundIn; for (const QString &groupName : d->groupNames) { if (yInGroup < d->groups[groupName].nRows()) { nameGroupFoundIn = groupName; break; } else { yInGroup -= d->groups[groupName].nRows(); } } - const KisSwatchGroup &groupFoundIn = nameGroupFoundIn == QString() - ? d->global : d->groups[nameGroupFoundIn]; + const KisSwatchGroup &groupFoundIn = d->groups[nameGroupFoundIn == QString() + ? Private::GLOBAL_GROUP_NAME : nameGroupFoundIn]; Q_ASSERT(groupFoundIn.checkEntry(x, yInGroup)); return groupFoundIn.getEntry(x, yInGroup); } KisSwatch KoColorSet::getColorGroup(quint32 x, quint32 y, QString groupName) { KisSwatch e; bool entryFound; const KisSwatchGroup &sourceGroup = d->groups.contains(groupName) ? d->groups[groupName] : d->groups[QString()]; // warnPigment << "Color group "<< groupName <<" not found"; entryFound = sourceGroup.checkEntry(x, y); if (entryFound) { e = sourceGroup.getEntry(x, y); } else { warnPigment << x << " " << y <<"doesn't exist in" << nColorsGroup(groupName); } return e; } QStringList KoColorSet::getGroupNames() { if (d->groupNames.size() != d->groups.size()) { warnPigment << "mismatch between groups and the groupnames list."; return QStringList(d->groups.keys()); } return d->groupNames; } bool KoColorSet::changeGroupName(QString oldGroupName, QString newGroupName) { if (d->groupNames.contains(oldGroupName)==false) { return false; } KisSwatchGroup tmp = d->groups.value(oldGroupName); d->groups.remove(oldGroupName); d->groups[newGroupName] = tmp; //rename the string in the stringlist; int index = d->groupNames.indexOf(oldGroupName); d->groupNames.replace(index, newGroupName); return true; } void KoColorSet::setColumnCount(int columns) { - d->global.setNColumns(columns); + d->groups[Private::GLOBAL_GROUP_NAME].setNColumns(columns); for (KisSwatchGroup &g : d->groups.values()) { // Q_FOREACH doesn't accept non const refs g.setNColumns(columns); } } int KoColorSet::columnCount() { - return d->global.nColumns(); + return d->groups[Private::GLOBAL_GROUP_NAME].nColumns(); } QString KoColorSet::comment() { return d->comment; } void KoColorSet::setComment(QString comment) { d->comment = comment; } bool KoColorSet::addGroup(const QString &groupName) { if (d->groups.contains(groupName) || d->groupNames.contains(groupName)) { return false; } d->groupNames.append(groupName); d->groups[groupName] = KisSwatchGroup(); return true; } bool KoColorSet::moveGroup(const QString &groupName, const QString &groupNameInsertBefore) { if (d->groupNames.contains(groupName)==false || d->groupNames.contains(groupNameInsertBefore)==false) { return false; } d->groupNames.removeAt(d->groupNames.indexOf(groupName)); int index = d->groupNames.size(); if (groupNameInsertBefore!=QString()) { index = d->groupNames.indexOf(groupNameInsertBefore); } d->groupNames.insert(index, groupName); return true; } bool KoColorSet::removeGroup(const QString &groupName, bool keepColors) { if (!d->groups.contains(groupName)) { return false; } if (keepColors) { // put all colors directly below global - int startingRow = d->global.nRows(); + int startingRow = d->groups[Private::GLOBAL_GROUP_NAME].nRows(); for (int x = 0; x < d->groups[groupName].nColumns(); x++) { for (int y = 0; y < d->groups[groupName].nRows(); y++) { if (d->groups[groupName].checkEntry(x, y)) { - d->global.setEntry(d->groups[groupName].getEntry(x, y), + d->groups[Private::GLOBAL_GROUP_NAME].setEntry(d->groups[groupName].getEntry(x, y), x, y + startingRow); } } } } for (int n = 0; ngroupNames.size(); n++) { if (d->groupNames.at(n) == groupName) { d->groupNames.removeAt(n); } } d->groups.remove(groupName); return true; } QString KoColorSet::defaultFileExtension() const { return QString(".kpl"); } int KoColorSet::rowCount() { - int res = d->global.nRows(); + int res = d->groups[Private::GLOBAL_GROUP_NAME].nRows(); Q_FOREACH (QString name, d->groupNames) { res += d->groups[name].nRows(); } return res; } /* QString KoColorSet::findGroupByGlobalIndex(quint32 x, quint32 y) { *index = globalIndex; QString groupName = QString(); if ((quint32)d->colors.size()<=*index) { *index -= (quint32)d->colors.size(); if (!d->groups.empty() || !d->groupNames.empty()) { QStringList groupNames = getGroupNames(); Q_FOREACH (QString name, groupNames) { quint32 size = (quint32)d->groups.value(name).size(); if (size<=*index) { *index -= size; } else { groupName = name; return groupName; } } } } return groupName; } QString KoColorSet::findGroupByColorName(const QString &name, quint32 *x, quint32 *y) { QString groupName = QString(); Q_FOREACH (const KisSwatchGroup::Column & col, d->global.colors()) { Q_FOREACH (const KisSwatch & entry, col.values()) { if (entry.name() == name) { *x = static_cast(entry.x()); *y = static_cast(entry.y()); return groupName; } } } QStringList groupNames = getGroupNames(); Q_FOREACH (QString name, groupNames) { Q_FOREACH (const KisSwatchGroup::Column & col, d->groups[name].colors()) { Q_FOREACH (const KisSwatch & entry, col.values()) { if (entry.name() == name) { *x = static_cast(entry.x()); *y = static_cast(entry.y()); return groupName; } } } } return groupName; } QString KoColorSet::findGroupByID(const QString &id, quint32 *index) { *index = 0; QString groupName = QString(); for (int i = 0; icolors.size(); i++) { if(d->colors.at(i).id() == id) { *index = (quint32)i; return groupName; } } QStringList groupNames = getGroupNames(); Q_FOREACH (QString name, groupNames) { for (int i=0; igroups[name].size(); i++) { if(d->groups[name].at(i).id() == id) { *index = (quint32)i; groupName = name; return groupName; } } } return groupName; return QString(); } const KisSwatchGroup &KoColorSet::getGroupByName(const QString &groupName, bool &success) const { if (groupName.isEmpty()) { success = true; return d->global; } if (d->groupNames.contains(groupName)) { success = true; return d->groups[groupName]; } success = false; return d->global; } bool KoColorSet::changeColorSetEntry(KisSwatch entry, QString groupName) { if (!d->groupNames.contains(groupName)) { return false; } if (groupName.isEmpty()) { d->global.setEntry(entry); } else { d->groups[groupName].setEntry(entry); } return true; } quint32 KoColorSet::getIndexClosestColor(const KoColor color, bool useGivenColorSpace) { quint32 closestIndex = 0; quint8 highestPercentage = 0; quint8 testPercentage = 0; KoColor compare = color; for (quint32 i=0; i < nColors(); i++) { KoColor entry = getColorGlobal(i).color(); if (useGivenColorSpace == true && compare.colorSpace() != entry.colorSpace()) { entry.convertTo(compare.colorSpace()); } else if(compare.colorSpace()!=entry.colorSpace()) { compare.convertTo(entry.colorSpace()); } testPercentage = (255 - compare.colorSpace()->difference(compare.data(), entry.data())); if (testPercentage>highestPercentage) { closestIndex = i; highestPercentage = testPercentage; } } return closestIndex; } void KoColorSet::removeAt(quint32 x, quint32 y, QString groupName) { if (d->groups.contains(groupName)){ if ((quint32)d->groups.value(groupName).size()>x) { d->groups[groupName].remove(x); } } else { if ((quint32)d->colors.size()>x) { d->colors.remove(x); } } if (x >= d->columns || x < 0) return; if (d->groups.contains(groupName)){ d->groups[groupName].removeEntry(x, y); } else { d->global.removeEntry(x, y); } } quint32 KoColorSet::insertBefore(const KisSwatch &c, qint32 index, const QString &groupName) { quint32 newIndex = index; if (d->groups.contains(groupName)) { d->groups[groupName].insert(index, c); } else if (groupName.isEmpty()){ d->colors.insert(index, c); } else { warnPigment << "Couldn't find group to insert to"; } return newIndex; return 0; } */ diff --git a/libs/pigment/resources/KoColorSet_p.cpp b/libs/pigment/resources/KoColorSet_p.cpp index e28d9a5ee0..cd9866192e 100644 --- a/libs/pigment/resources/KoColorSet_p.cpp +++ b/libs/pigment/resources/KoColorSet_p.cpp @@ -1,1137 +1,1136 @@ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // qFromLittleEndian #include #include #include #include #include #include #include #include #include #include "KoColorSet_p.h" QString KoColorSet::Private::GLOBAL_GROUP_NAME = QString(); KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba) { QFileInfo fi(fileName); // .pal if (ba.startsWith("RIFF") && ba.indexOf("PAL data", 8)) { return KoColorSet::RIFF_PAL; } // .gpl else if (ba.startsWith("GIMP Palette")) { return KoColorSet::GPL; } // .pal else if (ba.startsWith("JASC-PAL")) { return KoColorSet::PSP_PAL; } else if (fi.suffix().toLower() == "aco") { return KoColorSet::ACO; } else if (fi.suffix().toLower() == "act") { return KoColorSet::ACT; } else if (fi.suffix().toLower() == "xml") { return KoColorSet::XML; } else if (fi.suffix().toLower() == "kpl") { return KoColorSet::KPL; } else if (fi.suffix().toLower() == "sbz") { return KoColorSet::SBZ; } return KoColorSet::UNKNOWN; } void scribusParseColor(KoColorSet *set, QXmlStreamReader *xml) { KisSwatch colorEntry; // It's a color, retrieve it QXmlStreamAttributes colorProperties = xml->attributes(); QStringRef colorName = colorProperties.value("NAME"); colorEntry.setName(colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString()); // RGB or CMYK? if (colorProperties.hasAttribute("RGB")) { dbgPigment << "Color " << colorProperties.value("NAME") << ", RGB " << colorProperties.value("RGB"); KoColor currentColor(KoColorSpaceRegistry::instance()->rgb8()); QStringRef colorValue = colorProperties.value("RGB"); if (colorValue.length() != 7 && colorValue.at(0) != '#') { // Color is a hexadecimal number xml->raiseError("Invalid rgb8 color (malformed): " + colorValue); return; } else { bool rgbOk; quint32 rgb = colorValue.mid(1).toUInt(&rgbOk, 16); if (!rgbOk) { xml->raiseError("Invalid rgb8 color (unable to convert): " + colorValue); return; } quint8 r = rgb >> 16 & 0xff; quint8 g = rgb >> 8 & 0xff; quint8 b = rgb & 0xff; dbgPigment << "Color parsed: "<< r << g << b; currentColor.data()[0] = r; currentColor.data()[1] = g; currentColor.data()[2] = b; currentColor.setOpacity(OPACITY_OPAQUE_U8); colorEntry.setColor(currentColor); set->add(colorEntry); while(xml->readNextStartElement()) { //ignore - these are all unknown or the /> element tag xml->skipCurrentElement(); } return; } } else if (colorProperties.hasAttribute("CMYK")) { dbgPigment << "Color " << colorProperties.value("NAME") << ", CMYK " << colorProperties.value("CMYK"); KoColor currentColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer8BitsColorDepthID.id(), QString())); QStringRef colorValue = colorProperties.value("CMYK"); if (colorValue.length() != 9 && colorValue.at(0) != '#') { // Color is a hexadecimal number xml->raiseError("Invalid cmyk color (malformed): " % colorValue); return; } else { bool cmykOk; quint32 cmyk = colorValue.mid(1).toUInt(&cmykOk, 16); // cmyk uses the full 32 bits if (!cmykOk) { xml->raiseError("Invalid cmyk color (unable to convert): " % colorValue); return; } quint8 c = cmyk >> 24 & 0xff; quint8 m = cmyk >> 16 & 0xff; quint8 y = cmyk >> 8 & 0xff; quint8 k = cmyk & 0xff; dbgPigment << "Color parsed: "<< c << m << y << k; currentColor.data()[0] = c; currentColor.data()[1] = m; currentColor.data()[2] = y; currentColor.data()[3] = k; currentColor.setOpacity(OPACITY_OPAQUE_U8); colorEntry.setColor(currentColor); set->add(colorEntry); while(xml->readNextStartElement()) { //ignore - these are all unknown or the /> element tag xml->skipCurrentElement(); } return; } } else { xml->raiseError("Unknown color space for color " + colorEntry.name()); } } bool loadScribusXmlPalette(KoColorSet *set, QXmlStreamReader *xml) { //1. Get name QXmlStreamAttributes paletteProperties = xml->attributes(); QStringRef paletteName = paletteProperties.value("Name"); dbgPigment << "Processed name of palette:" << paletteName; set->setName(paletteName.toString()); //2. Inside the SCRIBUSCOLORS, there are lots of colors. Retrieve them while(xml->readNextStartElement()) { QStringRef currentElement = xml->name(); if(QStringRef::compare(currentElement, "COLOR", Qt::CaseInsensitive) == 0) { scribusParseColor(set, xml); } else { xml->skipCurrentElement(); } } if(xml->hasError()) { return false; } return true; } quint16 readShort(QIODevice *io) { quint16 val; quint64 read = io->read((char*)&val, 2); if (read != 2) return false; return qFromBigEndian(val); } KoColorSet::Private::Private(KoColorSet *a_colorSet) : colorSet(a_colorSet) - , global(groups[GLOBAL_GROUP_NAME]) { - + groups[GLOBAL_GROUP_NAME] = KisSwatchGroup(); } bool KoColorSet::Private::init() { // global.clear(); // just in case this is a reload (eg by KoEditColorSetDialog), groups.clear(); groupNames.clear(); if (colorSet->filename().isNull()) { warnPigment << "Cannot load palette" << colorSet->name() << "there is no filename set"; return false; } if (data.isNull()) { QFile file(colorSet->filename()); if (file.size() == 0) { warnPigment << "Cannot load palette" << colorSet->name() << "there is no data available"; return false; } file.open(QIODevice::ReadOnly); data = file.readAll(); file.close(); } bool res = false; paletteType = detectFormat(colorSet->filename(), data); switch(paletteType) { case GPL: res = loadGpl(); break; case ACT: res = loadAct(); break; case RIFF_PAL: res = loadRiff(); break; case PSP_PAL: res = loadPsp(); break; case ACO: res = loadAco(); break; case XML: res = loadXml(); break; case KPL: res = loadKpl(); break; case SBZ: res = loadSbz(); break; default: res = false; } colorSet->setValid(res); - QImage img(global.nColumns() * 4, global.nRows() * 4, QImage::Format_ARGB32); + QImage img(groups[GLOBAL_GROUP_NAME].nColumns() * 4, groups[GLOBAL_GROUP_NAME].nRows() * 4, QImage::Format_ARGB32); QPainter gc(&img); gc.fillRect(img.rect(), Qt::darkGray); - for (int x = 0; x < global.nColumns(); x++) { - for (int y = 0; y < global.nRows(); y++) { - QColor c = global.getEntry(x, y).color().toQColor(); + for (int x = 0; x < groups[GLOBAL_GROUP_NAME].nColumns(); x++) { + for (int y = 0; y < groups[GLOBAL_GROUP_NAME].nRows(); y++) { + QColor c = groups[GLOBAL_GROUP_NAME].getEntry(x, y).color().toQColor(); gc.fillRect(x * 4, y * 4, 4, 4, c); } } colorSet->setImage(img); // save some memory data.clear(); return res; } bool KoColorSet::Private::saveGpl(QIODevice *dev) const { QTextStream stream(dev); int columns = 0; stream << "GIMP Palette\nName: " << colorSet->name() << "\nColumns: " << columns << "\n#\n"; - for (int y = 0; y < global.nRows(); y++) { + for (int y = 0; y < groups[GLOBAL_GROUP_NAME].nRows(); y++) { for (int x = 0; x < columns; x++) { - if (!global.checkEntry(x, y)) { + if (!groups[GLOBAL_GROUP_NAME].checkEntry(x, y)) { continue; } - const KisSwatch& entry = global.getEntry(x, y); + const KisSwatch& entry = groups[GLOBAL_GROUP_NAME].getEntry(x, y); QColor c = entry.color().toQColor(); stream << c.red() << " " << c.green() << " " << c.blue() << "\t"; if (entry.name().isEmpty()) stream << "Untitled\n"; else stream << entry.name() << "\n"; } } return true; } bool KoColorSet::Private::loadGpl() { QString s = QString::fromUtf8(data.data(), data.count()); if (s.isEmpty() || s.isNull() || s.length() < 50) { warnPigment << "Illegal Gimp palette file: " << colorSet->filename(); return false; } quint32 index = 0; QStringList lines = s.split('\n', QString::SkipEmptyParts); if (lines.size() < 3) { warnPigment << "Not enough lines in palette file: " << colorSet->filename(); return false; } QString columnsText; qint32 r, g, b; KisSwatch e; // Read name if (!lines[0].startsWith("GIMP") || !lines[1].toLower().contains("name")) { warnPigment << "Illegal Gimp palette file: " << colorSet->filename(); return false; } colorSet->setName(i18n(lines[1].split(":")[1].trimmed().toLatin1())); index = 2; // Read columns int columns = 0; if (lines[index].toLower().contains("columns")) { columnsText = lines[index].split(":")[1].trimmed(); columns = columnsText.toInt(); - global.setNColumns(columns); + groups[GLOBAL_GROUP_NAME].setNColumns(columns); index = 3; } int x = 0, y = 0; for (qint32 i = index; i < lines.size(); i++) { if (lines[i].startsWith('#')) { comment += lines[i].mid(1).trimmed() + ' '; } else if (!lines[i].isEmpty()) { QStringList a = lines[i].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() < 3) { break; } r = qBound(0, a[0].toInt(), 255); g = qBound(0, a[1].toInt(), 255); b = qBound(0, a[2].toInt(), 255); e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); QString name = a.join(" "); e.setName(name.isEmpty() ? i18n("Untitled") : name); - global.addEntry(e); + groups[GLOBAL_GROUP_NAME].addEntry(e); } } return true; } bool KoColorSet::Private::loadAct() { QFileInfo info(colorSet->filename()); colorSet->setName(info.baseName()); KisSwatch e; for (int i = 0; i < data.size(); i += 3) { quint8 r = data[i]; quint8 g = data[i+1]; quint8 b = data[i+2]; e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); - global.addEntry(e); + groups[GLOBAL_GROUP_NAME].addEntry(e); } return true; } bool KoColorSet::Private::loadRiff() { // http://worms2d.info/Palette_file QFileInfo info(colorSet->filename()); colorSet->setName(info.baseName()); KisSwatch e; RiffHeader header; memcpy(&header, data.constData(), sizeof(RiffHeader)); header.colorcount = qFromBigEndian(header.colorcount); for (int i = sizeof(RiffHeader); (i < (int)(sizeof(RiffHeader) + header.colorcount) && i < data.size()); i += 4) { quint8 r = data[i]; quint8 g = data[i+1]; quint8 b = data[i+2]; e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); - global.addEntry(e); + groups[GLOBAL_GROUP_NAME].addEntry(e); } return true; } bool KoColorSet::Private::loadPsp() { QFileInfo info(colorSet->filename()); colorSet->setName(info.baseName()); KisSwatch e; qint32 r, g, b; QString s = QString::fromUtf8(data.data(), data.count()); QStringList l = s.split('\n', QString::SkipEmptyParts); if (l.size() < 4) return false; if (l[0] != "JASC-PAL") return false; if (l[1] != "0100") return false; int entries = l[2].toInt(); for (int i = 0; i < entries; ++i) { QStringList a = l[i + 3].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() != 3) { continue; } r = qBound(0, a[0].toInt(), 255); g = qBound(0, a[1].toInt(), 255); b = qBound(0, a[2].toInt(), 255); e.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8())); QString name = a.join(" "); e.setName(name.isEmpty() ? i18n("Untitled") : name); - global.addEntry(e); + groups[GLOBAL_GROUP_NAME].addEntry(e); } return true; } bool KoColorSet::Private::loadKpl() { QBuffer buf(&data); buf.open(QBuffer::ReadOnly); QScopedPointer store(KoStore::createStore(&buf, KoStore::Read, "application/x-krita-palette", KoStore::Zip)); if (!store || store->bad()) return false; if (store->hasFile("profiles.xml")) { if (!store->open("profiles.xml")) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); QDomDocument doc; doc.setContent(ba); QDomElement e = doc.documentElement(); QDomElement c = e.firstChildElement("Profiles"); while (!c.isNull()) { QString name = c.attribute("name"); QString filename = c.attribute("filename"); QString colorModelId = c.attribute("colorModelId"); QString colorDepthId = c.attribute("colorDepthId"); if (!KoColorSpaceRegistry::instance()->profileByName(name)) { store->open(filename); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(colorModelId, colorDepthId, data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); } } c = c.nextSiblingElement(); } } { if (!store->open("colorset.xml")) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); QDomDocument doc; doc.setContent(ba); QDomElement e = doc.documentElement(); colorSet->setName(e.attribute("name")); colorSet->setColumnCount(e.attribute("columns").toInt()); comment = e.attribute("comment"); QDomElement c = e.firstChildElement("ColorSetEntry"); while (!c.isNull()) { QString colorDepthId = c.attribute("bitdepth", Integer8BitsColorDepthID.id()); KisSwatch entry; entry.setColor(KoColor::fromXML(c.firstChildElement(), colorDepthId)); entry.setName(c.attribute("name")); entry.setId(c.attribute("id")); entry.setSpotColor(c.attribute("spot", "false") == "true" ? true : false); - global.addEntry(entry); + groups[GLOBAL_GROUP_NAME].addEntry(entry); c = c.nextSiblingElement("ColorSetEntry"); } QDomElement g = e.firstChildElement("Group"); while (!g.isNull()) { QString groupName = g.attribute("name"); colorSet->addGroup(groupName); QDomElement cg = g.firstChildElement("ColorSetEntry"); while (!cg.isNull()) { QString colorDepthId = cg.attribute("bitdepth", Integer8BitsColorDepthID.id()); KisSwatch entry; entry.setColor(KoColor::fromXML(cg.firstChildElement(), colorDepthId)); entry.setName(cg.attribute("name")); entry.setId(cg.attribute("id")); entry.setSpotColor(cg.attribute("spot", "false") == "true" ? true : false); groups[groupName].addEntry(entry); cg = cg.nextSiblingElement("ColorSetEntry"); } g = g.nextSiblingElement("Group"); } } buf.close(); return true; } bool KoColorSet::Private::loadAco() { QFileInfo info(colorSet->filename()); colorSet->setName(info.baseName()); QBuffer buf(&data); buf.open(QBuffer::ReadOnly); quint16 version = readShort(&buf); quint16 numColors = readShort(&buf); KisSwatch e; if (version == 1 && buf.size() > 4+numColors*10) { buf.seek(4+numColors*10); version = readShort(&buf); numColors = readShort(&buf); } const quint16 quint16_MAX = 65535; for (int i = 0; i < numColors && !buf.atEnd(); ++i) { quint16 colorSpace = readShort(&buf); quint16 ch1 = readShort(&buf); quint16 ch2 = readShort(&buf); quint16 ch3 = readShort(&buf); quint16 ch4 = readShort(&buf); bool skip = false; if (colorSpace == 0) { // RGB const KoColorProfile *srgb = KoColorSpaceRegistry::instance()->rgb8()->profile(); KoColor c(KoColorSpaceRegistry::instance()->rgb16(srgb)); reinterpret_cast(c.data())[0] = ch3; reinterpret_cast(c.data())[1] = ch2; reinterpret_cast(c.data())[2] = ch1; c.setOpacity(OPACITY_OPAQUE_U8); e.setColor(c); } else if (colorSpace == 1) { // HSB QColor qc; qc.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0); KoColor c(qc, KoColorSpaceRegistry::instance()->rgb16()); c.setOpacity(OPACITY_OPAQUE_U8); e.setColor(c); } else if (colorSpace == 2) { // CMYK KoColor c(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); reinterpret_cast(c.data())[0] = quint16_MAX - ch1; reinterpret_cast(c.data())[1] = quint16_MAX - ch2; reinterpret_cast(c.data())[2] = quint16_MAX - ch3; reinterpret_cast(c.data())[3] = quint16_MAX - ch4; c.setOpacity(OPACITY_OPAQUE_U8); e.setColor(c); } else if (colorSpace == 7) { // LAB KoColor c = KoColor(KoColorSpaceRegistry::instance()->lab16()); reinterpret_cast(c.data())[0] = ch3; reinterpret_cast(c.data())[1] = ch2; reinterpret_cast(c.data())[2] = ch1; c.setOpacity(OPACITY_OPAQUE_U8); e.setColor(c); } else if (colorSpace == 8) { // GRAY KoColor c(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), QString())); reinterpret_cast(c.data())[0] = ch1 * (quint16_MAX / 10000); c.setOpacity(OPACITY_OPAQUE_U8); e.setColor(c); } else { warnPigment << "Unsupported colorspace in palette" << colorSet->filename() << "(" << colorSpace << ")"; skip = true; } if (version == 2) { quint16 v2 = readShort(&buf); //this isn't a version, it's a marker and needs to be skipped. Q_UNUSED(v2); quint16 size = readShort(&buf) -1; //then comes the length if (size>0) { QByteArray ba = buf.read(size*2); if (ba.size() == size*2) { QTextCodec *Utf16Codec = QTextCodec::codecForName("UTF-16BE"); e.setName(Utf16Codec->toUnicode(ba)); } else { warnPigment << "Version 2 name block is the wrong size" << colorSet->filename(); } } v2 = readShort(&buf); //end marker also needs to be skipped. Q_UNUSED(v2); } if (!skip) { - global.addEntry(e); + groups[GLOBAL_GROUP_NAME].addEntry(e); } } return true; } bool KoColorSet::Private::loadSbz() { QBuffer buf(&data); buf.open(QBuffer::ReadOnly); // &buf is a subclass of QIODevice QScopedPointer store(KoStore::createStore(&buf, KoStore::Read, "application/x-swatchbook", KoStore::Zip)); if (!store || store->bad()) return false; if (store->hasFile("swatchbook.xml")) { // Try opening... if (!store->open("swatchbook.xml")) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); dbgPigment << "XML palette: " << colorSet->filename() << ", SwatchBooker format"; QDomDocument doc; int errorLine, errorColumn; QString errorMessage; bool status = doc.setContent(ba, &errorMessage, &errorLine, &errorColumn); if (!status) { warnPigment << "Illegal XML palette:" << colorSet->filename(); warnPigment << "Error (line" << errorLine << ", column" << errorColumn << "):" << errorMessage; return false; } QDomElement e = doc.documentElement(); // SwatchBook // Start reading properties... QDomElement metadata = e.firstChildElement("metadata"); if (e.isNull()) { warnPigment << "Palette metadata not found"; return false; } QDomElement title = metadata.firstChildElement("dc:title"); QString colorName = title.text(); colorName = colorName.isEmpty() ? i18n("Untitled") : colorName; colorSet->setName(colorName); dbgPigment << "Processed name of palette:" << colorSet->name(); // End reading properties // Now read colors... QDomElement materials = e.firstChildElement("materials"); if (materials.isNull()) { warnPigment << "Materials (color definitions) not found"; return false; } // This one has lots of "color" elements QDomElement colorElement = materials.firstChildElement("color"); if (colorElement.isNull()) { warnPigment << "Color definitions not found (line" << materials.lineNumber() << ", column" << materials.columnNumber() << ")"; return false; } // Also read the swatch book... QDomElement book = e.firstChildElement("book"); if (book.isNull()) { warnPigment << "Palette book (swatch composition) not found (line" << e.lineNumber() << ", column" << e.columnNumber() << ")"; return false; } // Which has lots of "swatch"es (todo: support groups) QDomElement swatch = book.firstChildElement(); if (swatch.isNull()) { warnPigment << "Swatches/groups definition not found (line" << book.lineNumber() << ", column" << book.columnNumber() << ")"; return false; } // We'll store colors here, and as we process swatches // we'll add them to the palette QHash materialsBook; QHash fileColorSpaces; // Color processing for(; !colorElement.isNull(); colorElement = colorElement.nextSiblingElement("color")) { KisSwatch currentEntry; // Set if color is spot currentEntry.setSpotColor(colorElement.attribute("usage") == "spot"); // inside contains id and name // one or more define the color QDomElement currentColorMetadata = colorElement.firstChildElement("metadata"); QDomNodeList currentColorValues = colorElement.elementsByTagName("values"); // Get color name QDomElement colorTitle = currentColorMetadata.firstChildElement("dc:title"); QDomElement colorId = currentColorMetadata.firstChildElement("dc:identifier"); // Is there an id? (we need that at the very least for identifying a color) if (colorId.text().isEmpty()) { warnPigment << "Unidentified color (line" << colorId.lineNumber()<< ", column" << colorId.columnNumber() << ")"; return false; } if (materialsBook.contains(colorId.text())) { warnPigment << "Duplicated color definition (line" << colorId.lineNumber()<< ", column" << colorId.columnNumber() << ")"; return false; } // Get a valid color name currentEntry.setId(colorId.text()); currentEntry.setName(colorTitle.text().isEmpty() ? colorId.text() : colorTitle.text()); // Get a valid color definition if (currentColorValues.isEmpty()) { warnPigment << "Color definitions not found (line" << colorElement.lineNumber() << ", column" << colorElement.columnNumber() << ")"; return false; } bool firstDefinition = false; const KoColorProfile *srgb = KoColorSpaceRegistry::instance()->rgb8()->profile(); // Priority: Lab, otherwise the first definition found for(int j = 0; j < currentColorValues.size(); j++) { QDomNode colorValue = currentColorValues.at(j); QDomElement colorValueE = colorValue.toElement(); QString model = colorValueE.attribute("model", QString()); // sRGB,RGB,HSV,HSL,CMY,CMYK,nCLR: 0 -> 1 // YIQ: Y 0 -> 1 : IQ -0.5 -> 0.5 // Lab: L 0 -> 100 : ab -128 -> 127 // XYZ: 0 -> ~100 if (model == "Lab") { QStringList lab = colorValueE.text().split(" "); if (lab.length() != 3) { warnPigment << "Invalid Lab color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float l = lab.at(0).toFloat(&status); float a = lab.at(1).toFloat(&status); float b = lab.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } KoColor c(KoColorSpaceRegistry::instance()->colorSpace(LABAColorModelID.id(), Float32BitsColorDepthID.id(), QString())); reinterpret_cast(c.data())[0] = l; reinterpret_cast(c.data())[1] = a; reinterpret_cast(c.data())[2] = b; c.setOpacity(OPACITY_OPAQUE_F); firstDefinition = true; currentEntry.setColor(c); break; // Immediately add this one } else if (model == "sRGB" && !firstDefinition) { QStringList rgb = colorValueE.text().split(" "); if (rgb.length() != 3) { warnPigment << "Invalid sRGB color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float r = rgb.at(0).toFloat(&status); float g = rgb.at(1).toFloat(&status); float b = rgb.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } KoColor c(KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), srgb)); reinterpret_cast(c.data())[0] = r; reinterpret_cast(c.data())[1] = g; reinterpret_cast(c.data())[2] = b; c.setOpacity(OPACITY_OPAQUE_F); currentEntry.setColor(c); firstDefinition = true; } else if (model == "XYZ" && !firstDefinition) { QStringList xyz = colorValueE.text().split(" "); if (xyz.length() != 3) { warnPigment << "Invalid XYZ color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float x = xyz.at(0).toFloat(&status); float y = xyz.at(1).toFloat(&status); float z = xyz.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } KoColor c(KoColorSpaceRegistry::instance()->colorSpace(XYZAColorModelID.id(), Float32BitsColorDepthID.id(), QString())); reinterpret_cast(c.data())[0] = x; reinterpret_cast(c.data())[1] = y; reinterpret_cast(c.data())[2] = z; c.setOpacity(OPACITY_OPAQUE_F); currentEntry.setColor(c); firstDefinition = true; } // The following color spaces admit an ICC profile (in SwatchBooker) else if (model == "CMYK" && !firstDefinition) { QStringList cmyk = colorValueE.text().split(" "); if (cmyk.length() != 4) { warnPigment << "Invalid CMYK color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float c = cmyk.at(0).toFloat(&status); float m = cmyk.at(1).toFloat(&status); float y = cmyk.at(2).toFloat(&status); float k = cmyk.at(3).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } QString space = colorValueE.attribute("space"); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), QString()); if (!space.isEmpty()) { // Try loading the profile and add it to the registry if (!fileColorSpaces.contains(space)) { store->enterDirectory("profiles"); store->open(space); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); colorSpace = KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), profile); fileColorSpaces.insert(space, colorSpace); } } else { colorSpace = fileColorSpaces.value(space); } } KoColor color(colorSpace); reinterpret_cast(color.data())[0] = c; reinterpret_cast(color.data())[1] = m; reinterpret_cast(color.data())[2] = y; reinterpret_cast(color.data())[3] = k; color.setOpacity(OPACITY_OPAQUE_F); currentEntry.setColor(color); firstDefinition = true; } else if (model == "GRAY" && !firstDefinition) { QString gray = colorValueE.text(); float g = gray.toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } QString space = colorValueE.attribute("space"); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Float32BitsColorDepthID.id(), QString()); if (!space.isEmpty()) { // Try loading the profile and add it to the registry if (!fileColorSpaces.contains(space)) { store->enterDirectory("profiles"); store->open(space); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); colorSpace = KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Float32BitsColorDepthID.id(), profile); fileColorSpaces.insert(space, colorSpace); } } else { colorSpace = fileColorSpaces.value(space); } } KoColor c(colorSpace); reinterpret_cast(c.data())[0] = g; c.setOpacity(OPACITY_OPAQUE_F); currentEntry.setColor(c); firstDefinition = true; } else if (model == "RGB" && !firstDefinition) { QStringList rgb = colorValueE.text().split(" "); if (rgb.length() != 3) { warnPigment << "Invalid RGB color definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } float r = rgb.at(0).toFloat(&status); float g = rgb.at(1).toFloat(&status); float b = rgb.at(2).toFloat(&status); if (!status) { warnPigment << "Invalid float definition (line" << colorValueE.lineNumber() << ", column" << colorValueE.columnNumber() << ")"; } QString space = colorValueE.attribute("space"); const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), srgb); if (!space.isEmpty()) { // Try loading the profile and add it to the registry if (!fileColorSpaces.contains(space)) { store->enterDirectory("profiles"); store->open(space); QByteArray data; data.resize(store->size()); data = store->read(store->size()); store->close(); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), data); if (profile && profile->valid()) { KoColorSpaceRegistry::instance()->addProfile(profile); colorSpace = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), profile); fileColorSpaces.insert(space, colorSpace); } } else { colorSpace = fileColorSpaces.value(space); } } KoColor c(colorSpace); reinterpret_cast(c.data())[0] = r; reinterpret_cast(c.data())[1] = g; reinterpret_cast(c.data())[2] = b; c.setOpacity(OPACITY_OPAQUE_F); currentEntry.setColor(c); firstDefinition = true; } else { warnPigment << "Color space not implemented:" << model << "(line" << colorValueE.lineNumber() << ", column "<< colorValueE.columnNumber() << ")"; } } if (firstDefinition) { materialsBook.insert(currentEntry.id(), currentEntry); } else { warnPigment << "No supported color spaces for the current color (line" << colorElement.lineNumber() << ", column "<< colorElement.columnNumber() << ")"; return false; } } // End colors // Now decide which ones will go into the palette for(;!swatch.isNull(); swatch = swatch.nextSiblingElement()) { QString type = swatch.tagName(); if (type.isEmpty() || type.isNull()) { warnPigment << "Invalid swatch/group definition (no id) (line" << swatch.lineNumber() << ", column" << swatch.columnNumber() << ")"; return false; } else if (type == "swatch") { QString id = swatch.attribute("material"); if (id.isEmpty() || id.isNull()) { warnPigment << "Invalid swatch definition (no material id) (line" << swatch.lineNumber() << ", column" << swatch.columnNumber() << ")"; return false; } if (materialsBook.contains(id)) { - global.addEntry(materialsBook.value(id)); + groups[GLOBAL_GROUP_NAME].addEntry(materialsBook.value(id)); } else { warnPigment << "Invalid swatch definition (material not found) (line" << swatch.lineNumber() << ", column" << swatch.columnNumber() << ")"; return false; } } else if (type == "group") { QDomElement groupMetadata = swatch.firstChildElement("metadata"); if (groupMetadata.isNull()) { warnPigment << "Invalid group definition (missing metadata) (line" << groupMetadata.lineNumber() << ", column" << groupMetadata.columnNumber() << ")"; return false; } QDomElement groupTitle = metadata.firstChildElement("dc:title"); if (groupTitle.isNull()) { warnPigment << "Invalid group definition (missing title) (line" << groupTitle.lineNumber() << ", column" << groupTitle.columnNumber() << ")"; return false; } QString currentGroupName = groupTitle.text(); QDomElement groupSwatch = swatch.firstChildElement("swatch"); while(!groupSwatch.isNull()) { QString id = groupSwatch.attribute("material"); if (id.isEmpty() || id.isNull()) { warnPigment << "Invalid swatch definition (no material id) (line" << groupSwatch.lineNumber() << ", column" << groupSwatch.columnNumber() << ")"; return false; } if (materialsBook.contains(id)) { groups[currentGroupName].addEntry(materialsBook.value(id)); } else { warnPigment << "Invalid swatch definition (material not found) (line" << groupSwatch.lineNumber() << ", column" << groupSwatch.columnNumber() << ")"; return false; } groupSwatch = groupSwatch.nextSiblingElement("swatch"); } } } // End palette } buf.close(); return true; } bool KoColorSet::Private::loadXml() { bool res = false; QXmlStreamReader *xml = new QXmlStreamReader(data); if (xml->readNextStartElement()) { QStringRef paletteId = xml->name(); if (QStringRef::compare(paletteId, "SCRIBUSCOLORS", Qt::CaseInsensitive) == 0) { // Scribus dbgPigment << "XML palette: " << colorSet->filename() << ", Scribus format"; res = loadScribusXmlPalette(colorSet, xml); } else { // Unknown XML format xml->raiseError("Unknown XML palette format. Expected SCRIBUSCOLORS, found " + paletteId); } } // If there is any error (it should be returned through the stream) if (xml->hasError() || !res) { warnPigment << "Illegal XML palette:" << colorSet->filename(); warnPigment << "Error (line"<< xml->lineNumber() << ", column" << xml->columnNumber() << "):" << xml->errorString(); return false; } else { dbgPigment << "XML palette parsed successfully:" << colorSet->filename(); return true; } } bool KoColorSet::Private::saveKpl(QIODevice *dev) const { QScopedPointer store(KoStore::createStore(dev, KoStore::Write, "application/x-krita-palette", KoStore::Zip)); if (!store || store->bad()) return false; QSet profiles; QMap profileMap; { QDomDocument doc; QDomElement root = doc.createElement("Colorset"); root.setAttribute("version", "1.0"); root.setAttribute("name", colorSet->name()); root.setAttribute("comment", comment); - root.setAttribute("columns", global.nColumns()); - for (int x = 0; x < global.nColumns(); x++) { - for (int y = 0; y < global.nRows(); y++) { + root.setAttribute("columns", groups[GLOBAL_GROUP_NAME].nColumns()); + for (int x = 0; x < groups[GLOBAL_GROUP_NAME].nColumns(); x++) { + for (int y = 0; y < groups[GLOBAL_GROUP_NAME].nRows(); y++) { // Only save non-builtin profiles.= /* const KoColorProfile *profile = entry.color().colorSpace()->profile(); if (!profile->fileName().isEmpty()) { profiles << profile; profileMap[profile] = entry.color().colorSpace(); } QDomElement el = doc.createElement("ColorSetEntry"); el.setAttribute("name", entry.name()); el.setAttribute("id", entry.id()); el.setAttribute("spot", entry.spotColor() ? "true" : "false"); el.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); entry.color().toXML(doc, el); root.appendChild(el); */ } } Q_FOREACH(const QString &groupName, groupNames) { QDomElement gl = doc.createElement("Group"); gl.setAttribute("name", groupName); root.appendChild(gl); for (int x = 0; x < groups[groupName].nColumns(); x++) { for (int y = 0; y < groups[groupName].nRows(); y++) { // Only save non-builtin profiles.= /* const KoColorProfile *profile = entry.color().colorSpace()->profile(); if (!profile->fileName().isEmpty()) { profiles << profile; profileMap[profile] = entry.color().colorSpace(); } QDomElement el = doc.createElement("ColorSetEntry"); el.setAttribute("name", entry.name()); el.setAttribute("id", entry.id()); el.setAttribute("spot", entry.spotColor() ? "true" : "false"); el.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); entry.color().toXML(doc, el); gl.appendChild(el); */ } } } doc.appendChild(root); if (!store->open("colorset.xml")) { return false; } QByteArray ba = doc.toByteArray(); if (store->write(ba) != ba.size()) { return false; } if (!store->close()) { return false; } } QDomDocument doc; QDomElement profileElement = doc.createElement("Profiles"); Q_FOREACH(const KoColorProfile *profile, profiles) { QString fn = QFileInfo(profile->fileName()).fileName(); if (!store->open(fn)) { return false; } QByteArray profileRawData = profile->rawData(); if (!store->write(profileRawData)) { return false; } if (!store->close()) { return false; } QDomElement el = doc.createElement("Profile"); el.setAttribute("filename", fn); el.setAttribute("name", profile->name()); el.setAttribute("colorModelId", profileMap[profile]->colorModelId().id()); el.setAttribute("colorDepthId", profileMap[profile]->colorDepthId().id()); profileElement.appendChild(el); } doc.appendChild(profileElement); if (!store->open("profiles.xml")) { return false; } QByteArray ba = doc.toByteArray(); if (store->write(ba) != ba.size()) { return false; } if (!store->close()) { return false; } return store->finalize(); } diff --git a/libs/pigment/resources/KoColorSet_p.h b/libs/pigment/resources/KoColorSet_p.h index 00e7c37e0f..22b60a5751 100644 --- a/libs/pigment/resources/KoColorSet_p.h +++ b/libs/pigment/resources/KoColorSet_p.h @@ -1,60 +1,60 @@ #ifndef KOCOLORSET_P_H #define KOCOLORSET_P_H #include #include +#include #include #include #include "KoColorSet.h" struct RiffHeader { quint32 riff; quint32 size; quint32 signature; quint32 data; quint32 datasize; quint16 version; quint16 colorcount; }; KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba); void scribusParseColor(KoColorSet *set, QXmlStreamReader *xml); bool loadScribusXmlPalette(KoColorSet *set, QXmlStreamReader *xml); class KoColorSet::Private { public: Private(KoColorSet *a_colorSet); public: bool init(); bool saveGpl(QIODevice *dev) const; bool loadGpl(); bool loadAct(); bool loadRiff(); bool loadPsp(); bool loadAco(); bool loadXml(); bool loadSbz(); bool saveKpl(QIODevice *dev) const; bool loadKpl(); public: KoColorSet *colorSet; KoColorSet::PaletteType paletteType; QByteArray data; QString comment; QStringList groupNames; //names of the groups, this is used to determine the order they are in. QHash groups; //grouped colors. - KisSwatchGroup &global; public: static QString GLOBAL_GROUP_NAME; }; #endif // KOCOLORSET_P_H diff --git a/libs/widgets/KisPaletteModel.cpp b/libs/widgets/KisPaletteModel.cpp index d590dc5396..c156029e18 100644 --- a/libs/widgets/KisPaletteModel.cpp +++ b/libs/widgets/KisPaletteModel.cpp @@ -1,632 +1,632 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisPaletteModel.h" #include #include #include #include #include #include #include #include #include KisPaletteModel::KisPaletteModel(QObject* parent) : QAbstractTableModel(parent), m_colorSet(0), m_displayRenderer(KoDumbColorDisplayRenderer::instance()) { } KisPaletteModel::~KisPaletteModel() { } void KisPaletteModel::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { if (m_displayRenderer) { disconnect(m_displayRenderer, 0, this, 0); } m_displayRenderer = displayRenderer; connect(m_displayRenderer, SIGNAL(displayConfigurationChanged()), SLOT(slotDisplayConfigurationChanged())); } else { m_displayRenderer = KoDumbColorDisplayRenderer::instance(); } } void KisPaletteModel::slotDisplayConfigurationChanged() { beginResetModel(); endResetModel(); } QVariant KisPaletteModel::data(const QModelIndex& index, int role) const { KoColorSetEntry entry; if (m_colorSet && m_displayRenderer) { //now to figure out whether we have a groupname row or not. bool groupNameRow = false; quint32 indexInGroup = 0; QString indexGroupName = QString(); /* int rowstotal = m_colorSet->nColorsGroup()/columnCount(); if (index.row()<=rowstotal && (quint32)(index.row()*columnCount()+index.column())nColorsGroup()) { indexInGroup = (quint32)(index.row()*columnCount()+index.column()); } if (m_colorSet->nColorsGroup()==0) { rowstotal+=1; //always add one for the default group when considering groups. } */ /* Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ //we make an int for the rows added by the current group. int newrows = 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { newrows+=1; } if (newrows==0) { newrows+=1; //always add one for the group when considering groups. } quint32 tempIndex = (quint32)((index.row()-(rowstotal+2))*columnCount()+index.column()); if (index.row() == rowstotal+1) { //rowstotal+1 is taken up by the groupname. indexGroupName = groupName; groupNameRow = true; } else if (index.row() > (rowstotal+1) && index.row() <= rowstotal+newrows && tempIndexnColorsGroup(groupName)){ //otherwise it's an index to the colors in the group. indexGroupName = groupName; indexInGroup = tempIndex; } //add the new rows to the totalrows we've looked at. rowstotal += newrows; } */ if (groupNameRow) { switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return indexGroupName; } case IsHeaderRole: { return true; } case RetrieveEntryRole: { QStringList entryList; entryList.append(indexGroupName); entryList.append(QString::number(0)); return entryList; } } } else { entry = m_colorSet->getColorGroup(index.row(), index.column(), indexGroupName); switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return entry.name(); } case Qt::BackgroundRole: { QColor color = m_displayRenderer->toQColor(entry.color()); return QBrush(color); } case IsHeaderRole: { return false; } case RetrieveEntryRole: { QStringList entryList; entryList.append(indexGroupName); // entryList.append(QString::number(indexInGroup)); return entryList; } } } } return QVariant(); } int KisPaletteModel::rowCount(const QModelIndex& /*parent*/) const { /* if (!m_colorSet) { return 0; } if (m_colorSet->nColors()==0) { return 0; } if (columnCount() > 0) { int countedrows = m_colorSet->nColorsGroup("")/columnCount(); if (m_colorSet->nColorsGroup()%columnCount() > 0) { countedrows+=1; } if (m_colorSet->nColorsGroup()==0) { countedrows+=1; } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()) { countedrows += 1; //add one for the name; countedrows += 1+(m_colorSet->nColorsGroup(groupName)/ columnCount()); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { countedrows+=1; } if (m_colorSet->nColorsGroup(groupName)==0) { countedrows+=1; } } countedrows +=1; //Our code up till now doesn't take 0 into account. return countedrows; } return m_colorSet->nColors()/15 + 1; */ if (m_colorSet) { return m_colorSet->rowCount() // count of color rows + m_colorSet->getGroupNames().size() // rows from names + 1; // take 0 into account } return 0; } int KisPaletteModel::columnCount(const QModelIndex& /*parent*/) const { if (m_colorSet && m_colorSet->columnCount() > 0) { return m_colorSet->columnCount(); } return 15; } Qt::ItemFlags KisPaletteModel::flags(const QModelIndex& index) const { if (index.isValid()) { return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } return Qt::ItemIsDropEnabled; } QModelIndex KisPaletteModel::index(int row, int column, const QModelIndex& parent) const { if (m_colorSet) { return QAbstractTableModel::index(row, column, parent); /* //make an int to hold the amount of rows we've looked at. The initial is the total rows in the default group. int rowstotal = m_colorSet->nColorsGroup()/columnCount(); if (row<=rowstotal && (quint32)(row*columnCount()+column)nColorsGroup()) { //if the total rows are in the default group, we just return an index. return QAbstractTableModel::index(row, column, parent); } else if(row<0 && column<0) { return QAbstractTableModel::index(0, 0, parent); } if (m_colorSet->nColorsGroup()==0) { rowstotal+=1; //always add one for the default group when considering groups. } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ //we make an int for the rows added by the current group. int newrows = 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { newrows+=1; } if (m_colorSet->nColorsGroup(groupName)==0) { newrows+=1; //always add one for the group when considering groups. } if (rowstotal + newrows>rowCount()) { newrows = rowCount() - rowstotal; } quint32 tempIndex = (quint32)((row-(rowstotal+2))*columnCount()+column); if (row == rowstotal+1) { //rowstotal+1 is taken up by the groupname. return QAbstractTableModel::index(row, 0, parent); } else if (row > (rowstotal+1) && row <= rowstotal+newrows && tempIndexnColorsGroup(groupName)){ //otherwise it's an index to the colors in the group. return QAbstractTableModel::index(row, column, parent); } //add the new rows to the totalrows we've looked at. rowstotal += newrows; } */ } return QModelIndex(); } void KisPaletteModel::setColorSet(KoColorSet* colorSet) { m_colorSet = colorSet; beginResetModel(); endResetModel(); } KoColorSet* KisPaletteModel::colorSet() const { return m_colorSet; } QModelIndex KisPaletteModel::indexFromId(int i) const { return QModelIndex(); /* QModelIndex index = QModelIndex(); if (!colorSet() || colorSet()->nColors() == 0) { return index; } if (i > (int)colorSet()->nColors()) { qWarning()<<"index is too big"<nColors(); index = this->index(0,0); } if (i < (int)colorSet()->nColorsGroup(0)) { index = QAbstractTableModel::index(i/columnCount(), i % columnCount()); if (!index.isValid()) { index = QAbstractTableModel::index(0, 0, QModelIndex()); } return index; } else { int rowstotal = 1 + m_colorSet->nColorsGroup() / columnCount(); if (m_colorSet->nColorsGroup() == 0) { rowstotal += 1; } int totalIndexes = colorSet()->nColorsGroup(); Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ if (i + 1 <= (int)(totalIndexes + colorSet()->nColorsGroup(groupName)) && i + 1 > (int)totalIndexes) { int col = (i - totalIndexes) % columnCount(); int row = rowstotal + 1 + ((i - totalIndexes) / columnCount()); index = this->index(row, col); return index; } else { rowstotal += 1 + m_colorSet->nColorsGroup(groupName) / columnCount(); totalIndexes += colorSet()->nColorsGroup(groupName); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { rowstotal += 1; } if (m_colorSet->nColorsGroup(groupName)==0) { rowstotal += 1; //always add one for the group when considering groups. } } } } return index; */ } int KisPaletteModel::idFromIndex(const QModelIndex &index) const { /* if (index.isValid()==false) { return -1; qWarning()<<"invalid index"; } int i=0; QStringList entryList = qvariant_cast(data(index, RetrieveEntryRole)); if (entryList.isEmpty()) { return -1; qWarning()<<"invalid index, there's no data to retrieve here"; } if (entryList.at(0)==QString()) { return entryList.at(1).toUInt(); } i = colorSet()->nColorsGroup(""); //find at which position the group is. int groupIndex = colorSet()->getGroupNames().indexOf(entryList.at(0)); //add all the groupsizes onto it till we get to our group. for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); } //then add the index. i += entryList.at(1).toUInt(); return i; */ return 0; } -KoColorSetEntry KisPaletteModel::colorSetEntryFromIndex(const QModelIndex &index) const +KisSwatch KisPaletteModel::colorSetEntryFromIndex(const QModelIndex &index) const { /* KoColorSetEntry blank = KoColorSetEntry(); if (!index.isValid()) { return blank; } QStringList entryList = qvariant_cast(data(index, RetrieveEntryRole)); if (entryList.isEmpty()) { return blank; } QString groupName = entryList.at(0); quint32 indexInGroup = entryList.at(1).toUInt(); return m_colorSet->getColorGroup(indexInGroup, groupName); */ - return KoColorSetEntry(); + return KisSwatch(); } bool KisPaletteModel::addColorSetEntry(KoColorSetEntry entry, QString groupName) { return true; } bool KisPaletteModel::removeEntry(QModelIndex index, bool keepColors) { return true; /* QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); if (entryList.empty()) { return false; } QString groupName = entryList.at(0); quint32 indexInGroup = entryList.at(1).toUInt(); if (qvariant_cast(index.data(IsHeaderRole))==false) { if (index.column()-1<0 && m_colorSet->nColorsGroup(groupName)%columnCount() <1 && index.row()-1>0 && m_colorSet->nColorsGroup(groupName)/columnCount()>0) { beginRemoveRows(QModelIndex(), index.row(), index.row()-1); } m_colorSet->removeAt(indexInGroup, groupName); if (index.column()-1<0 && m_colorSet->nColorsGroup(groupName)%columnCount() <1 && index.row()-1>0 && m_colorSet->nColorsGroup(groupName)/columnCount()>0) { endRemoveRows(); } } else { beginRemoveRows(QModelIndex(), index.row(), index.row()-1); m_colorSet->removeGroup(groupName, keepColors); endRemoveRows(); } return true; */ } bool KisPaletteModel::removeRows(int row, int count, const QModelIndex &parent) { /* Q_ASSERT(!parent.isValid()); int beginRow = qMax(0, row); int endRow = qMin(row + count - 1, (int)m_colorSet->nColors() - 1); beginRemoveRows(parent, beginRow, endRow); // Find the palette entry at row, count, remove from KoColorSet endRemoveRows(); return true; */ return true; } bool KisPaletteModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { return true; /* if (!data->hasFormat("krita/x-colorsetentry") && !data->hasFormat("krita/x-colorsetgroup")) { return false; } if (action == Qt::IgnoreAction) { return false; } int endRow; int endColumn; if (!parent.isValid()) { if (row < 0) { endRow = indexFromId(m_colorSet->nColors()).row(); endColumn = indexFromId(m_colorSet->nColors()).column(); } else { endRow = qMin(row, indexFromId(m_colorSet->nColors()).row()); endColumn = qMin(column, m_colorSet->columnCount()); } } else { endRow = qMin(parent.row(), rowCount()); endColumn = qMin(parent.column(), columnCount()); } if (data->hasFormat("krita/x-colorsetgroup")) { QByteArray encodedData = data->data("krita/x-colorsetgroup"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { QString groupName; stream >> groupName; QModelIndex index = this->index(endRow, 0); if (index.isValid()) { QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString groupDroppedOn = QString(); if (!entryList.isEmpty()) { groupDroppedOn = entryList.at(0); } int groupIndex = colorSet()->getGroupNames().indexOf(groupName); beginMoveRows( QModelIndex(), groupIndex, groupIndex, QModelIndex(), endRow); m_colorSet->moveGroup(groupName, groupDroppedOn); m_colorSet->save(); endMoveRows(); ++endRow; } } } else { QByteArray encodedData = data->data("krita/x-colorsetentry"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { KoColorSetEntry entry; QString oldGroupName; int indexInGroup; QString colorXml; QString name, id; bool spotColor; stream >> name >> id >> spotColor >> indexInGroup >> oldGroupName >> colorXml; entry.setName(name); entry.setId(id); entry.setSpotColor(spotColor); QDomDocument doc; doc.setContent(colorXml); QDomElement e = doc.documentElement(); QDomElement c = e.firstChildElement(); if (!c.isNull()) { QString colorDepthId = c.attribute("bitdepth", Integer8BitsColorDepthID.id()); entry.setColor(KoColor::fromXML(c, colorDepthId)); } QModelIndex index = this->index(endRow, endColumn); if (qvariant_cast(index.data(IsHeaderRole))){ endRow+=1; } if (index.isValid()) { // this is to figure out the row of the old color. // That way we can in turn avoid moverows from complaining the // index is out of bounds when using index. // Makes me wonder if we shouldn't just insert the index of the // old color when requesting the mimetype... int i = indexInGroup; if (oldGroupName != QString()) { colorSet()->nColorsGroup(""); //find at which position the group is. int groupIndex = colorSet()->getGroupNames().indexOf(oldGroupName); //add all the groupsizes onto it till we get to our group. for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); } } QModelIndex indexOld = indexFromId(i); if (action == Qt::MoveAction){ if (indexOld.row()!=qMax(endRow, 0) && indexOld.row()!=qMax(endRow+1,1)) { beginMoveRows(QModelIndex(), indexOld.row(), indexOld.row(), QModelIndex(), qMax(endRow+1,1)); } if (indexOld.column()!=qMax(endColumn, 0) && indexOld.column()!=qMax(endColumn+1,1)) { beginMoveColumns(QModelIndex(), indexOld.column(), indexOld.column(), QModelIndex(), qMax(endColumn+1,1)); } } else { beginInsertRows(QModelIndex(), endRow, endRow); } QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString entryInGroup = "0"; QString groupName = QString(); if (!entryList.isEmpty()) { groupName = entryList.at(0); entryInGroup = entryList.at(1); } int location = entryInGroup.toInt(); // Insert the entry if (groupName==oldGroupName && qvariant_cast(index.data(IsHeaderRole))==true) { groupName=QString(); location=m_colorSet->nColorsGroup(); } m_colorSet->insertBefore(entry, location, groupName); if (groupName==oldGroupName && locationremoveAt(indexInGroup, oldGroupName); } m_colorSet->save(); if (action == Qt::MoveAction){ if (indexOld.row()!=qMax(endRow, 0) && indexOld.row()!=qMax(endRow+1,1)) { endMoveRows(); } if (indexOld.column()!=qMax(endColumn, 0) && indexOld.column()!=qMax(endColumn+1,1)) { endMoveColumns(); } } else { endInsertRows(); } ++endRow; } } } return true; */ } QMimeData *KisPaletteModel::mimeData(const QModelIndexList &indexes) const { return new QMimeData(); /* QMimeData *mimeData = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QString mimeTypeName = "krita/x-colorsetentry"; //Q_FOREACH(const QModelIndex &index, indexes) { QModelIndex index = indexes.last(); if (index.isValid()) { if (qvariant_cast(index.data(IsHeaderRole))==false) { KoColorSetEntry entry = colorSetEntryFromIndex(index); QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString groupName = QString(); int indexInGroup = 0; if (!entryList.isEmpty()) { groupName = entryList.at(0); QString iig = entryList.at(1); indexInGroup = iig.toInt(); } QDomDocument doc; QDomElement root = doc.createElement("Color"); root.setAttribute("bitdepth", entry.color().colorSpace()->colorDepthId().id()); doc.appendChild(root); entry.color().toXML(doc, root); stream << entry.name() << entry.id() << entry.spotColor() << indexInGroup << groupName << doc.toString(); } else { mimeTypeName = "krita/x-colorsetgroup"; QStringList entryList = qvariant_cast(index.data(RetrieveEntryRole)); QString groupName = QString(); if (!entryList.isEmpty()) { groupName = entryList.at(0); } stream << groupName; } } mimeData->setData(mimeTypeName, encodedData); return mimeData; */ } QStringList KisPaletteModel::mimeTypes() const { return QStringList() << "krita/x-colorsetentry" << "krita/x-colorsetgroup"; } Qt::DropActions KisPaletteModel::supportedDropActions() const { return Qt::MoveAction; } diff --git a/libs/widgets/KisPaletteModel.h b/libs/widgets/KisPaletteModel.h index 7a266cc126..3c65c10ef5 100644 --- a/libs/widgets/KisPaletteModel.h +++ b/libs/widgets/KisPaletteModel.h @@ -1,142 +1,142 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PALETTEMODEL_H #define KIS_PALETTEMODEL_H #include #include #include #include "kritawidgets_export.h" #include #include class KoColorSet; /** * @brief The KisPaletteModel class * This, together with kis_palette_view and kis_palette_delegate forms a mvc way to access kocolorsets. */ class KRITAWIDGETS_EXPORT KisPaletteModel : public QAbstractTableModel { Q_OBJECT public: KisPaletteModel(QObject* parent = 0); ~KisPaletteModel() override; enum AdditionalRoles { IsHeaderRole = Qt::UserRole + 1, ExpandCategoryRole = Qt::UserRole + 2, RetrieveEntryRole = Qt::UserRole + 3 }; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; void setColorSet(KoColorSet* colorSet); KoColorSet* colorSet() const; /** * Installs a display renderer object for a palette that will * convert the KoColor to the displayable QColor. Default is the * dumb renderer. */ void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer); /** * @brief indexFromId * convenience function to get the tableindex from the global palette color. * used by lazybrush. * @param i * @return index in table. */ QModelIndex indexFromId(int i) const; /** * @brief idFromIndex * convenience function to get the global colorset entry id from the table index. * If you just want to use this to get the kocolorsetentry, use colorsetEntryFromIndex instead. * @param index * @return */ int idFromIndex(const QModelIndex &index) const; /** * @brief colorSetEntryFromIndex * This gives the colorset entry for the given table model index. * @param index the QModelIndex * @return the kocolorsetentry */ - KoColorSetEntry colorSetEntryFromIndex(const QModelIndex &index) const; + KisSwatch colorSetEntryFromIndex(const QModelIndex &index) const; /** * @brief addColorSetEntry * proper function to handle adding entries. * @return whether successful. */ bool addColorSetEntry(KoColorSetEntry entry, QString groupName=QString()); /** * @brief removeEntry * proper function to remove the colorsetentry at the given index. * The consolidtes both removeentry and removegroup. * @param keepColors: This bool determines whether, when deleting a group, * the colors should be added to the default group. This is usually desirable, * so hence the default is true. * @return if successful */ bool removeEntry(QModelIndex index, bool keepColors=true); bool removeRows(int row, int count, const QModelIndex &parent) override; /** * @brief dropMimeData * This is an overridden function that handles dropped mimedata. * right now only colorsetentries and colorsetgroups are handled. * @return */ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; /** * @brief mimeData * gives the mimedata for a kocolorsetentry or a kocolorsetgroup. * @param indexes * @return the mimedata for the given indices */ QMimeData *mimeData(const QModelIndexList &indexes) const override; QStringList mimeTypes() const override; Qt::DropActions supportedDropActions() const override; private Q_SLOTS: void slotDisplayConfigurationChanged(); private: QModelIndex getLastEntryIndex(); private: QPointer m_colorSet; QPointer m_displayRenderer; }; #endif diff --git a/libs/widgets/WdgPaletteListWidget.ui b/libs/widgets/WdgPaletteListWidget.ui new file mode 100644 index 0000000000..5ecc844de9 --- /dev/null +++ b/libs/widgets/WdgPaletteListWidget.ui @@ -0,0 +1,91 @@ + + + WdgPaletteListWidget + + + + 0 + 0 + 361 + 496 + + + + Form + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + .. + + + + + + + + .. + + + + + + + + .. + + + + + + + + .. + + + + + + + + .. + + + + + + + + + + KoResourceItemView + QTableView +
KoResourceItemView.h
+
+
+ + +
diff --git a/plugins/dockers/palettedocker/palettedocker_dock.h b/plugins/dockers/palettedocker/palettedocker_dock.h index 4cdc5b4198..2c92a9c1bc 100644 --- a/plugins/dockers/palettedocker/palettedocker_dock.h +++ b/plugins/dockers/palettedocker/palettedocker_dock.h @@ -1,86 +1,86 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PALETTEDOCKER_DOCK_H #define PALETTEDOCKER_DOCK_H #include #include #include #include #include #include #include #include #include class KisViewManager; class KisCanvasResourceProvider; class KisWorkspaceResource; -class KisColorsetChooser; +class KisPaletteListWidget; class KisPaletteModel; class Ui_WdgPaletteDock; class PaletteDockerDock : public QDockWidget, public KisMainwindowObserver, public KoResourceServerObserver { Q_OBJECT public: PaletteDockerDock(); ~PaletteDockerDock() override; QString observerName() override { return "PaletteDockerDock"; } void setMainWindow(KisViewManager* kisview) override; void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public: // KoResourceServerObserver void unsetResourceServer() override; void resourceAdded(KoColorSet *) override {} void removingResource(KoColorSet *resource) override; void resourceChanged(KoColorSet *resource) override; void syncTaggedResourceView() override {} void syncTagAddition(const QString&) override {} void syncTagRemoval(const QString&) override {} private Q_SLOTS: void addColorForeground(); void removeColor(); void entrySelected(KoColorSetEntry entry); void entrySelectedBack(KoColorSetEntry entry); void setColorSet(KoColorSet* colorSet); void setColorFromNameList(int index); void saveToWorkspace(KisWorkspaceResource* workspace); void loadFromWorkspace(KisWorkspaceResource* workspace); private: Ui_WdgPaletteDock* m_wdgPaletteDock; KisPaletteModel *m_model; QSharedPointer m_serverAdapter; KoColorSet *m_currentColorSet; - KisColorsetChooser *m_paletteChooser; + KisPaletteListWidget *m_paletteChooser; KisCanvasResourceProvider *m_resourceProvider; QPointer m_canvas; }; #endif diff --git a/plugins/extensions/pykrita/sip/krita/Palette.sip b/plugins/extensions/pykrita/sip/krita/Palette.sip index 4780b3c65c..5070275753 100644 --- a/plugins/extensions/pykrita/sip/krita/Palette.sip +++ b/plugins/extensions/pykrita/sip/krita/Palette.sip @@ -1,48 +1,47 @@ /* struct KoColorSetEntry { %TypeHeaderCode #include "KoColorSet.h" %End public: KoColorSetEntry(); QString name; QString id; bool spotColor; bool operator==(const KoColorSetEntry& rhs) const; }; */ -class KoColorSetEntry; +class KisSwatch; class Palette : QObject { %TypeHeaderCode #include "Palette.h" %End Palette(const Palette & __0); public: Palette(Resource *resource); int numberOfEntries() const; int columnCount(); void setColumnCount(int columns); QString comment(); void setComment(QString comment); QStringList groupNames(); bool addGroup(QString name); bool removeGroup(QString name, bool keepColors); int colorsCountTotal(); int colorsCountGroup(QString name); - KoColorSetEntry colorSetEntryByIndex(int index); - KoColorSetEntry colorSetEntryFromGroup(int index, const QString &groupName); - ManagedColor *colorForEntry(KoColorSetEntry entry) /Factory/; - void addEntry(KoColorSetEntry entry, QString groupName); + KisSwatch colorSetEntryByIndex(int index); + KisSwatch colorSetEntryFromGroup(int index, const QString &groupName); + ManagedColor *colorForEntry(KisSwatch entry) /Factory/; + void addEntry(KisSwatch entry, QString groupName); void removeEntry(int index, const QString &groupName); - void insertEntry(int index, KoColorSetEntry entry, QString groupName); - bool editEntry(int index, KoColorSetEntry entry, QString groupName); + bool editEntry(int index, KisSwatch entry, QString groupName); bool changeGroupName(QString oldGroupName, QString newGroupName); bool moveGroup(const QString &groupName, const QString &groupNameInsertBefore); bool save(); private: }; diff --git a/plugins/extensions/pykrita/sip/krita/PaletteView.sip b/plugins/extensions/pykrita/sip/krita/PaletteView.sip index 21bc77be93..5714b366dd 100644 --- a/plugins/extensions/pykrita/sip/krita/PaletteView.sip +++ b/plugins/extensions/pykrita/sip/krita/PaletteView.sip @@ -1,20 +1,20 @@ class PaletteView : QWidget { %TypeHeaderCode #include "PaletteView.h" %End PaletteView(const PaletteView & __0); public: PaletteView(QWidget *parent = 0); ~PaletteView(); public Q_SLOTS: void setPalette(Palette *palette); bool addEntryWithDialog(ManagedColor *color); bool addGroupWithDialog(); bool removeSelectedEntryWithDialog(); void trySelectClosestColor(ManagedColor *color); Q_SIGNALS: - void entrySelectedForeGround(KoColorSetEntry entry); - void entrySelectedBackGround(KoColorSetEntry entry); + void entrySelectedForeGround(KisSwatch entry); + void entrySelectedBackGround(KisSwatch entry); private: }; diff --git a/plugins/tools/basictools/kis_tool_colorpicker.cc b/plugins/tools/basictools/kis_tool_colorpicker.cc index 9b3487da52..238a23e156 100644 --- a/plugins/tools/basictools/kis_tool_colorpicker.cc +++ b/plugins/tools/basictools/kis_tool_colorpicker.cc @@ -1,350 +1,350 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2018 Emmet & Eoin O'Neill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_colorpicker.h" #include #include #include "kis_cursor.h" #include "KisDocument.h" #include "kis_canvas2.h" #include "KisReferenceImagesLayer.h" #include "KoCanvasBase.h" #include "kis_random_accessor_ng.h" #include "KoResourceServerProvider.h" #include #include "kis_wrapped_rect.h" #include "kis_tool_utils.h" namespace { // GUI ComboBox index constants const int SAMPLE_MERGED = 0; } KisToolColorPicker::KisToolColorPicker(KoCanvasBase *canvas) : KisTool(canvas, KisCursor::pickerCursor()), m_config(new KisToolUtils::ColorPickerConfig) { setObjectName("tool_colorpicker"); m_isActivated = false; m_optionsWidget = 0; m_pickedColor = KoColor(); } KisToolColorPicker::~KisToolColorPicker() { if (m_isActivated) { m_config->save(m_toolActivationSource == KisTool::DefaultActivation); } } void KisToolColorPicker::paint(QPainter &gc, const KoViewConverter &converter) { Q_UNUSED(gc); Q_UNUSED(converter); } void KisToolColorPicker::activate(ToolActivation activation, const QSet &shapes) { m_isActivated = true; m_toolActivationSource = activation; m_config->load(m_toolActivationSource == KisTool::DefaultActivation); updateOptionWidget(); KisTool::activate(activation, shapes); } void KisToolColorPicker::deactivate() { m_config->save(m_toolActivationSource == KisTool::DefaultActivation); m_isActivated = false; KisTool::deactivate(); } void KisToolColorPicker::pickColor(const QPointF &pos) { // Timer check. if (m_colorPickerDelayTimer.isActive()) { return; } else { m_colorPickerDelayTimer.setSingleShot(true); m_colorPickerDelayTimer.start(100); } QScopedPointer> imageLocker; m_pickedColor.setOpacity(0.0); // Pick from reference images. if (m_optionsWidget->cmbSources->currentIndex() == SAMPLE_MERGED) { auto *kisCanvas = dynamic_cast(canvas()); KIS_SAFE_ASSERT_RECOVER_RETURN(kisCanvas); KisSharedPtr referenceImageLayer = kisCanvas->imageView()->document()->referenceImagesLayer(); if (referenceImageLayer) { QColor color = referenceImageLayer->getPixel(pos); if (color.isValid()) { m_pickedColor.fromQColor(color); } } } if (m_pickedColor.opacityU8() == OPACITY_TRANSPARENT_U8) { KisPaintDeviceSP dev; if (m_optionsWidget->cmbSources->currentIndex() != SAMPLE_MERGED && currentNode() && currentNode()->colorPickSourceDevice()) { dev = currentNode()->colorPickSourceDevice(); } else { imageLocker.reset(new boost::lock_guard(*currentImage())); dev = currentImage()->projection(); } KoColor previousColor = canvas()->resourceManager()->foregroundColor(); KisToolUtils::pickColor(m_pickedColor, dev, pos.toPoint(), &previousColor, m_config->radius, m_config->blend); /*!*/ if (m_config->updateColor && m_pickedColor.opacityU8() != OPACITY_TRANSPARENT_U8) { KoColor publicColor = m_pickedColor; publicColor.setOpacity(OPACITY_OPAQUE_U8); if (m_config->toForegroundColor) { canvas()->resourceManager()->setResource(KoCanvasResourceManager::ForegroundColor, publicColor); } else { canvas()->resourceManager()->setResource(KoCanvasResourceManager::BackgroundColor, publicColor); } } } } void KisToolColorPicker::beginPrimaryAction(KoPointerEvent *event) { bool sampleMerged = m_optionsWidget->cmbSources->currentIndex() == SAMPLE_MERGED; if (!sampleMerged) { if (!currentNode()) { QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot pick a color as no layer is active.")); event->ignore(); return; } if (!currentNode()->visible()) { QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot pick a color as the active layer is not visible.")); event->ignore(); return; } } QPoint pos = convertToImagePixelCoordFloored(event); // Color picking has to start in the visible part of the layer if (!currentImage()->bounds().contains(pos) && !currentImage()->wrapAroundModePermitted()) { event->ignore(); return; } setMode(KisTool::PAINT_MODE); pickColor(pos); displayPickedColor(); } void KisToolColorPicker::continuePrimaryAction(KoPointerEvent *event) { CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); QPoint pos = convertToImagePixelCoordFloored(event); pickColor(pos); displayPickedColor(); } void KisToolColorPicker::endPrimaryAction(KoPointerEvent *event) { Q_UNUSED(event); CHECK_MODE_SANITY_OR_RETURN(KisTool::PAINT_MODE); if (m_config->addPalette) { - KoColorSetEntry ent; + KisSwatch ent; ent.setColor(m_pickedColor); // We don't ask for a name, too intrusive here KoColorSet *palette = m_palettes.at(m_optionsWidget->cmbPalette->currentIndex()); palette->add(ent); if (!palette->save()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Cannot write to palette file %1. Maybe it is read-only.", palette->filename())); } } } struct PickedChannel { QString name; QString valueText; }; void KisToolColorPicker::displayPickedColor() { if (m_pickedColor.data() && m_optionsWidget) { QList channels = m_pickedColor.colorSpace()->channels(); m_optionsWidget->listViewChannels->clear(); QVector pickedChannels; for (int i = 0; i < channels.count(); ++i) { pickedChannels.append(PickedChannel()); } for (int i = 0; i < channels.count(); ++i) { PickedChannel pc; pc.name = channels[i]->name(); if (m_config->normaliseValues) { pc.valueText = m_pickedColor.colorSpace()->normalisedChannelValueText(m_pickedColor.data(), i); } else { pc.valueText = m_pickedColor.colorSpace()->channelValueText(m_pickedColor.data(), i); } pickedChannels[channels[i]->displayPosition()] = pc; } Q_FOREACH (const PickedChannel &pc, pickedChannels) { QTreeWidgetItem *item = new QTreeWidgetItem(m_optionsWidget->listViewChannels); item->setText(0, pc.name); item->setText(1, pc.valueText); } } } QWidget* KisToolColorPicker::createOptionWidget() { m_optionsWidget = new ColorPickerOptionsWidget(0); m_optionsWidget->setObjectName(toolId() + " option widget"); m_optionsWidget->listViewChannels->setSortingEnabled(false); // See https://bugs.kde.org/show_bug.cgi?id=316896 QWidget *specialSpacer = new QWidget(m_optionsWidget); specialSpacer->setObjectName("SpecialSpacer"); specialSpacer->setFixedSize(0, 0); m_optionsWidget->layout()->addWidget(specialSpacer); // Initialize blend KisSliderSpinBox m_optionsWidget->blend->setRange(0,100); m_optionsWidget->blend->setSuffix("%"); updateOptionWidget(); connect(m_optionsWidget->cbUpdateCurrentColor, SIGNAL(toggled(bool)), SLOT(slotSetUpdateColor(bool))); connect(m_optionsWidget->cbNormaliseValues, SIGNAL(toggled(bool)), SLOT(slotSetNormaliseValues(bool))); connect(m_optionsWidget->cbPalette, SIGNAL(toggled(bool)), SLOT(slotSetAddPalette(bool))); connect(m_optionsWidget->radius, SIGNAL(valueChanged(int)), SLOT(slotChangeRadius(int))); connect(m_optionsWidget->blend, SIGNAL(valueChanged(int)), SLOT(slotChangeBlend(int))); connect(m_optionsWidget->cmbSources, SIGNAL(currentIndexChanged(int)), SLOT(slotSetColorSource(int))); KoResourceServer *srv = KoResourceServerProvider::instance()->paletteServer(); if (!srv) { return m_optionsWidget; } QList palettes = srv->resources(); Q_FOREACH (KoColorSet *palette, palettes) { if (palette) { m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); m_palettes.append(palette); } } return m_optionsWidget; } void KisToolColorPicker::updateOptionWidget() { if (!m_optionsWidget) return; m_optionsWidget->cbNormaliseValues->setChecked(m_config->normaliseValues); m_optionsWidget->cbUpdateCurrentColor->setChecked(m_config->updateColor); m_optionsWidget->cmbSources->setCurrentIndex(SAMPLE_MERGED + !m_config->sampleMerged); m_optionsWidget->cbPalette->setChecked(m_config->addPalette); m_optionsWidget->radius->setValue(m_config->radius); m_optionsWidget->blend->setValue(m_config->blend); } void KisToolColorPicker::setToForeground(bool newValue) { m_config->toForegroundColor = newValue; emit toForegroundChanged(); } bool KisToolColorPicker::toForeground() const { return m_config->toForegroundColor; } void KisToolColorPicker::slotSetUpdateColor(bool state) { m_config->updateColor = state; } void KisToolColorPicker::slotSetNormaliseValues(bool state) { m_config->normaliseValues = state; displayPickedColor(); } void KisToolColorPicker::slotSetAddPalette(bool state) { m_config->addPalette = state; } void KisToolColorPicker::slotChangeRadius(int value) { m_config->radius = value; } void KisToolColorPicker::slotChangeBlend(int value) { m_config->blend = value; } void KisToolColorPicker::slotSetColorSource(int value) { m_config->sampleMerged = value == SAMPLE_MERGED; } void KisToolColorPicker::slotAddPalette(KoResource *resource) { KoColorSet *palette = dynamic_cast(resource); if (palette) { m_optionsWidget->cmbPalette->addSqueezedItem(palette->name()); m_palettes.append(palette); } } diff --git a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp index af0a6f876e..f40c3cd285 100644 --- a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp +++ b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp @@ -1,381 +1,381 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_lazy_brush_options_widget.h" #include "ui_kis_tool_lazy_brush_options_widget.h" #include #include "KisPaletteModel.h" #include "kis_config.h" #include #include "kis_canvas_resource_provider.h" #include "kis_signal_auto_connection.h" #include "lazybrush/kis_colorize_mask.h" #include "kis_image.h" #include "kis_signals_blocker.h" #include "kis_signal_compressor.h" #include "kis_layer_properties_icons.h" struct KisToolLazyBrushOptionsWidget::Private { Private() : transparentColorIndex(-1), baseNodeChangedCompressor(500, KisSignalCompressor::FIRST_ACTIVE) { } Ui_KisToolLazyBrushOptionsWidget *ui; KisPaletteModel *colorModel; KisCanvasResourceProvider *provider; KisSignalAutoConnectionsStore providerSignals; KisSignalAutoConnectionsStore maskSignals; KisColorizeMaskSP activeMask; KoColorSet colorSet; int transparentColorIndex = -1; KisSignalCompressor baseNodeChangedCompressor; }; KisToolLazyBrushOptionsWidget::KisToolLazyBrushOptionsWidget(KisCanvasResourceProvider *provider, QWidget *parent) : QWidget(parent), m_d(new Private) { m_d->ui = new Ui_KisToolLazyBrushOptionsWidget(); m_d->ui->setupUi(this); m_d->colorModel = new KisPaletteModel(this); m_d->ui->colorView->setPaletteModel(m_d->colorModel); m_d->ui->colorView->setAllowModification(false); //people proly shouldn't be able to edit the colorentries themselves. m_d->ui->colorView->setCrossedKeyword("transparent"); connect(m_d->ui->chkUseEdgeDetection, SIGNAL(toggled(bool)), SLOT(slotUseEdgeDetectionChanged(bool))); connect(m_d->ui->intEdgeDetectionSize, SIGNAL(valueChanged(int)), SLOT(slotEdgeDetectionSizeChanged(int))); connect(m_d->ui->intRadius, SIGNAL(valueChanged(int)), SLOT(slotRadiusChanged(int))); connect(m_d->ui->intCleanUp, SIGNAL(valueChanged(int)), SLOT(slotCleanUpChanged(int))); connect(m_d->ui->chkLimitToDevice, SIGNAL(toggled(bool)), SLOT(slotLimitToDeviceChanged(bool))); m_d->ui->intEdgeDetectionSize->setRange(0, 100); m_d->ui->intEdgeDetectionSize->setExponentRatio(2.0); m_d->ui->intEdgeDetectionSize->setSuffix(i18n(" px")); m_d->ui->intEdgeDetectionSize->setPrefix(i18n("Edge detection: ")); m_d->ui->intEdgeDetectionSize->setToolTip( i18nc("@info:tooltip", "Activate for images with vast solid areas. " "Set the value to the width of the thinnest " "lines on the image")); m_d->ui->intRadius->setRange(0, 1000); m_d->ui->intRadius->setExponentRatio(3.0); m_d->ui->intRadius->setSuffix(i18n(" px")); m_d->ui->intRadius->setPrefix(i18n("Gap close hint: ")); m_d->ui->intRadius->setToolTip( i18nc("@info:tooltip", "The mask will try to close non-closed contours " "if the gap is smaller than \"Gap close hint\" value")); m_d->ui->intCleanUp->setRange(0, 100); m_d->ui->intCleanUp->setSuffix(i18n(" %")); m_d->ui->intCleanUp->setPrefix(i18n("Clean up: ")); m_d->ui->intCleanUp->setToolTip( i18nc("@info:tooltip", "The mask will try to remove parts of the key strokes " "that are placed outside the closed contours. 0% - no effect, 100% - max effect")); connect(m_d->ui->colorView, SIGNAL(indexEntrySelected(QModelIndex)), this, SLOT(entrySelected(QModelIndex))); connect(m_d->ui->btnTransparent, SIGNAL(toggled(bool)), this, SLOT(slotMakeTransparent(bool))); connect(m_d->ui->btnRemove, SIGNAL(clicked()), this, SLOT(slotRemove())); connect(m_d->ui->chkAutoUpdates, SIGNAL(toggled(bool)), m_d->ui->btnUpdate, SLOT(setDisabled(bool))); connect(m_d->ui->btnUpdate, SIGNAL(clicked()), this, SLOT(slotUpdate())); connect(m_d->ui->chkAutoUpdates, SIGNAL(toggled(bool)), this, SLOT(slotSetAutoUpdates(bool))); connect(m_d->ui->chkShowKeyStrokes, SIGNAL(toggled(bool)), this, SLOT(slotSetShowKeyStrokes(bool))); connect(m_d->ui->chkShowOutput, SIGNAL(toggled(bool)), this, SLOT(slotSetShowOutput(bool))); connect(&m_d->baseNodeChangedCompressor, SIGNAL(timeout()), this, SLOT(slotUpdateNodeProperties())); m_d->provider = provider; const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(); - m_d->colorSet.add(KoColorSetEntry(KoColor(Qt::red, cs), "color1")); - m_d->colorSet.add(KoColorSetEntry(KoColor(Qt::green, cs), "color2")); - m_d->colorSet.add(KoColorSetEntry(KoColor(Qt::blue, cs), "color3")); + m_d->colorSet.add(KisSwatch(KoColor(Qt::red, cs), "color1")); + m_d->colorSet.add(KisSwatch(KoColor(Qt::green, cs), "color2")); + m_d->colorSet.add(KisSwatch(KoColor(Qt::blue, cs), "color3")); m_d->colorModel->setColorSet(&m_d->colorSet); } KisToolLazyBrushOptionsWidget::~KisToolLazyBrushOptionsWidget() { } void KisToolLazyBrushOptionsWidget::showEvent(QShowEvent *event) { QWidget::showEvent(event); m_d->providerSignals.addConnection( m_d->provider, SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(slotCurrentNodeChanged(KisNodeSP))); m_d->providerSignals.addConnection( m_d->provider, SIGNAL(sigFGColorChanged(const KoColor&)), this, SLOT(slotCurrentFgColorChanged(const KoColor&))); slotCurrentNodeChanged(m_d->provider->currentNode()); slotCurrentFgColorChanged(m_d->provider->fgColor()); } void KisToolLazyBrushOptionsWidget::hideEvent(QHideEvent *event) { QWidget::hideEvent(event); m_d->providerSignals.clear(); } void KisToolLazyBrushOptionsWidget::entrySelected(QModelIndex index) { if (!index.isValid()) return; const int i = m_d->colorModel->idFromIndex(index); if (i >= 0 && i < (int)m_d->colorSet.nColors()) { - KoColorSetEntry entry = m_d->colorModel->colorSetEntryFromIndex(index); + KisSwatch entry = m_d->colorModel->colorSetEntryFromIndex(index); m_d->provider->setFGColor(entry.color()); } const bool transparentChecked = i >= 0 && i == m_d->transparentColorIndex; KisSignalsBlocker b(m_d->ui->btnTransparent); m_d->ui->btnTransparent->setChecked(transparentChecked); } void KisToolLazyBrushOptionsWidget::slotCurrentFgColorChanged(const KoColor &color) { /* int selectedIndex = -1; for (quint32 i = 0; i < m_d->colorSet.nColors(); i++) { KoColorSetEntry entry = m_d->colorSet.getColorGlobal(i); if (entry.color() == color) { selectedIndex = (int)i; break; } } m_d->ui->btnRemove->setEnabled(selectedIndex >= 0); m_d->ui->btnTransparent->setEnabled(selectedIndex >= 0); if (selectedIndex < 0) { KisSignalsBlocker b(m_d->ui->btnTransparent); m_d->ui->btnTransparent->setChecked(false); } QModelIndex newIndex = selectedIndex >= 0 ? m_d->colorModel->indexFromId(selectedIndex) : QModelIndex(); if (newIndex != m_d->ui->colorView->currentIndex()) { m_d->ui->colorView->setCurrentIndex(newIndex); } */ } void KisToolLazyBrushOptionsWidget::slotColorLabelsChanged() { m_d->colorSet.clear(); m_d->transparentColorIndex = -1; if (m_d->activeMask) { KisColorizeMask::KeyStrokeColors colors = m_d->activeMask->keyStrokesColors(); m_d->transparentColorIndex = colors.transparentIndex; for (int i = 0; i < colors.colors.size(); i++) { const QString name = i == m_d->transparentColorIndex ? "transparent" : ""; - m_d->colorSet.add(KoColorSetEntry(colors.colors[i], name)); + m_d->colorSet.add(KisSwatch(colors.colors[i], name)); } } m_d->colorModel->setColorSet(&m_d->colorSet); slotCurrentFgColorChanged(m_d->provider->fgColor()); } void KisToolLazyBrushOptionsWidget::slotUpdateNodeProperties() { KisSignalsBlocker b1(m_d->ui->chkAutoUpdates, m_d->ui->btnUpdate, m_d->ui->chkShowKeyStrokes, m_d->ui->chkShowOutput); KisSignalsBlocker b2(m_d->ui->chkUseEdgeDetection, m_d->ui->intEdgeDetectionSize, m_d->ui->intRadius, m_d->ui->intCleanUp, m_d->ui->chkLimitToDevice); // not implemented yet! //m_d->ui->chkAutoUpdates->setEnabled(m_d->activeMask); m_d->ui->chkAutoUpdates->setEnabled(false); m_d->ui->chkAutoUpdates->setVisible(false); bool value = false; value = m_d->activeMask && KisLayerPropertiesIcons::nodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeNeedsUpdate, true).toBool(); m_d->ui->btnUpdate->setEnabled(m_d->activeMask && !m_d->ui->chkAutoUpdates->isChecked() && value); value = m_d->activeMask && KisLayerPropertiesIcons::nodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, true).toBool(); m_d->ui->chkShowKeyStrokes->setEnabled(m_d->activeMask); m_d->ui->chkShowKeyStrokes->setChecked(value); value = m_d->activeMask && KisLayerPropertiesIcons::nodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeShowColoring, true).toBool(); m_d->ui->chkShowOutput->setEnabled(m_d->activeMask); m_d->ui->chkShowOutput->setChecked(value); m_d->ui->chkUseEdgeDetection->setEnabled(m_d->activeMask); m_d->ui->chkUseEdgeDetection->setChecked(m_d->activeMask && m_d->activeMask->useEdgeDetection()); m_d->ui->intEdgeDetectionSize->setEnabled(m_d->activeMask && m_d->ui->chkUseEdgeDetection->isChecked()); m_d->ui->intEdgeDetectionSize->setValue(m_d->activeMask ? m_d->activeMask->edgeDetectionSize() : 4.0); m_d->ui->intRadius->setEnabled(m_d->activeMask); m_d->ui->intRadius->setValue(2 * (m_d->activeMask ? m_d->activeMask->fuzzyRadius() : 15)); m_d->ui->intCleanUp->setEnabled(m_d->activeMask); m_d->ui->intCleanUp->setValue(100 * (m_d->activeMask ? m_d->activeMask->cleanUpAmount() : 0.7)); m_d->ui->chkLimitToDevice->setEnabled(m_d->activeMask); m_d->ui->chkLimitToDevice->setChecked(m_d->activeMask && m_d->activeMask->limitToDeviceBounds()); } void KisToolLazyBrushOptionsWidget::slotCurrentNodeChanged(KisNodeSP node) { m_d->maskSignals.clear(); KisColorizeMask *mask = dynamic_cast(node.data()); m_d->activeMask = mask; if (m_d->activeMask) { m_d->maskSignals.addConnection( m_d->activeMask, SIGNAL(sigKeyStrokesListChanged()), this, SLOT(slotColorLabelsChanged())); m_d->maskSignals.addConnection( m_d->provider->currentImage(), SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(slotUpdateNodeProperties())); } slotColorLabelsChanged(); slotUpdateNodeProperties(); m_d->ui->colorView->setEnabled(m_d->activeMask); } void KisToolLazyBrushOptionsWidget::slotMakeTransparent(bool value) { KIS_ASSERT_RECOVER_RETURN(m_d->activeMask); QModelIndex index = m_d->ui->colorView->currentIndex(); if (!index.isValid()) return; const int activeIndex = m_d->colorModel->idFromIndex(index); KIS_ASSERT_RECOVER_RETURN(activeIndex >= 0); KisColorizeMask::KeyStrokeColors colors; /* for (quint32 i = 0; i < m_d->colorSet.nColors(); i++) { colors.colors << m_d->colorSet.getColorGlobal(i).color(); } */ colors.transparentIndex = value ? activeIndex : -1; m_d->activeMask->setKeyStrokesColors(colors); } void KisToolLazyBrushOptionsWidget::slotRemove() { KIS_ASSERT_RECOVER_RETURN(m_d->activeMask); QModelIndex index = m_d->ui->colorView->currentIndex(); if (!index.isValid()) return; const int activeIndex = m_d->colorModel->idFromIndex(index); KIS_ASSERT_RECOVER_RETURN(activeIndex >= 0); const KoColor color; //m_d->colorSet.getColorGlobal((quint32)activeIndex).color(); m_d->activeMask->removeKeyStroke(color); } void KisToolLazyBrushOptionsWidget::slotUpdate() { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); KisLayerPropertiesIcons::setNodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeNeedsUpdate, false, m_d->provider->currentImage()); } void KisToolLazyBrushOptionsWidget::slotSetAutoUpdates(bool value) { // not implemented yet! ENTER_FUNCTION() << ppVar(value); } void KisToolLazyBrushOptionsWidget::slotSetShowKeyStrokes(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); KisLayerPropertiesIcons::setNodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, value, m_d->provider->currentImage()); } void KisToolLazyBrushOptionsWidget::slotSetShowOutput(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); KisLayerPropertiesIcons::setNodeProperty(m_d->activeMask, KisLayerPropertiesIcons::colorizeShowColoring, value, m_d->provider->currentImage()); } void KisToolLazyBrushOptionsWidget::slotUseEdgeDetectionChanged(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setUseEdgeDetection(value); m_d->ui->intEdgeDetectionSize->setEnabled(value); } void KisToolLazyBrushOptionsWidget::slotEdgeDetectionSizeChanged(int value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setEdgeDetectionSize(value); } void KisToolLazyBrushOptionsWidget::slotRadiusChanged(int value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setFuzzyRadius(0.5 * value); } void KisToolLazyBrushOptionsWidget::slotCleanUpChanged(int value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setCleanUpAmount(qreal(value) / 100.0); } void KisToolLazyBrushOptionsWidget::slotLimitToDeviceChanged(bool value) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->activeMask); m_d->activeMask->setLimitToDeviceBounds(value); }