BibleTime
cdisplaysettings.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 "cdisplaysettings.h"
14
15#include <map>
16#include <memory>
17#include <QCheckBox>
18#include <QComboBox>
19#include <QFont>
20#include <QLabel>
21#include <QLocale>
22#include <QMap>
23#include <QNonConstOverload>
24#include <QPalette>
25#include <QSizePolicy>
26#include <Qt>
27#include <QVBoxLayout>
28#include <QFormLayout>
29#include <utility>
30#include "../../backend/config/btconfig.h"
31#include "../../backend/language.h"
32#include "../../backend/managers/btlocalemgr.h"
33#include "../../backend/managers/colormanager.h"
34#include "../../backend/managers/cdisplaytemplatemgr.h"
35#include "../../backend/rendering/cdisplayrendering.h"
36#include "../../backend/rendering/ctextrendering.h"
37#include "../../util/btassert.h"
38#include "../../util/btconnect.h"
39#include "../../util/cresmgr.h"
40#include "../../util/tool.h"
42
43// Sword includes:
44#include <swbuf.h>
45
46
47/** Initializes the startup section of the OD. */
49 : BtConfigDialog::Page(CResMgr::settings::startup::icon(), parent)
50{
51 QVBoxLayout *mainLayout = new QVBoxLayout(this);
52
53 QFormLayout *formLayout = new QFormLayout();
54
55 //startup logo
56 m_showLogoLabel = new QLabel(this);
57 m_showLogoCheck = new QCheckBox(this);
58 m_showLogoCheck->setChecked(
59 btConfig().value<bool>(QStringLiteral("GUI/showSplashScreen"),
60 true));
61 formLayout->addRow(m_showLogoLabel, m_showLogoCheck);
62
63 m_swordLocaleCombo = new QComboBox(this);
64 m_languageNamesLabel = new QLabel(this);
66 formLayout->addRow(m_languageNamesLabel, m_swordLocaleCombo);
67
69
70 // Light/Dark Mode
71 m_lightDarkLabel = new QLabel(this);
72 m_lightDarkCombo = new QComboBox(this);
73 formLayout->addRow(m_lightDarkLabel, m_lightDarkCombo);
74
75 m_styleChooserCombo = new QComboBox( this ); //create first to enable buddy for label
76 BT_CONNECT(m_styleChooserCombo, qOverload<int>(&QComboBox::activated),
78
79 m_availableLabel = new QLabel(this);
81 formLayout->addRow(m_availableLabel, m_styleChooserCombo );
82 mainLayout->addLayout(formLayout);
83
84 m_previewLabel = new QLabel(this);
85 m_previewLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
86
87 m_stylePreviewViewer = new QLabel(this);
88 m_stylePreviewViewer->setWordWrap(true);
89 m_stylePreviewViewer->setTextFormat(Qt::RichText);
90 m_stylePreviewViewer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
91 m_stylePreviewViewer->setAlignment(Qt::AlignTop);
92 m_stylePreviewViewer->setMargin(15);
93 m_stylePreviewViewer->setAutoFillBackground(true);
94 QFont font = m_stylePreviewViewer->font();
95 font.setPointSize(font.pointSize()+2);
96 m_stylePreviewViewer->setFont(font);
97
98 mainLayout->addWidget(m_previewLabel);
99 mainLayout->addWidget(m_stylePreviewViewer);
100
102 m_styleChooserCombo->addItems(tMgr->availableTemplates());
103
104 for (int i = 0; i < m_styleChooserCombo->count(); ++i) {
106 m_styleChooserCombo->setCurrentIndex(i);
107 break;
108 }
109 }
110
111 m_transifexLabel = new QLabel(this);
112 mainLayout->addWidget(m_transifexLabel);
113
114 retranslateUi(); // also calls updateStylePreview();
115 m_lightDarkCombo->setCurrentIndex(
116 btConfig().value<int>(QStringLiteral("GUI/lightDarkMode")));
117}
118
120 setHeaderText(tr("Display"));
121
122 m_languageNamesLabel->setText(tr("Language for names of Bible books:"));
123 const QString toolTip(tr("The languages which can be used for the biblical book names. Translations are provided by the Sword library."));
124 m_languageNamesLabel->setToolTip(toolTip);
125 m_swordLocaleCombo->setToolTip(toolTip);
126
127 m_showLogoLabel->setText(tr("Show startup logo:"));
128 m_showLogoLabel->setToolTip(tr("Show the BibleTime logo on startup."));
129
130 m_lightDarkLabel->setText(tr("Light / dark Mode (Requires restart)"));
131 m_lightDarkCombo->addItem(tr("System default"));
132 m_lightDarkCombo->addItem(tr("Light"));
133 m_lightDarkCombo->addItem(tr("Dark"));
134
135 m_availableLabel->setText(tr("Available display styles:"));
136 m_previewLabel->setText(tr("Style preview"));
137
139
140 m_transifexLabel->setWordWrap(true);
141 m_transifexLabel->setOpenExternalLinks(true);
142 m_transifexLabel->setText(tr(
143 "Did you know? You can help translating the GUI of BibleTime to your "
144 "language at "
145 "<a href=\"https://www.transifex.com/bibletime/bibletime/\">Transifex"
146 "</a>."));
147}
148
150 QVector<QString> atv = bookNameAbbreviationsTryVector();
151
152 BT_ASSERT(!atv.isEmpty());
153 QString best = atv.takeLast();
154 for (auto const & localePair : BtLocaleMgr::internalSwordLocales()) {
155 auto const & swordAbbreviation = localePair.first;
156 if (swordAbbreviation == "locales")
157 continue;
158 auto abbreviation =
159 util::tool::fixSwordBcp47(swordAbbreviation.c_str());
160 if (auto const i = atv.indexOf(abbreviation); i >= 0) {
161 best = std::move(abbreviation);
162 if (i == 0)
163 break;
164 atv.resize(i);
165 }
166 }
167 btConfig().setValue(QStringLiteral("GUI/booknameLanguage"), best);
168}
169
171 QVector<QString> atv;
172 atv.reserve(4);
173 {
174 QString settingsLanguage = btConfig().booknameLanguage();
175 if (!settingsLanguage.isEmpty())
176 atv.append(settingsLanguage);
177 }
178 {
179 auto localeLanguageAndCountry = QLocale().name(); // ISO 639 _ ISO 3166
180 if (!localeLanguageAndCountry.isEmpty()) {
181 localeLanguageAndCountry.replace('_', '-'); // Ensure BCP 47
182 atv.append(localeLanguageAndCountry);
183 if (auto const i = localeLanguageAndCountry.indexOf('-'); i > 0)
184 atv.append(localeLanguageAndCountry.left(i));
185 }
186 }
187 atv.append(Language::fromAbbrev({})->abbrev());
188 return atv;
189}
190
192 QMap<QString, QString> languageNames;
193 {
194 auto const defaultLanguage = Language::fromAbbrev({});
195 languageNames.insert(defaultLanguage->translatedName(),
196 defaultLanguage->abbrev());
197 }
198
199 for (auto const & localePair : BtLocaleMgr::internalSwordLocales()) {
200 auto const & swordAbbreviation = localePair.first;
201 if (swordAbbreviation.size() <= 0)
202 continue; // work around Sword not checking [Meta] Name= validity
203 if (swordAbbreviation == "locales")
204 continue;
205 auto abbreviation =
206 util::tool::fixSwordBcp47(swordAbbreviation.c_str());
207 auto const l = Language::fromAbbrev(std::move(abbreviation));
208 languageNames.insert(l->translatedName(), l->abbrev());
209 }
210
211 int index = 0;
212 QVector<QString> atv = bookNameAbbreviationsTryVector();
213 for (auto it = languageNames.constBegin(); it != languageNames.constEnd(); ++it) {
214 if (!atv.isEmpty()) {
215 int i = atv.indexOf(it.value());
216 if (i >= 0) {
217 atv.resize(i);
218 index = m_swordLocaleCombo->count();
219 }
220 }
221 m_swordLocaleCombo->addItem(it.key(), it.value());
222 }
223 m_swordLocaleCombo->setCurrentIndex(index);
224}
225
226
228 //update the style preview widget
229 using namespace Rendering;
230
231 const QString styleName = m_styleChooserCombo->currentText();
233
235 settings.highlight = false;
236
237 auto const previewText =
238 tr(R"====(<div class="sectiontitle">CHAPTER 3</div>
239
240<div xml:lang="en" lang="en" class="sectiontitle">The New Birth</div>
241
242<span class="entryname">
243 <a name="crossref" href="sword://Bible/WEB/John 3:1">1</a>
244</span>
245<span lemma="G1161">Now</span>
246<span lemma="G444">there was a man</span>
247<span lemma="G5330">of the Pharisees</span>,
248<span lemma="G3686">named</span>
249<span class="crossreference">
250 <a href="sword://Bible/NASB/John 7:50;" name="crossref">John 7:50</a>;
251 <a href="sword://Bible/NASB/John 19:39;" name="crossref">19:39</a>
252</span>
253<span lemma="G3530">Nicodemus</span>, a
254<span class="crossreference">
255 <a href="sword://Bible/NASB/Luke 23:13;" name="crossref">Luke 23:13</a>;
256 <a href="sword://Bible/NASB/John 7:26;" name="crossref">John 7:26</a>,<a href="sword://Bible/NASB/John 7:48;" name="crossref">48</a>
257</span>
258<span lemma="G758">ruler</span>
259<span lemma="G2453">of the Jews</span>;
260
261<span class="entryname">
262 <a name="crossref" href="sword://Bible/WEB/John 3:2">2</a>
263</span>
264<span lemma="G3778">this</span>
265<span lemma="G3778">man</span>
266<span lemma="G2064">came</span>
267<span lemma="G3571">to Jesus by night</span>
268<span lemma="G3004">and said</span> to Him,
269<span class="crossreference">
270 <a href="sword://Bible/NASB/Matthew 23:7;" name="crossref">Matt 23:7</a>;
271 <a href="sword://Bible/NASB/John 3:26;" name="crossref">John 3:26</a>
272</span>
273"<span lemma="G4461">Rabbi</span>,
274<span lemma="G3609a">we know</span>
275<span lemma="G2064">that You have come</span>
276<span lemma="G2316">from God</span>
277<span class="transchange" title="Added text">
278 <span class="added">as</span>
279</span>
280<span lemma="G1320">a teacher</span>;
281<span lemma="G3762">for no</span>
282<span lemma="G3762">one</span>
283<span lemma="G1410">can</span>
284<span lemma="G4160">do</span>
285<span lemma="G3778">these</span>
286<span class="footnote" note="NASB/John 3:2/1">(1)</span>
287<span class="crossreference">
288 <a href="sword://Bible/NASB/John 2:11;" name="crossref">John 2:11</a>
289</span>
290<span lemma="G4592">signs</span>
291<span lemma="G4160">that You do</span>
292<span lemma="G1437|G3361">unless</span>
293<span class="crossreference">
294 <a href="sword://Bible/NASB/John 9:33;" name="crossref">John 9:33</a>;
295 <a href="sword://Bible/NASB/John 10:38;" name="crossref">10:38</a>;
296 <a href="sword://Bible/NASB/John 14:10-John 14:11;" name="crossref">
297 14:10f</a>;
298 <a href="sword://Bible/NASB/Acts 2:22;" name="crossref">Acts 2:22</a>;
299 <a href="sword://Bible/NASB/Acts 10:38;" name="crossref">10:38</a>
300</span>
301<span lemma="G2316">God</span> is with him."
302
303<span class="entryname">
304 <a name="crossref" href="sword://Bible/WEB/John 3:3">3</a>
305</span>
306<span lemma="G2424">Jesus answered and said to him</span>,
307<span class="jesuswords">
308 "Truly, truly, I say to you, unless one
309 <span class="crossreference">
310 <a href="sword://Bible/NASB/II Corinthians 5:17;" name="crossref">
311 2 Cor 5:17</a>;
312 <a href="sword://Bible/NASB/I Peter 1:23;" name="crossref">
313 1 Pet 1:23</a>
314 </span>
315 <span lemma="G1080">is born</span>
316 <span class="footnote" note="NASB/John 3:3/1">(1)</span>
317 <span lemma="G509">again</span>
318 <span lemma="G1410|G3756">he cannot</span>
319 <span lemma="G3708">see</span>
320 <span class="crossreference">
321 <a href="sword://Bible/NASB/Matthew 19:24;" name="crossref">
322 Matt 19:24</a>;
323 <a href="sword://Bible/NASB/Matthew 21:31;" name="crossref">21:31</a>;
324 <a href="sword://Bible/NASB/Mark 9:47;" name="crossref">Mark 9:47</a>;
325 <a href="sword://Bible/NASB/Mark 10:14-Mark 10:15;" name="crossref">
326 10:14f</a>;
327 <a href="sword://Bible/NASB/John 3:5;" name="crossref">John 3:5</a>
328 </span>
329 <span lemma="G932">the kingdom</span>
330 <span lemma="G2316">of God</span>."
331</span>)====",
332 "This markup is used to render the preview text in the settings "
333 "dialog. It contains a lot of markup because we want to "
334 "showcase multiple textual features to the user comparing "
335 "different display templates to choose from. For English we "
336 "have chosen to use John 3:1-3 but translations are free to use "
337 "other Bible passages as well as markup specific to the Bible "
338 "translations of the language as long as the text continues to "
339 "serve the intended purpose. At runtime, the translated text is "
340 "automatically split into multiple verses when empty lines (two "
341 "consecutive newline characters) are encountered.");
342 for (auto const & verse
343 : previewText.split(QStringLiteral("\n\n"), Qt::SkipEmptyParts))
344 tree.emplace_back(verse, settings);
345
346 CDisplayRendering render;
347 render.setDisplayTemplateName(styleName);
348 QString text = render.renderKeyTree(tree);
349 text.replace(QStringLiteral("#CHAPTERTITLE#"), QString());
350
351 // Update colors:
352 QPalette p = m_stylePreviewViewer->palette();
353 p.setColor(QPalette::Window, ColorManager::getBackgroundColor(styleName));
354 p.setColor(QPalette::WindowText,
356 m_stylePreviewViewer->setPalette(p);
357
358 text = ColorManager::replaceColors(text, styleName);
359 m_stylePreviewViewer->setText(text);
360}
361
363 btConfig().setValue(QStringLiteral("GUI/showSplashScreen"),
364 m_showLogoCheck->isChecked());
365 btConfig().setValue(QStringLiteral("GUI/activeTemplateName"),
366 m_styleChooserCombo->currentText());
367 btConfig().setValue(QStringLiteral("GUI/booknameLanguage"),
368 m_swordLocaleCombo->itemData(
369 m_swordLocaleCombo->currentIndex()));
370 btConfig().setValue(QStringLiteral("GUI/lightDarkMode"),
371 m_lightDarkCombo->currentIndex());
372}
#define BT_ASSERT(...)
Definition btassert.h:17
BtConfig & btConfig()
This is a shortchand for BtConfig::getInstance().
Definition btconfig.h:305
#define BT_CONNECT(...)
Definition btconnect.h:20
void setValue(QString const &key, T const &value)
Sets a value for a key.
void setHeaderText(QString const &headerText)
QString booknameLanguage()
Definition btconfig.cpp:464
static QVector< QString > bookNameAbbreviationsTryVector()
QComboBox * m_swordLocaleCombo
CDisplaySettingsPage(CConfigurationDialog *parent=nullptr)
void save() const final override
QComboBox * m_styleChooserCombo
static QString activeTemplateName()
static CDisplayTemplateMgr * instance()
QStringList const & availableTemplates() const
static std::shared_ptr< Language const > fromAbbrev(QString const &abbrev)
Definition language.cpp:329
Rendering for the html display widget.
void setDisplayTemplateName(QString displayTemplateName) noexcept
std::list< KeyTreeItem > KeyTree
QString renderKeyTree(KeyTree const &tree) const
std::map< sword::SWBuf, sword::SWLocale * > const & internalSwordLocales()
QString getForegroundColor()
QString getBackgroundColor()
QString replaceColors(QString content)
QString fixSwordBcp47(QString input)
Definition tool.cpp:158