Kstars

colorscheme.cpp
1/*
2 SPDX-FileCopyrightText: 2002 Jason Harris <kstars@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "colorscheme.h"
8
9#include "kspaths.h"
10#include "ksutils.h"
11#include "Options.h"
12#include "auxiliary/ksnotification.h"
13#include "skyobjects/starobject.h"
14#ifdef KSTARS_LITE
15#include "skymaplite.h"
16#else
17#include "skyqpainter.h"
18#endif
19
21{
22 //Each color has two names associated with it. The KeyName is its
23 //identification in the QMap, the *.colors file, and the config file.
24 //The Name is what appears in the ViewOpsDialog ListBox.
25 //In addition, we define default RGB strings for each item.
26 //To add another color to the Palette, just add an entry for KeyName,
27 //Name and Default here.
28
29 appendItem("SkyColor", i18n("Sky"), "#000000");
30 appendItem("DSOColor", i18n("Messier Object"), "#008f00");
31 appendItem("HSTColor", i18nc("Object with extra attached URLs", "Object w/ Links"), "#930000");
32 appendItem("SNameColor", i18n("Star Name"), "#577d7d");
33 appendItem("DSNameColor", i18n("Deep Sky Object Name"), "#75759c");
34 appendItem("PNameColor", i18n("Planet Name"), "#ac9800");
35 appendItem("CNameColor", i18nc("Constellation Name", "Constell. Name"), "#718488");
36 appendItem("CLineColor", i18nc("Constellation Line", "Constell. Line"), "#3d3d3d");
37 appendItem("CBoundColor", i18nc("Constellation Boundary", "Constell. Boundary"), "#222f2f");
38 appendItem("CBoundHighColor", i18nc("Highlighted Constellation Boundary", "Constell. Boundary Highlight"),
39 "#445555");
40 appendItem("MWColor", i18nc("refers to the band of stars in the sky due to the Galactic plane", "Milky Way"),
41 "#0d1115");
42 appendItem("EqColor", i18n("Equator"), "#909090");
43 appendItem("EclColor", i18n("Ecliptic"), "#613d12");
44 appendItem("HorzColor", i18n("Horizon"), "#091f14");
45 appendItem("LocalMeridianColor", i18n("Local Meridian"), "#0059b3");
46 appendItem("CompassColor", i18n("Compass Labels"), "#909055");
47 appendItem("EquatorialGridColor", i18n("Equatorial Coordinate Grid"), "#445566");
48 appendItem("HorizontalGridColor", i18n("Horizontal Coordinate Grid"), "#091f14");
49 appendItem("BoxTextColor", i18n("Info Box Text"), "#d2dbef");
50 appendItem("BoxGrabColor", i18n("Info Box Selected"), "#900000");
51 appendItem("BoxBGColor", i18n("Info Box Background"), "#000000");
52 appendItem("TargetColor", i18n("Target Indicator"), "#DD0000");
53 appendItem("UserLabelColor", i18n("User Labels"), "#AAAAAA");
54 appendItem("PlanetTrailColor", i18n("Planet Trails"), "#993311");
55 appendItem("AngularRuler", i18n("Angular Distance Ruler"), "#445566");
56 appendItem("ObsListColor", i18n("Observing List Label"), "#FF0000");
57 appendItem("StarHopRouteColor", i18n("Star-Hop Route"), "#00FFFF");
58 appendItem("VisibleSatColor", i18n("Visible Satellites"), "#00FF00");
59 appendItem("SatColor", i18n("Satellites"), "#FF0000");
60 appendItem("SatLabelColor", i18n("Satellites Labels"), "#640000");
61 appendItem("SupernovaColor", i18n("Supernovae"), "#FFA500");
62 appendItem("AsteroidColor", i18n("Asteroids"), "#F1C232");
63 appendItem("ArtificialHorizonColor", i18n("Artificial Horizon"), "#C82828");
64 appendItem("RAGuideError", i18n("RA Guide Error"), "#00FF00");
65 appendItem("DEGuideError", i18n("DEC Guide Error"), "#00A5FF");
66 appendItem("SolverFOVColor", i18n("Solver FOV"), "#FFFFFF");
67 appendItem("SensorFOVColor", i18n("Sensor FOV"), "#FFAA00");
68 appendItem("HIPSGridColor", i18n("HiPS Grid"), "#FFFFFF");
69 appendItem("FITSObjectLabelColor", i18n("FITS Image Object Label"), "#00FF00");
70
71 //Load colors from config object
73
74 //Default values for integer variables:
75 StarColorMode = 0;
76 StarColorIntensity = 4;
77 DarkPalette = 0;
78}
79
80void ColorScheme::appendItem(const QString &key, const QString &name, const QString &def)
81{
82 KeyName.append(key);
83 Name.append(name);
84 Default.append(def);
85}
86
88{
89 if (!hasColorNamed(name))
90 {
91 qWarning() << "No color named" << name << "found in color scheme.";
92 // Return white if no color found
93 return QColor(Qt::white);
94 }
95 return QColor(Palette[name]);
96}
97
99{
100 return QColor(Palette[KeyName.at(i)]);
101}
102
104{
105 return Name.at(i);
106}
107
109{
110 return KeyName.at(i);
111}
112
114{
115 return nameAt(KeyName.indexOf(key));
116}
117
118void ColorScheme::setColor(const QString &key, const QString &color)
119{
120 //We can blindly insert() the new value; if the key exists, the old value is replaced
121 Palette.insert(key, color);
122
124 cg.writeEntry(key, color);
125}
126
127bool ColorScheme::load(const QString &name)
128{
129 QString filename = name.toLower().trimmed();
130 QFile file;
131 int inew = 0, iold = 0;
132 bool ok = false;
133
134 //Parse default names which don't follow the regular file-naming scheme
135 if (name == i18nc("use default color scheme", "Default Colors"))
136 filename = "classic.colors";
137 if (name == i18nc("use 'star chart' color scheme", "Star Chart"))
138 filename = "chart.colors";
139 if (name == i18nc("use 'night vision' color scheme", "Night Vision"))
140 filename = "night.colors";
141
142 //Try the filename if it ends with ".colors"
143 if (filename.endsWith(QLatin1String(".colors")))
144 ok = KSUtils::openDataFile(file, filename);
145
146 //If that didn't work, try assuming that 'name' is the color scheme name
147 //convert it to a filename exactly as ColorScheme::save() does
148 if (!ok)
149 {
150 if (!filename.isEmpty())
151 {
152 filename.replace(' ', '-').append(".colors");
153 ok = KSUtils::openDataFile(file, filename);
154 }
155
156 if (!ok)
157 {
158 qDebug() << Q_FUNC_INFO << QString("Unable to load color scheme named %1. Also tried %2.").arg(name, filename);
159 return false;
160 }
161 }
162
163 //If we reach here, the file should have been successfully opened
164 QTextStream stream(&file);
165
166 //first line is the star-color mode and star color intensity and dark palette
167 QString line = stream.readLine();
168 QStringList modes = line.split(':');
169
170 // Star Color Mode
171 if (modes.count() > 0)
172 {
173 int newmode = modes[0].toInt(&ok);
174 if (ok)
175 setStarColorMode(newmode);
176 }
177
178 // Star Intensity
179 if (modes.count() > 1)
180 {
181 int newintens = modes[1].toInt(&ok);
182 if (ok)
183 setStarColorIntensity(newintens);
184 }
185
186 // Dark Palette
187#if 0
188 if (modes.count() > 2)
189 {
190 int newintens = modes[2].toInt(&ok);
191 if (ok)
192 setDarkPalette(newintens == 1);
193 }
194#endif
195
196 //More flexible method for reading in color values. Any order is acceptable, and
197 //missing entries are ignored.
198 while (!stream.atEnd())
199 {
200 line = stream.readLine();
201
202 if (line.count(':') ==
203 1) //the new color preset format contains a ":" in each line, followed by the name of the color
204 {
205 ++inew;
206 if (iold)
207 return false; //we read at least one line without a colon...file is corrupted.
208
209 //If this line has a valid Key, set the color.
210 QString tkey = line.mid(line.indexOf(':') + 1).trimmed();
211 QString tname = line.left(line.indexOf(':') - 1);
212
213 if (KeyName.contains(tkey))
214 {
215 setColor(tkey, tname);
216 }
217 else //attempt to translate from old color ID
218 {
219 QString k(line.mid(5).trimmed() + "Color");
220 if (KeyName.contains(k))
221 {
222 setColor(k, tname);
223 }
224 else
225 {
226 qWarning() << "Could not use the key \"" << tkey << "\" from the color scheme file \"" << filename
227 << "\". I also tried \"" << k << "\".";
228 }
229 }
230 }
231 else // no ':' seen in the line, so we must assume the old format
232 {
233 ++iold;
234 if (inew)
235 return false; //a previous line had a colon, this line doesn't. File is corrupted.
236
237 //Assuming the old *.colors format. Loop through the KeyName list,
238 //and assign each color. Note that order matters here, but only here
239 //(so if you don't use the old format, then order doesn't ever matter)
240 foreach (const QString &key, KeyName)
241 setColor(key, line.left(7));
242 }
243 }
244
245 FileName = filename;
246 return true;
247}
248
249bool ColorScheme::save(const QString &name)
250{
251 QFile file;
252
253 //Construct a file name from the scheme name. Make lowercase, replace spaces with "-",
254 //and append ".colors".
255 QString filename = name.toLower().trimmed();
256 if (!filename.isEmpty())
257 {
258 for (int i = 0; i < filename.length(); ++i)
259 if (filename.at(i) == ' ')
260 filename.replace(i, 1, "-");
261
262 filename = filename.append(".colors");
263 //determine filename in local user KDE directory tree.
264 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(filename));
265
266 //if (file.exists() || !file.open(QIODevice::ReadWrite | QIODevice::Append))
267 if (!file.open(QIODevice::ReadWrite))
268 {
269 KSNotification::sorry(i18n("Local color scheme file could not be opened.\nScheme cannot be recorded."));
270 return false;
271 }
272 else
273 {
274 QTextStream stream(&file);
275 stream << StarColorMode << ":" << StarColorIntensity << ":" << DarkPalette << '\n';
276
277 foreach (const QString &key, KeyName)
278 stream << Palette[key] << " :" << key << '\n';
279 file.close();
280 }
281
282 //determine filename in local user KDE directory tree.
283 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("colors.dat"));
284
285 if (!file.open(QIODevice::ReadWrite))
286 {
287 KSNotification::sorry(i18n("Local color scheme index file could not be opened.\nScheme cannot be recorded."));
288 }
289 else
290 {
291 bool found = false;
292 QString schemeLine = name + ':' + filename;
293
294 // Check if the scheme line is in the colors.dat file
295 // If not, then we add it
296 QTextStream stream(&file);
297 while (stream.atEnd() == false)
298 {
299 QString line = stream.readLine();
300 if (line == schemeLine)
301 {
302 found = true;
303 break;
304 }
305 }
306
307 if (found == false)
308 {
309 stream << schemeLine << '\n';
310 file.close();
311 }
312 }
313 }
314 else
315 {
316 KSNotification::sorry("Invalid filename requested.\nScheme cannot be recorded.");
317 return false;
318 }
319
320 FileName = filename;
321 saveToConfig();
322 return true;
323}
324
326{
328
329 for (int i = 0; i < KeyName.size(); ++i)
330 setColor(KeyName.at(i), cg.readEntry(KeyName.at(i).toUtf8().constData(), Default.at(i)));
331
332 setStarColorModeIntensity(cg.readEntry("StarColorMode", 0), cg.readEntry("StarColorIntensity", 5));
333 //setDarkPalette(cg.readEntry("DarkAppColors", false));
334
335 FileName = cg.readEntry("ColorSchemeFile", "moonless-night.colors");
336}
337
339{
341 for (int i = 0; i < KeyName.size(); ++i)
342 {
343 QString c = colorNamed(KeyName.at(i)).name();
344 cg.writeEntry(KeyName.at(i), c);
345 }
346
347 cg.writeEntry("StarColorMode", starColorMode());
348 cg.writeEntry("StarColorIntensity", starColorIntensity());
349 cg.writeEntry("ColorSchemeFile", FileName);
350 cg.writeEntry("DarkAppColors", useDarkPalette());
351}
352
354{
355 StarColorMode = mode;
356 Options::setStarColorMode(mode);
357#ifndef KSTARS_LITE
359#endif
360}
361
362#if 0
363void ColorScheme::setDarkPalette(bool enable)
364{
365 DarkPalette = enable ? 1 : 0;
366 Options::setDarkAppColors(enable);
367#ifndef KSTARS_LITE
369#endif
370}
371#endif
372
374{
375 StarColorIntensity = intens;
376 Options::setStarColorIntensity(intens);
377#ifndef KSTARS_LITE
379#endif
380}
381
383{
384 StarColorMode = mode;
385 StarColorIntensity = intens;
386 Options::setStarColorMode(mode);
387 Options::setStarColorIntensity(intens);
388#ifndef KSTARS_LITE
390#endif
391}
bool save(const QString &name)
Save the current color scheme to a *.colors file.
void saveToConfig()
Save color-scheme data to the Config object.
void setStarColorModeIntensity(int mode, int intens)
Set the star color mode and intensity value used by the color scheme mode the star color mode to use ...
QColor colorNamed(const QString &name) const
Retrieve a color by name.
int starColorIntensity() const
int starColorMode() const
void setStarColorIntensity(int intens)
Set the star color intensity value used by the color scheme intens The star color intensity value.
bool hasColorNamed(const QString &name) const
Definition colorscheme.h:36
QString nameFromKey(const QString &key) const
QColor colorAt(int i) const
i the index of the color to retrieve
QString nameAt(int i) const
i the index of the long name to retrieve
void setDarkPalette(bool enable)
setDarkPalette Set whether the color schemes uses dark palette
QString keyAt(int i) const
i the index of the key name to retrieve
bool load(const QString &filename)
Load a color scheme from a *.colors file filename the filename of the color scheme to be loaded.
void setColor(const QString &key, const QString &color)
Change the color with the given key to the given value key the key-name of the color to be changed co...
void loadFromConfig()
Read color-scheme data from the Config object.
void setStarColorMode(int mode)
Set the star color mode used by the color scheme mode the star color mode to use.
ColorScheme()
Constructor.
bool useDarkPalette() const
KConfigGroup group(const QString &group)
void writeEntry(const char *key, const char *value, WriteConfigFlags pFlags=Normal)
QString readEntry(const char *key, const char *aDefault=nullptr) const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
static void initStarImages()
Recalculates the star pixmaps.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString name(NameFormat format) const const
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
void setFileName(const QString &name)
virtual void close() override
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
qsizetype size() const const
qsizetype count() const const
QString & append(QChar ch)
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString toLower() const const
QString trimmed() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
qsizetype indexOf(const QRegularExpression &re, qsizetype from) const const
bool atEnd() const const
QString readLine(qint64 maxlen)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:01 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.