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("SkyColorDaytime", i18n("Sky Daytime"), "#7896e6");
31 appendItem("DSOColor", i18n("Messier Object"), "#008f00");
32 appendItem("HSTColor", i18nc("Object with extra attached URLs", "Object w/ Links"), "#930000");
33 appendItem("SNameColor", i18n("Star Name"), "#577d7d");
34 appendItem("DSNameColor", i18n("Deep Sky Object Name"), "#75759c");
35 appendItem("PNameColor", i18n("Planet Name"), "#ac9800");
36 appendItem("CNameColor", i18nc("Constellation Name", "Constell. Name"), "#718488");
37 appendItem("CLineColor", i18nc("Constellation Line", "Constell. Line"), "#3d3d3d");
38 appendItem("CBoundColor", i18nc("Constellation Boundary", "Constell. Boundary"), "#222f2f");
39 appendItem("CBoundHighColor", i18nc("Highlighted Constellation Boundary", "Constell. Boundary Highlight"),
40 "#445555");
41 appendItem("MWColor", i18nc("refers to the band of stars in the sky due to the Galactic plane", "Milky Way"),
42 "#0d1115");
43 appendItem("EqColor", i18n("Equator"), "#909090");
44 appendItem("EclColor", i18n("Ecliptic"), "#613d12");
45 appendItem("HorzColor", i18n("Horizon"), "#091f14");
46 appendItem("LocalMeridianColor", i18n("Local Meridian"), "#0059b3");
47 appendItem("CompassColor", i18n("Compass Labels"), "#909055");
48 appendItem("EquatorialGridColor", i18n("Equatorial Coordinate Grid"), "#445566");
49 appendItem("HorizontalGridColor", i18n("Horizontal Coordinate Grid"), "#091f14");
50 appendItem("BoxTextColor", i18n("Info Box Text"), "#d2dbef");
51 appendItem("BoxGrabColor", i18n("Info Box Selected"), "#900000");
52 appendItem("BoxBGColor", i18n("Info Box Background"), "#000000");
53 appendItem("TargetColor", i18n("Target Indicator"), "#DD0000");
54 appendItem("UserLabelColor", i18n("User Labels"), "#AAAAAA");
55 appendItem("PlanetTrailColor", i18n("Planet Trails"), "#993311");
56 appendItem("AngularRuler", i18n("Angular Distance Ruler"), "#445566");
57 appendItem("ObsListColor", i18n("Observing List Label"), "#FF0000");
58 appendItem("StarHopRouteColor", i18n("Star-Hop Route"), "#00FFFF");
59 appendItem("VisibleSatColor", i18n("Visible Satellites"), "#00FF00");
60 appendItem("SatColor", i18n("Satellites"), "#FF0000");
61 appendItem("SatLabelColor", i18n("Satellites Labels"), "#640000");
62 appendItem("SupernovaColor", i18n("Supernovae"), "#FFA500");
63 appendItem("AsteroidColor", i18n("Asteroids"), "#F1C232");
64 appendItem("ArtificialHorizonColor", i18n("Artificial Horizon"), "#C82828");
65 appendItem("RAGuideError", i18n("RA Guide Error"), "#00FF00");
66 appendItem("DEGuideError", i18n("DEC Guide Error"), "#00A5FF");
67 appendItem("SolverFOVColor", i18n("Solver FOV"), "#FFFFFF");
68 appendItem("SensorFOVColor", i18n("Sensor FOV"), "#FFAA00");
69 appendItem("HIPSGridColor", i18n("HiPS Grid"), "#FFFFFF");
70 appendItem("DomeColor", i18n("Dome Slit"), "#445566");
71 appendItem("FITSObjectLabelColor", i18n("FITS Image Object Label"), "#00FF00");
72 appendItem("FITSObjectHighlightLabelColor", i18n("FITS Image Object Highlight Label"), "#FF0000");
73
74 //Load colors from config object
76
77 //Default values for integer variables:
78 StarColorMode = 0;
79 StarColorIntensity = 4;
80 DarkPalette = 0;
81}
82
83void ColorScheme::appendItem(const QString &key, const QString &name, const QString &def)
84{
85 KeyName.append(key);
86 Name.append(name);
87 Default.append(def);
88}
89
91{
92 if (!hasColorNamed(name))
93 {
94 qWarning() << "No color named" << name << "found in color scheme.";
95 // Return white if no color found
96 return QColor(Qt::white);
97 }
98 return QColor(Palette[name]);
99}
100
102{
103 return QColor(Palette[KeyName.at(i)]);
104}
105
107{
108 return Name.at(i);
109}
110
112{
113 return KeyName.at(i);
114}
115
117{
118 return nameAt(KeyName.indexOf(key));
119}
120
121void ColorScheme::setColor(const QString &key, const QString &color)
122{
123 //We can blindly insert() the new value; if the key exists, the old value is replaced
124 Palette.insert(key, color);
125
127 cg.writeEntry(key, color);
128}
129
130bool ColorScheme::load(const QString &name)
131{
132 QString filename = name.toLower().trimmed();
133 QFile file;
134 int inew = 0, iold = 0;
135 bool ok = false;
136
137 //Parse default names which don't follow the regular file-naming scheme
138 if (name == i18nc("use default color scheme", "Default Colors"))
139 filename = "classic.colors";
140 if (name == i18nc("use 'star chart' color scheme", "Star Chart"))
141 filename = "chart.colors";
142 if (name == i18nc("use 'night vision' color scheme", "Night Vision"))
143 filename = "night.colors";
144
145 //Try the filename if it ends with ".colors"
146 if (filename.endsWith(QLatin1String(".colors")))
147 ok = KSUtils::openDataFile(file, filename);
148
149 //If that didn't work, try assuming that 'name' is the color scheme name
150 //convert it to a filename exactly as ColorScheme::save() does
151 if (!ok)
152 {
153 if (!filename.isEmpty())
154 {
155 filename.replace(' ', '-').append(".colors");
156 ok = KSUtils::openDataFile(file, filename);
157 }
158
159 if (!ok)
160 {
161 qDebug() << Q_FUNC_INFO << QString("Unable to load color scheme named %1. Also tried %2.").arg(name, filename);
162 return false;
163 }
164 }
165
166 //If we reach here, the file should have been successfully opened
167 QTextStream stream(&file);
168
169 //first line is the star-color mode and star color intensity and dark palette
170 QString line = stream.readLine();
171 QStringList modes = line.split(':');
172
173 // Star Color Mode
174 if (modes.count() > 0)
175 {
176 int newmode = modes[0].toInt(&ok);
177 if (ok)
178 setStarColorMode(newmode);
179 }
180
181 // Star Intensity
182 if (modes.count() > 1)
183 {
184 int newintens = modes[1].toInt(&ok);
185 if (ok)
186 setStarColorIntensity(newintens);
187 }
188
189 // Dark Palette
190#if 0
191 if (modes.count() > 2)
192 {
193 int newintens = modes[2].toInt(&ok);
194 if (ok)
195 setDarkPalette(newintens == 1);
196 }
197#endif
198
199 //More flexible method for reading in color values. Any order is acceptable, and
200 //missing entries are ignored.
201 while (!stream.atEnd())
202 {
203 line = stream.readLine();
204
205 if (line.count(':') ==
206 1) //the new color preset format contains a ":" in each line, followed by the name of the color
207 {
208 ++inew;
209 if (iold)
210 return false; //we read at least one line without a colon...file is corrupted.
211
212 //If this line has a valid Key, set the color.
213 QString tkey = line.mid(line.indexOf(':') + 1).trimmed();
214 QString tname = line.left(line.indexOf(':') - 1);
215
216 if (KeyName.contains(tkey))
217 {
218 setColor(tkey, tname);
219 }
220 else //attempt to translate from old color ID
221 {
222 QString k(line.mid(5).trimmed() + "Color");
223 if (KeyName.contains(k))
224 {
225 setColor(k, tname);
226 }
227 else
228 {
229 qWarning() << "Could not use the key \"" << tkey << "\" from the color scheme file \"" << filename
230 << "\". I also tried \"" << k << "\".";
231 }
232 }
233 }
234 else // no ':' seen in the line, so we must assume the old format
235 {
236 ++iold;
237 if (inew)
238 return false; //a previous line had a colon, this line doesn't. File is corrupted.
239
240 //Assuming the old *.colors format. Loop through the KeyName list,
241 //and assign each color. Note that order matters here, but only here
242 //(so if you don't use the old format, then order doesn't ever matter)
243 foreach (const QString &key, KeyName)
244 setColor(key, line.left(7));
245 }
246 }
247
248 FileName = filename;
249 return true;
250}
251
252bool ColorScheme::save(const QString &name)
253{
254 QFile file;
255
256 //Construct a file name from the scheme name. Make lowercase, replace spaces with "-",
257 //and append ".colors".
258 QString filename = name.toLower().trimmed();
259 if (!filename.isEmpty())
260 {
261 for (int i = 0; i < filename.length(); ++i)
262 if (filename.at(i) == ' ')
263 filename.replace(i, 1, "-");
264
265 filename = filename.append(".colors");
266 //determine filename in local user KDE directory tree.
267 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(filename));
268
269 //if (file.exists() || !file.open(QIODevice::ReadWrite | QIODevice::Append))
270 if (!file.open(QIODevice::ReadWrite))
271 {
272 KSNotification::sorry(i18n("Local color scheme file could not be opened.\nScheme cannot be recorded."));
273 return false;
274 }
275 else
276 {
277 QTextStream stream(&file);
278 stream << StarColorMode << ":" << StarColorIntensity << ":" << DarkPalette << '\n';
279
280 foreach (const QString &key, KeyName)
281 stream << Palette[key] << " :" << key << '\n';
282 file.close();
283 }
284
285 //determine filename in local user KDE directory tree.
286 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("colors.dat"));
287
288 if (!file.open(QIODevice::ReadWrite))
289 {
290 KSNotification::sorry(i18n("Local color scheme index file could not be opened.\nScheme cannot be recorded."));
291 }
292 else
293 {
294 bool found = false;
295 QString schemeLine = name + ':' + filename;
296
297 // Check if the scheme line is in the colors.dat file
298 // If not, then we add it
299 QTextStream stream(&file);
300 while (stream.atEnd() == false)
301 {
302 QString line = stream.readLine();
303 if (line == schemeLine)
304 {
305 found = true;
306 break;
307 }
308 }
309
310 if (found == false)
311 {
312 stream << schemeLine << '\n';
313 file.close();
314 }
315 }
316 }
317 else
318 {
319 KSNotification::sorry("Invalid filename requested.\nScheme cannot be recorded.");
320 return false;
321 }
322
323 FileName = filename;
324 saveToConfig();
325 return true;
326}
327
329{
331
332 for (int i = 0; i < KeyName.size(); ++i)
333 setColor(KeyName.at(i), cg.readEntry(KeyName.at(i).toUtf8().constData(), Default.at(i)));
334
335 setStarColorModeIntensity(cg.readEntry("StarColorMode", 0), cg.readEntry("StarColorIntensity", 5));
336 //setDarkPalette(cg.readEntry("DarkAppColors", false));
337
338 FileName = cg.readEntry("ColorSchemeFile", "moonless-night.colors");
339}
340
342{
344 for (int i = 0; i < KeyName.size(); ++i)
345 {
346 QString c = colorNamed(KeyName.at(i)).name();
347 cg.writeEntry(KeyName.at(i), c);
348 }
349
350 cg.writeEntry("StarColorMode", starColorMode());
351 cg.writeEntry("StarColorIntensity", starColorIntensity());
352 cg.writeEntry("ColorSchemeFile", FileName);
353 cg.writeEntry("DarkAppColors", useDarkPalette());
354}
355
357{
358 StarColorMode = mode;
359 Options::setStarColorMode(mode);
360#ifndef KSTARS_LITE
362#endif
363}
364
365#if 0
366void ColorScheme::setDarkPalette(bool enable)
367{
368 DarkPalette = enable ? 1 : 0;
369 Options::setDarkAppColors(enable);
370#ifndef KSTARS_LITE
372#endif
373}
374#endif
375
377{
378 StarColorIntensity = intens;
379 Options::setStarColorIntensity(intens);
380#ifndef KSTARS_LITE
382#endif
383}
384
386{
387 StarColorMode = mode;
388 StarColorIntensity = intens;
389 Options::setStarColorMode(mode);
390 Options::setStarColorIntensity(intens);
391#ifndef KSTARS_LITE
393#endif
394}
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)
qsizetype count() 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 atEnd() const const
QString readLine(qint64 maxlen)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:52:59 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.