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