Skip to content

Commit c5cc634

Browse files
committed
raster save creation options validation:
- move help and validation to gdal provider - validate options before saving - test for valid PREDICTOR option, depending raster properties
1 parent bb7dc52 commit c5cc634

8 files changed

Lines changed: 203 additions & 47 deletions

‎python/gui/qgsrasterformatsaveoptionswidget.sip‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class QgsRasterFormatSaveOptionsWidget : QWidget
2929

3030
void apply();
3131
void helpOptions();
32-
bool validateOptions( bool gui = true );
32+
QString validateOptions( bool gui = true, bool reportOk = true );
3333

3434
private slots:
3535

‎src/core/qgsrasterdataprovider.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,11 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
597597
tr( "Cubic" ) << tr( "Mode" ) << tr( "None" ) : QStringList();
598598
}
599599

600+
/** Validates creation options for a specific dataset and destination format - used by GDAL provider only.
601+
* See also validateCreationOptionsFormat() in gdal provider for validating options based on format only. */
602+
virtual QString validateCreationOptions( const QStringList& createOptions, QString format )
603+
{ Q_UNUSED( createOptions ); Q_UNUSED( format ); return QString(); }
604+
600605
signals:
601606
/** Emit a signal to notify of the progress event.
602607
* Emited theProgress is in percents (0.0-100.0) */

‎src/gui/qgsrasterformatsaveoptionswidget.cpp‎

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@
1818
#include "qgsrasterformatsaveoptionswidget.h"
1919
#include "qgslogger.h"
2020
#include "qgsdialog.h"
21-
22-
#include "gdal.h"
23-
#include "cpl_string.h"
24-
#include "cpl_conv.h"
25-
#include "cpl_minixml.h"
21+
#include "qgsrasterlayer.h"
22+
#include "qgsproviderregistry.h"
2623

2724
#include <QSettings>
2825
#include <QInputDialog>
@@ -31,28 +28,16 @@
3128
#include <QMouseEvent>
3229
#include <QMenu>
3330

34-
// todo put this somewhere else - how can we access gdal provider?
35-
char** papszFromStringList( const QStringList& list )
36-
{
37-
char **papszRetList = NULL;
38-
foreach ( QString elem, list )
39-
{
40-
papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
41-
}
42-
return papszRetList;
43-
}
4431

4532
QMap< QString, QStringList > QgsRasterFormatSaveOptionsWidget::mBuiltinProfiles;
4633

4734
QgsRasterFormatSaveOptionsWidget::QgsRasterFormatSaveOptionsWidget( QWidget* parent, QString format,
48-
QgsRasterFormatSaveOptionsWidget::Type type,
49-
QString provider )
50-
: QWidget( parent ), mFormat( format ), mProvider( provider )
35+
QgsRasterFormatSaveOptionsWidget::Type type, QString provider )
36+
: QWidget( parent ), mFormat( format ), mProvider( provider ), mRasterLayer( 0 )
5137

5238
{
5339
setupUi( this );
5440

55-
5641
setType( type );
5742

5843
if ( mBuiltinProfiles.isEmpty() )
@@ -104,6 +89,7 @@ QgsRasterFormatSaveOptionsWidget::QgsRasterFormatSaveOptionsWidget( QWidget* par
10489
mOptionsLineEdit->installEventFilter( this );
10590
mOptionsStackedWidget->installEventFilter( this );
10691

92+
updateControls();
10793
updateProfiles();
10894
}
10995

@@ -114,12 +100,14 @@ QgsRasterFormatSaveOptionsWidget::~QgsRasterFormatSaveOptionsWidget()
114100
void QgsRasterFormatSaveOptionsWidget::setFormat( QString format )
115101
{
116102
mFormat = format;
103+
updateControls();
117104
updateProfiles();
118105
}
119106

120107
void QgsRasterFormatSaveOptionsWidget::setProvider( QString provider )
121108
{
122109
mProvider = provider;
110+
updateControls();
123111
}
124112

125113
// show/hide widgets - we need this function if widget is used in creator
@@ -236,27 +224,35 @@ void QgsRasterFormatSaveOptionsWidget::apply()
236224
setCreateOptions();
237225
}
238226

227+
// typedefs for gdal provider function pointers
228+
typedef QString validateCreationOptionsFormat_t( const QStringList& createOptions, QString format );
229+
typedef QString helpCreationOptionsFormat_t( QString format );
239230

