mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 19:24:08 +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 <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include "fsencoding.hh"
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QRegularExpression>
|
||||
|
|
|
@ -46,10 +46,29 @@ void HeadwordListModel::setFilter( QRegularExpression reg )
|
|||
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()
|
||||
{
|
||||
// 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(); )
|
||||
{
|
||||
if( ( *i )->isFinished() )
|
||||
|
|
|
@ -20,6 +20,7 @@ public:
|
|||
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override;
|
||||
QString getRow( int row );
|
||||
void setFilter( QRegularExpression );
|
||||
void addMatches( QStringList matches );
|
||||
int getCurrentIndex();
|
||||
QSet< QString > getRemainRows( int & nodeIndex );
|
||||
signals:
|
||||
|
|
|
@ -17,19 +17,19 @@
|
|||
#include "wildcard.hh"
|
||||
#include "help.hh"
|
||||
#include <QMessageBox>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#define AUTO_APPLY_LIMIT 150000
|
||||
|
||||
DictHeadwords::DictHeadwords( QWidget *parent, Config::Class & cfg_,
|
||||
Dictionary::Class * dict_ ) :
|
||||
QDialog(parent)
|
||||
, cfg( cfg_ )
|
||||
, dict( dict_ )
|
||||
, helpAction( this )
|
||||
DictHeadwords::DictHeadwords( QWidget * parent, Config::Class & cfg_, Dictionary::Class * dict_ ):
|
||||
QDialog( parent ),
|
||||
cfg( cfg_ ),
|
||||
dict( dict_ ),
|
||||
helpAction( this )
|
||||
{
|
||||
ui.setupUi( this );
|
||||
|
||||
bool fromMainWindow = parent->objectName() == "MainWindow";
|
||||
const bool fromMainWindow = parent->objectName() == "MainWindow";
|
||||
|
||||
if( fromMainWindow )
|
||||
setAttribute( Qt::WA_DeleteOnClose, false );
|
||||
|
@ -126,7 +126,7 @@ void DictHeadwords::setup( Dictionary::Class *dict_ )
|
|||
|
||||
setWindowTitle( QString::fromUtf8( dict->getName().c_str() ) );
|
||||
|
||||
auto size = dict->getWordCount();
|
||||
const auto size = dict->getWordCount();
|
||||
model->setDict(dict);
|
||||
proxy->sort( 0 );
|
||||
filterChanged();
|
||||
|
@ -180,13 +180,13 @@ bool DictHeadwords::eventFilter( QObject * obj, QEvent * ev )
|
|||
void DictHeadwords::okButtonClicked()
|
||||
{
|
||||
savePos();
|
||||
closeDialog();
|
||||
emit closeDialog();
|
||||
}
|
||||
|
||||
void DictHeadwords::reject()
|
||||
{
|
||||
savePos();
|
||||
closeDialog();
|
||||
emit closeDialog();
|
||||
}
|
||||
|
||||
void DictHeadwords::exportButtonClicked()
|
||||
|
@ -201,11 +201,11 @@ void DictHeadwords::filterChangedInternal()
|
|||
QTimer::singleShot( 100, this, &DictHeadwords::filterChanged );
|
||||
}
|
||||
|
||||
void DictHeadwords::filterChanged()
|
||||
QRegularExpression DictHeadwords::getFilterRegex( )
|
||||
{
|
||||
QRegExp::PatternSyntax syntax =
|
||||
QRegExp::PatternSyntax( ui.searchModeCombo->itemData(
|
||||
ui.searchModeCombo->currentIndex()).toInt() );
|
||||
const QRegExp::PatternSyntax syntax =
|
||||
static_cast< QRegExp::PatternSyntax >(ui.searchModeCombo->itemData(
|
||||
ui.searchModeCombo->currentIndex() ).toInt());
|
||||
|
||||
QRegularExpression::PatternOptions options = QRegularExpression::UseUnicodePropertiesOption;
|
||||
if( !ui.matchCase->isChecked() )
|
||||
|
@ -214,28 +214,46 @@ 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 );
|
||||
QRegularExpression regExp = QRegularExpression( pattern, options );
|
||||
|
||||
if( !regExp.isValid() )
|
||||
{
|
||||
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 );
|
||||
|
||||
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->sort( 0 );
|
||||
|
@ -266,6 +284,47 @@ void DictHeadwords::showHeadwordsNumber()
|
|||
.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()
|
||||
{
|
||||
QString exportPath;
|
||||
|
@ -295,59 +354,34 @@ void DictHeadwords::saveHeadersToFile()
|
|||
cfg.headwordsDialog.headwordsExportPath = QDir::toNativeSeparators(
|
||||
QFileInfo( fileName ).absoluteDir().absolutePath() );
|
||||
|
||||
QSet< QString > allHeadwords;
|
||||
int headwordsNumber = model->totalCount();
|
||||
const int headwordsNumber = model->totalCount();
|
||||
|
||||
//headwordsNumber*2 , read + write
|
||||
QProgressDialog progress( tr( "Export headwords..." ), tr( "Cancel" ), 0, headwordsNumber*2, this );
|
||||
progress.setWindowModality( Qt::WindowModal );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
qDebug()<<model->getCurrentIndex();
|
||||
loadAllSortedWords( progress );
|
||||
|
||||
// Write UTF-8 BOM
|
||||
QByteArray line;
|
||||
line.append( 0xEF ).append( 0xBB ).append( 0xBF );
|
||||
file.write( line );
|
||||
|
||||
QList< QString > sortedWords = allHeadwords.values();
|
||||
sortedWords.sort();
|
||||
QStringList filtered;
|
||||
|
||||
const QRegularExpression regExp = getFilterRegex();
|
||||
if(regExp.isValid() && !regExp.pattern().isEmpty()){
|
||||
filtered = sortedWords.filter( regExp );
|
||||
}
|
||||
else{
|
||||
filtered = sortedWords;
|
||||
}
|
||||
auto currentValue = progress.value();
|
||||
// Write headwords
|
||||
for( auto const & word : sortedWords )
|
||||
for ( auto const & word : filtered )
|
||||
{
|
||||
if( progress.wasCanceled() )
|
||||
break;
|
||||
progress.setValue( totalCount++ );
|
||||
|
||||
progress.setValue( currentValue++ );
|
||||
line = word.toUtf8();
|
||||
|
||||
line.replace( '\n', ' ' );
|
||||
|
@ -361,6 +395,7 @@ void DictHeadwords::saveHeadersToFile()
|
|||
|
||||
file.close();
|
||||
|
||||
progress.setValue( progress.maximum() );
|
||||
if( progress.wasCanceled() )
|
||||
{
|
||||
QMessageBox::warning( this, "GoldenDict", tr( "Export process is interrupted" ) );
|
||||
|
@ -370,7 +405,7 @@ void DictHeadwords::saveHeadersToFile()
|
|||
{
|
||||
//completed.
|
||||
progress.setValue(headwordsNumber*2);
|
||||
progress.hide();
|
||||
progress.close();
|
||||
QMessageBox::information( this, "GoldenDict", tr( "Export finished" ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QStringListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QAction>
|
||||
#include <qprogressdialog.h>
|
||||
|
||||
#include "config.hh"
|
||||
#include "ui_dictheadwords.h"
|
||||
|
@ -42,15 +43,19 @@ protected:
|
|||
|
||||
private:
|
||||
Ui::DictHeadwords ui;
|
||||
QStringList sortedWords;
|
||||
QMutex mutex;
|
||||
private slots:
|
||||
void savePos();
|
||||
void filterChangedInternal();
|
||||
QRegularExpression getFilterRegex();
|
||||
void filterChanged();
|
||||
void exportButtonClicked();
|
||||
void okButtonClicked();
|
||||
void itemClicked( const QModelIndex & index );
|
||||
void autoApplyStateChanged( int state );
|
||||
void showHeadwordsNumber();
|
||||
void loadAllSortedWords( QProgressDialog & progress );
|
||||
virtual void reject();
|
||||
|
||||
signals:
|
||||
|
|
Loading…
Reference in a new issue