opt: headwords dialog filtering optimization

when in filtering process, fetch more return false.
This commit is contained in:
Xiao YiFang 2022-10-02 19:53:54 +08:00
parent 63ddf68d3b
commit 7c30b89336
7 changed files with 230 additions and 213 deletions

View file

@ -14,7 +14,7 @@
#include "dictionary.hh" #include "dictionary.hh"
#include "delegate.hh" #include "delegate.hh"
#include "helpwindow.hh" #include "helpwindow.hh"
#include "headwordslistmodel.h" #include "headwordsmodel.h"
class DictHeadwords : public QDialog class DictHeadwords : public QDialog
{ {

View file

@ -443,7 +443,7 @@ public:
/// Retrieve all dictionary headwords /// Retrieve all dictionary headwords
virtual bool getHeadwords( QStringList & ) virtual bool getHeadwords( QStringList & )
{ return false; } { return false; }
virtual void findHeadWordsWithLenth( int &, QSet< QString > * headwords, uint32_t length ){} virtual void findHeadWordsWithLenth( int &, QSet< QString > * /*headwords*/, uint32_t ){}
/// Enable/disable search via synonyms /// Enable/disable search via synonyms
void setSynonymSearchEnabled( bool enabled ) void setSynonymSearchEnabled( bool enabled )

View file

@ -268,8 +268,8 @@ HEADERS += folding.hh \
articlewebpage.h \ articlewebpage.h \
base/globalregex.hh \ base/globalregex.hh \
globalbroadcaster.h \ globalbroadcaster.h \
headwordsmodel.h \
iframeschemehandler.h \ iframeschemehandler.h \
headwordslistmodel.h \
inc_case_folding.hh \ inc_case_folding.hh \
inc_diacritic_folding.hh \ inc_diacritic_folding.hh \
mainwindow.hh \ mainwindow.hh \
@ -412,8 +412,8 @@ SOURCES += folding.cc \
articlewebpage.cpp \ articlewebpage.cpp \
base/globalregex.cc \ base/globalregex.cc \
globalbroadcaster.cpp \ globalbroadcaster.cpp \
headwordsmodel.cpp \
iframeschemehandler.cpp \ iframeschemehandler.cpp \
headwordslistmodel.cpp \
main.cc \ main.cc \
dictionary.cc \ dictionary.cc \
config.cc \ config.cc \

View file

@ -1,161 +0,0 @@
#include "headwordslistmodel.h"
#include "wstring_qt.hh"
HeadwordListModel::HeadwordListModel(QObject *parent)
: QAbstractListModel(parent), index(0),ptr(0)
{}
int HeadwordListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : words.size();
}
int HeadwordListModel::totalCount() const{
return totalSize;
}
bool HeadwordListModel::isFinish() const{
return words.size() >=totalSize;
}
//export headword
QString HeadwordListModel::getRow(int row)
{
if(fileSortedList.empty()){
fileSortedList<<words;
fileSortedList.sort();
}
return fileSortedList.at(row);
}
void HeadwordListModel::setFilter(QRegularExpression reg){
if(reg.pattern().isEmpty())
return;
filterWords.clear();
auto sr = _dict->prefixMatch(gd::toWString(reg.pattern()),30);
connect( sr.get(), SIGNAL( finished() ),
this, SLOT( requestFinished() ), Qt::QueuedConnection );
queuedRequests.push_back( sr );
}
void HeadwordListModel::requestFinished()
{
// See how many new requests have finished, and if we have any new results
for( std::list< sptr< Dictionary::WordSearchRequest > >::iterator i =
queuedRequests.begin(); i != queuedRequests.end(); )
{
if ( (*i)->isFinished() )
{
if ( !(*i)->getErrorString().isEmpty() )
{
qDebug()<<"error:"<<(*i)->getErrorString();
}
if ( (*i)->matchesCount() )
{
auto allmatches = (*i)->getAllMatches();
for(auto& match:allmatches)
filterWords.append(gd::toQString(match.word));
}
queuedRequests.erase( i++ );
}
else
++i;
}
if(queuedRequests.empty()){
QStringList filtered;
for(auto& w:filterWords){
if(!words.contains(w)){
filtered<<w;
}
}
beginInsertRows(QModelIndex(), words.size(), words.size() + filtered.count() - 1);
for(const auto & word:filtered)
words.append(word);
endInsertRows();
}
}
int HeadwordListModel::wordCount() const{
return words.size();
}
QVariant HeadwordListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row() >= totalSize || index.row() < 0 || index.row()>=words.size())
return QVariant();
if (role == Qt::DisplayRole) {
return words.at(index.row());
}
return QVariant();
}
bool HeadwordListModel::canFetchMore(const QModelIndex &parent) const
{
if (parent.isValid())
return false;
return (words.size() < totalSize);
}
void HeadwordListModel::fetchMore(const QModelIndex &parent)
{
if (parent.isValid())
return;
QSet<QString> headword;
Mutex::Lock _(lock);
_dict->findHeadWordsWithLenth(index,&headword,10000);
if(headword.isEmpty()){
return;
}
QSet<QString> filtered;
for(const auto & word:qAsConst(headword))
{
if(!words.contains(word))
filtered.insert(word);
}
beginInsertRows(QModelIndex(), words.size(), words.size() + filtered.count() - 1);
for(const auto & word:filtered)
{
words.append(word);
}
endInsertRows();
emit numberPopulated(words.size());
}
int HeadwordListModel::getCurrentIndex()
{
return index;
}
QSet<QString> HeadwordListModel::getRemainRows(int & nodeIndex)
{
QSet<QString> headword;
Mutex::Lock _(lock);
_dict->findHeadWordsWithLenth(nodeIndex, &headword,10000);
QSet<QString> filtered;
for(const auto & word:headword)
{
if(!words.contains(word))
filtered.insert(word);
}
return filtered;
}
void HeadwordListModel::setDict(Dictionary::Class * dict){
_dict = dict;
totalSize = _dict->getWordCount();
}

