mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 20:14:05 +00:00
opt: headwords dialog filtering optimization
when in filtering process, fetch more return false.
This commit is contained in:
parent
63ddf68d3b
commit
7c30b89336
|
@ -14,7 +14,7 @@
|
|||
#include "dictionary.hh"
|
||||
#include "delegate.hh"
|
||||
#include "helpwindow.hh"
|
||||
#include "headwordslistmodel.h"
|
||||
#include "headwordsmodel.h"
|
||||
|
||||
class DictHeadwords : public QDialog
|
||||
{
|
||||
|
|
|
@ -443,7 +443,7 @@ public:
|
|||
/// Retrieve all dictionary headwords
|
||||
virtual bool getHeadwords( QStringList & )
|
||||
{ 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
|
||||
void setSynonymSearchEnabled( bool enabled )
|
||||
|
|
|
@ -268,8 +268,8 @@ HEADERS += folding.hh \
|
|||
articlewebpage.h \
|
||||
base/globalregex.hh \
|
||||
globalbroadcaster.h \
|
||||
headwordsmodel.h \
|
||||
iframeschemehandler.h \
|
||||
headwordslistmodel.h \
|
||||
inc_case_folding.hh \
|
||||
inc_diacritic_folding.hh \
|
||||
mainwindow.hh \
|
||||
|
@ -412,8 +412,8 @@ SOURCES += folding.cc \
|
|||
articlewebpage.cpp \
|
||||
base/globalregex.cc \
|
||||
globalbroadcaster.cpp \
|
||||
headwordsmodel.cpp \
|
||||
iframeschemehandler.cpp \
|
||||
headwordslistmodel.cpp \
|
||||
main.cc \
|
||||
dictionary.cc \
|
||||
config.cc \
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
176
headwordsmodel.cpp
Normal 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
50
headwordsmodel.h
Normal 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
|
Loading…
Reference in a new issue