240231
void QgsRasterFormatSaveOptionsWidget::helpOptions()
241232
{
242233
QString message;
243234

244235
if ( mProvider == "gdal" && mFormat != "" && mFormat != "_pyramids" )
245236
{
246-
GDALDriverH myGdalDriver = GDALGetDriverByName( mFormat.toLocal8Bit().constData() );
247-
if ( myGdalDriver )
237+
// get helpCreationOptionsFormat() function ptr for provider
238+
QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( mProvider );
239+
if ( library )
248240
{
249-
// need to serialize xml to get newlines
250-
CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
251-
GDAL_DMD_CREATIONOPTIONLIST, "" ) );
252-
char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
253-
if ( pszFormattedXML )
254-
message = tr( "Create Options:\n\n%1" ).arg( pszFormattedXML );
255-
if ( psCOL )
256-
CPLDestroyXMLNode( psCOL );
257-
if ( pszFormattedXML )
258-
CPLFree( pszFormattedXML );
241+
helpCreationOptionsFormat_t * helpCreationOptionsFormat =
242+
( helpCreationOptionsFormat_t * ) cast_to_fptr( library->resolve( "helpCreationOptionsFormat" ) );
243+
if ( helpCreationOptionsFormat )
244+
{
245+
message = helpCreationOptionsFormat( mFormat );
246+
}
247+
else
248+
{
249+
message = library->fileName() + " does not have helpCreationOptionsFormat";
250+
}
259251
}
252+
else
253+
message = QString( "cannot load provider library %1" ).arg( mProvider );
254+
255+
260256
if ( message.isEmpty() )
261257
message = tr( "Cannot get create options for driver %1" ).arg( mFormat );
262258
}
@@ -267,36 +263,65 @@ void QgsRasterFormatSaveOptionsWidget::helpOptions()
267263
QgsDialog *dlg = new QgsDialog( this );
268264
QTextEdit *textEdit = new QTextEdit( dlg );
269265
textEdit->setReadOnly( true );
266+
message = tr( "Create Options:\n\n%1" ).arg( message );
270267
textEdit->setText( message );
271268
dlg->layout()->addWidget( textEdit );
272-
dlg->resize( 600, 600 );
269+
dlg->resize( 600, 400 );
273270
dlg->show(); //non modal
274271
}
275272

276-
bool QgsRasterFormatSaveOptionsWidget::validateOptions( bool gui )
273+
QString QgsRasterFormatSaveOptionsWidget::validateOptions( bool gui, bool reportOK )
277274
{
278275
QStringList createOptions = options();
279-
bool ok = false;
276+
QString message;
280277

281278
if ( !createOptions.isEmpty() && mProvider == "gdal" && mFormat != "" && mFormat != "_pyramids" )
282279
{
283-
GDALDriverH myGdalDriver = GDALGetDriverByName( mFormat.toLocal8Bit().constData() );
284-
if ( myGdalDriver )
280+
if ( mRasterLayer )
281+
{
282+
QgsDebugMsg( "calling validate on layer's data provider" );
283+
message = mRasterLayer->dataProvider()->validateCreationOptions( createOptions, mFormat );
284+
}
285+
else
285286
{
286-
// print error string?
287-
char** papszOptions = papszFromStringList( createOptions );
288-
ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
289-
CSLDestroy( papszOptions );
290-
if ( gui )
287+
// get validateCreationOptionsFormat() function ptr for provider
288+
QLibrary *library = QgsProviderRegistry::instance()->providerLibrary( mProvider );
289+
if ( library )
291290
{
292-
if ( ok )
293-
QMessageBox::information( this, "", tr( "Valid" ), QMessageBox::Close );
291+
validateCreationOptionsFormat_t * validateCreationOptionsFormat =
292+
( validateCreationOptionsFormat_t * ) cast_to_fptr( library->resolve( "validateCreationOptionsFormat" ) );
293+
if ( validateCreationOptionsFormat )
294+
{
295+
message = validateCreationOptionsFormat( createOptions, mFormat );
296+
}
294297
else
295-
QMessageBox::warning( this, "", tr( "Invalid" ), QMessageBox::Close );
298+
{
299+
message = library->fileName() + " does not have validateCreationOptionsFormat";
300+
}
301+
}
302+
else
303+
message = QString( "cannot load provider library %1" ).arg( mProvider );
304+
}
305+
306+
if ( gui )
307+
{
308+
if ( message.isNull() )
309+
{
310+
if ( reportOK )
311+
QMessageBox::information( this, "", tr( "Valid" ), QMessageBox::Close );
312+
}
313+
else
314+
{
315+
QMessageBox::warning( this, "", tr( "Invalid creation option :\n\n%1\n\nClick on help button to get valid creation options for this format" ).arg( message ), QMessageBox::Close );
296316
}
297317
}
298318
}
299-
return ok;
319+
else
320+
{
321+
QMessageBox::information( this, "", tr( "Cannot validate" ), QMessageBox::Close );
322+
}
323+
324+
return message;
300325
}
301326

