Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #7879 from borysiasty/append_raster_to_geopackage
Append raster layer to an existing GeoPackage
  • Loading branch information
borysiasty committed Sep 14, 2018
2 parents ec2ddb4 + daf7f3e commit 4ac834d
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 9 deletions.
8 changes: 8 additions & 0 deletions python/gui/auto_generated/qgsrasterlayersaveasdialog.sip.in
Expand Up @@ -54,6 +54,13 @@ Constructor for QgsRasterLayerSaveAsDialog
bool tileMode() const;
bool addToCanvas() const;
QString outputFileName() const;

QString outputLayerName() const;
%Docstring
Name of the output layer within GeoPackage file

.. versionadded:: 3.4
%End
QString outputFormat() const;
QgsCoordinateReferenceSystem outputCrs();
QStringList createOptions() const;
Expand All @@ -72,6 +79,7 @@ Constructor for QgsRasterLayerSaveAsDialog
public slots:
virtual void accept();


};


Expand Down
26 changes: 23 additions & 3 deletions src/app/qgisapp.cpp
Expand Up @@ -7156,13 +7156,16 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
bool tileMode = d.tileMode();
bool addToCanvas = d.addToCanvas();
QPointer< QgsRasterLayer > rlWeakPointer( rasterLayer );
QString outputLayerName = d.outputLayerName();
QString outputFormat = d.outputFormat();

QgsRasterFileWriterTask *writerTask = new QgsRasterFileWriterTask( fileWriter, pipe.release(), d.nColumns(), d.nRows(),
d.outputRectangle(), d.outputCrs() );

// when writer is successful:

