BibleTime
colormanager.cpp
Go to the documentation of this file.
1/*********
2*
3* In the name of the Father, and of the Son, and of the Holy Spirit.
4*
5* This file is part of BibleTime's source code, https://bibletime.info/
6*
7* Copyright 1999-2026 by the BibleTime developers.
8* The BibleTime source code is licensed under the GNU General Public License
9* version 2.0.
10*
11**********/
12
13#include "colormanager.h"
14
15#include <map>
16#include <QApplication>
17#include <QColor>
18#include <QDir>
19#include <QFileInfo>
20#include <QPalette>
21#include <QSettings>
22#include <QStringList>
23#include <QStyleHints>
24#include <QVariant>
25#include <utility>
26#include "../../util/btassert.h"
27#include "../../util/directory.h"
28#include "../../backend/managers/cdisplaytemplatemgr.h"
29
30
31namespace ColorManager {
32namespace {
33
34bool darkMode() {
35 switch (QApplication::styleHints()->colorScheme()) {
36 case Qt::ColorScheme::Dark: return true;
37 case Qt::ColorScheme::Light: return false;
38 case Qt::ColorScheme::Unknown: break;
39 default: break;
40 }
41 auto const & palette = QApplication::palette();
42 return palette.color(QPalette::WindowText).lightness()
43 > palette.color(QPalette::Window).lightness();
44}
45
46using ColorMaps = std::map<QString, std::map<QString, QString> >;
47
49 namespace DU = util::directory;
50 QDir::Filters const readableFileFilter(QDir::Files | QDir::Readable);
51 QStringList const cssFilter(QStringLiteral("*.css"));
52
54
55 auto const loadColorMap =
56 [&colorMaps](QString const & filePath) {
57 QFileInfo const cssInfo(filePath);
58 static auto const cMapPathTemplate(
59 QStringLiteral("%1/%2.cmap"));
60 auto cMapPath(cMapPathTemplate.arg(cssInfo.path())
61 .arg(cssInfo.completeBaseName()));
62 QFileInfo const cMapInfo(cMapPath);
63 auto fileName(cssInfo.fileName());
64
65 // Start with default color map:
66 std::map<QString, QString> colorMap;
67 auto const p(qApp->palette());
68 if (darkMode()) {
69 colorMap.emplace(QStringLiteral("FOREGROUND_COLOR"),
70 p.color(QPalette::WindowText).name());
71 colorMap.emplace(QStringLiteral("BACKGROUND_COLOR"),
72 p.color(QPalette::Base).name());
73 colorMap.emplace(QStringLiteral("HIGHLIGHT"),
74 QStringLiteral("#ffff00"));
75 colorMap.emplace(QStringLiteral("BACKGROUND_HIGHLIGHT"),
76 QStringLiteral("#444466"));
77 colorMap.emplace(QStringLiteral("CROSSREF_COLOR"),
78 QStringLiteral("#aac2ff"));
79 colorMap.emplace(QStringLiteral("JESUS_WORDS_COLOR"),
80 QStringLiteral("#ff0000"));
81 } else {
82 colorMap.emplace(QStringLiteral("FOREGROUND_COLOR"),
83 p.color(QPalette::WindowText).name());
84 colorMap.emplace(QStringLiteral("BACKGROUND_COLOR"),
85 p.color(QPalette::Base).name());
86 colorMap.emplace(QStringLiteral("HIGHLIGHT"),
87 QStringLiteral("#ffff00"));
88 colorMap.emplace(QStringLiteral("BACKGROUND_HIGHLIGHT"),
89 QStringLiteral("#ddddff"));
90 colorMap.emplace(QStringLiteral("CROSSREF_COLOR"),
91 QStringLiteral("#1414ff"));
92 colorMap.emplace(QStringLiteral("JESUS_WORDS_COLOR"),
93 QStringLiteral("#ff0000"));
94 }
95
96 if (cMapInfo.exists()) {
97 QSettings cMapSettings(cMapPath, QSettings::IniFormat);
98 static auto const dark = QStringLiteral("dark");
99 static auto const light = QStringLiteral("light");
100 cMapSettings.beginGroup(darkMode() ? dark : light);
101 for (auto const & colorKey : cMapSettings.childKeys())
102 colorMap[colorKey] = cMapSettings.value(colorKey).toString();
103 }
104 colorMaps[std::move(fileName)] = std::move(colorMap);
105 };
106
107 // Load global app stylesheets
108 auto const & td = DU::getDisplayTemplatesDir();
109 for (auto const & file : td.entryList(cssFilter, readableFileFilter))
110 loadColorMap(QStringLiteral("%1/%2").arg(td.canonicalPath(), file));
111
112 // Load user app stylesheets
113 auto const & utd = DU::getUserDisplayTemplatesDir();
114 for (auto const & file : utd.entryList(cssFilter, readableFileFilter))
115 loadColorMap(QStringLiteral("%1/%2").arg(utd.canonicalPath(), file));
116
117 return colorMaps;
118}
119
120auto const & colorMaps() {
121 static auto const maps = createColorMaps();
122 return maps;
123}
124
125QString getColorByPattern(QString const & pattern, QString const & templateName)
126{
127 BT_ASSERT(!templateName.isEmpty());
128 auto const & maps = colorMaps();
129 auto const mapIt(maps.find(templateName));
130 BT_ASSERT(mapIt != maps.end());
131 auto const valueIt(mapIt->second.find(pattern));
132 BT_ASSERT(valueIt != mapIt->second.end());
133 BT_ASSERT(!valueIt->second.isEmpty());
134 return valueIt->second;
135}
136
137} // anonymous namespace
138
139
140QString replaceColors(QString content) {
141 return replaceColors(std::move(content),
143}
144
145QString replaceColors(QString content, QString const & templateName) {
146 auto const & maps = colorMaps();
147 auto const mapsIt = maps.find(templateName);
148 BT_ASSERT(mapsIt != maps.end());
149 for (auto const & [key, value] : mapsIt->second)
150 content.replace(QStringLiteral("#%1#").arg(key), value);
151 return content;
152}
153
156
157QString getBackgroundColor(QString const & templateName)
158{ return getColorByPattern(QStringLiteral("BACKGROUND_COLOR"), templateName); }
159
164
165QString getBackgroundHighlightColor(QString const & templateName) {
166 return getColorByPattern(QStringLiteral("BACKGROUND_HIGHLIGHT"),
167 templateName);
168}
169
172
173QString getForegroundColor(QString const & templateName)
174{ return getColorByPattern(QStringLiteral("FOREGROUND_COLOR"), templateName); }
175
176} // namespace ColorManager
#define BT_ASSERT(...)
Definition btassert.h:17
static QString activeTemplateName()
std::map< QString, std::map< QString, QString > > ColorMaps
QString getColorByPattern(QString const &pattern, QString const &templateName)
QString getForegroundColor()
QString getBackgroundColor()
QString replaceColors(QString content)
QString getBackgroundHighlightColor()