273 changes: 157 additions & 116 deletions src/core/raster/qgsrasterfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
#include <QMessageBox>

QgsRasterFileWriter::QgsRasterFileWriter( const QString& outputUrl ):
mOutputUrl( outputUrl ), mOutputProviderKey( "gdal" ), mOutputFormat( "GTiff" ),
mMode( Raw ), mOutputUrl( outputUrl ), mOutputProviderKey( "gdal" ), mOutputFormat( "GTiff" ),
mTiledMode( false ), mMaxTileWidth( 500 ), mMaxTileHeight( 500 ),
mBuildPyramidsFlag( QgsRasterDataProvider::PyramidsFlagNo ),
mPyramidsFormat( QgsRasterDataProvider::PyramidsGTiff ),
mProgressDialog( 0 )
mProgressDialog( 0 ), mPipe( 0 ), mInput( 0 )
{

}
Expand All @@ -57,13 +57,24 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( const QgsRast
{
return SourceProviderError;
}
mPipe = pipe;

//const QgsRasterInterface* iface = iter->input();
const QgsRasterInterface* iface = pipe->last();
if ( !iface )
{
return SourceProviderError;
}
mInput = iface;

if ( QgsRasterBlock::typeIsColor( iface->dataType( 1 ) ) )
{
mMode = Image;
}
else
{
mMode = Raw;
}

QgsDebugMsg( QString( "reading from %1" ).arg( typeid( *iface ).name() ) );

Expand All @@ -78,8 +89,22 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( const QgsRast

QgsRasterIterator iter( pipe->last() );

if ( iface->dataType( 1 ) == QGis::ARGB32 ||
iface->dataType( 1 ) == QGis::ARGB32_Premultiplied )
//create directory for output files
if ( mTiledMode )
{
QFileInfo fileInfo( mOutputUrl );
if ( !fileInfo.exists() )
{
QDir dir = fileInfo.dir();
if ( !dir.mkdir( fileInfo.fileName() ) )
{
QgsDebugMsg( "Cannot create output VRT directory " + fileInfo.fileName() + " in " + dir.absolutePath() );
return CreateDatasourceError;
}
}
}

if ( mMode == Image )
{
WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent, crs, progressDialog );
mProgressDialog = 0;
Expand Down Expand Up @@ -118,13 +143,6 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
return SourceProviderError;
}

//create directory for output files
QDir destDir( mOutputUrl );
if ( mTiledMode )
{
destDir.mkdir( mOutputUrl );
}

iter->setMaximumTileWidth( mMaxTileWidth );
iter->setMaximumTileHeight( mMaxTileHeight );

Expand All @@ -134,11 +152,6 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
return SourceProviderError;
}

//create destProvider for whole dataset here
QgsRasterDataProvider* destProvider = 0;
double pixelSize;
double geoTransform[6];
globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );

//check if all the bands have the same data type size, otherwise we cannot write it to the provider
//(at least not with the current interface)
Expand Down Expand Up @@ -238,15 +251,30 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
}
}

destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType );
//create destProvider for whole dataset here
QgsRasterDataProvider* destProvider = 0;
double pixelSize;
double geoTransform[6];
globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );

// initOutput() returns 0 in tile mode!
destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList );

WriterError error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );

if ( error == NoDataConflict )
{
// The value used for no data was found in source data, we must use wider data type
destProvider->remove();
delete destProvider;
if ( destProvider ) // no tiles
{
destProvider->remove();
delete destProvider;
destProvider = 0;
}
else // VRT
{
// TODO: remove created VRT
}

// But we don't know which band -> wider all
for ( int i = 0; i < nBands; i++ )
Expand All @@ -259,9 +287,10 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
destDataType = destDataTypeList.value( 0 );

// Try again
destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType );
destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType , destHasNoDataValueList, destNoDataValueList );
error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );
}
if ( destProvider ) delete destProvider;

return error;
}
Expand All @@ -285,6 +314,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
const QgsRasterInterface* iface = iter->input();
const QgsRasterDataProvider* srcProvider = dynamic_cast<const QgsRasterDataProvider*>( iface->srcInput() );
int nBands = iface->bandCount();
QgsDebugMsg( QString( "nBands = %1" ).arg( nBands ) );

