17#include <QDomDocument>
19#include <QDomNodeList>
23#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
31#include <QXmlStreamReader>
32#include <QXmlStreamAttributes>
34#include <QRegularExpression>
35#include <QRegularExpressionMatch>
38#include <klocalizedstring.h>
66 buffer.open(QBuffer::ReadOnly);
67 QTextStream stream(&buffer);
71 while (stream.readLineInto(&line)) {
124 QPair<int, int> pos = modifiedGroup->addSwatch(
m_swatch);
138 modifiedGroup->removeSwatch(
m_x,
m_y);
155 ,
m_swatch(group->getSwatch(column, row))
345 for (
const KisSwatchGroup::SwatchInfo &info :
m_oldGroup->infoList()) {
346 globalGroup->setSwatch(info.swatch,
366 for (
const KisSwatchGroup::SwatchInfo &info : globalGroup->infoList()) {
368 globalGroup->removeSwatch(info.column,
524 switch(paletteType) {
576 d->paletteType = rhs.
d->paletteType;
577 d->data = rhs.
d->data;
578 d->comment = rhs.
d->comment;
579 d->swatchGroups = rhs.
d->swatchGroups;
593 Q_UNUSED(resourcesInterface);
595 if (!dev->isOpen()) dev->open(QIODevice::ReadOnly);
597 d->data = dev->readAll();
599 Q_ASSERT(
d->data.size() != 0);
607 switch(
d->paletteType) {
609 res =
d->saveGpl(dev);
612 res =
d->saveKpl(dev);
624 buf.open(QIODevice::ReadOnly);
630 return d->paletteType;
639 d->undoStack.push(cmd);
645 if (
d->isLocked)
return;
649 d->undoStack.push(cmd);
655 if (
d->isLocked)
return;
658 d->undoStack.push(cmd);
663 if (
d->isLocked)
return;
667 d->undoStack.push(cmd);
678 if (group->name().isEmpty()) {
679 rowInGroup = (int)row - titleRow;
682 rowInGroup = (int)row - (titleRow + 1);
685 Q_ASSERT((
isGroupTitleRow(titleRow) && titleRow > 0) || titleRow == 0);
686 Q_ASSERT(rowInGroup < group->
rowCount());
688 return group->getSwatch(column, rowInGroup);
696 if (group->name() == groupName) {
697 if (group->checkSwatchExists(column, row)) {
698 swatch = group->getSwatch(column, row);
710 groupNames << group->name();
719 idx += group->rowCount();
732 if (groupName.isEmpty())
return 0;
736 if (group->name() == groupName) {
739 row += group->rowCount();
754 for (
int i = rowNumber; i > -1; i--) {
777 if (!groupName.isEmpty()) {
796 if (
d->undoStack.canUndo()) {
806 if (!
swatchGroupNames().contains(oldGroupName) || (oldGroupName == newGroupName) ||
d->isLocked)
return;
809 d->undoStack.push(cmd);
814 if (
d->isLocked || (columns ==
d->columns))
return;
818 d->undoStack.push(cmd);
823 Q_ASSERT(
d->swatchGroups.size() > 0);
825 return d->swatchGroups.first()->columnCount();
835 if (
d->isLocked ||
comment ==
d->comment)
return;
839 d->undoStack.push(cmd);
848 d->undoStack.push(cmd);
854 if (!groupNames.contains(groupName)
855 || !groupNames.contains(groupNameInsertBefore)
856 ||
d->isLocked)
return;
860 d->undoStack.push(cmd);
871 d->undoStack.push(cmd);
876 return (
d->paletteType ==
GPL) ?
".gpl" :
".kpl";
881 return &
d->undoStack;
898 res += group->rowCount();
905 return rowCount() +
d->swatchGroups.size() - 1;
929 if (group->name() ==
name) {
946 int groupRowCount = group->rowCount();
955 bool hit = (currentRow <= row && row < currentRow + groupRowCount);
961 currentRow += group->rowCount();
976 Q_ASSERT(
d->swatchGroups.size() > 0);
978 return d->swatchGroups.first();
983 KisSwatchGroup::SwatchInfo closestSwatch;
985 quint8 highestPercentage = 0;
986 quint8 testPercentage = 0;
989 for (
const KisSwatchGroup::SwatchInfo &currInfo : group->infoList()) {
990 KoColor color = currInfo.swatch.color();
998 if (testPercentage > highestPercentage)
1000 highestPercentage = testPercentage;
1001 closestSwatch = currInfo;
1005 return closestSwatch;
1014 int lastRowInGroup = 0;
1015 for (
const KisSwatchGroup::SwatchInfo &info : group->infoList()) {
1016 lastRowInGroup = qMax(lastRowInGroup, info.row);
1018 rows += (lastRowInGroup + 1);
1021 QImage img(
d->global()->columnCount() * 4, rows * 4, QImage::Format_ARGB32);
1023 gc.fillRect(img.rect(), Qt::darkGray);
1027 int lastRowGroup = 0;
1028 for (
const KisSwatchGroup::SwatchInfo &info : group->infoList()) {
1029 QColor c = info.swatch.color().toQColor();
1030 gc.fillRect(info.column * 4, (lastRow + info.row) * 4, 4, 4, c);
1031 lastRowGroup = qMax(lastRowGroup, info.row);
1033 lastRow += (lastRowGroup + 1);
1042 : colorSet(a_colorSet)
1053 QFileInfo fi(fileName);
1056 if (ba.startsWith(
"RIFF") && ba.indexOf(
"PAL data", 8)) {
1060 else if (ba.startsWith(
"GIMP Palette")) {
1064 else if (ba.startsWith(
"JASC-PAL")) {
1067 else if (ba.contains(
"krita/x-colorset") || ba.contains(
"application/x-krita-palette")) {
1070 else if (fi.suffix().toLower() ==
"aco") {
1073 else if (fi.suffix().toLower() ==
"act") {
1076 else if (fi.suffix().toLower() ==
"xml") {
1079 else if (fi.suffix().toLower() ==
"sbz") {
1082 else if (fi.suffix().toLower() ==
"ase" || ba.startsWith(
"ASEF")) {
1085 else if (fi.suffix().toLower() ==
"acb" || ba.startsWith(
"8BCB")) {
1088 else if (fi.suffix().toLower() ==
"css") {
1098 QXmlStreamAttributes colorProperties = xml->attributes();
1099 auto colorName = colorProperties.value(
"NAME");
1100 colorEntry.
setName(colorName.isEmpty() || colorName.isNull() ? i18n(
"Untitled") : colorName.toString());
1103 if (colorProperties.hasAttribute(
"RGB")) {
1104 dbgPigment <<
"Color " << colorProperties.value(
"NAME") <<
", RGB " << colorProperties.value(
"RGB");
1107 auto colorValue = colorProperties.value(
"RGB");
1109 if (colorValue.length() != 7 && colorValue.at(0) !=
'#') {
1110 xml->raiseError(
"Invalid rgb8 color (malformed): " + colorValue);
1114 quint32 rgb = colorValue.mid(1).toUInt(&rgbOk, 16);
1116 xml->raiseError(
"Invalid rgb8 color (unable to convert): " + colorValue);
1120 quint8 r = rgb >> 16 & 0xff;
1121 quint8 g = rgb >> 8 & 0xff;
1122 quint8 b = rgb & 0xff;
1124 dbgPigment <<
"Color parsed: "<< r << g << b;
1126 currentColor.
data()[0] = r;
1127 currentColor.
data()[1] = g;
1128 currentColor.
data()[2] = b;
1134 while(xml->readNextStartElement()) {
1136 xml->skipCurrentElement();
1141 else if (colorProperties.hasAttribute(
"CMYK")) {
1142 dbgPigment <<
"Color " << colorProperties.value(
"NAME") <<
", CMYK " << colorProperties.value(
"CMYK");
1145 auto colorValue = colorProperties.value(
"CMYK");
1147 if (colorValue.length() != 9 && colorValue.at(0) !=
'#') {
1148 xml->raiseError(
"Invalid cmyk color (malformed): " % colorValue);
1153 quint32 cmyk = colorValue.mid(1).toUInt(&cmykOk, 16);
1155 xml->raiseError(
"Invalid cmyk color (unable to convert): " % colorValue);
1159 quint8 c = cmyk >> 24 & 0xff;
1160 quint8 m = cmyk >> 16 & 0xff;
1161 quint8 y = cmyk >> 8 & 0xff;
1162 quint8 k = cmyk & 0xff;
1164 dbgPigment <<
"Color parsed: "<< c << m << y << k;
1166 currentColor.
data()[0] = c;
1167 currentColor.
data()[1] = m;
1168 currentColor.
data()[2] = y;
1169 currentColor.
data()[3] = k;
1175 while(xml->readNextStartElement()) {
1177 xml->skipCurrentElement();
1183 xml->raiseError(
"Unknown color space for color " + colorEntry.
name());
1191 QXmlStreamAttributes paletteProperties = xml->attributes();
1192 auto paletteName = paletteProperties.value(
"Name");
1193 dbgPigment <<
"Processed name of palette:" << paletteName;
1194 set->
setName(paletteName.toString());
1198 while(xml->readNextStartElement()) {
1199 auto currentElement = xml->name();
1200 if (currentElement.compare(QString(
"COLOR"), Qt::CaseInsensitive) == 0) {
1201 scribusParseColor(set, xml);
1204 xml->skipCurrentElement();
1208 if(xml->hasError()) {
1218 quint64 read = io->read((
char*)&val, 1);
1219 if (read != 1)
return false;
1225 quint64 read = io->read((
char*)&val, 2);
1226 if (read != 2)
return false;
1227 return qFromBigEndian(val);
1233 quint64 read = io->read((
char*)&val, 4);
1234 if (read != 4)
return false;
1235 return qFromBigEndian(val);
1241 quint64 read = io->read((
char*)&val, 4);
1242 if (read != 4)
return false;
1243 return qFromBigEndian(val);
1253 size = readShort(io)-1;
1256 QByteArray ba = io->read(size*2);
1257 if (ba.size() ==
int(size)*2) {
1258 QTextCodec *Utf16Codec = QTextCodec::codecForName(
"UTF-16BE");
1259 unicode = Utf16Codec->toUnicode(ba);
1261 warnPigment <<
"Unicode name block is the wrong size" << colorSet->filename();
1267 return unicode.trimmed();
1273 swatchGroups.clear();
1276 swatchGroups.append(globalGroup);
1279 if (colorSet->filename().isNull()) {
1280 warnPigment <<
"Cannot load palette" << colorSet->name() <<
"there is no filename set";
1283 if (data.isNull()) {
1284 QFile file(colorSet->filename());
1285 if (file.size() == 0) {
1286 warnPigment <<
"Cannot load palette" << colorSet->name() <<
"there is no data available";
1289 if (!file.open(QIODevice::ReadOnly)) {
1290 warnPigment <<
"Cannot load palette" << colorSet->name() <<
":" << file.errorString();
1293 data = file.readAll();
1298 paletteType = detectFormat(colorSet->filename(), data);
1337 int rowCount = global()->colorCount() / global()->columnCount();
1343 colorSet->setValid(res);
1344 colorSet->updateThumbnail();
1354 Q_ASSERT(dev->isOpen());
1355 Q_ASSERT(dev->isWritable());
1357 QTextStream stream(dev);
1359 stream <<
"GIMP Palette\nName: " << colorSet->name() <<
"\nColumns: " << colorSet->columnCount() <<
"\n#\n";
1362 for (
int y = 0; y < global->rowCount(); y++) {
1363 for (
int x = 0; x < colorSet->columnCount(); x++) {
1364 if (!global->checkSwatchExists(x, y)) {
1367 const KisSwatch& entry = global->getSwatch(x, y);
1369 stream << c.red() <<
" " << c.green() <<
" " << c.blue() <<
"\t";
1370 if (entry.
name().isEmpty())
1371 stream <<
"Untitled\n";
1373 stream << entry.
name() <<
"\n";
1382 if (data.isEmpty() || data.isNull() || data.length() < 50) {
1383 warnPigment <<
"Illegal Gimp palette file: " << colorSet->filename();
1391 if (lines.size() < 3) {
1392 warnPigment <<
"Not enough lines in palette file: " << colorSet->filename();
1396 QString columnsText;
1401 if (!lines[0].startsWith(
"GIMP") || !lines[1].toLower().contains(
"name")) {
1402 warnPigment <<
"Illegal Gimp palette file: " << colorSet->filename();
1407 colorSet->
setName(lines[1].split(
":")[1].trimmed());
1413 if (lines[index].toLower().contains(
"columns")) {
1414 columnsText = lines[index].split(
":")[1].trimmed();
1415 columns = columnsText.toInt();
1417 warnPigment <<
"Refusing to set unreasonable number of columns (" << columns <<
") in GIMP Palette file " << colorSet->filename() <<
" - using maximum number of allowed columns instead";
1421 global()->setColumnCount(columns);
1427 for (qint32 i = index; i < lines.size(); i++) {
1428 if (lines[i].startsWith(
'#')) {
1429 comment += lines[i].mid(1).trimmed() +
' ';
1430 }
else if (!lines[i].isEmpty()) {
1431 QStringList a = lines[i].replace(
'\t',
' ').split(
' ', Qt::SkipEmptyParts);
1433 if (a.count() < 3) {
1437 r = qBound(0, a[0].toInt(), 255);
1438 g = qBound(0, a[1].toInt(), 255);
1439 b = qBound(0, a[2].toInt(), 255);
1443 for (
int i = 0; i != 3; i++) {
1446 QString
name = a.join(
" ");
1449 global()->addSwatch(swatch);
1457 QFileInfo info(colorSet->filename());
1458 colorSet->setName(info.completeBaseName());
1460 int numOfTriplets = int(data.size() / 3);
1461 for (
int i = 0; i < numOfTriplets * 3; i += 3) {
1463 quint8 g = data[i+1];
1464 quint8 b = data[i+2];
1466 global()->addSwatch(swatch);
1474 QFileInfo info(colorSet->filename());
1475 colorSet->setName(info.completeBaseName());
1479 memcpy(&header, data.constData(),
sizeof(
RiffHeader));
1486 quint8 g = data[i+1];
1487 quint8 b = data[i+2];
1489 colorSet->getGlobalGroup()->addSwatch(swatch);
1497 QFileInfo info(colorSet->filename());
1498 colorSet->setName(info.completeBaseName());
1503 if (l.size() < 4)
return false;
1504 if (l[0] !=
"JASC-PAL")
return false;
1505 if (l[1] !=
"0100")
return false;
1507 int entries = l[2].toInt();
1511 for (
int i = 0; i < entries; ++i) {
1513 QStringList a = l[i + 3].replace(
'\t',
' ').split(
' ', Qt::SkipEmptyParts);
1515 if (a.count() != 3) {
1519 r = qBound(0, a[0].toInt(), 255);
1520 g = qBound(0, a[1].toInt(), 255);
1521 b = qBound(0, a[2].toInt(), 255);
1526 QString
name = a.join(
" ");
1529 global->addSwatch(swatch);
1536 QFileInfo info(colorSet->filename());
1537 colorSet->setName(info.completeBaseName());
1539 QString text = readAllLinesSafe(&data).join(
"").replace(
"\t",
"").replace(
" ",
"");
1541 QRegularExpression re(
"/\\*.*?\\*/");
1548 QRegularExpression
palette(
"(.*?){(?:[^:;]+:[^;]+;)*?color:(.*?)(?:;.*?)*?}");
1550 QRegularExpressionMatchIterator colors =
palette.globalMatch(text);
1552 if (!colors.hasNext()) {
1553 warnPigment <<
"No color found in CSS palette : " << colorSet->filename();
1557 while (colors.hasNext()) {
1558 QRegularExpressionMatch match = colors.next();
1559 QString colorInfo = match.captured();
1560 QString colorName = match.captured(1);
1561 QString colorValue = match.captured(2);
1563 if (!colorInfo.startsWith(
".") || colorValue.isEmpty()) {
1564 warnPigment <<
"Illegal CSS palette syntax : " << colorInfo;
1570 colorName.remove(
".");
1573 if (colorValue.startsWith(
"rgb")) {
1576 if (colorValue.startsWith(
"rgba")) {
1577 colorValue.remove(
"rgba(").remove(
")");
1578 color = colorValue.split(
",");
1580 if (color.size() != 4) {
1581 warnPigment <<
"Invalid RGBA color definition : " << colorInfo;
1585 int alpha = color[3].toFloat() * 255;
1587 if (alpha < 0 || alpha > 255) {
1588 warnPigment <<
"Invalid alpha parameter : " << colorInfo;
1593 colorValue.remove(
"rgb(").remove(
")");
1595 color = colorValue.split(
",");
1597 if (color.size() != 3) {
1598 warnPigment <<
"Invalid RGB color definition : " << colorInfo;
1605 for (
int i = 0; i < 3; i++) {
1606 if (color[i].endsWith(
"%")) {
1607 color[i].replace(
"%",
"");
1608 rgb[i] = color[i].toFloat() / 100 * 255 ;
1611 rgb[i] = color[i].toInt();
1615 qColor = QColor(rgb[0], rgb[1], rgb[2]);
1617 else if (colorValue.startsWith(
"hsl")) {
1620 if (colorValue.startsWith(
"hsla")) {
1621 colorValue.remove(
"hsla(").remove(
")").replace(
"%",
"");
1622 color = colorValue.split(
",");
1623 if (color.size() != 4) {
1624 warnPigment <<
"Invalid HSLA color definition : " << colorInfo;
1628 float alpha = color[3].toFloat();
1630 if (alpha < 0.0 || alpha > 1.0) {
1631 warnPigment <<
"Invalid alpha parameter : " << colorInfo;
1637 colorValue.remove(
"hsl(").remove(
")").replace(
"%",
"");
1638 color = colorValue.split(
",");
1639 if (color.size() != 3) {
1640 warnPigment <<
"Invalid HSL color definition : " << colorInfo;
1645 float hue = color[0].toFloat() / 359;
1646 float saturation = color[1].toFloat() / 100;
1647 float lightness = color[2].toFloat() / 100;
1649 if (hue < 0.0 || hue > 1.0) {
1650 warnPigment <<
"Invalid hue parameter : " << colorInfo;
1654 if (saturation < 0.0 || saturation > 1.0) {
1655 warnPigment <<
"Invalid saturation parameter : " << colorInfo;
1659 if (lightness < 0.0 || lightness > 1.0) {
1660 warnPigment <<
"Invalid lightness parameter : " << colorInfo;
1664 qColor = QColor::fromHslF(hue, saturation, lightness);
1667 else if (colorValue.startsWith(
"#")) {
1668 if (colorValue.size() == 9) {
1671 colorValue.truncate(7);
1674 qColor = QColor(colorValue);
1677 warnPigment <<
"Unknown color declaration : " << colorInfo;
1681 if (!qColor.isValid()) {
1682 warnPigment <<
"Invalid color definition : " << colorInfo;
1688 global()->addSwatch(swatch);
1695 const QString &path,
1696 const QString &modelId,
1697 const QString &colorDepthId)
1699 if (!store->open(path)) {
1703 QByteArray bytes = store->read(store->size());
1708 if (!profile || !profile->
valid()) {
1718 if (!store->open(
"profiles.xml")) {
1722 QByteArray bytes = store->read(store->size());
1726 if(!doc.setContent(bytes)) {
1730 QDomElement root = doc.documentElement();
1743 loadColorProfile(store,
filename, colorModelId, colorDepthId);
1752 if (!store->open(
"colorset.xml")) {
1756 QByteArray bytes = store->read(store->size());
1760 if (!doc.setContent(bytes)) {
1764 QDomElement root = doc.documentElement();
1771 warnPigment <<
"Refusing to set unreasonable number of columns (" << desiredColumnCount
1772 <<
") in KPL palette file " << colorSet->filename()
1773 <<
" - setting maximum allowed column count instead.";
1776 colorSet->setColumnCount(desiredColumnCount);
1779 loadKplGroup(doc, root, colorSet->getGlobalGroup(),
version);
1785 colorSet->addGroup(groupName);
1786 loadKplGroup(doc, g, colorSet->getGroup(groupName),
version);
1795 buf.open(QBuffer::ReadOnly);
1797 QScopedPointer<KoStore> store(
1799 "application/x-krita-palette",
1801 if (!store || store->bad()) {
1805 if (store->hasFile(
"profiles.xml") && !loadKplProfiles(store)) {
1809 if (!loadKplColorset(store)) {
1819 QFileInfo info(colorSet->filename());
1820 colorSet->setName(info.completeBaseName());
1823 buf.open(QBuffer::ReadOnly);
1825 quint16
version = readShort(&buf);
1826 quint16 numColors = readShort(&buf);
1829 if (
version == 1 && buf.size() > 4+numColors*10) {
1830 buf.seek(4+numColors*10);
1832 numColors = readShort(&buf);
1839 for (
int i = 0; i < numColors && !buf.atEnd(); ++i) {
1841 quint16 colorSpace = readShort(&buf);
1842 quint16 ch1 = readShort(&buf);
1843 quint16 ch2 = readShort(&buf);
1844 quint16 ch3 = readShort(&buf);
1845 quint16 ch4 = readShort(&buf);
1848 if (colorSpace == 0) {
1851 reinterpret_cast<quint16*
>(c.
data())[0] = ch3;
1852 reinterpret_cast<quint16*
>(c.
data())[1] = ch2;
1853 reinterpret_cast<quint16*
>(c.
data())[2] = ch1;
1857 else if (colorSpace == 1) {
1859 qc.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0);
1864 else if (colorSpace == 2) {
1873 else if (colorSpace == 7) {
1875 reinterpret_cast<quint16*
>(c.
data())[0] = ch3;
1876 reinterpret_cast<quint16*
>(c.
data())[1] = ch2;
1877 reinterpret_cast<quint16*
>(c.
data())[2] = ch1;
1881 else if (colorSpace == 8) {
1883 reinterpret_cast<quint16*
>(c.
data())[0] = ch1 * (
quint16_MAX / 10000);
1888 warnPigment <<
"Unsupported colorspace in palette" << colorSet->filename() <<
"(" << colorSpace <<
")";
1893 QString
name = readUnicodeString(&buf,
true);
1897 group->addSwatch(swatch);
1905 if (!store->open(
"swatchbook.xml")) {
1909 QByteArray bytes = store->read(store->size());
1912 dbgPigment <<
"XML palette: " << colorSet->filename() <<
", SwatchBooker format";
1915#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
1916 int errorLine, errorColumn;
1917 QString errorMessage;
1918 if (!doc.setContent(bytes, &errorMessage, &errorLine, &errorColumn)) {
1919 warnPigment <<
"Illegal XML palette:" << colorSet->filename();
1921 <<
", column" << errorColumn
1922 <<
"):" << errorMessage;
1924 QDomDocument::ParseResult result = doc.setContent(bytes);
1926 warnPigment <<
"Illegal XML palette:" << colorSet->filename();
1928 <<
", column" << result.errorColumn
1929 <<
"):" << result.errorMessage;
1934 QDomElement root = doc.documentElement();
1937 QDomElement
metadata = root.firstChildElement(
"metadata");
1943 QDomElement title =
metadata.firstChildElement(
"dc:title");
1944 QString colorName = title.text();
1945 colorName = colorName.isEmpty() ? i18n(
"Untitled") : colorName;
1946 colorSet->setName(colorName);
1947 dbgPigment <<
"Processed name of palette:" << colorSet->name();
1951 QDomElement book = root.firstChildElement(
"book");
1952 if (book.isNull()) {
1953 warnPigment <<
"Palette book (swatch composition) not found (line" << root.lineNumber()
1954 <<
", column" << root.columnNumber()
1960 QDomElement swatch = book.firstChildElement();
1961 if (swatch.isNull()) {
1962 warnPigment <<
"Swatches/groups definition not found (line" << book.lineNumber()
1963 <<
", column" << book.columnNumber()
1969 QDomElement materials = root.firstChildElement(
"materials");
1970 if (materials.isNull()) {
1971 warnPigment <<
"Materials (color definitions) not found";
1976 if (materials.firstChildElement(
"color").isNull()) {
1977 warnPigment <<
"Color definitions not found (line" << materials.lineNumber()
1978 <<
", column" << materials.columnNumber()
1985 QHash<QString, KisSwatch> materialsBook;
1986 QHash<QString, const KoColorSpace*> fileColorSpaces;
1989 store->enterDirectory(
"profiles");
1990 for (QDomElement colorElement = materials.firstChildElement(
"color");
1991 !colorElement.isNull();
1992 colorElement = colorElement.nextSiblingElement(
"color")) {
1995 currentEntry.
setSpotColor(colorElement.attribute(
"usage") ==
"spot");
1999 QDomElement currentColorMetadata = colorElement.firstChildElement(
"metadata");
2001 QDomElement colorTitle = currentColorMetadata.firstChildElement(
"dc:title");
2002 QDomElement colorId = currentColorMetadata.firstChildElement(
"dc:identifier");
2004 if (colorId.text().isEmpty()) {
2005 warnPigment <<
"Unidentified color (line" << colorId.lineNumber()
2006 <<
", column" << colorId.columnNumber()
2011 if (materialsBook.contains(colorId.text())) {
2012 warnPigment <<
"Duplicated color definition (line" << colorId.lineNumber()
2013 <<
", column" << colorId.columnNumber()
2019 currentEntry.
setId(colorId.text());
2020 currentEntry.
setName(colorTitle.text().isEmpty() ? colorId.text() : colorTitle.text());
2023 if (colorElement.firstChildElement(
"values").isNull()) {
2024 warnPigment <<
"Color definitions not found (line" << colorElement.lineNumber()
2025 <<
", column" << colorElement.columnNumber()
2031 bool firstDefinition =
false;
2035 for (QDomElement colorValueE = colorElement.firstChildElement(
"values");
2036 !colorValueE.isNull();
2037 colorValueE = colorValueE.nextSiblingElement(
"values")) {
2038 QString model = colorValueE.attribute(
"model");
2042 if (model ==
"Lab") {
2044 }
else if (model ==
"sRGB") {
2047 }
else if (model ==
"XYZ") {
2049 }
else if (model ==
"CMYK") {
2051 }
else if (model ==
"GRAY") {
2053 }
else if (model ==
"RGB") {
2056 warnPigment <<
"Color space not implemented:" << model
2057 <<
"(line" << colorValueE.lineNumber()
2058 <<
", column "<< colorValueE.columnNumber()
2067 QString space = colorValueE.attribute(
"space");
2068 if (!space.isEmpty()) {
2069 if (fileColorSpaces.contains(space)) {
2070 colorSpace = fileColorSpaces.value(space);
2073 profile = loadColorProfile(store, space, modelId, colorDepthId);
2075 colorSpace = colorSpaceRegistry->
colorSpace(modelId, colorDepthId, profile);
2076 fileColorSpaces.insert(space, colorSpace);
2088 for (
const QString &str : colorValueE.text().split(
" ")) {
2089 float channelValue = str.toFloat(&status);
2091 warnPigment <<
"Invalid float definition (line" << colorValueE.lineNumber()
2092 <<
", column" << colorValueE.columnNumber()
2098 channels.append(channelValue);
2104 firstDefinition =
true;
2106 if (model ==
"Lab") {
2111 if (firstDefinition) {
2112 materialsBook.insert(currentEntry.
id(), currentEntry);
2114 warnPigment <<
"No supported color spaces for the current color (line" << colorElement.lineNumber()
2115 <<
", column "<< colorElement.columnNumber()
2121 store->leaveDirectory();
2126 for(; !swatch.isNull(); swatch = swatch.nextSiblingElement()) {
2127 QString type = swatch.tagName();
2128 if (type.isEmpty() || type.isNull()) {
2129 warnPigment <<
"Invalid swatch/group definition (no id) (line" << swatch.lineNumber()
2130 <<
", column" << swatch.columnNumber()
2133 }
else if (type ==
"swatch") {
2134 QString
id = swatch.attribute(
"material");
2135 if (
id.isEmpty() ||
id.isNull()) {
2136 warnPigment <<
"Invalid swatch definition (no material id) (line" << swatch.lineNumber()
2137 <<
", column" << swatch.columnNumber()
2142 if (materialsBook.contains(
id)) {
2143 global->addSwatch(materialsBook.value(
id));
2145 warnPigment <<
"Invalid swatch definition (material not found) (line" << swatch.lineNumber()
2146 <<
", column" << swatch.columnNumber()
2150 }
else if (type ==
"group") {
2151 QDomElement groupMetadata = swatch.firstChildElement(
"metadata");
2152 if (groupMetadata.isNull()) {
2153 warnPigment <<
"Invalid group definition (missing metadata) (line" << groupMetadata.lineNumber()
2154 <<
", column" << groupMetadata.columnNumber()
2158 QDomElement groupTitle =
metadata.firstChildElement(
"dc:title");
2159 if (groupTitle.isNull()) {
2160 warnPigment <<
"Invalid group definition (missing title) (line" << groupTitle.lineNumber()
2161 <<
", column" << groupTitle.columnNumber()
2165 QString currentGroupName = groupTitle.text();
2166 colorSet->addGroup(currentGroupName);
2168 for (QDomElement groupSwatch = swatch.firstChildElement(
"swatch");
2169 !groupSwatch.isNull();
2170 groupSwatch = groupSwatch.nextSiblingElement(
"swatch")) {
2171 QString
id = groupSwatch.attribute(
"material");
2172 if (
id.isEmpty() ||
id.isNull()) {
2173 warnPigment <<
"Invalid swatch definition (no material id) (line" << groupSwatch.lineNumber()
2174 <<
", column" << groupSwatch.columnNumber()
2179 if (materialsBook.contains(
id)) {
2180 colorSet->getGroup(currentGroupName)->addSwatch(materialsBook.value(
id));
2182 warnPigment <<
"Invalid swatch definition (material not found) (line" << groupSwatch.lineNumber()
2183 <<
", column" << groupSwatch.columnNumber()
2197 buf.open(QBuffer::ReadOnly);
2200 QScopedPointer<KoStore> store(
2202 "application/x-swatchbook",
2204 if (!store || store->bad()) {
2208 if (store->hasFile(
"swatchbook.xml") && !loadSbzSwatchbook(store)) {
2218 QFileInfo info(colorSet->filename());
2219 colorSet->setName(info.completeBaseName());
2222 buf.open(QBuffer::ReadOnly);
2226 quint16
version = readShort(&buf);
2227 quint16 version2 = readShort(&buf);
2233 qint32 numBlocks = readInt(&buf);
2235 QByteArray groupStart(
"\xC0\x01");
2236 QByteArray groupEnd(
"\xC0\x02");
2237 QByteArray swatchSig(
"\x00\x01");
2239 bool inGroup =
false;
2241 for (qint32 i = 0; i < numBlocks; i++) {
2242 QByteArray blockType;
2243 blockType = buf.read(2);
2244 qint32 blockSize = readInt(&buf);
2245 qint64 pos = buf.pos();
2247 if (blockType == groupStart) {
2248 groupName = readUnicodeString(&buf);
2249 colorSet->addGroup(groupName);
2252 else if (blockType == groupEnd) {
2253 int colorCount = colorSet->getGroup(groupName)->colorCount();
2254 int columns = colorSet->columnCount();
2259 colorSet->getGroup(groupName)->setRowCount(rows);
2264 swatch.
setName(readUnicodeString(&buf).trimmed());
2265 QByteArray colorModel;
2267 colorModel = buf.read(4);
2268 if (colorModel ==
"RGB ") {
2269 QDomElement elt = doc.createElement(
"sRGB");
2271 elt.setAttribute(
"r", readFloat(&buf));
2272 elt.setAttribute(
"g", readFloat(&buf));
2273 elt.setAttribute(
"b", readFloat(&buf));
2277 }
else if (colorModel ==
"CMYK") {
2278 QDomElement elt = doc.createElement(
"CMYK");
2280 elt.setAttribute(
"c", readFloat(&buf));
2281 elt.setAttribute(
"m", readFloat(&buf));
2282 elt.setAttribute(
"y", readFloat(&buf));
2283 elt.setAttribute(
"k", readFloat(&buf));
2285 elt.setAttribute(
"space",
"U.S. Web Coated (SWOP) v2");
2289 }
else if (colorModel ==
"LAB ") {
2290 QDomElement elt = doc.createElement(
"Lab");
2292 elt.setAttribute(
"L", readFloat(&buf)*100.0);
2293 elt.setAttribute(
"a", readFloat(&buf));
2294 elt.setAttribute(
"b", readFloat(&buf));
2298 }
else if (colorModel ==
"GRAY") {
2299 QDomElement elt = doc.createElement(
"Gray");
2301 elt.setAttribute(
"g", readFloat(&buf));
2306 qint16 type = readShort(&buf);
2311 colorSet->addSwatch(swatch, groupName);
2313 colorSet->addSwatch(swatch);
2316 buf.seek(pos + qint64(blockSize));
2324 QFileInfo info(colorSet->filename());
2327 buf.open(QBuffer::ReadOnly);
2331 quint16
version = readShort(&buf);
2332 quint16 bookID = readShort(&buf);
2340 for (
int i = 0; i< 4; i++) {
2342 QString metadataString = readUnicodeString(&buf,
true);
2343 if (metadataString.startsWith(
"\"")) {
2344 metadataString = metadataString.remove(0, 1);
2346 if (metadataString.endsWith(
"\"")) {
2347 metadataString.chop(1);
2349 if (metadataString.startsWith(
"$$$/")) {
2350 if (metadataString.contains(
"=")) {
2351 metadataString = metadataString.split(
"=").last();
2353 metadataString = QString();
2359 colorSet->setName(title);
2362 QString description =
metadata.at(3);
2363 colorSet->setComment(description);
2365 quint16 numColors = readShort(&buf);
2366 quint16 numColumns = readShort(&buf);
2367 numColumns = numColumns > 0 ? numColumns : 8;
2368 colorSet->setColumnCount(numColumns);
2369 quint16 numKeyColorPage = readShort(&buf);
2370 Q_UNUSED(numKeyColorPage);
2371 quint16 colorType = readShort(&buf);
2374 if (colorType == 2) {
2375 QString profileName =
"U.S. Web Coated (SWOP) v2";
2377 }
else if (colorType == 7) {
2381 for (quint16 i = 0; i < numColors; i++) {
2385 name << readUnicodeString(&buf,
true);
2390 swatch.
setId(QString::fromLatin1(key));
2392 quint8 c1 = readByte(&buf);
2393 quint8 c2 = readByte(&buf);
2394 quint8 c3 = readByte(&buf);
2396 if (colorType == 0) {
2400 }
else if (colorType == 2) {
2401 quint8 c4 = readByte(&buf);
2406 }
else if (colorType == 7) {
2413 colorSet->addSwatch(swatch);
2422 QXmlStreamReader *xml =
new QXmlStreamReader(data);
2424 if (xml->readNextStartElement()) {
2425 auto paletteId = xml->name();
2426 if (paletteId.compare(QString(
"SCRIBUSCOLORS"), Qt::CaseInsensitive) == 0) {
2427 dbgPigment <<
"XML palette: " << colorSet->filename() <<
", Scribus format";
2428 res = loadScribusXmlPalette(colorSet, xml);
2432 xml->raiseError(
"Unknown XML palette format. Expected SCRIBUSCOLORS, found " + paletteId);
2437 if (xml->hasError() || !res) {
2438 warnPigment <<
"Illegal XML palette:" << colorSet->filename();
2439 warnPigment <<
"Error (line"<< xml->lineNumber() <<
", column" << xml->columnNumber() <<
"):" << xml->errorString();
2443 dbgPigment <<
"XML palette parsed successfully:" << colorSet->filename();
2451 if (!store || store->bad()) {
2452 qWarning() <<
"saveKpl could not create store";
2456 QSet<const KoColorSpace *> colorSpaces;
2473 root.appendChild(gl);
2474 saveKplGroup(doc, gl, group, colorSpaces);
2477 doc.appendChild(root);
2478 if (!store->open(
"colorset.xml")) {
return false; }
2479 QByteArray ba = doc.toByteArray();
2480 if (store->write(ba) != ba.size()) {
return false; }
2481 if (!store->close()) {
return false; }
2485 QDomElement profileElement = doc.createElement(
"Profiles");
2488 QString fn = QFileInfo(colorSpace->profile()->fileName()).fileName();
2489 if (!store->open(fn)) { qWarning() <<
"Could not open the store for profiles directory";
return false; }
2490 QByteArray profileRawData = colorSpace->profile()->rawData();
2491 if (!store->write(profileRawData)) { qWarning() <<
"Could not write the profiles data into the store";
return false; }
2492 if (!store->close()) { qWarning() <<
"Could not close the store for profiles directory";
return false; }
2498 profileElement.appendChild(el);
2501 doc.appendChild(profileElement);
2503 if (!store->open(
"profiles.xml")) { qWarning() <<
"Could not open profiles.xml";
return false; }
2504 QByteArray ba = doc.toByteArray();
2506 int bytesWritten = store->write(ba);
2507 if (bytesWritten != ba.size()) { qWarning() <<
"Bytes written is wrong" << ba.size();
return false; }
2509 if (!store->close()) { qWarning() <<
"Could not close the store";
return false; }
2511 bool r = store->finalize();
2512 if (!r) { qWarning() <<
"Could not finalize the store"; }
2517 QDomElement &groupEle,
2519 QSet<const KoColorSpace *> &colorSetSet)
const
2523 for (
const KisSwatchGroup::SwatchInfo &info : group->infoList()) {
2524 const KoColorProfile *profile = info.swatch.color().colorSpace()->profile();
2526 if (!profile->
fileName().isEmpty()) {
2527 bool alreadyIncluded =
false;
2528 Q_FOREACH(
const KoColorSpace* colorSpace, colorSetSet) {
2530 alreadyIncluded =
true;
2534 if(!alreadyIncluded) {
2535 colorSetSet.insert(info.swatch.color().colorSpace());
2543 info.swatch.color().toXML(doc, swatchEle);
2548 swatchEle.appendChild(positionEle);
2550 groupEle.appendChild(swatchEle);
2560 group->setColumnCount(colorSet->columnCount());
2562 for (QDomElement swatchEle = parentEle.firstChildElement(
KPL_SWATCH_TAG);
2563 !swatchEle.isNull();
2568 if (
version ==
"1.0" && swatchEle.firstChildElement().tagName() ==
"Lab") {
2572 QDomElement el = swatchEle.firstChildElement();
2574 el.setAttribute(
"L", L*100.0);
2577 ab = (0.5 - ab) * 2 * -128.0;
2579 ab = (ab - 0.5) * 2 * 127.0;
2581 el.setAttribute(
"a", ab);
2585 ab = (0.5 - ab) * 2 * -128.0;
2587 ab = (ab - 0.5) * 2 * 127.0;
2589 el.setAttribute(
"b", ab);
2598 if (!positionEle.isNull()) {
2601 if (columnNumber < 0 ||
2602 columnNumber >= colorSet->columnCount() ||
2606 <<
"of palette" << colorSet->name()
2607 <<
"has invalid position.";
2610 group->setSwatch(swatch, columnNumber, rowNumber);
2612 group->addSwatch(swatch);
2617 && group->colorCount() > 0
2618 && group->columnCount() > 0
2619 && (group->colorCount() / (group->columnCount()) + 1) < 20) {
2620 group->setRowCount((group->colorCount() / group->columnCount()) + 1);
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID XYZAColorModelID("XYZA", ki18n("XYZ/Alpha"))
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const KoID CMYKAColorModelID("CMYKA", ki18n("CMYK/Alpha"))
const KoID LABAColorModelID("LABA", ki18n("L*a*b*/Alpha"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
const int MAXIMUM_ALLOWED_COLUMNS
const qreal OPACITY_OPAQUE_F
const quint8 OPACITY_OPAQUE_U8
void setUndoLimit(int limit)
The KisSwatchGroup class stores a matrix of color swatches swatches can accessed using (x,...
void setSpotColor(bool spotColor)
void setColor(const KoColor &color)
void setId(const QString &id)
void setName(const QString &name)
bool saveKpl(QIODevice *dev) const
KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba)
bool loadSbzSwatchbook(QScopedPointer< KoStore > &store)
quint8 readByte(QIODevice *io)
const KoColorProfile * loadColorProfile(QScopedPointer< KoStore > &store, const QString &path, const QString &modelId, const QString &colorDepthId)
bool loadKplColorset(QScopedPointer< KoStore > &store)
Private(KoColorSet *a_colorSet)
void scribusParseColor(KoColorSet *set, QXmlStreamReader *xml)
bool loadKplProfiles(QScopedPointer< KoStore > &store)
float readFloat(QIODevice *io)
void saveKplGroup(QDomDocument &doc, QDomElement &groupEle, const KisSwatchGroupSP group, QSet< const KoColorSpace * > &colorSetSet) const
bool saveGpl(QIODevice *dev) const
bool loadScribusXmlPalette(KoColorSet *set, QXmlStreamReader *xml)
quint16 readShort(QIODevice *io)
QList< KisSwatchGroupSP > swatchGroups
QString readUnicodeString(QIODevice *io, bool sizeIsInt=false)
void loadKplGroup(const QDomDocument &doc, const QDomElement &parentElement, KisSwatchGroupSP group, QString version)
qint32 readInt(QIODevice *io)
static const QString KPL_COLOR_DEPTH_ID_ATTR
static const QString KPL_SWATCH_TAG
int rowNumberInGroup(int rowNumber) const
rowNumberInGroup calculates the row number in the group from the global rownumber
KoColorSet(const QString &filename=QString())
static const QString KPL_SWATCH_ROW_ATTR
int rowCountWithTitles() const
friend struct SetColumnCountCommand
static const QString KPL_COLOR_MODEL_ID_ATTR
void setColumnCount(int columns)
void removeGroup(const QString &groupName, bool keepColors=true)
removeGroup Remove a group from the KoColorSet
KUndo2Stack * undoStack() const
static const QString KPL_SWATCH_COL_ATTR
static const QString KPL_PALETTE_PROFILE_TAG
static const QString KPL_PALETTE_COMMENT_ATTR
static const QString KPL_PALETTE_NAME_ATTR
void canUndoChanged(bool canUndo)
friend struct MoveGroupCommand
KisSwatchGroup::SwatchInfo getClosestSwatchInfo(KoColor compare, bool useGivenColorSpace=true) const
getIndexClosestColor function that matches the color to all colors in the colorset,...
void setLocked(bool lock)
bool isGroupTitleRow(int row) const
isGroupRow checks whether the current row is a group title
int startRowForGroup(const QString &groupName) const
rowForNamedGroup returns the row the group's title is on
void updateThumbnail() override
updateThumbnail updates the thumbnail for this resource. Reimplement if your thumbnail is something e...
bool saveToDevice(QIODevice *dev) const override
static const QString KPL_SWATCH_POS_TAG
static const QString KPL_PALETTE_READONLY_ATTR
bool fromByteArray(QByteArray &data, KisResourcesInterfaceSP resourcesInterface)
friend struct AddSwatchCommand
KisSwatchGroupSP getGlobalGroup() const
getGlobalGroup
friend struct SetPaletteTypeCommand
void setPaletteType(PaletteType paletteType)
static const QString KPL_PALETTE_COLUMN_COUNT_ATTR
const QScopedPointer< Private > d
quint32 slotCount() const
static const QString KPL_GROUP_TAG
static const QString GLOBAL_GROUP_NAME
KisSwatch getColorGlobal(quint32 column, quint32 row) const
getColorGlobal A function for getting a color based on a global index. Useful for iterating through a...
QStringList swatchGroupNames() const
getGroupNames
void addSwatch(const KisSwatch &swatch, const QString &groupName=GLOBAL_GROUP_NAME, int column=-1, int row=-1)
Add a color to the palette.
static const QString KPL_GROUP_NAME_ATTR
static const QString KPL_PALETTE_TAG
friend struct ClearCommand
KisSwatchGroupSP getGroup(const QString &name) const
getGroup
KisSwatch getSwatchFromGroup(quint32 column, quint32 row, QString groupName=KoColorSet::GLOBAL_GROUP_NAME) const
getColorGroup A function for getting the color from a specific group.
static const QString KPL_VERSION_ATTR
friend struct SetCommentCommand
friend struct AddGroupCommand
static const QString KPL_GROUP_ROW_COUNT_ATTR
void notifySwatchChanged(const QString &groupName, int column, int row)
friend struct RemoveGroupCommand
static const QString KPL_SWATCH_BITDEPTH_ATTR
static const QString KPL_PALETTE_FILENAME_ATTR
void moveGroup(const QString &groupName, const QString &groupNameInsertBefore=GLOBAL_GROUP_NAME)
moveGroup Move a group in the internal stringlist.
void clear()
clears the complete colorset
void setComment(QString comment)
bool loadFromDevice(QIODevice *dev, KisResourcesInterfaceSP resourcesInterface) override
void canRedoChanged(bool canRedo)
void addGroup(const QString &groupName, int columnCount=KisSwatchGroup::DEFAULT_COLUMN_COUNT, int rowCount=KisSwatchGroup::DEFAULT_ROW_COUNT)
addGroup Adds a new group.
friend struct ChangeGroupNameCommand
KoResourceSP clone() const override
friend struct RemoveSwatchCommand
void removeSwatch(int column, int row, KisSwatchGroupSP group)
remove the swatch from the given group at column and row
static const QString KPL_SWATCH_SPOT_ATTR
quint32 colorCount() const
PaletteType paletteType() const
void entryChanged(int column, int row)
static const QString KPL_SWATCH_NAME_ATTR
void layoutAboutToChange()
void changeGroupName(const QString &oldGroupName, const QString &newGroupName)
changeGroupName
QString defaultFileExtension() const override
static const QString KPL_SWATCH_ID_ATTR
virtual quint8 difference(const quint8 *src1, const quint8 *src2) const =0
virtual void fromNormalisedChannelsValue(quint8 *pixel, const QVector< float > &values) const =0
virtual const KoColorProfile * profile() const =0
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
void setOpacity(quint8 alpha)
const KoColorSpace * colorSpace() const
return the current colorSpace
void toQColor(QColor *c) const
a convenience method for the above.
static KoStore * createStore(const QString &fileName, Mode mode, const QByteArray &appIdentification=QByteArray(), Backend backend=Auto, bool writeMimetype=true)
const quint16 quint16_MAX
QSharedPointer< KoResource > KoResourceSP
double toDouble(const QString &str, bool *ok=nullptr)
void setUtf8OnStream(QTextStream &stream)
rgba palette[MAX_PALETTE]
AddGroupCommand(KoColorSet *colorSet, QString groupName, int columnCount, int rowCount)
void undo() override
revert the actions done in redo
void redo() override
redo the command
void undo() override
revert the actions done in redo
~AddSwatchCommand() override
AddSwatchCommand(KoColorSet *colorSet, const KisSwatch &swatch, const QString &groupName, int column, int row)
void redo() override
redo the command
~ChangeGroupNameCommand() override
void undo() override
revert the actions done in redo
ChangeGroupNameCommand(KoColorSet *colorSet, QString oldGroupName, const QString &newGroupName)
void redo() override
redo the command
ClearCommand(KoColorSet *colorSet)
void undo() override
revert the actions done in redo
KoColorSet * m_OldColorSet
void redo() override
redo the command
virtual bool valid() const =0
const KoColorProfile * profileByName(const QString &name) const
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)
void addProfile(KoColorProfile *profile)
void setName(const QString &name)
void setFilename(const QString &filename)
void setDirty(bool value)
Mark the preset as modified but not saved.
void setImage(const QImage &image)
QMap< QString, QVariant > metadata
KoResourceSignature signature() const
MoveGroupCommand(KoColorSet *colorSet, QString groupName, const QString &groupNameInsertBefore)
QString m_groupNameInsertBefore
void redo() override
redo the command
void undo() override
revert the actions done in redo
RemoveGroupCommand(KoColorSet *colorSet, QString groupName, bool keepColors=true)
void redo() override
redo the command
void undo() override
revert the actions done in redo
KisSwatchGroupSP m_oldGroup
void undo() override
revert the actions done in redo
void redo() override
redo the command
RemoveSwatchCommand(KoColorSet *colorSet, int column, int row, KisSwatchGroupSP group)
void redo() override
redo the command
SetColumnCountCommand(KoColorSet *colorSet, int columnCount)
void undo() override
revert the actions done in redo
void undo() override
revert the actions done in redo
KoColorSet::PaletteType m_paletteType
QString suffix(KoColorSet::PaletteType paletteType) const
SetPaletteTypeCommand(KoColorSet *colorSet, const KoColorSet::PaletteType &paletteType)
void redo() override
redo the command
KoColorSet::PaletteType m_oldPaletteType