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 distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -654,9 +655,10 @@ sptr< Dictionary::DataRequest > AardDictionary::getSearchResults( QString const
int searchMode, bool matchCase,
int distanceBetweenWords,
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()

View file

@ -52,15 +52,20 @@ using std::list;
class AccentMarkHandler
{
protected:
QString normalizedString;
QVector< int > accentMarkPos;
public:
AccentMarkHandler()
{}
virtual ~AccentMarkHandler()
{}
static QChar accentMark()
{ return QChar( 0x301 ); }
/// Create text without accent marks
/// and store mark positions
void setText( QString const & baseString )
virtual void setText( QString const & baseString )
{
accentMarkPos.clear();
normalizedString.clear();
@ -100,6 +105,72 @@ public:
/// 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 )
{
return frame->evaluateJavaScript(
@ -340,7 +411,8 @@ void ArticleView::showDefinition( QString const & word, unsigned group,
}
void ArticleView::showDefinition( QString const & word, QStringList const & dictIDs,
QRegExp const & searchRegExp, unsigned group )
QRegExp const & searchRegExp, unsigned group,
bool ignoreDiacritics )
{
if( dictIDs.isEmpty() )
return;
@ -360,6 +432,8 @@ void ArticleView::showDefinition( QString const & word, QStringList const & dict
if( searchRegExp.patternSyntax() == QRegExp::WildcardUnix )
Qt4x5::Url::addQueryItem( req, "wildcards", "1" );
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)
saveHistoryUserData();
@ -1060,7 +1134,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QStringList dictsList = Qt4x5::Url::queryItemValue( ref, "dictionaries" )
.split( ",", QString::SkipEmptyParts );
showDefinition( url.path(), dictsList, QRegExp(), getGroup( ref ) );
showDefinition( url.path(), dictsList, QRegExp(), getGroup( ref ), false );
}
else
showDefinition( url.path(),
@ -1082,7 +1156,7 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
QStringList dictsList = Qt4x5::Url::queryItemValue( ref, "dictionaries" )
.split( ",", QString::SkipEmptyParts );
showDefinition( url.path().mid( 1 ), dictsList, QRegExp(), getGroup( ref ) );
showDefinition( url.path().mid( 1 ), dictsList, QRegExp(), getGroup( ref ), false );
return;
}
@ -2200,7 +2274,7 @@ void ArticleView::doubleClicked( QPoint pos )
{
QStringList dictsList = Qt4x5::Url::queryItemValue(ref, "dictionaries" )
.split( ",", QString::SkipEmptyParts );
showDefinition( selectedText, dictsList, QRegExp(), getGroup( ref ) );
showDefinition( selectedText, dictsList, QRegExp(), getGroup( ref ), false );
}
else
showDefinition( selectedText, getGroup( ref ), getCurrentArticle() );
@ -2368,18 +2442,29 @@ void ArticleView::highlightFTSResults()
{
closeSearch();
AccentMarkHandler markHandler;
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, "wildcards" ) ? QRegExp::WildcardUnix : QRegExp::RegExp2 );
if( regexp.pattern().isEmpty() )
return;
regexp.setMinimal( true );
sptr< AccentMarkHandler > marksHandler = ignoreDiacritics ?
new DiacriticsHandler : new AccentMarkHandler;
// Clear any current selection
if ( ui.definition->selectedText().size() )
{
@ -2388,18 +2473,23 @@ void ArticleView::highlightFTSResults()
}
QString pageText = ui.definition->page()->currentFrame()->toPlainText();
markHandler.setText( pageText );
marksHandler->setText( pageText );
int pos = 0;
while( pos >= 0 )
{
pos = regexp.indexIn( markHandler.normalizedText(), pos );
pos = regexp.indexIn( marksHandler->normalizedText(), pos );
if( pos >= 0 )
{
// Mirror pos and matched length to original string
int spos = markHandler.mirrorPosition( pos );
int matched = markHandler.mirrorPosition( pos + regexp.matchedLength() ) - spos;
int spos = marksHandler->mirrorPosition( pos );
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 )
{

View file

@ -101,7 +101,8 @@ public:
Contexts const & contexts = Contexts() );
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,
/// which will be restored when some article loads eventually.

8
bgl.cc
View file

@ -242,7 +242,8 @@ namespace
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual QString const& getDescription();
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 distanceBetweenWords,
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();
}
vector< WordArticleLink > BtreeIndex::findArticles( wstring const & word )
vector< WordArticleLink > BtreeIndex::findArticles( wstring const & word, bool ignoreDiacritics )
{
vector< WordArticleLink > result;
@ -108,7 +108,7 @@ vector< WordArticleLink > BtreeIndex::findArticles( wstring const & word )
{
result = readChain( chainOffset );
antialias( word, result );
antialias( word, result, ignoreDiacritics );
}
}
catch( std::exception & e )
@ -910,7 +910,8 @@ vector< WordArticleLink > BtreeIndex::readChain( char const * & ptr )
}
void BtreeIndex::antialias( wstring const & str,
vector< WordArticleLink > & chain )
vector< WordArticleLink > & chain,
bool ignoreDiacritics )
{
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
// drop the entry.
if ( Folding::applySimpleCaseOnly( gd::normalize( Utf8::decode( chain[ x ].prefix + chain[ x ].word ) ) ) !=
caseFolded )
wstring entry = Folding::applySimpleCaseOnly( gd::normalize( Utf8::decode( chain[ x ].prefix + chain[ x ].word ) ) );
if( ignoreDiacritics )
entry = Folding::applyDiacriticsOnly( entry );
if ( entry != caseFolded )
chain.erase( chain.begin() + x );
else
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
/// is performed.
vector< WordArticleLink > findArticles( wstring const & );
vector< WordArticleLink > findArticles( wstring const &, bool ignoreDiacritics = false );
/// Find all unique article links in the index
void findAllArticleLinks( QVector< WordArticleLink > & articleLinks );
@ -133,7 +133,7 @@ protected:
/// Drops any alises which arose due to folding. Only case-folded aliases
/// are left.
void antialias( wstring const &, vector< WordArticleLink > & );
void antialias( wstring const &, vector< WordArticleLink > &, bool ignoreDiactitics );
protected:

View file

@ -931,6 +931,9 @@ Class load() throw( exError )
if ( !fts.namedItem( "ignoreWordsOrder" ).isNull() )
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() )
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" ) );
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.appendChild( dd.createTextNode( QString::number( c.preferences.fts.maxDictionarySize ) ) );
hd.appendChild( opt );

View file

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

View file

@ -133,7 +133,8 @@ public:
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -588,9 +589,10 @@ sptr< Dictionary::DataRequest > DictdDictionary::getSearchResults( QString const
int searchMode, bool matchCase,
int distanceBetweenWords,
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

View file

@ -175,7 +175,7 @@ sptr< DataRequest > Class::getResource( string const & /*name*/ )
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 );
}

