BibleTime
cswordversekey.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 "cswordversekey.h"
14 
15 #include <QDebug>
16 #include <QStringList>
17 #include <string_view>
18 #include "../../util/btassert.h"
19 #include "../drivers/cswordbiblemoduleinfo.h"
20 
21 // Sword includes:
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic ignored "-Wextra-semi"
24 #pragma GCC diagnostic ignored "-Wsuggest-override"
25 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
26 #ifdef __clang__
27 #pragma clang diagnostic push
28 #pragma clang diagnostic ignored "-Wsuggest-destructor-override"
29 #endif
30 #include <swmodule.h>
31 #ifdef __clang__
32 #pragma clang diagnostic pop
33 #endif
34 #pragma GCC diagnostic pop
35 
36 
38  : CSwordKey(module)
39 {
40  if(CSwordBibleModuleInfo const * bible =
41  dynamic_cast<CSwordBibleModuleInfo const *>(module))
42  {
43  // Copy important settings like versification system
44  m_key.copyFrom(bible->swordModule().getKey());
45  setKey(bible->lowerBound().key());
46  }
47  m_key.setAutoNormalize(true);
48 }
49 
51  : CSwordKey(copy)
52  , m_key(copy.m_key)
53 { m_key.setAutoNormalize(true); }
54 
55 CSwordVerseKey::CSwordVerseKey(sword::VerseKey const * k,
56  CSwordModuleInfo const * module)
57  : CSwordKey(module)
58  , m_key(*k)
59 {}
60 
62 
63 sword::SWKey const & CSwordVerseKey::asSwordKey() const noexcept
64 { return m_key; }
65 
66 /** Clones this object. */
68 { return new CSwordVerseKey(*this); }
69 
70 /** Sets the module for this key */
72  BT_ASSERT(newModule);
73  if (m_module == newModule) return;
74  BT_ASSERT(newModule->type() == CSwordModuleInfo::Bible ||
75  newModule->type() == CSwordModuleInfo::Commentary);
76 
77  CSwordBibleModuleInfo const * bible = static_cast<CSwordBibleModuleInfo const *>(newModule);
78  const char * newVersification =
79  static_cast<sword::VerseKey *>(
80  bible->swordModule().getKey())->getVersificationSystem();
81  bool inVersification = true;
82 
83  if (strcmp(m_key.getVersificationSystem(), newVersification)) {
84  /// Remap key position to new versification
85  sword::VerseKey oldKey(m_key);
86 
87  m_key.setVersificationSystem(newVersification);
88 
89  m_key.positionFrom(oldKey);
90  inVersification = !m_key.popError();
91  }
92 
93  m_module = newModule;
94 
96 
97  if(inVersification) {
98  /// Limit to Bible bounds
99  if (m_key._compare(bible->lowerBound().m_key) < 0) {
100  setKey(bible->lowerBound().m_key);
101  }
102  if (m_key._compare(bible->upperBound().m_key) > 0) {
103  setKey(bible->upperBound().m_key);
104  }
105  }
106 
107  m_valid = inVersification;
108 }
109 
111 { return ((testament() > 1) ? m_key.BMAX[0] : 0) + book(); }
112 
114 { return {&m_key.getLowerBound(), module()}; }
115 
117 { m_key.setLowerBound(bound.m_key); }
118 
120 { return {&m_key.getUpperBound(), module()}; }
121 
123 { m_key.setUpperBound(bound.m_key); }
124 
125 /** Returns the current book as Text, not as integer. */
126 QString CSwordVerseKey::bookName() const {
127  using CSBMI = CSwordBibleModuleInfo;
128  int min = 0;
129  int max = 1;
130 
131  const CSBMI *bible = dynamic_cast<const CSBMI*>(module());
132  if (bible != nullptr) {
133  const bool hasOT = bible->hasOldTestament();
134  const bool hasNT = bible->hasNewTestament();
135 
136  if (hasOT && hasNT) {
137  min = 0;
138  max = 1;
139  }
140  else if (hasOT && !hasNT) {
141  min = 0;
142  max = 0;
143  }
144  else if (!hasOT && hasNT) {
145  min = 1;
146  max = 1;
147  }
148  else if (!hasOT && !hasNT) {
149  min = 0;
150  max = -1; //no loop
151  }
152  }
153 
154  if ((m_key.getTestament() >= min + 1) && (m_key.getTestament() <= max + 1) && (m_key.getBook() <= m_key.BMAX[min])) {
155  return QString::fromUtf8(m_key.getBookName());
156  }
157 
158  //return QString::fromUtf8( books[min][0].name ); //return the first book, i.e. Genesis
159  return QString();
160 }
161 
162 /** Sets the key we use to the parameter. */
163 QString CSwordVerseKey::key() const {
164  return QString::fromUtf8(m_key.isBoundSet()
165  ? m_key.getRangeText()
166  : m_key.getText());
167 }
168 
170  using namespace std::string_view_literals;
171  if (m_key.getLocale() == "en"sv)
172  return key();
173  sword::VerseKey clone(m_key);
174  clone.setLocale("en");
175  return QString::fromUtf8(clone.isBoundSet()
176  ? clone.getRangeText()
177  : clone.getText());
178 }
179 
180 const char * CSwordVerseKey::rawKey() const { return m_key.getText(); }
181 
182 bool CSwordVerseKey::setKey(const QString &newKey) {
183  return setKey(newKey.toUtf8().constData());
184 }
185 
186 bool CSwordVerseKey::setKey(const char *newKey) {
187  if(QByteArray(newKey).contains('-')) {
188  sword::VerseKey vk(newKey, newKey, m_key.getVersificationSystem());
189  m_key.setLowerBound(vk.getLowerBound());
190  m_key.setUpperBound(vk.getUpperBound());
191  m_key.setPosition(sword::TOP);
192  } else {
193  m_key.clearBounds();
194  m_key.positionFrom(newKey);
195  }
196 
197  m_valid = !m_key.popError();
198 
199  emitAfterChanged(); /// \todo Do we ALWAYS need to emit this signal
200 
201  return m_valid;
202 }
203 
204 bool CSwordVerseKey::next( const JumpType type ) {
205  using CSBMI = CSwordBibleModuleInfo;
206 
207  m_key.popError(); //clear Error status
208  bool ret = true;
209 
210  switch (type) {
211 
212  case UseBook: {
213  const int currentTestament = m_key.getTestament();
214  const int currentBook = m_key.getBook();
215 
216  if ((currentTestament == 2) && (currentBook >= m_key.BMAX[currentTestament-1])) { //Revelation, i.e. end of navigation
217  return false;
218  }
219  else if ((currentTestament == 1) && (currentBook >= m_key.BMAX[currentTestament-1])) { //Malachi, switch to the NT
220  m_key.setTestament(currentTestament + 1);
221  m_key.setBook(1);
222  }
223  else {
224  m_key.setBook(m_key.getBook() + 1);
225  }
226  break;
227  }
228 
229  case UseChapter: {
230  m_key.setChapter(m_key.getChapter() + 1);
231  break;
232  }
233 
234  case UseVerse: {
235  if (!m_module) {
236  m_key.setVerse(m_key.getVerse() + 1);
237  } else {
238  auto & m = m_module->swordModule();
239  const bool oldStatus = m.isSkipConsecutiveLinks();
240  m.setSkipConsecutiveLinks(true);
241 
242  auto * vKey = static_cast<sword::VerseKey *>(m.getKey());
243 
244  // disable headings for next verse
245  bool const oldHeadingsStatus = vKey->isIntros();
246  vKey->setIntros(true);
247  //don't use setKey(), that would create a new key without Headings set
248  vKey->setText(key().toUtf8().constData());
249 
250  m++;
251 
252  vKey = static_cast<sword::VerseKey *>(m.getKey());
253  vKey->setIntros(oldHeadingsStatus);
254  m.setSkipConsecutiveLinks(oldStatus);
255 
256  if (!m.popError()) {
257  setKey(QString::fromUtf8(vKey->getText()));
258  } else {
259  // Verse(Verse()+1);
260  //don't change the key, restore the module's position
261  vKey->setText(key().toUtf8().constData());
262  ret = false;
263  break;
264  }
265  }
266 
267  break;
268  }
269 
270  default:
271  return false;
272  }
273 
274  const CSBMI *bible = dynamic_cast<const CSBMI*>(module());
275  if (bible != nullptr) {
276  if (m_key._compare(bible->lowerBound().m_key) < 0 ) {
277  setKey(bible->lowerBound().m_key);
278  ret = false;
279  }
280 
281  if (m_key._compare(bible->upperBound().m_key) > 0 ) {
282  setKey(bible->upperBound().m_key);
283  ret = false;
284  }
285 
287  return ret;
288  }
289  else if (m_key.popError()) { //we have no module, so take care of VerseKey::Error()
290  return false;
291  }
292 
294  return ret;
295 }
296 
297 bool CSwordVerseKey::previous( const JumpType type ) {
298  using CSBMI = CSwordBibleModuleInfo;
299 
300  bool ret = true;
301 
302  switch (type) {
303 
304  case UseBook: {
305  if ((m_key.getBook() == 1) && (m_key.getTestament() == 1)) { //Genesis
306  return false;
307  }
308  else if ((m_key.getBook() == 1) && (m_key.getTestament() == 2)) { //Matthew
309  m_key.setTestament(1);
310  m_key.setBook(m_key.BMAX[0]);
311  }
312  else {
313  m_key.setBook(m_key.getBook() - 1);
314  }
315 
316  break;
317  }
318 
319  case UseChapter: {
320  m_key.setChapter(m_key.getChapter() - 1);
321  break;
322  }
323 
324  case UseVerse: {
325  if (!m_module) {
326  m_key.setVerse(m_key.getVerse() - 1);
327  } else {
328  auto & m = m_module->swordModule();
329  auto * vKey = static_cast<sword::VerseKey *>(m.getKey());
330  bool const oldHeadingsStatus = vKey->isIntros();
331  vKey->setIntros(true);
332  vKey->setText(key().toUtf8().constData());
333 
334  bool const oldStatus = m.isSkipConsecutiveLinks();
335  m.setSkipConsecutiveLinks(true);
336  m--;
337 
338  vKey = static_cast<sword::VerseKey *>(m.getKey());
339  vKey->setIntros(oldHeadingsStatus);
340  m.setSkipConsecutiveLinks(oldStatus);
341 
342  if (!m.popError()) {
343  /// \warning Weird comment:
344  // don't use fromUtf8:
345  setKey(QString::fromUtf8(vKey->getText()));
346  } else {
347  ret = false;
348  // Verse(Verse()-1);
349  // Restore module's key:
350  vKey->setText(key().toUtf8().constData());
351  }
352  }
353 
354  break;
355  }
356 
357  default:
358  return false;
359  }
360 
361  const CSBMI *bible = dynamic_cast<const CSBMI*>(module());
362  if (bible != nullptr) {
363  if (m_key._compare(bible->lowerBound().m_key) < 0 ) {
364  setKey(bible->lowerBound().m_key);
365  ret = false;
366  }
367 
368  if (m_key._compare(bible->upperBound().m_key) > 0 ) {
369  setKey(bible->upperBound().m_key);
370  ret = false;
371  }
372 
374  return ret;
375  }
376  else if (m_key.popError()) {
377  return false;
378  }
379 
381  return ret;
382 }
383 
385  if (m_afterChangedSignaller.isNull())
387 
389 }
390 
391 
393  if (!m_afterChangedSignaller.isNull())
394  m_afterChangedSignaller->emitSignal();
395 }
#define BT_ASSERT(...)
Definition: btassert.h:17
Implementation for Sword Bibles.
CSwordVerseKey const & lowerBound() const
CSwordVerseKey const & upperBound() const
const CSwordModuleInfo * m_module
Definition: cswordkey.h:112
CSwordModuleInfo const * module() const
Definition: cswordkey.h:68
bool m_valid
Definition: cswordkey.h:113
ModuleType type() const
sword::SWModule & swordModule() const
CSwordKey implementation for Sword's VerseKey.
CSwordVerseKey upperBound() const
void setLowerBound(CSwordVerseKey const &bound)
char bibleBook() const
char book() const
~CSwordVerseKey() override
QString bookName() const
bool next(const JumpType type=JumpType::UseVerse)
char testament() const
void setModule(const CSwordModuleInfo *newModule) final override
CSwordVerseKey(const CSwordModuleInfo *module)
bool previous(const JumpType type=JumpType::UseVerse)
QString key() const final override
sword::VerseKey m_key
QPointer< BtSignal > m_afterChangedSignaller
bool setKey(const QString &key) final override
const BtSignal * afterChangedSignaller()
CSwordVerseKey * copy() const final override
const char * rawKey() const final override
QString normalizedKey() const final override
void setUpperBound(CSwordVerseKey const &bound)
sword::SWKey const & asSwordKey() const noexcept final override
CSwordVerseKey lowerBound() const