Skip to content

Commit

Permalink
[FEATURE][browser] Add "New" menu to context menu on directories
Browse files Browse the repository at this point in the history
With option to create a new geopackage or shapefile in the
clicked directory
  • Loading branch information
nyalldawson committed Nov 4, 2018
1 parent 348c1dc commit 40443eb
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 8 deletions.
17 changes: 16 additions & 1 deletion python/gui/auto_generated/qgsnewvectorlayerdialog.sip.in
Expand Up @@ -17,10 +17,13 @@ class QgsNewVectorLayerDialog: QDialog
%End
public:

static QString runAndCreateLayer( QWidget *parent = 0, QString *enc = 0, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
static QString runAndCreateLayer( QWidget *parent = 0, QString *enc = 0, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem(),
const QString &initialPath = QString() );
%Docstring
Runs the dialog and creates a layer matching the dialog parameters.

If the ``initialPath`` argument is specified, then the dialog will default to the specified filename.

:return: fileName on success, empty string use aborted, QString() if creation failed
%End

Expand All @@ -42,9 +45,21 @@ Returns the file format for storage
%Docstring
Returns the file format for storage
%End

QString filename() const;
%Docstring
Returns the name for the new layer

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

void setFilename( const QString &filename );
%Docstring
Sets the initial file name to show in the dialog.

.. seealso:: :py:func:`filename`

.. versionadded:: 3.6
%End

QgsCoordinateReferenceSystem crs() const;
Expand Down
35 changes: 32 additions & 3 deletions src/app/browser/qgsinbuiltdataitemproviders.cpp
Expand Up @@ -27,6 +27,8 @@
#include "qgsbrowserdockwidget_p.h"
#include "qgswindowmanagerinterface.h"
#include "qgsrasterlayer.h"
#include "qgsnewvectorlayerdialog.h"
#include "qgsnewgeopackagelayerdialog.h"
#include <QMenu>
#include <QInputDialog>
#include <QMessageBox>
Expand All @@ -47,8 +49,9 @@ void QgsAppDirectoryItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe

QgsSettings settings;

QMenu *newMenu = new QMenu( tr( "New" ), menu );

QAction *createFolder = new QAction( tr( "New Directory…" ), menu );
QAction *createFolder = new QAction( tr( "Directory…" ), menu );
connect( createFolder, &QAction::triggered, this, [ = ]
{
bool ok = false;
Expand All @@ -71,7 +74,34 @@ void QgsAppDirectoryItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe
}
}
} );
menu->addAction( createFolder );
newMenu->addAction( createFolder );

QAction *createGpkg = new QAction( tr( "GeoPackage…" ), newMenu );
createGpkg->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionNewGeoPackageLayer.svg" ) ) );
connect( createGpkg, &QAction::triggered, this, [ = ]
{
QgsNewGeoPackageLayerDialog dialog( QgisApp::instance() );
QDir dir( directoryItem->dirPath() );
dialog.setDatabasePath( dir.filePath( QStringLiteral( "new_geopackage" ) ) );
dialog.setCrs( QgsProject::instance()->defaultCrsForNewLayers() );
if ( dialog.exec() )
item->refresh();
} );
newMenu->addAction( createGpkg );

QAction *createShp = new QAction( tr( "ShapeFile…" ), newMenu );
createShp->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionNewVectorLayer.svg" ) ) );
connect( createShp, &QAction::triggered, this, [ = ]
{
QString enc;
QDir dir( directoryItem->dirPath() );
const QString newFile = QgsNewVectorLayerDialog::runAndCreateLayer( QgisApp::instance(), &enc, QgsProject::instance()->defaultCrsForNewLayers(), dir.filePath( QStringLiteral( "new_layer.shp" ) ) );
if ( !newFile.isEmpty() )
item->refresh();
} );
newMenu->addAction( createShp );

menu->addMenu( newMenu );

menu->addSeparator();

