diff options
Diffstat (limited to 'src/frontend/searchdialog/btsearchresultarea.cpp')
-rw-r--r-- | src/frontend/searchdialog/btsearchresultarea.cpp | 332 |
1 files changed, 26 insertions, 306 deletions
diff --git a/src/frontend/searchdialog/btsearchresultarea.cpp b/src/frontend/searchdialog/btsearchresultarea.cpp index 262ff23..6a82a4f 100644 --- a/src/frontend/searchdialog/btsearchresultarea.cpp +++ b/src/frontend/searchdialog/btsearchresultarea.cpp @@ -2,7 +2,7 @@ * * This file is part of BibleTime's source code, http://www.bibletime.info/. * -* Copyright 1999-2011 by the BibleTime developers. +* Copyright 1999-2014 by the BibleTime developers. * The BibleTime source code is licensed under the GNU General Public License version 2.0. * **********/ @@ -10,7 +10,6 @@ #include "frontend/searchdialog/btsearchresultarea.h" #include <QApplication> -#include <QDebug> #include <QFrame> #include <QMenu> #include <QProgressDialog> @@ -22,13 +21,19 @@ #include <QWidget> #include "backend/keys/cswordversekey.h" #include "backend/rendering/cdisplayrendering.h" -#include "frontend/display/cdisplay.h" +#include "backend/config/btconfig.h" +#include "frontend/display/bthtmlreaddisplay.h" #include "frontend/searchdialog/cmoduleresultview.h" #include "frontend/searchdialog/csearchdialog.h" #include "frontend/searchdialog/csearchresultview.h" #include "util/tool.h" +namespace { +const QString MainSplitterSizesKey = "GUI/SearchDialog/SearchResultsArea/mainSplitterSizes"; +const QString ResultSplitterSizesKey = "GUI/SearchDialog/SearchResultsArea/resultSplitterSizes"; +} // anonymous namespace + namespace Search { BtSearchResultArea::BtSearchResultArea(QWidget *parent) @@ -76,7 +81,7 @@ void BtSearchResultArea::initView() { QVBoxLayout* frameLayout = new QVBoxLayout(m_displayFrame); frameLayout->setContentsMargins(0, 0, 0, 0); - m_previewDisplay = CDisplay::createReadInstance(0, m_displayFrame); + m_previewDisplay = new BtHtmlReadDisplay(0, m_displayFrame); m_previewDisplay->view()->setToolTip(tr("Text of the selected search result item")); frameLayout->addWidget(m_previewDisplay->view()); @@ -143,10 +148,10 @@ void BtSearchResultArea::updatePreview(const QString& key) { //for bibles render 5 context verses if (module->type() == CSwordModuleInfo::Bible) { CSwordVerseKey vk(module); - vk.Headings(1); + vk.setIntros(true); vk.setKey(key); - ((sword::VerseKey*)(module->module()->getKey()))->Headings(1); //HACK: enable headings for VerseKeys + ((sword::VerseKey*)(module->module()->getKey()))->setIntros(true); //HACK: enable headings for VerseKeys //first go back and then go forward the keys to be in context vk.previous(CSwordVerseKey::UseVerse); @@ -174,10 +179,10 @@ void BtSearchResultArea::updatePreview(const QString& key) { //for commentaries only one verse, but with heading else if (module->type() == CSwordModuleInfo::Commentary) { CSwordVerseKey vk(module); - vk.Headings(1); + vk.setIntros(true); vk.setKey(key); - ((sword::VerseKey*)(module->module()->getKey()))->Headings(1); //HACK: enable headings for VerseKeys + ((sword::VerseKey*)(module->module()->getKey()))->setIntros(true); //HACK: enable headings for VerseKeys //include Headings in display, they are indexed and searched too if (vk.getVerse() == 1) { @@ -198,295 +203,11 @@ void BtSearchResultArea::updatePreview(const QString& key) { text = render.renderSingleKey(key, modules, settings); } - m_previewDisplay->setText( highlightSearchedText(text, searchedText) ); + m_previewDisplay->setText( CSwordModuleSearch::highlightSearchedText(text, searchedText) ); m_previewDisplay->moveToAnchor( CDisplayRendering::keyToHTMLAnchor(key) ); } } -QStringList BtSearchResultArea::queryParser(const QString& queryString) { - QString token; - QStringList tokenList; - int cnt, pos; - - token = ""; - cnt = 0; - while (cnt < queryString.length()) { - // add to token - if ((queryString[cnt]).isLetterOrNumber() || (queryString[cnt] == '*')) { - token = token + queryString[cnt]; - cnt++; - } - else if ((queryString[cnt]).isLetterOrNumber() || (queryString[cnt] == '?')) { - token = token + queryString[cnt]; - cnt++; - } - // token break - else if (queryString[cnt] == ' ') { - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - token = ""; - cnt++; - } - // clucene appears to ignore quoted strings in the sence - // that it treats all the words within quoted strings as - // regular tokens and not as a single token. - else if (queryString[cnt] == '"') { - cnt++; - } - // wild card - treat as a special token break - //else if (queryString[cnt] == '*') { - // token = token + queryString[cnt]; - // token = token.simplified(); - // if ((token != "*") && (token != "")) - // tokenList.append(token); - // // start next token with wildcard (kin*m -> kin* *m) - // token = "*"; - // cnt++; - //} - // the ! token is also a token break - else if (queryString[cnt] == '!') { - // store away current token - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - // add the ! token - tokenList.append("!"); - token = ""; - cnt++; - } - // the - token is also a token break - else if (queryString[cnt] == '-') { - // store away current token - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - // add the ! token - tokenList.append("-"); - token = ""; - cnt++; - } - // the + token is also a token break - else if (queryString[cnt] == '+') { - // store away current token - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - // add the + token - tokenList.append("+"); - token = ""; - cnt++; - } - // the || token is also a token break - else if ((queryString[cnt] == '|') && (queryString[cnt+1] == '|')) { - // store away current token - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - // add the || token - tokenList.append("||"); - token = ""; - cnt += 2; - } - // the && token is also a token break - else if ((queryString[cnt] == '&') && (queryString[cnt+1] == '&')) { - // store away current token - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - // add the || token - tokenList.append("&&"); - token = ""; - cnt += 2; - } - else cnt++; - } - token = token.simplified(); - if ((token != "*") && (token != "")) - tokenList.append(token); - - cnt = 0; - QStringList::iterator it; - for ( it = tokenList.begin(); it != tokenList.end(); it++ ) { - //----------------------------------------------------------- - // remove all the NOT(!) tokens - these do not need to be - // highlighted in the highlighter - //----------------------------------------------------------- - if (((*it) == "!") || ((*it) == "NOT") || ((*it) == "-")) { - it = tokenList.erase(it); - if (it == tokenList.end()) - break; - it = tokenList.erase(it); - if (it == tokenList.end()) - break; - it--; - } - //----------------------------------------------------------- - // remove all the operator tokens - these do not need to be - // highlighted in the highlighter - //----------------------------------------------------------- - else if ( ((*it) == "||") || ((*it) == "OR") || ((*it) == "+") || - ((*it) == "AND") || ((*it) == "&&") ) { - it = tokenList.erase(it); - if (it == tokenList.end()) - break; - it--; - } - // if the token contains a ^ then trim the remainder of the - // token from the ^ - //What??? error: invalid conversion from ‘const void*’ to ‘int’ - // and how come "contains" returns bool but is used as int? - //else if ( (pos = (*it).contains("^")) >= 0 ) { - else if ( (pos = (*it).indexOf("^") ) >= 0 ) { - (*it) = (*it).left(pos - 1); - } - // if the token contains a ~ then trim the remainder of the - // token from the ~ - else if ( (pos = (*it).indexOf("~") ) >= 0 ) { - (*it) = (*it).left(pos - 2) + "*"; - } - } - return(tokenList); -} - -QString BtSearchResultArea::highlightSearchedText(const QString& content, const QString& searchedText) { - QString ret = content; - - const Qt::CaseSensitivity cs = Qt::CaseInsensitive; - - // int index = 0; - int index = ret.indexOf("<body", 0); - int matchLen = 0; - int length = searchedText.length(); - - // Highlighting constants - - // \todo We need to make the highlight color configurable. - const QString rep1("<span style=\"background-color:#FFFF66;\">"); - const QString rep2("</span>"); - const unsigned int repLength = rep1.length() + rep1.length(); - const QString rep3("style=\"background-color:#FFFF66;\" "); - const unsigned int rep3Length = rep3.length(); - - - QString newSearchText; - - newSearchText = searchedText; - - // find the strongs search lemma and highlight it - // search the searched text for "strong:" until it is not found anymore - QStringList list; - - // split the search string - some possibilities are "\\s|\\|", "\\s|\\+", or "\\s|\\|\\+" - // \todo find all possible seperators - QString regExp = "\\s"; - list = searchedText.split(QRegExp(regExp)); - foreach (QString newSearchText, list) { - int sstIndex; // strong search text index for finding "strong:" - int idx1, idx2; - QString sNumber, lemmaText; - - sstIndex = newSearchText.indexOf("strong:"); - if (sstIndex == -1) - continue; - - // set the start index to the start of <body> - int strongIndex = index; - - // Get the strongs number from the search text. - // First, find the first space after "strong:" - sstIndex = sstIndex + 7; - // get the strongs number -> the text following "strong:" to the end of the string. - sNumber = newSearchText.mid(sstIndex, -1); - // find all the "lemma=" inside the the content - while ((strongIndex = ret.indexOf("lemma=", strongIndex, cs)) != -1) { - // get the strongs number after the lemma and compare it with the - // strongs number we are looking for - idx1 = ret.indexOf("\"", strongIndex) + 1; - idx2 = ret.indexOf("\"", idx1 + 1); - lemmaText = ret.mid(idx1, idx2 - idx1); - - // this is interesting because we could have a strongs number like: G3218|G300 - // To handle this we will use some extra cpu cycles and do a partial match against - // the lemmaText - if (lemmaText.contains(sNumber)) { - // strongs number is found now we need to highlight it - // I believe the easiest way is to insert rep3 just before "lemma=" - ret = ret.insert(strongIndex, rep3); - strongIndex += rep3Length; - } - strongIndex += 6; // 6 is the length of "lemma=" - } - } - //--------------------------------------------------------------------- - // now that the strong: stuff is out of the way continue with - // other search options - //--------------------------------------------------------------------- - - // try to figure out how to use the lucene query parser - - //using namespace lucene::queryParser; - //using namespace lucene::search; - //using namespace lucene::analysis; - //using namespace lucene::util; - - //wchar_t *buf; - //char buf8[1000]; - //standard::WhitespaceAnalyzer analyzer; - //lucene_utf8towcs(m_wcharBuffer, searchedText.utf8(), MAX_CONV_SIZE); - //QSharedPointer<Query> q( QueryParser::parse(m_wcharBuffer, _T("content"), &analyzer) ); - //StringReader reader(m_wcharBuffer); - //TokenStream* tokenStream = analyzer.tokenStream( _T("field"), &reader); - //Token token; - //while(tokenStream->next(&token) != 0) { - // lucene_wcstoutf8(buf8, token.termText(), 1000); - // printf("%s\n", buf8); - //} - - //=========================================================== - // since I could not figure out the lucene query parser, I - // made a simple parser. - //=========================================================== - QStringList words = queryParser(newSearchText); - qDebug() << "btsearchresultarea.cpp: " << __LINE__ << ": " << words << '\n'; - foreach (QString word, words) { //search for every word in the list - QRegExp findExp; - if (word.contains("*")) { - length = word.length() - 1; - word.replace('*', "\\S*"); //match within a word - findExp = QRegExp(word); - findExp.setMinimal(true); - } - else if (word.contains("?")) { - length = word.length() - 1; - word.replace('?', "\\S?"); //match within a word - findExp = QRegExp(word); - findExp.setMinimal(true); - } - else { - length = word.length(); - findExp = QRegExp("\\b" + word + "\\b"); - } - - // index = 0; //for every word start at the beginning - index = ret.indexOf("<body", 0); - findExp.setCaseSensitivity(cs); - //while ( (index = ret.find(findExp, index)) != -1 ) { //while we found the word - while ( (index = findExp.indexIn(ret, index)) != -1 ) { //while we found the word - matchLen = findExp.matchedLength(); - if (!util::tool::inHTMLTag(index, ret)) { - length = matchLen; - ret = ret.insert( index + length, rep2 ); - ret = ret.insert( index, rep1 ); - index += repLength; - } - index += length; - } - } - qDebug() << "btsearchresultarea.cpp: " << __LINE__ << ": " << words << '\n'; - //qWarning("\n\n\n%s", ret.latin1()); - return ret; -} - /** Initializes the signal slot conections of the child widgets, */ void BtSearchResultArea::initConnections() { connect(m_resultListBox, SIGNAL(keySelected(const QString&)), this, SLOT(updatePreview(const QString&))); @@ -506,26 +227,28 @@ void BtSearchResultArea::initConnections() { * Load the settings from the resource file */ void BtSearchResultArea::loadDialogSettings() { - QList<int> mainSplitterSizes = CBTConfig::get(CBTConfig::searchMainSplitterSizes); - if (mainSplitterSizes.count() > 0) { + QList<int> mainSplitterSizes = btConfig().value< QList<int> >(MainSplitterSizesKey, QList<int>()); + if (mainSplitterSizes.count() > 0) m_mainSplitter->setSizes(mainSplitterSizes); - } - else { + else + { int w = this->size().width(); int w2 = m_moduleListBox->sizeHint().width(); mainSplitterSizes << w2 << w - w2; m_mainSplitter->setSizes(mainSplitterSizes); } - QList<int> resultSplitterSizes = CBTConfig::get(CBTConfig::searchResultSplitterSizes); - if (resultSplitterSizes.count() > 0) m_resultListSplitter->setSizes(resultSplitterSizes); + + QList<int> resultSplitterSizes = btConfig().value< QList<int> >(ResultSplitterSizesKey, QList<int>()); + if (resultSplitterSizes.count() > 0) + m_resultListSplitter->setSizes(resultSplitterSizes); } /** * Save the settings to the resource file */ void BtSearchResultArea::saveDialogSettings() const { - CBTConfig::set(CBTConfig::searchMainSplitterSizes, m_mainSplitter->sizes()); - CBTConfig::set(CBTConfig::searchResultSplitterSizes, m_resultListSplitter->sizes()); + btConfig().setValue(MainSplitterSizesKey, m_mainSplitter->sizes()); + btConfig().setValue(ResultSplitterSizesKey, m_resultListSplitter->sizes()); } /****************************************************************************** @@ -533,15 +256,12 @@ void BtSearchResultArea::saveDialogSettings() const { ******************************************************************************/ StrongsResultList::StrongsResultList(const CSwordModuleInfo *module, - const sword::ListKey &results, + const sword::ListKey & result, const QString &strongsNumber) { using namespace Rendering; - /// \warning This is a workaround for Sword constness - sword::ListKey result = results; - - int count = result.Count(); + int count = result.getCount(); if (!count) return; |