Skip to content

Commit 3f4c3d0

Browse files
committed
Add widget and dialog for finding files by pattern match, with an
optional recursive search
1 parent 5edf06a commit 3f4c3d0

File tree

6 files changed

+422
-0
lines changed

6 files changed

+422
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/qgsfindfilesbypatternwidget.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsFindFilesByPatternWidget : QWidget
14+
{
15+
%Docstring
16+
A reusable widget for finding files (recursively) by file pattern.
17+
18+
.. versionadded:: 3.8
19+
%End
20+
21+
%TypeHeaderCode
22+
#include "qgsfindfilesbypatternwidget.h"
23+
%End
24+
public:
25+
26+
QgsFindFilesByPatternWidget( QWidget *parent /TransferThis/ = 0 );
27+
%Docstring
28+
Constructor for QgsFindFilesByPatternWidget, with the specified ``parent`` widget.
29+
%End
30+
31+
QStringList files() const;
32+
%Docstring
33+
Returns the list of files found by the dialog.
34+
35+
.. seealso:: :py:func:`filesFound`
36+
%End
37+
38+
signals:
39+
40+
void filesFound( const QStringList &files );
41+
%Docstring
42+
Emitted after files are found in the dialog.
43+
44+
.. seealso:: :py:func:`files`
45+
%End
46+
47+
};
48+
49+
class QgsFindFilesByPatternDialog : QDialog
50+
{
51+
%Docstring
52+
A dialog for finding files (recursively) by file pattern.
53+
54+
.. versionadded:: 3.8
55+
%End
56+
57+
%TypeHeaderCode
58+
#include "qgsfindfilesbypatternwidget.h"
59+
%End
60+
public:
61+
62+
QgsFindFilesByPatternDialog( QWidget *parent /TransferThis/ = 0 );
63+
%Docstring
64+
Constructor for QgsFindFilesByPatternDialog, with the specified ``parent`` widget.
65+
%End
66+
67+
QStringList files() const;
68+
%Docstring
69+
Returns the list of files found by the dialog.
70+
71+
.. seealso:: :py:func:`filesFound`
72+
%End
73+
74+
};
75+
76+
/************************************************************************
77+
* This file has been generated automatically from *
78+
* *
79+
* src/gui/qgsfindfilesbypatternwidget.h *
80+
* *
81+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
82+
************************************************************************/

python/gui/gui_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
%Include auto_generated/qgsfeatureselectiondlg.sip
114114
%Include auto_generated/qgsfieldcombobox.sip
115115
%Include auto_generated/qgsfieldexpressionwidget.sip
116+
%Include auto_generated/qgsfindfilesbypatternwidget.sip
116117
%Include auto_generated/qgsfeaturelistcombobox.sip
117118
%Include auto_generated/qgsfieldvalidator.sip
118119
%Include auto_generated/qgsfieldvalueslineedit.sip

