mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-24 04:24:09 +00:00
fix: headword dialog filter and export
the wildcard and regex filter does not work as expected. fix #556
This commit is contained in:
parent
d0ae253c27
commit
72fca59a92
|
@ -17,7 +17,6 @@
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include "fsencoding.hh"
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
|
@ -46,10 +46,29 @@ void HeadwordListModel::setFilter( QRegularExpression reg )
|
||||||
queuedRequests.push_back( sr );
|
queuedRequests.push_back( sr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeadwordListModel::addMatches( QStringList matches)
|
||||||
|
{
|
||||||
|
QStringList filtered;
|
||||||
|
for ( auto & w : matches ) {
|
||||||
|
if ( !words.contains( w ) ) {
|
||||||
|
filtered << w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( filtered.isEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
beginInsertRows( QModelIndex(), words.size(), words.size() + filtered.count() - 1 );
|
||||||
|
for ( const auto & word : filtered ) {
|
||||||
|
words.append( word );
|
||||||
|
}
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
void HeadwordListModel::requestFinished()
|
void HeadwordListModel::requestFinished()
|
||||||
{
|
{
|
||||||
// See how many new requests have finished, and if we have any new results
|
// See how many new requests have finished, and if we have any new results
|
||||||
for( std::list< sptr< Dictionary::WordSearchRequest > >::iterator i = queuedRequests.begin();
|
for( auto i = queuedRequests.begin();
|
||||||
i != queuedRequests.end(); )
|
i != queuedRequests.end(); )
|
||||||
{
|
{
|
||||||
if( ( *i )->isFinished() )
|
if( ( *i )->isFinished() )
|
||||||
|
|
|
@ -20,6 +20,7 @@ public:
|
||||||
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
|
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
|
||||||
QString getRow( int row );
|
QString getRow( int row );
|
||||||
void setFilter( QRegularExpression );
|
void setFilter( QRegularExpression );
|
||||||
|
void addMatches( QStringList matches );
|
||||||
int getCurrentIndex();
|
int getCurrentIndex();
|
||||||
QSet< QString > getRemainRows( int & nodeIndex );
|
QSet< QString > getRemainRows( int & nodeIndex );
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -17,19 +17,19 @@
|
||||||
#include "wildcard.hh"
|
#include "wildcard.hh"
|
||||||
#include "help.hh"
|
#include "help.hh"
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
|
||||||
#define AUTO_APPLY_LIMIT 150000
|
#define AUTO_APPLY_LIMIT 150000
|
||||||
|
|
||||||
DictHeadwords::DictHeadwords( QWidget *parent, Config::Class & cfg_,
|
DictHeadwords::DictHeadwords( QWidget * parent, Config::Class & cfg_, Dictionary::Class * dict_ ):
|
||||||
Dictionary::Class * dict_ ) :
|
QDialog( parent ),
|
||||||
QDialog(parent)
|
cfg( cfg_ ),
|
||||||
, cfg( cfg_ )
|
dict( dict_ ),
|
||||||
, dict( dict_ )
|
helpAction( this )
|
||||||
, helpAction( this )
|
|
||||||
{
|
{
|
||||||
ui.setupUi( this );
|
ui.setupUi( this );
|
||||||
|
|
||||||
bool fromMainWindow = parent->objectName() == "MainWindow";
|
const bool fromMainWindow = parent->objectName() == "MainWindow";
|
||||||
|
|
||||||
if( fromMainWindow )
|
if( fromMainWindow )
|
||||||
setAttribute( Qt::WA_DeleteOnClose, false );
|
setAttribute( Qt::WA_DeleteOnClose, false );
|
||||||
|
@ -126,7 +126,7 @@ void DictHeadwords::setup( Dictionary::Class *dict_ )
|
||||||
|
|
||||||
setWindowTitle( QString::fromUtf8( dict->getName().c_str() ) );
|
setWindowTitle( QString::fromUtf8( dict->getName().c_str() ) );
|
||||||
|
|
||||||
auto size = dict->getWordCount();
|
const auto size = dict->getWordCount();
|
||||||
model->setDict(dict);
|
model->setDict(dict);
|
||||||
proxy->sort( 0 );
|
proxy->sort( 0 );
|
||||||
filterChanged();
|
filterChanged();
|
||||||
|
@ -180,13 +180,13 @@ bool DictHeadwords::eventFilter( QObject * obj, QEvent * ev )
|
||||||
void DictHeadwords::okButtonClicked()
|
void DictHeadwords::okButtonClicked()
|
||||||
{
|
{
|
||||||
savePos();
|
savePos();
|
||||||
closeDialog();
|
emit closeDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DictHeadwords::reject()
|
void DictHeadwords::reject()
|
||||||
{
|
{
|
||||||
savePos();
|
savePos();
|
||||||
closeDialog();
|
emit closeDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DictHeadwords::exportButtonClicked()
|
void DictHeadwords::exportButtonClicked()
|
||||||
|
@ -201,10 +201,10 @@ void DictHeadwords::filterChangedInternal()
|
||||||
QTimer::singleShot( 100, this, &DictHeadwords::filterChanged );
|
QTimer::singleShot( 100, this, &DictHeadwords::filterChanged );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DictHeadwords::filterChanged()
|
QRegularExpression DictHeadwords::getFilterRegex( )
|
||||||
{
|
{
|
||||||
QRegExp::PatternSyntax syntax =
|
const QRegExp::PatternSyntax syntax =
|
||||||
QRegExp::PatternSyntax( ui.searchModeCombo->itemData(
|
static_cast< QRegExp::PatternSyntax >(ui.searchModeCombo->itemData(
|
||||||
ui.searchModeCombo->currentIndex() ).toInt());
|
ui.searchModeCombo->currentIndex() ).toInt());
|
||||||
|
|
||||||
QRegularExpression::PatternOptions options = QRegularExpression::UseUnicodePropertiesOption;
|
QRegularExpression::PatternOptions options = QRegularExpression::UseUnicodePropertiesOption;
|
||||||
|
@ -225,17 +225,35 @@ void DictHeadwords::filterChanged()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegularExpression regExp( pattern, options );
|
QRegularExpression regExp = QRegularExpression( pattern, options );
|
||||||
|
|
||||||
if( !regExp.isValid() )
|
if( !regExp.isValid() )
|
||||||
{
|
{
|
||||||
gdWarning( "Invalid regexp pattern: %s\n", pattern.toUtf8().data() );
|
gdWarning( "Invalid regexp pattern: %s\n", pattern.toUtf8().data() );
|
||||||
regExp.setPattern( QString::fromLatin1( "\1" ) );
|
|
||||||
}
|
}
|
||||||
|
return regExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DictHeadwords::filterChanged()
|
||||||
|
{
|
||||||
|
const QRegularExpression regExp= getFilterRegex();
|
||||||
|
|
||||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||||
|
|
||||||
model->setFilter(regExp);
|
qDebug()<<regExp.pattern();
|
||||||
|
if ( sortedWords.isEmpty() && regExp.isValid() && !regExp.pattern().isEmpty() ) {
|
||||||
|
const int headwordsNumber = model->totalCount();
|
||||||
|
|
||||||
|
QProgressDialog progress( tr( "Loading headwords..." ), tr( "Cancel" ), 0, headwordsNumber, this );
|
||||||
|
progress.setWindowModality( Qt::WindowModal );
|
||||||
|
loadAllSortedWords( progress );
|
||||||
|
progress.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto filtered = sortedWords.filter( regExp );
|
||||||
|
model->addMatches( filtered );
|
||||||
|
|
||||||
|
// model->setFilter(regExp);
|
||||||
|
|
||||||
proxy->setFilterRegularExpression( regExp );
|
proxy->setFilterRegularExpression( regExp );
|
||||||
proxy->sort( 0 );
|
proxy->sort( 0 );
|
||||||
|
@ -266,6 +284,47 @@ void DictHeadwords::showHeadwordsNumber()
|
||||||
.arg( QString::number( model->totalCount() ), QString::number( proxy->rowCount() ) ) );
|
.arg( QString::number( model->totalCount() ), QString::number( proxy->rowCount() ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO , the ui and the code mixed together , this is not the right way to do this. need future refactor
|
||||||
|
void DictHeadwords::loadAllSortedWords( QProgressDialog & progress )
|
||||||
|
{
|
||||||
|
const int headwordsNumber = model->totalCount();
|
||||||
|
|
||||||
|
QMutexLocker _( &mutex );
|
||||||
|
if ( sortedWords.isEmpty() ) {
|
||||||
|
QSet< QString > allHeadwords;
|
||||||
|
|
||||||
|
int totalCount = 0;
|
||||||
|
for ( int i = 0; i < headwordsNumber && i < model->wordCount(); ++i ) {
|
||||||
|
if ( progress.wasCanceled() )
|
||||||
|
break;
|
||||||
|
progress.setValue( totalCount++ );
|
||||||
|
|
||||||
|
QVariant value = model->getRow( i );
|
||||||
|
if ( !value.canConvert< QString >() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
allHeadwords.insert( value.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue to write the remaining headword
|
||||||
|
int nodeIndex = model->getCurrentIndex();
|
||||||
|
auto headwords = model->getRemainRows( nodeIndex );
|
||||||
|
while ( !headwords.isEmpty() ) {
|
||||||
|
if ( progress.wasCanceled() )
|
||||||
|
break;
|
||||||
|
allHeadwords.unite( headwords );
|
||||||
|
|
||||||
|
totalCount += headwords.size();
|
||||||
|
progress.setValue( totalCount );
|
||||||
|
|
||||||
|
headwords = model->getRemainRows( nodeIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
sortedWords = allHeadwords.values();
|
||||||
|
sortedWords.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DictHeadwords::saveHeadersToFile()
|
void DictHeadwords::saveHeadersToFile()
|
||||||
{
|
{
|
||||||
QString exportPath;
|
QString exportPath;
|
||||||
|
@ -295,59 +354,34 @@ void DictHeadwords::saveHeadersToFile()
|
||||||
cfg.headwordsDialog.headwordsExportPath = QDir::toNativeSeparators(
|
cfg.headwordsDialog.headwordsExportPath = QDir::toNativeSeparators(
|
||||||
QFileInfo( fileName ).absoluteDir().absolutePath() );
|
QFileInfo( fileName ).absoluteDir().absolutePath() );
|
||||||
|
|
||||||
QSet< QString > allHeadwords;
|
const int headwordsNumber = model->totalCount();
|
||||||
int headwordsNumber = model->totalCount();
|
|
||||||
|
|
||||||
//headwordsNumber*2 , read + write
|
|
||||||
QProgressDialog progress( tr( "Export headwords..." ), tr( "Cancel" ), 0, headwordsNumber*2, this );
|
QProgressDialog progress( tr( "Export headwords..." ), tr( "Cancel" ), 0, headwordsNumber*2, this );
|
||||||
progress.setWindowModality( Qt::WindowModal );
|
progress.setWindowModality( Qt::WindowModal );
|
||||||
|
|
||||||
int totalCount=0;
|
loadAllSortedWords( progress );
|
||||||
for( int i = 0; i < headwordsNumber && i < model->wordCount(); ++i )
|
|
||||||
{
|
|
||||||
if( progress.wasCanceled() )
|
|
||||||
break;
|
|
||||||
progress.setValue( totalCount++ );
|
|
||||||
|
|
||||||
QVariant value = model->getRow( i );
|
|
||||||
if( !value.canConvert< QString >() )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
allHeadwords.insert( value.toString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// continue to write the remaining headword
|
|
||||||
int nodeIndex = model->getCurrentIndex();
|
|
||||||
auto headwords = model->getRemainRows( nodeIndex );
|
|
||||||
while( !headwords.isEmpty() )
|
|
||||||
{
|
|
||||||
if( progress.wasCanceled() )
|
|
||||||
break;
|
|
||||||
allHeadwords.unite(headwords);
|
|
||||||
|
|
||||||
totalCount += headwords.size();
|
|
||||||
progress.setValue( totalCount );
|
|
||||||
|
|
||||||
headwords = model->getRemainRows( nodeIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug()<<model->getCurrentIndex();
|
|
||||||
|
|
||||||
// Write UTF-8 BOM
|
// Write UTF-8 BOM
|
||||||
QByteArray line;
|
QByteArray line;
|
||||||
line.append( 0xEF ).append( 0xBB ).append( 0xBF );
|
line.append( 0xEF ).append( 0xBB ).append( 0xBF );
|
||||||
file.write( line );
|
file.write( line );
|
||||||
|
|
||||||
QList< QString > sortedWords = allHeadwords.values();
|
QStringList filtered;
|
||||||
sortedWords.sort();
|
|
||||||
|
|
||||||
|
const QRegularExpression regExp = getFilterRegex();
|
||||||
|
if(regExp.isValid() && !regExp.pattern().isEmpty()){
|
||||||
|
filtered = sortedWords.filter( regExp );
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
filtered = sortedWords;
|
||||||
|
}
|
||||||
|
auto currentValue = progress.value();
|
||||||
// Write headwords
|
// Write headwords
|
||||||
for( auto const & word : sortedWords )
|
for ( auto const & word : filtered )
|
||||||
{
|
{
|
||||||
if( progress.wasCanceled() )
|
if( progress.wasCanceled() )
|
||||||
break;
|
break;
|
||||||
progress.setValue( totalCount++ );
|
progress.setValue( currentValue++ );
|
||||||
|
|
||||||
line = word.toUtf8();
|
line = word.toUtf8();
|
||||||
|
|
||||||
line.replace( '\n', ' ' );
|
line.replace( '\n', ' ' );
|
||||||
|
@ -361,6 +395,7 @@ void DictHeadwords::saveHeadersToFile()
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
progress.setValue( progress.maximum() );
|
||||||
if( progress.wasCanceled() )
|
if( progress.wasCanceled() )
|
||||||
{
|
{
|
||||||
QMessageBox::warning( this, "GoldenDict", tr( "Export process is interrupted" ) );
|
QMessageBox::warning( this, "GoldenDict", tr( "Export process is interrupted" ) );
|
||||||
|
@ -370,7 +405,7 @@ void DictHeadwords::saveHeadersToFile()
|
||||||
{
|
{
|
||||||
//completed.
|
//completed.
|
||||||
progress.setValue(headwordsNumber*2);
|
progress.setValue(headwordsNumber*2);
|
||||||
progress.hide();
|
progress.close();
|
||||||
QMessageBox::information( this, "GoldenDict", tr( "Export finished" ) );
|
QMessageBox::information( this, "GoldenDict", tr( "Export finished" ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <qprogressdialog.h>
|
||||||
|
|
||||||
#include "config.hh"
|
#include "config.hh"
|
||||||
#include "ui_dictheadwords.h"
|
#include "ui_dictheadwords.h"
|
||||||
|
@ -42,15 +43,19 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::DictHeadwords ui;
|
Ui::DictHeadwords ui;
|
||||||
|
QStringList sortedWords;
|
||||||
|
QMutex mutex;
|
||||||
private slots:
|
private slots:
|
||||||
void savePos();
|
void savePos();
|
||||||
void filterChangedInternal();
|
void filterChangedInternal();
|
||||||
|
QRegularExpression getFilterRegex();
|
||||||
void filterChanged();
|
void filterChanged();
|
||||||
void exportButtonClicked();
|
void exportButtonClicked();
|
||||||
void okButtonClicked();
|
void okButtonClicked();
|
||||||
void itemClicked( const QModelIndex & index );
|
void itemClicked( const QModelIndex & index );
|
||||||
void autoApplyStateChanged( int state );
|
void autoApplyStateChanged( int state );
|
||||||
void showHeadwordsNumber();
|
void showHeadwordsNumber();
|
||||||
|
void loadAllSortedWords( QProgressDialog & progress );
|
||||||
virtual void reject();
|
virtual void reject();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
Loading…
Reference in a new issue