16 #include <QtAlgorithms>
17 #include "../../util/btassert.h"
18 #include "../config/btconfig.h"
19 #include "../drivers/cswordmoduleinfo.h"
20 #include "../keys/cswordkey.h"
21 #include "../keys/cswordversekey.h"
22 #include "../managers/cdisplaytemplatemgr.h"
23 #include "../managers/cswordbackend.h"
34 : m_settings(settings)
40 : m_settings(settings)
41 , m_alternativeContent(content)
47 : m_settings(settings)
53 const QString &stopKey,
56 : m_settings(settings)
71 if (!
m_key.isEmpty() && !stopKey.isEmpty()) {
74 while (ok && ((start < stop) || (start == stop)) ) {
79 settings.keyRenderingFace});
83 else if (
m_key.isEmpty()) {
108 if (startKey == stopKey) {
112 sword::VerseKey vk(startKey.toUtf8().constData(), stopKey.toUtf8().constData());
114 if (vk.getLowerBound().getBook() != vk.getUpperBound().getBook()) {
117 else if (vk.getLowerBound().getChapter() != vk.getUpperBound().getChapter()) {
119 .arg(QString::fromUtf8(vk.getLowerBound().getText()))
120 .arg(vk.getUpperBound().getChapter())
121 .arg(vk.getUpperBound().getVerse());
125 .arg(QString::fromUtf8(vk.getLowerBound().getText()))
126 .arg(vk.getUpperBound().getVerse());
130 QStringLiteral(
"<div class=\"rangeheading\" dir=\"ltr\">%1 (%2)"
145 : m_displayOptions(displayOptions)
146 , m_filterOptions(filterOptions)
156 for (
auto const & item : tree)
157 for (
auto const *
const mod : item.modules())
158 if (!modules.contains(mod))
172 if (modules.count() == 1) {
173 std::unique_ptr<CSwordKey> key(modules.first()->createKey());
174 for (
auto const & item : tree) {
175 key->setKey(item.key());
180 for (
auto const & item : tree)
191 const QString &highlightKey,
195 if (lowerBound == upperBound)
203 auto curKey = lowerBound;
206 settings.
highlight = (!highlightKey.isEmpty() ? (curKey.key() == highlightKey) :
false);
214 if (curKey.chapter() == 0) {
216 tree.emplace_back(curKey.key(), modules, settings);
217 curKey.setChapter(1);
220 tree.emplace_back(curKey.key(), modules, settings);
221 if (!curKey.next()) {
225 }
while (curKey < upperBound);
235 tree.emplace_back(key, modules, settings);
243 ? QStringLiteral(
"<div class=\"currententry\">")
244 : QStringLiteral(
"<div class=\"entry\">");
252 if (modules.count() == 1)
255 QStringLiteral(
"dir=\"%1\" ")
256 .arg(modules.first()->textDirectionAsHtml()));
258 for (
auto const & item : tree)
262 ret.append(QStringLiteral(
"</div>"));
268 if (modules.isEmpty())
271 std::unique_ptr<CSwordKey> scoped_key(
272 !k ? modules.first()->createKey() :
nullptr);
273 CSwordKey *
const key = k ? k : scoped_key.get();
280 bool const oneModule = modules.size() == 1;
281 auto renderedText(oneModule
282 ? QStringLiteral(
"\n")
283 : QStringLiteral(
"\n\t\t<tr>\n"));
286 for (
auto const & modulePtr : modules) {
302 auto & swModule = modulePtr->swordModule();
303 auto const langAttr =
304 QStringLiteral(
" xml:lang=\"%1\" lang=\"%1\"").arg(
305 modulePtr->language()->abbrev());
307 QString key_renderedText;
315 if (vk->isBoundSet()) {
317 auto const lowerBoundIndex = vk->lowerBound().index();
318 auto const upperBoundIndex = vk->upperBound().index();
319 for (
auto i = lowerBoundIndex; i < upperBoundIndex; ++i) {
320 key_renderedText +=
' ';
328 QStringLiteral(
"<span class=\"inactive\">—</span>");
335 swModule.renderText(
nullptr, -1, 0);
338 : swModule.getEntryAttributes()[
"Heading"][
"Preverse"])
340 auto preverseHeading(QString::fromUtf8(vp.second.c_str()));
341 if (preverseHeading.isEmpty())
344 static QString
const greaterOrS(
345 QStringLiteral(
">\x20\x09\x0d\x0a"));
346 for (
auto i = preverseHeading.indexOf(
'<');
348 i = preverseHeading.indexOf(
'<', i))
350 auto ref = QStringView(preverseHeading).mid(i + 1);
351 if (ref.startsWith(QStringLiteral(
"title"))) {
353 if (!ref.isEmpty() && greaterOrS.contains(ref[0])) {
354 auto const charsUntilTagEnd = ref.indexOf(
'>');
355 if (charsUntilTagEnd < 0)
358 preverseHeading.remove(i, charsUntilTagEnd + 7);
362 }
else if (ref.startsWith(QStringLiteral(
"/title"))) {
364 if (!ref.isEmpty() && greaterOrS.contains(ref[0])) {
365 auto const charsUntilTagEnd = ref.indexOf(
'>');
366 if (charsUntilTagEnd < 0)
369 preverseHeading.remove(i, charsUntilTagEnd + 8);
373 }
else if (ref.startsWith(QStringLiteral(
"div"))) {
375 if (!ref.isEmpty() && greaterOrS.contains(ref[0])) {
376 auto const charsUntilTagEnd = ref.indexOf(
'>');
377 if (charsUntilTagEnd < 0)
379 if (charsUntilTagEnd > 0) {
380 if (ref[charsUntilTagEnd - 1] ==
'/') {
382 preverseHeading.remove(
384 charsUntilTagEnd + 5);
386 i += charsUntilTagEnd + 5;
400 if (!preverseHeading.isEmpty())
401 entry = QStringLiteral(
402 "<div%1 class=\"sectiontitle\">%2</div>")
403 .arg(langAttr, preverseHeading);
408 ? QStringLiteral(
"<div class=\"")
409 : QStringLiteral(
"<div class=\"inline "));
411 entry.append(QStringLiteral(
"current"));
412 entry.append(QStringLiteral(
"entry\""));
413 auto const textDirectionAttribute =
414 QStringLiteral(
" dir=\"%1\">").arg(
415 modulePtr->textDirectionAsHtml());
416 entry.append(langAttr).append(textDirectionAttribute);
422 "<span class=\"entryname\" dir=\"ltr\">%1</span>")
426 entry.append(key_renderedText);
431 entry.append(QStringLiteral(
"</div>"));
434 renderedText.append(QStringLiteral(
"\t\t%1\n").arg(entry));
437 QStringLiteral(
"\t\t<td class=\"%1entry\"%2%3\n\t\t\t%4"
440 ? QStringLiteral(
"current")
443 textDirectionAttribute,
449 renderedText.append(QStringLiteral(
"\t\t</tr>\n"));
460 if (settings.
modules.count() == 1) {
465 settings.
langAbbrev = QStringLiteral(
"unknown");
479 {
return item.
key(); }
BtConfig & btConfig()
This is a shortchand for BtConfig::getInstance().
QList< CSwordModuleInfo const * > BtConstModuleList
QString fillTemplate(const QString &name, const QString &content, const Settings &settings) const
Fills the template.
static QString activeTemplateName()
static CDisplayTemplateMgr * instance()
static CSwordBackend & instance() noexcept
void setFilterOptions(const FilterOptions &options)
QString renderedText(const CSwordKey::TextRenderType mode=CSwordKey::Normal)
virtual void setModule(const CSwordModuleInfo *newModule)
virtual bool setKey(const QString &key)=0
virtual QString key() const =0
std::shared_ptr< Language const > language() const
CSwordModuleInfo::TextDirection textDirection() const
QString const & name() const
CSwordKey implementation for Sword's VerseKey.
bool next(const JumpType type=JumpType::UseVerse)
QString key() const final override
bool setKey(const QString &key) final override
void setMappedKey(CSwordKey const *key) const
KeyTree & childList() const noexcept
QString const & getAlternativeContent() const
Settings const & settings() const
BtConstModuleList m_moduleList
QString m_alternativeContent
BtConstModuleList const & modules() const
bool hasAlternativeContent() const
QString const & key() const
KeyTreeItem(KeyTreeItem &&)=delete
Text rendering based on trees.
virtual QString renderEntry(KeyTreeItem const &item, CSwordKey *key=nullptr) const
virtual QString finishText(QString const &text, KeyTree const &tree) const
QString renderSingleKey(const QString &key, const BtConstModuleList &modules, const KeyTreeItem::Settings &settings=KeyTreeItem::Settings())
virtual QString entryLink(KeyTreeItem const &item, CSwordModuleInfo const &module) const
virtual ~CTextRendering()
QString renderKeyRange(CSwordVerseKey const &lowerBound, CSwordVerseKey const &upperBound, const BtConstModuleList &modules, const QString &hightlightKey=QString(), const KeyTreeItem::Settings &settings=KeyTreeItem::Settings())
std::list< KeyTreeItem > KeyTree
CTextRendering(bool addText)
QString renderKeyTree(KeyTree const &tree) const
DisplayOptions m_displayOptions
static BtConstModuleList collectModules(KeyTree const &tree)
FilterOptions m_filterOptions
CSwordModuleInfo::TextDirection textDirection
BtConstModuleList modules
@ NoKey
means no key shown at all
KeyRenderingFace keyRenderingFace