Full-text search: Allow ignore diacritics while search

This commit is contained in:
Abs62 2018-04-10 17:49:52 +03:00
parent eb6dc37470
commit 5fa5cc123f
29 changed files with 280 additions and 92 deletions

View file

@ -272,7 +272,8 @@ class AardDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -654,9 +655,10 @@ sptr< Dictionary::DataRequest > AardDictionary::getSearchResults( QString const
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
/// AardDictionary::getArticle() /// AardDictionary::getArticle()

View file

@ -52,15 +52,20 @@ using std::list;
class AccentMarkHandler class AccentMarkHandler
{ {
protected:
QString normalizedString; QString normalizedString;
QVector< int > accentMarkPos; QVector< int > accentMarkPos;
public: public:
AccentMarkHandler()
{}
virtual ~AccentMarkHandler()
{}
static QChar accentMark() static QChar accentMark()
{ return QChar( 0x301 ); } { return QChar( 0x301 ); }
/// Create text without accent marks /// Create text without accent marks
/// and store mark positions /// and store mark positions
void setText( QString const & baseString ) virtual void setText( QString const & baseString )
{ {
accentMarkPos.clear(); accentMarkPos.clear();
normalizedString.clear(); normalizedString.clear();
@ -100,6 +105,72 @@ public:
/// End of DslAccentMark class /// End of DslAccentMark class
/// DiacriticsHandler class
///
/// Remove diacritics from text
/// and mirror position in normalized text to original text
class DiacriticsHandler : public AccentMarkHandler
{
public:
DiacriticsHandler()
{}
~DiacriticsHandler()
{}
/// Create text without diacriticss
/// and store diacritic marks positions
virtual void setText( QString const & baseString )
{
accentMarkPos.clear();
normalizedString.clear();
gd::wstring baseText = gd::toWString( baseString );
gd::wstring normText;
int pos = 0;
normText.reserve( baseText.size() );
gd::wchar const * nextChar = baseText.data();
size_t consumed;
for( size_t left = baseText.size(); left; )
{
if( *nextChar >= 0x10000U )
{
// Will be translated into surrogate pair
normText.push_back( *nextChar );
pos += 2;
nextChar++; left--;
continue;
}
gd::wchar ch = Folding::foldedDiacritic( nextChar, left, consumed );
if( Folding::isCombiningMark( ch ) )
{
accentMarkPos.append( pos );
nextChar++; left--;
continue;
}
if( consumed > 1 )
{
for( size_t i = 1; i < consumed; i++ )
accentMarkPos.append( pos );
}
normText.push_back( ch );
pos += 1;
nextChar += consumed;
left -= consumed;
}
normalizedString = gd::toQString( normText );
}
};
/// End of DiacriticsHandler class
static QVariant evaluateJavaScriptVariableSafe( QWebFrame * frame, const QString & variable ) static QVariant evaluateJavaScriptVariableSafe( QWebFrame * frame, const QString & variable )
{ {
return frame->evaluateJavaScript( return frame->evaluateJavaScript(
@ -340,7 +411,8 @@ void ArticleView::showDefinition( QString const & word, unsigned group,
} }
void ArticleView::showDefinition( QString const & word, QStringList const & dictIDs, void ArticleView::showDefinition( QString const & word, QStringList const & dictIDs,
QRegExp const & searchRegExp, unsigned group ) QRegExp const & searchRegExp, unsigned group,
bool ignoreDiacritics )
{ {
if( dictIDs.isEmpty() ) if( dictIDs.isEmpty() )
return; return;
@ -360,6 +432,8 @@ void ArticleView::showDefinition( QString const & word, QStringList const & dict
if( searchRegExp.patternSyntax() == QRegExp::WildcardUnix ) if( searchRegExp.patternSyntax() == QRegExp::WildcardUnix )
Qt4x5::Url::addQueryItem( req, "wildcards", "1" ); Qt4x5::Url::addQueryItem( req, "wildcards", "1" );
Qt4x5::Url::addQueryItem( req, "group", QString::number( group ) ); Qt4x5::Url::addQueryItem( req, "group", QString::number( group ) );
if( ignoreDiacritics )
Qt4x5::Url::addQueryItem( req, "ignore_diacritics", "1" );
// Update both histories (pages history and headwords history) // Update both histories (pages history and headwords history)
saveHistoryUserData(); saveHistoryUserData();
@ -1060,7 +1134,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QStringList dictsList = Qt4x5::Url::queryItemValue( ref, "dictionaries" ) QStringList dictsList = Qt4x5::Url::queryItemValue( ref, "dictionaries" )
.split( ",", QString::SkipEmptyParts ); .split( ",", QString::SkipEmptyParts );
showDefinition( url.path(), dictsList, QRegExp(), getGroup( ref ) ); showDefinition( url.path(), dictsList, QRegExp(), getGroup( ref ), false );
} }
else else
showDefinition( url.path(), showDefinition( url.path(),
@ -1082,7 +1156,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QStringList dictsList = Qt4x5::Url::queryItemValue( ref, "dictionaries" ) QStringList dictsList = Qt4x5::Url::queryItemValue( ref, "dictionaries" )
.split( ",", QString::SkipEmptyParts ); .split( ",", QString::SkipEmptyParts );
showDefinition( url.path().mid( 1 ), dictsList, QRegExp(), getGroup( ref ) ); showDefinition( url.path().mid( 1 ), dictsList, QRegExp(), getGroup( ref ), false );
return; return;
} }
@ -2200,7 +2274,7 @@ void ArticleView::doubleClicked( QPoint pos )
{ {
QStringList dictsList = Qt4x5::Url::queryItemValue(ref, "dictionaries" ) QStringList dictsList = Qt4x5::Url::queryItemValue(ref, "dictionaries" )
.split( ",", QString::SkipEmptyParts ); .split( ",", QString::SkipEmptyParts );
showDefinition( selectedText, dictsList, QRegExp(), getGroup( ref ) ); showDefinition( selectedText, dictsList, QRegExp(), getGroup( ref ), false );
} }
else else
showDefinition( selectedText, getGroup( ref ), getCurrentArticle() ); showDefinition( selectedText, getGroup( ref ), getCurrentArticle() );
@ -2368,18 +2442,29 @@ void ArticleView::highlightFTSResults()
{ {
closeSearch(); closeSearch();
AccentMarkHandler markHandler;
const QUrl & url = ui.definition->url(); const QUrl & url = ui.definition->url();
QRegExp regexp( Qt4x5::Url::queryItemValue( url, "regexp" ).remove( AccentMarkHandler::accentMark() ),
bool ignoreDiacritics = Qt4x5::Url::hasQueryItem( url, "ignore_diacritics" );
QString regString = Qt4x5::Url::queryItemValue( url, "regexp" );
if( ignoreDiacritics )
regString = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( regString ) ) );
else
regString = regString.remove( AccentMarkHandler::accentMark() );
QRegExp regexp( regString,
Qt4x5::Url::hasQueryItem( url, "matchcase" ) ? Qt::CaseSensitive : Qt::CaseInsensitive, Qt4x5::Url::hasQueryItem( url, "matchcase" ) ? Qt::CaseSensitive : Qt::CaseInsensitive,
Qt4x5::Url::hasQueryItem( url, "wildcards" ) ? QRegExp::WildcardUnix : QRegExp::RegExp2 ); Qt4x5::Url::hasQueryItem( url, "wildcards" ) ? QRegExp::WildcardUnix : QRegExp::RegExp2 );
if( regexp.pattern().isEmpty() ) if( regexp.pattern().isEmpty() )
return; return;
regexp.setMinimal( true ); regexp.setMinimal( true );
sptr< AccentMarkHandler > marksHandler = ignoreDiacritics ?
new DiacriticsHandler : new AccentMarkHandler;
// Clear any current selection // Clear any current selection
if ( ui.definition->selectedText().size() ) if ( ui.definition->selectedText().size() )
{ {
@ -2388,18 +2473,23 @@ void ArticleView::highlightFTSResults()
} }
QString pageText = ui.definition->page()->currentFrame()->toPlainText(); QString pageText = ui.definition->page()->currentFrame()->toPlainText();
markHandler.setText( pageText ); marksHandler->setText( pageText );
int pos = 0; int pos = 0;
while( pos >= 0 ) while( pos >= 0 )
{ {
pos = regexp.indexIn( markHandler.normalizedText(), pos ); pos = regexp.indexIn( marksHandler->normalizedText(), pos );
if( pos >= 0 ) if( pos >= 0 )
{ {
// Mirror pos and matched length to original string // Mirror pos and matched length to original string
int spos = markHandler.mirrorPosition( pos ); int spos = marksHandler->mirrorPosition( pos );
int matched = markHandler.mirrorPosition( pos + regexp.matchedLength() ) - spos; int matched = marksHandler->mirrorPosition( pos + regexp.matchedLength() ) - spos;
// Add mark pos (if presented)
while( spos + matched < pageText.length()
&& pageText[ spos + matched ].category() == QChar::Mark_NonSpacing )
matched++;
if( matched > FTS::MaxMatchLengthForHighlightResults ) if( matched > FTS::MaxMatchLengthForHighlightResults )
{ {

View file

@ -101,7 +101,8 @@ public:
Contexts const & contexts = Contexts() ); Contexts const & contexts = Contexts() );
void showDefinition( QString const & word, QStringList const & dictIDs, void showDefinition( QString const & word, QStringList const & dictIDs,
QRegExp const & searchRegExp, unsigned group ); QRegExp const & searchRegExp, unsigned group,
bool ignoreDiacritics );
/// Clears the view and sets the application-global waiting cursor, /// Clears the view and sets the application-global waiting cursor,
/// which will be restored when some article loads eventually. /// which will be restored when some article loads eventually.

8
bgl.cc
View file

@ -242,7 +242,8 @@ namespace
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual QString const& getDescription(); virtual QString const& getDescription();
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
@ -1199,9 +1200,10 @@ sptr< Dictionary::DataRequest > BglDictionary::getSearchResults( QString const &
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }

View file

@ -83,7 +83,7 @@ void BtreeIndex::openIndex( IndexInfo const & indexInfo,
rootNode.clear(); rootNode.clear();
} }
vector< WordArticleLink > BtreeIndex::findArticles( wstring const & word ) vector< WordArticleLink > BtreeIndex::findArticles( wstring const & word, bool ignoreDiacritics )
{ {
vector< WordArticleLink > result; vector< WordArticleLink > result;
@ -108,7 +108,7 @@ vector< WordArticleLink > BtreeIndex::findArticles( wstring const & word )
{ {
result = readChain( chainOffset ); result = readChain( chainOffset );
antialias( word, result ); antialias( word, result, ignoreDiacritics );
} }
} }
catch( std::exception & e ) catch( std::exception & e )
@ -910,7 +910,8 @@ vector< WordArticleLink > BtreeIndex::readChain( char const * & ptr )
} }
void BtreeIndex::antialias( wstring const & str, void BtreeIndex::antialias( wstring const & str,
vector< WordArticleLink > & chain ) vector< WordArticleLink > & chain,
bool ignoreDiacritics )
{ {
wstring caseFolded = Folding::applySimpleCaseOnly( gd::normalize( str ) ); wstring caseFolded = Folding::applySimpleCaseOnly( gd::normalize( str ) );
@ -918,8 +919,11 @@ void BtreeIndex::antialias( wstring const & str,
{ {
// If after applying case folding to each word they wouldn't match, we // If after applying case folding to each word they wouldn't match, we
// drop the entry. // drop the entry.
if ( Folding::applySimpleCaseOnly( gd::normalize( Utf8::decode( chain[ x ].prefix + chain[ x ].word ) ) ) != wstring entry = Folding::applySimpleCaseOnly( gd::normalize( Utf8::decode( chain[ x ].prefix + chain[ x ].word ) ) );
caseFolded ) if( ignoreDiacritics )
entry = Folding::applyDiacriticsOnly( entry );
if ( entry != caseFolded )
chain.erase( chain.begin() + x ); chain.erase( chain.begin() + x );
else else
if ( chain[ x ].prefix.size() ) // If there's a prefix, merge it with the word, if ( chain[ x ].prefix.size() ) // If there's a prefix, merge it with the word,

View file

@ -84,7 +84,7 @@ public:
/// Finds articles that match the given string. A case-insensitive search /// Finds articles that match the given string. A case-insensitive search
/// is performed. /// is performed.
vector< WordArticleLink > findArticles( wstring const & ); vector< WordArticleLink > findArticles( wstring const &, bool ignoreDiacritics = false );
/// Find all unique article links in the index /// Find all unique article links in the index
void findAllArticleLinks( QVector< WordArticleLink > & articleLinks ); void findAllArticleLinks( QVector< WordArticleLink > & articleLinks );
@ -133,7 +133,7 @@ protected:
/// Drops any alises which arose due to folding. Only case-folded aliases /// Drops any alises which arose due to folding. Only case-folded aliases
/// are left. /// are left.
void antialias( wstring const &, vector< WordArticleLink > & ); void antialias( wstring const &, vector< WordArticleLink > &, bool ignoreDiactitics );
protected: protected:

View file

@ -931,6 +931,9 @@ Class load() throw( exError )
if ( !fts.namedItem( "ignoreWordsOrder" ).isNull() ) if ( !fts.namedItem( "ignoreWordsOrder" ).isNull() )
c.preferences.fts.ignoreWordsOrder = ( fts.namedItem( "ignoreWordsOrder" ).toElement().text() == "1" ); c.preferences.fts.ignoreWordsOrder = ( fts.namedItem( "ignoreWordsOrder" ).toElement().text() == "1" );
if ( !fts.namedItem( "ignoreDiacritics" ).isNull() )
c.preferences.fts.ignoreDiacritics = ( fts.namedItem( "ignoreDiacritics" ).toElement().text() == "1" );
if ( !fts.namedItem( "maxDictionarySize" ).isNull() ) if ( !fts.namedItem( "maxDictionarySize" ).isNull() )
c.preferences.fts.maxDictionarySize = fts.namedItem( "maxDictionarySize" ).toElement().text().toUInt(); c.preferences.fts.maxDictionarySize = fts.namedItem( "maxDictionarySize" ).toElement().text().toUInt();
} }
@ -1878,6 +1881,10 @@ void save( Class const & c ) throw( exError )
opt.appendChild( dd.createTextNode( c.preferences.fts.ignoreWordsOrder ? "1" : "0" ) ); opt.appendChild( dd.createTextNode( c.preferences.fts.ignoreWordsOrder ? "1" : "0" ) );
hd.appendChild( opt ); hd.appendChild( opt );
opt = dd.createElement( "ignoreDiacritics" );
opt.appendChild( dd.createTextNode( c.preferences.fts.ignoreDiacritics ? "1" : "0" ) );
hd.appendChild( opt );
opt = dd.createElement( "maxDictionarySize" ); opt = dd.createElement( "maxDictionarySize" );
opt.appendChild( dd.createTextNode( QString::number( c.preferences.fts.maxDictionarySize ) ) ); opt.appendChild( dd.createTextNode( QString::number( c.preferences.fts.maxDictionarySize ) ) );
hd.appendChild( opt ); hd.appendChild( opt );

View file

@ -161,6 +161,7 @@ struct FullTextSearch
bool useMaxArticlesPerDictionary; bool useMaxArticlesPerDictionary;
bool enabled; bool enabled;
bool ignoreWordsOrder; bool ignoreWordsOrder;
bool ignoreDiacritics;
quint32 maxDictionarySize; quint32 maxDictionarySize;
QByteArray dialogGeometry; QByteArray dialogGeometry;
QString disabledTypes; QString disabledTypes;
@ -173,6 +174,7 @@ struct FullTextSearch
useMaxArticlesPerDictionary( false ), useMaxArticlesPerDictionary( false ),
enabled( true ), enabled( true ),
ignoreWordsOrder( false ), ignoreWordsOrder( false ),
ignoreDiacritics( false ),
maxDictionarySize( 0 ) maxDictionarySize( 0 )
{} {}
}; };

View file

@ -133,7 +133,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -588,9 +589,10 @@ sptr< Dictionary::DataRequest > DictdDictionary::getSearchResults( QString const
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
} // anonymous namespace } // anonymous namespace

View file

@ -175,7 +175,7 @@ sptr< DataRequest > Class::getResource( string const & /*name*/ )
return new DataRequestInstant( false ); return new DataRequestInstant( false );
} }
sptr< DataRequest > Class::getSearchResults(const QString &, int, bool, int, int, bool ) sptr< DataRequest > Class::getSearchResults(const QString &, int, bool, int, int, bool, bool )
{ {
return new DataRequestInstant( false ); return new DataRequestInstant( false );
} }

View file

@ -397,7 +397,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxArticlesPerDictionary, int maxArticlesPerDictionary,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
// Return dictionary description if presented // Return dictionary description if presented
virtual QString const& getDescription(); virtual QString const& getDescription();

8
dsl.cc
View file

@ -227,7 +227,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual QString const& getDescription(); virtual QString const& getDescription();
virtual QString getMainFilename(); virtual QString getMainFilename();
@ -1991,9 +1992,10 @@ sptr< Dictionary::DataRequest > DslDictionary::getSearchResults( QString const &
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
} // anonymous namespace } // anonymous namespace

View file

@ -128,7 +128,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -784,9 +785,10 @@ sptr< Dictionary::DataRequest > EpwingDictionary::getSearchResults( QString cons
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
int EpwingDictionary::japaneseWriting( gd::wchar ch ) int EpwingDictionary::japaneseWriting( gd::wchar ch )

View file

@ -10,8 +10,6 @@
namespace Folding { namespace Folding {
namespace
{
#include "inc_case_folding.hh" #include "inc_case_folding.hh"
#include "inc_diacritic_folding.hh" #include "inc_diacritic_folding.hh"
@ -28,7 +26,6 @@ namespace
( ch >= 0xFE20 && ch <= 0xFE2F ) ( ch >= 0xFE20 && ch <= 0xFE2F )
); );
} }
}
wstring apply( wstring const & in, bool preserveWildcards ) wstring apply( wstring const & in, bool preserveWildcards )
{ {
@ -691,4 +688,10 @@ QString unescapeWildcardSymbols( const QString & str )
return unescaped; return unescaped;
} }
wchar foldedDiacritic( wchar const * in, size_t size, size_t & consumed )
{
return foldDiacritic( in, size, consumed );
}
} }

View file

@ -85,6 +85,12 @@ QString unescapeWildcardSymbols( QString const & );
/// Escape all wildcard symbols (for place word to input line) /// Escape all wildcard symbols (for place word to input line)
QString escapeWildcardSymbols( QString const & ); QString escapeWildcardSymbols( QString const & );
/// Return result of foldDiacritic() from "inc_diacritic_folding.hh"
wchar foldedDiacritic( wchar const * in, size_t size, size_t & consumed );
/// Tests if the given char is one of the Unicode combining marks.
bool isCombiningMark( wchar ch );
} }
#endif #endif

View file

@ -6,6 +6,7 @@
#include "wstring_qt.hh" #include "wstring_qt.hh"
#include "file.hh" #include "file.hh"
#include "gddebug.hh" #include "gddebug.hh"
#include "folding.hh"
#include "qt4x5.hh" #include "qt4x5.hh"
#include <vector> #include <vector>
@ -472,6 +473,9 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets,
dict.getArticleText( offsets.at( i ), headword, articleText ); dict.getArticleText( offsets.at( i ), headword, articleText );
articleText = articleText.normalized( QString::NormalizationForm_C ); articleText = articleText.normalized( QString::NormalizationForm_C );
if( ignoreDiacritics )
articleText = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( articleText ) ) );
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
if( articleText.contains( searchRegularExpression ) ) if( articleText.contains( searchRegularExpression ) )
#else #else
@ -530,8 +534,12 @@ void FTSResultsRequest::checkArticles( QVector< uint32_t > const & offsets,
dict.getArticleText( offsets.at( i ), headword, articleText ); dict.getArticleText( offsets.at( i ), headword, articleText );
QStringList articleWords = articleText.normalized( QString::NormalizationForm_C ) articleText = articleText.normalized( QString::NormalizationForm_C );
.split( needHandleBrackets ? splitWithBrackets : splitWithoutBrackets,
if( ignoreDiacritics )
articleText = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( articleText ) ) );
QStringList articleWords = articleText.split( needHandleBrackets ? splitWithBrackets : splitWithoutBrackets,
QString::SkipEmptyParts ); QString::SkipEmptyParts );
int wordsNum = articleWords.length(); int wordsNum = articleWords.length();
@ -802,7 +810,7 @@ void FTSResultsRequest::indexSearch( BtreeIndexing::BtreeIndex & ftsIndex,
tmp.clear(); tmp.clear();
links = ftsIndex.findArticles( gd::toWString( indexWords.at( i ) ) ); links = ftsIndex.findArticles( gd::toWString( indexWords.at( i ) ), ignoreDiacritics );
for( unsigned x = 0; x < links.size(); x++ ) for( unsigned x = 0; x < links.size(); x++ )
{ {
@ -949,6 +957,10 @@ void FTSResultsRequest::combinedIndexSearch( BtreeIndexing::BtreeIndex & ftsInde
return; return;
QString word = QString::fromUtf8( links[ x ].word.data(), links[ x ].word.size() ); QString word = QString::fromUtf8( links[ x ].word.data(), links[ x ].word.size() );
if( ignoreDiacritics )
word = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( word ) ) );
for( int i = 0; i < wordsList.size(); i++ ) for( int i = 0; i < wordsList.size(); i++ )
{ {
if( word.length() >= wordsList.at( i ).length() && word.contains( wordsList.at( i ) ) ) if( word.length() >= wordsList.at( i ).length() && word.contains( wordsList.at( i ) ) )
@ -1035,6 +1047,10 @@ void FTSResultsRequest::fullIndexSearch( BtreeIndexing::BtreeIndex & ftsIndex,
return; return;
QString word = QString::fromUtf8( links[ x ].word.data(), links[ x ].word.size() ); QString word = QString::fromUtf8( links[ x ].word.data(), links[ x ].word.size() );
if( ignoreDiacritics )
word = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( word ) ) );
for( int i = 0; i < indexWords.size(); i++ ) for( int i = 0; i < indexWords.size(); i++ )
{ {
if( word.length() >= indexWords.at( i ).length() && word.contains( indexWords.at( i ) ) ) if( word.length() >= indexWords.at( i ).length() && word.contains( indexWords.at( i ) ) )

View file

@ -11,6 +11,8 @@
#include "btreeidx.hh" #include "btreeidx.hh"
#include "fulltextsearch.hh" #include "fulltextsearch.hh"
#include "chunkedstorage.hh" #include "chunkedstorage.hh"
#include "folding.hh"
#include "wstring_qt.hh"
#include <string> #include <string>
@ -92,6 +94,7 @@ class FTSResultsRequest : public Dictionary::DataRequest
int maxResults; int maxResults;
bool hasCJK; bool hasCJK;
bool ignoreWordsOrder; bool ignoreWordsOrder;
bool ignoreDiacritics;
int wordsInIndex; int wordsInIndex;
QAtomicInt isCancelled; QAtomicInt isCancelled;
@ -126,7 +129,7 @@ public:
FTSResultsRequest( BtreeIndexing::BtreeDictionary & dict_, QString const & searchString_, 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_ ): bool ignoreWordsOrder_, bool ignoreDiacritics_ ):
dict( dict_ ), dict( dict_ ),
searchString( searchString_ ), searchString( searchString_ ),
searchMode( searchMode_ ), searchMode( searchMode_ ),
@ -135,8 +138,12 @@ public:
maxResults( maxResults_ ), maxResults( maxResults_ ),
hasCJK( false ), hasCJK( false ),
ignoreWordsOrder( ignoreWordsOrder_ ), ignoreWordsOrder( ignoreWordsOrder_ ),
ignoreDiacritics( ignoreDiacritics_ ),
wordsInIndex( 0 ) wordsInIndex( 0 )
{ {
if( ignoreDiacritics_ )
searchString = gd::toQString( Folding::applyDiacriticsOnly( gd::toWString( searchString_ ) ) );
foundHeadwords = new QList< FTS::FtsHeadword >; foundHeadwords = new QList< FTS::FtsHeadword >;
QThreadPool::globalInstance()->start( QThreadPool::globalInstance()->start(
new FTSResultsRequestRunnable( *this, hasExited ), -100 ); new FTSResultsRequestRunnable( *this, hasExited ), -100 );

View file

@ -137,6 +137,7 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
groups( groups_ ), groups( groups_ ),
group( 0 ), group( 0 ),
ignoreWordsOrder( cfg_.preferences.fts.ignoreWordsOrder ), ignoreWordsOrder( cfg_.preferences.fts.ignoreWordsOrder ),
ignoreDiacritics( cfg_.preferences.fts.ignoreDiacritics ),
ftsIdx( ftsidx ) ftsIdx( ftsidx )
, helpAction( this ) , helpAction( this )
{ {
@ -193,6 +194,8 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
ui.checkBoxIgnoreWordOrder->setEnabled( false ); ui.checkBoxIgnoreWordOrder->setEnabled( false );
} }
ui.checkBoxIgnoreDiacritics->setChecked( ignoreDiacritics );
ui.matchCase->setChecked( cfg.preferences.fts.matchCase ); ui.matchCase->setChecked( cfg.preferences.fts.matchCase );
setLimitsUsing(); setLimitsUsing();
@ -205,6 +208,8 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
this, SLOT( setLimitsUsing() ) ); this, SLOT( setLimitsUsing() ) );
connect( ui.checkBoxIgnoreWordOrder, SIGNAL( stateChanged( int ) ), connect( ui.checkBoxIgnoreWordOrder, SIGNAL( stateChanged( int ) ),
this, SLOT( ignoreWordsOrderClicked() ) ); this, SLOT( ignoreWordsOrderClicked() ) );
connect( ui.checkBoxIgnoreDiacritics, SIGNAL( stateChanged( int ) ),
this, SLOT( ignoreDiacriticsClicked() ) );
model = new HeadwordsListModel( this, results, activeDicts ); model = new HeadwordsListModel( this, results, activeDicts );
ui.headwordsView->setModel( model ); ui.headwordsView->setModel( model );
@ -319,6 +324,7 @@ void FullTextSearchDialog::saveData()
cfg.preferences.fts.useMaxDistanceBetweenWords = ui.checkBoxDistanceBetweenWords->isChecked(); cfg.preferences.fts.useMaxDistanceBetweenWords = ui.checkBoxDistanceBetweenWords->isChecked();
cfg.preferences.fts.useMaxArticlesPerDictionary = ui.checkBoxArticlesPerDictionary->isChecked(); cfg.preferences.fts.useMaxArticlesPerDictionary = ui.checkBoxArticlesPerDictionary->isChecked();
cfg.preferences.fts.ignoreWordsOrder = ignoreWordsOrder; cfg.preferences.fts.ignoreWordsOrder = ignoreWordsOrder;
cfg.preferences.fts.ignoreDiacritics = ignoreDiacritics;
cfg.preferences.fts.dialogGeometry = saveGeometry(); cfg.preferences.fts.dialogGeometry = saveGeometry();
} }
@ -355,6 +361,11 @@ void FullTextSearchDialog::ignoreWordsOrderClicked()
ignoreWordsOrder = ui.checkBoxIgnoreWordOrder->isChecked(); ignoreWordsOrder = ui.checkBoxIgnoreWordOrder->isChecked();
} }
void FullTextSearchDialog::ignoreDiacriticsClicked()
{
ignoreDiacritics = ui.checkBoxIgnoreDiacritics->isChecked();
}
void FullTextSearchDialog::accept() void FullTextSearchDialog::accept()
{ {
QStringList list1, list2; QStringList list1, list2;
@ -421,7 +432,8 @@ void FullTextSearchDialog::accept()
ui.matchCase->isChecked(), ui.matchCase->isChecked(),
distanceBetweenWords, distanceBetweenWords,
maxResultsPerDict, maxResultsPerDict,
ignoreWordsOrder ignoreWordsOrder,
ignoreDiacritics
); );
connect( req.get(), SIGNAL( finished() ), connect( req.get(), SIGNAL( finished() ),
this, SLOT( searchReqFinished() ), Qt::QueuedConnection ); this, SLOT( searchReqFinished() ), Qt::QueuedConnection );
@ -512,7 +524,7 @@ void FullTextSearchDialog::itemClicked( const QModelIndex & idx )
} }
else else
reg = searchRegExp; reg = searchRegExp;
emit showTranslationFor( headword, results[ idx.row() ].dictIDs, reg ); emit showTranslationFor( headword, results[ idx.row() ].dictIDs, reg, ignoreDiacritics );
} }
} }

