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