Skip to content

Commit

Permalink
add lazy loading to headwords dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoyifang committed Apr 17, 2022
1 parent 0ea3ad0 commit 473c617
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 24 deletions.
43 changes: 21 additions & 22 deletions dictheadwords.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ DictHeadwords::DictHeadwords( QWidget *parent, Config::Class & cfg_,

ui.matchCase->setChecked( cfg.headwordsDialog.matchCase );

model = new QStringListModel( this );
model->setStringList( headers );
model = new HeadwordListModel( this );

connect(model,&HeadwordListModel::finished,this,[this](){
ui.exportButton->setEnabled(true);
});
proxy = new QSortFilterProxyModel( this );

proxy->setSourceModel( model );
Expand Down Expand Up @@ -134,16 +136,12 @@ void DictHeadwords::setup( Dictionary::Class *dict_ )

setWindowTitle( QString::fromUtf8( dict->getName().c_str() ) );

headers.clear();
model->setStringList( headers );

dict->getHeadwords( headers );
model->setStringList( headers );

auto size = dict->getWordCount();
model->setDict(dict);
proxy->sort( 0 );
filterChanged();

if( headers.size() > AUTO_APPLY_LIMIT )
if( size > AUTO_APPLY_LIMIT )
{
cfg.headwordsDialog.autoApply = ui.autoApply->isChecked();
ui.autoApply->setChecked( false );
Expand All @@ -155,6 +153,7 @@ void DictHeadwords::setup( Dictionary::Class *dict_ )
ui.autoApply->setChecked( cfg.headwordsDialog.autoApply );
}

ui.exportButton->setEnabled(false);
ui.applyButton->setEnabled( !ui.autoApply->isChecked() );

setWindowIcon( dict->getIcon() );
Expand All @@ -169,7 +168,7 @@ void DictHeadwords::savePos()
cfg.headwordsDialog.searchMode = ui.searchModeCombo->currentIndex();
cfg.headwordsDialog.matchCase = ui.matchCase->isChecked();

if( headers.size() <= AUTO_APPLY_LIMIT )
if( model->totalCount() <= AUTO_APPLY_LIMIT )
cfg.headwordsDialog.autoApply = ui.autoApply->isChecked();

cfg.headwordsDialog.headwordsDialogGeometry = saveGeometry();
Expand Down Expand Up @@ -226,12 +225,15 @@ void DictHeadwords::filterChanged()
QString pattern;
switch( syntax )
{
case QRegExp::FixedString: pattern = QRegularExpression::escape( ui.filterLine->text() );
break;
case QRegExp::WildcardUnix: pattern = wildcardsToRegexp( ui.filterLine->text() );
break;
default: pattern = ui.filterLine->text();
break;
case QRegExp::FixedString:
pattern = QRegularExpression::escape( ui.filterLine->text() );
break;
case QRegExp::WildcardUnix:
pattern = wildcardsToRegexp( ui.filterLine->text() );
break;
default:
pattern = ui.filterLine->text();
break;
}

QRegularExpression regExp( pattern, options );
Expand All @@ -245,8 +247,6 @@ void DictHeadwords::filterChanged()
QApplication::setOverrideCursor( Qt::WaitCursor );

proxy->setFilterRegularExpression( regExp );


proxy->sort( 0 );

QApplication::restoreOverrideCursor();
Expand All @@ -272,8 +272,7 @@ void DictHeadwords::autoApplyStateChanged( int state )
void DictHeadwords::showHeadwordsNumber()
{
ui.headersNumber->setText( tr( "Unique headwords total: %1, filtered: %2" )
.arg( QString::number( headers.size() ) )
.arg( QString::number( proxy->rowCount() ) ) );
.arg( QString::number( model->totalCount() ), QString::number( proxy->rowCount() ) ) );
}

void DictHeadwords::saveHeadersToFile()
Expand Down Expand Up @@ -303,7 +302,7 @@ void DictHeadwords::saveHeadersToFile()
if ( !file.open( QFile::WriteOnly | QIODevice::Text ) )
break;