View file

@ -175,6 +175,7 @@ class FullTextSearchDialog : public QDialog
unsigned group; unsigned group;
std::vector< sptr< Dictionary::Class > > activeDicts; std::vector< sptr< Dictionary::Class > > activeDicts;
bool ignoreWordsOrder; bool ignoreWordsOrder;
bool ignoreDiacritics;
std::list< sptr< Dictionary::DataRequest > > searchReqs; std::list< sptr< Dictionary::DataRequest > > searchReqs;
@ -217,6 +218,7 @@ private slots:
void accept(); void accept();
void setLimitsUsing(); void setLimitsUsing();
void ignoreWordsOrderClicked(); void ignoreWordsOrderClicked();
void ignoreDiacriticsClicked();
void searchReqFinished(); void searchReqFinished();
void reject(); void reject();
void itemClicked( QModelIndex const & idx ); void itemClicked( QModelIndex const & idx );
@ -225,7 +227,7 @@ private slots:
signals: signals:
void showTranslationFor( QString const &, QStringList const & dictIDs, void showTranslationFor( QString const &, QStringList const & dictIDs,
QRegExp const & searchRegExp ); QRegExp const & searchRegExp, bool ignoreDiacritics );
void closeDialog(); void closeDialog();
}; };

View file

@ -74,6 +74,8 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
<widget class="QCheckBox" name="checkBoxIgnoreWordOrder"> <widget class="QCheckBox" name="checkBoxIgnoreWordOrder">
<property name="text"> <property name="text">
@ -81,6 +83,15 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBoxIgnoreDiacritics">
<property name="text">
<string>Ignore diacritics</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

