From 7c30b89336769ae48695a08b6aca6c7c06612264 Mon Sep 17 00:00:00 2001 From: Xiao YiFang Date: Sun, 2 Oct 2022 19:53:54 +0800 Subject: [PATCH] opt: headwords dialog filtering optimization when in filtering process, fetch more return false. --- dictheadwords.hh | 2 +- dictionary.hh | 2 +- goldendict.pro | 4 +- headwordslistmodel.cpp | 161 ------------------------------------- headwordslistmodel.h | 48 ----------- headwordsmodel.cpp | 176 +++++++++++++++++++++++++++++++++++++++++ headwordsmodel.h | 50 ++++++++++++ 7 files changed, 230 insertions(+), 213 deletions(-) delete mode 100644 headwordslistmodel.cpp delete mode 100644 headwordslistmodel.h create mode 100644 headwordsmodel.cpp create mode 100644 headwordsmodel.h diff --git a/dictheadwords.hh b/dictheadwords.hh index 59676993..18b5d025 100644 --- a/dictheadwords.hh +++ b/dictheadwords.hh @@ -14,7 +14,7 @@ #include "dictionary.hh" #include "delegate.hh" #include "helpwindow.hh" -#include "headwordslistmodel.h" +#include "headwordsmodel.h" class DictHeadwords : public QDialog { diff --git a/dictionary.hh b/dictionary.hh index 4e767a9b..369f8300 100644 --- a/dictionary.hh +++ b/dictionary.hh @@ -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 ) diff --git a/goldendict.pro b/goldendict.pro index 4369eaa0..ec6317b1 100644 --- a/goldendict.pro +++ b/goldendict.pro @@ -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 \ diff --git a/headwordslistmodel.cpp b/headwordslistmodel.cpp deleted file mode 100644 index 931d1d57..00000000 --- a/headwordslistmodel.cpp +++ /dev/null @@ -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<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<= 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 headword; - Mutex::Lock _(lock); - _dict->findHeadWordsWithLenth(index,&headword,10000); - if(headword.isEmpty()){ - return; - } - - QSet 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 HeadwordListModel::getRemainRows(int & nodeIndex) -{ - QSet headword; - Mutex::Lock _(lock); - _dict->findHeadWordsWithLenth(nodeIndex, &headword,10000); - - QSet 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(); -} - diff --git a/headwordslistmodel.h b/headwordslistmodel.h deleted file mode 100644 index e184f63a..00000000 --- a/headwordslistmodel.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef HEADWORDSLISTMODEL_H -#define HEADWORDSLISTMODEL_H - -#include "dictionary.hh" - -#include -#include - -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 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 diff --git a/headwordsmodel.cpp b/headwordsmodel.cpp new file mode 100644 index 00000000..3d4d7f69 --- /dev/null +++ b/headwordsmodel.cpp @@ -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(); +} diff --git a/headwordsmodel.h b/headwordsmodel.h new file mode 100644 index 00000000..e6ea49cb --- /dev/null +++ b/headwordsmodel.h @@ -0,0 +1,50 @@ +#ifndef HEADWORDSMODEL_H +#define HEADWORDSMODEL_H + +#include "dictionary.hh" + +#include +#include + +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