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-2021 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"
41 #include "cconfigurationdialog.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.
Definition: btconfigcore.h:73
void setHeaderText(QString const &headerText)
QString booknameLanguage()
Definition: btconfig.cpp:473
static QVector< QString > bookNameAbbreviationsTryVector()
QComboBox * m_swordLocaleCombo
QCheckBox * m_showLogoCheck
CDisplaySettingsPage(CConfigurationDialog *parent=nullptr)
QComboBox * m_lightDarkCombo
void save() const final override
QComboBox * m_styleChooserCombo
static QString activeTemplateName()
QStringList const & availableTemplates() const
static CDisplayTemplateMgr * instance()
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()
Definition: btlocalemgr.cpp:48
QString getForegroundColor()
QString getBackgroundColor()
QString replaceColors(QString content)
QString fixSwordBcp47(QString input)
Definition: tool.cpp:158