connect( writerTask, &QgsRasterFileWriterTask::writeComplete, this, [this, tileMode, addToCanvas, rlWeakPointer ]( const QString & newFilename )
connect( writerTask, &QgsRasterFileWriterTask::writeComplete, this,
[this, tileMode, addToCanvas, rlWeakPointer, outputLayerName, outputFormat]( const QString & newFilename )
{
QString fileName = newFilename;
if ( tileMode )
Expand All @@ -7173,7 +7176,14 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )

if ( addToCanvas )
{
addRasterLayers( QStringList( fileName ) );
if ( outputFormat == QLatin1String( "GPKG" ) && !outputLayerName.isEmpty() )
{
addRasterLayers( QStringList( QStringLiteral( "GPKG:%1:%2" ).arg( fileName, outputLayerName ) ) );
}
else
{
addRasterLayers( QStringList( fileName ) );
}
}
if ( rlWeakPointer )
emit layerSavedAs( rlWeakPointer, fileName );
Expand Down Expand Up @@ -12813,8 +12823,18 @@ bool QgisApp::addRasterLayers( QStringList const &fileNameQStringList, bool guiW
{
QFileInfo myFileInfo( *myIterator );

// set the layer name to the file base name...
QString layerName = myFileInfo.completeBaseName();

// ...unless provided explicitly
const QVariantMap uriDetails = QgsProviderRegistry::instance()->decodeUri( QStringLiteral( "gdal" ), *myIterator );
if ( !uriDetails[ QStringLiteral( "layerName" ) ].toString().isEmpty() )
{
layerName = uriDetails[ QStringLiteral( "layerName" ) ].toString();
}

// try to create the layer
QgsRasterLayer *layer = addRasterLayerPrivate( *myIterator, myFileInfo.completeBaseName(),
QgsRasterLayer *layer = addRasterLayerPrivate( *myIterator, layerName,
QString(), guiWarning, true );
if ( layer && layer->isValid() )
{
Expand Down
99 changes: 98 additions & 1 deletion src/gui/qgsrasterlayersaveasdialog.cpp
Expand Up @@ -179,6 +179,12 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer *rasterLa
QFileInfo tmplFileInfo( filePath );
settings.setValue( QStringLiteral( "UI/lastRasterFileDir" ), tmplFileInfo.absolutePath() );

if ( !filePath.isEmpty() && mLayerName->isEnabled() )
{
QFileInfo fileInfo( filePath );
mLayerName->setText( fileInfo.baseName() );
}

if ( mTileModeCheckBox->isChecked() )
{
QString fileName = filePath;
Expand Down Expand Up @@ -314,6 +320,21 @@ void QgsRasterLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( const QStr
tr( "All files (*.*)" ) );
}
mFilename->setFilter( filter );

// Disable mTileModeCheckBox for GeoPackages
mTileModeCheckBox->setEnabled( outputFormat() != QStringLiteral( "GPKG" ) );
mFilename->setConfirmOverwrite( outputFormat() != QStringLiteral( "GPKG" ) );
mLayerName->setEnabled( outputFormat() == QStringLiteral( "GPKG" ) );
if ( mLayerName->isEnabled() )
{
QString layerName = QFileInfo( mFilename->filePath() ).baseName();
mLayerName->setText( layerName );
mTileModeCheckBox->setChecked( false );
}
else
{
mLayerName->setText( QString() );
}
}

int QgsRasterLayerSaveAsDialog::nColumns() const
Expand Down Expand Up @@ -380,14 +401,55 @@ QString QgsRasterLayerSaveAsDialog::outputFileName() const
return fileName;
}

QString QgsRasterLayerSaveAsDialog::outputLayerName() const
{
if ( mLayerName->text().isEmpty() && outputFormat() == QStringLiteral( "GPKG" ) && !mTileModeCheckBox->isChecked() )
{
// Always return layer name for GeoPackages
return QFileInfo( mFilename->filePath() ).baseName();
}
else
{
return mLayerName->text();
}
}

QString QgsRasterLayerSaveAsDialog::outputFormat() const
{
return mFormatComboBox->currentData().toString();
}

QStringList QgsRasterLayerSaveAsDialog::createOptions() const
{
return mCreateOptionsGroupBox->isChecked() ? mCreateOptionsWidget->options() : QStringList();
QStringList options = mCreateOptionsGroupBox->isChecked() ? mCreateOptionsWidget->options() : QStringList();
if ( outputFormat() == QStringLiteral( "GPKG" ) )
{
// Overwrite the GPKG table options
int indx = options.indexOf( QRegularExpression( "^RASTER_TABLE=.*", QRegularExpression::CaseInsensitiveOption | QRegularExpression::MultilineOption ) );
if ( indx > -1 )
{
options.replace( indx, QStringLiteral( "RASTER_TABLE=%1" ).arg( outputLayerName() ) );
}
else
{
options.append( QStringLiteral( "RASTER_TABLE=%1" ).arg( outputLayerName() ) );
}

// Only enable the append mode if the layer doesn't exist yet. For existing layers a 'confirm overwrite' dialog will be shown.
if ( !outputLayerExists() )
{
indx = options.indexOf( QRegularExpression( "^APPEND_SUBDATASET=.*", QRegularExpression::CaseInsensitiveOption | QRegularExpression::MultilineOption ) );
if ( indx > -1 )
{
options.replace( indx, QStringLiteral( "APPEND_SUBDATASET=YES" ) );
}
else
{
options.append( QStringLiteral( "APPEND_SUBDATASET=YES" ) );
}
}
}
return options;
}

QgsRectangle QgsRasterLayerSaveAsDialog::outputRectangle() const
Expand Down Expand Up @@ -845,6 +907,41 @@ bool QgsRasterLayerSaveAsDialog::validate() const
return true;
}

bool QgsRasterLayerSaveAsDialog::outputLayerExists() const
{
QString uri;
if ( outputFormat() == QStringLiteral( "GPKG" ) )
{
uri = QStringLiteral( "GPKG:%1:%2" ).arg( outputFileName(), outputLayerName() );
}
else
{
uri = outputFileName();
}

std::unique_ptr< QgsRasterLayer > layer( new QgsRasterLayer( uri, "", QStringLiteral( "gdal" ) ) );
return layer->isValid();
}

void QgsRasterLayerSaveAsDialog::accept()
{
if ( !validate() )
{
return;
}

if ( outputFormat() == QStringLiteral( "GPKG" ) && outputLayerExists() &&
QMessageBox::warning( this, tr( "Save Raster Layer" ),
tr( "The layer %1 already exists in the target file, and overwriting layers in GeoPackage is not supported. "
"Do you want to overwrite the whole file?" ).arg( outputLayerName() ),
QMessageBox::Yes | QMessageBox::No ) == QMessageBox::No )
{
return;
}

QDialog::accept();
}

void QgsRasterLayerSaveAsDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "managing_data_source/create_layers.html#save-layer-from-an-existing-file" ) );
Expand Down
10 changes: 9 additions & 1 deletion src/gui/qgsrasterlayersaveasdialog.h
Expand Up @@ -71,6 +71,12 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
bool tileMode() const;
bool addToCanvas() const;
QString outputFileName() const;

/**
* Name of the output layer within GeoPackage file
* \since QGIS 3.4
*/
QString outputLayerName() const;
QString outputFormat() const;
QgsCoordinateReferenceSystem outputCrs();
QStringList createOptions() const;
Expand All @@ -87,7 +93,7 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
void hideOutput();

public slots:
void accept() override { if ( validate() ) QDialog::accept(); }
void accept() override;

private slots:
void mRawModeRadioButton_toggled( bool );
Expand Down Expand Up @@ -138,6 +144,8 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
double noDataCellValue( int row, int column ) const;
void adjustNoDataCellWidth( int row, int column );
bool validate() const;
// Returns true if the output layer already exists.
bool outputLayerExists() const;

void insertAvailableOutputFormats();
};
Expand Down
19 changes: 15 additions & 4 deletions src/ui/qgsrasterlayersaveasdialogbase.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>575</width>
<height>580</height>
<height>610</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -86,7 +86,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QgsProjectionSelectionWidget" name="mCrsSelector" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
Expand Down Expand Up @@ -118,7 +118,7 @@ datasets with maximum width and height specified below.</string>
</item>
</layout>
</item>
<item row="3" column="0">
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
Expand Down Expand Up @@ -147,7 +147,7 @@ datasets with maximum width and height specified below.</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="mAddToCanvas">
<property name="text">
<string>Add saved file to map</string>
Expand All @@ -157,6 +157,16 @@ datasets with maximum width and height specified below.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Layer name</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="mLayerName"/>
</item>
</layout>
</item>
<item>
Expand Down Expand Up @@ -716,6 +726,7 @@ datasets with maximum width and height specified below.</string>
<tabstop>mFormatComboBox</tabstop>
<tabstop>mTileModeCheckBox</tabstop>
<tabstop>mFilename</tabstop>
<tabstop>mLayerName</tabstop>
<tabstop>mCrsSelector</tabstop>
<tabstop>mAddToCanvas</tabstop>
<tabstop>mScrollArea</tabstop>
Expand Down

0 comments on commit 4ac834d

Please sign in to comment.