From 61a5afab1a2ab95196bb57a35d6f03ac0d16354d Mon Sep 17 00:00:00 2001 From: James Hogan Date: Sat, 1 Nov 2008 15:20:35 +0000 Subject: [PATCH] Improve sword integration and bible interface --- kworship/bible/KwBibleManagerSword.cpp | 7 +- kworship/bible/KwBibleModule.cpp | 8 ++ kworship/bible/KwBibleModule.h | 3 + kworship/bible/KwBibleModuleSword.cpp | 197 ++++++++++++++++++++++++++++----- kworship/bible/KwBibleModuleSword.h | 22 +++- kworship/kworship.cpp | 138 ++++++++++++++++++++--- kworship/kworship.h | 3 + kworship/kworshipview_base.ui | 4 +- 8 files changed, 335 insertions(+), 47 deletions(-) diff --git a/kworship/bible/KwBibleManagerSword.cpp b/kworship/bible/KwBibleManagerSword.cpp index 40585d9..330417a 100644 --- a/kworship/bible/KwBibleManagerSword.cpp +++ b/kworship/bible/KwBibleManagerSword.cpp @@ -28,6 +28,7 @@ #include #include +#include #include /* @@ -48,7 +49,11 @@ KwBibleManagerSword::KwBibleManagerSword() { sword::SWBuf modName = (*modIterator).first; sword::SWModule* module = (*modIterator).second; - m_modules[QLatin1String(modName)] = new KwBibleModuleSword(module); + sword::SWText* text = dynamic_cast(module); + if (0 != text) + { + m_modules[QLatin1String(modName)] = new KwBibleModuleSword(text); + } } } diff --git a/kworship/bible/KwBibleModule.cpp b/kworship/bible/KwBibleModule.cpp index 35efa06..3e4c6f8 100644 --- a/kworship/bible/KwBibleModule.cpp +++ b/kworship/bible/KwBibleModule.cpp @@ -56,6 +56,14 @@ KwBibleModule::Key KwBibleModule::createKey(const QString& text) } /// Create a key from individual values. +KwBibleModule::Key KwBibleModule::createKey(int book, int chapter, int verse) +{ + Key key = { { book, chapter, verse }, + { -1, -1, -1 } }; + return key; +} + +/// Create a key from individual values. KwBibleModule::Key KwBibleModule::createKey(const QString& book, int chapter, int verse) { int bookId = bookIndex(book); diff --git a/kworship/bible/KwBibleModule.h b/kworship/bible/KwBibleModule.h index 7a8632f..31b9aa1 100644 --- a/kworship/bible/KwBibleModule.h +++ b/kworship/bible/KwBibleModule.h @@ -76,6 +76,9 @@ class KwBibleModule Key createKey(const QString& text); /// Create a key from individual values. + Key createKey(int book, int chapter, int verse = -1); + + /// Create a key from individual values. Key createKey(const QString& book, int chapter, int verse = -1); /// Create a range key between two verses in the same chapter. diff --git a/kworship/bible/KwBibleModuleSword.cpp b/kworship/bible/KwBibleModuleSword.cpp index 044a523..81a7c82 100644 --- a/kworship/bible/KwBibleModuleSword.cpp +++ b/kworship/bible/KwBibleModuleSword.cpp @@ -28,6 +28,7 @@ #include #include +#include #include /* @@ -35,10 +36,11 @@ */ /// Default constructor. -KwBibleModuleSword::KwBibleModuleSword(sword::SWModule* module) +KwBibleModuleSword::KwBibleModuleSword(sword::SWText* module) : KwBibleModule() , m_module(module) { + m_hasTestament[0] = m_hasTestament[1] = -1; } /// Destructor. @@ -62,45 +64,107 @@ QString KwBibleModuleSword::description() int KwBibleModuleSword::numChapters(int book) { - return 0; + int result = 0; + int testament = bookInTestament(book); // book gets changed + if (testament >= 0) + { + sword::VerseKey key = m_module->getKey(); + result = key.books[testament][book].chapmax; + } + return result; } int KwBibleModuleSword::numVerses(int book, int chapter) { - return 0; + int result = 0; + int testament = bookInTestament(book); // book gets changed + if (testament >= 0) + { + sword::VerseKey key = m_module->getKey(); + if (chapter < key.books[testament][book].chapmax) + { + result = key.books[testament][book].versemax[chapter]; + } + } + return result; } QString KwBibleModuleSword::renderText(const KwBibleModule::Key& key) { - sword::VerseKey vkey; - vkey.LowerBound().Book(key.start.book); - vkey.LowerBound().Chapter(key.start.chapter); - vkey.LowerBound().Verse(key.start.verse); - vkey.UpperBound().Book(key.end.book); - vkey.UpperBound().Chapter(key.end.chapter); - vkey.UpperBound().Verse(key.end.verse); - QString result; - sword::VerseKey verse = vkey.LowerBound(); - verse.Headings(1); - sword::VerseKey last = vkey.UpperBound(); - Q_ASSERT(verse.isTraversable()); - - int limit = 100; - for (; verse.compare(last) <= 0; verse.increment(1)) + int startBook = key.start.book; + int endBook = key.start.book; + int startTestament = bookInTestament(startBook); // book gets changed + int endTestament = bookInTestament(endBook); // book gets changed + if (startTestament >= 0) { - m_module->setKey(&verse); - m_module->RenderText(); - const char* preverse = m_module->getEntryAttributes()["Heading"]["Preverse"]["0"]; - result += " "; - if (preverse[0] != '\0') + if (endTestament == -1) { - result += QString("

