QGIS API Documentation  2.99.0-Master (cb63e82)
qgsrasterformatsaveoptionswidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterformatsaveoptionswidget.cpp
3  -------------------
4  begin : July 2012
5  copyright : (C) 2012 by Etienne Tourigny
6  email : etourigny dot dev at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgslogger.h"
20 #include "qgsdialog.h"
21 #include "qgsrasterlayer.h"
22 #include "qgsproviderregistry.h"
23 #include "qgsrasterdataprovider.h"
24 #include "qgssettings.h"
25 
26 #include <QInputDialog>
27 #include <QMessageBox>
28 #include <QTextEdit>
29 #include <QMouseEvent>
30 #include <QMenu>
31 
32 
33 QMap< QString, QStringList > QgsRasterFormatSaveOptionsWidget::sBuiltinProfiles;
34 
35 static const QString PYRAMID_JPEG_YCBCR_COMPRESSION( QStringLiteral( "JPEG_QUALITY_OVERVIEW=75 COMPRESS_OVERVIEW=JPEG PHOTOMETRIC_OVERVIEW=YCBCR INTERLEAVE_OVERVIEW=PIXEL" ) );
36 static const QString PYRAMID_JPEG_COMPRESSION( QStringLiteral( "JPEG_QUALITY_OVERVIEW=75 COMPRESS_OVERVIEW=JPEG INTERLEAVE_OVERVIEW=PIXEL" ) );
37 
39  QgsRasterFormatSaveOptionsWidget::Type type, const QString &provider )
40  : QWidget( parent )
41  , mFormat( format )
42  , mProvider( provider )
43  , mRasterLayer( nullptr )
44  , mRasterFileName( QString() )
45  , mPyramids( false )
46  , mPyramidsFormat( QgsRaster::PyramidsGTiff )
47 
48 {
49  setupUi( this );
50 
51  setType( type );
52 
53  if ( sBuiltinProfiles.isEmpty() )
54  {
55  // key=profileKey values=format,profileName,options
56  sBuiltinProfiles[ QStringLiteral( "z_adefault" )] = ( QStringList() << QLatin1String( "" ) << tr( "Default" ) << QLatin1String( "" ) );
57 
58  // these GTiff profiles are based on Tim's benchmarks at
59  // http://linfiniti.com/2011/05/gdal-efficiency-of-various-compression-algorithms/
60  // big: no compression | medium: reasonable size/speed tradeoff | small: smallest size
61  sBuiltinProfiles[ QStringLiteral( "z_gtiff_1big" )] =
62  ( QStringList() << QStringLiteral( "GTiff" ) << tr( "No compression" )
63  << QStringLiteral( "COMPRESS=NONE BIGTIFF=IF_NEEDED" ) );
64  sBuiltinProfiles[ QStringLiteral( "z_gtiff_2medium" )] =
65  ( QStringList() << QStringLiteral( "GTiff" ) << tr( "Low compression" )
66  << QStringLiteral( "COMPRESS=PACKBITS" ) );
67  sBuiltinProfiles[ QStringLiteral( "z_gtiff_3small" )] =
68  ( QStringList() << QStringLiteral( "GTiff" ) << tr( "High compression" )
69  << QStringLiteral( "COMPRESS=DEFLATE PREDICTOR=2 ZLEVEL=9" ) );
70  sBuiltinProfiles[ QStringLiteral( "z_gtiff_4jpeg" )] =
71  ( QStringList() << QStringLiteral( "GTiff" ) << tr( "JPEG compression" )
72  << QStringLiteral( "COMPRESS=JPEG JPEG_QUALITY=75" ) );
73 
74  // overview compression schemes for GTiff format, see
75  // http://www.gdal.org/gdaladdo.html and http://www.gdal.org/frmt_gtiff.html
76  // TODO - should we offer GDAL_TIFF_OVR_BLOCKSIZE option here or in QgsRasterPyramidsOptionsWidget ?
77  sBuiltinProfiles[ QStringLiteral( "z__pyramids_gtiff_1big" )] =
78  ( QStringList() << QStringLiteral( "_pyramids" ) << tr( "No compression" )
79  << QStringLiteral( "COMPRESS_OVERVIEW=NONE BIGTIFF_OVERVIEW=IF_NEEDED" ) );
80  sBuiltinProfiles[ QStringLiteral( "z__pyramids_gtiff_2medium" )] =
81  ( QStringList() << QStringLiteral( "_pyramids" ) << tr( "Low compression" )
82  << QStringLiteral( "COMPRESS_OVERVIEW=PACKBITS" ) );
83  sBuiltinProfiles[ QStringLiteral( "z__pyramids_gtiff_3small" )] =
84  ( QStringList() << QStringLiteral( "_pyramids" ) << tr( "High compression" )
85  << QStringLiteral( "COMPRESS_OVERVIEW=DEFLATE PREDICTOR_OVERVIEW=2 ZLEVEL=9" ) ); // how to set zlevel?
86  sBuiltinProfiles[ QStringLiteral( "z__pyramids_gtiff_4jpeg" )] =
87  ( QStringList() << QStringLiteral( "_pyramids" ) << tr( "JPEG compression" )
88  << PYRAMID_JPEG_YCBCR_COMPRESSION );
89  }
90 
91  connect( mProfileComboBox, static_cast<void ( QComboBox::* )( const QString & )>( &QComboBox::currentIndexChanged ),
92  this, &QgsRasterFormatSaveOptionsWidget::updateOptions );
93  connect( mOptionsTable, &QTableWidget::cellChanged, this, &QgsRasterFormatSaveOptionsWidget::optionsTableChanged );
94  connect( mOptionsHelpButton, &QAbstractButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::helpOptions );
95  connect( mOptionsValidateButton, &QAbstractButton::clicked, this, [ = ] { validateOptions(); } );
96 
97  // create eventFilter to map right click to swapOptionsUI()
98  // mOptionsLabel->installEventFilter( this );
99  mOptionsLineEdit->installEventFilter( this );
100  mOptionsStackedWidget->installEventFilter( this );
101 
102  updateControls();
103  updateProfiles();
104 
105  QgsDebugMsg( "done" );
106 }
107 
108 void QgsRasterFormatSaveOptionsWidget::setFormat( const QString &format )
109 {
110  mFormat = format;
111  updateControls();
112  updateProfiles();
113 }
114 
115 void QgsRasterFormatSaveOptionsWidget::setProvider( const QString &provider )
116 {
117  mProvider = provider;
118  updateControls();
119 }
120 
121 // show/hide widgets - we need this function if widget is used in creator
123 {
124  QList< QWidget * > widgets = this->findChildren<QWidget *>();
125  if ( ( type == Table ) || ( type == LineEdit ) )
126  {
127  // hide all controls, except stacked widget
128  Q_FOREACH ( QWidget *widget, widgets )
129  widget->setVisible( false );
130  mOptionsStackedWidget->setVisible( true );
131  Q_FOREACH ( QWidget *widget, mOptionsStackedWidget->findChildren<QWidget *>() )
132  widget->setVisible( true );
133 
134  // show relevant page
135  if ( type == Table )
136  swapOptionsUI( 0 );
137  else if ( type == LineEdit )
138  swapOptionsUI( 1 );
139  }
140  else
141  {
142  // show all widgets, except profile buttons (unless Full)
143  Q_FOREACH ( QWidget *widget, widgets )
144  widget->setVisible( true );
145  if ( type != Full )
146  mProfileButtons->setVisible( false );
147 
148  // show elevant page
149  if ( type == ProfileLineEdit )
150  swapOptionsUI( 1 );
151  }
152 }
153 
154 QString QgsRasterFormatSaveOptionsWidget::pseudoFormat() const
155 {
156  return mPyramids ? QStringLiteral( "_pyramids" ) : mFormat;
157 }
158 
160 {
161  // build profiles list = user + builtin(last)
162  QString format = pseudoFormat();
163  QStringList profileKeys = profiles();
164  QMapIterator<QString, QStringList> it( sBuiltinProfiles );
165  while ( it.hasNext() )
166  {
167  it.next();
168  QString profileKey = it.key();
169  if ( ! profileKeys.contains( profileKey ) && !it.value().isEmpty() )
170  {
171  // insert key if is for all formats or this format (GTiff)
172  if ( it.value()[0] == QLatin1String( "" ) || it.value()[0] == format )
173  {
174  profileKeys.insert( 0, profileKey );
175  }
176  }
177  }
178  std::sort( profileKeys.begin(), profileKeys.end() );
179 
180  // populate mOptionsMap and mProfileComboBox
181  mOptionsMap.clear();
182  mProfileComboBox->blockSignals( true );
183  mProfileComboBox->clear();
184  Q_FOREACH ( const QString &profileKey, profileKeys )
185  {
186  QString profileName, profileOptions;
187  profileOptions = createOptions( profileKey );
188  if ( sBuiltinProfiles.contains( profileKey ) )
189  {
190  profileName = sBuiltinProfiles[ profileKey ][ 1 ];
191  if ( profileOptions.isEmpty() )
192  profileOptions = sBuiltinProfiles[ profileKey ][ 2 ];
193  }
194  else
195  {
196  profileName = profileKey;
197  }
198  mOptionsMap[ profileKey ] = profileOptions;
199  mProfileComboBox->addItem( profileName, profileKey );
200  }
201 
202  // update UI
203  mProfileComboBox->blockSignals( false );
204  // mProfileComboBox->setCurrentIndex( 0 );
205  QgsSettings mySettings;
206  mProfileComboBox->setCurrentIndex( mProfileComboBox->findData( mySettings.value(
207  mProvider + "/driverOptions/" + format.toLower() + "/defaultProfile",
208  "z_adefault" ) ) );
209  updateOptions();
210 }
211 
212 void QgsRasterFormatSaveOptionsWidget::updateOptions()
213 {
214  QString myOptions = mOptionsMap.value( currentProfileKey() );
215  QStringList myOptionsList = myOptions.trimmed().split( ' ', QString::SkipEmptyParts );
216 
217  // If the default JPEG compression profile was selected, remove PHOTOMETRIC_OVERVIEW=YCBCR
218  // if the raster is not RGB. Otherwise this is bound to fail afterwards.
219  if ( mRasterLayer && mRasterLayer->bandCount() != 3 &&
220  myOptions == PYRAMID_JPEG_YCBCR_COMPRESSION )
221  {
222  myOptions = PYRAMID_JPEG_COMPRESSION;
223  }
224 
225  if ( mOptionsStackedWidget->currentIndex() == 0 )
226  {
227  mOptionsTable->setRowCount( 0 );
228  for ( int i = 0; i < myOptionsList.count(); i++ )
229  {
230  QStringList key_value = myOptionsList[i].split( '=' );
231  if ( key_value.count() == 2 )
232  {
233  mOptionsTable->insertRow( i );
234  mOptionsTable->setItem( i, 0, new QTableWidgetItem( key_value[0] ) );
235  mOptionsTable->setItem( i, 1, new QTableWidgetItem( key_value[1] ) );
236  }
237  }
238  }
239  else
240  {
241  mOptionsLineEdit->setText( myOptions );
242  mOptionsLineEdit->setCursorPosition( 0 );
243  }
244 
245  emit optionsChanged();
246 }
247 
249 {
250  setCreateOptions();
251 }
252 
253 // typedefs for gdal provider function pointers
254 typedef QString validateCreationOptionsFormat_t( const QStringList &createOptions, QString format );
255 typedef QString helpCreationOptionsFormat_t( QString format );
256 
258 {
259  QString message;
260 
261  if ( mProvider == QLatin1String( "gdal" ) && mFormat != QLatin1String( "" ) && ! mPyramids )
262  {
263  // get helpCreationOptionsFormat() function ptr for provider
264  std::unique_ptr< QLibrary > library( QgsProviderRegistry::instance()->providerLibrary( mProvider ) );
265  if ( library )
266  {
267  helpCreationOptionsFormat_t *helpCreationOptionsFormat =
268  ( helpCreationOptionsFormat_t * ) cast_to_fptr( library->resolve( "helpCreationOptionsFormat" ) );
269  if ( helpCreationOptionsFormat )
270  {
271  message = helpCreationOptionsFormat( mFormat );
272  }
273  else
274  {
275  message = library->fileName() + " does not have helpCreationOptionsFormat";
276  }
277  }
278  else
279  message = QStringLiteral( "cannot load provider library %1" ).arg( mProvider );
280 
281 
282  if ( message.isEmpty() )
283  message = tr( "Cannot get create options for driver %1" ).arg( mFormat );
284  }
285  else if ( mProvider == QLatin1String( "gdal" ) && mPyramids )
286  {
287  message = tr( "For details on pyramids options please see the following pages" );
288  message += QLatin1String( "\n\nhttp://www.gdal.org/gdaladdo.html\n\nhttp://www.gdal.org/frmt_gtiff.html" );
289  }
290  else
291  message = tr( "No help available" );
292 
293  // show simple non-modal dialog - should we make the basic xml prettier?
294  QgsDialog *dlg = new QgsDialog( this );
295  QTextEdit *textEdit = new QTextEdit( dlg );
296  textEdit->setReadOnly( true );
297  // message = tr( "Create Options:\n\n%1" ).arg( message );
298  textEdit->setText( message );
299  dlg->layout()->addWidget( textEdit );
300  dlg->resize( 600, 400 );
301 #ifdef Q_OS_MAC
302  dlg->exec(); //modal
303 #else
304  dlg->show(); //non modal
305 #endif
306 }
307 
308 QString QgsRasterFormatSaveOptionsWidget::validateOptions( bool gui, bool reportOK )
309 {
310  QStringList createOptions = options();
311  QString message;
312 
313  QgsDebugMsg( QString( "layer: [%1] file: [%2] format: [%3]" ).arg( mRasterLayer ? mRasterLayer->id() : "none", mRasterFileName, mFormat ) );
314  // if no rasterLayer is defined, but we have a raster fileName, then create a temp. rasterLayer to validate options
315  // ideally we should keep it for future access, but this is trickier
316  QgsRasterLayer *rasterLayer = mRasterLayer;
317  bool tmpLayer = false;
318  if ( !( mRasterLayer && rasterLayer->dataProvider() ) && ! mRasterFileName.isNull() )
319  {
320  // temporarily override /Projections/defaultBehavior to avoid dialog prompt
321  // this is taken from qgsbrowserdockwidget.cpp
322  // TODO - integrate this into qgis core
323  QgsSettings settings;
324  QString defaultProjectionOption = settings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString();
325  if ( settings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString() == QLatin1String( "prompt" ) )
326  {
327  settings.setValue( QStringLiteral( "Projections/defaultBehavior" ), "useProject" );
328  }
329  tmpLayer = true;
330  rasterLayer = new QgsRasterLayer( mRasterFileName, QFileInfo( mRasterFileName ).baseName(), QStringLiteral( "gdal" ) );
331  // restore /Projections/defaultBehavior
332  if ( defaultProjectionOption == QLatin1String( "prompt" ) )
333  {
334  settings.setValue( QStringLiteral( "Projections/defaultBehavior" ), defaultProjectionOption );
335  }
336  }
337 
338  if ( mProvider == QLatin1String( "gdal" ) && mPyramids )
339  {
340  if ( rasterLayer && rasterLayer->dataProvider() )
341  {
342  QgsDebugMsg( "calling validate pyramids on layer's data provider" );
343  message = rasterLayer->dataProvider()->validatePyramidsConfigOptions( mPyramidsFormat, createOptions, mFormat );
344  }
345  else
346  {
347  message = tr( "cannot validate pyramid options" );
348  }
349  }
350  else if ( !createOptions.isEmpty() && mProvider == QLatin1String( "gdal" ) && mFormat != QLatin1String( "" ) )
351  {
352  if ( rasterLayer && rasterLayer->dataProvider() )
353  {
354  QgsDebugMsg( "calling validate on layer's data provider" );
355  message = rasterLayer->dataProvider()->validateCreationOptions( createOptions, mFormat );
356  }
357  else
358  {
359  // get validateCreationOptionsFormat() function ptr for provider
360  std::unique_ptr< QLibrary > library( QgsProviderRegistry::instance()->providerLibrary( mProvider ) );
361  if ( library )
362  {
363  validateCreationOptionsFormat_t *validateCreationOptionsFormat =
364  ( validateCreationOptionsFormat_t * ) cast_to_fptr( library->resolve( "validateCreationOptionsFormat" ) );
365  if ( validateCreationOptionsFormat )
366  {
367  message = validateCreationOptionsFormat( createOptions, mFormat );
368  }
369  else
370  {
371  message = library->fileName() + " does not have validateCreationOptionsFormat";
372  }
373  }
374  else
375  message = QStringLiteral( "cannot load provider library %1" ).arg( mProvider );
376  }
377  }
378  else if ( ! createOptions.isEmpty() )
379  {
380  QMessageBox::information( this, QLatin1String( "" ), tr( "Cannot validate creation options" ), QMessageBox::Close );
381  if ( tmpLayer )
382  delete rasterLayer;
383  return QString();
384  }
385 
386  if ( gui )
387  {
388  if ( message.isNull() )
389  {
390  if ( reportOK )
391  QMessageBox::information( this, QLatin1String( "" ), tr( "Valid" ), QMessageBox::Close );
392  }
393  else
394  {
395  QMessageBox::warning( this, QLatin1String( "" ), tr( "Invalid %1:\n\n%2\n\nClick on help button to get valid creation options for this format." ).arg( mPyramids ? tr( "pyramid creation option" ) : tr( "creation option" ), message ), QMessageBox::Close );
396  }
397  }
398 
399  if ( tmpLayer )
400  delete rasterLayer;
401 
402  return message;
403 }
404 
405 void QgsRasterFormatSaveOptionsWidget::optionsTableChanged()
406 {
407  QTableWidgetItem *key, *value;
408  QString options;
409  for ( int i = 0 ; i < mOptionsTable->rowCount(); i++ )
410  {
411  key = mOptionsTable->item( i, 0 );
412  if ( ! key || key->text().isEmpty() )
413  continue;
414  value = mOptionsTable->item( i, 1 );
415  if ( ! value || value->text().isEmpty() )
416  continue;
417  options += key->text() + '=' + value->text() + ' ';
418  }
419  options = options.trimmed();
420  mOptionsMap[ currentProfileKey()] = options;
421  mOptionsLineEdit->setText( options );
422  mOptionsLineEdit->setCursorPosition( 0 );
423 }
424 
425 void QgsRasterFormatSaveOptionsWidget::on_mOptionsLineEdit_editingFinished()
426 {
427  mOptionsMap[ currentProfileKey()] = mOptionsLineEdit->text().trimmed();
428 }
429 
430 void QgsRasterFormatSaveOptionsWidget::on_mProfileNewButton_clicked()
431 {
432  QString profileName = QInputDialog::getText( this, QLatin1String( "" ), tr( "Profile name:" ) );
433  if ( ! profileName.isEmpty() )
434  {
435  profileName = profileName.trimmed();
436  mOptionsMap[ profileName ] = QLatin1String( "" );
437  mProfileComboBox->addItem( profileName, profileName );
438  mProfileComboBox->setCurrentIndex( mProfileComboBox->count() - 1 );
439  }
440 }
441 
442 void QgsRasterFormatSaveOptionsWidget::on_mProfileDeleteButton_clicked()
443 {
444  int index = mProfileComboBox->currentIndex();
445  QString profileKey = currentProfileKey();
446  if ( index != -1 && ! sBuiltinProfiles.contains( profileKey ) )
447  {
448  mOptionsMap.remove( profileKey );
449  mProfileComboBox->removeItem( index );
450  }
451 }
452 
453 void QgsRasterFormatSaveOptionsWidget::on_mProfileResetButton_clicked()
454 {
455  QString profileKey = currentProfileKey();
456  if ( sBuiltinProfiles.contains( profileKey ) )
457  {
458  mOptionsMap[ profileKey ] = sBuiltinProfiles[ profileKey ][ 2 ];
459  }
460  else
461  {
462  mOptionsMap[ profileKey ] = QLatin1String( "" );
463  }
464  mOptionsLineEdit->setText( mOptionsMap.value( currentProfileKey() ) );
465  mOptionsLineEdit->setCursorPosition( 0 );
466  updateOptions();
467 }
468 
469 void QgsRasterFormatSaveOptionsWidget::optionsTableEnableDeleteButton()
470 {
471  mOptionsDeleteButton->setEnabled( mOptionsTable->currentRow() >= 0 );
472 }
473 
474 void QgsRasterFormatSaveOptionsWidget::on_mOptionsAddButton_clicked()
475 {
476  mOptionsTable->insertRow( mOptionsTable->rowCount() );
477  // select the added row
478  int newRow = mOptionsTable->rowCount() - 1;
479  QTableWidgetItem *item = new QTableWidgetItem();
480  mOptionsTable->setItem( newRow, 0, item );
481  mOptionsTable->setCurrentItem( item );
482 }
483 
484 void QgsRasterFormatSaveOptionsWidget::on_mOptionsDeleteButton_clicked()
485 {
486  if ( mOptionsTable->currentRow() >= 0 )
487  {
488  mOptionsTable->removeRow( mOptionsTable->currentRow() );
489  // select the previous row or the next one if there is no previous row
490  QTableWidgetItem *item = mOptionsTable->item( mOptionsTable->currentRow(), 0 );
491  mOptionsTable->setCurrentItem( item );
492  optionsTableChanged();
493  }
494 }
495 
496 
497 QString QgsRasterFormatSaveOptionsWidget::settingsKey( QString profileName ) const
498 {
499  if ( profileName != QLatin1String( "" ) )
500  profileName = "/profile_" + profileName;
501  else
502  profileName = "/profile_default" + profileName;
503  return mProvider + "/driverOptions/" + pseudoFormat().toLower() + profileName + "/create";
504 }
505 
506 QString QgsRasterFormatSaveOptionsWidget::currentProfileKey() const
507 {
508  return mProfileComboBox->currentData().toString();
509 }
510 
512 {
513  return mOptionsMap.value( currentProfileKey() ).trimmed().split( ' ', QString::SkipEmptyParts );
514 }
515 
516 QString QgsRasterFormatSaveOptionsWidget::createOptions( const QString &profileName ) const
517 {
518  QgsSettings mySettings;
519  return mySettings.value( settingsKey( profileName ), "" ).toString();
520 }
521 
522 void QgsRasterFormatSaveOptionsWidget::deleteCreateOptions( const QString &profileName )
523 {
524  QgsSettings mySettings;
525  mySettings.remove( settingsKey( profileName ) );
526 }
527 
528 void QgsRasterFormatSaveOptionsWidget::setCreateOptions()
529 {
530  QgsSettings mySettings;
531  QString myProfiles;
532  QMap< QString, QString >::const_iterator i = mOptionsMap.constBegin();
533  while ( i != mOptionsMap.constEnd() )
534  {
535  setCreateOptions( i.key(), i.value() );
536  myProfiles += i.key() + QStringLiteral( " " );
537  ++i;
538  }
539  mySettings.setValue( mProvider + "/driverOptions/" + pseudoFormat().toLower() + "/profiles",
540  myProfiles.trimmed() );
541  mySettings.setValue( mProvider + "/driverOptions/" + pseudoFormat().toLower() + "/defaultProfile",
542  currentProfileKey().trimmed() );
543 }
544 
545 void QgsRasterFormatSaveOptionsWidget::setCreateOptions( const QString &profileName, const QString &options )
546 {
547  QgsSettings mySettings;
548  mySettings.setValue( settingsKey( profileName ), options.trimmed() );
549 }
550 
551 void QgsRasterFormatSaveOptionsWidget::setCreateOptions( const QString &profileName, const QStringList &list )
552 {
553  setCreateOptions( profileName, list.join( QStringLiteral( " " ) ) );
554 }
555 
556 QStringList QgsRasterFormatSaveOptionsWidget::profiles() const
557 {
558  QgsSettings mySettings;
559  return mySettings.value( mProvider + "/driverOptions/" + pseudoFormat().toLower() + "/profiles", "" ).toString().trimmed().split( ' ', QString::SkipEmptyParts );
560 }
561 
562 void QgsRasterFormatSaveOptionsWidget::swapOptionsUI( int newIndex )
563 {
564  // set new page
565  int oldIndex;
566  if ( newIndex == -1 )
567  {
568  oldIndex = mOptionsStackedWidget->currentIndex();
569  newIndex = ( oldIndex + 1 ) % 2;
570  }
571  else
572  {
573  oldIndex = ( newIndex + 1 ) % 2;
574  }
575 
576  // resize pages to minimum - this works well with gdaltools merge ui, but not raster save as...
577  mOptionsStackedWidget->setCurrentIndex( newIndex );
578  mOptionsStackedWidget->widget( newIndex )->setSizePolicy(
579  QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
580  mOptionsStackedWidget->widget( oldIndex )->setSizePolicy(
581  QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) );
582  layout()->activate();
583 
584  updateOptions();
585 }
586 
587 void QgsRasterFormatSaveOptionsWidget::updateControls()
588 {
589  bool valid = mProvider == QLatin1String( "gdal" ) && mFormat != QLatin1String( "" );
590  mOptionsValidateButton->setEnabled( valid );
591  mOptionsHelpButton->setEnabled( valid );
592 }
593 
594 // map options label left mouse click to optionsToggle()
595 bool QgsRasterFormatSaveOptionsWidget::eventFilter( QObject *obj, QEvent *event )
596 {
597  if ( event->type() == QEvent::MouseButtonPress )
598  {
599  QMouseEvent *mouseEvent = static_cast<QMouseEvent *>( event );
600  if ( mouseEvent && ( mouseEvent->button() == Qt::RightButton ) )
601  {
602  QMenu *menu = nullptr;
603  QString text;
604  if ( mOptionsStackedWidget->currentIndex() == 0 )
605  text = tr( "Use simple interface" );
606  else
607  text = tr( "Use table interface" );
608  if ( obj->objectName() == QLatin1String( "mOptionsLineEdit" ) )
609  {
610  menu = mOptionsLineEdit->createStandardContextMenu();
611  menu->addSeparator();
612  }
613  else
614  menu = new QMenu( this );
615  QAction *action = new QAction( text, menu );
616  menu->addAction( action );
617  connect( action, &QAction::triggered, this, &QgsRasterFormatSaveOptionsWidget::swapOptionsUI );
618  menu->exec( mouseEvent->globalPos() );
619  delete menu;
620  return true;
621  }
622  }
623  // standard event processing
624  return QObject::eventFilter( obj, event );
625 }
626 
628 {
629  Q_UNUSED( event );
630  mOptionsTable->horizontalHeader()->resizeSection( 0, mOptionsTable->width() - 115 );
631  QgsDebugMsg( "done" );
632 }
633 
634 void QgsRasterFormatSaveOptionsWidget::setOptions( const QString &options )
635 {
636  mOptionsTable->blockSignals( true );
637  mOptionsTable->clearContents();
638 
639  QStringList values;
640  QStringList optionsList = options.trimmed().split( ' ', QString::SkipEmptyParts );
641  Q_FOREACH ( const QString &opt, optionsList )
642  {
643  int rowCount = mOptionsTable->rowCount();
644  mOptionsTable->insertRow( rowCount );
645 
646  values = opt.split( '=' );
647  if ( values.count() == 2 )
648  {
649  QTableWidgetItem *nameItem = new QTableWidgetItem( values.at( 0 ) );
650  mOptionsTable->setItem( rowCount, 0, nameItem );
651  QTableWidgetItem *valueItem = new QTableWidgetItem( values.at( 1 ) );
652  mOptionsTable->setItem( rowCount, 0, valueItem );
653  }
654  }
655 
656  mOptionsMap[ currentProfileKey()] = options.trimmed();
657  mOptionsLineEdit->setText( options.trimmed() );
658  mOptionsLineEdit->setCursorPosition( 0 );
659 
660  mOptionsTable->blockSignals( false );
661 }
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
QgsRasterFormatSaveOptionsWidget(QWidget *parent=nullptr, const QString &format="GTiff", QgsRasterFormatSaveOptionsWidget::Type type=Default, const QString &provider="gdal")
int bandCount() const
Get the number of bands in this layer.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
QString helpCreationOptionsFormat_t(QString format)
void setProvider(const QString &provider)
Set provider key, , it is used to determine list of available options.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void helpOptions()
Opens window with options desctiption for given provider and output format.
A generic dialog with layout and button box.
Definition: qgsdialog.h:32
virtual QString validatePyramidsConfigOptions(QgsRaster::RasterPyramidsFormat pyramidsFormat, const QStringList &configOptions, const QString &fileFormat)
Validates pyramid creation options for a specific dataset and destination format. ...
void updateProfiles()
Reloads profiles list from QGIS settings.
QString validateCreationOptionsFormat_t(const QStringList &createOptions, QString format)
QgsRasterDataProvider * dataProvider() override
void setValue(const QString &key, const QVariant &value, const QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
void setOptions(const QString &options)
Populate widget with user-defined options.
QString validateOptions(bool gui=true, bool reportOk=true)
Validates options correctness.
#define cast_to_fptr(f)
Definition: qgis.h:128
Raster namespace.
Definition: qgsraster.h:29
virtual void showEvent(QShowEvent *event) override
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
QVBoxLayout * layout()
Returns the central layout. Widgets added to it must have this dialog as parent.
Definition: qgsdialog.h:45
void setType(QgsRasterFormatSaveOptionsWidget::Type type=Default)
Set widget look and feel.
virtual QString validateCreationOptions(const QStringList &createOptions, const QString &format)
Validates creation options for a specific dataset and destination format.
void setFormat(const QString &format)
Set output raster format, it is used to determine list of available options.
QStringList options() const
Returns list of selected options.
void remove(const QString &key)
Removes the setting key and any sub-settings of key.