src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ SET(QGIS_GUI_SRCS
277277
qgsfilecontentsourcelineedit.cpp
278278
qgsfilewidget.cpp
279279
qgsfilterlineedit.cpp
280+
qgsfindfilesbypatternwidget.cpp
280281
qgsfloatingwidget.cpp
281282
qgsfocuswatcher.cpp
282283
qgsfontbutton.cpp
@@ -452,6 +453,7 @@ SET(QGIS_GUI_MOC_HDRS
452453
qgsfeatureselectiondlg.h
453454
qgsfieldcombobox.h
454455
qgsfieldexpressionwidget.h
456+
qgsfindfilesbypatternwidget.h
455457
qgsfeaturelistcombobox.h
456458
qgsfieldvalidator.h
457459
qgsfieldvalueslineedit.h
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/***************************************************************************
2+
qgsfindfilesbypatternwidget.cpp
3+
-----------------------------
4+
begin : April 2019
5+
copyright : (C) 2019 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsfindfilesbypatternwidget.h"
17+
#include "qgsgui.h"
18+
#include "qgssettings.h"
19+
20+
#include <QDir>
21+
#include <QDirIterator>
22+
#include <QDialogButtonBox>
23+
24+
25+
QgsFindFilesByPatternWidget::QgsFindFilesByPatternWidget( QWidget *parent )
26+
: QWidget( parent )
27+
{
28+
setupUi( this );
29+
30+
mFolderWidget->setStorageMode( QgsFileWidget::GetDirectory );
31+
mResultsTable->setColumnCount( 2 );
32+
33+
mResultsTable->setHorizontalHeaderLabels( QStringList() << tr( "File" ) << tr( "Directory" ) );
34+
mResultsTable->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
35+
mResultsTable->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );
36+
37+
connect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::find );
38+
39+
QgsSettings settings;
40+
mFolderWidget->setFilePath( settings.value( QStringLiteral( "qgis/lastFindRecursiveFolder" ) ).toString() );
41+
mFindButton->setEnabled( !mFolderWidget->filePath().isEmpty() );
42+
connect( mFolderWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath )
43+
{
44+
QgsSettings settings;
45+
settings.setValue( QStringLiteral( "qgis/lastFindRecursiveFolder" ), filePath );
46+
mFindButton->setEnabled( !filePath.isEmpty() );
47+
} );
48+
49+
}
50+
51+
void QgsFindFilesByPatternWidget::find()
52+
{
53+
mFindButton->setText( tr( "Cancel" ) );
54+
disconnect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::find );
55+
connect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::cancel );
56+
mCanceled = false;
57+
58+
mResultsTable->setRowCount( 0 );
59+
mFiles.clear();
60+
61+
const QString pattern = mPatternLineEdit->text();
62+
const QString path = mFolderWidget->filePath();
63+
64+
QDir startDir( path );
65+
66+
QStringList filter;
67+
if ( !pattern.isEmpty() )
68+
filter << pattern;
69+
70+
QDirIterator it( path, filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot, mRecursiveCheckBox->isChecked() ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags );
71+
QStringList files;
72+
while ( it.hasNext() )
73+
{
74+
const QString fullPath = it.next();
75+
mFiles << fullPath;
76+
77+
QFileInfo fi( fullPath );
78+
79+
const QString toolTip = QDir::toNativeSeparators( fullPath );
80+
const QString fileName = fi.fileName();
81+
const QString relativeDirectory = QDir::toNativeSeparators( startDir.relativeFilePath( fi.dir().absolutePath() ) );
82+
const QString fullDirectory = QDir::toNativeSeparators( fi.dir().absolutePath() );
83+
84+
QTableWidgetItem *fileNameItem = new QTableWidgetItem( fileName );
85+
fileNameItem->setToolTip( toolTip );
86+
fileNameItem->setFlags( fileNameItem->flags() ^ Qt::ItemIsEditable );
87+
88+
QTableWidgetItem *directoryItem = new QTableWidgetItem( relativeDirectory );
89+
directoryItem->setToolTip( fullDirectory );
90+
directoryItem->setFlags( directoryItem->flags() ^ Qt::ItemIsEditable );
91+
92+
const int row = mResultsTable->rowCount();
93+
mResultsTable->insertRow( row );
94+
mResultsTable->setItem( row, 0, fileNameItem );
95+
mResultsTable->setItem( row, 1, directoryItem );
96+
97+
QCoreApplication::processEvents();
98+
if ( mCanceled )
99+
break;
100+
}
101+
102+
mFindButton->setText( tr( "Find Files" ) );
103+
disconnect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::cancel );
104+
connect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::find );
105+
106+
emit filesFound( mFiles );
107+
}
108+
109+
void QgsFindFilesByPatternWidget::cancel()
110+
{
111+
mCanceled = true;
112+
}
113+
114+
115+
//
116+
// QgsFindFilesByPatternDialog
117+
//
118+
119+
QgsFindFilesByPatternDialog::QgsFindFilesByPatternDialog( QWidget *parent )
120+
: QDialog( parent )
121+
{
122+
setWindowTitle( tr( "Find Files by Pattern" ) );
123+
setObjectName( "QgsFindFilesByPatternDialog" );
124+
125+
QgsGui::enableAutoGeometryRestore( this );
126+
127+
QVBoxLayout *vLayout = new QVBoxLayout();
128+
mWidget = new QgsFindFilesByPatternWidget();
129+
130+
vLayout->addWidget( mWidget );
131+
mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
132+
connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
133+
connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
134+
vLayout->addWidget( mButtonBox );
135+
setLayout( vLayout );
136+
137+
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
138+
connect( mWidget, &QgsFindFilesByPatternWidget::filesFound, this, [ = ]( const QStringList & files )
139+
{
140+
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !files.empty() );
141+
} );
142+
}
143+
144+
QStringList QgsFindFilesByPatternDialog::files() const
145+
{
146+
return mWidget->files();
147+
}

src/gui/qgsfindfilesbypatternwidget.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/***************************************************************************
2+
qgsfindfilesbypatternwidget.h
3+
-----------------------------
4+
begin : April 2019
5+
copyright : (C) 2019 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSFINDFILESBYPATTERNWIDGET_H
17+
#define QGSFINDFILESBYPATTERNWIDGET_H
18+
19+
#include "ui_qgsfindfilesbypatternwidget.h"
20+
#include "qgis_gui.h"
21+
22+
#include <QDialog>
23+
24+
class QDialogButtonBox;
25+
26+
/**
27+
* \class QgsFindFilesByPatternWidget
28+
* \ingroup gui
29+
* A reusable widget for finding files (recursively) by file pattern.
30+
* \since QGIS 3.8
31+
*/
32+
class GUI_EXPORT QgsFindFilesByPatternWidget : public QWidget, private Ui::QgsFindFilesByPatternWidgetBase
33+
{
34+
Q_OBJECT
35+
36+
public:
37+
38+
/**
39+
* Constructor for QgsFindFilesByPatternWidget, with the specified \a parent widget.
40+
*/
41+
QgsFindFilesByPatternWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr );
42+
43+
/**
44+
* Returns the list of files found by the dialog.
45+
* \see filesFound()
46+
*/
47+
QStringList files() const { return mFiles; }
48+
49+
signals:
50+
51+
/**
52+
* Emitted after files are found in the dialog.
53+
*
54+
* \see files()
55+
*/
56+
void filesFound( const QStringList &files );
57+
58+
private slots:
59+
60+
void find();
61+
void cancel();
62+
63+
private:
64+
65+
bool mCanceled = false;
66+
QStringList mFiles;
67+
};
68+
69+
/**
70+
* \class QgsFindFilesByPatternDialog
71+
* \ingroup gui
72+
* A dialog for finding files (recursively) by file pattern.
73+
* \since QGIS 3.8
74+
*/
75+
class GUI_EXPORT QgsFindFilesByPatternDialog : public QDialog
76+
{
77+
Q_OBJECT
78+
79+
public:
80+
81+
/**
82+
* Constructor for QgsFindFilesByPatternDialog, with the specified \a parent widget.
83+
*/
84+
QgsFindFilesByPatternDialog( QWidget *parent SIP_TRANSFERTHIS = nullptr );
85+
86+
/**
87+
* Returns the list of files found by the dialog.
88+
* \see filesFound()
89+
*/
90+
QStringList files() const;
91+
92+
private:
93+
94+
QgsFindFilesByPatternWidget *mWidget = nullptr;
95+
QDialogButtonBox *mButtonBox = nullptr;
96+
97+
};
98+
99+
#endif // QGSFINDFILESBYPATTERNWIDGET_H

0 commit comments

Comments
 (0)