From cdf2c0d404a5d0c4b54af355966bfebf34ae6af1 Mon Sep 17 00:00:00 2001 From: Abs62 Date: Tue, 25 Jul 2017 18:28:29 +0300 Subject: [PATCH] Add option to ignore words order while full-text search --- aard.cc | 8 ++- bgl.cc | 8 ++- config.cc | 7 ++ config.hh | 2 + dictdfiles.cc | 8 ++- dictionary.cc | 2 +- dictionary.hh | 3 +- dsl.cc | 8 ++- epwing.cc | 8 ++- ftshelpers.cc | 172 +++++++++++++++++++++++++++++++++++++--------- ftshelpers.hh | 7 +- fulltextsearch.cc | 48 ++++++++++++- fulltextsearch.hh | 11 ++- fulltextsearch.ui | 7 ++ gls.cc | 8 ++- mdx.cc | 8 ++- sdict.cc | 8 ++- slob.cc | 8 ++- stardict.cc | 8 ++- xdxf.cc | 8 ++- zim.cc | 8 ++- 21 files changed, 279 insertions(+), 76 deletions(-) diff --git a/aard.cc b/aard.cc index ffe14c56..0583b5ab 100644 --- a/aard.cc +++ b/aard.cc @@ -267,7 +267,8 @@ class AardDictionary: public BtreeIndexing::BtreeDictionary virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -630,9 +631,10 @@ void AardDictionary::getArticleText( uint32_t articleAddress, QString & headword sptr< Dictionary::DataRequest > AardDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } /// AardDictionary::getArticle() diff --git a/bgl.cc b/bgl.cc index fc95e98a..8dd51790 100644 --- a/bgl.cc +++ b/bgl.cc @@ -237,7 +237,8 @@ namespace virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual QString const& getDescription(); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); @@ -1139,9 +1140,10 @@ sptr< Dictionary::DataRequest > BglDictionary::getResource( string const & name sptr< Dictionary::DataRequest > BglDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } diff --git a/config.cc b/config.cc index 1a55d523..50662018 100644 --- a/config.cc +++ b/config.cc @@ -883,6 +883,9 @@ Class load() throw( exError ) if ( !fts.namedItem( "enabled" ).isNull() ) c.preferences.fts.enabled = ( fts.namedItem( "enabled" ).toElement().text() == "1" ); + if ( !fts.namedItem( "ignoreWordsOrder" ).isNull() ) + c.preferences.fts.ignoreWordsOrder = ( fts.namedItem( "ignoreWordsOrder" ).toElement().text() == "1" ); + if ( !fts.namedItem( "maxDictionarySize" ).isNull() ) c.preferences.fts.maxDictionarySize = fts.namedItem( "maxDictionarySize" ).toElement().text().toUInt(); } @@ -1823,6 +1826,10 @@ void save( Class const & c ) throw( exError ) opt.appendChild( dd.createTextNode( c.preferences.fts.enabled ? "1" : "0" ) ); hd.appendChild( opt ); + opt = dd.createElement( "ignoreWordsOrder" ); + opt.appendChild( dd.createTextNode( c.preferences.fts.ignoreWordsOrder ? "1" : "0" ) ); + hd.appendChild( opt ); + opt = dd.createElement( "maxDictionarySize" ); opt.appendChild( dd.createTextNode( QString::number( c.preferences.fts.maxDictionarySize ) ) ); hd.appendChild( opt ); diff --git a/config.hh b/config.hh index 95626022..7046b43d 100644 --- a/config.hh +++ b/config.hh @@ -160,6 +160,7 @@ struct FullTextSearch bool useMaxDistanceBetweenWords; bool useMaxArticlesPerDictionary; bool enabled; + bool ignoreWordsOrder; quint32 maxDictionarySize; QByteArray dialogGeometry; QString disabledTypes; @@ -171,6 +172,7 @@ struct FullTextSearch useMaxDistanceBetweenWords( true ), useMaxArticlesPerDictionary( false ), enabled( true ), + ignoreWordsOrder( false ), maxDictionarySize( 0 ) {} }; diff --git a/dictdfiles.cc b/dictdfiles.cc index cbd0a683..92578df3 100644 --- a/dictdfiles.cc +++ b/dictdfiles.cc @@ -128,7 +128,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -539,9 +540,10 @@ void DictdDictionary::getArticleText( uint32_t articleAddress, QString & headwor sptr< Dictionary::DataRequest > DictdDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } } // anonymous namespace diff --git a/dictionary.cc b/dictionary.cc index 141fa8a3..7e5e2290 100644 --- a/dictionary.cc +++ b/dictionary.cc @@ -171,7 +171,7 @@ sptr< DataRequest > Class::getResource( string const & /*name*/ ) return new DataRequestInstant( false ); } -sptr< DataRequest > Class::getSearchResults(const QString &, int, bool, int, int ) +sptr< DataRequest > Class::getSearchResults(const QString &, int, bool, int, int, bool ) { return new DataRequestInstant( false ); } diff --git a/dictionary.hh b/dictionary.hh index e44626d4..fec9f33c 100644 --- a/dictionary.hh +++ b/dictionary.hh @@ -396,7 +396,8 @@ public: virtual sptr< DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxArticlesPerDictionary ); + int maxArticlesPerDictionary, + bool ignoreWordsOrder ); // Return dictionary description if presented virtual QString const& getDescription(); diff --git a/dsl.cc b/dsl.cc index 704ec1f5..794de3c6 100644 --- a/dsl.cc +++ b/dsl.cc @@ -219,7 +219,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual QString const& getDescription(); virtual QString getMainFilename(); @@ -1959,9 +1960,10 @@ static void findCorrespondingFiles( string const & ifo, sptr< Dictionary::DataRequest > DslDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } } // anonymous namespace diff --git a/epwing.cc b/epwing.cc index ae89f551..5c5ce8c9 100644 --- a/epwing.cc +++ b/epwing.cc @@ -127,7 +127,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -782,9 +783,10 @@ sptr< Dictionary::DataRequest > EpwingDictionary::getResource( string const & na sptr< Dictionary::DataRequest > EpwingDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } int EpwingDictionary::japaneseWriting( gd::wchar ch ) diff --git a/ftshelpers.cc b/ftshelpers.cc index 0822a7b2..e3177d73 100644 --- a/ftshelpers.cc +++ b/ftshelpers.cc @@ -11,6 +11,8 @@ #include #include +#include + using std::vector; using std::string; @@ -31,6 +33,31 @@ bool ftsIndexIsOldOrBad( string const & indexFile, header.formatVersion != CurrentFtsFormatVersion + dict->getFtsIndexVersion(); } +static QString makeHiliteRegExpString( QStringList const & words, + int searchMode, + int distanceBetweenWords ) +{ + QString searchString( "(" ); + + QString stripWords( "(?:\\W+\\w+){0," ); + if( distanceBetweenWords >= 0 ) + stripWords += QString::number( distanceBetweenWords ); + stripWords += "}\\W+"; + + QString boundWord( searchMode == FTS::WholeWords ? "\\b" : "(?:\\w*)"); + + for( int x = 0; x < words.size(); x++ ) + { + if( x ) + searchString += stripWords; + + searchString += boundWord + words[ x ] + boundWord; + } + + searchString += ")"; + return searchString; +} + bool parseSearchString( QString const & str, QStringList & indexWords, QStringList & searchWords, QRegExp & searchRegExp, int searchMode, @@ -71,24 +98,7 @@ bool parseSearchString( QString const & str, QStringList & indexWords, // Make regexp for results hilite QStringList allWords = str.split( spacesRegExp, QString::SkipEmptyParts ); - QString searchString( "(" ); - - QString stripWords( "(?:\\W+\\w+){0," ); - if( distanceBetweenWords >= 0 ) - stripWords += QString::number( distanceBetweenWords ); - stripWords += "}\\W+"; - - QString boundWord( searchMode == FTS::WholeWords ? "\\b" : "(?:\\w*)"); - - for( int x = 0; x < allWords.size(); x++ ) - { - if( x ) - searchString += stripWords; - - searchString += boundWord + allWords[ x ] + boundWord; - } - - searchString += ")"; + QString searchString = makeHiliteRegExpString( allWords, searchMode, distanceBetweenWords ); searchRegExp = QRegExp( searchString, matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::RegExp2 ); @@ -338,6 +348,7 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets, int results = 0; QString headword, articleText; QList< uint32_t > offsetsForHeadwords; + QVector< QStringList > hiliteRegExps; QString id = QString::fromUtf8( dict.getId().c_str() ); @@ -357,7 +368,7 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets, if( headword.isEmpty() ) offsetsForHeadwords.append( offsets.at( i ) ); else - foundHeadwords->append( FTS::FtsHeadword( headword, id ) ); + foundHeadwords->append( FTS::FtsHeadword( headword, id, QStringList(), matchCase ) ); results++; if( maxResults > 0 && results >= maxResults ) @@ -371,6 +382,12 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets, QRegExp regex( "\\b\\w+\\b" ); Qt::CaseSensitivity cs = matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive; + QVector< QPair< QString, bool > > wordsList; + if( ignoreWordsOrder ) + { + for( QStringList::const_iterator it = words.begin(); it != words.end(); ++it ) + wordsList.append( QPair< QString, bool >( *it, true ) ); + } for( int i = 0; i < offsets.size(); i++ ) { @@ -381,6 +398,15 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets, int matchWordNom = 0; int unmatchWordNom = 0; + QVector< QStringList > allOrders; + QStringList order; + + if( ignoreWordsOrder ) + { + for( int i = 0; i < wordsList.size(); i++ ) + wordsList[ i ].second = true; + } + dict.getArticleText( offsets.at( i ), headword, articleText ); int articleLength = articleText.length(); @@ -390,36 +416,118 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets, if( pos >= 0 ) { QString s = regex.cap().normalized( QString::NormalizationForm_C ); - if( ( searchMode == FTS::WholeWords && s.compare( words.at( matchWordNom ), cs ) == 0 ) - || ( searchMode == FTS::PlainText && s.contains( words.at( matchWordNom ), cs ) ) ) + + if( ignoreWordsOrder ) { - matchWordNom += 1; + int i; + for( i = 0; i < wordsList.size(); i++ ) + { + if( wordsList.at( i ).second ) + { + if( ( searchMode == FTS::WholeWords && s.compare( wordsList.at( i ).first, cs ) == 0 ) + || ( searchMode == FTS::PlainText && s.contains( wordsList.at( i ).first, cs ) ) ) + { + wordsList[ i ].second = false; + order.append( wordsList.at( i ).first ); + break; + } + } + } + if( i < wordsList.size() ) + { + // Word found + matchWordNom += 1; - if( matchWordNom >= words.size() ) - break; // All words are found + if( matchWordNom >= words.size() ) + { + // All words are found + // Store found words sequence and continue search + // It's nesessary for hilite search results - unmatchWordNom = 0; + // Check if such sequence already presented + int x; + for( x = 0; x < allOrders.size(); x++ ) + { + if( allOrders[ x ] == order ) + break; + } + if( x >= allOrders.size() ) + allOrders.append( order ); + + order.clear(); + + matchWordNom = 0; + unmatchWordNom = 0; + for( int i = 0; i < wordsList.size(); i++ ) + wordsList[ i ].second = true; + + pos += s.isEmpty() ? 1 : s.length(); + continue; + } + + unmatchWordNom = 0; + } + else + if( matchWordNom > 0 ) + { + unmatchWordNom += 1; + if( distanceBetweenWords >= 0 && unmatchWordNom > distanceBetweenWords ) + { + // Sequence broken, clear all counters + matchWordNom = 0; + unmatchWordNom = 0; + for( int i = 0; i < wordsList.size(); i++ ) + wordsList[ i ].second = true; + order.clear(); + } + } } else - if( matchWordNom > 0 ) { - unmatchWordNom += 1; - if( distanceBetweenWords >= 0 && unmatchWordNom > distanceBetweenWords ) + if( ( searchMode == FTS::WholeWords && s.compare( words.at( matchWordNom ), cs ) == 0 ) + || ( searchMode == FTS::PlainText && s.contains( words.at( matchWordNom ), cs ) ) ) { - matchWordNom = 0; + matchWordNom += 1; + + if( matchWordNom >= words.size() ) + break; // All words are found + unmatchWordNom = 0; } + else + if( matchWordNom > 0 ) + { + unmatchWordNom += 1; + if( distanceBetweenWords >= 0 && unmatchWordNom > distanceBetweenWords ) + { + matchWordNom = 0; + unmatchWordNom = 0; + } + } } pos += s.isEmpty() ? 1 : s.length(); } } - if( matchWordNom >= words.size() ) + if( !allOrders.isEmpty() || matchWordNom >= words.size() ) { + QStringList hiliteReg; + if( !allOrders.isEmpty() ) + { + for( int i = 0; i < allOrders.size(); i++ ) + { + QString hiliteStr = makeHiliteRegExpString( allOrders.at( i ), searchMode, distanceBetweenWords ); + hiliteReg.append( hiliteStr ); + } + allOrders.clear(); + } if( headword.isEmpty() ) + { offsetsForHeadwords.append( offsets.at( i ) ); + hiliteRegExps.append( hiliteReg ); + } else - foundHeadwords->append( FTS::FtsHeadword( headword, id ) ); + foundHeadwords->append( FTS::FtsHeadword( headword, id, hiliteReg, matchCase ) ); results++; if( maxResults > 0 && results >= maxResults ) @@ -432,7 +540,7 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets, QVector< QString > headwords; dict.getHeadwordsFromOffsets( offsetsForHeadwords, headwords, &isCancelled ); for( int x = 0; x < headwords.size(); x++ ) - foundHeadwords->append( FTS::FtsHeadword( headwords.at( x ), id ) ); + foundHeadwords->append( FTS::FtsHeadword( headwords.at( x ), id, x < hiliteRegExps.size() ? hiliteRegExps.at( x ) : QStringList(), matchCase ) ); } } diff --git a/ftshelpers.hh b/ftshelpers.hh index ee3838dd..22ad6dc8 100644 --- a/ftshelpers.hh +++ b/ftshelpers.hh @@ -90,6 +90,7 @@ class FTSResultsRequest : public Dictionary::DataRequest int distanceBetweenWords; int maxResults; bool hasCJK; + bool ignoreWordsOrder; QAtomicInt isCancelled; QSemaphore hasExited; @@ -122,14 +123,16 @@ class FTSResultsRequest : public Dictionary::DataRequest public: FTSResultsRequest( BtreeIndexing::BtreeDictionary & dict_, QString const & searchString_, - int searchMode_, bool matchCase_, int distanceBetweenWords_, int maxResults_ ): + int searchMode_, bool matchCase_, int distanceBetweenWords_, int maxResults_, + bool ignoreWordsOrder_ ): dict( dict_ ), searchString( searchString_ ), searchMode( searchMode_ ), matchCase( matchCase_ ), distanceBetweenWords( distanceBetweenWords_ ), maxResults( maxResults_ ), - hasCJK( false ) + hasCJK( false ), + ignoreWordsOrder( ignoreWordsOrder_ ) { foundHeadwords = new QList< FTS::FtsHeadword >; QThreadPool::globalInstance()->start( diff --git a/fulltextsearch.cc b/fulltextsearch.cc index 21761957..df82eef0 100644 --- a/fulltextsearch.cc +++ b/fulltextsearch.cc @@ -136,6 +136,7 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent, dictionaries( dictionaries_ ), groups( groups_ ), group( 0 ), + ignoreWordsOrder( cfg_.preferences.fts.ignoreWordsOrder ), ftsIdx( ftsidx ) , helpAction( this ) { @@ -180,6 +181,18 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent, ui.articlesPerDictionary->setMaximum( MaxArticlesPerDictionary ); ui.articlesPerDictionary->setValue( cfg.preferences.fts.maxArticlesPerDictionary ); + int mode = ui.searchMode->itemData( ui.searchMode->currentIndex() ).toInt(); + if( mode == WholeWords || mode == PlainText ) + { + ui.checkBoxIgnoreWordOrder->setChecked( ignoreWordsOrder ); + ui.checkBoxIgnoreWordOrder->setEnabled( true ); + } + else + { + ui.checkBoxIgnoreWordOrder->setChecked( false ); + ui.checkBoxIgnoreWordOrder->setEnabled( false ); + } + ui.matchCase->setChecked( cfg.preferences.fts.matchCase ); setLimitsUsing(); @@ -190,6 +203,8 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent, this, SLOT( setLimitsUsing() ) ); connect( ui.searchMode, SIGNAL( currentIndexChanged( int ) ), this, SLOT( setLimitsUsing() ) ); + connect( ui.checkBoxIgnoreWordOrder, SIGNAL( stateChanged( int ) ), + this, SLOT( ignoreWordsOrderClicked() ) ); model = new HeadwordsListModel( this, results, activeDicts ); ui.headwordsView->setModel( model ); @@ -303,6 +318,7 @@ void FullTextSearchDialog::saveData() cfg.preferences.fts.maxDistanceBetweenWords = ui.distanceBetweenWords->text().toInt(); cfg.preferences.fts.useMaxDistanceBetweenWords = ui.checkBoxDistanceBetweenWords->isChecked(); cfg.preferences.fts.useMaxArticlesPerDictionary = ui.checkBoxArticlesPerDictionary->isChecked(); + cfg.preferences.fts.ignoreWordsOrder = ignoreWordsOrder; cfg.preferences.fts.dialogGeometry = saveGeometry(); } @@ -321,15 +337,24 @@ void FullTextSearchDialog::setLimitsUsing() { ui.checkBoxDistanceBetweenWords->setEnabled( true ); ui.distanceBetweenWords->setEnabled( ui.checkBoxDistanceBetweenWords->isChecked() ); + ui.checkBoxIgnoreWordOrder->setChecked( ignoreWordsOrder ); + ui.checkBoxIgnoreWordOrder->setEnabled( true ); } else { + ui.checkBoxIgnoreWordOrder->setEnabled( false ); + ui.checkBoxIgnoreWordOrder->setChecked( false ); ui.checkBoxDistanceBetweenWords->setEnabled( false ); ui.distanceBetweenWords->setEnabled( false ); } ui.articlesPerDictionary->setEnabled( ui.checkBoxArticlesPerDictionary->isChecked() ); } +void FullTextSearchDialog::ignoreWordsOrderClicked() +{ + ignoreWordsOrder = ui.checkBoxIgnoreWordOrder->isChecked(); +} + void FullTextSearchDialog::accept() { QStringList list1, list2; @@ -395,7 +420,8 @@ void FullTextSearchDialog::accept() mode, ui.matchCase->isChecked(), distanceBetweenWords, - maxResultsPerDict + maxResultsPerDict, + ignoreWordsOrder ); connect( req.get(), SIGNAL( finished() ), this, SLOT( searchReqFinished() ), Qt::QueuedConnection ); @@ -476,7 +502,17 @@ void FullTextSearchDialog::itemClicked( const QModelIndex & idx ) if( idx.isValid() && idx.row() < results.size() ) { QString headword = results[ idx.row() ].headword; - emit showTranslationFor( headword, results[ idx.row() ].dictIDs, searchRegExp ); + QRegExp reg; + if( !results[ idx.row() ].foundHiliteRegExps.isEmpty() ) + { + reg = QRegExp( results[ idx.row() ].foundHiliteRegExps.join( "|"), + results[ idx.row() ].matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive, + QRegExp::RegExp2 ); + reg.setMinimal( true ); + } + else + reg = searchRegExp; + emit showTranslationFor( headword, results[ idx.row() ].dictIDs, reg ); } } @@ -607,7 +643,15 @@ Q_UNUSED( parent ); { QList< FtsHeadword >::iterator it = qBinaryFind( headwords.begin(), headwords.end(), hws.at( x ) ); if( it != headwords.end() ) + { it->dictIDs.push_back( hws.at( x ).dictIDs.front() ); + for( QStringList::const_iterator itr = it->foundHiliteRegExps.constBegin(); + itr != it->foundHiliteRegExps.constEnd(); ++itr ) + { + if( !it->foundHiliteRegExps.contains( *itr ) ) + it->foundHiliteRegExps.append( *itr ); + } + } else temp.append( hws.at( x ) ); } diff --git a/fulltextsearch.hh b/fulltextsearch.hh index dd323a3d..6be03f3f 100644 --- a/fulltextsearch.hh +++ b/fulltextsearch.hh @@ -41,9 +41,14 @@ struct FtsHeadword { QString headword; QStringList dictIDs; + QStringList foundHiliteRegExps; + bool matchCase; - FtsHeadword( QString const & headword_, QString const & dictid_ ) : - headword( headword_ ) + FtsHeadword( QString const & headword_, QString const & dictid_, + QStringList hilites, bool match_case ) : + headword( headword_ ), + foundHiliteRegExps( hilites ), + matchCase( match_case ) { dictIDs.append( dictid_ ); } @@ -169,6 +174,7 @@ class FullTextSearchDialog : public QDialog std::vector< Instances::Group > const & groups; unsigned group; std::vector< sptr< Dictionary::Class > > activeDicts; + bool ignoreWordsOrder; std::list< sptr< Dictionary::DataRequest > > searchReqs; @@ -210,6 +216,7 @@ private slots: void saveData(); void accept(); void setLimitsUsing(); + void ignoreWordsOrderClicked(); void searchReqFinished(); void reject(); void itemClicked( QModelIndex const & idx ); diff --git a/fulltextsearch.ui b/fulltextsearch.ui index b4b97cd9..529c982f 100644 --- a/fulltextsearch.ui +++ b/fulltextsearch.ui @@ -74,6 +74,13 @@ + + + + Ignore words order + + + diff --git a/gls.cc b/gls.cc index 9e485529..1cf34e0d 100644 --- a/gls.cc +++ b/gls.cc @@ -481,7 +481,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); @@ -1382,9 +1383,10 @@ sptr< Dictionary::DataRequest > GlsDictionary::getResource( string const & name sptr< Dictionary::DataRequest > GlsDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } } // anonymous namespace diff --git a/mdx.cc b/mdx.cc index 16568fcd..95e14857 100644 --- a/mdx.cc +++ b/mdx.cc @@ -249,7 +249,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -509,9 +510,10 @@ void MdxDictionary::getArticleText( uint32_t articleAddress, QString & headword, sptr< Dictionary::DataRequest > MdxDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } /// MdxDictionary::getArticle diff --git a/sdict.cc b/sdict.cc index 122a1ac3..43054c9b 100644 --- a/sdict.cc +++ b/sdict.cc @@ -167,7 +167,8 @@ class SdictDictionary: public BtreeIndexing::BtreeDictionary virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -446,9 +447,10 @@ void SdictDictionary::getArticleText( uint32_t articleAddress, QString & headwor sptr< Dictionary::DataRequest > SdictDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } /// SdictDictionary::getArticle() diff --git a/slob.cc b/slob.cc index 579fab7b..d6dfd40c 100644 --- a/slob.cc +++ b/slob.cc @@ -551,7 +551,8 @@ class SlobDictionary: public BtreeIndexing::BtreeDictionary virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -1179,9 +1180,10 @@ void SlobDictionary::getArticleText( uint32_t articleAddress, QString & headword sptr< Dictionary::DataRequest > SlobDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString, searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString, searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } diff --git a/stardict.cc b/stardict.cc index 9c1532ce..8848ca4a 100644 --- a/stardict.cc +++ b/stardict.cc @@ -183,7 +183,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -1020,9 +1021,10 @@ void StardictDictionary::getArticleText( uint32_t articleAddress, QString & head sptr< Dictionary::DataRequest > StardictDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } /// StardictDictionary::findHeadwordsForSynonym() diff --git a/xdxf.cc b/xdxf.cc index c856cbf7..3a92fb62 100644 --- a/xdxf.cc +++ b/xdxf.cc @@ -178,7 +178,8 @@ public: virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); @@ -421,9 +422,10 @@ void XdxfDictionary::getArticleText( uint32_t articleAddress, QString & headword sptr< Dictionary::DataRequest > XdxfDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } /// XdxfDictionary::getArticle() diff --git a/zim.cc b/zim.cc index 94b7303f..7afcc36d 100644 --- a/zim.cc +++ b/zim.cc @@ -372,7 +372,8 @@ class ZimDictionary: public BtreeIndexing::BtreeDictionary virtual sptr< Dictionary::DataRequest > getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ); + int maxResults, + bool ignoreWordsOrder ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); quint32 getArticleText( uint32_t articleAddress, QString & headword, QString & text, @@ -828,9 +829,10 @@ quint32 ZimDictionary::getArticleText( uint32_t articleAddress, QString & headwo sptr< Dictionary::DataRequest > ZimDictionary::getSearchResults( QString const & searchString, int searchMode, bool matchCase, int distanceBetweenWords, - int maxResults ) + int maxResults, + bool ignoreWordsOrder ) { - return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults ); + return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); } /// ZimDictionary::getArticle()