View file

@ -1,48 +0,0 @@
#ifndef HEADWORDSLISTMODEL_H
#define HEADWORDSLISTMODEL_H
#include "dictionary.hh"
#include <QAbstractListModel>
#include <QStringList>
class HeadwordListModel : public QAbstractListModel
{
Q_OBJECT
public:
HeadwordListModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int totalCount() const;
int wordCount() const;
bool isFinish() const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QString getRow(int row);
void setFilter(QRegularExpression);
int getCurrentIndex();
QSet<QString> getRemainRows(int & nodeIndex);
signals:
void numberPopulated(int number);
void finished(int number);
public slots:
void setDict(Dictionary::Class * dict);
void requestFinished();
protected:
bool canFetchMore(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;
private:
QStringList words;
QStringList filterWords;
QStringList fileSortedList;
long totalSize;
Dictionary::Class * _dict;
int index;
char* ptr;
Mutex lock;
std::list< sptr< Dictionary::WordSearchRequest > > queuedRequests;
};
#endif // HEADWORDSLISTMODEL_H

176
headwordsmodel.cpp Normal file
View file

@ -0,0 +1,176 @@
#include "headwordsmodel.h"
#include "wstring_qt.hh"
HeadwordListModel::HeadwordListModel( QObject * parent ) :
QAbstractListModel( parent ), filtering( false ), index( 0 ), ptr( 0 )
{
}
int HeadwordListModel::rowCount( const QModelIndex & parent ) const
{
return parent.isValid() ? 0 : words.size();
}
int HeadwordListModel::totalCount() const
{
return totalSize;
}
bool HeadwordListModel::isFinish() const
{
return words.size() >= totalSize;
}
// export headword
QString HeadwordListModel::getRow( int row )
{
if( fileSortedList.empty() )
{
fileSortedList << words;
fileSortedList.sort();
}
return fileSortedList.at( row );
}
void HeadwordListModel::setFilter( QRegularExpression reg )
{
if( reg.pattern().isEmpty() )
{
filtering = false;
return;
}
filtering = true;
filterWords.clear();
auto sr = _dict->prefixMatch( gd::toWString( reg.pattern() ), 30 );
connect( sr.get(), SIGNAL( finished() ), this, SLOT( requestFinished() ), Qt::QueuedConnection );
queuedRequests.push_back( sr );
}
void HeadwordListModel::requestFinished()
{
// See how many new requests have finished, and if we have any new results
for( std::list< sptr< Dictionary::WordSearchRequest > >::iterator i = queuedRequests.begin();
i != queuedRequests.end(); )
{
if( ( *i )->isFinished() )
{
if( !( *i )->getErrorString().isEmpty() )
{
qDebug() << "error:" << ( *i )->getErrorString();
}
if( ( *i )->matchesCount() )
{
auto allmatches = ( *i )->getAllMatches();
for( auto & match : allmatches )
filterWords.append( gd::toQString( match.word ) );
}
queuedRequests.erase( i++ );
}
else
++i;
}
if( queuedRequests.empty() )
{
QStringList filtered;
for( auto & w : filterWords )
{
if( !words.contains( w ) )
{
filtered << w;
}
}
beginInsertRows( QModelIndex(), words.size(), words.size() + filtered.count() - 1 );
for( const auto & word : filtered )
words.append( word );
endInsertRows();
}
}
int HeadwordListModel::wordCount() const
{
return words.size();
}
QVariant HeadwordListModel::data( const QModelIndex & index, int role ) const
{
if( !index.isValid() )
return QVariant();
if( index.row() >= totalSize || index.row() < 0 || index.row() >= words.size() )
return QVariant();
if( role == Qt::DisplayRole )
{
return words.at( index.row() );
}
return QVariant();
}
bool HeadwordListModel::canFetchMore( const QModelIndex & parent ) const
{
if( parent.isValid() || filtering )
return false;
return ( words.size() < totalSize );
}
void HeadwordListModel::fetchMore( const QModelIndex & parent )
{
if( parent.isValid() || filtering )
return;
QSet< QString > headword;
Mutex::Lock _( lock );
_dict->findHeadWordsWithLenth( index, &headword, 1000 );
if( headword.isEmpty() )
{
return;
}
QSet< QString > filtered;
for( const auto & word : qAsConst( headword ) )
{
if( !words.contains( word ) )
filtered.insert( word );
}
beginInsertRows( QModelIndex(), words.size(), words.size() + filtered.count() - 1 );
for( const auto & word : filtered )
{
words.append( word );
}
endInsertRows();
emit numberPopulated( words.size() );
}
int HeadwordListModel::getCurrentIndex()
{
return index;
}
QSet< QString > HeadwordListModel::getRemainRows( int & nodeIndex )
{
QSet< QString > headword;
Mutex::Lock _( lock );
_dict->findHeadWordsWithLenth( nodeIndex, &headword, 10000 );
QSet< QString > filtered;
for( const auto & word : headword )
{
if( !words.contains( word ) )
filtered.insert( word );
}
return filtered;
}
void HeadwordListModel::setDict( Dictionary::Class * dict )
{
_dict = dict;
totalSize = _dict->getWordCount();
}

50
headwordsmodel.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef HEADWORDSMODEL_H
#define HEADWORDSMODEL_H
#include "dictionary.hh"
#include <QAbstractListModel>
#include <QStringList>
class HeadwordListModel : public QAbstractListModel
{
Q_OBJECT
public:
HeadwordListModel( QObject * parent = nullptr );
int rowCount( const QModelIndex & parent = QModelIndex() ) const override;
int totalCount() const;
int wordCount() const;
bool isFinish() const;
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
QString getRow( int row );
void setFilter( QRegularExpression );
int getCurrentIndex();
QSet< QString > getRemainRows( int & nodeIndex );
signals:
void numberPopulated( int number );
void finished( int number );
public slots:
void setDict( Dictionary::Class * dict );
void requestFinished();
protected:
bool canFetchMore( const QModelIndex & parent ) const override;
void fetchMore( const QModelIndex & parent ) override;
private:
QStringList words;
QStringList filterWords;
bool filtering;
QStringList fileSortedList;
long totalSize;
Dictionary::Class * _dict;
int index;
char * ptr;
Mutex lock;
std::list< sptr< Dictionary::WordSearchRequest > > queuedRequests;
};
#endif // HEADWORDSMODEL_H