File indexing completed on 2023-12-03 07:42:26
0001 /* This file is part of the KDE libraries 0002 SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 // KDE color collection 0008 0009 #include "kcolorcollection.h" 0010 0011 #include <QDir> 0012 #include <QFile> 0013 #include <QSaveFile> 0014 #include <QSharedData> 0015 #include <QStandardPaths> 0016 #include <QTextStream> 0017 0018 // BEGIN KColorCollectionPrivate 0019 class KColorCollectionPrivate : public QSharedData 0020 { 0021 public: 0022 KColorCollectionPrivate(const QString &); 0023 KColorCollectionPrivate(const KColorCollectionPrivate &) = default; 0024 ~KColorCollectionPrivate() 0025 { 0026 } 0027 struct ColorNode { 0028 ColorNode(const QColor &c, const QString &n) 0029 : color(c) 0030 , name(n) 0031 { 0032 } 0033 QColor color; 0034 QString name; 0035 }; 0036 QList<ColorNode> colorList; 0037 0038 QString name; 0039 QString desc; 0040 KColorCollection::Editable editable; 0041 }; 0042 0043 KColorCollectionPrivate::KColorCollectionPrivate(const QString &_name) 0044 : name(_name) 0045 { 0046 if (name.isEmpty()) { 0047 return; 0048 } 0049 0050 QString filename = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QLatin1String("colors/") + name); 0051 if (filename.isEmpty()) { 0052 return; 0053 } 0054 0055 QFile paletteFile(filename); 0056 if (!paletteFile.exists()) { 0057 return; 0058 } 0059 if (!paletteFile.open(QIODevice::ReadOnly)) { 0060 return; 0061 } 0062 0063 // Read first line 0064 // Expected "GIMP Palette" 0065 QString line = QString::fromLocal8Bit(paletteFile.readLine()); 0066 if (line.contains(QLatin1String(" Palette"))) { 0067 return; 0068 } 0069 0070 while (!paletteFile.atEnd()) { 0071 line = QString::fromLocal8Bit(paletteFile.readLine()); 0072 if (line[0] == QLatin1Char('#')) { 0073 // This is a comment line 0074 line.remove(0, 1); // Strip '#' 0075 line = line.trimmed(); // Strip remaining white space.. 0076 if (!line.isEmpty()) { 0077 desc += line + QLatin1Char('\n'); // Add comment to description 0078 } 0079 } else { 0080 // This is a color line, hopefully 0081 line = line.trimmed(); 0082 if (line.isEmpty()) { 0083 continue; 0084 } 0085 int r; 0086 int g; 0087 int b; 0088 int pos = 0; 0089 if (sscanf(line.toLatin1().constData(), "%d %d %d%n", &r, &g, &b, &pos) >= 3) { 0090 r = qBound(0, r, 255); 0091 g = qBound(0, g, 255); 0092 b = qBound(0, b, 255); 0093 QString name = line.mid(pos).trimmed(); 0094 colorList.append(ColorNode(QColor(r, g, b), name)); 0095 } 0096 } 0097 } 0098 } 0099 // END KColorCollectionPrivate 0100 0101 QStringList KColorCollection::installedCollections() 0102 { 0103 const QStringList paletteDirs = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QStringLiteral("colors"), QStandardPaths::LocateDirectory); 0104 0105 QStringList paletteList; 0106 for (const QString &dir : paletteDirs) { 0107 paletteList += QDir(dir).entryList(QDir::Files | QDir::NoDotAndDotDot); 0108 } 0109 paletteList.removeDuplicates(); 0110 0111 return paletteList; 0112 } 0113 0114 KColorCollection::KColorCollection(const QString &name) 0115 : d(new KColorCollectionPrivate(name)) 0116 { 0117 } 0118 0119 KColorCollection::KColorCollection(const KColorCollection &p) = default; 0120 0121 // Need auto-save? 0122 KColorCollection::~KColorCollection() = default; 0123 0124 bool KColorCollection::save() 0125 { 0126 QString filename = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1String("/colors/") + d->name; 0127 QSaveFile sf(filename); 0128 if (!sf.open(QIODevice::WriteOnly)) { 0129 return false; 0130 } 0131 0132 QTextStream str(&sf); 0133 0134 QString description = d->desc.trimmed(); 0135 description = QLatin1Char('#') + description.split(QLatin1Char('\n'), Qt::KeepEmptyParts).join(QLatin1String("\n#")); 0136 0137 str << QLatin1String("KDE RGB Palette\n"); 0138 str << description << QLatin1Char('\n'); 0139 for (const KColorCollectionPrivate::ColorNode &node : std::as_const(d->colorList)) { 0140 int r; 0141 int g; 0142 int b; 0143 node.color.getRgb(&r, &g, &b); 0144 str << r << " " << g << " " << b << " " << node.name << "\n"; 0145 } 0146 0147 return sf.commit(); 0148 } 0149 0150 QString KColorCollection::description() const 0151 { 0152 return d->desc; 0153 } 0154 0155 void KColorCollection::setDescription(const QString &desc) 0156 { 0157 d->desc = desc; 0158 } 0159 0160 QString KColorCollection::name() const 0161 { 0162 return d->name; 0163 } 0164 0165 void KColorCollection::setName(const QString &name) 0166 { 0167 d->name = name; 0168 } 0169 0170 KColorCollection::Editable KColorCollection::editable() const 0171 { 0172 return d->editable; 0173 } 0174 0175 void KColorCollection::setEditable(Editable editable) 0176 { 0177 d->editable = editable; 0178 } 0179 0180 int KColorCollection::count() const 0181 { 0182 return d->colorList.count(); 0183 } 0184 0185 KColorCollection &KColorCollection::operator=(const KColorCollection &p) = default; 0186 0187 QColor KColorCollection::color(int index) const 0188 { 0189 if ((index < 0) || (index >= count())) { 0190 return QColor(); 0191 } 0192 0193 return d->colorList[index].color; 0194 } 0195 0196 int KColorCollection::findColor(const QColor &color) const 0197 { 0198 for (int i = 0; i < d->colorList.size(); ++i) { 0199 if (d->colorList[i].color == color) { 0200 return i; 0201 } 0202 } 0203 return -1; 0204 } 0205 0206 QString KColorCollection::name(int index) const 0207 { 0208 if ((index < 0) || (index >= count())) { 0209 return QString(); 0210 } 0211 0212 return d->colorList[index].name; 0213 } 0214 0215 QString KColorCollection::name(const QColor &color) const 0216 { 0217 return name(findColor(color)); 0218 } 0219 0220 int KColorCollection::addColor(const QColor &newColor, const QString &newColorName) 0221 { 0222 d->colorList.append(KColorCollectionPrivate::ColorNode(newColor, newColorName)); 0223 return count() - 1; 0224 } 0225 0226 int KColorCollection::changeColor(int index, const QColor &newColor, const QString &newColorName) 0227 { 0228 if ((index < 0) || (index >= count())) { 0229 return -1; 0230 } 0231 0232 KColorCollectionPrivate::ColorNode &node = d->colorList[index]; 0233 node.color = newColor; 0234 node.name = newColorName; 0235 0236 return index; 0237 } 0238 0239 int KColorCollection::changeColor(const QColor &oldColor, const QColor &newColor, const QString &newColorName) 0240 { 0241 return changeColor(findColor(oldColor), newColor, newColorName); 0242 }