mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
[FEATURE] More output format choices in raster save as dialog
Previously only geotiff format was available, even though the underlying QgsRasterFileWriter/GDAL libraries support other formats. This commit exposes those other formats to the dialog so that users can directly save rasters to them (including everyone's new BFF, geopackage).
This commit is contained in:
parent
6b23e1f299
commit
9e4518fe42
@ -165,6 +165,17 @@ class QgsRasterFileWriter
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
static QStringList extensionsForFormat( const QString &format );
|
||||
%Docstring
|
||||
Returns a list of known file extensions for the given GDAL driver ``format``.
|
||||
E.g. returns "tif", "tiff" for the format "GTiff".
|
||||
|
||||
If no matching format driver is found an empty list will be returned.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
:rtype: list of str
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
@ -6750,6 +6750,10 @@ void QgisApp::saveAsRasterFile( QgsRasterLayer *rasterLayer )
|
||||
fileWriter.setMaxTileWidth( d.maximumTileSizeX() );
|
||||
fileWriter.setMaxTileHeight( d.maximumTileSizeY() );
|
||||
}
|
||||
else
|
||||
{
|
||||
fileWriter.setOutputFormat( d.outputFormat() );
|
||||
}
|
||||
|
||||
// TODO: show error dialogs
|
||||
// TODO: this code should go somewhere else, but probably not into QgsRasterFileWriter
|
||||
|
@ -1009,3 +1009,17 @@ QString QgsRasterFileWriter::driverForExtension( const QString &extension )
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList QgsRasterFileWriter::extensionsForFormat( const QString &format )
|
||||
{
|
||||
GDALDriverH drv = GDALGetDriverByName( format.toLocal8Bit().data() );
|
||||
if ( drv )
|
||||
{
|
||||
char **driverMetadata = GDALGetMetadata( drv, nullptr );
|
||||
if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, false ) && CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, false ) )
|
||||
{
|
||||
return QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS, nullptr ) ).split( ' ' );
|
||||
}
|
||||
}
|
||||
return QStringList();
|
||||
}
|
||||
|
@ -142,6 +142,16 @@ class CORE_EXPORT QgsRasterFileWriter
|
||||
*/
|
||||
static QString driverForExtension( const QString &extension );
|
||||
|
||||
/**
|
||||
* Returns a list of known file extensions for the given GDAL driver \a format.
|
||||
* E.g. returns "tif", "tiff" for the format "GTiff".
|
||||
*
|
||||
* If no matching format driver is found an empty list will be returned.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
static QStringList extensionsForFormat( const QString &format );
|
||||
|
||||
private:
|
||||
QgsRasterFileWriter(); //forbidden
|
||||
WriterError writeDataRaster( const QgsRasterPipe *pipe, QgsRasterIterator *iter, int nCols, int nRows, const QgsRectangle &outputExtent,
|
||||
|
@ -23,7 +23,8 @@
|
||||
#include "qgsrastertransparency.h"
|
||||
#include "qgsprojectionselectiondialog.h"
|
||||
#include "qgssettings.h"
|
||||
|
||||
#include "qgsrasterfilewriter.h"
|
||||
#include "cpl_string.h"
|
||||
#include <gdal.h>
|
||||
|
||||
#include <QFileDialog>
|
||||
@ -74,13 +75,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer *rasterLa
|
||||
|
||||
toggleResolutionSize();
|
||||
|
||||
//only one hardcoded format at the moment
|
||||
QStringList myFormats;
|
||||
myFormats << QStringLiteral( "GTiff" );
|
||||
Q_FOREACH ( const QString &myFormat, myFormats )
|
||||
{
|
||||
mFormatComboBox->addItem( myFormat );
|
||||
}
|
||||
insertAvailableOutputFormats();
|
||||
|
||||
//fill reasonable default values depending on the provider
|
||||
if ( mDataProvider )
|
||||
@ -104,7 +99,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer *rasterLa
|
||||
mCreateOptionsWidget->setProvider( mDataProvider->name() );
|
||||
if ( mDataProvider->name() == QLatin1String( "gdal" ) )
|
||||
{
|
||||
mCreateOptionsWidget->setFormat( myFormats[0] );
|
||||
mCreateOptionsWidget->setFormat( mFormatComboBox->currentData().toString() );
|
||||
}
|
||||
mCreateOptionsWidget->setRasterLayer( mRasterLayer );
|
||||
mCreateOptionsWidget->update();
|
||||
@ -165,6 +160,68 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer *rasterLa
|
||||
recalcResolutionSize();
|
||||
}
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::insertAvailableOutputFormats()
|
||||
{
|
||||
GDALAllRegister();
|
||||
|
||||
int nDrivers = GDALGetDriverCount();
|
||||
QMap< int, QPair< QString, QString > > topPriorityDrivers;
|
||||
QMap< QString, QString > lowPriorityDrivers;
|
||||
|
||||
for ( int i = 0; i < nDrivers; ++i )
|
||||
{
|
||||
GDALDriverH driver = GDALGetDriver( i );
|
||||
if ( driver )
|
||||
{
|
||||
char **driverMetadata = GDALGetMetadata( driver, nullptr );
|
||||
|
||||
if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, false ) && CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, false ) )
|
||||
{
|
||||
QString driverShortName = GDALGetDriverShortName( driver );
|
||||
QString driverLongName = GDALGetDriverLongName( driver );
|
||||
if ( driverShortName == QLatin1String( "MEM" ) )
|
||||
{
|
||||
// in memory rasters are not (yet) supported because the GDAL dataset handle
|
||||
// would need to be passed directly to QgsRasterLayer (it is not possible to
|
||||
// close it in raster calculator and reopen the dataset again in raster layer)
|
||||
continue;
|
||||
}
|
||||
else if ( driverShortName == QLatin1String( "VRT" ) )
|
||||
{
|
||||
// skip GDAL vrt driver, since we handle that format manually
|
||||
continue;
|
||||
}
|
||||
else if ( driverShortName == QStringLiteral( "GTiff" ) )
|
||||
{
|
||||
// always list geotiff first
|
||||
topPriorityDrivers.insert( 1, qMakePair( driverLongName, driverShortName ) );
|
||||
}
|
||||
else if ( driverShortName == QStringLiteral( "GPKG" ) )
|
||||
{
|
||||
// and gpkg second
|
||||
topPriorityDrivers.insert( 2, qMakePair( driverLongName, driverShortName ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
lowPriorityDrivers.insert( driverLongName, driverShortName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// will be sorted by priority, so that geotiff and geopackage are listed first
|
||||
for ( auto priorityDriversIt = topPriorityDrivers.constBegin(); priorityDriversIt != topPriorityDrivers.constEnd(); ++priorityDriversIt )
|
||||
{
|
||||
mFormatComboBox->addItem( priorityDriversIt.value().first, priorityDriversIt.value().second );
|
||||
}
|
||||
// will be sorted by driver name
|
||||
for ( auto lowPriorityDriversIt = lowPriorityDrivers.constBegin(); lowPriorityDriversIt != lowPriorityDrivers.constEnd(); ++lowPriorityDriversIt )
|
||||
{
|
||||
mFormatComboBox->addItem( lowPriorityDriversIt.key(), lowPriorityDriversIt.value() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::setValidators()
|
||||
{
|
||||
mXResolutionLineEdit->setValidator( new QDoubleValidator( this ) );
|
||||
@ -212,12 +269,26 @@ void QgsRasterLayerSaveAsDialog::mBrowseButton_clicked()
|
||||
}
|
||||
else
|
||||
{
|
||||
fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), dirName, tr( "GeoTIFF" ) + " (*.tif *.tiff *.TIF *.TIFF)" );
|
||||
QStringList extensions = QgsRasterFileWriter::extensionsForFormat( outputFormat() );
|
||||
QString filter;
|
||||
QString defaultExt;
|
||||
if ( extensions.empty() )
|
||||
filter = tr( "All files (*.*)" );
|
||||
else
|
||||
{
|
||||
filter = QStringLiteral( "%1 (*.%2);;%3" ).arg( mFormatComboBox->currentText(),
|
||||
extensions.join( QStringLiteral( " *." ) ),
|
||||
tr( "All files (*.*)" ) );
|
||||
defaultExt = extensions.at( 0 );
|
||||
}
|
||||
|
||||
fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), dirName, filter );
|
||||
|
||||
// ensure the user never omits the extension from the file name
|
||||
if ( !fileName.isEmpty() && !fileName.endsWith( QLatin1String( ".tif" ), Qt::CaseInsensitive ) && !fileName.endsWith( QLatin1String( ".tiff" ), Qt::CaseInsensitive ) )
|
||||
QFileInfo fi( fileName );
|
||||
if ( !fileName.isEmpty() && fi.suffix().isEmpty() )
|
||||
{
|
||||
fileName += QLatin1String( ".tif" );
|
||||
fileName += '.' + defaultExt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,12 +310,12 @@ void QgsRasterLayerSaveAsDialog::mSaveAsLineEdit_textChanged( const QString &tex
|
||||
}
|
||||
|
||||
|
||||
void QgsRasterLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( const QString &text )
|
||||
void QgsRasterLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( const QString & )
|
||||
{
|
||||
//gdal-specific
|
||||
if ( mDataProvider && mDataProvider->name() == QLatin1String( "gdal" ) )
|
||||
{
|
||||
mCreateOptionsWidget->setFormat( text );
|
||||
mCreateOptionsWidget->setFormat( outputFormat() );
|
||||
mCreateOptionsWidget->update();
|
||||
}
|
||||
}
|
||||
@ -296,7 +367,7 @@ QString QgsRasterLayerSaveAsDialog::outputFileName() const
|
||||
|
||||
QString QgsRasterLayerSaveAsDialog::outputFormat() const
|
||||
{
|
||||
return mFormatComboBox->currentText();
|
||||
return mFormatComboBox->currentData().toString();
|
||||
}
|
||||
|
||||
QStringList QgsRasterLayerSaveAsDialog::createOptions() const
|
||||
|
@ -139,6 +139,7 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
|
||||
void adjustNoDataCellWidth( int row, int column );
|
||||
bool validate() const;
|
||||
|
||||
void insertAvailableOutputFormats();
|
||||
};
|
||||
|
||||
|
||||
|
@ -109,6 +109,11 @@ class TestQgsRasterFileWriter(unittest.TestCase):
|
||||
self.assertEqual(QgsRasterFileWriter.driverForExtension('not a format'), '')
|
||||
self.assertEqual(QgsRasterFileWriter.driverForExtension(''), '')
|
||||
|
||||
def testExtensionsForFormat(self):
|
||||
self.assertCountEqual(QgsRasterFileWriter.extensionsForFormat('not format'), [])
|
||||
self.assertCountEqual(QgsRasterFileWriter.extensionsForFormat('GTiff'), ['tiff', 'tif'])
|
||||
self.assertCountEqual(QgsRasterFileWriter.extensionsForFormat('GPKG'), ['gpkg'])
|
||||
|
||||
def testImportIntoGpkg(self):
|
||||
# init target file
|
||||
test_gpkg = tempfile.mktemp(suffix='.gpkg', dir=self.testDataDir)
|
||||
|
Loading…
x
Reference in New Issue
Block a user