View file

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

8
dsl.cc
View file

@ -227,7 +227,8 @@ public:
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual QString const& getDescription();
virtual QString getMainFilename();
@ -1991,9 +1992,10 @@ sptr< Dictionary::DataRequest > DslDictionary::getSearchResults( QString const &
int searchMode, bool matchCase,
int distanceBetweenWords,
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

View file

@ -128,7 +128,8 @@ public:
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -784,9 +785,10 @@ sptr< Dictionary::DataRequest > EpwingDictionary::getSearchResults( QString cons
int searchMode, bool matchCase,
int distanceBetweenWords,
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 )

View file

@ -10,24 +10,21 @@
namespace Folding {
namespace
{
#include "inc_case_folding.hh"
#include "inc_diacritic_folding.hh"
#include "inc_case_folding.hh"
#include "inc_diacritic_folding.hh"
/// Tests if the given char is one of the Unicode combining marks. Some are
/// caught by the diacritics folding table, but they are only handled there
/// when they come with their main characters, not by themselves. The rest
/// are caught here.
bool isCombiningMark( wchar ch )
{
return (
( ch >= 0x300 && ch <= 0x36F ) ||
( ch >= 0x1DC0 && ch <= 0x1DFF ) ||
( ch >= 0x20D0 && ch <= 0x20FF ) ||
( ch >= 0xFE20 && ch <= 0xFE2F )
);
}
/// Tests if the given char is one of the Unicode combining marks. Some are
/// caught by the diacritics folding table, but they are only handled there
/// when they come with their main characters, not by themselves. The rest
/// are caught here.
bool isCombiningMark( wchar ch )
{
return (
( ch >= 0x300 && ch <= 0x36F ) ||
( ch >= 0x1DC0 && ch <= 0x1DFF ) ||
( ch >= 0x20D0 && ch <= 0x20FF ) ||
( ch >= 0xFE20 && ch <= 0xFE2F )
);
}
wstring apply( wstring const & in, bool preserveWildcards )
@ -691,4 +688,10 @@ QString unescapeWildcardSymbols( const QString & str )
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)
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

View file

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

View file

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

View file

@ -137,6 +137,7 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
groups( groups_ ),
group( 0 ),
ignoreWordsOrder( cfg_.preferences.fts.ignoreWordsOrder ),
ignoreDiacritics( cfg_.preferences.fts.ignoreDiacritics ),
ftsIdx( ftsidx )
, helpAction( this )
{
@ -193,6 +194,8 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
ui.checkBoxIgnoreWordOrder->setEnabled( false );
}
ui.checkBoxIgnoreDiacritics->setChecked( ignoreDiacritics );
ui.matchCase->setChecked( cfg.preferences.fts.matchCase );
setLimitsUsing();
@ -205,6 +208,8 @@ FullTextSearchDialog::FullTextSearchDialog( QWidget * parent,
this, SLOT( setLimitsUsing() ) );
connect( ui.checkBoxIgnoreWordOrder, SIGNAL( stateChanged( int ) ),
this, SLOT( ignoreWordsOrderClicked() ) );
connect( ui.checkBoxIgnoreDiacritics, SIGNAL( stateChanged( int ) ),
this, SLOT( ignoreDiacriticsClicked() ) );
model = new HeadwordsListModel( this, results, activeDicts );
ui.headwordsView->setModel( model );
@ -319,6 +324,7 @@ void FullTextSearchDialog::saveData()
cfg.preferences.fts.useMaxDistanceBetweenWords = ui.checkBoxDistanceBetweenWords->isChecked();
cfg.preferences.fts.useMaxArticlesPerDictionary = ui.checkBoxArticlesPerDictionary->isChecked();
cfg.preferences.fts.ignoreWordsOrder = ignoreWordsOrder;
cfg.preferences.fts.ignoreDiacritics = ignoreDiacritics;
cfg.preferences.fts.dialogGeometry = saveGeometry();
}
@ -355,6 +361,11 @@ void FullTextSearchDialog::ignoreWordsOrderClicked()
ignoreWordsOrder = ui.checkBoxIgnoreWordOrder->isChecked();
}
void FullTextSearchDialog::ignoreDiacriticsClicked()
{
ignoreDiacritics = ui.checkBoxIgnoreDiacritics->isChecked();
}
void FullTextSearchDialog::accept()
{
QStringList list1, list2;
@ -421,7 +432,8 @@ void FullTextSearchDialog::accept()
ui.matchCase->isChecked(),
distanceBetweenWords,
maxResultsPerDict,
ignoreWordsOrder
ignoreWordsOrder,
ignoreDiacritics
);
connect( req.get(), SIGNAL( finished() ),
this, SLOT( searchReqFinished() ), Qt::QueuedConnection );
@ -512,7 +524,7 @@ void FullTextSearchDialog::itemClicked( const QModelIndex & idx )
}
else
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;
std::vector< sptr< Dictionary::Class > > activeDicts;
bool ignoreWordsOrder;
bool ignoreDiacritics;
std::list< sptr< Dictionary::DataRequest > > searchReqs;
@ -217,6 +218,7 @@ private slots:
void accept();
void setLimitsUsing();
void ignoreWordsOrderClicked();
void ignoreDiacriticsClicked();
void searchReqFinished();
void reject();
void itemClicked( QModelIndex const & idx );
@ -225,7 +227,7 @@ private slots:
signals:
void showTranslationFor( QString const &, QStringList const & dictIDs,
QRegExp const & searchRegExp );
QRegExp const & searchRegExp, bool ignoreDiacritics );
void closeDialog();
};

