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("FITSObjectLabelColor", i18n("FITS Image Object Label"), "#00FF00");
71 appendItem("FITSObjectHighlightLabelColor", i18n("FITS Image Object Highlight Label"), "#FF0000");
72
73 //Load colors from config object
75
76 //Default values for integer variables:
77 StarColorMode = 0;
78 StarColorIntensity = 4;
79 DarkPalette = 0;
80}
81
82void ColorScheme::appendItem(const QString &key, const QString &name, const QString &def)
83{
84 KeyName.append(key);
85 Name.append(name);
86 Default.append(def);
87}
88
90{
91 if (!hasColorNamed(name))
92 {
93 qWarning() << "No color named" << name << "found in color scheme.";
94 // Return white if no color found
95 return QColor(Qt::white);
96 }
97 return QColor(Palette[name]);
98}
99
101{
102 return QColor(Palette[KeyName.at(i)]);
103}
104
106{
107 return Name.at(i);
108}
109
111{
112 return KeyName.at(i);
113}
114
116{
117 return nameAt(KeyName.indexOf(key));
118}
119
120void ColorScheme::setColor(const QString &key, const QString &color)
121{
122 //We can blindly insert() the new value; if the key exists, the old value is replaced
123 Palette.insert(key, color);
124
126 cg.writeEntry(key, color);
127}
128
129bool ColorScheme::load(const QString &name)
130{
131 QString filename = name.toLower().trimmed();
132 QFile file;
133 int inew = 0, iold = 0;
134 bool ok = false;
135
136 //Parse default names which don't follow the regular file-naming scheme
137 if (name == i18nc("use default color scheme", "Default Colors"))
138 filename = "classic.colors";
139 if (name == i18nc("use 'star chart' color scheme", "Star Chart"))
140 filename = "chart.colors";
141 if (name == i18nc("use 'night vision' color scheme", "Night Vision"))
142 filename = "night.colors";
143
144 //Try the filename if it ends with ".colors"
145 if (filename.endsWith(QLatin1String(".colors")))
146 ok = KSUtils::openDataFile(file, filename);
147
148 //If that didn't work, try assuming that 'name' is the color scheme name
149 //convert it to a filename exactly as ColorScheme::save() does
150 if (!ok)
151 {
152 if (!filename.isEmpty())
153 {
154 filename.replace(' ', '-').append(".colors");
155 ok = KSUtils::openDataFile(file, filename);
156 }
157
158 if (!ok)
159 {
160 qDebug() << Q_FUNC_INFO << QString("Unable to load color scheme named %1. Also tried %2.").arg(name, filename);
161 return false;
162 }
163 }
164
165 //If we reach here, the file should have been successfully opened
166 QTextStream stream(&file);
167
168 //first line is the star-color mode and star color intensity and dark palette
169 QString line = stream.readLine();
170 QStringList modes = line.split(':');
171
172 // Star Color Mode
173 if (modes.count() > 0)
174 {
175 int newmode = modes[0].toInt(&ok);
176 if (ok)
177 setStarColorMode(newmode);
178 }
179
180 // Star Intensity
181 if (modes.count() > 1)
182 {
183 int newintens = modes[1].toInt(&ok);
184 if (ok)
185 setStarColorIntensity(newintens);
186 }
187
188 // Dark Palette
189#if 0
190 if (modes.count() > 2)
191 {
192 int newintens = modes[2].toInt(&ok);
193 if (ok)
194 setDarkPalette(newintens == 1);
195 }
196#endif
197
198 //More flexible method for reading in color values. Any order is acceptable, and
199 //missing entries are ignored.
200 while (!stream.atEnd())
201 {
202 line = stream.readLine();
203
204 if (line.count(':') ==
205 1) //the new color preset format contains a ":" in each line, followed by the name of the color
206 {
207 ++inew;
208 if (iold)
209 return false; //we read at least one line without a colon...file is corrupted.
210
211 //If this line has a valid Key, set the color.
212 QString tkey = line.mid(line.indexOf(':') + 1).trimmed();
213 QString tname = line.left(line.indexOf(':') - 1);
214
215 if (KeyName.contains(tkey))
216 {
217 setColor(tkey, tname);
218 }
219 else //attempt to translate from old color ID
220 {
221 QString k(line.mid(5).trimmed() + "Color");
222 if (KeyName.contains(k))
223 {
224 setColor(k, tname);
225 }
226 else
227 {
228 qWarning() << "Could not use the key \"" << tkey << "\" from the color scheme file \"" << filename
229 << "\". I also tried \"" << k << "\".";
230 }
231 }
232 }
233 else // no ':' seen in the line, so we must assume the old format
234 {
235 ++iold;
236 if (inew)
237 return false; //a previous line had a colon, this line doesn't. File is corrupted.
238
239 //Assuming the old *.colors format. Loop through the KeyName list,
240 //and assign each color. Note that order matters here, but only here
241 //(so if you don't use the old format, then order doesn't ever matter)
242 foreach (const QString &key, KeyName)
243 setColor(key, line.left(7));
244 }
245 }
246
247 FileName = filename;
248 return true;
249}
250
251bool ColorScheme::save(const QString &name)
252{
253 QFile file;
254
255 //Construct a file name from the scheme name. Make lowercase, replace spaces with "-",
256 //and append ".colors".
257 QString filename = name.toLower().trimmed();
258 if (!filename.isEmpty())
259 {
260 for (int i = 0; i < filename.length(); ++i)
261 if (filename.at(i) == ' ')
262 filename.replace(i, 1, "-");
263
264 filename = filename.append(".colors");
265 //determine filename in local user KDE directory tree.
266 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(filename));
267
268 //if (file.exists() || !file.open(QIODevice::ReadWrite | QIODevice::Append))
269 if (!file.open(QIODevice::ReadWrite))
270 {
271 KSNotification::sorry(i18n("Local color scheme file could not be opened.\nScheme cannot be recorded."));
272 return false;
273 }
274 else
275 {
276 QTextStream stream(&file);
277 stream << StarColorMode << ":" << StarColorIntensity << ":" << DarkPalette << '\n';
278
279 foreach (const QString &key, KeyName)
280 stream << Palette[key] << " :" << key << '\n';
281 file.close();
282 }
283
284 //determine filename in local user KDE directory tree.
285 file.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("colors.dat"));
286
287 if (!file.open(QIODevice::ReadWrite))
288 {
289 KSNotification::sorry(i18n("Local color scheme index file could not be opened.\nScheme cannot be recorded."));
290 }
291 else
292 {
293 bool found = false;
294 QString schemeLine = name + ':' + filename;
295
296 // Check if the scheme line is in the colors.dat file
297 // If not, then we add it
298 QTextStream stream(&file);
299 while (stream.atEnd() == false)
300 {
301 QString line = stream.readLine();
302 if (line == schemeLine)
303 {
304 found = true;
305 break;
306 }
307 }
308
309 if (found == false)
310 {
311 stream << schemeLine << '\n';
312 file.close();
313 }
314 }
315 }
316 else
317 {
318 KSNotification::sorry("Invalid filename requested.\nScheme cannot be recorded.");
319 return false;
320 }
321
322 FileName = filename;
323 saveToConfig();
324 return true;
325}
326
328{
330
331 for (int i = 0; i < KeyName.size(); ++i)
332 setColor(KeyName.at(i), cg.readEntry(KeyName.at(i).toUtf8().constData(), Default.at(i)));
333
334 setStarColorModeIntensity(cg.readEntry("StarColorMode", 0), cg.readEntry("StarColorIntensity", 5));
335 //setDarkPalette(cg.readEntry("DarkAppColors", false));
336
337 FileName = cg.readEntry("ColorSchemeFile", "moonless-night.colors");
338}
339
341{
343 for (int i = 0; i < KeyName.size(); ++i)
344 {
345 QString c = colorNamed(KeyName.at(i)).name();
346 cg.writeEntry(KeyName.at(i), c);
347 }
348
349 cg.writeEntry("StarColorMode", starColorMode());
350 cg.writeEntry("StarColorIntensity", starColorIntensity());
351 cg.writeEntry("ColorSchemeFile", FileName);
352 cg.writeEntry("DarkAppColors", useDarkPalette());
353}
354
356{
357 StarColorMode = mode;
358 Options::setStarColorMode(mode);
359#ifndef KSTARS_LITE
361#endif
362}
363
364#if 0
365void ColorScheme::setDarkPalette(bool enable)
366{
367 DarkPalette = enable ? 1 : 0;
368 Options::setDarkAppColors(enable);
369#ifndef KSTARS_LITE
371#endif
372}
373#endif
374
376{
377 StarColorIntensity = intens;
378 Options::setStarColorIntensity(intens);
379#ifndef KSTARS_LITE
381#endif
382}
383
385{
386 StarColorMode = mode;
387 StarColorIntensity = intens;
388 Options::setStarColorMode(mode);
389 Options::setStarColorIntensity(intens);
390#ifndef KSTARS_LITE
392#endif
393}
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 Mon Nov 4 2024 16:38:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.