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

KDE's Doxygen guidelines are available online.