View file

@ -75,11 +75,22 @@
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxIgnoreWordOrder">
<property name="text">
<string>Ignore words order</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QCheckBox" name="checkBoxIgnoreWordOrder">
<property name="text">
<string>Ignore words order</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxIgnoreDiacritics">
<property name="text">
<string>Ignore diacritics</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

8
gls.cc
View file

@ -487,7 +487,8 @@ public:
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
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 distanceBetweenWords,
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

View file

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

View file

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

8
mdx.cc
View file

@ -254,7 +254,8 @@ public:
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -515,9 +516,10 @@ sptr< Dictionary::DataRequest > MdxDictionary::getSearchResults( QString const &
int searchMode, bool matchCase,
int distanceBetweenWords,
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

View file

@ -172,7 +172,8 @@ class SdictDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -477,9 +478,10 @@ sptr< Dictionary::DataRequest > SdictDictionary::getSearchResults( QString const
int searchMode, bool matchCase,
int distanceBetweenWords,
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()

View file

@ -556,7 +556,8 @@ class SlobDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -1262,9 +1263,10 @@ sptr< Dictionary::DataRequest > SlobDictionary::getSearchResults( QString const
int searchMode, bool matchCase,
int distanceBetweenWords,
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 distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -1264,9 +1265,10 @@ sptr< Dictionary::DataRequest > StardictDictionary::getSearchResults( QString co
int searchMode, bool matchCase,
int distanceBetweenWords,
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()

View file

@ -179,7 +179,8 @@ public:
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void getArticleText( uint32_t articleAddress, QString & headword, QString & text );
virtual void makeFTSIndex(QAtomicInt & isCancelled, bool firstIteration );
@ -423,9 +424,10 @@ sptr< Dictionary::DataRequest > XdxfDictionary::getSearchResults( QString const
int searchMode, bool matchCase,
int distanceBetweenWords,
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()

8
zim.cc
View file

@ -569,7 +569,8 @@ class ZimDictionary: public BtreeIndexing::BtreeDictionary
int searchMode, bool matchCase,
int distanceBetweenWords,
int maxResults,
bool ignoreWordsOrder );
bool ignoreWordsOrder,
bool ignoreDiacritics );
virtual void 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 distanceBetweenWords,
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()