1 | /* This file is part of the KDE libraries |
2 | SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | // KDE color collection |
8 | |
9 | #include "kcolorcollection.h" |
10 | |
11 | #if KGUIADDONS_BUILD_DEPRECATED_SINCE(6, 3) |
12 | #include <QDir> |
13 | #include <QFile> |
14 | #include <QSaveFile> |
15 | #include <QSharedData> |
16 | #include <QStandardPaths> |
17 | #include <QTextStream> |
18 | |
19 | // BEGIN KColorCollectionPrivate |
20 | class KColorCollectionPrivate : public QSharedData |
21 | { |
22 | public: |
23 | KColorCollectionPrivate(const QString &); |
24 | KColorCollectionPrivate(const KColorCollectionPrivate &) = default; |
25 | ~KColorCollectionPrivate() |
26 | { |
27 | } |
28 | struct ColorNode { |
29 | ColorNode(const QColor &c, const QString &n) |
30 | : color(c) |
31 | , name(n) |
32 | { |
33 | } |
34 | QColor color; |
35 | QString name; |
36 | }; |
37 | QList<ColorNode> colorList; |
38 | |
39 | QString name; |
40 | QString desc; |
41 | KColorCollection::Editable editable; |
42 | }; |
43 | |
44 | KColorCollectionPrivate::KColorCollectionPrivate(const QString &_name) |
45 | : name(_name) |
46 | { |
47 | if (name.isEmpty()) { |
48 | return; |
49 | } |
50 | |
51 | QString filename = QStandardPaths::locate(type: QStandardPaths::GenericConfigLocation, fileName: QLatin1String("colors/" ) + name); |
52 | if (filename.isEmpty()) { |
53 | return; |
54 | } |
55 | |
56 | QFile paletteFile(filename); |
57 | if (!paletteFile.exists()) { |
58 | return; |
59 | } |
60 | if (!paletteFile.open(flags: QIODevice::ReadOnly)) { |
61 | return; |
62 | } |
63 | |
64 | // Read first line |
65 | // Expected "GIMP Palette" |
66 | QString line = QString::fromLocal8Bit(ba: paletteFile.readLine()); |
67 | if (line.contains(s: QLatin1String(" Palette" ))) { |
68 | return; |
69 | } |
70 | |
71 | while (!paletteFile.atEnd()) { |
72 | line = QString::fromLocal8Bit(ba: paletteFile.readLine()); |
73 | if (line[0] == QLatin1Char('#')) { |
74 | // This is a comment line |
75 | line.remove(i: 0, len: 1); // Strip '#' |
76 | line = line.trimmed(); // Strip remaining white space.. |
77 | if (!line.isEmpty()) { |
78 | desc += line + QLatin1Char('\n'); // Add comment to description |
79 | } |
80 | } else { |
81 | // This is a color line, hopefully |
82 | line = line.trimmed(); |
83 | if (line.isEmpty()) { |
84 | continue; |
85 | } |
86 | int r; |
87 | int g; |
88 | int b; |
89 | int pos = 0; |
90 | if (sscanf(s: line.toLatin1().constData(), format: "%d %d %d%n" , &r, &g, &b, &pos) >= 3) { |
91 | r = qBound(min: 0, val: r, max: 255); |
92 | g = qBound(min: 0, val: g, max: 255); |
93 | b = qBound(min: 0, val: b, max: 255); |
94 | QString name = line.mid(position: pos).trimmed(); |
95 | colorList.append(t: ColorNode(QColor(r, g, b), name)); |
96 | } |
97 | } |
98 | } |
99 | } |
100 | // END KColorCollectionPrivate |
101 | |
102 | QStringList KColorCollection::installedCollections() |
103 | { |
104 | const QStringList paletteDirs = QStandardPaths::locateAll(type: QStandardPaths::GenericConfigLocation, QStringLiteral("colors" ), options: QStandardPaths::LocateDirectory); |
105 | |
106 | QStringList paletteList; |
107 | for (const QString &dir : paletteDirs) { |
108 | paletteList += QDir(dir).entryList(filters: QDir::Files | QDir::NoDotAndDotDot); |
109 | } |
110 | paletteList.removeDuplicates(); |
111 | |
112 | return paletteList; |
113 | } |
114 | |
115 | KColorCollection::KColorCollection(const QString &name) |
116 | : d(new KColorCollectionPrivate(name)) |
117 | { |
118 | } |
119 | |
120 | KColorCollection::KColorCollection(const KColorCollection &p) = default; |
121 | |
122 | // Need auto-save? |
123 | KColorCollection::~KColorCollection() = default; |
124 | |
125 | bool KColorCollection::save() |
126 | { |
127 | QString filename = QStandardPaths::writableLocation(type: QStandardPaths::GenericConfigLocation) + QLatin1String("/colors/" ) + d->name; |
128 | QSaveFile sf(filename); |
129 | if (!sf.open(flags: QIODevice::WriteOnly)) { |
130 | return false; |
131 | } |
132 | |
133 | QTextStream str(&sf); |
134 | |
135 | QString description = d->desc.trimmed(); |
136 | description = QLatin1Char('#') + description.split(sep: QLatin1Char('\n'), behavior: Qt::KeepEmptyParts).join(sep: QLatin1String("\n#" )); |
137 | |
138 | str << QLatin1String("KDE RGB Palette\n" ); |
139 | str << description << QLatin1Char('\n'); |
140 | for (const KColorCollectionPrivate::ColorNode &node : std::as_const(t&: d->colorList)) { |
141 | int r; |
142 | int g; |
143 | int b; |
144 | node.color.getRgb(r: &r, g: &g, b: &b); |
145 | str << r << " " << g << " " << b << " " << node.name << "\n" ; |
146 | } |
147 | |
148 | return sf.commit(); |
149 | } |
150 | |
151 | QString KColorCollection::description() const |
152 | { |
153 | return d->desc; |
154 | } |
155 | |
156 | void KColorCollection::setDescription(const QString &desc) |
157 | { |
158 | d->desc = desc; |
159 | } |
160 | |
161 | QString KColorCollection::name() const |
162 | { |
163 | return d->name; |
164 | } |
165 | |
166 | void KColorCollection::setName(const QString &name) |
167 | { |
168 | d->name = name; |
169 | } |
170 | |
171 | KColorCollection::Editable KColorCollection::editable() const |
172 | { |
173 | return d->editable; |
174 | } |
175 | |
176 | void KColorCollection::setEditable(Editable editable) |
177 | { |
178 | d->editable = editable; |
179 | } |
180 | |
181 | int KColorCollection::count() const |
182 | { |
183 | return d->colorList.count(); |
184 | } |
185 | |
186 | KColorCollection &KColorCollection::operator=(const KColorCollection &p) = default; |
187 | |
188 | QColor KColorCollection::color(int index) const |
189 | { |
190 | if ((index < 0) || (index >= count())) { |
191 | return QColor(); |
192 | } |
193 | |
194 | return d->colorList[index].color; |
195 | } |
196 | |
197 | int KColorCollection::findColor(const QColor &color) const |
198 | { |
199 | for (int i = 0; i < d->colorList.size(); ++i) { |
200 | if (d->colorList[i].color == color) { |
201 | return i; |
202 | } |
203 | } |
204 | return -1; |
205 | } |
206 | |
207 | QString KColorCollection::name(int index) const |
208 | { |
209 | if ((index < 0) || (index >= count())) { |
210 | return QString(); |
211 | } |
212 | |
213 | return d->colorList[index].name; |
214 | } |
215 | |
216 | QString KColorCollection::name(const QColor &color) const |
217 | { |
218 | return name(index: findColor(color)); |
219 | } |
220 | |
221 | int KColorCollection::addColor(const QColor &newColor, const QString &newColorName) |
222 | { |
223 | d->colorList.append(t: KColorCollectionPrivate::ColorNode(newColor, newColorName)); |
224 | return count() - 1; |
225 | } |
226 | |
227 | int KColorCollection::changeColor(int index, const QColor &newColor, const QString &newColorName) |
228 | { |
229 | if ((index < 0) || (index >= count())) { |
230 | return -1; |
231 | } |
232 | |
233 | KColorCollectionPrivate::ColorNode &node = d->colorList[index]; |
234 | node.color = newColor; |
235 | node.name = newColorName; |
236 | |
237 | return index; |
238 | } |
239 | |
240 | int KColorCollection::changeColor(const QColor &oldColor, const QColor &newColor, const QString &newColorName) |
241 | { |
242 | return changeColor(index: findColor(color: oldColor), newColor, newColorName); |
243 | } |
244 | |
245 | #endif |
246 | |