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-2025 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 <QVariant>
24#include <utility>
25#include "../../util/btassert.h"
26#include "../../util/directory.h"
27#include "../../backend/managers/cdisplaytemplatemgr.h"
28
29
30namespace ColorManager {
31namespace {
32
33bool darkMode() {
34 auto const & palette = qApp->palette();
35 return palette.color(QPalette::WindowText).value()
36 > palette.color(QPalette::Window).value();
37}
38
39using ColorMaps = std::map<QString, std::map<QString, QString> >;
40
42 namespace DU = util::directory;
43 QDir::Filters const readableFileFilter(QDir::Files | QDir::Readable);
44 QStringList const cssFilter(QStringLiteral("*.css"));
45
47
48 auto const loadColorMap =
49 [&colorMaps](QString const & filePath) {
50 QFileInfo const cssInfo(filePath);
51 static auto const cMapPathTemplate(
52 QStringLiteral("%1/%2.cmap"));
53 auto cMapPath(cMapPathTemplate.arg(cssInfo.path())
54 .arg(cssInfo.completeBaseName()));
55 QFileInfo const cMapInfo(cMapPath);
56 auto fileName(cssInfo.fileName());
57
58 // Start with default color map:
59 std::map<QString, QString> colorMap;
60 auto const p(qApp->palette());
61 if (darkMode()) {
62 colorMap.emplace(QStringLiteral("FOREGROUND_COLOR"),
63 p.color(QPalette::WindowText).name());
64 colorMap.emplace(QStringLiteral("BACKGROUND_COLOR"),
65 p.color(QPalette::Base).name());
66 colorMap.emplace(QStringLiteral("HIGHLIGHT"),
67 QStringLiteral("#ffff00"));
68 colorMap.emplace(QStringLiteral("BACKGROUND_HIGHLIGHT"),
69 QStringLiteral("#444466"));
70 colorMap.emplace(QStringLiteral("CROSSREF_COLOR"),
71 QStringLiteral("#aac2ff"));
72 colorMap.emplace(QStringLiteral("JESUS_WORDS_COLOR"),
73 QStringLiteral("#ff0000"));
74 } else {
75 colorMap.emplace(QStringLiteral("FOREGROUND_COLOR"),
76 p.color(QPalette::WindowText).name());
77 colorMap.emplace(QStringLiteral("BACKGROUND_COLOR"),
78 p.color(QPalette::Base).name());
79 colorMap.emplace(QStringLiteral("HIGHLIGHT"),
80 QStringLiteral("#ffff00"));
81 colorMap.emplace(QStringLiteral("BACKGROUND_HIGHLIGHT"),
82 QStringLiteral("#ddddff"));
83 colorMap.emplace(QStringLiteral("CROSSREF_COLOR"),
84 QStringLiteral("#1414ff"));
85 colorMap.emplace(QStringLiteral("JESUS_WORDS_COLOR"),
86 QStringLiteral("#ff0000"));
87 }
88
89 if (cMapInfo.exists()) {
90 QSettings cMapSettings(cMapPath, QSettings::IniFormat);
91 static auto const dark = QStringLiteral("dark");
92 static auto const light = QStringLiteral("light");
93 cMapSettings.beginGroup(darkMode() ? dark : light);
94 for (auto const & colorKey : cMapSettings.childKeys())
95 colorMap[colorKey] = cMapSettings.value(colorKey).toString();
96 }
97 colorMaps[std::move(fileName)] = std::move(colorMap);
98 };
99
100 // Load global app stylesheets
101 auto const & td = DU::getDisplayTemplatesDir();
102 for (auto const & file : td.entryList(cssFilter, readableFileFilter))
103 loadColorMap(QStringLiteral("%1/%2").arg(td.canonicalPath(), file));
104
105 // Load user app stylesheets
106 auto const & utd = DU::getUserDisplayTemplatesDir();
107 for (auto const & file : utd.entryList(cssFilter, readableFileFilter))
108 loadColorMap(QStringLiteral("%1/%2").arg(utd.canonicalPath(), file));
109
110 return colorMaps;
111}
112
113auto const & colorMaps() {
114 static auto const maps = createColorMaps();
115 return maps;
116}
117
118QString getColorByPattern(QString const & pattern, QString const & templateName)
119{
120 BT_ASSERT(!templateName.isEmpty());
121 auto const & maps = colorMaps();
122 auto const mapIt(maps.find(templateName));
123 BT_ASSERT(mapIt != maps.end());
124 auto const valueIt(mapIt->second.find(pattern));
125 BT_ASSERT(valueIt != mapIt->second.end());
126 BT_ASSERT(!valueIt->second.isEmpty());
127 return valueIt->second;
128}
129
130} // anonymous namespace
131
132
133QString replaceColors(QString content) {
134 return replaceColors(std::move(content),
136}
137
138QString replaceColors(QString content, QString const & templateName) {
139 auto const & maps = colorMaps();
140 auto const mapsIt = maps.find(templateName);
141 BT_ASSERT(mapsIt != maps.end());
142 for (auto const & [key, value] : mapsIt->second)
143 content.replace(QStringLiteral("#%1#").arg(key), value);
144 return content;
145}
146
149
150QString getBackgroundColor(QString const & templateName)
151{ return getColorByPattern(QStringLiteral("BACKGROUND_COLOR"), templateName); }
152
157
158QString getBackgroundHighlightColor(QString const & templateName) {
159 return getColorByPattern(QStringLiteral("BACKGROUND_HIGHLIGHT"),
160 templateName);
161}
162
165
166QString getForegroundColor(QString const & templateName)
167{ return getColorByPattern(QStringLiteral("FOREGROUND_COLOR"), templateName); }
168
171
172QString getCrossRefColor(QString const & templateName)
173{ return getColorByPattern(QStringLiteral("CROSSREF_COLOR"), templateName); }
174
175} // 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()
QString getCrossRefColor()