20#include <QRegularExpression>
21#include <QRegularExpressionMatch>
22#include <QSharedPointer>
26#include "../../util/btassert.h"
27#include "../btglobal.h"
28#include "../config/btconfig.h"
29#include "../drivers/btmodulelist.h"
30#include "../drivers/cswordlexiconmoduleinfo.h"
31#include "../drivers/cswordmoduleinfo.h"
32#include "../keys/cswordkey.h"
33#include "../managers/cdisplaytemplatemgr.h"
34#include "../managers/cswordbackend.h"
39#pragma GCC diagnostic push
40#pragma GCC diagnostic ignored "-Wextra-semi"
41#pragma GCC diagnostic ignored "-Wsuggest-override"
42#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
44#pragma clang diagnostic push
45#pragma clang diagnostic ignored "-Wsuggest-destructor-override"
53#pragma clang diagnostic pop
55#pragma GCC diagnostic pop
68 return QStringLiteral(
69 "<div class=\"abbreviation\"><h3>%1: text</h3><p>%2</p></div>")
70 .arg(QObject::tr(
"Abbreviation"), data);
77 return QStringLiteral(
"<div class=\"crossrefinfo\"><h3>%1</h3></div>")
78 .arg(QObject::tr(
"Cross references"));
94 static QRegularExpression
const re(QStringLiteral(R
"PCRE(^[^ ]+:)PCRE"));
96 int pos = re.match(data).capturedEnd();
101 auto moduleName = data.left(pos);
103 module = CSwordBackend::instance().findModuleByName(
104 std::move(moduleName));
108 module = btConfig().getDefaultSwordModuleByType(
109 QStringLiteral("standardBible"));
111 if (!module && modules.size() > 0)
112 module = modules.at(0);
122 sword::ListKey refs =
124 (
const char*) data.mid((pos == -1) ? 0 : pos + 1).toUtf8(),
128 for (
int i = 0; i < refs.getCount(); i++) {
129 sword::SWKey *
const key = refs.getElement(i);
131 sword::VerseKey *
const vk =
dynamic_cast<sword::VerseKey*
>(key);
133 if (vk && vk->isBoundSet()) {
135 QString::fromUtf8(vk->getLowerBound().getText()),
136 QString::fromUtf8(vk->getUpperBound().getText()),
140 tree.emplace_back(QString::fromUtf8(key->getText()),
141 QString::fromUtf8(key->getText()),
147 tree.emplace_back(data.mid((pos == -1) ? 0 : pos + 1),
155 return QStringLiteral(
"<div class=\"crossrefinfo\" lang=\"%1\"><h3>%2</h3>"
156 "<div class=\"para\" dir=\"%3\">%4</div></div>")
157 .arg(module ? module->
language()->abbrev() : QStringLiteral(
"en"),
158 QObject::tr(
"Cross references"),
159 module ? module->textDirectionAsHtml() : QString())
160 .arg(renderer.renderKeyTree(tree));
164 QStringList list = data.split(
'/');
173 const QString modulename = list.first();
174 const QString swordFootnote = list.last();
179 const QString keyname = list.join(
'/');
181 auto *
const module =
182 CSwordBackend::instance().findModuleByName(modulename);
186 QSharedPointer<CSwordKey> key(module->createKey());
187 key->setKey(keyname);
192 auto & m =
module->swordModule();
193 const char *
const note =
194 m.getEntryAttributes()
195 [
"Footnote"][swordFootnote.toLatin1().data()][
"body"].c_str();
196 return QStringLiteral(
"<div class=\"footnoteinfo\" lang=\"%1\"><h3>%2</h3>"
198 .arg(module->language()->abbrev(),
199 QObject::tr(
"Footnote"),
200 QString::fromUtf8(m.renderText(note).c_str()));
206 auto lexModule = qobject_cast<CSwordLexiconModuleInfo *>(m);
209 && lexModule->hasStrongsKeys())
213 && lexModule->hasStrongsKeys())
224 ? QStringLiteral(
"standardHebrewStrongsLexicon")
225 : QStringLiteral(
"standardGreekStrongsLexicon"));
231 for (
auto const & strongs : data.split(
'|')) {
232 bool const wantHebrew = strongs.left(1) ==
'H';
236 QSharedPointer<CSwordKey> key(module->createKey());
237 auto lexModule = qobject_cast<CSwordLexiconModuleInfo *>(module);
238 key->setKey(lexModule->normalizeStrongsKey(strongs));
239 text = key->renderedText();
244 QStringLiteral(
"<div class=\"strongsinfo\" lang=\"%1\"><h3>%2: %3"
245 "</h3><p>%4</p></div>")
246 .arg(module ? module->language()->abbrev() : QStringLiteral(
"en"),
247 QObject::tr(
"Strongs"),
256 QStringList morphs = data.split(
'|');
259 for (
auto const & morph : morphs) {
262 bool skipFirstChar =
false;
266 int valStart = morph.indexOf(
':');
268 valueClass = morph.mid(0, valStart);
270 module = CSwordBackend::instance().findModuleByName(valueClass);
272 value = morph.mid(valStart + 1);
280 if (value.size() > 1 && value.at(1).isDigit()) {
281 switch (value.at(0).toLatin1()) {
283 module = btConfig().getDefaultSwordModuleByType(
285 "standardGreekMorphLexicon"));
286 skipFirstChar =
true;
289 module = btConfig().getDefaultSwordModuleByType(
291 "standardHebrewMorphLexicon"));
292 skipFirstChar =
true;
295 skipFirstChar =
false;
306 module = btConfig().getDefaultSwordModuleByType(
307 QStringLiteral("standardGreekMorphLexicon"));
313 QSharedPointer<CSwordKey> key(module->createKey());
316 const bool isOk = key->setKey(skipFirstChar ? value.mid(1) : value);
324 QStringLiteral(
"standardHebrewMorphLexicon")));
325 key->setKey(skipFirstChar ? value.mid(1) : value);
328 text = key->renderedText();
332 ret.append(QStringLiteral(
"<div class=\"morphinfo\" lang=\"%1\">"
333 "<h3>%2: %3</h3><p>%4</p></div>")
335 ? module->language()->abbrev()
336 : QStringLiteral(
"en"),
337 QObject::tr(
"Morphology"),
346 static QRegularExpression
const rx(
347 QStringLiteral(R
"PCRE(sword://(bible|lexicon)/(.*)/(.*))PCRE"),
348 QRegularExpression::CaseInsensitiveOption);
349 if (
auto const match = rx.match(data); match.hasMatch()) {
350 if (
auto *
const module =
354 std::unique_ptr<CSwordKey> key(module->createKey());
355 auto reference = match.captured(3);
356 key->setKey(reference);
357 return QStringLiteral(
"<div class=\"crossrefinfo\" lang=\"%1\">"
358 "<h3>%2</h3><p>%3</p></div>")
359 .arg(module->language()->abbrev(),
360 std::move(reference),
361 key->renderedText());
373 auto const attrList(data.split(QStringLiteral(
"||")));
375 for (
auto const & attrPair : attrList) {
376 auto const attr(attrPair.split(
'='));
377 if (attr.size() == 2) {
378 auto const & attrName = attr[0];
379 auto const & attrValue = attr[1];
380 if (attrName == QStringLiteral(
"note")) {
381 list.append(qMakePair(
Footnote, attrValue));
382 }
else if (attrName == QStringLiteral(
"lemma")) {
383 list.append(qMakePair(
Lemma, attrValue));
384 }
else if (attrName == QStringLiteral(
"morph")) {
385 list.append(qMakePair(
Morph, attrValue));
386 }
else if (attrName == QStringLiteral(
"expansion")) {
388 }
else if (attrName == QStringLiteral(
"crossrefs")) {
390 }
else if (attrName == QStringLiteral(
"href")) {
391 list.append(qMakePair(
Reference, attrValue));
401 BT_ASSERT(!modules.contains(
nullptr) && (modules.size() <= 1 &&
"not implemented"));
408 for (
auto const & infoData : list) {
409 auto const & value = infoData.second;
410 switch (infoData.first) {
412 text.append(decodeStrongs(value));
415 text.append(decodeMorph(value));
418 text.append(decodeCrossReference(value, modules));
421 text.append(decodeFootnote(value));
424 text.append(decodeAbbreviation(value));
430 if (value.contains(QStringLiteral(
"strongs:"))) {
431 auto v(value.right(value.size() - value.lastIndexOf(
'/')
433 if (value.contains(QStringLiteral(
"GREEK"))) {
435 }
else if (value.contains(QStringLiteral(
"HEBREW"))) {
440 text.append(decodeStrongs(v));
441 }
else if (value.contains(QStringLiteral(
"sword:"))) {
442 text.append(decodeSwordReference(value));
456QString
formatInfo(QString
const & info, QString
const & lang) {
461 settings.
pageCSS_ID = QStringLiteral(
"infodisplay");
465 QStringLiteral(
"<div class=\"infodisplay\"%1>%2</div>")
468 : QStringLiteral(
" lang=\"%1\"").arg(lang),
BtConfig & btConfig()
This is a shortchand for BtConfig::getInstance().
QList< CSwordModuleInfo const * > BtConstModuleList
CSwordModuleInfo * getDefaultSwordModuleByType(const QString &moduleType)
Returns default sword module info class for a given module type.
QString fillTemplate(const QString &name, const QString &content, const Settings &settings) const
Fills the template.
static QString activeTemplateName()
static CDisplayTemplateMgr * instance()
CSwordModuleInfo * findModuleByName(const QString &name) const
Searches for a module with the given name.
static CSwordBackend & instance() noexcept
QList< CSwordModuleInfo * > const & moduleList() const
void setFilterOptions(const FilterOptions &options)
@ ProcessEntryAttributesOnly
std::shared_ptr< Language const > language() const
std::list< KeyTreeItem > KeyTree
QList< InfoData > ListInfoData
QString formatInfo(const ListInfoData &list, BtConstModuleList const &modules)
ListInfoData detectInfo(QString const &data)
QString decodeMorph(QString const &data)
QString decodeStrongs(QString const &data)
QString decodeAbbreviation(QString const &data)
CSwordModuleInfo * getStrongsModule(bool const wantHebrew)
CSwordModuleInfo * getFirstAvailableStrongsModule(bool wantHebrew)
QString decodeFootnote(QString const &data)
QString decodeSwordReference(QString const &data)
QString decodeCrossReference(QString const &data, BtConstModuleList const &modules)
@ CompleteShort
means key like "Gen 1:1"