Expand All @@ -97,7 +127,6 @@ void QgsAppDirectoryItemGuiProvider::populateContextMenu( QgsDataItem *item, QMe
renameFavorite( favoriteItem );
} );
menu->addAction( actionRename );
menu->addSeparator();
QAction *removeFavoriteAction = new QAction( tr( "Remove Favorite" ), menu );
connect( removeFavoriteAction, &QAction::triggered, this, [ = ]
{
Expand Down
16 changes: 14 additions & 2 deletions src/gui/qgsnewvectorlayerdialog.cpp
Expand Up @@ -30,7 +30,7 @@
#include <QComboBox>
#include <QLibrary>
#include <QFileDialog>

#include <QMessageBox>

QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFlags fl )
: QDialog( parent, fl )
Expand Down Expand Up @@ -104,6 +104,7 @@ QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFla

mFileName->setStorageMode( QgsFileWidget::SaveFile );
mFileName->setFilter( QgsVectorFileWriter::filterForDriver( mFileFormatComboBox->currentData( Qt::UserRole ).toString() ) );
mFileName->setConfirmOverwrite( false );
mFileName->setDialogTitle( tr( "Save Layer As" ) );
mFileName->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() );
connect( mFileName, &QgsFileWidget::fileChanged, this, [ = ]
Expand Down Expand Up @@ -245,22 +246,33 @@ QString QgsNewVectorLayerDialog::filename() const
return mFileName->filePath();
}

void QgsNewVectorLayerDialog::setFilename( const QString &filename )
{
mFileName->setFilePath( filename );
}

void QgsNewVectorLayerDialog::checkOk()
{
bool ok = ( !mFileName->filePath().isEmpty() && mAttributeView->topLevelItemCount() > 0 );
mOkButton->setEnabled( ok );
}

// this is static
QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pEnc, const QgsCoordinateReferenceSystem &crs )
QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pEnc, const QgsCoordinateReferenceSystem &crs, const QString &initialPath )
{
QgsNewVectorLayerDialog geomDialog( parent );
geomDialog.setCrs( crs );
if ( !initialPath.isEmpty() )
geomDialog.setFilename( initialPath );
if ( geomDialog.exec() == QDialog::Rejected )
{
return QString();
}

if ( QFile::exists( geomDialog.filename() ) && QMessageBox::warning( parent, tr( "New ShapeFile Layer" ), tr( "The layer already exists. Are you sure you want to overwrite the existing file?" ),
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel ) != QMessageBox::Yes )
return QString();

QgsWkbTypes::Type geometrytype = geomDialog.selectedType();
QString fileformat = geomDialog.selectedFileFormat();
QString enc = geomDialog.selectedFileEncoding();
Expand Down
22 changes: 20 additions & 2 deletions src/gui/qgsnewvectorlayerdialog.h
Expand Up @@ -36,9 +36,13 @@ class GUI_EXPORT QgsNewVectorLayerDialog: public QDialog, private Ui::QgsNewVect

/**
* Runs the dialog and creates a layer matching the dialog parameters.
*
* If the \a initialPath argument is specified, then the dialog will default to the specified filename.
*
* \returns fileName on success, empty string use aborted, QString() if creation failed
*/
static QString runAndCreateLayer( QWidget *parent = nullptr, QString *enc = nullptr, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
static QString runAndCreateLayer( QWidget *parent = nullptr, QString *enc = nullptr, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem(),
const QString &initialPath = QString() );

QgsNewVectorLayerDialog( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
~QgsNewVectorLayerDialog() override;
Expand All @@ -50,9 +54,23 @@ class GUI_EXPORT QgsNewVectorLayerDialog: public QDialog, private Ui::QgsNewVect
QString selectedFileFormat() const;
//! Returns the file format for storage
QString selectedFileEncoding() const;
//! Returns the name for the new layer

/**
* Returns the name for the new layer
*
* \see setFilename()
*/
QString filename() const;

/**
* Sets the initial file name to show in the dialog.
*
* \see filename()
*
* \since QGIS 3.6
*/
void setFilename( const QString &filename );

/**
* Returns the selected CRS for the new layer.
* \see setCrs()
Expand Down

0 comments on commit 40443eb

Please sign in to comment.