Skip to content
Permalink
Browse files

Add widget and dialog for finding files by pattern match, with an

optional recursive search
  • Loading branch information
nyalldawson committed Apr 26, 2019
1 parent 5edf06a commit 3f4c3d07222793c49de0857f63dc2a58811ccc13
@@ -0,0 +1,82 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsfindfilesbypatternwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsFindFilesByPatternWidget : QWidget
{
%Docstring
A reusable widget for finding files (recursively) by file pattern.

.. versionadded:: 3.8
%End

%TypeHeaderCode
#include "qgsfindfilesbypatternwidget.h"
%End
public:

QgsFindFilesByPatternWidget( QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsFindFilesByPatternWidget, with the specified ``parent`` widget.
%End

QStringList files() const;
%Docstring
Returns the list of files found by the dialog.

.. seealso:: :py:func:`filesFound`
%End

signals:

void filesFound( const QStringList &files );
%Docstring
Emitted after files are found in the dialog.

.. seealso:: :py:func:`files`
%End

};

class QgsFindFilesByPatternDialog : QDialog
{
%Docstring
A dialog for finding files (recursively) by file pattern.

.. versionadded:: 3.8
%End

%TypeHeaderCode
#include "qgsfindfilesbypatternwidget.h"
%End
public:

QgsFindFilesByPatternDialog( QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsFindFilesByPatternDialog, with the specified ``parent`` widget.
%End

QStringList files() const;
%Docstring
Returns the list of files found by the dialog.

.. seealso:: :py:func:`filesFound`
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsfindfilesbypatternwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -113,6 +113,7 @@
%Include auto_generated/qgsfeatureselectiondlg.sip
%Include auto_generated/qgsfieldcombobox.sip
%Include auto_generated/qgsfieldexpressionwidget.sip
%Include auto_generated/qgsfindfilesbypatternwidget.sip
%Include auto_generated/qgsfeaturelistcombobox.sip
%Include auto_generated/qgsfieldvalidator.sip
%Include auto_generated/qgsfieldvalueslineedit.sip
@@ -277,6 +277,7 @@ SET(QGIS_GUI_SRCS
qgsfilecontentsourcelineedit.cpp
qgsfilewidget.cpp
qgsfilterlineedit.cpp
qgsfindfilesbypatternwidget.cpp
qgsfloatingwidget.cpp
qgsfocuswatcher.cpp
qgsfontbutton.cpp
@@ -452,6 +453,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsfeatureselectiondlg.h
qgsfieldcombobox.h
qgsfieldexpressionwidget.h
qgsfindfilesbypatternwidget.h
qgsfeaturelistcombobox.h
qgsfieldvalidator.h
qgsfieldvalueslineedit.h
@@ -0,0 +1,147 @@
/***************************************************************************
qgsfindfilesbypatternwidget.cpp
-----------------------------
begin : April 2019
copyright : (C) 2019 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsfindfilesbypatternwidget.h"
#include "qgsgui.h"
#include "qgssettings.h"

#include <QDir>
#include <QDirIterator>
#include <QDialogButtonBox>


QgsFindFilesByPatternWidget::QgsFindFilesByPatternWidget( QWidget *parent )
: QWidget( parent )
{
setupUi( this );

mFolderWidget->setStorageMode( QgsFileWidget::GetDirectory );
mResultsTable->setColumnCount( 2 );

mResultsTable->setHorizontalHeaderLabels( QStringList() << tr( "File" ) << tr( "Directory" ) );
mResultsTable->horizontalHeader()->setSectionResizeMode( 0, QHeaderView::Stretch );
mResultsTable->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::Stretch );

connect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::find );

QgsSettings settings;
mFolderWidget->setFilePath( settings.value( QStringLiteral( "qgis/lastFindRecursiveFolder" ) ).toString() );
mFindButton->setEnabled( !mFolderWidget->filePath().isEmpty() );
connect( mFolderWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath )
{
QgsSettings settings;
settings.setValue( QStringLiteral( "qgis/lastFindRecursiveFolder" ), filePath );
mFindButton->setEnabled( !filePath.isEmpty() );
} );

}

void QgsFindFilesByPatternWidget::find()
{
mFindButton->setText( tr( "Cancel" ) );
disconnect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::find );
connect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::cancel );
mCanceled = false;

mResultsTable->setRowCount( 0 );
mFiles.clear();

const QString pattern = mPatternLineEdit->text();
const QString path = mFolderWidget->filePath();

QDir startDir( path );

QStringList filter;
if ( !pattern.isEmpty() )
filter << pattern;

QDirIterator it( path, filter, QDir::AllEntries | QDir::NoSymLinks | QDir::NoDotAndDotDot, mRecursiveCheckBox->isChecked() ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags );
QStringList files;
while ( it.hasNext() )
{
const QString fullPath = it.next();
mFiles << fullPath;

QFileInfo fi( fullPath );

const QString toolTip = QDir::toNativeSeparators( fullPath );
const QString fileName = fi.fileName();
const QString relativeDirectory = QDir::toNativeSeparators( startDir.relativeFilePath( fi.dir().absolutePath() ) );
const QString fullDirectory = QDir::toNativeSeparators( fi.dir().absolutePath() );

QTableWidgetItem *fileNameItem = new QTableWidgetItem( fileName );
fileNameItem->setToolTip( toolTip );
fileNameItem->setFlags( fileNameItem->flags() ^ Qt::ItemIsEditable );

QTableWidgetItem *directoryItem = new QTableWidgetItem( relativeDirectory );
directoryItem->setToolTip( fullDirectory );
directoryItem->setFlags( directoryItem->flags() ^ Qt::ItemIsEditable );

const int row = mResultsTable->rowCount();
mResultsTable->insertRow( row );
mResultsTable->setItem( row, 0, fileNameItem );
mResultsTable->setItem( row, 1, directoryItem );

QCoreApplication::processEvents();
if ( mCanceled )
break;
}

mFindButton->setText( tr( "Find Files" ) );
disconnect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::cancel );
connect( mFindButton, &QPushButton::clicked, this, &QgsFindFilesByPatternWidget::find );

emit filesFound( mFiles );
}

void QgsFindFilesByPatternWidget::cancel()
{
mCanceled = true;
}


//
// QgsFindFilesByPatternDialog
//

QgsFindFilesByPatternDialog::QgsFindFilesByPatternDialog( QWidget *parent )
: QDialog( parent )
{
setWindowTitle( tr( "Find Files by Pattern" ) );
setObjectName( "QgsFindFilesByPatternDialog" );

QgsGui::enableAutoGeometryRestore( this );

QVBoxLayout *vLayout = new QVBoxLayout();
mWidget = new QgsFindFilesByPatternWidget();

vLayout->addWidget( mWidget );
mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
vLayout->addWidget( mButtonBox );
setLayout( vLayout );

mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
connect( mWidget, &QgsFindFilesByPatternWidget::filesFound, this, [ = ]( const QStringList & files )
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !files.empty() );
} );
}

QStringList QgsFindFilesByPatternDialog::files() const
{
return mWidget->files();
}
@@ -0,0 +1,99 @@
/***************************************************************************
qgsfindfilesbypatternwidget.h
-----------------------------
begin : April 2019
copyright : (C) 2019 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSFINDFILESBYPATTERNWIDGET_H
#define QGSFINDFILESBYPATTERNWIDGET_H

#include "ui_qgsfindfilesbypatternwidget.h"
#include "qgis_gui.h"

#include <QDialog>

class QDialogButtonBox;

/**
* \class QgsFindFilesByPatternWidget
* \ingroup gui
* A reusable widget for finding files (recursively) by file pattern.
* \since QGIS 3.8
*/
class GUI_EXPORT QgsFindFilesByPatternWidget : public QWidget, private Ui::QgsFindFilesByPatternWidgetBase
{
Q_OBJECT

public:

/**
* Constructor for QgsFindFilesByPatternWidget, with the specified \a parent widget.
*/
QgsFindFilesByPatternWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr );

/**
* Returns the list of files found by the dialog.
* \see filesFound()
*/
QStringList files() const { return mFiles; }

signals:

/**
* Emitted after files are found in the dialog.
*
* \see files()
*/
void filesFound( const QStringList &files );

private slots:

void find();
void cancel();

private:

bool mCanceled = false;
QStringList mFiles;
};

/**
* \class QgsFindFilesByPatternDialog
* \ingroup gui
* A dialog for finding files (recursively) by file pattern.
* \since QGIS 3.8
*/
class GUI_EXPORT QgsFindFilesByPatternDialog : public QDialog
{
Q_OBJECT

public:

/**
* Constructor for QgsFindFilesByPatternDialog, with the specified \a parent widget.
*/
QgsFindFilesByPatternDialog( QWidget *parent SIP_TRANSFERTHIS = nullptr );

/**
* Returns the list of files found by the dialog.
* \see filesFound()
*/
QStringList files() const;

private:

QgsFindFilesByPatternWidget *mWidget = nullptr;
QDialogButtonBox *mButtonBox = nullptr;

};

#endif // QGSFINDFILESBYPATTERNWIDGET_H

0 comments on commit 3f4c3d0

Please sign in to comment.
You can’t perform that action at this time.