//Get output map units per pixel
int iterLeft = 0;
Expand All @@ -299,8 +329,10 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
// TODO: no need to alloc memory, change to readBlock() returning the allocated block
//blockList.push_back( QgsMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
blockList.push_back( 0 );
// TODO - fix segfault here when using tiles+vrt (reported by Etienne)
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
if ( destProvider ) // no tiles
{
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
}
}

int nParts = 0;
Expand All @@ -323,18 +355,24 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
{
if ( !iter->readNextRasterPart( i, iterCols, iterRows, &( blockList[i - 1] ), iterLeft, iterTop ) )
{
delete destProvider;
// No more parts, create VRT and return
//delete destProvider;
if ( mTiledMode )
{
QFileInfo outputInfo( mOutputUrl );
QString vrtFilePath( mOutputUrl + "/" + outputInfo.baseName() + ".vrt" );
writeVRT( vrtFilePath );
buildPyramids( vrtFilePath );
if ( mBuildPyramidsFlag == QgsRasterDataProvider::PyramidsFlagYes )
{
buildPyramids( vrtFilePath );
}
}
else
{
if ( mBuildPyramidsFlag == QgsRasterDataProvider::PyramidsFlagYes )
{
buildPyramids( mOutputUrl );
}
}

QgsDebugMsg( "Done" );
Expand Down Expand Up @@ -369,9 +407,6 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
else
{
// TODO: this conversion should go to QgsRasterDataProvider::write with additional input data type param
//void *destData = QgsRasterBlock::convert( blockList[i-1], srcProvider->dataType( i ), destDataType, iterCols * iterRows );
//destBlockList.push_back( destData );
//QgsFree( blockList[i-1] );
blockList[i-1]->convert( destDataType );
destBlockList.push_back( blockList[i-1] );
}
Expand All @@ -380,17 +415,21 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(

if ( mTiledMode ) //write to file
{
delete destProvider;
destProvider = createPartProvider( outputExtent, nCols, iterCols, iterRows,
iterLeft, iterTop, mOutputUrl, fileIndex, nBands, destDataType, crs );
//delete destProvider;
QgsRasterDataProvider* partDestProvider = createPartProvider( outputExtent,
nCols, iterCols, iterRows,
iterLeft, iterTop, mOutputUrl,
fileIndex, nBands, destDataType, crs );

//write data to output file. todo: loop over the data list
for ( int i = 1; i <= nBands; ++i )
{
destProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 );
partDestProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
partDestProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 );
delete destBlockList[i - 1];
addToVRT( QString::number( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
}
delete partDestProvider;
}
else
{
Expand Down Expand Up @@ -425,13 +464,6 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
return SourceProviderError;
}

//create directory for output files
QDir destDir( mOutputUrl );
if ( mTiledMode )
{
destDir.mkdir( mOutputUrl );
}

iter->setMaximumTileWidth( mMaxTileWidth );
iter->setMaximumTileHeight( mMaxTileHeight );

Expand Down Expand Up @@ -518,20 +550,23 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
//create output file
if ( mTiledMode )
{
delete destProvider;
destProvider = createPartProvider( outputExtent, nCols, iterCols, iterRows,
iterLeft, iterTop, mOutputUrl, fileIndex, 4, QGis::Byte, crs );
//delete destProvider;
QgsRasterDataProvider* partDestProvider = createPartProvider( outputExtent,
nCols, iterCols, iterRows,
iterLeft, iterTop, mOutputUrl, fileIndex,
4, QGis::Byte, crs );

//write data to output file
destProvider->write( redData, 1, iterCols, iterRows, 0, 0 );
destProvider->write( greenData, 2, iterCols, iterRows, 0, 0 );
destProvider->write( blueData, 3, iterCols, iterRows, 0, 0 );
destProvider->write( alphaData, 4, iterCols, iterRows, 0, 0 );

addToVRT( QString::number( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
addToVRT( QString::number( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
addToVRT( QString::number( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
addToVRT( QString::number( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
partDestProvider->write( redData, 1, iterCols, iterRows, 0, 0 );
partDestProvider->write( greenData, 2, iterCols, iterRows, 0, 0 );
partDestProvider->write( blueData, 3, iterCols, iterRows, 0, 0 );
partDestProvider->write( alphaData, 4, iterCols, iterRows, 0, 0 );

addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
delete partDestProvider;
}
else
{
Expand All @@ -544,7 +579,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
++fileIndex;
}

delete destProvider;
if ( destProvider ) delete destProvider;
QgsFree( redData ); QgsFree( greenData ); QgsFree( blueData ); QgsFree( alphaData );

if ( progressDialog )
Expand All @@ -557,37 +592,24 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
QFileInfo outputInfo( mOutputUrl );
QString vrtFilePath( mOutputUrl + "/" + outputInfo.baseName() + ".vrt" );
writeVRT( vrtFilePath );
buildPyramids( vrtFilePath );
if ( mBuildPyramidsFlag == QgsRasterDataProvider::PyramidsFlagYes )
{
buildPyramids( vrtFilePath );
}
}
else
{
if ( mBuildPyramidsFlag == QgsRasterDataProvider::PyramidsFlagYes )
{
buildPyramids( mOutputUrl );
}
}
return NoError;
}

void QgsRasterFileWriter::addToVRT( const QString& filename, int band, int xSize, int ySize, int xOffset, int yOffset )
{
QDomElement bandElem;

switch ( band )
{
case 1:
bandElem = mVRTRedBand;
break;
case 2:
bandElem = mVRTGreenBand;
break;
case 3:
bandElem = mVRTBlueBand;
break;
case 4:
bandElem = mVRTAlphaBand;
break;
default:
return;
}
QDomElement bandElem = mVRTBands.value( band - 1 );

QDomElement simpleSourceElem = mVRTDocument.createElement( "SimpleSource" );

Expand Down Expand Up @@ -665,6 +687,7 @@ void QgsRasterFileWriter::buildPyramids( const QString& filename )

void QgsRasterFileWriter::buildPyramids( const QString& filename )
{
QgsDebugMsg( "filename = " + filename );
// open new dataProvider so we can build pyramids with it
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, filename );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, filename );
Expand Down Expand Up @@ -722,6 +745,7 @@ void QgsRasterFileWriter::buildPyramids( const QString& filename )
QMessageBox::warning( 0, title, message );
QgsDebugMsg( res + " - " + message );
}
delete destProvider;
}

#if 0
Expand All @@ -744,7 +768,7 @@ int QgsRasterFileWriter::pyramidsProgress( double dfComplete, const char *pszMes
}
#endif

void QgsRasterFileWriter::createVRT( int xSize, int ySize, const QgsCoordinateReferenceSystem& crs, double* geoTransform )
void QgsRasterFileWriter::createVRT( int xSize, int ySize, const QgsCoordinateReferenceSystem& crs, double* geoTransform, QGis::DataType type, QList<bool> destHasNoDataValueList, QList<double> destNoDataValueList )
{
mVRTDocument.clear();
QDomElement VRTDatasetElem = mVRTDocument.createElement( "VRTDataset" );
Expand All @@ -771,43 +795,56 @@ void QgsRasterFileWriter::createVRT( int xSize, int ySize, const QgsCoordinateRe
VRTDatasetElem.appendChild( geoTransformElem );
}

//VRT rasterbands
mVRTRedBand = mVRTDocument.createElement( "VRTRasterBand" );
mVRTRedBand.setAttribute( "dataType", "Byte" );
mVRTRedBand.setAttribute( "band", "1" );
QDomElement colorInterpRedElement = mVRTDocument.createElement( "ColorInterp" );
QDomText redInterprText = mVRTDocument.createTextNode( "Red" );
colorInterpRedElement.appendChild( redInterprText );
mVRTRedBand.appendChild( colorInterpRedElement );

mVRTGreenBand = mVRTDocument.createElement( "VRTRasterBand" );
mVRTGreenBand.setAttribute( "dataType", "Byte" );
mVRTGreenBand.setAttribute( "band", "2" );
QDomElement colorInterpGreenElement = mVRTDocument.createElement( "ColorInterp" );
QDomText greenInterprText = mVRTDocument.createTextNode( "Green" );
colorInterpGreenElement.appendChild( greenInterprText );
mVRTGreenBand.appendChild( colorInterpGreenElement );

mVRTBlueBand = mVRTDocument.createElement( "VRTRasterBand" );
mVRTBlueBand.setAttribute( "dataType", "Byte" );
mVRTBlueBand.setAttribute( "band", "3" );
QDomElement colorInterpBlueElement = mVRTDocument.createElement( "ColorInterp" );
QDomText blueInterprText = mVRTDocument.createTextNode( "Blue" );
colorInterpBlueElement.appendChild( blueInterprText );
mVRTBlueBand.appendChild( colorInterpBlueElement );

mVRTAlphaBand = mVRTDocument.createElement( "VRTRasterBand" );
mVRTAlphaBand.setAttribute( "dataType", "Byte" );
mVRTAlphaBand.setAttribute( "band", "4" );
QDomElement colorInterpAlphaElement = mVRTDocument.createElement( "ColorInterp" );
QDomText alphaInterprText = mVRTDocument.createTextNode( "Alpha" );
colorInterpAlphaElement.appendChild( alphaInterprText );
mVRTAlphaBand.appendChild( colorInterpAlphaElement );

VRTDatasetElem.appendChild( mVRTRedBand );
VRTDatasetElem.appendChild( mVRTGreenBand );
VRTDatasetElem.appendChild( mVRTBlueBand );
VRTDatasetElem.appendChild( mVRTAlphaBand );
int nBands;
if ( mMode == Raw )
{
nBands = mInput->bandCount();
}
else
{
nBands = 4;
}

QStringList colorInterp;
colorInterp << "Red" << "Green" << "Blue" << "Alpha";

QMap<QGis::DataType, QString> dataTypes;
dataTypes.insert( QGis::Byte, "Byte" );
dataTypes.insert( QGis::UInt16, "UInt16" );
dataTypes.insert( QGis::Int16, "Int16" );
dataTypes.insert( QGis::UInt32, "Int32" );
dataTypes.insert( QGis::Float32, "Float32" );
dataTypes.insert( QGis::Float64, "Float64" );
dataTypes.insert( QGis::CInt16, "CInt16" );
dataTypes.insert( QGis::CInt32, "CInt32" );
dataTypes.insert( QGis::CFloat32, "CFloat32" );
dataTypes.insert( QGis::CFloat64, "CFloat64" );

for ( int i = 1; i <= nBands; i++ )
{
QDomElement VRTBand = mVRTDocument.createElement( "VRTRasterBand" );

VRTBand.setAttribute( "band", QString::number( i ) );
QString dataType = dataTypes.value( type );
VRTBand.setAttribute( "dataType", dataType );

if ( mMode == Image )
{
VRTBand.setAttribute( "dataType", "Byte" );
QDomElement colorInterpElement = mVRTDocument.createElement( "ColorInterp" );
QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
colorInterpElement.appendChild( interpText );
VRTBand.appendChild( colorInterpElement );
}

if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
{
VRTBand.setAttribute( "NoDataValue", QString::number( destNoDataValueList.value( i - 1 ) ) );
}

mVRTBands.append( VRTBand );
VRTDatasetElem.appendChild( VRTBand );
}
}

bool QgsRasterFileWriter::writeVRT( const QString& file )
Expand All @@ -834,7 +871,7 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang
double mapBottom = mapTop - iterRows * mup;
QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );

QString outputFile = outputUrl + "/" + QString::number( fileIndex );
QString outputFile = outputUrl + "/" + partFileName( fileIndex );
//QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, outputFile );
QgsRasterDataProvider* destProvider = ( QgsRasterDataProvider* ) QgsProviderRegistry::instance()->provider( mOutputProviderKey, outputFile );
if ( !destProvider )
Expand Down Expand Up @@ -862,11 +899,12 @@ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider( const QgsRectang
}

QgsRasterDataProvider* QgsRasterFileWriter::initOutput( int nCols, int nRows, const QgsCoordinateReferenceSystem& crs,
double* geoTransform, int nBands, QGis::DataType type )
double* geoTransform, int nBands, QGis::DataType type,
QList<bool> destHasNoDataValueList, QList<double> destNoDataValueList )
{
if ( mTiledMode )
{
createVRT( nCols, nRows, crs, geoTransform );
createVRT( nCols, nRows, crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
return 0;
}
else
Expand Down Expand Up @@ -911,6 +949,9 @@ void QgsRasterFileWriter::globalOutputParameters( const QgsRectangle& extent, in
geoTransform[5] = -( extent.height() / nRows );
}




QString QgsRasterFileWriter::partFileName( int fileIndex )
{
// .tif for now
QFileInfo outputInfo( mOutputUrl );
return QString( "%1.%2.tif" ).arg( outputInfo.baseName() ).arg( fileIndex );
}
24 changes: 17 additions & 7 deletions src/core/raster/qgsrasterfilewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class QgsRasterIterator;
class CORE_EXPORT QgsRasterFileWriter
{
public:
enum Mode
{
Raw = 0, // Raw data
Image = 1 // Rendered image
};
enum WriterError
{
NoError = 0,
Expand Down Expand Up @@ -109,7 +114,7 @@ class CORE_EXPORT QgsRasterFileWriter
const QgsCoordinateReferenceSystem& crs, QProgressDialog* progressDialog = 0 );

//initialize vrt member variables
void createVRT( int xSize, int ySize, const QgsCoordinateReferenceSystem& crs, double* geoTransform );
void createVRT( int xSize, int ySize, const QgsCoordinateReferenceSystem& crs, double* geoTransform, QGis::DataType type, QList<bool> destHasNoDataValueList, QList<double> destNoDataValueList );
//write vrt document to disk
bool writeVRT( const QString& file );
//add file entry to vrt
Expand All @@ -125,12 +130,17 @@ class CORE_EXPORT QgsRasterFileWriter
const QgsCoordinateReferenceSystem& crs );

/**Init VRT (for tiled mode) or create global output provider (single-file mode)*/
QgsRasterDataProvider* initOutput( int nCols, int nRows, const QgsCoordinateReferenceSystem& crs, double* geoTransform, int nBands,
QGis::DataType type );
QgsRasterDataProvider* initOutput( int nCols, int nRows,
const QgsCoordinateReferenceSystem& crs, double* geoTransform, int nBands,
QGis::DataType type,
QList<bool> destHasNoDataValueList = QList<bool>(), QList<double> destNoDataValueList = QList<double>() );

/**Calculate nRows, geotransform and pixel size for output*/
void globalOutputParameters( const QgsRectangle& extent, int nCols, int& nRows, double* geoTransform, double& pixelSize );

QString partFileName( int fileIndex );

Mode mMode;
QString mOutputUrl;
QString mOutputProviderKey;
QString mOutputFormat;
Expand All @@ -148,12 +158,12 @@ class CORE_EXPORT QgsRasterFileWriter
QgsRasterDataProvider::RasterPyramidsFormat mPyramidsFormat;

QDomDocument mVRTDocument;
QDomElement mVRTRedBand;
QDomElement mVRTGreenBand;
QDomElement mVRTBlueBand;
QDomElement mVRTAlphaBand;
QList<QDomElement> mVRTBands;

QProgressDialog* mProgressDialog;

const QgsRasterPipe* mPipe;
const QgsRasterInterface* mInput;
};

#endif // QGSRASTERFILEWRITER_H
67 changes: 58 additions & 9 deletions src/gui/qgsrasterlayersaveasdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
#include "qgsgenericprojectionselector.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>


QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLayer,
QgsRasterDataProvider* sourceProvider, const QgsRectangle& currentExtent,
const QgsCoordinateReferenceSystem& layerCrs, const QgsCoordinateReferenceSystem& currentCrs,
Expand Down Expand Up @@ -117,10 +117,12 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLa
// restore checked state for most groupboxes (default is to restore collapsed state)
// create options and pyramids will be preset, if user has selected defaults in the gdal options dlg
mCreateOptionsGroupBox->setSaveCheckedState( true );
mTilesGroupBox->setSaveCheckedState( true );
//mTilesGroupBox->setSaveCheckedState( true );
// don't restore nodata, it needs user input
// pyramids are not necessarily built every time

mTilesGroupBox->hide();

updateCrsGroup();

QPushButton* okButton = mButtonBox->button( QDialogButtonBox::Ok );
Expand Down Expand Up @@ -153,11 +155,44 @@ void QgsRasterLayerSaveAsDialog::on_mBrowseButton_clicked()
QString fileName;
if ( mTileModeCheckBox->isChecked() )
{
fileName = QFileDialog::getExistingDirectory( this, tr( "Select output directory" ) );
while ( true )
{
// TODO: would not it be better to select .vrt file instead of directory?
fileName = QFileDialog::getExistingDirectory( this, tr( "Select output directory" ) );
//fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), QString(), tr( "VRT" ) + " (*.vrt *.VRT)" );

if ( fileName.isEmpty() ) break; // canceled

// Check if directory is empty
QDir dir( fileName );
QString baseName = QFileInfo( fileName ).baseName();
QStringList filters;
filters << QString( "%1.*" ).arg( baseName );
QStringList files = dir.entryList( filters );
if ( !files.isEmpty() )
{
QMessageBox::StandardButton button = QMessageBox::warning( this, tr( "Warning" ),
tr( "The directory %1 contains files which will be overwritten: %2" ).arg( dir.absolutePath() ).arg( files.join( ", " ) ),
QMessageBox::Ok | QMessageBox::Cancel );

if ( button == QMessageBox::Ok )
{
break;
}
else
{
fileName = "";
}
}
else
{
break;
}
}
}
else
{
fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ) );
fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), QString(), tr( "GeoTIFF" ) + " (*.tif *.tiff *.TIF *.TIFF)" );
}

if ( !fileName.isEmpty() )
Expand Down Expand Up @@ -667,11 +702,25 @@ void QgsRasterLayerSaveAsDialog::on_mTileModeCheckBox_toggled( bool toggled )
if ( toggled )
{
// enable pyramids
if ( ! mPyramidsGroupBox->isChecked() )
mPyramidsGroupBox->setChecked( true );
if ( mPyramidsGroupBox->isCollapsed() )
mPyramidsGroupBox->setCollapsed( false );
mPyramidsOptionsWidget->checkAllLevels( true );

// Disabled (Radim), auto enabling of pyramids was making impression that
// we (programmers) know better what you (user) want to do,
// certainly auto expaning was bad experience

//if ( ! mPyramidsGroupBox->isChecked() )
// mPyramidsGroupBox->setChecked( true );

// Auto expanding mPyramidsGroupBox is bad - it auto crolls content of dialog
//if ( mPyramidsGroupBox->isCollapsed() )
// mPyramidsGroupBox->setCollapsed( false );
//mPyramidsOptionsWidget->checkAllLevels( true );

// Show / hide tile options
mTilesGroupBox->show();
}
else
{
mTilesGroupBox->hide();
}
}

Expand Down
238 changes: 121 additions & 117 deletions src/ui/qgsrasterlayersaveasdialogbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mTileModeCheckBox">
<property name="toolTip">
<string>Create GDAL Virtual Format composed of multiple
datasets with maximum width and height specified below.</string>
</property>
<property name="text">
<string>Create VRT</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
Expand Down Expand Up @@ -146,7 +157,7 @@
<item>
<widget class="QComboBox" name="mCrsComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
Expand All @@ -162,7 +173,7 @@
<item>
<widget class="QPushButton" name="mChangeCrsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
Expand Down Expand Up @@ -190,8 +201,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>536</width>
<height>779</height>
<width>549</width>
<height>700</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
Expand Down Expand Up @@ -453,30 +464,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mCreateOptionsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Create Options</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QgsRasterFormatSaveOptionsWidget" name="mCreateOptionsWidget" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mTilesGroupBox">
<property name="sizePolicy">
Expand All @@ -486,10 +473,10 @@
</sizepolicy>
</property>
<property name="title">
<string>Tiles</string>
<string>VRT Tiles</string>
</property>
<property name="checkable">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
Expand Down Expand Up @@ -529,10 +516,111 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mTileModeCheckBox">
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mCreateOptionsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Create Options</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QgsRasterFormatSaveOptionsWidget" name="mCreateOptionsWidget" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mPyramidsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Pyramids</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
<widget class="QgsRasterPyramidsOptionsWidget" name="mPyramidsOptionsWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="mPyramidResolutionsLabel">
<property name="text">
<string>Resolutions</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="mPyramidResolutionsLineEdit">
<property name="toolTip">
<string>Pyramid resolutions corresponding to levels given</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mPyramidsUseExistingCheckBox">
<property name="text">
<string>Create VRT</string>
<string>Use existing</string>
</property>
</widget>
</item>
Expand Down Expand Up @@ -642,90 +730,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="mPyramidsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Pyramids</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
<widget class="QgsRasterPyramidsOptionsWidget" name="mPyramidsOptionsWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="mPyramidResolutionsLabel">
<property name="text">
<string>Resolutions</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="mPyramidResolutionsLineEdit">
<property name="toolTip">
<string>Pyramid resolutions corresponding to levels given</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mPyramidsUseExistingCheckBox">
<property name="text">
<string>Use existing</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
Expand Down