Skip to content

Commit 7ac5215

Browse files
committed
[FEATURE] Add "export to file" options for raster and vector layers
within the browser panel Allows direct export of these files (e.g. to a different format, crs, etc) without having to actually load them into a project first.
1 parent 2089887 commit 7ac5215

12 files changed

+224
-29
lines changed

python/gui/auto_generated/qgsrasterlayersaveasdialog.sip.in

+16
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,23 @@ Constructor for QgsRasterLayerSaveAsDialog
5252
int maximumTileSizeX() const;
5353
int maximumTileSizeY() const;
5454
bool tileMode() const;
55+
5556
bool addToCanvas() const;
57+
%Docstring
58+
Returns true if the "add to canvas" checkbox is checked.
59+
60+
.. seealso:: :py:func:`setAddToCanvas`
61+
%End
62+
63+
void setAddToCanvas( bool checked );
64+
%Docstring
65+
Sets whether the "add to canvas" checkbox should be ``checked``.
66+
67+
.. seealso:: :py:func:`addToCanvas`
68+
69+
.. versionadded:: 3.6
70+
%End
71+
5672
QString outputFileName() const;
5773

5874
QString outputLayerName() const;

python/gui/auto_generated/qgswindowmanagerinterface.sip.in

+35
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111

12+
1213
class QgsWindowManagerInterface
1314
{
1415
%Docstring
@@ -44,6 +45,40 @@ existing instance to the foreground.
4445

4546
Returns the dialog if shown, or None if the dialog either could not be
4647
created or is not supported by the window manager implementation.
48+
%End
49+
50+
virtual QString executeExportVectorLayerDialog( QgsVectorLayer *layer );
51+
%Docstring
52+
Executes the standard "Export Vector Layer" dialog for the specified ``layer``,
53+
and performs an export using the settings accepted in the dialog.
54+
55+
The created vector file name is returned.
56+
57+
Depending on the window manager implementation the actual export of the
58+
layer may occur in a background task, in which case calling this method
59+
will immediately return after the dialog has been accepted, but before
60+
the exported layer has been finalized.
61+
62+
.. seealso:: :py:func:`executeExportRasterLayerDialog`
63+
64+
.. versionadded:: 3.6
65+
%End
66+
67+
virtual QString executeExportRasterLayerDialog( QgsRasterLayer *layer );
68+
%Docstring
69+
Executes the standard "Export Raster Layer" dialog for the specified ``layer``,
70+
and performs an export using the settings accepted in the dialog.
71+
72+
The created raster file name is returned.
73+
74+
Depending on the window manager implementation the actual export of the
75+
layer may occur in a background task, in which case calling this method
76+
will immediately return after the dialog has been accepted, but before
77+
the exported layer has been finalized.
78+
79+
.. seealso:: :py:func:`executeExportVectorLayerDialog`
80+
81+
.. versionadded:: 3.6
4782
%End
4883

4984
};

src/app/qgisapp.cpp

+24-18
Original file line numberDiff line numberDiff line change
@@ -7160,22 +7160,23 @@ void QgisApp::attributeTable( QgsAttributeTableFilterModel::FilterMode filter )
71607160
// the dialog will be deleted by itself on close
71617161
}
71627162

