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, http://www.bibletime.info/.
6 *
7 * Copyright 1999-2016 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 "btwindowinterface.h"
14
15 #include <QDebug>
16 #include <QFile>
17 #include <QObject>
18 #include <QQmlContext>
19 #include <QQmlEngine>
20 #include <QQuickItem>
21 #include <QStringList>
22 #include <swkey.h>
23 #include "backend/config/btconfig.h"
24 #include "backend/drivers/cswordbiblemoduleinfo.h"
25 #include "backend/drivers/cswordbookmoduleinfo.h"
26 #include "backend/drivers/cswordlexiconmoduleinfo.h"
27 #include "backend/drivers/cswordmoduleinfo.h"
28 #include "backend/keys/cswordkey.h"
29 #include "backend/keys/cswordtreekey.h"
30 #include "backend/managers/cswordbackend.h"
31 #include "backend/models/btmoduletextmodel.h"
32 #include "backend/rendering/cdisplayrendering.h"
33 #include "backend/rendering/centrydisplay.h"
34 #include "mobile/btmmain.h"
35 #include "mobile/keychooser/bookkeychooser.h"
36 #include "mobile/keychooser/keynamechooser.h"
37 #include "mobile/keychooser/versechooser.h"
38 #include "mobile/ui/modulechooser.h"
39 #include "mobile/ui/viewmanager.h"
40 #include "util/btconnect.h"
41
42
43 namespace btm {
44
BtWindowInterface(QObject * parent)45 BtWindowInterface::BtWindowInterface(QObject* parent)
46 : QObject(parent),
47 m_key(nullptr),
48 m_textModel(new RoleItemModel()),
49 m_moduleTextModel(new BtModuleTextModel(this)),
50 m_bookKeyChooser(nullptr),
51 m_keyNameChooser(nullptr),
52 m_verseKeyChooser(nullptr),
53 m_historyIndex(-1) {
54
55 ViewManager* viewManager = getViewManager();
56 if (viewManager == nullptr)
57 return;
58 QtQuick2ApplicationViewer* viewer = viewManager->getViewer();
59 m_verseKeyChooser = new VerseChooser(viewer, this);
60
61 BT_CONNECT(m_verseKeyChooser, SIGNAL(referenceChanged()),
62 this, SLOT(referenceChosen()));
63
64 m_bookKeyChooser = new BookKeyChooser(viewer, this);
65 BT_CONNECT(m_bookKeyChooser, SIGNAL(referenceChanged()),
66 this, SLOT(referenceChosen()));
67
68 m_keyNameChooser = new KeyNameChooser(viewer, this);
69 BT_CONNECT(m_keyNameChooser, SIGNAL(referenceChanged(int)),
70 this, SLOT(referenceChosen(int)));
71
72 BT_CONNECT(CSwordBackend::instance(),
73 SIGNAL(sigSwordSetupChanged(CSwordBackend::SetupChangedReason)),
74 this,
75 SLOT(reloadModules(CSwordBackend::SetupChangedReason)));
76 }
77
reloadModules(CSwordBackend::SetupChangedReason)78 void BtWindowInterface::reloadModules(CSwordBackend::SetupChangedReason /* reason */ ) {
79 //first make sure all used Sword modules are still present
80
81 if (CSwordBackend::instance()->findModuleByName(m_moduleName)) {
82 QString moduleName = m_moduleName;
83 m_moduleName = "";
84 setModuleName(moduleName);
85 ;
86 } else {
87 // close window ?
88 }
89 }
90
updateModel()91 void BtWindowInterface::updateModel() {
92 QString moduleName= getModuleName();
93 QStringList moduleList = QStringList() << moduleName;
94 QList<const CSwordModuleInfo*> modules =
95 CSwordBackend::instance()->getConstPointerList(moduleList);
96 }
97
moduleIsBook(const CSwordModuleInfo * module)98 static bool moduleIsBook(const CSwordModuleInfo* module) {
99 CSwordModuleInfo::Category category = module->category();
100 if (category == CSwordModuleInfo::Books)
101 return true;
102 return false;
103 }
104
moduleIsLexicon(const CSwordModuleInfo * module)105 static bool moduleIsLexicon(const CSwordModuleInfo* module) {
106 CSwordModuleInfo::Category category = module->category();
107 if (category == CSwordModuleInfo::Lexicons ||
108 category == CSwordModuleInfo::DailyDevotional)
109 return true;
110 return false;
111 }
112
moduleIsBibleOrCommentary(const CSwordModuleInfo * module)113 static bool moduleIsBibleOrCommentary(const CSwordModuleInfo* module) {
114 CSwordModuleInfo::Category category = module->category();
115 if (category == CSwordModuleInfo::Bibles ||
116 category == CSwordModuleInfo::Cult ||
117 category == CSwordModuleInfo::Commentaries)
118 return true;
119 return false;
120 }
121
getCurrentModelIndex() const122 int BtWindowInterface::getCurrentModelIndex() const {
123 if (m_key == nullptr)
124 return 0;
125 if (moduleIsBibleOrCommentary(module())) {
126 CSwordVerseKey* verseKey = dynamic_cast<CSwordVerseKey*>(m_key);
127 int index = m_moduleTextModel->verseKeyToIndex(*verseKey);
128 return index;
129 }
130 else if (moduleIsBook(module())) {
131 const CSwordBookModuleInfo *m = qobject_cast<const CSwordBookModuleInfo*>(module());
132 CSwordTreeKey key(m->tree(), m);
133 QString keyName = m_key->key();
134 key.setKey(keyName);
135 CSwordTreeKey p(key);
136 p.root();
137 if(p != key)
138 return key.getIndex()/4;
139 }
140 else if (moduleIsLexicon(module())){ const CSwordLexiconModuleInfo *li = qobject_cast<const CSwordLexiconModuleInfo*>(m_key->module());
141 int index = li->entries().indexOf(m_key->key());
142 return index;
143 }
144 return 0;
145 }
146
getModuleLanguage() const147 QString BtWindowInterface::getModuleLanguage() const {
148 QString language;
149 if (m_key)
150 language = m_key->module()->language()->englishName();
151 return language;
152 }
153
getModuleName() const154 QString BtWindowInterface::getModuleName() const {
155 QString moduleName;
156 if (m_key)
157 moduleName = m_key->module()->name();
158 return moduleName;
159 }
160
setReference(const QString & key)161 void BtWindowInterface::setReference(const QString& key) {
162 if (m_key && m_key->key() == key)
163 return;
164 if (m_key) {
165 CSwordVerseKey* verseKey = dynamic_cast<CSwordVerseKey*>(m_key);
166 if (verseKey)
167 verseKey->setIntros(true);
168 m_key->setKey(key);
169 referenceChanged();
170 }
171 }
172
moduleNameChanged(const QString & moduleName)173 void BtWindowInterface::moduleNameChanged(const QString& moduleName)
174 {
175 setModuleName(moduleName);
176 setHistoryPoint();
177 }
178
setModuleToBeginning()179 void BtWindowInterface::setModuleToBeginning() {
180 if (moduleIsBibleOrCommentary(m_key->module())) {
181 CSwordVerseKey* verseKey = dynamic_cast<CSwordVerseKey*>(m_key);
182 verseKey->setPosition(sword::TOP);
183 emit referenceChange();
184 }
185 }
186
setModuleName(const QString & moduleName)187 void BtWindowInterface::setModuleName(const QString& moduleName) {
188 if (m_key && m_moduleName == moduleName)
189 return;
190 if (moduleName.isEmpty())
191 return;
192 m_moduleName = moduleName;
193 CSwordModuleInfo* m = CSwordBackend::instance()->findModuleByName(moduleName);
194 if (!m_key) {
195 m_key = CSwordKey::createInstance(m);
196 }
197 else {
198 if (moduleIsBibleOrCommentary(m) &&
199 moduleIsBibleOrCommentary(m_key->module())) {
200 m_key->setModule(m);
201 }
202 else if (moduleIsBook(m) &&
203 moduleIsBook(m_key->module())) {
204 m_key->setModule(m);
205 }
206
207 else {
208 delete m_key;
209 m_key = CSwordKey::createInstance(m);
210 }
211
212 }
213
214 CSwordTreeKey* treeKey = dynamic_cast<CSwordTreeKey*>(m_key);
215 if (treeKey)
216 treeKey->firstChild();
217
218 QStringList moduleNames;
219 moduleNames.append(moduleName);
220 m_moduleTextModel->setModules(moduleNames);
221
222 emit moduleChanged();
223 emit referenceChange();
224 updateModel();
225 }
226
getReference() const227 QString BtWindowInterface::getReference() const {
228 QString reference;
229 if (m_key)
230 reference = m_key->key();
231 return reference;
232 }
233
changeModule()234 void BtWindowInterface::changeModule() {
235 QtQuick2ApplicationViewer* viewer = getViewManager()->getViewer();
236 ModuleChooser* dlg = new ModuleChooser(viewer, this);
237 dlg->open();
238 }
239
updateCurrentModelIndex()240 void BtWindowInterface::updateCurrentModelIndex() {
241 emit currentModelIndexChanged();
242 }
243
updateTextFonts()244 void BtWindowInterface::updateTextFonts() {
245 emit textChanged();
246 }
247
parseKey(CSwordTreeKey * currentKey,QStringList * keyPath,QStringList * children)248 static void parseKey(CSwordTreeKey* currentKey, QStringList* keyPath, QStringList* children)
249 {
250 if (currentKey == nullptr)
251 return;
252
253 CSwordTreeKey localKey(*currentKey);
254
255 QString oldKey = localKey.key(); //string backup of key
256
257 if (oldKey.isEmpty()) { //don't set keys equal to "/", always use a key which may have content
258 localKey.firstChild();
259 oldKey = localKey.key();
260 }
261
262 QStringList siblings; //split up key
263 if (!oldKey.isEmpty()) {
264 siblings = oldKey.split('/', QString::SkipEmptyParts);
265 }
266
267 int depth = 0;
268 int index = 0;
269 localKey.root(); //start iteration at root node
270
271 while ( localKey.firstChild() && (depth < siblings.count()) ) {
272 QString key = localKey.key();
273 index = (depth == 0) ? -1 : 0;
274
275 bool found = false;
276 do { //look for matching sibling
277 ++index;
278 found = (localKey.getLocalNameUnicode() == siblings[depth]);
279 }
280 while (!found && localKey.nextSibling());
281
282 if (found)
283 key = localKey.key(); //found: change key to this level
284 else
285 localKey.setKey(key); //not found: restore old key
286
287 *keyPath << key;
288
289 //last iteration: get child entries
290 if (depth == siblings.count() - 1 && localKey.hasChildren()) {
291 localKey.firstChild();
292 ++depth;
293 do {
294 *children << localKey.getLocalNameUnicode();
295 }
296 while (localKey.nextSibling());
297 }
298 depth++;
299 }
300 }
301
getEnglishKey(CSwordKey * m_key)302 static QString getEnglishKey(CSwordKey* m_key) {
303 sword::VerseKey * vk = dynamic_cast<sword::VerseKey*>(m_key);
304 QString oldLang;
305 if (vk) {
306 // Save keys in english only:
307 const QString oldLang = QString::fromLatin1(vk->getLocale());
308 vk->setLocale("en");
309 QString englishKey = m_key->key();
310 vk->setLocale(oldLang.toLatin1());
311 return englishKey;
312 } else {
313 return m_key->key();
314 }
315 }
316
saveWindowStateToConfig(int windowIndex)317 void BtWindowInterface::saveWindowStateToConfig(int windowIndex) {
318 const QString windowKey = QString::number(windowIndex);
319 const QString windowGroup = "window/" + windowKey + '/';
320
321 BtConfig & conf = btConfig();
322 conf.beginGroup(windowGroup);
323 conf.setSessionValue("key", getEnglishKey(m_key));
324 QStringList modules;
325 QString moduleName = getModuleName();
326 modules.append(moduleName);
327 conf.setSessionValue("modules", modules);
328 conf.endGroup();
329 }
330
changeReference()331 void BtWindowInterface::changeReference() {
332 CSwordVerseKey* verseKey = dynamic_cast<CSwordVerseKey*>(m_key);
333 if (verseKey != nullptr) {
334 m_verseKeyChooser->open(verseKey);
335 }
336
337 CSwordTreeKey* treeKey = dynamic_cast<CSwordTreeKey*>(m_key);
338 if (treeKey != nullptr) {
339 QStringList keyPath;
340 QStringList children;
341 parseKey(treeKey, &keyPath, &children);
342 m_bookKeyChooser->open();
343 }
344 CSwordLDKey* lexiconKey = dynamic_cast<CSwordLDKey*>(m_key);
345 if (lexiconKey != nullptr) {
346 m_keyNameChooser->open(m_moduleTextModel);
347 }
348 }
349
referenceChanged()350 void BtWindowInterface::referenceChanged() {
351 emit referenceChange();
352 }
353
referenceChosen()354 void BtWindowInterface::referenceChosen() {
355 emit referenceChange();
356 updateModel();
357 emit currentModelIndexChanged();
358 setHistoryPoint();
359 }
360
referenceChosen(int index)361 void BtWindowInterface::referenceChosen(int index) {
362 updateKeyText(index);
363 QString keyName = m_moduleTextModel->indexToKeyName(index);
364 m_key->setKey(keyName);
365 setReference(keyName);
366 emit currentModelIndexChanged();
367 setHistoryPoint();
368 }
369
module() const370 const CSwordModuleInfo* BtWindowInterface::module() const {
371 const CSwordModuleInfo* module = m_key->module();
372 return module;
373 }
374
getKey() const375 CSwordKey* BtWindowInterface::getKey() const {
376 return m_key;
377 }
378
getFontName() const379 QString BtWindowInterface::getFontName() const {
380 const CSwordModuleInfo* m = module();
381 if (m == nullptr)
382 return QString();
383 const CLanguageMgr::Language* lang = m->language();
384 if (lang == nullptr)
385 return QString();
386 BtConfig::FontSettingsPair fontPair = btConfig().getFontForLanguage(*lang);
387 if (fontPair.first) {
388 QFont font = fontPair.second;
389 QString fontName = font.family();
390 return fontName;
391 }
392 QFont font = getDefaultFont();
393 QString fontName = font.family();
394 return fontName;
395 }
396
getFontSize() const397 int BtWindowInterface::getFontSize() const {
398 const CLanguageMgr::Language* lang = module()->language();
399 BtConfig::FontSettingsPair fontPair = btConfig().getFontForLanguage(*lang);
400 if (fontPair.first) {
401 QFont font = fontPair.second;
402 int fontPointSize = font.pointSize();
403 return fontPointSize;
404 }
405 int fontPointSize = btConfig().value<int>("ui/textFontSize",22);
406 return fontPointSize;
407 }
408
setFontSize(int size)409 void BtWindowInterface::setFontSize(int size) {
410 const CLanguageMgr::Language* lang = module()->language();
411 BtConfig::FontSettingsPair fontPair = btConfig().getFontForLanguage(*lang);
412 fontPair.second.setPointSize(size);
413 btConfig().setFontForLanguage(*lang, fontPair);
414 emit textChanged();
415 }
416
getTextModel()417 QVariant BtWindowInterface::getTextModel() {
418 QVariant var;
419 var.setValue(m_moduleTextModel);
420 return var;
421 }
422
updateKeyText(int index)423 void BtWindowInterface::updateKeyText(int index) {
424 QString keyName = m_moduleTextModel->indexToKeyName(index);
425 setReference(keyName);
426 }
427
getHighlightWords() const428 QString BtWindowInterface::getHighlightWords() const {
429 return m_highlightWords;
430 }
431
setHighlightWords(const QString & words)432 void BtWindowInterface::setHighlightWords(const QString& words) {
433 m_highlightWords = words;
434 m_moduleTextModel->setHighlightWords(words);
435 }
436
setHistoryPoint()437 void BtWindowInterface::setHistoryPoint() {
438 History history;
439 while ( m_history.count()>0 && (m_historyIndex<m_history.count()-1) )
440 m_history.pop_back();
441 history.moduleName = getModuleName();
442 history.reference = getReference();
443 m_history.append(history);
444 m_historyIndex = m_history.count() - 1;
445 emit historyChanged();
446 }
447
getHistoryForwardVisible() const448 bool BtWindowInterface::getHistoryForwardVisible() const {
449 return m_historyIndex < (m_history.count() - 1);
450 }
451
getHistoryBackwardVisible() const452 bool BtWindowInterface::getHistoryBackwardVisible() const {
453 return (m_historyIndex > 0) && (m_history.count() > 1);
454 }
455
moveHistoryBackward()456 void BtWindowInterface::moveHistoryBackward() {
457 if ( ! getHistoryBackwardVisible())
458 return;
459 m_historyIndex--;
460 History history = m_history.at(m_historyIndex);
461 setModuleName(history.moduleName);
462 setReference(history.reference);
463 emit currentModelIndexChanged();
464 emit historyChanged();
465 }
466
moveHistoryForward()467 void BtWindowInterface::moveHistoryForward() {
468 if ( ! getHistoryForwardVisible())
469 return;
470 m_historyIndex++;
471 History history = m_history.at(m_historyIndex);
472 setModuleName(history.moduleName);
473 setReference(history.reference);
474 emit currentModelIndexChanged();
475 emit historyChanged();
476 }
477
478 } // end namespace
479