diff options
Diffstat (limited to 'src/backend/managers')
-rw-r--r-- | src/backend/managers/btstringmgr.cpp | 139 | ||||
-rw-r--r-- | src/backend/managers/btstringmgr.h | 53 | ||||
-rw-r--r-- | src/backend/managers/cdisplaytemplatemgr.cpp | 170 | ||||
-rw-r--r-- | src/backend/managers/cdisplaytemplatemgr.h | 91 | ||||
-rw-r--r-- | src/backend/managers/clanguagemgr.cpp | 546 | ||||
-rw-r--r-- | src/backend/managers/clanguagemgr.h | 151 | ||||
-rw-r--r-- | src/backend/managers/creferencemanager.cpp | 422 | ||||
-rw-r--r-- | src/backend/managers/creferencemanager.h | 110 | ||||
-rw-r--r-- | src/backend/managers/cswordbackend.cpp | 555 | ||||
-rw-r--r-- | src/backend/managers/cswordbackend.h | 273 |
10 files changed, 2510 insertions, 0 deletions
diff --git a/src/backend/managers/btstringmgr.cpp b/src/backend/managers/btstringmgr.cpp new file mode 100644 index 0000000..9f57258 --- /dev/null +++ b/src/backend/managers/btstringmgr.cpp @@ -0,0 +1,139 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "btstringmgr.h" + +char* BTStringMgr::upperUTF8(char* text, unsigned int maxlen) const { + const int max = (maxlen>0) ? maxlen : strlen(text); + + if (isUtf8(text)) { + strncpy(text, (const char*)QString::fromUtf8(text).toUpper().toUtf8(), max); + + return text; + } + else { + char* ret = text; + + while (*text) { + *text = toupper(*text); + text++; + } + + return ret; + } + + return text; +} + +char* BTStringMgr::upperLatin1(char* text, unsigned int /*max*/) const { + char* ret = text; + + while (*text) { + *text = toupper(*text); + text++; + } + + return ret; +} + +bool BTStringMgr::supportsUnicode() const { + return true; +} + +bool BTStringMgr::isUtf8(const char *buf) const { + int i, n; + register unsigned char c; + bool gotone = false; + + #define F 0 /* character never appears in text */ + #define T 1 /* character appears in plain ASCII text */ + #define I 2 /* character appears in ISO-8859 text */ + #define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */ + + static const unsigned char text_chars[256] = { + /* BEL BS HT LF FF CR */ + F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */ + /* ESC */ + F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */ + T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */ + /* NEL */ + X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */ + X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */ + I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */ + }; + + /* *ulen = 0; */ + + for (i = 0; (c = buf[i]); i++) { + if ((c & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */ + /* + * Even if the whole file is valid UTF-8 sequences, + * still reject it if it uses weird control characters. + */ + + if (text_chars[c] != T) + return false; + + } + else if ((c & 0x40) == 0) { /* 10xxxxxx never 1st byte */ + return false; + } + else { /* 11xxxxxx begins UTF-8 */ + int following; + + if ((c & 0x20) == 0) { /* 110xxxxx */ + following = 1; + } + else if ((c & 0x10) == 0) { /* 1110xxxx */ + following = 2; + } + else if ((c & 0x08) == 0) { /* 11110xxx */ + following = 3; + } + else if ((c & 0x04) == 0) { /* 111110xx */ + following = 4; + } + else if ((c & 0x02) == 0) { /* 1111110x */ + following = 5; + } + else + return false; + + for (n = 0; n < following; n++) { + i++; + + if (!(c = buf[i])) + goto done; + + if ((c & 0x80) == 0 || (c & 0x40)) + return false; + } + + gotone = true; + } + } + +done: + return gotone; /* don't claim it's UTF-8 if it's all 7-bit */ +} + +#undef F +#undef T +#undef I +#undef X diff --git a/src/backend/managers/btstringmgr.h b/src/backend/managers/btstringmgr.h new file mode 100644 index 0000000..d202c7f --- /dev/null +++ b/src/backend/managers/btstringmgr.h @@ -0,0 +1,53 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef BTSTRINGMGR_H +#define BTSTRINGMGR_H + +//Sword includes +#include <stringmgr.h> + +//Qt includes +#include <QString> + +/** Unicode string manager implementation. + * This is the StringManager implementation which works with QString. + * @author The BibleTime developers + */ + +class BTStringMgr : public sword::StringMgr { + +public: + /** Converts the param to an upper case Utf8 string + * @param The text encoded in utf8 which should be turned into an upper case string + */ + virtual char *upperUTF8(char *text, unsigned int max = 0) const; + + /** Converts the param to an uppercase latin1 string + * @param The text encoded in latin1 which should be turned into an upper case string + */ + virtual char *upperLatin1(char *text, unsigned int max = 0) const; + +protected: + /** Enable Unicode support. + * Reimplementation to show unicode support. + */ + virtual bool supportsUnicode() const; + + /** CODE TAKEN FROM KDELIBS 3.2, which is licensed under the LGPL 2. + * + * This code was taken from KStringHandler, which is part of the KDE libraries. + * + * This function checks whether a string is utf8 or not. + * It was taken from kdelibs so we do not depend on KDE 3.2. + */ + bool isUtf8(const char *buf) const; +}; + +#endif diff --git a/src/backend/managers/cdisplaytemplatemgr.cpp b/src/backend/managers/cdisplaytemplatemgr.cpp new file mode 100644 index 0000000..6ddd6b7 --- /dev/null +++ b/src/backend/managers/cdisplaytemplatemgr.cpp @@ -0,0 +1,170 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "cdisplaytemplatemgr.h" + +#include "backend/drivers/cswordmoduleinfo.h" +#include "backend/managers/clanguagemgr.h" +#include "backend/config/cbtconfig.h" +#include "util/cpointers.h" +#include "util/directoryutil.h" + +//Qt +#include <QStringList> +#include <QFile> +#include <QFileInfo> +#include <QTextStream> +#include <QDebug> + +CDisplayTemplateMgr::CDisplayTemplateMgr() { + loadTemplates(); +} + +CDisplayTemplateMgr::~CDisplayTemplateMgr() { +} + +const QString CDisplayTemplateMgr::fillTemplate( const QString& name, const QString& content, Settings& settings ) +{ + qDebug() << "CDisplayTemplateMgr::fillTemplate"; + + const QString templateName = m_templateMap.contains(name) ? name : defaultTemplate(); + + QString displayTypeString; + + if (!settings.pageCSS_ID.isEmpty()) { + displayTypeString = settings.pageCSS_ID; + } + else { + if (settings.modules.count()) { + switch (settings.modules.first()->type()) { + + case CSwordModuleInfo::Bible: + displayTypeString = "bible"; + break; + + case CSwordModuleInfo::GenericBook: + displayTypeString = "book"; + break; + + case CSwordModuleInfo::Commentary: + case CSwordModuleInfo::Lexicon: + default: + displayTypeString = "singleentry"; + break; + }; + } + else { //use bible as default type if no modules are set + displayTypeString = "bible"; + }; + } + + QString newContent = content; + const int moduleCount = settings.modules.count(); + + if (moduleCount >= 2) { + //create header for the modules + qDebug("There were more than 1 module, create headers"); + QString header; + + QList<CSwordModuleInfo*>::iterator end_it = settings.modules.end(); + + for (QList<CSwordModuleInfo*>::iterator it(settings.modules.begin()); it != end_it; ++it) { + header.append("<th style=\"width:") + .append(QString::number(int( 100.0 / (float)moduleCount ))) + .append("%;\">") + .append((*it)->name()) + .append("</th>"); + } + + newContent = QString("<table><tr>") + .append(header) + .append("</tr>") + .append(content) + .append("</table>"); + } + + QString langCSS; + CLanguageMgr::LangMap langMap = CPointers::languageMgr()->availableLanguages(); + + qDebug() << "langMap length:" << langMap.count(); + qDebug("loop through langMap"); + foreach(const CLanguageMgr::Language* lang, langMap) { + //const CLanguageMgr::Language* lang = *it; + //qDebug() << "foreach, lang: "; + //qDebug() << lang; + + //if (lang->isValid() && CBTConfig::get(lang).first) { + if (!lang->abbrev().isEmpty() && CBTConfig::get(lang).first) { + const QFont f = CBTConfig::get(lang).second; + + //don't use important, because it would reset the title formatting, etc. to the setup font + QString css("{ "); + css.append("font-family:").append(f.family())/*.append(" !important")*/; + css.append("; font-size:").append(QString::number(f.pointSize())).append("pt /*!important*/"); + css.append("; font-weight:").append(f.bold() ? "bold" : "normal /*!important*/"); + css.append("; font-style:").append(f.italic() ? "italic" : "normal /*!important*/"); + css.append("; }\n"); + + langCSS += + QString("\n*[lang=%1] %2") + .arg(lang->abbrev()) + .arg(css); + } + } + + //at first append the font standard settings for all languages without configured font + // Create a dummy language (the langmap may be empty) + CLanguageMgr::Language lang_v(QString("en"), QString("English"), QString()); + CLanguageMgr::Language* lang = &lang_v; + + if (lang && !lang->abbrev().isEmpty()/*&& lang->isValid()*/) { + const QFont standardFont = CBTConfig::getDefault(lang); //we just need a dummy lang param + langCSS.prepend( + QString("\n#content {font-family:%1; font-size:%2pt; font-weight:%3; font-style: %4;}\n") + .arg(standardFont.family()) + .arg(standardFont.pointSize()) + .arg(standardFont.bold() ? "bold" : "normal") + .arg(standardFont.italic() ? "italic" : "normal") + ); + } + +// qWarning("Outputing unformated text"); + const QString t = QString(m_templateMap[ templateName ]) //don't change the map's content directly, use a copy + .replace("#TITLE#", settings.title) + .replace("#LANG_ABBREV#", settings.langAbbrev.isEmpty() ? QString("en") : settings.langAbbrev) + .replace("#DISPLAYTYPE#", displayTypeString) + .replace("#LANG_CSS#", langCSS) + .replace("#PAGE_DIRECTION#", settings.pageDirection) + .replace("#CONTENT#", newContent); + + return t; +} + +void CDisplayTemplateMgr::loadTemplates() { + QStringList files; + foreach (QString file, util::filesystem::DirectoryUtil::getDisplayTemplatesDir().entryList(QStringList("*.tmpl"))) + { + files += util::filesystem::DirectoryUtil::getDisplayTemplatesDir().canonicalPath() + "/" + file; + } + foreach (QString file, util::filesystem::DirectoryUtil::getUserDisplayTemplatesDir().entryList(QStringList("*.tmpl"))) + { + files += util::filesystem::DirectoryUtil::getUserDisplayTemplatesDir().canonicalPath() + "/" + file; + } + + foreach (QString file, files) { + QFile f(file); + if (f.exists() && f.open( QIODevice::ReadOnly )) { + QString fileContent = QTextStream( &f ).readAll(); + + if (!fileContent.isEmpty()) { + m_templateMap[ QFileInfo(file).fileName() ] = fileContent; + } + } + } +} diff --git a/src/backend/managers/cdisplaytemplatemgr.h b/src/backend/managers/cdisplaytemplatemgr.h new file mode 100644 index 0000000..c791e16 --- /dev/null +++ b/src/backend/managers/cdisplaytemplatemgr.h @@ -0,0 +1,91 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CDISPLAYTEMPLATEMGR_H +#define CDISPLAYTEMPLATEMGR_H + +//BibleTime include +class CSwordModuleInfo; + +//Qt includes +#include <QMap> +#include <QString> +#include <QStringList> + +/** + * Manages the display templates used in the filters and display classes. + * @author The BibleTime team +*/ + +class CDisplayTemplateMgr { + +public: + /** Settings which are used to fill the content into the template. + */ + + struct Settings { + /** Constructor. Constructs the new settings object. The default values are empty. + */ + Settings() { + title = QString::null; + langAbbrev = QString::null; + pageCSS_ID = QString::null; + pageDirection = QString("ltr"); + }; + + QList<CSwordModuleInfo*> modules; /**< the list of modules */ + QString title; /**< the title which is used for the new processed HTML page */ + QString langAbbrev; /**< the language for the HTML page. */ + QString pageDirection; /**< the language for the HTML page. */ + QString pageCSS_ID; /**< the CSS ID which is used in the content part of the page */ + }; + + /** Available templates. + * @return The list of templates, which are available. + */ + inline const QStringList availableTemplates(); + /** Fill template. Fill rendered content into the template given by the name. + * @param name The name of the template + * @param content The content which should be filled into the template + * @param settings The settings which are used to process the templating process + * @return The full HTML template HTML code including the CSS data. + */ + const QString fillTemplate( const QString& name, const QString& content, Settings& settings); + /** Default template. + * @return The i18n'ed name of the default template + */ + inline static const QString defaultTemplate(); + +protected: + friend class CPointers; + /** Display template manager constructor. Protected to just allow CPointers to create objects. */ + CDisplayTemplateMgr(); + /** Destructor. */ + ~CDisplayTemplateMgr(); + /** Does the actual work of loading templates from disk */ + void loadTemplates(); + +private: + QMap<QString, QString> m_templateMap; +}; + +inline const QString CDisplayTemplateMgr::defaultTemplate() { + return QString("Blue.tmpl"); +} + +/** + * CDisplayTemplateMgr::availableTemplates() + */ +inline const QStringList CDisplayTemplateMgr::availableTemplates() { + return m_templateMap.keys(); +} + + + +#endif diff --git a/src/backend/managers/clanguagemgr.cpp b/src/backend/managers/clanguagemgr.cpp new file mode 100644 index 0000000..4dcc411 --- /dev/null +++ b/src/backend/managers/clanguagemgr.cpp @@ -0,0 +1,546 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "clanguagemgr.h" + +#include "backend/drivers/cswordmoduleinfo.h" +#include "cswordbackend.h" + +#include "util/cpointers.h" + +//KDE + + +CLanguageMgr::Language::Language() {} + +CLanguageMgr::Language::Language(const Language& l) { + m_abbrev = l.m_abbrev; + m_englishName = l.m_englishName; + m_translatedName = l.m_translatedName; + m_altAbbrevs = l.m_altAbbrevs; +} + +CLanguageMgr::Language::Language( const QString& abbrev, const QString& name, const QString& translatedName, const QStringList& altAbbrevs ) { + m_abbrev = abbrev; + m_englishName = name; + m_translatedName = translatedName; + m_altAbbrevs = altAbbrevs; +} + +CLanguageMgr::Language::~Language() { +} + + +/****************************************************/ +/******************** CLanguageMgr ******************/ +/****************************************************/ +CLanguageMgr::CLanguageMgr() : m_langMap() { + m_availableModulesCache.moduleCount = 0; + init(); +} + +CLanguageMgr::~CLanguageMgr() { + qDeleteAll(m_cleanupLangPtrs); + m_cleanupLangPtrs.clear(); + qDeleteAll(m_langList); + m_langList.clear(); +} + +const CLanguageMgr::LangMap& CLanguageMgr::availableLanguages() { + QList<CSwordModuleInfo*> mods = CPointers::backend()->moduleList(); + + if ( m_availableModulesCache.moduleCount != (unsigned int)mods.count() ) { //we have to refill the cached map + m_availableModulesCache.availableLanguages.clear(); + m_availableModulesCache.moduleCount = mods.count(); + + //collect the languages abbrevs of all modules + QStringList abbrevs; + + foreach (const CSwordModuleInfo* mod, mods) { + if (!abbrevs.contains(mod->module()->Lang())){ + abbrevs.append(mod->module()->Lang()); + } + } + + //now create a map of available langs + foreach ( QString abbrev, abbrevs ) { + const Language* const lang = languageForAbbrev(abbrev); + + if (lang->isValid()) { + m_availableModulesCache.availableLanguages.insert( abbrev, lang ); + } + else { //invalid lang used by a module, create a new language using the abbrev + Language* newLang = new Language(abbrev, abbrev, abbrev); + m_cleanupLangPtrs.append(newLang); + m_availableModulesCache.availableLanguages.insert( abbrev, newLang ); + } + } + } + return m_availableModulesCache.availableLanguages; +} + +const CLanguageMgr::Language* CLanguageMgr::languageForAbbrev( const QString& abbrev ) const { + LangMapIterator it = m_langMap.find(abbrev); + if (it != m_langMap.constEnd()) return *it; //Language is already here + + //try to search in the alternative abbrevs + foreach (const Language* lang, m_langList ) { + if (lang->alternativeAbbrevs().contains(abbrev)) return lang; + } + + // Invalid lang used by a modules, create a new language using the abbrev + Language* newLang = new Language(abbrev, abbrev, abbrev); //return a language which holds the valid abbrev + m_cleanupLangPtrs.append(newLang); + + return newLang; +} + +const CLanguageMgr::Language* CLanguageMgr::languageForName( const QString& name ) const { + foreach ( const Language* lang, m_langList ) { + if (lang->name() == name) return lang; + } + return &m_defaultLanguage;//invalid language +} + +const CLanguageMgr::Language* CLanguageMgr::languageForTranslatedName( const QString& name ) const { + foreach ( const Language* lang, m_langList ) { + if (lang->translatedName() == name) return lang; + } + return &m_defaultLanguage; //invalid language +} + +void CLanguageMgr::init() { + + // The main() sets string literal codec to utf8: + // QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); + // The language names include escape sequences \uxxxx + + //if we've already inserted all items we do not proceed + if (m_langMap.count() > 0) return; + + // Developers: It's easy to get a list of used language codes from all modules: + // Refresh all sources; go to .sword/InstallMgr/; run: + // grep -R -hs Lang= *|cut -c 6-|sort|uniq + // Don't remove unused languages from the source code unless you know it won't be used + // anymore.in any module ever. + + /*: + The string "Names of languages" doesn't actually need translation. + It is put here to help translators notice this help text. + ------- + The names of the languages should follow the conventions of your + language. You can write the names with a capital first letter even if your language + uses non-capitalized language names (they look better with capital + first letter when they are listed). + ------- + To find the names of all languages from internet try searching for + "names of languages in language_x" but in your own language, e.g. + "kielten nimet suomeksi" in Finnish or "names of languages in english" + in English. + ------- + You can find the language codes and names by googling for the standards + mentioned below. + ------- + Preference order for locale codes are: + ------- + ISO 639-1 ------- + ISO 639-2 ------- + ISO 639-3 + ------- + x-E-XXX form is deprecated and no modules in repositories use it. + If you find a module with x-E-XXX language, update the module. + */ + QObject::tr("Names of languages", "No need to translate - see the longer comment (If there is no longer comment, it doesn't work yet :)) ------ "); + // m_langList.append( new Language("aa", "Afar", QObject::tr("Afar")) ); + // m_langList.append( new Language("ab", "Abkhazian", QObject::tr("Abkhazian")) ); + // m_langList.append( new Language("ae", "Avestan", QObject::tr("Avestan")) ); + //: Language name af + m_langList.append( new Language("af", "Afrikaans", QObject::tr("Afrikaans")) ); + // m_langList.append( new Language("am", "Amharic", QObject::tr("Amharic")) ); + //: Language name amu + m_langList.append( new Language("amu", "Amuzgo, Guerrero", QObject::tr("Amuzgo, Guerrero")) ); + //: Language name ang + m_langList.append( new Language("ang", "English, Old (ca.450-1100)", QObject::tr("English, Old (ca.450-1100)")) ); + //: Language name ar + m_langList.append( new Language("ar", "Arabic", QObject::tr("Arabic")) ); + // m_langList.append( new Language("as", "Assamese", QObject::tr("Assamese")) ); + //: Language name az + m_langList.append( new Language("az", "Azerbaijani", QObject::tr("Azerbaijani")) ); + //: Language name azb + m_langList.append( new Language("azb", "Azerbaijani, South", QObject::tr("Azerbaijani, South")) ); + // m_langList.append( new Language("ba", "Bashkir", QObject::tr("Bashkir")) ); + //: Language name bar + m_langList.append( new Language("bar", "Bavarian", QObject::tr("Bavarian")) ); + //: Language name be + m_langList.append( new Language("be", "Belarusian", QObject::tr("Belarusian")) ); + //: Language name bg + m_langList.append( new Language("bg", "Bulgarian", QObject::tr("Bulgarian")) ); + // m_langList.append( new Language("bh", "Bihari", QObject::tr("Bihari")) ); + // m_langList.append( new Language("bi", "Bislama", QObject::tr("Bislama")) ); + // m_langList.append( new Language("bn", "Bengali", QObject::tr("Bengali")) ); + // m_langList.append( new Language("bo", "Tibetan", QObject::tr("Tibetan")) ); + //: Language name br + m_langList.append( new Language("br", "Breton", QObject::tr("Breton")) ); + //: Language name bs + m_langList.append( new Language("bs", "Bosnian", QObject::tr("Bosnian")) ); + //: Language name ca + m_langList.append( new Language("ca", "Catalan", QObject::tr("Catalan")) ); + // m_langList.append( new Language("ce", "Chechen", QObject::tr("Chechen")) ); + //: Language name cco + m_langList.append( new Language("cco", "Chinantec, Comaltepec", QObject::tr("Chinantec, Comaltepec")) ); + //: Language name ceb + m_langList.append( new Language("ceb", "Cebuano", QObject::tr("Cebuano")) ); + //: Language name ch + m_langList.append( new Language("ch", "Chamorro", QObject::tr("Chamorro")) ); + //: Language name chd + m_langList.append( new Language("chd", "Chontal, Highland Oaxaca", QObject::tr("Chontal, Highland Oaxaca")) ); + //: Language name chq + m_langList.append( new Language("chq", "Chinantec, Quiotepec", QObject::tr("Chinantec, Quiotepec")) ); + //: Language name chz + m_langList.append( new Language("chz", "Chinantec, Ozumac\u00edn", QObject::tr("Chinantec, Ozumac\u00edn")) ); + // m_langList.append( new Language("co", "Corsican", QObject::tr("Corsican")) ); + //: Language name ckw + m_langList.append( new Language("ckw", "Cakchiquel, Western", QObject::tr("Cakchiquel, Western")) ); + //: Language name cnl + m_langList.append( new Language("cnl", "Chinantec, Lalana", QObject::tr("Chinantec, Lalana")) ); + //: Language name cnt + m_langList.append( new Language("cnt", "Chinantec, Tepetotutla", QObject::tr("Chinantec, Tepetotutla")) ); + //: Language name cop + m_langList.append( new Language("cop", "Coptic", QObject::tr("Coptic")) ); + //: Language name cs + m_langList.append( new Language("cs", "Czech", QObject::tr("Czech")) ); + //: Language name cso + m_langList.append( new Language("cso", "Chinantec, Sochiapan", QObject::tr("Chinantec, Sochiapan")) ); + //: Language name cti + m_langList.append( new Language("cti", "Chol, Tila", QObject::tr("Chol, Tila")) ); + //: Language name ctp + m_langList.append( new Language("ctp", "Chatino, Western Highland", QObject::tr("Chatino, Western Highland")) ); + //: Language name cu + m_langList.append( new Language("cu", "Church Slavic", QObject::tr("Church Slavic")) ); + // m_langList.append( new Language("cv", "Chuvash", QObject::tr("Chuvash")) ); + //: Language name cy + m_langList.append( new Language("cy", "Welsh", QObject::tr("Welsh")) ); + //: Language name da + m_langList.append( new Language("da", "Danish", QObject::tr("Danish")) ); + //: Language name de + m_langList.append( new Language("de", "German", QObject::tr("German")) ); + //: Language name dug + m_langList.append( new Language("dug", "Duruma", QObject::tr("Duruma")) ); + // m_langList.append( new Language("dz", "Dzongkha", QObject::tr("Dzongkha")) ); + //: Language name el + m_langList.append( new Language("el", "Greek, Modern (1453-)", QObject::tr("Greek, Modern (1453-)"), makeStringList("gre;ell")) ); + //: Language name en + m_langList.append( new Language("en", "English", QObject::tr("English")) ); + //: Language name en_US + m_langList.append( new Language("en_US","American English", QObject::tr("American English")) ); + //: Language name enm + m_langList.append( new Language("enm", "English, Middle (1100-1500)", QObject::tr("English, Middle (1100-1500)")) ); + //: Language name eo + m_langList.append( new Language("eo", "Esperanto", QObject::tr("Esperanto")) ); + //: Language name es + m_langList.append( new Language("es", "Spanish", QObject::tr("Spanish")) ); + //: Language name et + m_langList.append( new Language("et", "Estonian", QObject::tr("Estonian")) ); + //: Language name eu + m_langList.append( new Language("eu", "Basque", QObject::tr("Basque")) ); + //: Language name fa + m_langList.append( new Language("fa", "Persian", QObject::tr("Persian")) ); + //: Language name fi + m_langList.append( new Language("fi", "Finnish", QObject::tr("Finnish")) ); + // m_langList.append( new Language("fj", "Fijian", QObject::tr("Fijian")) ); + // m_langList.append( new Language("fo", "Faroese", QObject::tr("Faroese")) ); + //: Language name fr + m_langList.append( new Language("fr", "French", QObject::tr("French")) ); + //: Language name fy + m_langList.append( new Language("fy", "Frisian", QObject::tr("Frisian")) ); + //: Language name ga + m_langList.append( new Language("ga", "Irish", QObject::tr("Irish")) ); + //: Language name gd + m_langList.append( new Language("gd", "Gaelic (Scots)", QObject::tr("Gaelic (Scots)")) ); + //: Language name gez + m_langList.append( new Language("gez", "Geez", QObject::tr("Geez")) ); + // m_langList.append( new Language("gl", "Gallegan", QObject::tr("Gallegan")) ); + // m_langList.append( new Language("gn", "Guarani", QObject::tr("Guarani")) ); + // m_langList.append( new Language("gn", "Gujarati", QObject::tr("Gujarati")) ); + //: Language name got + m_langList.append( new Language("got", "Gothic", QObject::tr("Gothic")) ); + //: Language name gv + m_langList.append( new Language("gv", "Manx", QObject::tr("Manx")) ); + //: Language name grc + m_langList.append( new Language("grc", "Greek, Ancient (to 1453)", QObject::tr("Greek, Ancient (to 1453)")) ); + //: Language name he + m_langList.append( new Language("he", "Hebrew", QObject::tr("Hebrew")) ); + //: Language name hau + m_langList.append( new Language("hau", "Hausa", QObject::tr("Hausa")) ); + //: Language name haw + m_langList.append( new Language("haw", "Hawaiian", QObject::tr("Hawaiian")) ); + //: Language name hi + m_langList.append( new Language("hi", "Hindi", QObject::tr("Hindi")) ); + // m_langList.append( new Language("ho", "Hiri Motu", QObject::tr("Hiri Motu")) ); + //: Language name hr + m_langList.append( new Language("hr", "Croatian", QObject::tr("Croatian")) ); + //: Language name ht + m_langList.append( new Language("ht", "Haitian Creole", QObject::tr("Haitian Creole")) ); + //: Language name hu + m_langList.append( new Language("hu", "Hungarian", QObject::tr("Hungarian")) ); + //: Language name huv + m_langList.append( new Language("huv", "Huave, San Mateo Del Mar", QObject::tr("Huave, San Mateo Del Mar")) ); + //: Language name hy + m_langList.append( new Language("hy", "Armenian", QObject::tr("Armenian")) ); + // m_langList.append( new Language("hz", "Herero", QObject::tr("Herero")) ); + // m_langList.append( new Language("ia", "Interlingua", QObject::tr("Interlingua")) ); + //: Language name id + m_langList.append( new Language("id", "Indonesian", QObject::tr("Indonesian")) ); + // m_langList.append( new Language("ie", "Interlingue", QObject::tr("Interlingue")) ); + // m_langList.append( new Language("ik", "Inupiaq", QObject::tr("Inupiaq")) ); + //: Language name is + m_langList.append( new Language("is", "Icelandic", QObject::tr("Icelandic")) ); + //: Language name it + m_langList.append( new Language("it", "Italian", QObject::tr("Italian")) ); + //: Language name itz + m_langList.append( new Language("itz", "Itz\u00e1", QObject::tr("Itz\u00e1")) ); + //: Language name ixl + m_langList.append( new Language("ixl", "Ixil, San Juan Cotzal", QObject::tr("Ixil, San Juan Cotzal")) ); + // m_langList.append( new Language("iu", "Inuktitut", QObject::tr("Inuktitut")) ); + //: Language name ja + m_langList.append( new Language("ja", "Japanese", QObject::tr("Japanese")) ); + //: Language name jac + m_langList.append( new Language("jac", "Jacalteco, Eastern", QObject::tr("Jacalteco, Eastern")) ); + //: Language name jvn + m_langList.append( new Language("jvn", "Javanese, Caribbean", QObject::tr("Javanese, Caribbean")) ); + //: Language name ka + m_langList.append( new Language("ka", "Georgian", QObject::tr("Georgian")) ); + //: Language name kek + m_langList.append( new Language("kek", "Kekch\u00ed", QObject::tr("Kekch\u00ed", "kek")) ); + // m_langList.append( new Language("ki", "Kikuyu", QObject::tr("Kikuyu")) ); + // m_langList.append( new Language("kj", "Kuanyama", QObject::tr("Kuanyama")) ); + // m_langList.append( new Language("kk", "Kazakh", QObject::tr("Kazakh")) ); + // m_langList.append( new Language("kl", "Kalaallisut", QObject::tr("Kalaallisut")) ); + // m_langList.append( new Language("km", "Khmer", QObject::tr("Khmer")) ); + // m_langList.append( new Language("kn", "Kannada", QObject::tr("Kannada")) ); + //: Language name ko + m_langList.append( new Language("ko", "Korean", QObject::tr("Korean")) ); + // m_langList.append( new Language("ks", "Kashmiri", QObject::tr("Kashmiri")) ); + //: Language name ku + m_langList.append( new Language("ku", "Kurdish", QObject::tr("Kurdish")) ); + // m_langList.append( new Language("kv", "Komi", QObject::tr("Komi")) ); + // m_langList.append( new Language("kw", "Cornish", QObject::tr("Cornish")) ); + //: Language name ky + m_langList.append( new Language("ky", "Kirghiz", QObject::tr("Kirghiz")) ); + //: Language name la + m_langList.append( new Language("la", "Latin", QObject::tr("Latin")) ); + //: Language name lac + m_langList.append( new Language("lac", "Lacandon", QObject::tr("Lacandon")) ); + // m_langList.append( new Language("lb", "Letzeburgesch", QObject::tr("Letzeburgesch")) ); + //: Language name lmo + m_langList.append( new Language("lmo", "Lombard", QObject::tr("Lombard")) ); + // m_langList.append( new Language("ln", "Lingala", QObject::tr("Lingala")) ); + // m_langList.append( new Language("lo", "Lao", QObject::tr("Lao")) ); + //: Language name lt + m_langList.append( new Language("lt", "Lithuanian", QObject::tr("Lithuanian")) ); + //: Language name lv + m_langList.append( new Language("lv", "Latvian", QObject::tr("Latvian")) ); + //: Language name mg + m_langList.append( new Language("mg", "Malagasy", QObject::tr("Malagasy")) ); + // m_langList.append( new Language("mh", "Marshall", QObject::tr("Marshall")) ); + //: Language name mi + m_langList.append( new Language("mi", "Maori", QObject::tr("Maori")) ); + //: Language name mir + m_langList.append( new Language("mir", "Mixe, Isthmus", QObject::tr("Mixe, Isthmus")) ); + //: Language name miz + m_langList.append( new Language("miz", "Mixtec, Coatzospan", QObject::tr("Mixtec, Coatzospan")) ); + //: Language name mk + m_langList.append( new Language("mk", "Macedonian", QObject::tr("Macedonian")) ); + //: Language name mks + m_langList.append( new Language("mks", "Mixtec, Silacayoapan", QObject::tr("Mixtec, Silacayoapan")) ); + // m_langList.append( new Language("ml", "Malayalam", QObject::tr("Malayalam")) ); + // m_langList.append( new Language("mn", "Mongolian", QObject::tr("Mongolian")) ); + // m_langList.append( new Language("mo", "Moldavian", QObject::tr("Moldavian")) ); + //: Language name mos + m_langList.append( new Language("mos", "More", QObject::tr("More")) ); + // m_langList.append( new Language("mr", "Marathi", QObject::tr("Marathi")) ); + //: Language name ms + m_langList.append( new Language("ms", "Malay", QObject::tr("Malay")) ); + //: Language name mt + m_langList.append( new Language("mt", "Maltese", QObject::tr("Maltese")) ); + //: Language name mul (meaning that the work has multiple languages) + m_langList.append( new Language("mul", "(Multiple languages)", QObject::tr("(Multiple languages)")) ); + //: Language name mvc + m_langList.append( new Language("mvc", "Mam, Central", QObject::tr("Mam, Central")) ); + //: Language name mvj + m_langList.append( new Language("mvj", "Mam, Todos Santos Cuchumat\u00e1n", QObject::tr("Mam, Todos Santos Cuchumat\u00e1n")) ); + //: Language name mxq + m_langList.append( new Language("mxq", "Mixe, Juquila", QObject::tr("Mixe, Juquila")) ); + //: Language name mxt + m_langList.append( new Language("mxt", "Mixtec, Jamiltepec", QObject::tr("Mixtec, Jamiltepec")) ); + //: Language name my + m_langList.append( new Language("my", "Burmese", QObject::tr("Burmese")) ); + // m_langList.append( new Language("na", "Nauru", QObject::tr("Nauru")) ); + //: Language name nb + m_langList.append( new Language("nb", "Norwegian Bokm\u00e5l", QObject::tr("Norwegian Bokm\u00e5l")) ); + //: Language name ncl + m_langList.append( new Language("ncl", "Nahuatl, Michoac\u00e1n", QObject::tr("Nahuatl, Michoac\u00e1n")) ); + // m_langList.append( new Language("nd", "Ndebele, North", QObject::tr("Ndebele, North")) ); + //: Language name nds + m_langList.append( new Language("nds", "Low German; Low Saxon", QObject::tr("Low German; Low Saxon")) ); + //: Language name ne + m_langList.append( new Language("ne", "Nepali", QObject::tr("Nepali")) ); + //: Language name ngu + m_langList.append( new Language("ngu", "Nahuatl, Guerrero", QObject::tr("Nahuatl, Guerrero")) ); + //: Language name nhy + m_langList.append( new Language("nhy", "Nahuatl, Northern Oaxaca", QObject::tr("Nahuatl, Northern Oaxaca")) ); + // m_langList.append( new Language("ng", "Ndonga", QObject::tr("Ndonga")) ); + //: Language name nl + m_langList.append( new Language("nl", "Dutch", QObject::tr("Dutch")) ); + //: Language name nn + m_langList.append( new Language("nn", "Norwegian Nynorsk", QObject::tr("Norwegian Nynorsk")) ); + //: Language name no + m_langList.append( new Language("no", "Norwegian", QObject::tr("Norwegian")) ); + // m_langList.append( new Language("nr", "Ndebele, South", QObject::tr("Ndebele, South")) ); + // m_langList.append( new Language("nv", "Navajo", QObject::tr("Navajo")) ); + // m_langList.append( new Language("ny", "Chichewa; Nyanja", QObject::tr("Chichewa; Nyanja")) ); + // m_langList.append( new Language("oc", "Occitan (post 1500); Provençal", QObject::tr("Occitan (post 1500); Provençal")) ); + // m_langList.append( new Language("om", "Oromo", QObject::tr("Oromo")) ); + // m_langList.append( new Language("or", "Oriya", QObject::tr("Oriya")) ); + // m_langList.append( new Language("os", "Ossetian; Ossetic", QObject::tr("Ossetian; Ossetic")) ); + //: Language name otq + m_langList.append( new Language("otq", "Otomi, Quer\u00e9taro", QObject::tr("Otomi, Quer\u00e9taro")) ); + // m_langList.append( new Language("pa", "Panjabi", QObject::tr("Panjabi")) ); + //: Language name pap + m_langList.append( new Language("pap", "Papiamento", QObject::tr("Papiamento")) ); + // m_langList.append( new Language("pi", "Pali", QObject::tr("Pali")) ); + //: Language name ppk + m_langList.append( new Language("ppk", "Uma", QObject::tr("Uma")) ); + //: Language name pl + m_langList.append( new Language("pl", "Polish", QObject::tr("Polish")) ); + //: Language name pot + m_langList.append( new Language("pot", "Potawatomi", QObject::tr("Potawatomi")) ); + //: Language name ppk + m_langList.append( new Language("ppk", "Uma", QObject::tr("Uma")) ); + //: Language name prs + m_langList.append( new Language("prs", "Persian (Dari)", QObject::tr("Persian (Dari)")) ); + + // m_langList.append( new Language("ps", "Pushto", QObject::tr("Pushto")) ); + //: Language name pt + m_langList.append( new Language("pt", "Portuguese", QObject::tr("Portuguese")) ); + //: Language name pt_BR + m_langList.append( new Language("pt_BR", "Brasilian Portuguese", QObject::tr("Brasilian Portuguese")) );//added by ourself + // m_langList.append( new Language("qu", "Quechua", QObject::tr("Quechua")) ); + //: Language name qut + m_langList.append( new Language("qut", "Quich\u00e9, West Central", QObject::tr("Quich\u00e9, West Central")) ); + // m_langList.append( new Language("rm", "Raeto-Romance", QObject::tr("Raeto-Romance")) ); + // m_langList.append( new Language("rn", "Rundi", QObject::tr("Rundi")) ); + //: Language name ro + m_langList.append( new Language("ro", "Romanian", QObject::tr("Romanian")) ); + //: Language name ru + m_langList.append( new Language("ru", "Russian", QObject::tr("Russian")) ); + // m_langList.append( new Language("rw", "Kinyarwanda", QObject::tr("Kinyarwanda")) ); + // m_langList.append( new Language("sa", "Sanskrit", QObject::tr("Sanskrit")) ); + // m_langList.append( new Language("sc", "Sardinian", QObject::tr("Sardinian")) ); + //: Language name sco + m_langList.append( new Language("sco", "Scots", QObject::tr("Scots")) ); + // m_langList.append( new Language("sd", "Sindhi", QObject::tr("Sindhi")) ); + // m_langList.append( new Language("se", "Northern Sami", QObject::tr("Northern Sami")) ); + // m_langList.append( new Language("sg", "Sango", QObject::tr("Sango")) ); + // m_langList.append( new Language("si", "Sinhalese", QObject::tr("Sinhalese")) ); + //: Language name sk + m_langList.append( new Language("sk", "Slovak", QObject::tr("Slovak")) ); + //: Language name sl + m_langList.append( new Language("sl", "Slovenian", QObject::tr("Slovenian")) ); + // m_langList.append( new Language("sm", "Samoan", QObject::tr("Samoan")) ); + // m_langList.append( new Language("sn", "Shona", QObject::tr("Shona")) ); + //: Language name so + m_langList.append( new Language("so", "Somali", QObject::tr("Somali")) ); + //: Language name sq + m_langList.append( new Language("sq", "Albanian", QObject::tr("Albanian")) ); + // m_langList.append( new Language("sr", "Serbian", QObject::tr("Serbian")) ); + //: Language name srn + m_langList.append( new Language("srn", "Sranan", QObject::tr("Sranan")) ); + // m_langList.append( new Language("ss", "Swati", QObject::tr("Swati")) ); + // m_langList.append( new Language("st", "Sotho, Southern", QObject::tr("Sotho, Southern")) ); + // m_langList.append( new Language("su", "Sundanese", QObject::tr("Sundanese")) ); + //: Language name sv + m_langList.append( new Language("sv", "Swedish", QObject::tr("Swedish")) ); + //: Language name sw + m_langList.append( new Language("sw", "Swahili", QObject::tr("Swahili")) ); + //: Language name syr + m_langList.append( new Language("syr", "Syriac", QObject::tr("Syriac")) ); + //: Language name ta + m_langList.append( new Language("ta", "Tamil", QObject::tr("Tamil")) ); + // m_langList.append( new Language("te", "Telugu", QObject::tr("Telugu")) ); + // m_langList.append( new Language("tg", "Tajik", QObject::tr("Tajik")) ); + //: Language name th + m_langList.append( new Language("th", "Thai", QObject::tr("Thai")) ); + // m_langList.append( new Language("tk", "Turkmen", QObject::tr("Turkmen")) ); + //: Language name tl + m_langList.append( new Language("tl", "Tagalog", QObject::tr("Tagalog")) ); + //: Language name tlh + m_langList.append( new Language("tlh", "Klingon", QObject::tr("Klingon")) ); + //: Language name tn + m_langList.append( new Language("tn", "Tswana", QObject::tr("Tswana")) ); + //: Language name tr + m_langList.append( new Language("tr", "Turkish", QObject::tr("Turkish")) ); + // m_langList.append( new Language("ts", "Tsonga", QObject::tr("Tsonga")) ); + // m_langList.append( new Language("tt", "Tatar", QObject::tr("Tatar")) ); + //: Language name ttc + m_langList.append( new Language("ttc", "Tektiteko", QObject::tr("Tektiteko")) ); + // m_langList.append( new Language("tw", "Twi", QObject::tr("Twi")) ); + //: Language name ty + m_langList.append( new Language("ty", "Tahitian", QObject::tr("Tahitian")) ); + //: Language name tzz + m_langList.append( new Language("tzz", "Tzotzil, Zinacant\u00e1n", QObject::tr("Tzotzil, Zinacant\u00e1n")) ); + // m_langList.append( new Language("ug", "Uighur", QObject::tr("Uighur")) ); + //: Language name uk + m_langList.append( new Language("uk", "Ukrainian", QObject::tr("Ukrainian")) ); + // m_langList.append( new Language("ur", "Urdu", QObject::tr("Urdu")) ); + //: Language name ury + m_langList.append( new Language("ury", "Orya", QObject::tr("Orya")) ); + //: Language name usp + m_langList.append( new Language("usp", "Uspanteco", QObject::tr("Uspanteco")) ); + // m_langList.append( new Language("uz", "Uzbek", QObject::tr("Uzbek")) ); + //: Language name vi + m_langList.append( new Language("vi", "Vietnamese", QObject::tr("Vietnamese")) ); + // m_langList.append( new Language("vo", "Volapük", QObject::tr("Volapük")) ); + // m_langList.append( new Language("wo", "Wolof", QObject::tr("Wolof")) ); + //: Language name xh + m_langList.append( new Language("xh", "Xhosa", QObject::tr("Xhosa")) ); + //: Language name xtd + m_langList.append( new Language("xtd", "Mixtec, Diuxi-Tilantongo", QObject::tr("Mixtec, Diuxi-Tilantongo")) ); + //: Language name yi + m_langList.append( new Language("yi", "Yiddish", QObject::tr("Yiddish")) ); + //: Language name yo + m_langList.append( new Language("yo", "Yoruba", QObject::tr("Yoryba")) ); + // m_langList.append( new Language("za", "Zhuang", QObject::tr("Zhuang")) ); + //: Language name zab + m_langList.append( new Language("zab", "Zapotec, San Juan Guelav\u00eda", QObject::tr("Zapotec, San Juan Guelav\u00eda")) ); + //: Language name zaw + m_langList.append( new Language("zaw", "Zapotec, Mitla", QObject::tr("Zapotec, Mitla")) ); + //: Language name zh + m_langList.append( new Language("zh", "Chinese", QObject::tr("Chinese")) ); + //: Language name zpo + m_langList.append( new Language("zpo", "Zapotec, Amatl\u00e1n", QObject::tr("Zapotec, Amatl\u00e1n")) ); + //: Language name zpq + m_langList.append( new Language("zpq", "Zapotec, Zoogocho", QObject::tr("Zapotec, Zoogocho")) ); + //: Language name zpu + m_langList.append( new Language("zpu", "Zapotec, Yal\u00e1lag", QObject::tr("Zapotec, Yal\u00e1lag")) ); + //: Language name zpv + m_langList.append( new Language("zpv", "Zapotec, Chichicapan", QObject::tr("Zapotec, Chichicapan")) ); + //: Language name zsr + m_langList.append( new Language("zsr", "Zapotec, Southern Rincon", QObject::tr("Zapotec, Southern Rincon")) ); + //: Language name ztq + m_langList.append( new Language("ztq", "Zapotec, Quioquitani-Quier\u00ed", QObject::tr("Zapotec, Quioquitani-Quier\u00ed")) ); + //: Language name zty + m_langList.append( new Language("zty", "Zapotec, Yatee", QObject::tr("Zapotec, Yatee")) ); + //: Language name zu + m_langList.append( new Language("zu", "Zulu", QObject::tr("Zulu")) ); + + foreach (Language* lang, m_langList) { + m_langMap.insert( lang->abbrev(), lang); + } +} diff --git a/src/backend/managers/clanguagemgr.h b/src/backend/managers/clanguagemgr.h new file mode 100644 index 0000000..f421e62 --- /dev/null +++ b/src/backend/managers/clanguagemgr.h @@ -0,0 +1,151 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CLANGUAGEMGR_H +#define CLANGUAGEMGR_H + +//Qt includes +#include <QString> +#include <QStringList> +#include <QList> +#include <QHash> + +/** Manages the languages of BibleTime and provides functions to work with them. + * @author The BibleTime team + */ + +class CLanguageMgr { + +public: + /** Language container. + * This class (Language) contains the information about the chosen language. + */ + class Language { + public: + /** Default constructor of a language object. + * Uses the abbreviation parameter to lookup the + * language name and to be able to return the name, flag etc. + * Possible values for abbrev are de, en, fr, it etc. + */ + Language(); + /** Copy constructor. + */ + Language(const Language&); + /** Constructor which takes all necessary data. + */ + Language(const QString& abbrev, const QString& englishName, const QString& translatedName, const QStringList& altAbbrevs = QStringList()); + /** Destructor. + */ + ~Language(); + /** Returns the abbreviation. + * @return The abbreviation of the chosen language. + */ + inline const QString& abbrev() const { + if (m_abbrev.isEmpty() && m_altAbbrevs.count()) { //no standard abbrev but alternative ones + return m_altAbbrevs.first(); + } + return m_abbrev; + } + /** Returns the translated name. + * @return The translated name of the language. + */ + inline const QString& translatedName() const { + return m_translatedName; + } + /** The english name of the language. + * @return The english name of the chosen language. + */ + inline const QString& name() const { + return m_englishName; + } + /** The alternative abbreviations which are avalable for this language. + * @return The List of alternate abbreviations + */ + inline const QStringList alternativeAbbrevs() const { + return m_altAbbrevs; + } + /** + * Returns true if this language object is valid, i.e. has an abbrev and name. + * @return True if the data is valid for this language. + */ + inline bool isValid() const { + return (!abbrev().isEmpty() && !name().isEmpty()); + } + + private: + QString m_abbrev; + QString m_englishName; + QString m_translatedName; + QStringList m_altAbbrevs; + }; + + typedef QList<Language*> LanguageList; + typedef QHash<QString, const Language*> LangMap; + typedef QHash<QString, const Language*>::const_iterator LangMapIterator; + + /** Constructor. + */ + CLanguageMgr(); + /** Destructor + */ + virtual ~CLanguageMgr(); + /** + * Returns the standard languages available as standard. Does nothing for Sword. + * @return A LangMap map which contains all known languages + */ + inline const CLanguageMgr::LangMap* languages() const { + return &m_langMap; + } + /** + * Returns the languages which are available. The languages cover all available modules, but nothing more. + * @return A map of all languages with modules available for them + */ + const CLanguageMgr::LangMap& availableLanguages(); + /** Language for abbreviation. + * @param abbrev The language abbreviation + * @return Pointer to a language for the given string abbreviation. + */ + const CLanguageMgr::Language* languageForAbbrev( const QString& abbrev ) const; + /** Language for english name. + * @param abbrev The english language name. + * @return Pointer to a language for the given name + */ + const CLanguageMgr::Language* languageForName( const QString& language ) const; + /** Language for translated language name. + * @param abbrev The translated language name + * @return Pointer to a language for the given translated language name + */ + const CLanguageMgr::Language* languageForTranslatedName( const QString& language ) const; + /** Default language so we don't return NULL pointers. + * @return Pointer to the default language + */ + inline const CLanguageMgr::Language* defaultLanguage() const { + return &m_defaultLanguage; + } + +private: + void init(); + inline const QStringList makeStringList(const QString& abbrevs) { + return abbrevs.split( ";", QString::KeepEmptyParts, Qt::CaseSensitive ); + } + + Language m_defaultLanguage; + mutable LanguageList m_langList; + mutable LangMap m_langMap; + mutable LanguageList m_cleanupLangPtrs; + + struct ModuleCache { + unsigned int moduleCount; + LangMap availableLanguages; + } + m_availableModulesCache; +}; + +#endif + diff --git a/src/backend/managers/creferencemanager.cpp b/src/backend/managers/creferencemanager.cpp new file mode 100644 index 0000000..adae180 --- /dev/null +++ b/src/backend/managers/creferencemanager.cpp @@ -0,0 +1,422 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "creferencemanager.h" +#include "backend/keys/cswordversekey.h" + +#include "backend/config/cbtconfig.h" +#include "util/cpointers.h" + +//QT +#include <QRegExp> + +//stl +#include <algorithm> // STL algorithms class library + +/** Returns a hyperlink used to be imbedded in the display windows. At the moment the format is sword://module/key */ +const QString CReferenceManager::encodeHyperlink( const QString moduleName, const QString key, const CReferenceManager::Type type) { + QString ret = QString::null; + + switch (type) { + + case Bible: + ret = QString("sword://Bible/"); + break; + case Commentary: + ret = QString("sword://Commentary/"); + break; + case Lexicon: + ret = QString("sword://Lexicon/"); + break; + case GenericBook: + ret = QString("sword://Book/"); + break; + case MorphHebrew: + ret = QString("morph://Hebrew/"); + break; + case MorphGreek: + ret = QString("morph://Greek/"); + break; + case StrongsHebrew: + ret = QString("strongs://Hebrew/"); + break; + case StrongsGreek: + ret = QString("strongs://Greek/"); + break; + default: + break; + } + + if (!moduleName.isEmpty()) { + ret.append( moduleName ).append('/'); + } + else { //if module is empty use fallback module + ret.append( preferredModule(type) ).append('/'); + } + + if (type == GenericBook) { + const QString s = (!key.isEmpty() ? key : QString::null); + QString newKey = QString::null; + //replace all / of the key (e.g. of a CSwordTreeKey) with + // the escape sequence \/ so we know it's a link internal divider (e.g. of CSwordTreeKey)! + + QChar c; + + for(int i = 0; i < s.length(); ++i) { + c = s.at(i); + + if (c == '/') { + newKey.append("\\/"); + } + else { + newKey.append(c); + } + } + + ret.append( newKey ); + } + else { //slashes do not appear in verses and dictionary entries + + switch (type) { + + case Bible: //bibles or commentary keys need parsing + + case Commentary: { +/* CSwordModuleInfo* mod = CPointers::backend()->findModuleByName(moduleName); + + ParseOptions options; + options.refDestinationModule = mod->name(); + options.refBase = + options.sourceLanguage = mod->module()->Lang(); + options.destinationLanguage = "en"; + + ret.append( parseVerseReference(key, options) ); //we add the english key, so drag and drop will work in all cases*/ + ret.append(key); + break; + } + + default: + ret.append( key ); //use the standard key, no parsing required + break; + } + } + + return ret; +} + +/** Decodes the given hyperlink to module and key. */ +bool CReferenceManager::decodeHyperlink( const QString& hyperlink, QString& module, QString& key, CReferenceManager::Type& type ) { + /** + * We have to decide between three types of URLS: sword://Type/Module/Key, morph://Testament/key and strongs://Testament/Key + */ + module = QString::null; + key = QString::null; + + type = Unknown; //not yet known + QString ref = hyperlink; + //remove the trailing slash + + if (ref.right(1)=="/" && ref.right(2) != "\\/") //trailing slash, but not escaped + ref = ref.left(ref.length()-1); + + //find out which type we have by looking at the beginning (protocoll section of URL) + if (ref.left(8).toLower() == "sword://") { //Bible, Commentary or Lexicon + ref = ref.mid(8); + + if (ref.left(5).toLower() == "bible") { //a bible hyperlink + type = CReferenceManager::Bible; + ref = ref.mid(6); //inclusive trailing slash + } + else if (ref.left(10).toLower() == "commentary") { // a Commentary hyperlink + type = CReferenceManager::Commentary; + ref = ref.mid(11); //inclusive trailing slash + } + else if (ref.left(7).toLower() == "lexicon") { // a Lexicon hyperlink + type = CReferenceManager::Lexicon; + ref = ref.mid(8); //inclusive trailing slash + } + else if (ref.left(4).toLower() == "book") { // a Book hyperlink + type = CReferenceManager::GenericBook; + ref = ref.mid(5); //inclusive trailing slash + } + + // string up to next slash is the modulename + if (ref.at(0) != '/' ) { //we have a module given + + while (true) { + const int pos = ref.indexOf("/"); + + if ((pos>0) && ref.at(pos-1) != '\\') { //found a slash which is not escaped + module = ref.mid(0,pos); + ref = ref.mid(pos+1); + break; + } + else if (pos == -1) { + break; + } + } + + // the rest is the key + key = ref; + } + else { + key = ref.mid(1); + } + + //the key may be an osis key like "NASBLex:Moses", which sets the module, too + // const int modPos = key.find(":"); + // if (modPos != -1 && key.at(modPos-1).isLetter() && key.at(modPos+1).isLetter()) { + // module = key.left(modPos); + // key = key.mid(modPos+1); + // + // qWarning("found the module name %s with key %s", module.latin1(), key.latin1()); + // } + + //replace \/ escapes with / + key.replace(QRegExp("\\\\/"), "/"); + } + else if (ref.left(8).toLower() == "morph://" || ref.left(10).toLower() == "strongs://") { //strongs or morph URL have the same format + enum PreType {IsMorph, IsStrongs}; + PreType preType = IsMorph; + + if (ref.left(8).toLower() == "morph://") { //morph code hyperlink + ref = ref.mid(8); + preType = IsMorph; + } + else if (ref.left(10).toLower() == "strongs://") { + ref = ref.mid(10); + preType = IsStrongs; + } + + //part up to next slash is the language + const int pos = ref.indexOf("/"); + + if (pos>0) { //found + const QString language = ref.mid(0,pos); + + if (language.toLower() == "hebrew") { + switch (preType) { + + case IsMorph: + type = CReferenceManager::MorphHebrew; + break; + + case IsStrongs: + type = CReferenceManager::StrongsHebrew; + break; + } + } + else if (language.toLower() == "greek") { + switch (preType) { + + case IsMorph: + type = CReferenceManager::MorphGreek; + break; + + case IsStrongs: + type = CReferenceManager::StrongsGreek; + break; + } + } + + ref = ref.mid(pos+1); + key = ref; //the remaining part is the key + + module = preferredModule(type); + } + } + + if (key.isEmpty() && module.isEmpty()) + return false; + + return true; +} + +const QString CReferenceManager::encodeReference(const QString &module, const QString &reference) { + //return QString("(%1)%2").arg(module).arg(reference); + return QString("(").append(module).append(")").append(reference); +} + +void CReferenceManager::decodeReference(QString &dragreference, QString &module, QString &reference) { + const int pos = dragreference.indexOf(")"); + const QString fallbackModule = dragreference.mid( 1, pos - 1); + dragreference = dragreference.mid(pos+1); + + module = fallbackModule; + reference = dragreference; +} + +/** Returns true if the parameter is a hyperlink. */ +bool CReferenceManager::isHyperlink( const QString& hyperlink ) { + return ( hyperlink.left(8) == "sword://") + || (hyperlink.left(10) == "strongs://") + || (hyperlink.left(8) == "morph://"); +} + +/** Returns the preferred module name for the given type. */ +const QString CReferenceManager::preferredModule( const CReferenceManager::Type type ) { + QString moduleName = QString::null; + CSwordModuleInfo* module = 0; + + switch (type) { + + case CReferenceManager::Bible: + + module = CBTConfig::get + ( CBTConfig::standardBible ); + + break; + + case CReferenceManager::Commentary: + module = CBTConfig::get + ( CBTConfig::standardCommentary ); + + break; + + case CReferenceManager::Lexicon: + module = CBTConfig::get + ( CBTConfig::standardLexicon ); + + break; + + case CReferenceManager::StrongsHebrew: + module = CBTConfig::get + ( CBTConfig::standardHebrewStrongsLexicon ); + + break; + + case CReferenceManager::StrongsGreek: + module = CBTConfig::get + ( CBTConfig::standardGreekStrongsLexicon ); + + break; + + case CReferenceManager::MorphHebrew: + module = CBTConfig::get + ( CBTConfig::standardHebrewMorphLexicon ); + + break; + + case CReferenceManager::MorphGreek: + module = CBTConfig::get + ( CBTConfig::standardGreekMorphLexicon ); + + break; + + default: + module = 0; + + break; + } + + return module ? module->name() : QString::null; +} + +/** No descriptions */ +CReferenceManager::Type CReferenceManager::typeFromModule( const CSwordModuleInfo::ModuleType type) { + switch (type) { + + case CSwordModuleInfo::Bible: + return CReferenceManager::Bible; + + case CSwordModuleInfo::Commentary: + return CReferenceManager::Commentary; + + case CSwordModuleInfo::Lexicon: + return CReferenceManager::Lexicon; + + case CSwordModuleInfo::GenericBook: + return CReferenceManager::GenericBook; + + default: + return CReferenceManager::Unknown; + } +} + +/** Parses the given verse references using the given language and the module.*/ +const QString CReferenceManager::parseVerseReference( const QString& ref, const CReferenceManager::ParseOptions& options) { + + CSwordModuleInfo* const mod = CPointers::backend()->findModuleByName(options.refDestinationModule); + //Q_ASSERT(mod); tested later + + if (!mod) { + //parsing of non-verse based references is not supported + return ref; + } + + if ((mod->type() != CSwordModuleInfo::Bible) && (mod->type() != CSwordModuleInfo::Commentary)) { + qDebug("CReferenceManager: Only verse based modules are supported as ref destination module"); + return QString::null; + } + + QString sourceLanguage = options.sourceLanguage; + QString destinationLanguage = options.destinationLanguage; + + sword::StringList locales = sword::LocaleMgr::getSystemLocaleMgr()->getAvailableLocales(); + if (/*options.sourceLanguage == "en" ||*/ std::find(locales.begin(), locales.end(), sourceLanguage.toUtf8().constData()) == locales.end()) { //sourceLanguage not available + sourceLanguage = "en_US"; + } + + if (/*options.destinationLanguage == "en" ||*/ std::find(locales.begin(), locales.end(), sourceLanguage.toUtf8().constData()) == locales.end()) { //destination not available + destinationLanguage = "en_US"; + } + + QString ret; + QStringList refList = ref.split(";"); + + CSwordVerseKey baseKey(0); + baseKey.setLocale( sourceLanguage.toUtf8().constData() ); + baseKey.key( options.refBase ); //probably in the sourceLanguage + baseKey.setLocale( "en_US" ); //english works in all environments as base + +// CSwordVerseKey dummy(0); + //HACK: We have to workaround a Sword bug, we have to set the default locale to the same as the sourceLanguage ! + const QString oldLocaleName = CPointers::backend()->booknameLanguage(); + CPointers::backend()->booknameLanguage(sourceLanguage); + + sword::VerseKey dummy; + dummy.setLocale( sourceLanguage.toUtf8().constData() ); + Q_ASSERT( !strcmp(dummy.getLocale(), sourceLanguage.toUtf8().constData()) ); + +// qDebug("Parsing '%s' in '%s' using '%s' as base, source lang '%s', dest lang '%s'", ref.latin1(), options.refDestinationModule.latin1(), baseKey.key().latin1(), sourceLanguage.latin1(), destinationLanguage.latin1()); + + for (QStringList::iterator it = refList.begin(); it != refList.end(); it++) { + //The listkey may contain more than one item, because a ref lik "Gen 1:3,5" is parsed into two single refs + sword::ListKey lk = dummy.ParseVerseList((*it).toUtf8().constData(), baseKey.key().toUtf8().constData(), true); + Q_ASSERT(!dummy.Error()); + + //Q_ASSERT(lk.Count()); + if (!lk.Count()) { + ret.append( *it ); //don't change the original + continue; + } + + for (int i = 0; i < lk.Count(); ++i) { + if (dynamic_cast<sword::VerseKey*>(lk.getElement(i))) { // a range + sword::VerseKey* k = dynamic_cast<sword::VerseKey*>(lk.getElement(i)); + Q_ASSERT(k); + k->setLocale( destinationLanguage.toUtf8().constData() ); + + ret.append( QString::fromUtf8(k->getRangeText()) ).append("; "); + } + else { // a single ref + sword::VerseKey vk; + vk.setLocale( sourceLanguage.toUtf8().constData() ); + vk = lk.getElement(i)->getText(); + vk.setLocale( destinationLanguage.toUtf8().constData() ); + + ret.append( QString::fromUtf8(vk.getText()) ).append("; "); + } + } + + } + + CPointers::backend()->booknameLanguage(oldLocaleName); + return ret; +} diff --git a/src/backend/managers/creferencemanager.h b/src/backend/managers/creferencemanager.h new file mode 100644 index 0000000..19baae7 --- /dev/null +++ b/src/backend/managers/creferencemanager.h @@ -0,0 +1,110 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CREFERENCEMANAGER_H +#define CREFERENCEMANAGER_H + +#include "backend/drivers/cswordmoduleinfo.h" + +//Qt includes +#include <QString> + +/** Contains static functions to work with references used for Drag & Drop and for hyperlinks used in our + * rendered HTML code. + * @author The BibleTime team + */ + +class CReferenceManager { + +public: + enum Type { + Bible, /**< Bibles */ + Commentary, /**< Commentary */ + Lexicon, /**< Lexicon */ + GenericBook, /**< Generic Book */ + MorphHebrew, /**< Module for hebrew morphology*/ + MorphGreek, /**< Module for greek morphology */ + StrongsHebrew, /**< Module for hebrew strongs */ + StrongsGreek, /**< Module for greek strongs */ + Unknown /**< Unknown */ + }; + + /** Turn a hyperlink into module, key and type. + * Decodes the given hyperlink into module, key and type. + * @param hyperlink The hyperlink to decode + * @param module The string which will contain the module name after decoding + * @param key The string which will contain the key after decoding + * @param type The type param will contain the reference type after decoding + */ + static bool decodeHyperlink( const QString& hyperlink, QString& module, QString& key, Type& type); + /** + * Returns a hyperlink used to be embedded in the display windows. + * At the moment the format is sword://module/key + * @param module The module which is used to encode the hyperlink + * @param key The key which is used to encode the hyperlink + * @param type The type which is used to encode the hyperlink + * @return The encoded hyperlink + */ + static const QString encodeHyperlink( const QString module, const QString key, const Type type); + /** + * Puts a module Name and a Reference together in the 'draggable' form + * (module)reference + * @param module The name of the module + * @param reference The key reference as text + * @return The encoded reference using module and reference + * @author Martin Gruner + */ + static const QString encodeReference(const QString &module, const QString &reference); + /** + * decodes a 'draggable' reference into a modulename and a reference + * @author Martin Gruner + */ + static void decodeReference(QString &dragreference, QString &module, QString &reference); + /** + * Returns true if the parameter is a hyperlink. + * @param hyperlink The string which is tested + * @return True if the passed string is a hyperlink + */ + static bool isHyperlink( const QString& hyperlink ); + /** + * Returns the preferred module name for the given type. + * @param type The type which is used to find the module + * @return The default module name for the passed type + */ + static const QString preferredModule( const Type type ); + /** + * Returns the type of the passed module type + * @param type The CSwordModuleInfo module typpe + * @return The ReferenceManager type + */ + static CReferenceManager::Type typeFromModule( const CSwordModuleInfo::ModuleType type ); + + + struct ParseOptions { + QString refDestinationModule; + QString refBase; /* only valid for verse based destination modules*/ + QString sourceLanguage; /* only valid for verse based destination modules*/ + QString destinationLanguage; /* only valid for verse based destination modules*/ + + ParseOptions() { + destinationLanguage = "en"; + }; + }; + + /** Parses the given verse references using the given language and the module. + * @param moduleName The name of the module to use. Required for the language checking before parsing the key. + * @param ref The verse reference. + * @param lang The language of the verse reference + * @param newLang The language of the reference, which will be returned. For example: If BibleTime using an english environment parses a spanish ref (lang=es) the returned ref should be in english (newLang=en), because his english standard module only understands en. + */ + static const QString parseVerseReference( const QString& ref, const ParseOptions& options); +}; + +#endif + diff --git a/src/backend/managers/cswordbackend.cpp b/src/backend/managers/cswordbackend.cpp new file mode 100644 index 0000000..0afe467 --- /dev/null +++ b/src/backend/managers/cswordbackend.cpp @@ -0,0 +1,555 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#include "cswordbackend.h" + +#include "backend/rendering/centrydisplay.h" +#include "backend/rendering/cbookdisplay.h" +#include "backend/rendering/cchapterdisplay.h" +#include "backend/drivers/cswordbiblemoduleinfo.h" +#include "backend/drivers/cswordcommentarymoduleinfo.h" +#include "backend/drivers/cswordlexiconmoduleinfo.h" +#include "backend/drivers/cswordbookmoduleinfo.h" +#include "backend/filters/bt_thmlhtml.h" +#include "backend/filters/bt_thmlplain.h" +#include "backend/filters/bt_osishtml.h" +#include "backend/filters/bt_gbfhtml.h" +#include "backend/filters/bt_plainhtml.h" +#include "backend/filters/osismorphsegmentation.h" + +#include "backend/config/cbtconfig.h" + +#include "util/directoryutil.h" + +#include <dirent.h> + +//Qt +#include <QString> +#include <QDir> +#include <QFileInfo> +#include <QSet> +#include <QDebug> + +//Sword +#include <swdisp.h> +#include <swfiltermgr.h> +#include <encfiltmgr.h> +#include <rtfhtml.h> +#include <filemgr.h> +#include <utilstr.h> +#include <swfilter.h> + +using namespace Filters; +using namespace Rendering; + +CSwordBackend::CSwordBackend() + : sword::SWMgr(0, 0, false, new sword::EncodingFilterMgr( sword::ENC_UTF8 ), true) +{ + m_filters.gbf = new BT_GBFHTML(); + m_filters.plain = new BT_PLAINHTML(); + m_filters.thml = new BT_ThMLHTML(); + m_filters.osis = new BT_OSISHTML(); + + m_displays.entry = new CEntryDisplay(); + m_displays.chapter = new CChapterDisplay(); + m_displays.book = new CBookDisplay(); + + filterInit(); +} + +CSwordBackend::CSwordBackend(const QString& path, const bool augmentHome) + : sword::SWMgr(!path.isEmpty() ? path.toLocal8Bit().constData() : 0, false, new sword::EncodingFilterMgr( sword::ENC_UTF8 ), false, augmentHome) // don't allow module renaming, because we load from a path +{ + m_filters.gbf = new BT_GBFHTML(); + m_filters.plain = new BT_PLAINHTML(); + m_filters.thml = new BT_ThMLHTML(); + m_filters.osis = new BT_OSISHTML(); + + m_displays.entry = new CEntryDisplay(); + m_displays.chapter = new CChapterDisplay(); + m_displays.book = new CBookDisplay(); + + filterInit(); +} + +CSwordBackend::~CSwordBackend() { + shutdownModules(); + + delete m_filters.gbf; + delete m_filters.plain; + delete m_filters.thml; + delete m_filters.osis; + + delete m_displays.book; + delete m_displays.chapter; + delete m_displays.entry; +} + +void CSwordBackend::filterInit() { + //HACK: replace Sword's OSISMorphSegmentation filter, seems to be buggy, ours works + if (sword::SWOptionFilter* filter = optionFilters["OSISMorphSegmentation"]) + { + cleanupFilters.remove(filter); + optionFilters.erase("OSISMorphSegmentation"); + delete filter; + } + sword::SWOptionFilter* tmpFilter = new OSISMorphSegmentation(); + optionFilters.insert(sword::OptionFilterMap::value_type("OSISMorphSegmentation", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + //HACK: replace Sword's ThML strip filter with our own version + //remove this hack as soon as Sword is fixed + cleanupFilters.remove(thmlplain); + delete thmlplain; + thmlplain = new BT_ThMLPlain(); + cleanupFilters.push_back(thmlplain); +} + +QList<CSwordModuleInfo*> CSwordBackend::takeModulesFromList(QStringList names) +{ + int numberOfRemoved = 0; + QList<CSwordModuleInfo*> list; + foreach(QString name, names) { + CSwordModuleInfo* mInfo = findModuleByName(name); + if (mInfo) { + m_moduleList.removeAll(mInfo); + ++numberOfRemoved; + list.append(mInfo); + } + } + if (numberOfRemoved > 0) + emit sigSwordSetupChanged(RemovedModules); + return list; +} + +/** Initializes the Sword modules. */ +CSwordBackend::LoadError CSwordBackend::initModules(SetupChangedReason reason) { + // qWarning("globalSwordConfigPath is %s", globalConfPath); + LoadError ret = NoError; + + shutdownModules(); //remove previous modules + m_moduleList.clear(); + + sword::ModMap::iterator end = Modules.end(); + ret = LoadError( Load() ); + + for (sword::ModMap::iterator it = Modules.begin(); it != end; it++) { + sword::SWModule* const curMod = (*it).second; + CSwordModuleInfo* newModule = 0; + + if (!strcmp(curMod->Type(), "Biblical Texts")) { + newModule = new CSwordBibleModuleInfo(curMod, this); + newModule->module()->Disp(m_displays.chapter); + } + else if (!strcmp(curMod->Type(), "Commentaries")) { + newModule = new CSwordCommentaryModuleInfo(curMod, this); + newModule->module()->Disp(m_displays.entry); + } + else if (!strcmp(curMod->Type(), "Lexicons / Dictionaries")) { + newModule = new CSwordLexiconModuleInfo(curMod, this); + newModule->module()->Disp(m_displays.entry); + } + else if (!strcmp(curMod->Type(), "Generic Books")) { + newModule = new CSwordBookModuleInfo(curMod, this); + newModule->module()->Disp(m_displays.book); + } + + if (newModule) { + //Append the new modules to our list, but only if it's supported + //The constructor of CSwordModuleInfo prints a warning on stdout + if (!newModule->hasVersion() || (newModule->minimumSwordVersion() <= sword::SWVersion::currentVersion)) { + m_moduleList.append( newModule ); + } + else + { + delete newModule; + } + } + } + + QList<CSwordModuleInfo*>::iterator end_it = m_moduleList.end(); + + foreach (CSwordModuleInfo* mod, m_moduleList) { + m_moduleDescriptionMap.insert( mod->config(CSwordModuleInfo::Description), mod->name() ); + //unlock modules if keys are present + if ( mod->isEncrypted() ) { + const QString unlockKey = CBTConfig::getModuleEncryptionKey( mod->name() ); + if (!unlockKey.isNull()) { + setCipherKey( mod->name().toUtf8().constData(), unlockKey.toUtf8().constData() ); + } + } + } + + emit sigSwordSetupChanged(reason); + return ret; +} + +void CSwordBackend::AddRenderFilters(sword::SWModule *module, sword::ConfigEntMap §ion) { + sword::SWBuf moduleDriver; + sword::SWBuf sourceformat; + sword::ConfigEntMap::iterator entry; + bool noDriver = true; + + sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (sword::SWBuf) ""; + moduleDriver = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (sword::SWBuf) ""; + + if (sourceformat == "GBF") { + module->AddRenderFilter(m_filters.gbf); + noDriver = false; + } + else if (sourceformat == "PLAIN") { + module->AddRenderFilter(m_filters.plain); + noDriver = false; + } + else if (sourceformat == "ThML") { + module->AddRenderFilter(m_filters.thml); + noDriver = false; + } + else if (sourceformat == "OSIS") { + module->AddRenderFilter(m_filters.osis); + noDriver = false; + } + + if (noDriver) { //no driver found + if ( (moduleDriver == "RawCom") || (moduleDriver == "RawLD") ) { + module->AddRenderFilter(m_filters.plain); + noDriver = false; + } + } +} + +/** This function deinitializes the modules and deletes them. */ +bool CSwordBackend::shutdownModules() { + QList<CSwordModuleInfo*>::iterator it = m_moduleList.begin(); + QList<CSwordModuleInfo*>::iterator end = m_moduleList.end(); + + while (it != end) { + CSwordModuleInfo* current = (*it); + it = m_moduleList.erase(it); + delete current; + } + + Q_ASSERT(m_moduleList.count() == 0); + //BT mods are deleted now, delete Sword mods, too. + DeleteMods(); + + /* Cipher filters must be handled specially, because SWMgr creates them, + * stores them in cipherFilters and cleanupFilters and attaches them to locked + * modules. If these modules are removed, the filters need to be removed as well, + * so that they are re-created for the new module objects. + */ + sword::FilterMap::iterator cipher_it; + for (cipher_it = cipherFilters.begin(); cipher_it != cipherFilters.end(); cipher_it++) + { + //Delete the Filter and remove it from the cleanup list + cleanupFilters.remove(cipher_it->second); + delete cipher_it->second; + } + cipherFilters.clear(); + + return true; +} + +void CSwordBackend::setOption( const CSwordModuleInfo::FilterTypes type, const int state ) { + sword::SWBuf value; + + switch (type) { + + case CSwordModuleInfo::textualVariants: + + if (state == 0) { + value = "Primary Reading"; + } + else if (state == 1) { + value = "Secondary Reading"; + } + else { + value = "All Readings"; + } + + break; + + default: + value = state ? "On": "Off"; + break; + }; + + if (value.length()) + setGlobalOption(optionName(type).toUtf8().constData(), value.c_str()); +} + +void CSwordBackend::setFilterOptions( const CSwordBackend::FilterOptions options) { + setOption( CSwordModuleInfo::footnotes, options.footnotes ); + setOption( CSwordModuleInfo::strongNumbers, options.strongNumbers ); + setOption( CSwordModuleInfo::headings, options.headings ); + setOption( CSwordModuleInfo::morphTags, options.morphTags ); + setOption( CSwordModuleInfo::lemmas, options.lemmas ); + setOption( CSwordModuleInfo::hebrewPoints, options.hebrewPoints ); + setOption( CSwordModuleInfo::hebrewCantillation, options.hebrewCantillation ); + setOption( CSwordModuleInfo::greekAccents, options.greekAccents ); + setOption( CSwordModuleInfo::redLetterWords, options.redLetterWords ); + setOption( CSwordModuleInfo::textualVariants, options.textualVariants ); + setOption( CSwordModuleInfo::morphSegmentation, options.morphSegmentation ); + // setOption( CSwordModuleInfo::transliteration, options.transliteration ); + setOption( CSwordModuleInfo::scriptureReferences, options.scriptureReferences); +} + +/** This function searches for a module with the specified description */ +CSwordModuleInfo* CSwordBackend::findModuleByDescription(const QString& description) { + foreach(CSwordModuleInfo* mod, m_moduleList) { + if (mod->config(CSwordModuleInfo::Description) == description) return mod; + } + return 0; +} + +/** This function searches for a module with the specified description */ +const QString CSwordBackend::findModuleNameByDescription(const QString& description) { + if (m_moduleDescriptionMap.contains(description)) { + return m_moduleDescriptionMap[description]; + } + return QString::null; +} + +/** This function searches for a module with the specified name */ +CSwordModuleInfo* CSwordBackend::findModuleByName(const QString& name) { + foreach(CSwordModuleInfo* mod, m_moduleList) { + if (mod->name() == name) return mod; + } + return 0; +} + +CSwordModuleInfo* CSwordBackend::findSwordModuleByPointer(const sword::SWModule* const swmodule) { + foreach(CSwordModuleInfo* mod, m_moduleList) { + if (mod->module() == swmodule ) return mod; + } + return 0; +} + +CSwordModuleInfo* CSwordBackend::findModuleByPointer(const CSwordModuleInfo* const module) { + foreach(CSwordModuleInfo* mod, m_moduleList) { + if (mod == module) return mod; + } + return 0; +} + +/** Returns our local config object to store the cipher keys etc. locally for each user. The values of the config are merged with the global config. */ +bool CSwordBackend::moduleConfig(const QString& module, sword::SWConfig& moduleConfig) { + sword::SectionMap::iterator section; + DIR *dir = opendir(configPath); + + struct dirent *ent; + + bool foundConfig = false; + QString modFile; + + if (dir) { // find and update .conf file + rewinddir(dir); + + while ((ent = readdir(dir)) && !foundConfig) { + if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { + modFile = QString(configPath); + modFile.append("/"); + modFile.append( QString::fromLocal8Bit(ent->d_name) ); + + moduleConfig = sword::SWConfig( modFile.toLocal8Bit().constData() ); + section = moduleConfig.Sections.find( module.toLocal8Bit().constData() ); + foundConfig = ( section != moduleConfig.Sections.end() ); + } + } + + closedir(dir); + } + else { //try to read mods.conf + moduleConfig = sword::SWConfig("");//global config + section = config->Sections.find( module.toLocal8Bit().constData() ); + foundConfig = ( section != config->Sections.end() ); + + sword::ConfigEntMap::iterator entry; + + if (foundConfig) { //copy module section + + for (entry = section->second.begin(); entry != section->second.end(); entry++) { + moduleConfig.Sections[section->first].insert(sword::ConfigEntMap::value_type(entry->first, entry->second)); + } + } + } + + if (!foundConfig && configType != 2) { //search in $HOME/.sword/ + + QString myPath = util::filesystem::DirectoryUtil::getUserHomeDir().absolutePath(); + myPath.append("/.sword/mods.d"); + dir = opendir(myPath.toUtf8().constData()); + + if (dir) { + rewinddir(dir); + + while ((ent = readdir(dir)) && !foundConfig) { + if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { + modFile = myPath; + modFile.append('/'); + modFile.append(ent->d_name); + moduleConfig = sword::SWConfig( modFile.toLocal8Bit().constData() ); + section = moduleConfig.Sections.find( module.toLocal8Bit().constData() ); + foundConfig = ( section != moduleConfig.Sections.end() ); + } + } + + closedir(dir); + } + } + + return foundConfig; +} + +/** Returns the text used for the option given as parameter. */ +const QString CSwordBackend::optionName( const CSwordModuleInfo::FilterTypes option ) { + switch (option) { + case CSwordModuleInfo::footnotes: return QString("Footnotes"); + case CSwordModuleInfo::strongNumbers: return QString("Strong's Numbers"); + case CSwordModuleInfo::headings: return QString("Headings"); + case CSwordModuleInfo::morphTags: return QString("Morphological Tags"); + case CSwordModuleInfo::lemmas: return QString("Lemmas"); + case CSwordModuleInfo::hebrewPoints: return QString("Hebrew Vowel Points"); + case CSwordModuleInfo::hebrewCantillation: return QString("Hebrew Cantillation"); + case CSwordModuleInfo::greekAccents: return QString("Greek Accents"); + case CSwordModuleInfo::redLetterWords: return QString("Words of Christ in Red"); + case CSwordModuleInfo::textualVariants: return QString("Textual Variants"); + case CSwordModuleInfo::scriptureReferences: return QString("Cross-references"); + case CSwordModuleInfo::morphSegmentation: return QString("Morph Segmentation"); + } + return QString::null; +} + +/** Returns the translated name of the option given as parameter. */ +const QString CSwordBackend::translatedOptionName(const CSwordModuleInfo::FilterTypes option) { + switch (option) { + case CSwordModuleInfo::footnotes: return QObject::tr("Footnotes"); + case CSwordModuleInfo::strongNumbers: return QObject::tr("Strong's numbers"); + case CSwordModuleInfo::headings: return QObject::tr("Headings"); + case CSwordModuleInfo::morphTags: return QObject::tr("Morphological tags"); + case CSwordModuleInfo::lemmas: return QObject::tr("Lemmas"); + case CSwordModuleInfo::hebrewPoints: return QObject::tr("Hebrew vowel points"); + case CSwordModuleInfo::hebrewCantillation: return QObject::tr("Hebrew cantillation marks"); + case CSwordModuleInfo::greekAccents: return QObject::tr("Greek accents"); + case CSwordModuleInfo::redLetterWords: return QObject::tr("Red letter words"); + case CSwordModuleInfo::textualVariants: return QObject::tr("Textual variants"); + case CSwordModuleInfo::scriptureReferences: return QObject::tr("Scripture cross-references"); + case CSwordModuleInfo::morphSegmentation: return QObject::tr("Morph segmentation"); + } + return QString::null; +} + + +const QString CSwordBackend::configOptionName( const CSwordModuleInfo::FilterTypes option ) { + switch (option) { + case CSwordModuleInfo::footnotes: return QString("Footnotes"); + case CSwordModuleInfo::strongNumbers: return QString("Strongs"); + case CSwordModuleInfo::headings: return QString("Headings"); + case CSwordModuleInfo::morphTags: return QString("Morph"); + case CSwordModuleInfo::lemmas: return QString("Lemma"); + case CSwordModuleInfo::hebrewPoints: return QString("HebrewPoints"); + case CSwordModuleInfo::hebrewCantillation: return QString("Cantillation"); + case CSwordModuleInfo::greekAccents: return QString("GreekAccents"); + case CSwordModuleInfo::redLetterWords: return QString("RedLetterWords"); + case CSwordModuleInfo::textualVariants: return QString("Variants"); + case CSwordModuleInfo::scriptureReferences: return QString("Scripref"); + case CSwordModuleInfo::morphSegmentation: return QString("MorphSegmentation"); + } + return QString::null; +} + +const QString CSwordBackend::booknameLanguage( const QString& language ) { + if (!language.isEmpty()) { + sword::LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName( language.toUtf8().constData() ); + + //refresh the locale of all Bible and commentary modules! + //use what sword returns, language may be different + QString newLocaleName( sword::LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName() ); + + foreach(CSwordModuleInfo* mod, m_moduleList) { + if ( (mod->type() == CSwordModuleInfo::Bible) || (mod->type() == CSwordModuleInfo::Commentary) ) { + //Create a new key, it will get the default bookname language + ((sword::VerseKey*)(mod->module()->getKey()))->setLocale( newLocaleName.toUtf8().constData() ); + } + } + + } + return QString( sword::LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName() ); +} + + +/** Reload all Sword modules. */ +void CSwordBackend::reloadModules(SetupChangedReason reason) { + shutdownModules(); + + //delete Sword's config to make Sword reload it! + + if (myconfig) { // force reload on config object because we may have changed the paths + delete myconfig; + config = myconfig = 0; + // we need to call findConfig to make sure that augPaths are reloaded +#ifdef SWORD_SYSCONF_CHANGED + findConfig(&configType, &prefixPath, &configPath, &augPaths, &sysConfig); +#else + findConfig(&configType, &prefixPath, &configPath, &augPaths, sysconfig); +#endif + // now re-read module configuration files + loadConfigDir(configPath); + } + else if (config) { + config->Load(); + } + + initModules(reason); +} + +const QStringList CSwordBackend::swordDirList() { + QSet<QString> ret; + const QString home = util::filesystem::DirectoryUtil::getUserHomeDir().absolutePath(); + + //return a list of used Sword dirs. Useful for the installer + QString configPath = QString("%1/.sword/sword.conf").arg(home); + + if (!QFile(configPath).exists()) { + configPath = globalConfPath; //e.g. /etc/sword.conf, /usr/local/etc/sword.conf + } + + QStringList configs = configPath.split(":"); + + for (QStringList::const_iterator it = configs.begin(); it != configs.end(); ++it) { + if (!QFileInfo(*it).exists()) { + continue; + } + + //get all DataPath and AugmentPath entries from the config file and add them to the list + sword::SWConfig conf( (*it).toUtf8().constData() ); + ret << conf["Install"]["DataPath"].c_str(); + sword::ConfigEntMap group = conf["Install"]; + sword::ConfigEntMap::iterator start = group.equal_range("AugmentPath").first; + sword::ConfigEntMap::iterator end = group.equal_range("AugmentPath").second; + + for (sword::ConfigEntMap::const_iterator it = start; it != end; ++it) { + ret << QDir(it->second.c_str()).absolutePath(); //added augment path + } + } + + if (!home.isEmpty()) { + // This is added to the set if not there already. Notice that + // this prevents duplication only if the QDir::absolutePath() returns + // string without the prepended "/". + ret << home + "/.sword"; + } + + return ret.values(); +} + +void CSwordBackend::notifyChange(SetupChangedReason reason) +{ + emit sigSwordSetupChanged(reason); +} diff --git a/src/backend/managers/cswordbackend.h b/src/backend/managers/cswordbackend.h new file mode 100644 index 0000000..0ffb484 --- /dev/null +++ b/src/backend/managers/cswordbackend.h @@ -0,0 +1,273 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +#ifndef CSWORDBACKEND_H +#define CSWORDBACKEND_H + +//BibleTime includes +#include "backend/drivers/cswordmoduleinfo.h" + +//Qt includes +#include <QObject> +#include <QMap> +#include <QString> +#include <QStringList> + +//Sword includes +#include <swmgr.h> +#include <swbuf.h> +#include <swmodule.h> +#include <swversion.h> +#include <localemgr.h> +#include <utilstr.h> + +//forward declarations +namespace Rendering { + class CEntryDisplay; + class CChapterDisplay; + class CBookDisplay; +} + +/** The backend layer main class. + * This is the implementation of CBackend for Sword. It's additionally derived from SWMgr + * to provide functions of Sword. + * + * @short The backend implementation of Sword + * @author The BibleTime team + * @version $Id: cswordbackend.h,v 1.58 2007/03/14 21:32:47 joachim Exp $ + */ + +class CSwordBackend : public QObject, public sword::SWMgr +{ + Q_OBJECT +public: + + /** The reason for the sigSwordSetupChanged signal, i.e. why the module list has changed. */ + enum SetupChangedReason { + AddedModules = 1, + RemovedModules = 2, + HidedModules = 4, + PathChanged = 8, + OtherChange = 16 + }; + + /** Filter options. Filter options to + * control the text display of modules. Uses int and not bool because not all + * options have just two toggle values. + */ + struct FilterOptions { + int footnotes; /**< 0 for disabled, 1 for enabled */ + int strongNumbers; /**< 0 for disabled, 1 for enabled */ + int headings; /**< 0 for disabled, 1 for enabled */ + int morphTags; /**< 0 for disabled, 1 for enabled */ + int lemmas; /**< 0 for disabled, 1 for enabled */ + int hebrewPoints; /**< 0 for disabled, 1 for enabled */ + int hebrewCantillation; /**< 0 for disabled, 1 for enabled */ + int greekAccents; /**< 0 for disabled, 1 for enabled */ + int textualVariants; /**< Number n to enabled the n-th variant */ + int redLetterWords; /**< 0 for disabled, 1 for enabled */ + int scriptureReferences; /**< 0 for disabled, 1 for enabled */ + int morphSegmentation; /**< 0 for disabled, 1 for enabled */ + }; + + /** Control the display of a text. + */ + struct DisplayOptions { + int lineBreaks; + int verseNumbers; + }; + + /** The error codes which may be returned by the @ref Load() call. + */ + enum LoadError { // the values exist to cast from the char return of SWMgr::Load + NoSwordConfig = -1, + NoError = 0, + NoModules = 1 + }; + /** + * The constructor of the Sword backend. + * It creates the SWModule objects using SWMgr's methods, it adds the necessary + * filters for the module format. + */ + CSwordBackend(); + /** + * The constructor of the Sword backend. This is actually used nowhere. + * Notice that using augmentHome=false can mess up the system because it is true elsewhere. + * @param path The path which is used to load modules + * @param augmentHome True if the $HOME/.sword/ modules should be augmented with the other modules + */ + CSwordBackend( const QString& path, const bool augmentHome = true ); + + /** + * The destrctor of this backend. This function shuts the modules down using @ref shutdownModules. + */ + virtual ~CSwordBackend(); + + /** + * This function returns the list of available modules managed by this backend. + * You have to call initModules() first; + * + * @return The list of modules managed by this backend + */ + inline virtual QList<CSwordModuleInfo*>& moduleList(); + /** + * Initializes the Sword modules. + * + * @return True if the initializiation was succesful, otherwise return false. + */ + virtual CSwordBackend::LoadError initModules(SetupChangedReason reason); + /** + * This function deinitializes the modules and deletes them. + * + * @return True if it was succesful, otherwise return false + */ + virtual bool shutdownModules(); + /** + * Sets the given options enabled or disabled depending on the second parameter. + * + * @param type This is the type this function should set enabled or disabled + * @param enable If this is true the option will be enabled, otherwise it will be disabled. + */ + void setOption( const CSwordModuleInfo::FilterTypes type, const int state ); + /** */ + void setFilterOptions( const CSwordBackend::FilterOptions options ); + /** + * Sets the language for the international booknames of Sword. + * @param langName The abbreviation string which should be used for the Sword backend + */ + const QString booknameLanguage( const QString& langName = QString::null ); + /** + * This function searches for a module with the specified description + * @param description The description of the desired module + * @return pointer to the desired module; null if no module has the specified description + */ + virtual CSwordModuleInfo* findModuleByDescription(const QString& description); + /** + * This function searches for a module with the specified description + * @param description The description of the desired module + * @return pointer to the desired module; null if no module has the specified description + */ + const QString findModuleNameByDescription(const QString& description); + /** + * This function searches for a module with the specified name + * @param name The name of the desired module + * @return Pointer to the desired module; null if no module has the specified name + */ + CSwordModuleInfo* findModuleByName(const QString& name); + /** + * This function searches for a module with the specified sword module as module() object! + * @param swmodule to a Sword module + * @return pointer to the desired module; null if no module has the specified name + */ + CSwordModuleInfo* findSwordModuleByPointer(const sword::SWModule* const swmodule); + /** + * This function searches for a module which is the same as the passed module. + * @param module The module which should be used for searching the new one. May be child of a different backend. + * @return Pointer to the desired module; null if no module has the specified name + */ + CSwordModuleInfo* findModuleByPointer(const CSwordModuleInfo* const module); + /** + * @return Our global config object which contains the configs of all modules merged together. + */ + inline sword::SWConfig* getConfig() const; + /** + * Tries to find the config object for the module. The second paramter will be the found config. + * @return True if the config was found, false if not. If false is returned the moduleConfig object is in undefined/unknwon state. + */ + bool moduleConfig(const QString& module, sword::SWConfig& moduleConfig ); + /** + * Returns the text used for the option given as parameter. + * @param The paramter enum + * @return The name of the option given by the parameter + */ + static const QString optionName( const CSwordModuleInfo::FilterTypes option ); + /** + * Returns the text used for the option given as parameter. + */ + static const QString configOptionName( const CSwordModuleInfo::FilterTypes option ); + /** + * Returns the translated name of the option given as parameter. + * @param The translated option name + */ + static const QString translatedOptionName(const CSwordModuleInfo::FilterTypes option ); + /** + * Returns the version of the Sword library. + * @return The version used by this backend + */ + inline virtual const sword::SWVersion Version(); + /** + * Reload all Sword modules. + */ + void reloadModules(SetupChangedReason reason); + + /** + * Takes off the given modules from the list and returns them. + * User must take care of the deletion of the returned CSwordModuleInfo pointers. + */ + QList<CSwordModuleInfo*> takeModulesFromList(QStringList names); + + /** Sword prefix list. + * @return A list of all known Sword prefix dirs + */ + const QStringList swordDirList(); + + /** Emits the sigSwordSetupChanged signal. + * This can be called directly from outside if there is no need to reload the backend. + */ + void notifyChange(SetupChangedReason reason); + +signals: + void sigSwordSetupChanged(CSwordBackend::SetupChangedReason reason); + +protected: + /** + * Adds a render filter to the module. + * This is used to apply our own render filters to our modules instead of the sword filters + */ + virtual void AddRenderFilters(sword::SWModule *module, sword::ConfigEntMap §ion); + /** + * Overrides Sword filters which appear to be buggy. + */ + virtual void filterInit(); + +private: + // Filters + struct Filters { + sword::SWFilter* gbf; + sword::SWFilter* plain; + sword::SWFilter* thml; + sword::SWFilter* osis; + } m_filters; + + struct Displays { + Rendering::CChapterDisplay* chapter; + Rendering::CEntryDisplay* entry; + Rendering::CBookDisplay* book; + } m_displays; + + QList<CSwordModuleInfo*> m_moduleList; + QMap<QString, QString> m_moduleDescriptionMap; +}; + +/**Returns The list of modules managed by this backend*/ +inline QList<CSwordModuleInfo*>& CSwordBackend::moduleList() { + return m_moduleList; +} + +/** Returns our local config object to store the cipher keys etc. locally for each user. The values of the config are merged with the global config. */ +inline sword::SWConfig* CSwordBackend::getConfig() const { + return config; +} + +/** Returns the version of the Sword library. */ +inline const sword::SWVersion CSwordBackend::Version() { + return sword::SWVersion::currentVersion; +} + +#endif |