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