%1

").arg(QString::fromUtf8(preverse)); + endTestament = startTestament; + endBook = startBook; } - result += QString("%1").arg(verse.Verse()) + QString::fromUtf8(m_module->RenderText()); - if (0 == --limit) + int startChapter = key.start.chapter; + int endChapter = key.start.chapter; + if (startChapter < 0) { - break; + startChapter = 0; + endChapter = numChapters(toBookIndex(endTestament, endBook))-1; + } + else if (endChapter < 0) + { + endChapter = startChapter; + } + + int startVerse = key.start.verse; + int endVerse = key.start.verse; + if (startVerse < 0) + { + startVerse = 0; + endVerse = numVerses(toBookIndex(endTestament, endBook), endChapter)-1; + } + else if (endVerse < 0) + { + endVerse = startVerse; + } + + sword::VerseKey vkey; + vkey.LowerBound().Testament(1+startTestament); + vkey.LowerBound().Book(1+startBook); + vkey.LowerBound().Chapter(1+startChapter); + vkey.LowerBound().Verse(1+startVerse); + vkey.UpperBound().Testament(1+endTestament); + vkey.UpperBound().Book(1+endBook); + vkey.UpperBound().Chapter(1+endChapter); + vkey.UpperBound().Verse(1+endVerse); + //std::cout << startTestament << " " << startBook << " " << startChapter << ":" << startVerse << std::endl; + //std::cout << endTestament << " " << endBook << " " << endChapter << ":" << endVerse << std::endl; + + sword::VerseKey verse = vkey.LowerBound(); + verse.Headings(1); + sword::VerseKey last = vkey.UpperBound(); + Q_ASSERT(verse.isTraversable()); + + // verse must be before last + if (verse.compare(last) <= 0) + { + int limit = 500; + while (--limit > 0) + { + m_module->setKey(&verse); + const char* text = m_module->RenderText(); + const char* preverse = m_module->getEntryAttributes()["Heading"]["Preverse"]["0"]; + result += " "; + if (preverse[0] != '\0') + { + result += QString("

%1