int headwordsNumber = proxy->rowCount();
int headwordsNumber = model->totalCount();

// Setup progress dialog
int n = headwordsNumber;
Expand Down Expand Up @@ -335,7 +334,7 @@ void DictHeadwords::saveHeadersToFile()
if( progress.wasCanceled() )
break;

QVariant value = proxy->data( proxy->index( i, 0 ) );
QVariant value = model->getRow(i);
if( !value.canConvert< QString >() )
continue;

Expand Down
5 changes: 3 additions & 2 deletions dictheadwords.hh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "dictionary.hh"
#include "delegate.hh"
#include "helpwindow.hh"
#include "headwordslistmodel.h"

class DictHeadwords : public QDialog
{
Expand All @@ -29,8 +30,8 @@ public:
protected:
Config::Class & cfg;
Dictionary::Class * dict;
QStringList headers;
QStringListModel * model;

HeadwordListModel * model;
QSortFilterProxyModel * proxy;
WordListItemDelegate * delegate;
QString dictId;
Expand Down
2 changes: 2 additions & 0 deletions goldendict.pro
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ DEFINES += PROGRAM_VERSION=\\\"$$VERSION\\\"
HEADERS += folding.hh \
article_inspect.h \
globalbroadcaster.h \
headwordslistmodel.h \
inc_case_folding.hh \
inc_diacritic_folding.hh \
mainwindow.hh \
Expand Down Expand Up @@ -363,6 +364,7 @@ FORMS += groups.ui \
SOURCES += folding.cc \
article_inspect.cpp \
globalbroadcaster.cpp \
headwordslistmodel.cpp \
main.cc \
dictionary.cc \
config.cc \
Expand Down
88 changes: 88 additions & 0 deletions headwordslistmodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "headwordslistmodel.h"

HeadwordListModel::HeadwordListModel(QObject *parent)
: QAbstractListModel(parent), wordsCount(0)
{}

int HeadwordListModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : wordsCount;
}

int HeadwordListModel::totalCount() const{
return totalSize;
}

bool HeadwordListModel::isFinish() const{
return wordsCount >=totalSize;
}

QString HeadwordListModel::getRow(int row)
{
if(fileSortedList.empty()){
fileSortedList<<fileList;
fileSortedList.sort();
}
return fileSortedList.at(row);
}

int HeadwordListModel::wordCount() const{
return wordsCount;
}

QVariant HeadwordListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

if (index.row() >= totalSize || index.row() < 0)
return QVariant();

if (role == Qt::DisplayRole) {
return fileList.at(index.row());
}
return QVariant();
}

bool HeadwordListModel::canFetchMore(const QModelIndex &parent) const
{
if (parent.isValid())
return false;
return (wordsCount < totalSize);
}

void HeadwordListModel::fetchMore(const QModelIndex &parent)
{
if (parent.isValid())
return;
int remainder = fileList.size() - wordsCount;
int itemsToFetch = qMin(100, remainder);

if (itemsToFetch <= 0)
return;

beginInsertRows(QModelIndex(), wordsCount, wordsCount + itemsToFetch - 1);

wordsCount+= itemsToFetch;

endInsertRows();

emit numberPopulated(wordsCount);
}

void HeadwordListModel::setDict(Dictionary::Class * dict){
_dict = dict;
totalSize = _dict->getWordCount();
wordsCount=0;
QThreadPool::globalInstance()->start(
[ this ]()
{
beginResetModel();
_dict->getHeadwords( fileList );
totalSize = fileList.size();
emit finished(totalSize);
endResetModel();
} );

}

42 changes: 42 additions & 0 deletions headwordslistmodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#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);
signals:
void numberPopulated(int number);
void finished(int number);

public slots:
void setDict(Dictionary::Class * dict);

protected:
bool canFetchMore(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;


private:
QStringList fileList;
QStringList fileSortedList;
long wordsCount;
long totalSize;
Dictionary::Class * _dict;
};

#endif // HEADWORDSLISTMODEL_H

0 comments on commit 473c617

Please sign in to comment.