QGIS API Documentation 3.99.0-Master (09f76ad7019)
Loading...
Searching...
No Matches
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
20#include "qgsdialog.h"
21#include "qgsgdalutils.h"
22#include "qgslogger.h"
24#include "qgsrasterlayer.h"
25#include "qgssettings.h"
26
27#include <QContextMenuEvent>
28#include <QFileInfo>
29#include <QInputDialog>
30#include <QMenu>
31#include <QMessageBox>
32#include <QString>
33#include <QTextEdit>
34
35#include "moc_qgsrasterformatsaveoptionswidget.cpp"
36
37using namespace Qt::StringLiterals;
38
39QMap<QString, QStringList> QgsRasterFormatSaveOptionsWidget::sBuiltinProfiles;
40
41static const QString PYRAMID_JPEG_YCBCR_COMPRESSION( u"JPEG_QUALITY_OVERVIEW=75 COMPRESS_OVERVIEW=JPEG PHOTOMETRIC_OVERVIEW=YCBCR INTERLEAVE_OVERVIEW=PIXEL"_s );
42static const QString PYRAMID_JPEG_COMPRESSION( u"JPEG_QUALITY_OVERVIEW=75 COMPRESS_OVERVIEW=JPEG INTERLEAVE_OVERVIEW=PIXEL"_s );
43
44QgsRasterFormatSaveOptionsWidget::QgsRasterFormatSaveOptionsWidget( QWidget *parent, const QString &format, QgsRasterFormatSaveOptionsWidget::Type type, const QString &provider )
45 : QWidget( parent )
46 , mFormat( format )
47 , mProvider( provider )
48{
49 setupUi( this );
50
51 // Set the table minimum size to fit at least 4 rows
52 mOptionsTable->setMinimumSize( 200, mOptionsTable->verticalHeader()->defaultSectionSize() * 4 + mOptionsTable->horizontalHeader()->height() + 2 );
53
54 connect( mProfileNewButton, &QPushButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::mProfileNewButton_clicked );
55 connect( mProfileDeleteButton, &QPushButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::mProfileDeleteButton_clicked );
56 connect( mProfileResetButton, &QPushButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::mProfileResetButton_clicked );
57 connect( mOptionsAddButton, &QPushButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::mOptionsAddButton_clicked );
58 connect( mOptionsDeleteButton, &QPushButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::mOptionsDeleteButton_clicked );
59 connect( mOptionsLineEdit, &QLineEdit::editingFinished, this, &QgsRasterFormatSaveOptionsWidget::mOptionsLineEdit_editingFinished );
60
61 setType( type );
62
63 if ( sBuiltinProfiles.isEmpty() )
64 {
65 // key=profileKey values=format,profileName,options
66 sBuiltinProfiles[u"z_adefault"_s] = ( QStringList() << QString() << tr( "Default" ) << QString() );
67
68 // these GTiff profiles are based on Tim's benchmarks at
69 // http://linfiniti.com/2011/05/gdal-efficiency-of-various-compression-algorithms/
70 // big: no compression | medium: reasonable size/speed tradeoff | small: smallest size
71 sBuiltinProfiles[u"z_gtiff_1big"_s] = ( QStringList() << u"GTiff"_s << tr( "No Compression" ) << u"COMPRESS=NONE BIGTIFF=IF_NEEDED"_s );
72 sBuiltinProfiles[u"z_gtiff_2medium"_s] = ( QStringList() << u"GTiff"_s << tr( "Low Compression" ) << u"COMPRESS=PACKBITS"_s );
73 sBuiltinProfiles[u"z_gtiff_3small"_s] = ( QStringList() << u"GTiff"_s << tr( "High Compression" ) << u"COMPRESS=DEFLATE PREDICTOR=2 ZLEVEL=9"_s );
74 sBuiltinProfiles[u"z_gtiff_4jpeg"_s] = ( QStringList() << u"GTiff"_s << tr( "JPEG Compression" ) << u"COMPRESS=JPEG JPEG_QUALITY=75"_s );
75
76 // overview compression schemes for GTiff format, see
77 // http://www.gdal.org/gdaladdo.html and http://www.gdal.org/frmt_gtiff.html
78 // TODO - should we offer GDAL_TIFF_OVR_BLOCKSIZE option here or in QgsRasterPyramidsOptionsWidget ?
79 sBuiltinProfiles[u"z__pyramids_gtiff_1big"_s] = ( QStringList() << u"_pyramids"_s << tr( "No Compression" ) << u"COMPRESS_OVERVIEW=NONE BIGTIFF_OVERVIEW=IF_NEEDED"_s );
80 sBuiltinProfiles[u"z__pyramids_gtiff_2medium"_s] = ( QStringList() << u"_pyramids"_s << tr( "Low Compression" ) << u"COMPRESS_OVERVIEW=PACKBITS"_s );
81 sBuiltinProfiles[u"z__pyramids_gtiff_3small"_s] = ( QStringList() << u"_pyramids"_s << tr( "High Compression" ) << u"COMPRESS_OVERVIEW=DEFLATE PREDICTOR_OVERVIEW=2 ZLEVEL=9"_s ); // how to set zlevel?
82 sBuiltinProfiles[u"z__pyramids_gtiff_4jpeg"_s] = ( QStringList() << u"_pyramids"_s << tr( "JPEG Compression" ) << PYRAMID_JPEG_YCBCR_COMPRESSION );
83 }
84
85 connect( mProfileComboBox, &QComboBox::currentTextChanged, this, &QgsRasterFormatSaveOptionsWidget::updateOptions );
86 connect( mOptionsTable, &QTableWidget::cellChanged, this, &QgsRasterFormatSaveOptionsWidget::optionsTableChanged );
87 connect( mOptionsHelpButton, &QAbstractButton::clicked, this, &QgsRasterFormatSaveOptionsWidget::helpOptions );
88 connect( mOptionsValidateButton, &QAbstractButton::clicked, this, [this] { validateOptions(); } );
89
90 // Install an eventFilter to customize the default QLineEdit contextMenu with an added swapOptionsUI action
91 mOptionsLineEdit->installEventFilter( this );
92
93 // Use a Custom Context menu for the widget to swap between modes (table / lineedit)
94 setContextMenuPolicy( Qt::CustomContextMenu );
95 connect( this, &QWidget::customContextMenuRequested, this, [this]( QPoint pos ) {
96 QMenu menu( this );
97 QString text;
98 if ( mTableWidget->isVisible() )
99 text = tr( "Use Simple Interface" );
100 else
101 text = tr( "Use Table Interface" );
102 QAction *swapAction = menu.addAction( text );
103 connect( swapAction, &QAction::triggered, this, [this]() { swapOptionsUI( -1 ); } );
104 menu.exec( this->mapToGlobal( pos ) );
105 } );
106
107
108 updateControls();
110
111 QgsDebugMsgLevel( u"done"_s, 3 );
112}
113
115{
116 mFormat = format;
117 updateControls();
119}
120
122{
123 mProvider = provider;
124 updateControls();
125}
126
127// show/hide widgets - we need this function if widget is used in creator
129{
130 const QList<QWidget *> widgets = this->findChildren<QWidget *>();
131 if ( ( type == Table ) || ( type == LineEdit ) )
132 {
133 // hide all controls, except stacked widget
134 const auto constWidgets = widgets;
135 for ( QWidget *widget : constWidgets )
136 widget->setVisible( false );
137 mOptionsWidget->setVisible( true );
138
139 // show relevant page
140 if ( type == Table )
141 swapOptionsUI( 0 );
142 else
143 swapOptionsUI( 1 );
144 }
145 else
146 {
147 // show all widgets, except profile buttons (unless Full)
148 const auto constWidgets = widgets;
149 for ( QWidget *widget : constWidgets )
150 widget->setVisible( true );
151 if ( type != Full )
152 mProfileButtons->setVisible( false );
153
154 // show elevant page
155 if ( type == ProfileLineEdit )
156 swapOptionsUI( 1 );
157 else
158 swapOptionsUI( 0 );
159 }
160}
161
162QString QgsRasterFormatSaveOptionsWidget::pseudoFormat() const
163{
164 return mPyramids ? u"_pyramids"_s : mFormat;
165}
166
168{
169 // build profiles list = user + builtin(last)
170 const QString format = pseudoFormat();
171 QStringList profileKeys = profiles();
172 QMapIterator<QString, QStringList> it( sBuiltinProfiles );
173 while ( it.hasNext() )
174 {
175 it.next();
176 const QString profileKey = it.key();
177 if ( !profileKeys.contains( profileKey ) && !it.value().isEmpty() )
178 {
179 // insert key if is for all formats or this format (GTiff)
180 if ( it.value()[0].isEmpty() || it.value()[0] == format )
181 {
182 profileKeys.insert( 0, profileKey );
183 }
184 }
185 }
186 std::sort( profileKeys.begin(), profileKeys.end() );
187
188 // populate mOptionsMap and mProfileComboBox
189 mOptionsMap.clear();
190 mProfileComboBox->blockSignals( true );
191 mProfileComboBox->clear();
192 const auto constProfileKeys = profileKeys;
193 for ( const QString &profileKey : constProfileKeys )
194 {
195 QString profileName, profileOptions;
196 profileOptions = creationOptions( profileKey );
197 if ( sBuiltinProfiles.contains( profileKey ) )
198 {
199 profileName = sBuiltinProfiles[profileKey][1];
200 if ( profileOptions.isEmpty() )
201 profileOptions = sBuiltinProfiles[profileKey][2];
202 }
203 else
204 {
205 profileName = profileKey;
206 }
207 mOptionsMap[profileKey] = profileOptions;
208 mProfileComboBox->addItem( profileName, profileKey );
209 }
210
211 // update UI
212 mProfileComboBox->blockSignals( false );
213 // mProfileComboBox->setCurrentIndex( 0 );
214 const QgsSettings mySettings;
215 mProfileComboBox->setCurrentIndex( mProfileComboBox->findData( mySettings.value(
216 mProvider + "/driverOptions/" + format.toLower() + "/defaultProfile",
217 "z_adefault"
218 ) ) );
219 updateOptions();
220}
221
222void QgsRasterFormatSaveOptionsWidget::updateOptions()
223{
224 mBlockOptionUpdates++;
225 QString myOptions = mOptionsMap.value( currentProfileKey() );
226 QStringList myOptionsList = myOptions.trimmed().split( ' ', Qt::SkipEmptyParts );
227
228 // If the default JPEG compression profile was selected, remove PHOTOMETRIC_OVERVIEW=YCBCR
229 // if the raster is not RGB. Otherwise this is bound to fail afterwards.
230 if ( mRasterLayer && mRasterLayer->bandCount() != 3 && myOptions == PYRAMID_JPEG_YCBCR_COMPRESSION )
231 {
232 myOptions = PYRAMID_JPEG_COMPRESSION;
233 }
234
235 if ( mTableWidget->isVisible() )
236 {
237 mOptionsTable->setRowCount( 0 );
238 for ( int i = 0; i < myOptionsList.count(); i++ )
239 {
240 QStringList key_value = myOptionsList[i].split( '=' );
241 if ( key_value.count() == 2 )
242 {
243 mOptionsTable->insertRow( i );
244 mOptionsTable->setItem( i, 0, new QTableWidgetItem( key_value[0] ) );
245 mOptionsTable->setItem( i, 1, new QTableWidgetItem( key_value[1] ) );
246 }
247 }
248 }
249 else
250 {
251 mOptionsLineEdit->setText( myOptions );
252 mOptionsLineEdit->setCursorPosition( 0 );
253 }
254
255 mBlockOptionUpdates--;
256 emit optionsChanged();
257}
258
260{
261 setCreationOptions();
262}
263
265{
266 QString message;
267
268 if ( mProvider == "gdal"_L1 && !mFormat.isEmpty() && !mPyramids )
269 {
270 message = QgsGdalUtils::helpCreationOptionsFormat( mFormat );
271 if ( message.isEmpty() )
272 message = tr( "Cannot get create options for driver %1" ).arg( mFormat );
273 }
274 else if ( mProvider == "gdal"_L1 && mPyramids )
275 {
276 message = tr( "For details on pyramids options please see the following pages" );
277 message += "\n\nhttps://gdal.org/programs/gdaladdo.html\n\nhttps://gdal.org/drivers/raster/gtiff.html"_L1;
278 }
279 else
280 message = tr( "No help available" );
281
282 // show simple non-modal dialog - should we make the basic xml prettier?
283 QgsDialog *dlg = new QgsDialog( this );
284 dlg->setWindowTitle( tr( "Create Options for %1" ).arg( mFormat ) );
285 QTextEdit *textEdit = new QTextEdit( dlg );
286 textEdit->setReadOnly( true );
287 // message = tr( "Create Options:\n\n%1" ).arg( message );
288 textEdit->setText( message );
289 dlg->layout()->addWidget( textEdit );
290 dlg->resize( 600, 400 );
291#ifdef Q_OS_MAC
292 dlg->exec(); //modal
293#else
294 dlg->show(); //non modal
295#endif
296}
297
299{
300 const QStringList creationOptions = options();
301 QString message;
302
303 QgsDebugMsgLevel( u"layer: [%1] file: [%2] format: [%3]"_s.arg( mRasterLayer ? mRasterLayer->id() : "none", mRasterFileName, mFormat ), 2 );
304 // if no rasterLayer is defined, but we have a raster fileName, then create a temp. rasterLayer to validate options
305 // ideally we should keep it for future access, but this is trickier
306 QgsRasterLayer *rasterLayer = mRasterLayer;
307 bool tmpLayer = false;
308 if ( !( mRasterLayer && rasterLayer->dataProvider() ) && !mRasterFileName.isNull() )
309 {
310 tmpLayer = true;
312 options.skipCrsValidation = true;
313 rasterLayer = new QgsRasterLayer( mRasterFileName, QFileInfo( mRasterFileName ).baseName(), u"gdal"_s, options );
314 }
315
316 if ( mProvider == "gdal"_L1 && mPyramids )
317 {
318 if ( rasterLayer && rasterLayer->dataProvider() )
319 {
320 QgsDebugMsgLevel( u"calling validate pyramids on layer's data provider"_s, 2 );
321 message = rasterLayer->dataProvider()->validatePyramidsConfigOptions( mPyramidsFormat, creationOptions, mFormat );
322 }
323 else
324 {
325 message = tr( "cannot validate pyramid options" );
326 }
327 }
328 else if ( !creationOptions.isEmpty() && mProvider == "gdal"_L1 && !mFormat.isEmpty() )
329 {
330 if ( rasterLayer && rasterLayer->dataProvider() )
331 {
332 QgsDebugMsgLevel( u"calling validate on layer's data provider"_s, 2 );
333 message = rasterLayer->dataProvider()->validateCreationOptions( creationOptions, mFormat );
334 }
335 else
336 {
337 // get validateCreationOptionsFormat() function ptr for provider
338 message = QgsGdalUtils::validateCreationOptionsFormat( creationOptions, mFormat );
339 }
340 }
341 else if ( !creationOptions.isEmpty() )
342 {
343 QMessageBox::information( this, QString(), tr( "Cannot validate creation options." ), QMessageBox::Close );
344 if ( tmpLayer )
345 delete rasterLayer;
346 return QString();
347 }
348
349 if ( gui )
350 {
351 if ( message.isNull() )
352 {
353 if ( reportOK )
354 QMessageBox::information( this, QString(), tr( "Valid" ), QMessageBox::Close );
355 }
356 else
357 {
358 QMessageBox::warning( this, QString(), 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 );
359 }
360 }
361
362 if ( tmpLayer )
363 delete rasterLayer;
364
365 return message;
366}
367
368void QgsRasterFormatSaveOptionsWidget::optionsTableChanged()
369{
370 if ( mBlockOptionUpdates )
371 return;
372
373 QTableWidgetItem *key, *value;
374 QString options;
375 for ( int i = 0; i < mOptionsTable->rowCount(); i++ )
376 {
377 key = mOptionsTable->item( i, 0 );
378 if ( !key || key->text().isEmpty() )
379 continue;
380 value = mOptionsTable->item( i, 1 );
381 if ( !value || value->text().isEmpty() )
382 continue;
383 options += key->text() + '=' + value->text() + ' ';
384 }
385 options = options.trimmed();
386 mOptionsMap[currentProfileKey()] = options;
387 mOptionsLineEdit->setText( options );
388 mOptionsLineEdit->setCursorPosition( 0 );
389}
390
391void QgsRasterFormatSaveOptionsWidget::mOptionsLineEdit_editingFinished()
392{
393 mOptionsMap[currentProfileKey()] = mOptionsLineEdit->text().trimmed();
394}
395
396void QgsRasterFormatSaveOptionsWidget::mProfileNewButton_clicked()
397{
398 QString profileName = QInputDialog::getText( this, QString(), tr( "Profile name:" ) );
399 if ( !profileName.isEmpty() )
400 {
401 profileName = profileName.trimmed();
402 mOptionsMap[profileName] = QString();
403 mProfileComboBox->addItem( profileName, profileName );
404 mProfileComboBox->setCurrentIndex( mProfileComboBox->count() - 1 );
405 }
406}
407
408void QgsRasterFormatSaveOptionsWidget::mProfileDeleteButton_clicked()
409{
410 const int index = mProfileComboBox->currentIndex();
411 const QString profileKey = currentProfileKey();
412 if ( index != -1 && !sBuiltinProfiles.contains( profileKey ) )
413 {
414 mOptionsMap.remove( profileKey );
415 mProfileComboBox->removeItem( index );
416 }
417}
418
419void QgsRasterFormatSaveOptionsWidget::mProfileResetButton_clicked()
420{
421 const QString profileKey = currentProfileKey();
422 if ( sBuiltinProfiles.contains( profileKey ) )
423 {
424 mOptionsMap[profileKey] = sBuiltinProfiles[profileKey][2];
425 }
426 else
427 {
428 mOptionsMap[profileKey] = QString();
429 }
430 mOptionsLineEdit->setText( mOptionsMap.value( currentProfileKey() ) );
431 mOptionsLineEdit->setCursorPosition( 0 );
432 updateOptions();
433}
434
435void QgsRasterFormatSaveOptionsWidget::optionsTableEnableDeleteButton()
436{
437 mOptionsDeleteButton->setEnabled( mOptionsTable->currentRow() >= 0 );
438}
439
440void QgsRasterFormatSaveOptionsWidget::mOptionsAddButton_clicked()
441{
442 mOptionsTable->insertRow( mOptionsTable->rowCount() );
443 // select the added row
444 const int newRow = mOptionsTable->rowCount() - 1;
445 QTableWidgetItem *item = new QTableWidgetItem();
446 mOptionsTable->setItem( newRow, 0, item );
447 mOptionsTable->setCurrentItem( item );
448}
449
450void QgsRasterFormatSaveOptionsWidget::mOptionsDeleteButton_clicked()
451{
452 if ( mOptionsTable->currentRow() >= 0 )
453 {
454 mOptionsTable->removeRow( mOptionsTable->currentRow() );
455 // select the previous row or the next one if there is no previous row
456 QTableWidgetItem *item = mOptionsTable->item( mOptionsTable->currentRow(), 0 );
457 mOptionsTable->setCurrentItem( item );
458 optionsTableChanged();
459 }
460}
461
462QString QgsRasterFormatSaveOptionsWidget::settingsKey( QString profileName ) const
463{
464 if ( !profileName.isEmpty() )
465 profileName = "/profile_" + profileName;
466 else
467 profileName = "/profile_default" + profileName;
468 return mProvider + "/driverOptions/" + pseudoFormat().toLower() + profileName + "/create";
469}
470
471QString QgsRasterFormatSaveOptionsWidget::currentProfileKey() const
472{
473 return mProfileComboBox->currentData().toString();
474}
475
477{
478 return mOptionsMap.value( currentProfileKey() ).trimmed().split( ' ', Qt::SkipEmptyParts );
479}
480
481QString QgsRasterFormatSaveOptionsWidget::creationOptions( const QString &profileName ) const
482{
483 const QgsSettings mySettings;
484 return mySettings.value( settingsKey( profileName ), "" ).toString();
485}
486
487void QgsRasterFormatSaveOptionsWidget::deleteCreationOptions( const QString &profileName )
488{
489 QgsSettings mySettings;
490 mySettings.remove( settingsKey( profileName ) );
491}
492
493void QgsRasterFormatSaveOptionsWidget::setCreationOptions()
494{
495 QgsSettings mySettings;
496 QStringList myProfiles;
497 QMap<QString, QString>::const_iterator i = mOptionsMap.constBegin();
498 while ( i != mOptionsMap.constEnd() )
499 {
500 setCreationOptions( i.key(), i.value() );
501 myProfiles << i.key();
502 ++i;
503 }
504 mySettings.setValue( mProvider + "/driverOptions/" + pseudoFormat().toLower() + "/profiles", myProfiles );
505 mySettings.setValue( mProvider + "/driverOptions/" + pseudoFormat().toLower() + "/defaultProfile", currentProfileKey().trimmed() );
506}
507
508void QgsRasterFormatSaveOptionsWidget::setCreationOptions( const QString &profileName, const QString &options )
509{
510 QgsSettings mySettings;
511 mySettings.setValue( settingsKey( profileName ), options.trimmed() );
512}
513
514void QgsRasterFormatSaveOptionsWidget::setCreationOptions( const QString &profileName, const QStringList &options )
515{
516 setCreationOptions( profileName, options.join( ' '_L1 ) );
517}
518
519QStringList QgsRasterFormatSaveOptionsWidget::profiles() const
520{
521 const QgsSettings mySettings;
522 return mySettings.value( mProvider + "/driverOptions/" + pseudoFormat().toLower() + "/profiles", "" ).toStringList();
523}
524
525void QgsRasterFormatSaveOptionsWidget::swapOptionsUI( int newIndex )
526{
527 // If newIndex == -1, toggle option mode
528 // If newIndex == 0, set option mode to Table
529 // If newIndex == 1, set option to lineEdit
530 bool lineEditMode = mOptionsLineEdit->isVisible();
531 mOptionsLineEdit->setVisible( ( newIndex == -1 && !lineEditMode ) || newIndex == 1 );
532 mTableWidget->setVisible( ( newIndex == -1 && lineEditMode ) || newIndex == 0 );
533 updateOptions();
534}
535
536void QgsRasterFormatSaveOptionsWidget::updateControls()
537{
538 const bool valid = mProvider == "gdal"_L1 && !mFormat.isEmpty();
539 mOptionsValidateButton->setEnabled( valid );
540 mOptionsHelpButton->setEnabled( valid );
541}
542
543// map options label left mouse click to optionsToggle()
544bool QgsRasterFormatSaveOptionsWidget::eventFilter( QObject *obj, QEvent *event )
545{
546 if ( event->type() == QEvent::ContextMenu )
547 {
548 QContextMenuEvent *contextEvent = static_cast<QContextMenuEvent *>( event );
549 QMenu *menu = nullptr;
550 menu = mOptionsLineEdit->createStandardContextMenu();
551 menu->addSeparator();
552 QAction *action = new QAction( tr( "Use Table Interface" ), menu );
553 menu->addAction( action );
554 connect( action, &QAction::triggered, this, [this] { swapOptionsUI( 0 ); } );
555 menu->exec( contextEvent->globalPos() );
556 delete menu;
557 return true;
558 }
559 // standard event processing
560 return QObject::eventFilter( obj, event );
561}
562
564{
565 Q_UNUSED( event )
566 updateOptions();
567 mOptionsTable->horizontalHeader()->resizeSection( 0, mOptionsTable->width() - 115 );
568 QgsDebugMsgLevel( u"done"_s, 3 );
569}
570
572{
573 mBlockOptionUpdates++;
574 mOptionsTable->clearContents();
575
576 const QStringList optionsList = options.trimmed().split( ' ', Qt::SkipEmptyParts );
577 for ( const QString &opt : optionsList )
578 {
579 const int rowCount = mOptionsTable->rowCount();
580 mOptionsTable->insertRow( rowCount );
581
582 const QStringList values = opt.split( '=' );
583 if ( values.count() == 2 )
584 {
585 QTableWidgetItem *nameItem = new QTableWidgetItem( values.at( 0 ) );
586 mOptionsTable->setItem( rowCount, 0, nameItem );
587 QTableWidgetItem *valueItem = new QTableWidgetItem( values.at( 1 ) );
588 mOptionsTable->setItem( rowCount, 1, valueItem );
589 }
590 }
591
592 // reset to no profile index, otherwise we are changing the definition of whichever profile
593 // is currently selected...
594 mProfileComboBox->setCurrentIndex( 0 );
595
596 mOptionsMap[currentProfileKey()] = options.trimmed();
597 mOptionsLineEdit->setText( options.trimmed() );
598 mOptionsLineEdit->setCursorPosition( 0 );
599
600 mBlockOptionUpdates--;
601}
A generic dialog with layout and button box.
Definition qgsdialog.h:34
QVBoxLayout * layout()
Returns the central layout. Widgets added to it must have this dialog as parent.
Definition qgsdialog.h:43
static QString helpCreationOptionsFormat(const QString &format)
Gets creation options metadata for a given format.
static QString validateCreationOptionsFormat(const QStringList &creationOptions, const QString &format)
Validates creation options for a given format, regardless of layer.
virtual QString validateCreationOptions(const QStringList &createOptions, const QString &format)
Validates creation options for a specific dataset and destination format.
virtual QString validatePyramidsConfigOptions(Qgis::RasterPyramidFormat pyramidsFormat, const QStringList &configOptions, const QString &fileFormat)
Validates pyramid 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.
void helpOptions()
Opens window with options description for given provider and output format.
void setOptions(const QString &options)
Populate widget with user-defined options.
void updateProfiles()
Reloads profiles list from QGIS settings.
QgsRasterFormatSaveOptionsWidget(QWidget *parent SIP_TRANSFERTHIS=nullptr, const QString &format="GTiff", QgsRasterFormatSaveOptionsWidget::Type type=Default, const QString &provider="gdal")
QString validateOptions(bool gui=true, bool reportOk=true)
Validates options correctness.
void setProvider(const QString &provider)
Set provider key, , it is used to determine list of available options.
void optionsChanged()
Emitted when the options configured in the widget are changed.
QStringList options() const
Returns list of selected options.
void setType(QgsRasterFormatSaveOptionsWidget::Type type=Default)
Set widget look and feel.
Represents a raster layer.
int bandCount() const
Returns the number of bands in this layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
Setting options for loading raster layers.