").arg(QString::fromUtf8(preverse)); + } + result += QString("%1").arg(verse.Verse()) + QString::fromUtf8(text); + if (verse.equals(last)) + { + break; + } + verse.increment(1); + } } } @@ -113,6 +177,83 @@ QString KwBibleModuleSword::renderText(const KwBibleModule::Key& key) void KwBibleModuleSword::obtainBooks() { - setBooks(QStringList()); + // List books + QStringList books; + sword::VerseKey key = m_module->getKey(); + for (int testament = 0; testament < 2; ++testament) + { + if (hasTestament(testament)) + { + for (int book = 0; book < key.BMAX[testament]; ++book) + { + books << QString::fromUtf8(key.books[testament][book].name); + } + } + } + setBooks(books); +} + +/* + * Internal functions + */ + +/// Find whether the module has a given testament. +bool KwBibleModuleSword::hasTestament(int testament) +{ + Q_ASSERT(testament >= 0 && testament < 2); + if (m_hasTestament[testament] < 0) + { + bool oldSCL = m_module->getSkipConsecutiveLinks(); + m_module->setSkipConsecutiveLinks(true); + + m_module->setPosition((testament == 0) ? sword::TOP : sword::BOTTOM); + sword::VerseKey key = m_module->KeyText(); + m_hasTestament[testament] = (key.Testament() == (testament+1)) ? 1 : 0; + + m_module->setSkipConsecutiveLinks(oldSCL); + } + return m_hasTestament[testament] != 0; +} + +/// Find the index of the book within the testament. +int KwBibleModuleSword::bookInTestament(int& book) +{ + sword::VerseKey key = m_module->getKey(); + if (book >= 0) + { + // Old testament? + if (book < key.BMAX[0] && hasTestament(0)) + { + return 0; + } + // New testament with old testament? + else if ( book < key.BMAX[0]+key.BMAX[1] && hasTestament(0) && hasTestament(1)) + { + book -= key.BMAX[0]; + return 1; + } + // New testament without old testament? + else if ( book < key.BMAX[1] && !hasTestament(0) && hasTestament(1)) + { + return 1; + } + } + return -1; +} + +/// Find the book index from testament and book id. +int KwBibleModuleSword::toBookIndex(int testament, int book) +{ + Q_ASSERT(testament >= 0 && testament < 2); + if (0 == testament || !hasTestament(0)) + { + return book; + } + else + { + sword::VerseKey key = m_module->getKey(); + return key.BMAX[0] + book; + } + } diff --git a/kworship/bible/KwBibleModuleSword.h b/kworship/bible/KwBibleModuleSword.h index 85ce87a..db41e33 100644 --- a/kworship/bible/KwBibleModuleSword.h +++ b/kworship/bible/KwBibleModuleSword.h @@ -30,7 +30,7 @@ namespace sword { - class SWModule; + class SWText; } /// A SWORD bible module. @@ -43,7 +43,7 @@ class KwBibleModuleSword : public KwBibleModule */ /// Default constructor. - KwBibleModuleSword(sword::SWModule* module); + KwBibleModuleSword(sword::SWText* module); /// Destructor. virtual ~KwBibleModuleSword(); @@ -76,6 +76,19 @@ class KwBibleModuleSword : public KwBibleModule // Reimplemented virtual void obtainBooks(); + /* + * Internal functions + */ + + /// Find whether the module has a given testament. + bool hasTestament(int testament); + + /// Find the testament and index of the book within the testament. + int bookInTestament(int& book); + + /// Find the book index from testament and book id. + int toBookIndex(int testament, int book); + private: /* @@ -83,7 +96,10 @@ class KwBibleModuleSword : public KwBibleModule */ /// SWORD module object. - sword::SWModule* m_module; + sword::SWText* m_module; + + /// Whether the module has each testament. + int m_hasTestament[2]; }; #endif // _KwBibleModuleSword_h_ diff --git a/kworship/kworship.cpp b/kworship/kworship.cpp index 9265ba2..0d18e48 100644 --- a/kworship/kworship.cpp +++ b/kworship/kworship.cpp @@ -337,6 +337,8 @@ kworship::kworship() m_bibleTabs = new QTabWidget(); m_bibleTabs->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + connect(m_bibleTabs, SIGNAL(currentChanged(int)), + this, SLOT(bibleChanged())); m_view->layoutBibleTabs->addWidget(m_bibleTabs); foreach (KwBibleManager* manager, managers) @@ -349,6 +351,8 @@ kworship::kworship() QHBoxLayout* layout = new QHBoxLayout(tabWidget); mgr.comboBibles = new QComboBox(); + connect(mgr.comboBibles, SIGNAL(currentIndexChanged(int)), + this, SLOT(bibleChanged())); // Only fill the module list if the manager is local // Otherwise we should wait until the user requests it @@ -389,19 +393,12 @@ kworship::kworship() m_bibleTabs->addTab(tabWidget, name); m_bibles.push_back(mgr); } - - /* - QList modules = manager->modules(); - foreach (KwBibleModule* module, modules) - { - m_view->comboSwordBibles->addItem(i18n("%1 - %2", module->name(), module->description()), QVariant(module->name())); - } - - connect(m_view->comboSwordBibles, SIGNAL(currentIndexChanged(int)), - this, SLOT(bibleSearch())); - connect(m_view->searchBible, SIGNAL(textEdited(const QString&)), - this, SLOT(bibleSearch())); - */ + // Ensure widgets are apropriately modified + connect(m_view->comboBibleBook, SIGNAL(currentIndexChanged(int)), + this, SLOT(bibleBookChanged())); + connect(m_view->comboBibleChapter, SIGNAL(currentIndexChanged(int)), + this, SLOT(bibleChapterChanged())); + bibleChanged(); } kworship::~kworship() @@ -1087,6 +1084,121 @@ void kworship::bibleConnect() } } +void kworship::bibleChanged() +{ + // Get the current bible manager + int tab = m_bibleTabs->currentIndex(); + if (tab >= 0 && tab < m_bibles.size()) + { + BibleManager& mgr = m_bibles[tab]; + bool enabled = mgr.comboBibles->isEnabled(); + + // Is a bible selected? + QString bible = mgr.comboBibles->currentText(); + KwBibleModule* module = mgr.manager->module(bible); + + // Update the list of books + QString book = m_view->comboBibleBook->currentText(); + int chapter = m_view->comboBibleChapter->currentIndex(); + m_view->comboBibleBook->clear(); + if (0 != module) + { + QStringList bookNames = module->books(); + for (int i = 0; i < bookNames.size(); ++i) + { + const QString& bookName = bookNames[i]; + m_view->comboBibleBook->addItem(bookName, QVariant(i)); + } + int index = m_view->comboBibleBook->findText(book); + bool canPreserveBook = (index >= 0); + if (!canPreserveBook && bookNames.size() > 0) + { + index = 0; + } + m_view->comboBibleBook->setCurrentIndex(index); + if (canPreserveBook && chapter >= 0) + { + // If we can restore book, also restore chapter + m_view->comboBibleChapter->setCurrentIndex(chapter); + } + } + else + { + enabled = false; + } + + //bibleBookChanged(); + m_view->comboBibleBook->setEnabled(enabled); + m_view->comboBibleChapter->setEnabled(enabled); + m_view->searchBible->setEnabled(enabled); + m_view->textBible->setEnabled(enabled); + + m_view->searchBible->setText(QString()); + + } +} + +void kworship::bibleBookChanged() +{ + m_view->comboBibleChapter->clear(); + + // Get the current bible manager + int tab = m_bibleTabs->currentIndex(); + if (tab >= 0 && tab < m_bibles.size()) + { + BibleManager& mgr = m_bibles[tab]; + + // Is a bible selected? + QString bible = mgr.comboBibles->currentText(); + KwBibleModule* module = mgr.manager->module(bible); + if (0 != module) + { + // Is a book selected? + int index = m_view->comboBibleBook->currentIndex(); + if (index >= 0) + { + int bookIndex = m_view->comboBibleBook->itemData(index).toInt(); + int numChapters = module->numChapters(bookIndex); + for (int i = 0; i < numChapters; ++i) + { + m_view->comboBibleChapter->addItem(QString("%1").arg(i+1), QVariant(i)); + } + } + } + } +} + +void kworship::bibleChapterChanged() +{ + // Get the current bible manager + int tab = m_bibleTabs->currentIndex(); + if (tab >= 0 && tab < m_bibles.size()) + { + BibleManager& mgr = m_bibles[tab]; + + // Is a bible selected? + QString bible = mgr.comboBibles->currentText(); + KwBibleModule* module = mgr.manager->module(bible); + if (0 != module) + { + // Is a book selected? + int bookIndex = m_view->comboBibleBook->currentIndex(); + if (bookIndex >= 0) + { + // Is a chapter selected? + int chapterIndex = m_view->comboBibleChapter->currentIndex(); + if (chapterIndex >= 0) + { + KwBibleModule::Key key = module->createKey(bookIndex, chapterIndex); + m_view->textBible->document()->setHtml(module->renderText(key)); + return; + } + } + } + } + m_view->textBible->document()->setPlainText(QString()); +} + void kworship::bibleSearch() { /* diff --git a/kworship/kworship.h b/kworship/kworship.h index 12c7ee5..cbd6f1d 100644 --- a/kworship/kworship.h +++ b/kworship/kworship.h @@ -131,6 +131,9 @@ private slots: // Bibles void bibleConnect(); + void bibleChanged(); + void bibleBookChanged(); + void bibleChapterChanged(); void bibleSearch(); private: diff --git a/kworship/kworshipview_base.ui b/kworship/kworshipview_base.ui index 0c35270..4faa279 100644 --- a/kworship/kworshipview_base.ui +++ b/kworship/kworshipview_base.ui @@ -26,7 +26,7 @@ - 1 + 0 @@ -180,7 +180,7 @@ - + -- 2.11.4.GIT