7163-
void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
7163+
QString QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer, const bool defaultAddToCanvas )
71647164
{
71657165
if ( !rasterLayer )
71667166
rasterLayer = qobject_cast<QgsRasterLayer *>( activeLayer() );
71677167

71687168
if ( !rasterLayer )
71697169
{
7170-
return;
7170+
return QString();
71717171
}
71727172

71737173
QgsRasterLayerSaveAsDialog d( rasterLayer, rasterLayer->dataProvider(),
71747174
mMapCanvas->extent(), rasterLayer->crs(),
71757175
mMapCanvas->mapSettings().destinationCrs(),
71767176
this );
7177+
d.setAddToCanvas( defaultAddToCanvas );
71777178
if ( d.exec() == QDialog::Rejected )
7178-
return;
7179+
return QString();
71797180

71807181
QgsSettings settings;
71817182
settings.setValue( QStringLiteral( "UI/lastRasterFileDir" ), QFileInfo( d.outputFileName() ).absolutePath() );
@@ -7205,7 +7206,7 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
72057206
if ( !pipe->set( rasterLayer->dataProvider()->clone() ) )
72067207
{
72077208
QgsDebugMsg( QStringLiteral( "Cannot set pipe provider" ) );
7208-
return;
7209+
return QString();
72097210
}
72107211

72117212
QgsRasterNuller *nuller = new QgsRasterNuller();
@@ -7216,7 +7217,7 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
72167217
if ( !pipe->insert( 1, nuller ) )
72177218
{
72187219
QgsDebugMsg( QStringLiteral( "Cannot set pipe nuller" ) );
7219-
return;
7220+
return QString();
72207221
}
72217222

72227223
// add projector if necessary
@@ -7227,7 +7228,7 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
72277228
if ( !pipe->insert( 2, projector ) )
72287229
{
72297230
QgsDebugMsg( QStringLiteral( "Cannot set pipe projector" ) );
7230-
return;
7231+
return QString();
72317232
}
72327233
}
72337234
}
@@ -7240,14 +7241,14 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
72407241
if ( !projector )
72417242
{
72427243
QgsDebugMsg( QStringLiteral( "Cannot get pipe projector" ) );
7243-
return;
7244+
return QString();
72447245
}
72457246
projector->setCrs( rasterLayer->crs(), d.outputCrs() );
72467247
}
72477248

72487249
if ( !pipe->last() )
72497250
{
7250-
return;
7251+
return QString();
72517252
}
72527253
fileWriter.setCreateOptions( d.createOptions() );
72537254

@@ -7309,26 +7310,28 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
73097310
} );
73107311

73117312
QgsApplication::taskManager()->addTask( writerTask );
7313+
return d.outputFileName();
73127314
}
73137315

73147316

7315-
void QgisApp::saveAsFile( QgsMapLayer *layer, bool onlySelected )
7317+
QString QgisApp::saveAsFile( QgsMapLayer *layer, const bool onlySelected, const bool defaultToAddToMap )
73167318
{
73177319
if ( !layer )
73187320
layer = activeLayer();
73197321

73207322
if ( !layer )
7321-
return;
7323+
return QString();
73227324

73237325
QgsMapLayer::LayerType layerType = layer->type();
73247326
if ( layerType == QgsMapLayer::RasterLayer )
73257327
{
7326-
saveAsRasterFile( qobject_cast<QgsRasterLayer *>( layer ) );
7328+
return saveAsRasterFile( qobject_cast<QgsRasterLayer *>( layer ), defaultToAddToMap );
73277329
}
73287330
else if ( layerType == QgsMapLayer::VectorLayer )
73297331
{
7330-
saveAsVectorFileGeneral( qobject_cast<QgsVectorLayer *>( layer ), true, onlySelected );
7332+
return saveAsVectorFileGeneral( qobject_cast<QgsVectorLayer *>( layer ), true, onlySelected, defaultToAddToMap );
73317333
}
7334+
return QString();
73327335
}
73337336

73347337
void QgisApp::makeMemoryLayerPermanent( QgsVectorLayer *layer )
@@ -7371,7 +7374,7 @@ void QgisApp::makeMemoryLayerPermanent( QgsVectorLayer *layer )
73717374
}
73727375
};
73737376

7374-
saveAsVectorFileGeneral( layer, true, false, onSuccess, onFailure, 0, tr( "Save Scratch Layer" ) );
7377+
saveAsVectorFileGeneral( layer, true, false, true, onSuccess, onFailure, 0, tr( "Save Scratch Layer" ) );
73757378
}
73767379

73777380
void QgisApp::saveAsLayerDefinition()
@@ -7475,15 +7478,15 @@ QgisAppFieldValueConverter *QgisAppFieldValueConverter::clone() const
74757478

74767479
///@endcond
74777480

