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 "moduleinterface.h"
14 
15 #include "qtquick2applicationviewer.h"
16 
17 #include "backend/config/btconfig.h"
18 #include "backend/bookshelfmodel/btbookshelftreemodel.h"
19 #include "backend/managers/cswordbackend.h"
20 #include "backend/keys/cswordversekey.h"
21 #include "mobile/util/findqmlobject.h"
22 #include "mobile/btmmain.h"
23 #include <cmath>
24 #include <QQuickItem>
25 #include <QQmlProperty>
26 #include <QQmlContext>
27 #include <QDebug>
28 #include <QQmlProperty>
29 #include <QCoreApplication>
30 #include "btwindowinterface.h"
31 #include "gridchooser.h"
32 
33 namespace btm {
34 
35 struct FontSettings {
36     QString language;
37     QString fontName;
38     qreal fontSize;
39 };
40 
41 static QList<FontSettings> savedFontSettings;
42 
ModuleInterface()43 ModuleInterface::ModuleInterface() {
44 }
45 
46 enum TextRoles {
47     TextRole = Qt::UserRole + 1
48 };
49 
50 using MRole = BtBookshelfModel::ModuleRole;
51 static const MRole HR(BtBookshelfModel::ModuleHiddenRole);
52 static const MRole PR(BtBookshelfModel::ModulePointerRole);
53 static const MRole IR(BtBookshelfModel::ModuleHasIndexRole);
54 static const MRole CR(BtBookshelfModel::ModuleCategoryRole);
55 
setupTextModel(const QSet<QString> & modelSet,RoleItemModel * model)56 static void setupTextModel(const QSet<QString>& modelSet, RoleItemModel* model) {
57 
58     QHash<int, QByteArray> roleNames;
59     roleNames[TextRole] =  "modelText";
60     model->setRoleNames(roleNames);
61 
62     QStringList modelList = modelSet.toList();
63     modelList.sort();
64 
65     model->clear();
66     for (int i=0; i< modelList.count(); ++i) {
67         QString source = modelList.at(i);
68         QStandardItem* item = new QStandardItem();
69         item->setData(source, TextRole);
70         model->appendRow(item);
71     }
72 }
73 
getModule(BtBookshelfModel * bookshelfModel,const QModelIndex & index)74 static CSwordModuleInfo* getModule(BtBookshelfModel* bookshelfModel, const QModelIndex& index) {
75     QVariant var = bookshelfModel->data(index, PR);
76     CSwordModuleInfo* module = static_cast<CSwordModuleInfo*>(var.value<void*>());
77     return module;
78 }
79 
updateCategoryAndLanguageModels()80 void ModuleInterface::updateCategoryAndLanguageModels() {
81     QQuickItem* object = findQmlObject("moduleChooser");
82     if (object == nullptr)
83         return;
84 
85     getCategoriesAndLanguages();
86     setupTextModel(m_categories, &m_categoryModel);
87     setupTextModel(m_languages, &m_languageModel);
88     updateWorksModel();
89     object->setProperty("categoryModel", QVariant::fromValue(&m_categoryModel));
90     object->setProperty("languageModel", QVariant::fromValue(&m_languageModel));
91 }
92 
getCategoriesAndLanguages()93 void ModuleInterface::getCategoriesAndLanguages() {
94 
95     m_categories.clear();
96     m_languages.clear();
97 
98     QQuickItem* object = findQmlObject("moduleChooser");
99     if (object == nullptr)
100         return;
101 
102     BtBookshelfModel* bookshelfModel = CSwordBackend::instance()->model();
103     if (bookshelfModel == nullptr)
104         return;
105     int count = bookshelfModel->rowCount();
106     for (int row=0; row<count; ++row) {
107         QModelIndex index = bookshelfModel->index(row);
108         CSwordModuleInfo* module = getModule(bookshelfModel, index);
109         CSwordModuleInfo::Category category = module->category();
110         QString categoryName = module->categoryName(category);
111         const CLanguageMgr::Language* language = module->language();
112         QString languageName = language->translatedName();
113         m_categories.insert(categoryName);
114         m_languages.insert(languageName);
115     }
116 }
117 
installedModuleLanguages()118 QStringList ModuleInterface::installedModuleLanguages() {
119     QStringList languages;
120     CLanguageMgr::LangMap langMap = CLanguageMgr::instance()->availableLanguages();
121     for (auto lang: langMap) {
122         languages << lang->englishName();
123     }
124     return languages;
125 }
126 
127 
updateWorksModel()128 void ModuleInterface::updateWorksModel() {
129     m_worksModel.clear();
130     m_modules.clear();
131 
132     QString currentLang = currentLanguage();
133     QString currentCat = currentCategory();
134 
135     QHash<int, QByteArray> roleNames;
136     roleNames[TextRole] =  "modelText";
137     m_worksModel.setRoleNames(roleNames);
138 
139     BtBookshelfModel* bookshelfModel = CSwordBackend::instance()->model();
140     if (bookshelfModel == nullptr)
141         return;
142     int count = bookshelfModel->rowCount();
143     for (int row=0; row<count; ++row) {
144         QModelIndex index = bookshelfModel->index(row);
145         CSwordModuleInfo* module = getModule(bookshelfModel, index);
146         CSwordModuleInfo::Category category = module->category();
147         QString categoryName = module->categoryName(category);
148         const CLanguageMgr::Language* language = module->language();
149         QString languageName = language->translatedName();
150         if (languageName == currentLang &&
151                 categoryName == currentCat) {
152             m_modules << module;
153             QString moduleName = module->name();
154             QStandardItem* item = new QStandardItem();
155             item->setData(moduleName, TextRole);
156             m_worksModel.appendRow(item);
157         }
158     }
159 
160     QQuickItem* object = findQmlObject("moduleChooser");
161     if (object == nullptr)
162         return;
163     object->setProperty("worksModel", QVariant::fromValue(&m_worksModel));
164 }
165 
currentLanguage() const166 QString ModuleInterface::currentLanguage() const {
167     QQuickItem* object = findQmlObject("moduleChooser");
168     if (object == nullptr)
169         return "";
170     int row = object->property("languageIndex").toInt();
171     QModelIndex modelIndex = m_languageModel.index(row,0);
172     QString language = modelIndex.data(TextRole).toString();
173     return language;
174 
175 }
176 
currentCategory() const177 QString ModuleInterface::currentCategory() const {
178     QQuickItem* object = findQmlObject("moduleChooser");
179     if (object == nullptr)
180         return "";
181     int row = object->property("categoryIndex").toInt();
182     QModelIndex modelIndex = m_categoryModel.index(row,0);
183     QString category = modelIndex.data(TextRole).toString();
184     return category;
185 }
186 
category(int index)187 QString ModuleInterface::category(int index) {
188     if (index < 0 || index >= m_modules.count())
189         return "";
190     CSwordModuleInfo* module = m_modules.at(index);
191     if (module == nullptr)
192         return "";
193     CSwordModuleInfo::Category category = module->category();
194     if (category == 0)
195         return "";
196     return module->categoryName(category);
197 }
198 
englishCategory(int index)199 QString ModuleInterface::englishCategory(int index) {
200     if (index < 0 || index >= m_modules.count())
201         return "";
202     CSwordModuleInfo* module = m_modules.at(index);
203     if (module == nullptr)
204         return "";
205     CSwordModuleInfo::Category category = module->category();
206     if (category == 0)
207         return "";
208     return module->englishCategoryName(category);
209 }
210 
language(int index)211 QString ModuleInterface::language(int index) {
212     if (index < 0 || index >= m_modules.count())
213         return "";
214     CSwordModuleInfo* module = m_modules.at(index);
215     if (module == nullptr)
216         return "";
217     const CLanguageMgr::Language* language = module->language();
218     if (language == nullptr)
219         return "";
220     return language->translatedName();
221 }
222 
module(int index)223 QString ModuleInterface::module(int index) {
224     if (index < 0 || index >= m_modules.count())
225         return "";
226     CSwordModuleInfo* module = m_modules.at(index);
227     if (module == nullptr)
228         return "";
229     return module->name();
230 }
231 
isLocked(const QString & moduleName)232 bool ModuleInterface::isLocked(const QString& moduleName) {
233     CSwordModuleInfo* module = CSwordBackend::instance()->findModuleByName(moduleName);
234     if (module) {
235 
236         // Verse intros must be false for checking lock
237         if (module->type() == CSwordModuleInfo::Bible ||
238                 module->type() == CSwordModuleInfo::Commentary) {
239                 ((sword::VerseKey*)(module->module().getKey()))->setIntros(false);
240         }
241 
242         bool locked = module->isLocked();
243         return locked;
244     }
245     return false;
246 }
247 
unlock(const QString & moduleName,const QString & unlockKey)248 void ModuleInterface::unlock(const QString& moduleName, const QString& unlockKey) {
249     CSwordModuleInfo* module = CSwordBackend::instance()->findModuleByName(moduleName);
250     if (module) {
251         module->unlock(unlockKey);
252 
253         // Re-initialize module pointers:
254         CSwordBackend *backend = CSwordBackend::instance();
255         backend->reloadModules(CSwordBackend::OtherChange);
256         module = CSwordBackend::instance()->findModuleByName(moduleName);
257         updateWorksModel();
258     }
259 }
260 
getLanguageFromEnglishName(const QString & name)261 static const CLanguageMgr::Language* getLanguageFromEnglishName(const QString& name) {
262     CLanguageMgr::LangMap langMap = CLanguageMgr::instance()->availableLanguages();
263     for (auto l: langMap) {
264         if (l->englishName() == name)
265             return l;
266     }
267     return nullptr;
268  }
269 
getFontNameForLanguage(const QString & language)270 QString ModuleInterface::getFontNameForLanguage(const QString& language)
271 {
272     auto lang = getLanguageFromEnglishName(language);
273     if (lang) {
274         BtConfig::FontSettingsPair fontPair = btConfig().getFontForLanguage(*lang);
275         if (fontPair.first) {
276             QFont font = fontPair.second;
277             QString fontFamily = font.family();
278             return fontFamily;
279         }
280     }
281     QString fontFamily = getDefaultFont().family();
282     return fontFamily;
283 }
284 
getFontSizeForLanguage(const QString & language)285 qreal ModuleInterface::getFontSizeForLanguage(const QString& language)
286 {
287     auto lang = getLanguageFromEnglishName(language);
288     if (lang) {
289         BtConfig::FontSettingsPair fontPair = btConfig().getFontForLanguage(*lang);
290         if (fontPair.first) {
291             QFont font = fontPair.second;
292             int fontPointSize = font.pointSize();
293             return fontPointSize;
294         }
295     }
296     qreal pointSize = getDefaultFont().pointSizeF();
297     return pointSize;
298 }
299 
setFontForLanguage(const QString & language,const QString & fontName,qreal fontSize)300 void ModuleInterface::setFontForLanguage(const QString& language, const QString& fontName, qreal fontSize) {
301     if (CLanguageMgr::instance() == nullptr)
302         return;
303     auto lang = getLanguageFromEnglishName(language);
304     if (lang) {
305 
306         QFont font;
307         font.setFamily(fontName);
308         font.setPointSizeF(fontSize);
309         BtConfig::FontSettingsPair fontPair;
310         fontPair.first = true;
311         fontPair.second = font;
312         btConfig().setFontForLanguage(*lang, fontPair);
313     }
314 }
315 
saveCurrentFonts()316 void ModuleInterface::saveCurrentFonts() {
317     savedFontSettings.clear();
318     CLanguageMgr::LangMap langMap = CLanguageMgr::instance()->availableLanguages();
319     for (auto lang: langMap) {
320         BtConfig::FontSettingsPair fontPair = btConfig().getFontForLanguage(*lang);
321         if (fontPair.first) {
322             FontSettings fontSettings;
323             QFont font = fontPair.second;
324             fontSettings.language = lang->englishName();
325             fontSettings.fontName = font.family();
326             fontSettings.fontSize = font.pointSize();
327             savedFontSettings.append(fontSettings);
328         }
329     }
330 }
331 
restoreSavedFonts()332 void ModuleInterface::restoreSavedFonts() {
333     for (auto fontSettings : savedFontSettings) {
334         setFontForLanguage(fontSettings.language, fontSettings.fontName, fontSettings.fontSize);
335     }
336 }
337 
338 } // end namespace
339