302327
void QgsRasterFormatSaveOptionsWidget::optionsTableChanged()
@@ -481,6 +506,13 @@ void QgsRasterFormatSaveOptionsWidget::swapOptionsUI( int newIndex )
481506
updateOptions();
482507
}
483508

509+
void QgsRasterFormatSaveOptionsWidget::updateControls()
510+
{
511+
bool enabled = ( mProvider == "gdal" && mFormat != "" && mFormat != "_pyramids" );
512+
mOptionsValidateButton->setEnabled( enabled );
513+
mOptionsHelpButton->setEnabled( enabled );
514+
}
515+
484516
// map options label left mouse click to optionsToggle()
485517
bool QgsRasterFormatSaveOptionsWidget::eventFilter( QObject *obj, QEvent *event )
486518
{

‎src/gui/qgsrasterformatsaveoptionswidget.h‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "ui_qgsrasterformatsaveoptionswidgetbase.h"
2222

23+
class QgsRasterLayer;
24+
2325
/** \ingroup gui
2426
* A widget to select format-specific raster saving options
2527
*/
@@ -46,14 +48,15 @@ class GUI_EXPORT QgsRasterFormatSaveOptionsWidget: public QWidget,
4648

4749
void setFormat( QString format );
4850
void setProvider( QString provider );
51+
void setRasterLayer( QgsRasterLayer* rasterLayer ) { mRasterLayer = rasterLayer; }
4952
QStringList options() const;
5053
void setType( QgsRasterFormatSaveOptionsWidget::Type type = Default );
5154

5255
public slots:
5356

5457
void apply();
5558
void helpOptions();
56-
bool validateOptions( bool gui = true );
59+
QString validateOptions( bool gui = true, bool reportOk = true );
5760
void updateProfiles();
5861

5962
private slots:
@@ -68,11 +71,13 @@ class GUI_EXPORT QgsRasterFormatSaveOptionsWidget: public QWidget,
6871
void optionsTableEnableDeleteButton();
6972
void updateOptions();
7073
void swapOptionsUI( int newIndex = -1 );
74+
void updateControls();
7175

7276
private:
7377

7478
QString mFormat;
7579
QString mProvider;
80+
QgsRasterLayer* mRasterLayer;
7681
QMap< QString, QString> mOptionsMap;
7782
static QMap< QString, QStringList > mBuiltinProfiles;
7883

‎src/gui/qgsrasterlayersaveasdialog.cpp‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLa
7676
{
7777
mCreateOptionsWidget->setFormat( myFormats[0] );
7878
}
79+
mCreateOptionsWidget->setRasterLayer( mRasterLayer );
7980
mCreateOptionsWidget->update();
8081
}
8182

@@ -753,3 +754,14 @@ QgsRasterDataProvider::RasterBuildPyramids QgsRasterLayerSaveAsDialog::buildPyra
753754
return QgsRasterDataProvider::PyramidsFlagYes;
754755
}
755756

757+
bool QgsRasterLayerSaveAsDialog::validate() const
758+
{
759+
if ( mCreateOptionsGroupBox->isChecked() )
760+
{
761+
QString message = mCreateOptionsWidget->validateOptions( true, false );
762+
if ( !message.isNull() )
763+
return false;
764+
}
765+
return true;
766+
}
767+

‎src/gui/qgsrasterlayersaveasdialog.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
6767
void hideFormat();
6868
void hideOutput();
6969

70+
public slots:
71+
virtual void accept() { if ( validate() ) return QDialog::accept(); }
72+
7073
private slots:
7174
void on_mRawModeRadioButton_toggled( bool );
7275
void on_mBrowseButton_clicked();
@@ -132,6 +135,7 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
132135
void setNoDataToEdited( int row );
133136
double noDataCellValue( int row, int column ) const;
134137
void adjustNoDataCellWidth( int row, int column );
138+
bool validate() const;
135139
};
136140

137141

0 commit comments

Comments
 (0)