7478-
void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOption, bool onlySelected )
7481+
QString QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOption, bool onlySelected, bool defaultToAddToMap )
74797482
{
74807483
if ( !vlayer )
74817484
{
74827485
vlayer = qobject_cast<QgsVectorLayer *>( activeLayer() ); // FIXME: output of multiple layers at once?
74837486
}
74847487

74857488
if ( !vlayer )
7486-
return;
7489+
return QString();
74877490

74887491
const QString layerId = vlayer->id();
74897492

@@ -7521,10 +7524,10 @@ void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOpt
75217524
}
75227525
};
75237526

7524-
saveAsVectorFileGeneral( vlayer, symbologyOption, onlySelected, onSuccess, onFailure );
7527+
return saveAsVectorFileGeneral( vlayer, symbologyOption, onlySelected, defaultToAddToMap, onSuccess, onFailure );
75257528
}
75267529

7527-
void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOption, bool onlySelected, const std::function<void( const QString &, bool, const QString &, const QString &, const QString & )> &onSuccess, const std::function<void ( int, const QString & )> &onFailure, int options, const QString &dialogTitle )
7530+
QString QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOption, bool onlySelected, bool defaultToAddToMap, const std::function<void( const QString &, bool, const QString &, const QString &, const QString & )> &onSuccess, const std::function<void ( int, const QString & )> &onFailure, int options, const QString &dialogTitle )
75287531
{
75297532
QgsCoordinateReferenceSystem destCRS;
75307533

@@ -7540,11 +7543,13 @@ void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOpt
75407543
dialog->setMapCanvas( mMapCanvas );
75417544
dialog->setIncludeZ( QgsWkbTypes::hasZ( vlayer->wkbType() ) );
75427545
dialog->setOnlySelected( onlySelected );
7546+
dialog->setAddToCanvas( defaultToAddToMap );
75437547

7548+
QString vectorFilename;
75447549
if ( dialog->exec() == QDialog::Accepted )
75457550
{
75467551
QString encoding = dialog->encoding();
7547-
QString vectorFilename = dialog->filename();
7552+
vectorFilename = dialog->filename();
75487553
QString format = dialog->format();
75497554
QStringList datasourceOptions = dialog->datasourceOptions();
75507555
bool autoGeometryType = dialog->automaticGeometryType();
@@ -7612,6 +7617,7 @@ void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOpt
76127617
}
76137618

76147619
delete dialog;
7620+
return vectorFilename;
76157621
}
76167622

76177623
void QgisApp::layerProperties()

src/app/qgisapp.h

+11-11
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
703703

704704
public slots:
705705
//! save current vector layer
706-
void saveAsFile( QgsMapLayer *layer = nullptr, bool onlySelected = false );
706+
QString saveAsFile( QgsMapLayer *layer = nullptr, bool onlySelected = false, bool defaultToAddToMap = true );
707707

