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