/********************************************************************** ** Copyright (C) 2001 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** Licensees holding valid Qtopia Developer license may use this ** file in accordance with the Qtopia Developer License Agreement ** provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING ** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR ** PURPOSE. ** ** email sales@trolltech.com for information about Qtopia License ** Agreements. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "qpsword.h" #include #include #include "qswtextview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #undef stricmp #include #include #include #include #include #include #include "about.h" using namespace sword; /* * Constructs a Example which is a child of 'parent', with the * name 'name' and widget flags set to 'f' */ QPSword::QPSword( QWidget* parent, const char* name, WFlags fl ) : MainForm( parent, name, fl ) { QFont uniFont("unifont"); uniFont.setCharSet(QFont::Unicode); textDisplay->setFont(uniFont); // textDisplay->setDragAutoScroll(false); ldDisplay->setFont(uniFont); // ldDisplay->setDragAutoScroll(false); gbKeyLoaded = false; // connect(quit, SIGNAL(clicked()), this, SLOT(goodBye())); mgr = new sword::SWMgr(new sword::MarkupFilterMgr(FMT_HTMLHREF)); ldFrame->hide(); bookIndexFrame->hide(); bookIndex->hide(); bookIndex->header()->hide(); bookIndex->setSorting(-1); searchFrame->hide(); searchProgress->hide(); resultsLB->clear(); zeroSubs = true; multiWordCkB->setChecked(true); QFont browser_font( textDisplay->font() ); browser_font.setFamily( "adobe-times" ); browser_font.setPointSize( 14 ); // textDisplay->setFont( browser_font ); // ldDisplay->setFont( browser_font ); currentDisplay = textDisplay; currentText = 0; currentLD = 0; sword::SWModule *module = 0; for (ModMap::iterator it = mgr->Modules.begin(); it != mgr->Modules.end(); it++) { module = it->second; if (!strcmp(module->Type(),"Biblical Texts")) currentText = module; if (!strcmp(module->Type(), "Lexicons / Dictionaries")) currentLD = module; if (module->getConfig().has("Feature", "HebrewDef")) { strongsHebrewLex = it->first.c_str(); qWarning(it->first.c_str()); } if (module->getConfig().has("Feature", "GreekDef")) { strongsGreekLex = it->first.c_str(); qWarning(it->first.c_str()); } } qWarning(strongsGreekLex); qWarning(strongsHebrewLex); SWConfig userConfig("swordprefs.conf"); if (userConfig["layout"]["currentText"].length()) { ModMap::iterator it = mgr->Modules.find(userConfig["layout"]["currentText"]); if (it != mgr->Modules.end()) currentText = it->second; } if (userConfig["layout"]["currentTextKey"].length()) { if (currentText) searchResultClick(userConfig["layout"]["currentTextKey"].c_str()); } if (userConfig["layout"]["currentLD"].length()) { ModMap::iterator it = mgr->Modules.find(userConfig["layout"]["currentLD"]); if (it != mgr->Modules.end()) currentLD = it->second; } if (userConfig["layout"]["currentLDKey"].length()) { if (currentLD) ldSelectEdit->setText(userConfig["layout"]["currentLDKey"].c_str()); } refreshText(); if (userConfig["layout"]["textFrame"].length()) { if (userConfig["layout"]["textFrame"] == "On") textFrame->show(); else textFrame->hide(); } if (userConfig["layout"]["ldFrame"].length()) { if (userConfig["layout"]["ldFrame"] == "On") ldFrame->show(); else ldFrame->hide(); } if (userConfig["layout"]["verseSelectFrame"].length()) { if (userConfig["layout"]["verseSelectFrame"] == "On") verseSelectFrame->show(); else verseSelectFrame->hide(); } if (userConfig["layout"]["bookIndexFrame"].length()) { if (userConfig["layout"]["bookIndexFrame"] == "On") bookIndexFrame->show(); else bookIndexFrame->hide(); } if (userConfig["layout"]["lastSearchText"].length()) { searchText->setText(userConfig["layout"]["lastSearchText"].c_str()); } ConfigEntMap::iterator itStart = userConfig["bookmarks"].lower_bound("bookmark"); ConfigEntMap::iterator itEnd = userConfig["bookmarks"].upper_bound("bookmark"); for (;itStart != itEnd; itStart++) { bookmarks.push_back(itStart->second); } modsPopup = 0; connect( bookCB, SIGNAL( activated(const QString&) ), this, SLOT( refreshText() ) ); connect( chapSB, SIGNAL( valueChanged ( int ) ), this, SLOT( refreshText() ) ); connect( verseSB, SIGNAL( valueChanged ( int ) ), this, SLOT( refreshText() ) ); connect( ldSelectEdit, SIGNAL( textChanged ( const QString& ) ), this, SLOT( refreshLD() ) ); connect( searchGo, SIGNAL( clicked () ), this, SLOT( doSearch() ) ); connect( showBKButton, SIGNAL( clicked () ), this, SLOT( showBookKey() ) ); connect( resultsLB, SIGNAL( highlighted (const QString &) ), this, SLOT( searchResultClick(const QString &) ) ); connect( bookIndex, SIGNAL( selectionChanged (QListViewItem *) ), this, SLOT( gbSelChanged(QListViewItem *) ) ); } /* * Destroys the object and frees any allocated resources */ QPSword::~QPSword() { SWConfig userConfig("swordprefs.conf"); if (currentText) { userConfig["layout"]["currentText"] = currentText->Name(); userConfig["layout"]["currentTextKey"] = currentText->KeyText(); } if (currentLD) { userConfig["layout"]["currentLD"] = currentLD->Name(); userConfig["layout"]["currentLDKey"] = currentLD->KeyText(); } userConfig["layout"]["lastSearchText"] = (const char *)searchText->text(); userConfig["layout"]["textFrame"] = ((!textFrame->isHidden()) ? "On" : "Off"); userConfig["layout"]["ldFrame"] = ((!ldFrame->isHidden()) ? "On" : "Off"); userConfig["layout"]["verseSelectFrame"] = ((!verseSelectFrame->isHidden()) ? "On" : "Off"); userConfig["layout"]["bookIndexFrame"] = ((!bookIndexFrame->isHidden()) ? "On" : "Off"); userConfig["bookmarks"].erase("bookmark"); for (unsigned int i = 0; i < bookmarks.size(); i++) { userConfig["bookmarks"].insert(ConfigEntMap::value_type("bookmark", bookmarks[i])); } userConfig.Save(); // no need to delete child widgets, Qt does it all for us if (mgr) delete mgr; } void QPSword::refreshLD() { if (!currentLD) return; // assert book is selected currentLD->SetKey((const char *)ldSelectEdit->text()); (const char *)*currentLD; // snap to entry QString text = ""; text += "" + QString(currentLD->KeyText()) + ""; text += QString::fromUtf8((currentLD->RenderText())); text += ""; ldDisplay->setText(text); // assume we want to see if we're refreshing if (!searchFrame->isHidden()) searchFrame->hide(); if (ldFrame->isHidden()) ldFrame->show(); } void QPSword::refreshText() { if (!currentText) return; // assert book is selected bool wholeChapter = false; showLocator(); showLocator(); // toggle locator on/off to be sure we have correct one for book type QString keyText = ""; VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, ((SWKey *)(*currentText))); if (vkey) { SWModule *saveCurrentText = currentText; if (zeroSubs) { currentText = 0; // used to keep us from going into a recursive loop if we set any values below if (((39 * (vkey->Testament() - 1)) + (vkey->Book()-1)) != bookCB->currentItem()) { chapSB->setValue(1); verseSB->setValue(1); } else if (vkey->Chapter() != chapSB->value()) { verseSB->setValue(1); } currentText = saveCurrentText; } keyText= bookCB->currentText() + " " + chapSB->text() + ":" + verseSB->text(); if (!strcmp(currentText->Type(),"Biblical Texts")) wholeChapter = true; } else { keyText = (const char *)gbKeySelectEdit->text(); } currentText->SetKey((const char *)keyText); if (wholeChapter) { // display an entire chapter VerseKey *key = (VerseKey *)(SWKey *)(*currentText); int verse = key->Verse(); int chapter = key->Chapter(); int book = key->Book(); VerseKey saveKey = *key; QString text = ""; for (key->Verse(1); ((key->Chapter() == chapter) && (key->Book() == book) && !currentText->Error()); (*currentText)++) { char buf[32]; int pvHeading = 0; do { sprintf(buf, "%i", pvHeading++); SWBuf preverseHeading = currentText->getEntryAttributes()["Heading"]["Preverse"][buf].c_str(); if (preverseHeading.length()) { text += "

"; text += currentText->RenderText(preverseHeading); // do any tag conversions for our requested markup text += "

"; } else break; } while (true); text += "" + QString::number(key->Verse()) + ""; if (key->Verse() == verse) text += ""; text += QString::fromUtf8(((const char *)*currentText)) + " "; if (key->Verse() == verse) text += ""; } currentText->SetKey(saveKey); text += ""; textDisplay->setText(text); textDisplay->scrollToAnchor("curVerse"); } else { QString text = ""; text += "" + QString(currentText->KeyText()) + ""; text += QString::fromUtf8(((const char *)*currentText)); text += ""; textDisplay->setText(text); } if (textFrame->isHidden()) textFrame->show(); } void QPSword::showLocator() { if (!currentText) return; // assert book is selected bool shown = ((!verseSelectFrame->isHidden()) || (!bookIndexFrame->isHidden())); if (((SWKey *)(*currentText))->getClass()->isAssignableFrom("VerseKey")) { if (!shown) verseSelectFrame->show(); else verseSelectFrame->hide(); if (!bookIndexFrame->isHidden()) bookIndexFrame->hide(); } else { if (!shown) bookIndexFrame->show(); else bookIndexFrame->hide(); if (!verseSelectFrame->isHidden()) verseSelectFrame->hide(); } } void QPSword::showLD() { if (ldFrame->isHidden()) { if (!searchFrame->isHidden()) searchFrame->hide(); ldFrame->show(); } else ldFrame->hide(); } void QPSword::showSearch() { if (searchFrame->isHidden()) { if (!ldFrame->isHidden()) ldFrame->hide(); searchFrame->show(); } else searchFrame->hide(); } void QPSword::showAbout() { AboutForm about(this, "About", TRUE); about.exec(); } void QPSword::showBookKey() { if (bookIndex->isHidden()) { if (!gbKeyLoaded) loadGBKey(); bookIndex->show(); } else bookIndex->hide(); textContentsFrameLayout->activate(); } void QPSword::fillTreeTOC(TreeKeyIdx treeKey, QListView *tree, QListViewItem *parent) { QListViewItem *node = (!parent) ? new QListViewItem(bookIndex, 0) : new QListViewItem(parent, 0); QListViewItem *lastChild; for (lastChild = node->nextSibling();lastChild;lastChild = lastChild->nextSibling()) { if (!lastChild->nextSibling()) break; } if (lastChild) node->moveItem(lastChild); node->setText( 0, tr( treeKey.getLocalName() ) ); if (treeKey.firstChild()) { fillTreeTOC(treeKey, tree, node); treeKey.parent(); } if (treeKey.nextSibling()) fillTreeTOC(treeKey, tree, parent); } void QPSword::loadGBKey() { if (currentText) { SWKey *key = (SWKey *)(*currentText); TreeKeyIdx *tree = SWDYNAMIC_CAST(TreeKeyIdx, key); if (tree) { tree->root(); tree->firstChild(); bookIndex->clear(); fillTreeTOC(*tree, bookIndex, 0); } gbKeyLoaded = true; } } void QPSword::gbSelChanged(QListViewItem *selItem) { SWBuf key = (const char *)selItem->text(0); for (selItem = selItem->parent(); selItem; selItem = selItem->parent()) key = (SWBuf)(const char *)selItem->text(0) + (SWBuf)"/" + (SWBuf)key; gbKeySelectEdit->setText(key.c_str()); refreshText(); } void QPSword::showBook() { if (textFrame->isHidden()) textFrame->show(); else textFrame->hide(); } void QPSword::showTextContextMenu() { QPopupMenu * m = new QPopupMenu( this ); QPSword *app = (QPSword *)this->topLevelWidget(); int id = 0; modsPopup = new QPopupMenu( this ); SWModule *module = 0; for (ModMap::iterator it = mgr->Modules.begin(); it != mgr->Modules.end(); it++) { module = it->second; id = modsPopup->insertItem( module->Name(), app, SLOT( chooseModule(int) ) ); modsPopup->setItemChecked(id, ((module == currentText)||(module == currentLD))); } m->insertItem( tr( "Choose Module" ), modsPopup ); /* if (!app->textFrame->isHidden()) { modsPopup = new QPopupMenu( this ); SWModule *module = 0; for (ModMap::iterator it = mgr->Modules.begin(); it != mgr->Modules.end(); it++) { module = it->second; id = modsPopup->insertItem( module->Name(), app, SLOT( chooseModule(int) ) ); modsPopup->setItemChecked(id, ((module == currentText)||(module == currentLD))); } m->insertItem( tr( "Choose Module" ), modsPopup ); } */ optionsPopup = new QPopupMenu( this ); // Add options to Options Main Menu choice StringList options = mgr->getGlobalOptions(); for (StringList::iterator it = options.begin(); it != options.end(); it++) { SWBuf oVal = mgr->getGlobalOption ( it->c_str() ); StringList values = mgr->getGlobalOptionValues((*it).c_str()); QPopupMenu *oPopup = new QPopupMenu( this ); StringList::iterator it2 = values.begin(); for (; it2 != values.end(); it2++) { if ((*it2 != "On") && (*it2 != "Off")) break; } if (it2 == values.end()) { // simple option const char *optVal = mgr->getGlobalOption(it->c_str()); id = optionsPopup->insertItem( it->c_str(), app, SLOT( toggleOption(int) ) ); if (optVal) optionsPopup->setItemChecked(id, (!strcmp(optVal, "On"))); } else { // complex option for (StringList::iterator it2 = values.begin(); it2 != values.end(); it2++) { id = oPopup->insertItem( it2->c_str(), app, SLOT( toggleOption(int) ) ); oPopup->setItemChecked(id, (*it2 == oVal)); } optionsPopup->insertItem( tr( it->c_str() ), oPopup ); } } /* const char *optVal = mgr->getGlobalOption ("Footnotes"); if (optVal) optionsPopup->setItemChecked(id, (!strcmp(optVal, "On"))); id = optionsPopup->insertItem( "Strong's Numbers", app, SLOT( toggleOption(int) ) ); optVal = mgr->getGlobalOption ("Strong's Numbers"); if (optVal) optionsPopup->setItemChecked(id, (!strcmp(optVal, "On"))); */ m->insertItem( tr( "Module Options" ), optionsPopup ); m->insertSeparator(); m->insertItem( tr( "Lookup" ), app, SLOT( lookup() ) ); if (!app->textFrame->isHidden() && app->searchFrame->isHidden()) { id = m->insertItem( tr( "Search" ), app, SLOT( showSearch() ) ); } autoScrollPopup = new QPopupMenu( this ); autoScrollPopup->insertItem( "Very Slow", app, SLOT( startAutoScroll(int) ) ); autoScrollPopup->insertItem( "Slow", app, SLOT( startAutoScroll(int) ) ); autoScrollPopup->insertItem( "Medium", app, SLOT( startAutoScroll(int) ) ); autoScrollPopup->insertItem( "Fast", app, SLOT( startAutoScroll(int) ) ); autoScrollPopup->insertItem( "Very Fast", app, SLOT( startAutoScroll(int) ) ); m->insertItem( tr( "Read Scrolling" ), autoScrollPopup ); m->insertSeparator(); if ((!app->ldFrame->isHidden()) || (!app->searchFrame->isHidden())) { id = m->insertItem( tr( "Show Book" ), app, SLOT( showBook() ) ); m->setItemChecked(id, !app->textFrame->isHidden()); } if (!app->textFrame->isHidden()) { id = m->insertItem( tr( "Show Key Nav" ), app, SLOT( showLocator() ) ); m->setItemChecked(id, ((!app->verseSelectFrame->isHidden())||(!app->bookIndexFrame->isHidden()))); id = m->insertItem( tr( "Show Lex/Dict" ), app, SLOT( showLD() ) ); m->setItemChecked(id, !app->ldFrame->isHidden()); if (!app->searchFrame->isHidden()) { id = m->insertItem( tr( "Show Search" ), app, SLOT( showSearch() ) ); m->setItemChecked(id, true); } } m->insertSeparator(); bookmarkPopup = new QPopupMenu( this ); // Add options to Options Main Menu choice unsigned int i; for (i = 0; i < bookmarks.size(); i++) { bookmarkPopup->insertItem( bookmarks[i].c_str(), app, SLOT( gotoBookmark(int) ) ); } if (i) m->insertItem( tr( "Bookmarks" ), bookmarkPopup ); id = m->insertItem( "Add Bookmark", app, SLOT( addBookmark() ) ); id = m->insertItem( "Clear All Bookmarks", app, SLOT( clearAllBookmarks() ) ); m->insertSeparator(); id = m->insertItem( "About...", app, SLOT( showAbout() ) ); m->popup( QCursor::pos() ); } // close(); void QPSword::startAutoScroll(int id) { int sSpeed = 1; QString speed = autoScrollPopup->text(id); if (speed == "Very Slow") sSpeed = 3; else if (speed == "Slow") sSpeed = 5; else if (speed == "Medium") sSpeed = 6; else if (speed == "Fast") sSpeed = 7; else if (speed == "Very Fast") sSpeed = 8; currentDisplay->startAutoScroll(sSpeed); } void QPSword::lookup() { if (!currentDisplay->hasSelectedText()) return; QString lookupText = currentDisplay->selectedText().stripWhiteSpace(); char *ltext = 0; stdstr(<ext, (const char *)lookupText); char *scan = 0; for (scan = ltext; *scan; scan++) { if (*scan == '<' || *scan == '>') *scan = ' '; if ((!isdigit(*scan)) && (*scan != ' ')) break; } if (!*scan) { // we're a strongs number ModMap::iterator strongsLex = 0; strongsLex = mgr->Modules.find(((bookCB->currentItem() < 39) ? (const char *)strongsHebrewLex : (const char *)strongsGreekLex)); if (strongsLex != mgr->Modules.end()) currentLD = strongsLex->second; } lookupText = ltext; lookupText = lookupText.stripWhiteSpace(); ldSelectEdit->setText(lookupText); delete [] ltext; refreshLD(); } void QPSword::chooseModule(int id) { QString modName = modsPopup->text(id); // QString modName = optionsPopup->text(id); ModMap::iterator it = mgr->Modules.find((const char *)modName); if (it != mgr->Modules.end()) { SWModule *module = it->second; if (!strcmp(module->Type(), "Lexicons / Dictionaries")) { if (currentLD) currentLD->flush(); currentLD = module; refreshLD(); } else { if (currentText) currentText->flush(); currentText = module; gbKeyLoaded = false; bookIndex->hide(); gbKeySelectEdit->setText(""); refreshText(); } } } void QPSword::toggleOption(int id) { QString optionName = optionsPopup->text(id); const char *optVal = mgr->getGlobalOption((const char *)optionName); // qWarning( optVal ); mgr->setGlobalOption ((const char *)optionName, ((!strcmp(optVal, "Off")) ? "On" : "Off")); refreshText(); } void QPSword::gotoBookmark(int id) { QString bookmarkText = bookmarkPopup->text(id); searchResultClick(bookmarkText); } void QPSword::clearAllBookmarks() { bookmarks.clear(); } void QPSword::addBookmark() { if (currentText) { bookmarks.push_back(((SWKey *)*currentText)->getShortText()); } } void searchProgressCallback(char pct, void *pbar) { QProgressBar *progressBar = (QProgressBar *)pbar; progressBar->setProgress(pct); } void QPSword::doSearch() { resultsLB->clear(); if (currentText) { searchProgress->setProgress(0); searchProgress->show(); resultsFrameLayout->activate(); QString entryText = searchText->text(); int searchType = regExpCkB->isChecked() ? 0 : exactPhrCkB->isChecked() ? -1 : -2; int searchParams = caseSensitiveCkB->isChecked() ? 0 : REG_ICASE; ListKey searchResults = currentText->Search((const char *)entryText, searchType, searchParams, 0, 0, &searchProgressCallback, searchProgress); searchProgress->hide(); for (; !searchResults.Error(); searchResults++) { SWKey *key = searchResults.GetElement(); if (key) { QString resultText = key->getShortText(); resultsLB->insertItem(resultText); } } } } void QPSword::searchResultClick(const QString &entry) { if (((SWKey *)(*currentText))->getClass()->isAssignableFrom("VerseKey")) { VerseKey key = (const char *)entry; SWModule *saveCurrentText = currentText; currentText = 0; // prevent multiple calls to refreshText bookCB->setCurrentItem((39 * (key.Testament() - 1)) + (key.Book()-1)); chapSB->setValue(key.Chapter()); currentText = saveCurrentText; jumpToVerse(key.Verse()); } else { gbKeySelectEdit->setText(entry); refreshText(); } } void QPSword::jumpToVerse(int verse) { SWModule *saveCurrentText = currentText; currentText = 0; // prevent multiple calls to refreshText zeroSubs = false; verseSB->setValue(verse); currentText = saveCurrentText; refreshText(); zeroSubs = true; }