8
gls.cc
View file

@ -487,7 +487,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
@ -1546,9 +1547,10 @@ sptr< Dictionary::DataRequest > GlsDictionary::getSearchResults( QString const &
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
} // anonymous namespace } // anonymous namespace

View file

@ -2792,14 +2792,16 @@ void MainWindow::showTranslationFor( QString const & inWord,
void MainWindow::showTranslationFor( QString const & inWord, void MainWindow::showTranslationFor( QString const & inWord,
QStringList const & dictIDs, QStringList const & dictIDs,
QRegExp const & searchRegExp ) QRegExp const & searchRegExp,
bool ignoreDiacritics )
{ {
ArticleView *view = getCurrentArticleView(); ArticleView *view = getCurrentArticleView();
navPronounce->setEnabled( false ); navPronounce->setEnabled( false );
view->showDefinition( inWord, dictIDs, searchRegExp, view->showDefinition( inWord, dictIDs, searchRegExp,
groupInstances[ groupList->currentIndex() ].id ); groupInstances[ groupList->currentIndex() ].id,
ignoreDiacritics );
updatePronounceAvailability(); updatePronounceAvailability();
updateFoundInDictsList(); updateFoundInDictsList();
@ -4407,8 +4409,8 @@ void MainWindow::showFullTextSearchDialog()
ftsDlg = new FTS::FullTextSearchDialog( this, cfg, dictionaries, groupInstances, ftsIndexing ); ftsDlg = new FTS::FullTextSearchDialog( this, cfg, dictionaries, groupInstances, ftsIndexing );
addGlobalActionsToDialog( ftsDlg ); addGlobalActionsToDialog( ftsDlg );
connect( ftsDlg, SIGNAL( showTranslationFor( QString, QStringList, QRegExp ) ), connect( ftsDlg, SIGNAL( showTranslationFor( QString, QStringList, QRegExp, bool ) ),
this, SLOT( showTranslationFor( QString, QStringList, QRegExp ) ) ); this, SLOT( showTranslationFor( QString, QStringList, QRegExp, bool ) ) );
connect( ftsDlg, SIGNAL( closeDialog() ), connect( ftsDlg, SIGNAL( closeDialog() ),
this, SLOT( closeFullTextSearchDialog() ), Qt::QueuedConnection ); this, SLOT( closeFullTextSearchDialog() ), Qt::QueuedConnection );
connect( &configEvents, SIGNAL( mutedDictionariesChanged() ), connect( &configEvents, SIGNAL( mutedDictionariesChanged() ),

View file

@ -391,7 +391,7 @@ private slots:
QString const & dictID = QString() ); QString const & dictID = QString() );
void showTranslationFor( QString const &, QStringList const & dictIDs, void showTranslationFor( QString const &, QStringList const & dictIDs,
QRegExp const & searchRegExp ); QRegExp const & searchRegExp, bool ignoreDiacritics );
void showHistoryItem( QString const & ); void showHistoryItem( QString const & );

8
mdx.cc
View file

@ -254,7 +254,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -515,9 +516,10 @@ sptr< Dictionary::DataRequest > MdxDictionary::getSearchResults( QString const &
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
/// MdxDictionary::getArticle /// MdxDictionary::getArticle

View file

@ -172,7 +172,8 @@ class SdictDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -477,9 +478,10 @@ sptr< Dictionary::DataRequest > SdictDictionary::getSearchResults( QString const
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
/// SdictDictionary::getArticle() /// SdictDictionary::getArticle()

View file

@ -556,7 +556,8 @@ class SlobDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -1262,9 +1263,10 @@ sptr< Dictionary::DataRequest > SlobDictionary::getSearchResults( QString const
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString, searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString, searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }

View file

@ -190,7 +190,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -1264,9 +1265,10 @@ sptr< Dictionary::DataRequest > StardictDictionary::getSearchResults( QString co
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
/// StardictDictionary::findHeadwordsForSynonym() /// StardictDictionary::findHeadwordsForSynonym()

View file

@ -179,7 +179,8 @@ public:
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration ); virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -423,9 +424,10 @@ sptr< Dictionary::DataRequest > XdxfDictionary::getSearchResults( QString const
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
/// XdxfDictionary::getArticle() /// XdxfDictionary::getArticle()

8
zim.cc
View file

@ -569,7 +569,8 @@ class ZimDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ); bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text ); virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
quint32 getArticleText( uint32_t articleAddress, QString & headword, QString & text, quint32 getArticleText( uint32_t articleAddress, QString & headword, QString & text,
@ -1148,9 +1149,10 @@ sptr< Dictionary::DataRequest > ZimDictionary::getSearchResults( QString const &
int searchMode, bool matchCase, int searchMode, bool matchCase,
int distanceBetweenWords, int distanceBetweenWords,
int maxResults, int maxResults,
bool ignoreWordsOrder ) bool ignoreWordsOrder,
bool ignoreDiacritics )
{ {
return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder ); return new FtsHelpers::FTSResultsRequest( *this, searchString,searchMode, matchCase, distanceBetweenWords, maxResults, ignoreWordsOrder, ignoreDiacritics );
} }
/// ZimDictionary::getArticle() /// ZimDictionary::getArticle()