708708
/**
709709
* Makes a memory layer permanent, by prompting users to save the layer to a disk-based (OGR)
@@ -716,7 +716,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
716716
//! save qrl definition for the current layer
717717
void saveAsLayerDefinition();
718718
//! save current raster layer
719-
void saveAsRasterFile( QgsRasterLayer *layer = nullptr );
719+
QString saveAsRasterFile( QgsRasterLayer *layer = nullptr, bool defaultAddToCanvas = true );
720720
//! Process the list of URIs that have been dropped in QGIS
721721
void handleDropUriList( const QgsMimeDataUtils::UriList &lst );
722722
//! Convenience function to open either a project or a layer file.
@@ -1841,16 +1841,16 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
18411841

18421842
void setLayoutAtlasFeature( QgsPrintLayout *layout, QgsMapLayer *layer, const QgsFeature &feat );
18431843

1844-
void saveAsVectorFileGeneral( QgsVectorLayer *vlayer = nullptr, bool symbologyOption = true, bool onlySelected = false );
1844+
QString saveAsVectorFileGeneral( QgsVectorLayer *vlayer = nullptr, bool symbologyOption = true, bool onlySelected = false, bool defaultToAddToMap = true );
18451845

1846-
void saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOption, bool onlySelected,
1847-
const std::function< void ( const QString &newFilename,
1848-
bool addToCanvas,
1849-
const QString &layerName,
1850-
const QString &encoding,
1851-
const QString &vectorFileName )> &onSuccess, const std::function< void ( int error, const QString &errorMessage ) > &onFailure,
1852-
int dialogOptions = QgsVectorLayerSaveAsDialog::AllOptions,
1853-
const QString &dialogTitle = QString() );
1846+
QString saveAsVectorFileGeneral( QgsVectorLayer *vlayer, bool symbologyOption, bool onlySelected, bool defaultToAddToMap,
1847+
const std::function< void ( const QString &newFilename,
1848+
bool addToCanvas,
1849+
const QString &layerName,
1850+
const QString &encoding,
1851+
const QString &vectorFileName )> &onSuccess, const std::function< void ( int error, const QString &errorMessage ) > &onFailure,
1852+
int dialogOptions = QgsVectorLayerSaveAsDialog::AllOptions,
1853+
const QString &dialogTitle = QString() );
18541854

18551855
//! Sets project properties, including map untis
18561856
void projectProperties( const QString &currentPage = QString() );

src/app/qgsappwindowmanager.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgsstyle.h"
1919
#include "qgisapp.h"
2020
#include "qgslayoutmanagerdialog.h"
21+
#include "qgsrasterlayer.h"
2122

2223
QgsAppWindowManager::~QgsAppWindowManager()
2324
{
@@ -46,6 +47,16 @@ QWidget *QgsAppWindowManager::openStandardDialog( QgsWindowManagerInterface::Sta
4647
return nullptr;
4748
}
4849

50+
QString QgsAppWindowManager::executeExportVectorLayerDialog( QgsVectorLayer *layer )
51+
{
52+
return QgisApp::instance()->saveAsFile( layer, false, false );
53+
}
54+
55+
QString QgsAppWindowManager::executeExportRasterLayerDialog( QgsRasterLayer *layer )
56+
{
57+
return QgisApp::instance()->saveAsFile( layer, false, false );
58+
}
59+
4960
QWidget *QgsAppWindowManager::openApplicationDialog( QgsAppWindowManager::ApplicationDialog dialog )
5061
{
5162
switch ( dialog )

src/app/qgsappwindowmanager.h

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class QgsAppWindowManager : public QgsWindowManagerInterface
4141
~QgsAppWindowManager();
4242

4343
QWidget *openStandardDialog( QgsWindowManagerInterface::StandardDialog dialog ) override;
44+
QString executeExportVectorLayerDialog( QgsVectorLayer *layer ) override;
45+
QString executeExportRasterLayerDialog( QgsRasterLayer *layer ) override;
4446

4547
/**
4648
* Opens an instance of a application QGIS dialog. Depending on the dialog,

src/gui/ogr/qgsvectorlayersaveasdialog.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,11 @@ bool QgsVectorLayerSaveAsDialog::addToCanvas() const
861861
return mAddToCanvas->isChecked();
862862
}
863863

864+
void QgsVectorLayerSaveAsDialog::setAddToCanvas( bool enabled )
865+
{
866+
mAddToCanvas->setChecked( enabled );
867+
}
868+
864869
int QgsVectorLayerSaveAsDialog::symbologyExport() const
865870
{
866871
return mSymbologyExportComboBox->currentData().toInt();

src/gui/ogr/qgsvectorlayersaveasdialog.h

+14
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,22 @@ class GUI_EXPORT QgsVectorLayerSaveAsDialog : public QDialog, private Ui::QgsVec
6565
QgsAttributeList selectedAttributes() const;
6666
//! Returns selected attributes that must be exported with their displayed values instead of their raw values. Added in QGIS 2.16
6767
QgsAttributeList attributesAsDisplayedValues() const;
68+
69+
/**
70+
* Returns true if the "add to canvas" checkbox is checked.
71+
*
72+
* \see setAddToCanvas()
73+
*/
6874
bool addToCanvas() const;
6975

76+
/**
77+
* Sets whether the "add to canvas" checkbox should be \a checked.
78+
*
79+
* \see addToCanvas()
80+
* \since QGIS 3.6
81+
*/
82+
void setAddToCanvas( bool checked );
83+
7084
/**
7185
* Returns type of symbology export.
7286
0: No symbology

0 commit comments

Comments
 (0)