/*************************************************************************** File: renderer.cpp Project: Kio-Sword -- An ioslave for SWORD and KDE Copyright: Copyright (C) 2004-2005 Luke Plant ***************************************************************************/ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ // Mine #include "renderer.h" #include "swordoptions.h" #include "ks_osishtml.h" #include "ks_gbfhtml.h" #include "ks_thmlhtml.h" #include "utils.h" #include "swordutils.h" #include "template.h" // Sword #include #include #include #include #include #include #include #include #include #include // KDE #include // QT #include #include // Standard C/C++ #include #include #include using std::string; using std::vector; using std::set; using std::list; using namespace sword; namespace KioSword { static const TQString prev("
  • « %1"); static TQString makePrevLink(const TQString& caption, const TQString& url) { return prev.arg(caption).arg(url); } static const TQString next("
  • %1 »"); static TQString makeNextLink(const TQString& caption, const TQString& url) { return next.arg(caption).arg(url); } static const TQString treeup("
  • %1 %2"); static TQString makeTreeUpLink(const TQString& caption1, const TQString& caption2, const TQString& url) { return treeup.arg(caption1).arg(caption2).arg(url); } static const TQString bibleup("
  • %1"); static TQString makeBibleUpLink(const TQString& caption, const TQString& url) { return bibleup.arg(caption).arg(url); } static const TQString genlink("
  • %1"); static TQString makeGeneralLink(const TQString& caption, const TQString& url) { return genlink.arg(caption).arg(url); } Renderer::Renderer() : sword::SWMgr(0, 0, true, new sword::EncodingFilterMgr(sword::ENC_UTF8)), m_osisfilter(0), m_gbffilter(0), m_thmlfilter(0), m_plainfilter(0), m_rtffilter(0) { for (int i = 0; i < NUM_MODULE_TYPES; i++) { m_moduleTypes.push_back(""); m_moduleTypeNames.push_back(TQString("")); } m_moduleTypes[BIBLE] = "Biblical Texts"; m_moduleTypes[COMMENTARY] = "Commentaries"; m_moduleTypes[LEXDICT] = "Lexicons / Dictionaries"; m_moduleTypes[GENERIC] = "Generic Books"; m_moduleTypeNames[BIBLE] = i18n("Bibles"); m_moduleTypeNames[COMMENTARY] = i18n("Commentaries"); m_moduleTypeNames[LEXDICT] = i18n("Lexicons & Dictionaries"); m_moduleTypeNames[GENERIC] = i18n("Other Books"); } Renderer::~Renderer() { delete m_osisfilter; delete m_gbffilter; delete m_thmlfilter; delete m_plainfilter; delete m_rtffilter; } void Renderer::setOptions(const SwordOptions& options) { setGlobalOption("Footnotes", (options.footnotes() ? "On" : "Off")); setGlobalOption("Headings", (options.headings() ? "On" : "Off")); setGlobalOption("Strong's Numbers", (options.strongs() ? "On" : "Off")); setGlobalOption("Morphological Tags", (options.morph() ? "On" : "Off")); setGlobalOption("Hebrew Cantillation", (options.cantillation() ? "On" : "Off")); setGlobalOption("Hebrew Vowel Points", (options.hebrewVowelPoints() ? "On" : "Off")); setGlobalOption("Greek Accents", (options.greekAccents() ? "On" : "Off")); setGlobalOption("Lemmas", (options.lemmas() ? "On" : "Off")); setGlobalOption("Cross-references", (options.crossRefs() ? "On" : "Off")); setGlobalOption("Words of Christ in Red",(options.redWords() ? "On" : "Off")); if (options.variants() == -1) setGlobalOption("Variants", "All Readings"); else if (options.variants() == 1) setGlobalOption("Variants", "Secondary Readings"); else setGlobalOption("Variants", "Primary Readings"); LocaleMgr::getSystemLocaleMgr()->setDefaultLocaleName(options.locale()); } /** Return an HTML hyperlinked list of all modules, * categorised, and including descriptions */ TQString Renderer::listModules(const SwordOptions &options) { TQString output; TQString temp; ModMap::iterator it; vector::size_type i; SWModule *curMod; setOptions(options); if (Modules.empty()) { output += ("

    " + i18n("No modules installed!") + "

    \n"); return output; } output += TQString("

    %1

    ") .arg(i18n("Modules")); for (i = 0; i < m_moduleTypes.size(); i++) { output += TQString("

    %1

    \n" "
      \n").arg(m_moduleTypeNames[i]); for (it = Modules.begin(); it != Modules.end(); it++) { curMod = (*it).second; if (!strcmp(curMod->Type(), m_moduleTypes[i])) { output += TQString("
    • %1 : %2\n") .arg(curMod->Name()) .arg(curMod->Description()) .arg(swordUrl(curMod->Name(), options)); } } output += "
    "; } output += "
    "; return output; } /** Return a sorted list of all module names * */ TQStringList Renderer::moduleList() { TQStringList output; ModMap::iterator it; SWModule *curMod; for (it = Modules.begin(); it != Modules.end(); it++) { curMod = (*it).second; output += TQString(curMod->Name()); } output.sort(); return output; } Renderer::ModuleType Renderer::getModuleType(sword::SWModule *module) { ModuleType modtype; vector::size_type i; modtype = GENERIC; // default for (i = 0; i < m_moduleTypes.size(); i++) { if (!strcmp(module->Type(), m_moduleTypes[i])) { modtype = (ModuleType)i; break; } } return modtype; } /** Add the relevant filter to a module * * This method checks to see whether we've already added * the Render filter to a module. If so, then don't * create or attach another, but ensure the options used * */ void Renderer::setModuleFilter(SWModule *module, const SwordOptions* options) { SectionMap::iterator sit; ConfigEntMap::iterator eit; SWTextMarkup modformat = FMT_UNKNOWN; SWBuf encoding; SWFilter *filter = 0; if (m_modset.find(module) != m_modset.end()) // already added return; // From corediatheke.cpp if ((sit = config->Sections.find(module->Name())) != config->Sections.end()) { if ((eit = (*sit).second.find("SourceType")) != (*sit).second.end()) { if (!strcasecmp((char *)(*eit).second.c_str(), "GBF")) modformat = FMT_GBF; else if (!strcasecmp((char *)(*eit).second.c_str(), "ThML")) modformat = FMT_THML; else if (!strcasecmp((char *)(*eit).second.c_str(), "OSIS")) modformat = FMT_OSIS; } // FIXME - do something with this if ((eit = (*sit).second.find("Encoding")) != (*sit).second.end()) encoding = (*eit).second; else encoding = (SWBuf)""; } switch (modformat) { // TODO - all filters used should subclass // FilterBase and know how to write // KioSword urls correctly using SwordOptions case FMT_UNKNOWN : case FMT_PLAIN : if (!m_plainfilter) m_plainfilter = new PLAINHTML(); filter = m_plainfilter; break; case FMT_THML : if (!m_thmlfilter) m_thmlfilter = new ThMLHTML(); m_thmlfilter->setSwordOptions(options); filter = m_thmlfilter; break; case FMT_GBF: if (!m_gbffilter) m_gbffilter = new GBFHTML(); m_gbffilter->setSwordOptions(options); filter = m_gbffilter; break; case FMT_HTML: break; case FMT_HTMLHREF: break; case FMT_RTF: if (!m_rtffilter) m_rtffilter = new RTFHTML(); filter = m_rtffilter; break; case FMT_OSIS: if (!m_osisfilter) m_osisfilter = new OSISHTML(); m_osisfilter->setSwordOptions(options); filter = m_osisfilter; break; case FMT_WEBIF: break; default: break; } if (filter) { module->AddRenderFilter(filter); m_modset.insert(m_modset.begin(), module); } } void Renderer::moduleQuery(const TQString &modname, const TQString &ref, const SwordOptions &options, Template* tmplt) { TQString nav; SWModule *module = 0; SWKey *skey = 0; KeyType keyt = SWKEY; VerseKey *vk; TreeKey *tk; ModuleType modtype; // Set the sword::Mgr options setOptions(options); // Find the module module = getModule(modname.latin1()); if (module == 0) { TQString output; output += "

    " + i18n("The module '%1' could not be found.").arg(modname) + "


    "; output += listModules(options); tmplt->setContent(output); tmplt->setTitle(i18n("Module not found - Kio-Sword")); } else { setModuleFilter(module, &options); // Determine key type. skey = module->getKey(); if (!(vk = dynamic_cast(skey))) { if (!(tk = dynamic_cast(skey))) { keyt = SWKEY; } else { keyt = TREEKEY; } } else { keyt = VERSEKEY; } modtype = getModuleType(module); nav += TQString("
  • %1 %2
  • ") .arg(i18n("Module:")) .arg(modname) .arg(swordUrl(modname, options)); if (keyt == VERSEKEY) { // Should be just bibles and commentaries verseQuery(module, ref, options, modtype, tmplt, nav); } else if (keyt == TREEKEY) { treeQuery(module, ref, options, modtype, tmplt, nav); } else if (keyt == SWKEY) { normalQuery(module, ref, options, modtype, tmplt, nav); } tmplt->setNav("
      " + nav + "
    "); tmplt->setShowToggles(true); } return; } TQString Renderer::search(const TQString &modname, const TQString &query, const SearchType searchType, const SwordOptions &options) { SWModule *module = 0; TQString output; ListKey lk; int stype = SEARCH_WORDS; TQString stypename; ModuleType modtype; setOptions(options); // Find the module module = getModule(modname.latin1()); if (module == 0) { output += "

    " + i18n("The module '%1' could not be found.").arg(modname) + "

    "; output += listModules(options); return output; } modtype = getModuleType(module); if (searchType == SEARCH_WORDS) { stype = -2; stypename = i18n("Word"); } else if (searchType == SEARCH_PHRASE) { stype = -1; stypename = i18n("Phrase"); } else if (searchType == SEARCH_REGEX) { stype = 0; stypename = i18n("Regular expression"); } output += "

    " + i18n("Search results:") + "

    "; output += TQString("
    %1%2
    %3%4
    %5%6
    ") .arg(i18n("Module:")) .arg(modname) .arg(i18n("Query:")) .arg(query) .arg(i18n("Search type:")) .arg(stypename); lk = module->search(query.utf8(), stype, REG_ICASE); if (lk.Count() == 0) { output += "

    " +i18n("No matches returned."); } else { output += "

    " + i18n("1 match returned:", "%1 matches returned:", lk.Count()).arg(lk.Count()); output += "

      "; for (int i = 0; i < lk.Count(); ++i) { TQString ref; ref = TQString::fromUtf8(lk.getElement(i)->getText()); if (modtype == BIBLE) { module->setKey(lk.getElement(i)); output += TQString("
    • %1: %2
    • ") .arg(ref) .arg(renderText(module)) .arg(swordUrl(modname, ref, options)); } else { output += TQString("
    • %1
    • ") .arg(ref) .arg(swordUrl(modname, ref, options)); } } output += "
    "; } output += "
    "; return output; } TQString Renderer::renderText(SWModule *module) { return TQString::fromUtf8(module->RenderText()); } /** Fill in template with formatted text for the query of a verse based module * Links are appended to navlinks. */ void Renderer::verseQuery(SWModule *module, const TQString &ref, const SwordOptions &options, ModuleType modtype, Template* tmplt, TQString &navlinks) { TQString modname(module->Name()); TQString text; bool doindex = false; const char* modtextdir; // text direction of the module ListKey lk; VerseKey *vk = dynamic_cast(module->getKey()); if (!vk) return; // FIXME - why do I need this call to setLocale()? vk->setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); modtextdir = textDirection(module); vk->AutoNormalize(0); do { // dummy loop if (ref.isEmpty()) { doindex = true; break; } lk = vk->ParseVerseList(ref, "Genesis 1:1", true); if (lk.Count() == 0) { text += "

    " + i18n("Couldn't find reference '%1'.").arg(ref) + "

    "; doindex = true; break; } char book = 0; char testament = 0; int chapter = 0; bool upToBookListShown = false; for (int i = 0; i < lk.Count(); ++i) { VerseKey *element = dynamic_cast(lk.GetElement(i)); if (element) { // Multiple verses char err = 0; // Check whether we have an entire book selected // (but treat single chapter books as if they were just // one chapter from a book) if (element->UpperBound().Chapter() > 1 && isEntireBook(element) && !options.wholeBook()) { // List books and link for viewing entire book SwordOptions options_wholebook(options); options_wholebook.wholeBook.set(true); // set just for creating the URL text += TQString("

    %1

    " "

    %2

    " "

    %3

    ") .arg(element->getBookName()) .arg(i18n("Chapters:")) .arg(chapterList(modname, element, options)) + TQString("

    %1

    ") .arg(i18n("View entire book.")) .arg(swordUrl(module->Name(), element->getBookName(), options_wholebook)); if (!upToBookListShown) { navlinks += makeBibleUpLink(i18n("Books"), swordUrl(modname, options)); upToBookListShown = true; } } else { // chapter or verse range selected module->Key(element->LowerBound()); if (lk.Count() == 1) { // add some navigation links if (isSingleChapter(element)) { // get link to previous chapter module->decrement(); if (!module->Error()) { navlinks += makePrevLink(bookChapter(module->getKey()), chapterLink(modname, module->getKey(), options)); } // get link to book module->Key(element->LowerBound()); navlinks += makeBibleUpLink(bookName(element), bookLink(modname, element, options)); } else { // less than a single chapter // get link to book navlinks += makeGeneralLink(bookName(element), bookLink(modname, element, options)); // get link to chapter navlinks += makeBibleUpLink(bookChapter(element), chapterLink(modname, element, options)); } } // Headings plus text itself bool inDirectionedDiv = false; do { VerseKey *curvk = dynamic_cast(module->getKey()); if (curvk->Book() != book || curvk->Testament() != testament) { if (inDirectionedDiv) { // close it before carrying on text += ""; inDirectionedDiv = false; } text += "

    " + TQString(curvk->getBookName()) + "

    "; chapter = 0; } if (curvk->Chapter() != chapter) { if (inDirectionedDiv) { // close it before carrying on text += ""; inDirectionedDiv = false; } text += "

    " + i18n("Chapter %1").arg(curvk->Chapter()) + "

    "; } if (!inDirectionedDiv) { text += TQString("
    ").arg(modtextdir); inDirectionedDiv = true; } if (options.verseNumbers() && modtype == BIBLE) { text += TQString("%1 ") .arg(curvk->Verse()) .arg(swordUrl(module->Name(), module->KeyText(), options)); } text += renderText(module); text += " "; if (options.verseLineBreaks()) text += "
    "; book = curvk->Book(); testament = curvk->Testament(); chapter = curvk->Chapter(); module->increment(1); } while (module->Key() <= element->UpperBound() && !(err = module->Error())); // Close the final div if (inDirectionedDiv) { text += "
    "; inDirectionedDiv = false; } if (lk.Count() == 1) { if (isSingleChapter(element)) { // add some navigation links if (!err) { navlinks += makeNextLink(bookChapter(module->getKey()), chapterLink(modname, module->getKey(), options)); } } } } } else { // Reset flags used by the multiple verse path book = 0; testament = 0; chapter = 0; // Single verse module->Key(*lk.GetElement(i)); element = dynamic_cast(module->getKey()); text += TQString("

    %1

    ").arg(module->KeyText()); text += TQString("
    ").arg(modtextdir); text += renderText(module); text += "
    "; if (lk.Count() == 1) navlinks += makeBibleUpLink(bookChapter(element), chapterLink(modname, element, options)); } if (i+1 != lk.Count()) text += "
    "; } } while (false); // Title: depends on what got printed above TQString title; if (doindex) { if (!text.isEmpty()) { // an error message was printed text = TQString("

    %1

    ").arg(module->Description()).arg(ref) + text; title = "Error - Kio-Sword"; } else { title = TQString("%1 - Kio-Sword").arg(module->Name()); } } else { if (modtype == COMMENTARY) { text = TQString("

    %1

    ").arg(module->Description()) + text; title = TQString("%1 - %2 - Kio-Sword") .arg(lk.getShortText()) .arg(module->Name()); } else if (modtype == BIBLE) { text += TQString("
    (%1)
    ").arg(module->Description()); title = TQString("%1 - %2 - Kio-Sword") .arg(lk.getShortText()) .arg(module->Name()); } } tmplt->setTitle(title); if (doindex) { if (!text.isEmpty()) text += "
    \n"; if (options.doBibleIndex()) { text += "

    " + i18n("Books:") + "

    "; text += indexBible(module, options); } else { SwordOptions options_doindex(options); options_doindex.doBibleIndex.set(true); text += TQString("

    %1

    ") .arg(i18n("Index of books")) .arg(swordUrl(modname, options_doindex)); } } tmplt->setContent(text); } void Renderer::treeQuery(SWModule *module, const TQString &ref, const SwordOptions &options, ModuleType modtype, Template* tmplt, TQString &navlinks) { TQString output; TQString modname(module->Name()); bool doindex; TreeKey *tk = dynamic_cast(module->getKey()); if (!tk) return; output += TQString("

    %1

    ").arg(module->Description()); if (ref.isEmpty()) { doindex = true; } else { tk->Error(); // clear tk->setText(ref.utf8()); doindex = false; if (tk->Error()) { output += "

    " + i18n("Couldn't find section '%1'.").arg(ref) + "

    "; output += "
    "; doindex = true; } else { TQString link; output += renderText(module); if (tk->previousSibling()) { link = TQString::fromUtf8(module->KeyText()); // FIXME ? local8Bit or utf8 navlinks += makePrevLink(shorten(link.section('/', -1, -1), 20), swordUrl(modname, link, options)); tk->nextSibling(); } SWKey *saved = tk->clone(); if (tk->parent()) { link = TQString::fromUtf8(module->KeyText()); navlinks += makeTreeUpLink(i18n("Up:"), shorten(link.section('/', -1, -1), 20), swordUrl(modname, link, options)); tk->copyFrom(*saved); } delete saved; if (tk->nextSibling()) { link = TQString::fromUtf8(module->KeyText()); navlinks += makeNextLink(shorten(link.section('/', -1, -1), 20), swordUrl(modname, link, options)); tk->previousSibling(); } if (tk->hasChildren()) { if (tk->firstChild()); output += "
    "; output += indexTree(module, options, false, 1); } } } if (doindex) { output += "

    " + i18n("Contents:") + "

    "; SwordOptions options_doindex(options); if (options.doFullTreeIndex()) { options_doindex.doFullTreeIndex.set(false); output += indexTree(module, options, true, -1); output += TQString("

    %1

    ") .arg(i18n("View simple index")) .arg(swordUrl(modname, options_doindex)); } else { options_doindex.doFullTreeIndex.set(true); output += indexTree(module, options, true, 1); output += TQString("

    %1

    ") .arg(i18n("View full index")) .arg(swordUrl(modname, options_doindex)); } tmplt->setTitle(TQString("%1 - %2 - Kio-Sword").arg(tk->getShortText()).arg(module->Name())); } else { tmplt->setTitle(TQString("%1 - Kio-Sword").arg(module->Name())); } tmplt->setContent(output); } void Renderer::normalQuery(SWModule *module, const TQString &ref, const SwordOptions &options, ModuleType modtype, Template* tmplt, TQString &navlinks) { TQString output; TQString modname(module->Name()); bool doindex; SWKey *skey = module->getKey(); output += TQString("

    %1

    ").arg(module->Description()); if (ref.isEmpty()) { doindex = true; } else { skey->Error(); // clear skey->setText(ref.utf8()); doindex = false; if (skey->Error()) { output += "

    " + TQString(i18n("Couldn't find reference '%1'.")).arg(ref) + "

    "; output += "
    "; doindex = true; } else { output += TQString("

    %1

    ").arg(module->KeyText()); output += renderText(module); module->decrement(); TQString link; if (!module->Error()) { link = module->KeyText(); navlinks += makePrevLink(link, swordUrl(modname, link, options)); module->increment(); } module->increment(); if (!module->Error()) { link = module->KeyText(); navlinks += makeNextLink(link, swordUrl(modname, link, options)); module->decrement(); } } } if (doindex) { if (((modtype == LEXDICT) && options.doDictIndex()) || ((modtype == GENERIC) && options.doOtherIndex())) { output += "

    " + i18n("Index:") + "

    "; output += indexBook(module, options); } else { output += TQString("
    " "%1 " "
    ") .arg(i18n("Enter query term: ")) .arg(swordUrl(modname, options)); SwordOptions options_doindex(options); options_doindex.doDictIndex.set(true); options_doindex.doOtherIndex.set(true); output += TQString("

    %1

    ") .arg(i18n("View complete index")) .arg(swordUrl(modname, options_doindex)); } tmplt->setTitle(TQString("%1 - Kio-Sword").arg(module->Name())); } else { tmplt->setTitle(TQString("%1 - %2 - Kio-Sword").arg(skey->getShortText()).arg(module->Name())); } tmplt->setContent(output); } /** Retrieves an HTML list of all the books in the module * * @param module The module to retrieve. Must be a Bible/commentary */ TQString Renderer::indexBible(SWModule *module, const SwordOptions& options) { TQString output; char book; char testament; VerseKey *vk = dynamic_cast(module->getKey()); if (!vk) return output; vk->setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName()); module->setSkipConsecutiveLinks(true); vk->AutoNormalize(1); module->setPosition(sword::TOP); book = vk->Book(); testament = vk->Testament(); output += "
      \n"; while (vk->Testament() == testament) { while (vk->Book() == book && !module->Error()) { output += TQString("
    • %1\n") .arg(vk->getBookName()) .arg(swordUrl(module->Name(), vk->getBookName(), options)); vk->Book(++book); }; // Move to new testament, if not there already. ++testament; module->setPosition(sword::BOTTOM); book = 1; vk->Book(book); }; output += "
    \n"; module->setSkipConsecutiveLinks(false); return output; } /** Retrieves an HTML list of all the keys in a module * * @param module The module to retrieve. Must have key type SWKey */ TQString Renderer::indexBook(SWModule *module, const SwordOptions& options) { TQString output; TQString ref; module->setPosition(sword::TOP); output += "
      \n"; do { ref = TQString::fromUtf8(module->KeyText()); output += TQString("
    • %1
    • ") .arg(ref) .arg(swordUrl(module->Name(), ref, options)); (*module)++; } while(!module->Error()) ; output += "
    \n"; return output; } /** Return the index of a tree-key based module * * @param module The module to scan * @param fromTop If true, get the index from the top level * @param depth How many levels to scan, -1 for all */ TQString Renderer::indexTree(SWModule *module, const SwordOptions& options, bool fromTop, const int depth) { TQString output; TQString ref; bool gonext; bool cont; TreeKey *tk = dynamic_cast(module->getKey()); int mydepth = 1; if (!tk) return output; if (fromTop) { tk->root(); tk->firstChild(); } output += "
      "; cont = true; gonext = false; do { if (!gonext) { ref = TQString::fromUtf8(module->KeyText()); output += TQString("
    • %1\n") .arg(ref.section('/', -1)) .arg(swordUrl(module->Name(), ref, options)); } if (!gonext && tk->hasChildren() && (mydepth < depth || depth == -1) ) { if (tk->firstChild()) { mydepth++; output += "
        "; cont = true; } else { cont = false; } } else { if (tk->nextSibling()) { gonext = false; cont = true; } else { // try to go up a level cont = false; if (mydepth > 1) { if (tk->parent()) { mydepth--; output += "
      "; cont = true; gonext = true; } } } } } while (cont); output += "
    "; return output; } TQString Renderer::chapterList(const TQString &modname, const VerseKey *vk, const SwordOptions& options) { VerseKey cp(vk->LowerBound()); TQString output; do { cp.Verse(0); if (!output.isNull()) output += " | "; output += TQString("%1") .arg(cp.Chapter()) .arg(chapterLink(modname, &cp, options)); cp.Chapter(cp.Chapter()+1); } while (cp.Chapter() <= vk->UpperBound().Chapter()) ; return output; } TQString Renderer::chapterLink(const TQString &modname, const VerseKey *vk, const SwordOptions& options) { return swordUrl(modname, bookChapter(vk), options); } TQString Renderer::chapterLink(const TQString &modname, const SWKey *sk, const SwordOptions& options) { const VerseKey *vk = dynamic_cast(sk); if (vk) return chapterLink(modname, vk, options); else return TQString::null; } TQString Renderer::bookLink(const TQString &modname, const VerseKey *vk, const SwordOptions& options) { return swordUrl(modname, bookName(vk), options); } TQString Renderer::bookLink(const TQString &modname, const SWKey *sk, const SwordOptions& options) { const VerseKey *vk = dynamic_cast(sk); if (vk) return bookLink(modname, vk, options); else return TQString::null; } TQString Renderer::bookChapter(const VerseKey *vk) { return TQString("%1 %2").arg(vk->getBookName()).arg(vk->Chapter()); } TQString Renderer::bookChapter(const SWKey *sk) { const VerseKey *vk = dynamic_cast(sk); if (vk) return bookChapter(vk); else return TQString::null; } TQString Renderer::bookName(const VerseKey *vk) { return TQString(vk->getBookName()); } TQString Renderer::bookName(const SWKey *sk) { const VerseKey *vk = dynamic_cast(sk); if (vk) return bookName(vk); else return TQString::null; } TQStringList Renderer::availableLocales() { list locales = LocaleMgr::getSystemLocaleMgr()->getAvailableLocales(); list::const_iterator it; list::const_iterator it_end = locales.end(); TQStringList output; for (it = locales.begin(); it != it_end; it++) { output.append(TQString((*it).c_str())); } return output; } }