diff --git a/libs/pigment/resources/KoColorSet.h b/libs/pigment/resources/KoColorSet.h --- a/libs/pigment/resources/KoColorSet.h +++ b/libs/pigment/resources/KoColorSet.h @@ -86,14 +86,90 @@ void setColumnCount(int columns); int columnCount(); + /** + * @brief comment + * @return the comment. + */ + QString comment(); public: - void add(const KoColorSetEntry &); - void remove(const KoColorSetEntry &); - void removeAt(quint32 index); - KoColorSetEntry getColor(quint32 index); - qint32 nColors(); + /** + * @brief add Add a color to the palette. + * @param groupName color to add the group to. If empty, it will be added to the unsorted. + */ + void add(const KoColorSetEntry &, QString groupName = QString()); + + /** + * @brief insertBefore insert color before index into group. + * @param index + * @param groupName name of the group that the color goes into. + * @return new index of index after the prepending. + */ + quint32 insertBefore(const KoColorSetEntry &, qint32 index, QString groupName = QString()); + + void remove(const KoColorSetEntry &);//unsure + /** + * @brief removeAt remove the color at this index. + * @param index index to remove at + * @param groupName group in which the color is. + */ + void removeAt(quint32 index, QString groupName = QString()); + + /** + * @brief getColorGlobal + * A function for getting a color based on a global index. Useful for itterating through all color entries. + * @param globalIndex the global index over the whole palette. + * @return the entry. + */ + KoColorSetEntry getColorGlobal(quint32 globalIndex); + /** + * @brief getColorGroup + * A function for getting the color from a specific group. + * @param groupName the name of the group, will give unosrted when not defined. + * @param index the index within the group. + * @return the entry + */ + KoColorSetEntry getColorGroup(quint32 index, QString groupName = QString()); + + QString findGroupByGlobalIndex(quint32 globalIndex, quint32 *index); + QString findGroupByColorName(QString name, quint32 *index); + QString findGroupByID(QString id,quint32 *index); + + /** + * @brief getGroupNames + * @return returns a list of group names, excluding the unsorted group. + */ + QStringList getGroupNames(); + + /** + * @brief nColorsGroup + * @param groupName string name of the group, when not specified, returns unsorted colors. + * @return the amount of colors in this group. + */ + quint32 nColorsGroup(QString groupName = QString()); + /** + * @brief nColors + * @return total colors in palette. + */ + quint32 nColors(); + + /** + * @brief addGroup + * Adds a new group. + * @param groupName the name of the new group. When not specified, this will fail. + * @return whether thegroup was made. + */ + bool addGroup(QString groupName = QString()); + /** + * @brief removeGroup + * Remove a group from the KoColorSet + * @param groupName the name of the group you want to remove. + * @param keepColors Whether you wish to keep the colorsetentries. These will be added to the unsorted. + * @return whether it could find the group to remove. + */ + bool removeGroup(QString groupName = QString(), bool keepColors = true); + void clear(); /** @@ -105,7 +181,7 @@ * when the two colors' colorspaces don't match. Else it'll use the entry's colorspace. * @return returns the int of the closest match. */ - qint32 getIndexClosestColor(KoColor color, bool useGivenColorSpace = true); + quint32 getIndexClosestColor(KoColor color, bool useGivenColorSpace = true); /** * @brief closestColorName diff --git a/libs/pigment/resources/KoColorSet.cpp b/libs/pigment/resources/KoColorSet.cpp --- a/libs/pigment/resources/KoColorSet.cpp +++ b/libs/pigment/resources/KoColorSet.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,9 @@ QByteArray data; QString comment; qint32 columns; - QVector colors; + QVector colors; //ungrouped colors + QStringList groupNames; //names of the groups, this is used to determine the order they are in. + QMap> groups; //grouped colors. }; KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba) { @@ -152,42 +155,6 @@ return true; } -qint32 KoColorSet::nColors() -{ - return d->colors.count(); -} - -qint32 KoColorSet::getIndexClosestColor(KoColor color, bool useGivenColorSpace) -{ - qint32 closestIndex = 0; - quint8 highestPercentage = 0; - quint8 testPercentage = 0; - KoColor compare = color; - for (qint32 i=0; icolors.at(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; -} - -QString KoColorSet::closestColorName(KoColor color, bool useGivenColorSpace) -{ - int i = getIndexClosestColor(color, useGivenColorSpace); - QString name = d->colors.at(i).name; - return name; -} - bool KoColorSet::saveToDevice(QIODevice *dev) const { bool res; @@ -297,9 +264,79 @@ return true; } -void KoColorSet::add(const KoColorSetEntry & c) +quint32 KoColorSet::nColors() +{ + quint32 total = d->colors.count(); + if (!d->groups.empty()) { + QStringList groupNames = getGroupNames(); + Q_FOREACH (QString name, groupNames) { + total += d->groups[name].size(); + } + } + return total; +} + +quint32 KoColorSet::nColorsGroup(QString groupName) { + if (d->groups.contains(groupName)) { + return d->groups.value(groupName).size(); + } else if (groupName == QString()){ + return d->colors.size(); + } else { + return 0; + } +} + +quint32 KoColorSet::getIndexClosestColor(KoColor color, bool useGivenColorSpace) +{ + quint32 closestIndex = 0; + quint8 highestPercentage = 0; + quint8 testPercentage = 0; + KoColor compare = color; + for (quint32 i=0; idifference(compare.data(), entry.data())); + if (testPercentage>highestPercentage) + { + closestIndex = i; + highestPercentage = testPercentage; + } + } + return closestIndex; +} + +QString KoColorSet::closestColorName(KoColor color, bool useGivenColorSpace) +{ + int i = getIndexClosestColor(color, useGivenColorSpace); + QString name = d->colors.at(i).name; + return name; +} + +void KoColorSet::add(const KoColorSetEntry & c, QString groupName) { - d->colors.push_back(c); + if (d->groups.contains(groupName) || d->groupNames.contains(groupName)) { + d->groups[groupName].push_back(c); + } else { + d->colors.push_back(c); + } +} + +quint32 KoColorSet::insertBefore(const KoColorSetEntry &c, qint32 index, QString groupName) +{ + quint32 newIndex = index; + if (d->groups.contains(groupName)) { + d->groups[groupName].insert(index, c); + } else if (groupName == QString()){ + d->colors.insert(index, c);; + } else { + warnPigment << "Couldn't find group to insert to"; + } + return newIndex; } void KoColorSet::remove(const KoColorSetEntry & c) @@ -311,21 +348,138 @@ } ++it; } + QMap>::const_iterator g = d->groups.constBegin(); + while (g!= d->groups.constEnd()) { + for (auto it = d->groups[g.key()].begin(); it != d->groups[g.key()].end(); /*noop*/) { + if ((*it) == c) { + it = d->groups[g.key()].erase(it); + return; + } + ++it; + } + ++g; + } } -void KoColorSet::removeAt(quint32 index) +void KoColorSet::removeAt(quint32 index, QString groupName) { - d->colors.remove(index); + if (d->groups.contains(groupName)){ + if ((quint32)d->groups.value(groupName).size()>index) { + d->groups[groupName].remove(index); + } + } else { + if ((quint32)d->colors.size()>index) { + d->colors.remove(index); + } + } } void KoColorSet::clear() { d->colors.clear(); + d->groups.clear(); +} + +KoColorSetEntry KoColorSet::getColorGlobal(quint32 index) +{ + KoColorSetEntry e; + quint32 groupIndex = index; + QString groupName = findGroupByGlobalIndex(index, &groupIndex); + e = getColorGroup(groupIndex, groupName); + return e; +} + +KoColorSetEntry KoColorSet::getColorGroup(quint32 index, QString groupName) +{ + KoColorSetEntry e; + if (d->groups.contains(groupName) && index<(quint32)d->groups.value(groupName).size()) { + e = d->groups.value(groupName).at(index); + } else if (groupName == QString() && index<(quint32)d->colors.size()) { + e = d->colors.at(index); + } else { + warnPigment << "Color group "<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(QString name, quint32 *index) { + *index = (quint32)0; + QString groupName = QString(); + for (int i = 0; icolors.size(); i++) { + if(d->colors.at(i).name == name) { + *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).name == name) { + *index = (quint32)i; + groupName = name; + return groupName; + } + } + } + return groupName; +} + +QString KoColorSet::findGroupByID(QString id, quint32 *index) { + *index = (quint32)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; } -KoColorSetEntry KoColorSet::getColor(quint32 index) +QStringList KoColorSet::getGroupNames() { - return d->colors[index]; + if (d->groupNames.size()groups.size()) { + warnPigment << "mismatch between groups and the groupnames list. Will rectify for now."; + Q_FOREACH(QString name, d->groups.keys()) { + if (!d->groupNames.contains(name)) { + d->groupNames.append(name); + } + } + } + return d->groupNames; } void KoColorSet::setColumnCount(int columns) @@ -338,6 +492,41 @@ return d->columns; } +QString KoColorSet::comment() +{ + return d->comment; +} + +bool KoColorSet::addGroup(QString groupName) +{ + if (d->groups.contains(groupName) || d->groupNames.contains(groupName)) { + return false; + } + d->groupNames.append(groupName); + d->groups[groupName]; + return true; +} + +bool KoColorSet::removeGroup(QString groupName, bool keepColors) +{ + if (!d->groups.contains(groupName)) { + return false; + } + if (keepColors) { + for (int i = 0; igroups.value(groupName).size(); i++) { + d->colors.append(d->groups.value(groupName).at(i)); + } + } + 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"); @@ -696,6 +885,28 @@ entry.color.toXML(doc, el); root.appendChild(el); } + Q_FOREACH(const QString groupName, d->groupNames) { + QDomElement gl = doc.createElement("Group"); + gl.setAttribute("name", groupName); + root.appendChild(gl); + Q_FOREACH(const KoColorSetEntry &entry, d->groups.value(groupName)) { + + // 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(); @@ -799,9 +1010,31 @@ entry.spotColor = c.attribute("spot", "false") == "true" ? true : false; d->colors << entry; - c = c.nextSiblingElement(); + c = c.nextSiblingElement("ColorSetEntry"); } + QDomElement g = e.firstChildElement("Group"); + while (!g.isNull()) { + QString groupName = g.attribute("name"); + addGroup(groupName); + QDomElement cg = g.firstChildElement("ColorSetEntry"); + while (!cg.isNull()) { + QString colorDepthId = e.attribute("bitdepth", Integer8BitsColorDepthID.id()); + KoColorSetEntry entry; + + + entry.color = KoColor::fromXML(cg.firstChildElement(), colorDepthId); + entry.name = cg.attribute("name"); + entry.id = cg.attribute("id"); + entry.spotColor = cg.attribute("spot", "false") == "true" ? true : false; + add(entry, groupName); + + cg = cg.nextSiblingElement("ColorSetEntry"); + + } + g = g.nextSiblingElement("Group"); + } + } diff --git a/libs/ui/KisColorsetChooser.cpp b/libs/ui/KisColorsetChooser.cpp --- a/libs/ui/KisColorsetChooser.cpp +++ b/libs/ui/KisColorsetChooser.cpp @@ -76,9 +76,9 @@ painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, colorSet->name()); int size = 7; - for (int i = 0; i < colorSet->nColors() && i*size < option.rect.width(); i++) { + for (quint32 i = 0; i < colorSet->nColors() && i*size < option.rect.width(); i++) { QRect rect(option.rect.x() + i*size, option.rect.y() + option.rect.height() - size, size, size); - painter->fillRect(rect, colorSet->getColor(i).color.toQColor()); + painter->fillRect(rect, colorSet->getColorGlobal(i).color.toQColor()); } painter->restore(); diff --git a/libs/ui/KisPaletteModel.cpp b/libs/ui/KisPaletteModel.cpp --- a/libs/ui/KisPaletteModel.cpp +++ b/libs/ui/KisPaletteModel.cpp @@ -60,14 +60,14 @@ QVariant KisPaletteModel::data(const QModelIndex& index, int role) const { if (m_colorSet) { - int i = index.row()*columnCount()+index.column(); + quint32 i = (quint32)(index.row()*columnCount()+index.column()); if (i < m_colorSet->nColors()) { switch (role) { case Qt::DisplayRole: { - return m_colorSet->getColor(i).name; + return m_colorSet->getColorGlobal(i).name; } case Qt::BackgroundRole: { - QColor color = m_displayRenderer->toQColor(m_colorSet->getColor(i).color); + QColor color = m_displayRenderer->toQColor(m_colorSet->getColorGlobal(i).color); return QBrush(color); } } @@ -104,7 +104,7 @@ QModelIndex KisPaletteModel::index(int row, int column, const QModelIndex& parent) const { int index = row*columnCount()+column; - if (m_colorSet && index < m_colorSet->nColors()) { + if (m_colorSet && (quint32)index < m_colorSet->nColors()) { return QAbstractTableModel::index(row, column, parent); } return QModelIndex(); diff --git a/libs/widgets/KoColorSetWidget.cpp b/libs/widgets/KoColorSetWidget.cpp --- a/libs/widgets/KoColorSetWidget.cpp +++ b/libs/widgets/KoColorSetWidget.cpp @@ -68,20 +68,21 @@ colorNameCmb->clear(); if (colorSet) { - for( int i = 0, p= 0; i < colorSet->nColors(); i++) { + for( quint32 i = 0, p= 0; i < colorSet->nColors(); i++) { KoColorPatch *patch = new KoColorPatch(colorSetContainer); patch->setFrameStyle(QFrame::Plain | QFrame::Box); patch->setLineWidth(1); - patch->setColor(colorSet->getColor(i).color); - patch->setToolTip(colorSet->getColor(i).name); + KoColorSetEntry c = colorSet->getColorGlobal(i); + patch->setColor(c.color); + patch->setToolTip(c.name); connect(patch, SIGNAL(triggered(KoColorPatch *)), thePublic, SLOT(colorTriggered(KoColorPatch *))); colorSetLayout->addWidget(patch, p/columns, p%columns); patch->setDisplayRenderer(displayRenderer); patchWidgetList.append(patch); - colornames.append(colorSet->getColor(i).name); + colornames.append(c.name); QPixmap colorsquare = QPixmap(12,12); - colorsquare.fill(colorSet->getColor(i).color.toQColor()); - colorNameCmb->addItem(QIcon(colorsquare), colorSet->getColor(i).name); + colorsquare.fill(c.color.toQColor()); + colorNameCmb->addItem(QIcon(colorsquare), c.name); ++p; } } diff --git a/libs/widgets/KoEditColorSetDialog.cpp b/libs/widgets/KoEditColorSetDialog.cpp --- a/libs/widgets/KoEditColorSetDialog.cpp +++ b/libs/widgets/KoEditColorSetDialog.cpp @@ -133,10 +133,11 @@ columns = m_activeColorSet->columnCount(); if (columns==0){columns=16;} widget.remove->setEnabled(false); - for (int i = 0; i < m_activeColorSet->nColors(); i++) { + for (quint32 i = 0; i < m_activeColorSet->nColors(); i++) { KoColorPatch *patch = new KoColorPatch(widget.patchesFrame); - patch->setColor(m_activeColorSet->getColor(i).color); - patch->setToolTip(m_activeColorSet->getColor(i).name); + KoColorSetEntry c = m_activeColorSet->getColorGlobal(i); + patch->setColor(c.color); + patch->setToolTip(c.name); connect(patch, SIGNAL(triggered(KoColorPatch *)), this, SLOT(setTextLabel(KoColorPatch *))); m_gridLayout->addWidget(patch, i/columns, i%columns); } @@ -183,9 +184,10 @@ void KoEditColorSetWidget::removeColor() { Q_ASSERT(m_activeColorSet); - for (int i = 0; i < m_activeColorSet->nColors(); i++) { - if (m_activePatch->color() == m_activeColorSet->getColor(i).color) { - m_activeColorSet->remove(m_activeColorSet->getColor(i)); + for (quint32 i = 0; i < m_activeColorSet->nColors(); i++) { + KoColorSetEntry c = m_activeColorSet->getColorGlobal(i); + if (m_activePatch->color() == c.color) { + m_activeColorSet->remove(c); setActiveColorSet(widget.selector->currentIndex()); break; } diff --git a/plugins/dockers/palettedocker/palettedocker_dock.cpp b/plugins/dockers/palettedocker/palettedocker_dock.cpp --- a/plugins/dockers/palettedocker/palettedocker_dock.cpp +++ b/plugins/dockers/palettedocker/palettedocker_dock.cpp @@ -222,10 +222,16 @@ return; } - int i = index.row()*m_model->columnCount()+index.column(); + quint32 i = (quint32)(index.row()*m_model->columnCount()+index.column()); if (i < m_currentColorSet->nColors()) { - KoColorSetEntry entry = m_currentColorSet->getColor(i); - m_wdgPaletteDock->lblColorName->setText(entry.name); + KoColorSetEntry entry = m_currentColorSet->getColorGlobal(i); + quint32 li = 0; + QString groupName = m_currentColorSet->findGroupByGlobalIndex(i, &li); + if (groupName != QString()) { + groupName = groupName+" - "; + } + m_wdgPaletteDock->lblColorName->setText(groupName+entry.name); + qDebug()<<"The index of the currently selected color within its group is: "<setFGColor(entry.color); } diff --git a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp --- a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp +++ b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp @@ -74,7 +74,7 @@ const int pixelSize = device->colorSpace()->pixelSize(); do { grey = device->colorSpace()->intensity8(it.oldRawData()); - outColor = gradientCache->getColor((quint32)grey).color; + outColor = gradientCache->getColorGlobal((quint32)grey).color; outColor.setOpacity(qMin(KoColor(it.oldRawData(), device->colorSpace()).opacityF(), outColor.opacityF())); outColor.convertTo(device->colorSpace()); memcpy(it.rawData(), outColor.data(), pixelSize); 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 --- a/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp +++ b/plugins/tools/tool_lazybrush/kis_tool_lazy_brush_options_widget.cpp @@ -123,10 +123,10 @@ { if (!index.isValid()) return; - const int i = m_d->colorModel->idFromIndex(index); + const quint32 i = (quint32)m_d->colorModel->idFromIndex(index); if (i >= 0 && i < m_d->colorSet.nColors()) { - KoColorSetEntry entry = m_d->colorSet.getColor(i); + KoColorSetEntry entry = m_d->colorSet.getColorGlobal(i); m_d->provider->setFGColor(entry.color); } @@ -139,10 +139,10 @@ { int selectedIndex = -1; - for (int i = 0; i < m_d->colorSet.nColors(); i++) { - KoColorSetEntry entry = m_d->colorSet.getColor(i); + for (quint32 i = 0; i < m_d->colorSet.nColors(); i++) { + KoColorSetEntry entry = m_d->colorSet.getColorGlobal(i); if (entry.color == color) { - selectedIndex = i; + selectedIndex = (int)i; break; } } @@ -241,8 +241,8 @@ KisColorizeMask::KeyStrokeColors colors; - for (int i = 0; i < m_d->colorSet.nColors(); i++) { - colors.colors << m_d->colorSet.getColor(i).color; + for (quint32 i = 0; i < m_d->colorSet.nColors(); i++) { + colors.colors << m_d->colorSet.getColorGlobal(i).color; } colors.transparentIndex = value ? activeIndex : -1; @@ -261,7 +261,7 @@ KIS_ASSERT_RECOVER_RETURN(activeIndex >= 0); - const KoColor color = m_d->colorSet.getColor(activeIndex).color; + const KoColor color = m_d->colorSet.getColorGlobal((quint32)activeIndex).color; m_d->activeMask->removeKeyStroke(color); }