26 #include <QInputDialog> 27 #include <QMessageBox> 29 #include <QMouseEvent> 33 QMap< QString, QStringList > QgsRasterFormatSaveOptionsWidget::sBuiltinProfiles;
35 static const QString PYRAMID_JPEG_YCBCR_COMPRESSION( QStringLiteral(
"JPEG_QUALITY_OVERVIEW=75 COMPRESS_OVERVIEW=JPEG PHOTOMETRIC_OVERVIEW=YCBCR INTERLEAVE_OVERVIEW=PIXEL" ) );
36 static const QString PYRAMID_JPEG_COMPRESSION( QStringLiteral(
"JPEG_QUALITY_OVERVIEW=75 COMPRESS_OVERVIEW=JPEG INTERLEAVE_OVERVIEW=PIXEL" ) );
42 , mProvider( provider )
45 connect( mProfileNewButton, &QPushButton::clicked,
this, &QgsRasterFormatSaveOptionsWidget::mProfileNewButton_clicked );
46 connect( mProfileDeleteButton, &QPushButton::clicked,
this, &QgsRasterFormatSaveOptionsWidget::mProfileDeleteButton_clicked );
47 connect( mProfileResetButton, &QPushButton::clicked,
this, &QgsRasterFormatSaveOptionsWidget::mProfileResetButton_clicked );
48 connect( mOptionsAddButton, &QPushButton::clicked,
this, &QgsRasterFormatSaveOptionsWidget::mOptionsAddButton_clicked );
49 connect( mOptionsDeleteButton, &QPushButton::clicked,
this, &QgsRasterFormatSaveOptionsWidget::mOptionsDeleteButton_clicked );
50 connect( mOptionsLineEdit, &QLineEdit::editingFinished,
this, &QgsRasterFormatSaveOptionsWidget::mOptionsLineEdit_editingFinished );
54 if ( sBuiltinProfiles.isEmpty() )
57 sBuiltinProfiles[ QStringLiteral(
"z_adefault" )] = ( QStringList() << QString() << tr(
"Default" ) << QString() );
62 sBuiltinProfiles[ QStringLiteral(
"z_gtiff_1big" )] =
63 ( QStringList() << QStringLiteral(
"GTiff" ) << tr(
"No Compression" )
64 << QStringLiteral(
"COMPRESS=NONE BIGTIFF=IF_NEEDED" ) );
65 sBuiltinProfiles[ QStringLiteral(
"z_gtiff_2medium" )] =
66 ( QStringList() << QStringLiteral(
"GTiff" ) << tr(
"Low Compression" )
67 << QStringLiteral(
"COMPRESS=PACKBITS" ) );
68 sBuiltinProfiles[ QStringLiteral(
"z_gtiff_3small" )] =
69 ( QStringList() << QStringLiteral(
"GTiff" ) << tr(
"High Compression" )
70 << QStringLiteral(
"COMPRESS=DEFLATE PREDICTOR=2 ZLEVEL=9" ) );
71 sBuiltinProfiles[ QStringLiteral(
"z_gtiff_4jpeg" )] =
72 ( QStringList() << QStringLiteral(
"GTiff" ) << tr(
"JPEG Compression" )
73 << QStringLiteral(
"COMPRESS=JPEG JPEG_QUALITY=75" ) );
78 sBuiltinProfiles[ QStringLiteral(
"z__pyramids_gtiff_1big" )] =
79 ( QStringList() << QStringLiteral(
"_pyramids" ) << tr(
"No Compression" )
80 << QStringLiteral(
"COMPRESS_OVERVIEW=NONE BIGTIFF_OVERVIEW=IF_NEEDED" ) );
81 sBuiltinProfiles[ QStringLiteral(
"z__pyramids_gtiff_2medium" )] =
82 ( QStringList() << QStringLiteral(
"_pyramids" ) << tr(
"Low Compression" )
83 << QStringLiteral(
"COMPRESS_OVERVIEW=PACKBITS" ) );
84 sBuiltinProfiles[ QStringLiteral(
"z__pyramids_gtiff_3small" )] =
85 ( QStringList() << QStringLiteral(
"_pyramids" ) << tr(
"High Compression" )
86 << QStringLiteral(
"COMPRESS_OVERVIEW=DEFLATE PREDICTOR_OVERVIEW=2 ZLEVEL=9" ) );
87 sBuiltinProfiles[ QStringLiteral(
"z__pyramids_gtiff_4jpeg" )] =
88 ( QStringList() << QStringLiteral(
"_pyramids" ) << tr(
"JPEG Compression" )
89 << PYRAMID_JPEG_YCBCR_COMPRESSION );
92 connect( mProfileComboBox,
static_cast<void ( QComboBox::* )(
const QString & )
>( &QComboBox::currentIndexChanged ),
93 this, &QgsRasterFormatSaveOptionsWidget::updateOptions );
94 connect( mOptionsTable, &QTableWidget::cellChanged,
this, &QgsRasterFormatSaveOptionsWidget::optionsTableChanged );
96 connect( mOptionsValidateButton, &QAbstractButton::clicked,
this, [ = ] {
validateOptions(); } );
100 mOptionsLineEdit->installEventFilter(
this );
101 mOptionsStackedWidget->installEventFilter(
this );
118 mProvider = provider;
125 QList< QWidget * > widgets = this->findChildren<QWidget *>();
129 const auto constWidgets = widgets;
130 for ( QWidget *widget : constWidgets )
131 widget->setVisible(
false );
132 mOptionsStackedWidget->setVisible(
true );
133 const auto children { mOptionsStackedWidget->findChildren<QWidget *>() };
134 for ( QWidget *widget : children )
135 widget->setVisible(
true );
146 const auto constWidgets = widgets;
147 for ( QWidget *widget : constWidgets )
148 widget->setVisible(
true );
150 mProfileButtons->setVisible(
false );
158 QString QgsRasterFormatSaveOptionsWidget::pseudoFormat()
const 160 return mPyramids ? QStringLiteral(
"_pyramids" ) : mFormat;
166 QString format = pseudoFormat();
167 QStringList profileKeys = profiles();
168 QMapIterator<QString, QStringList> it( sBuiltinProfiles );
169 while ( it.hasNext() )
172 QString profileKey = it.key();
173 if ( ! profileKeys.contains( profileKey ) && !it.value().isEmpty() )
176 if ( it.value()[0].isEmpty() || it.value()[0] == format )
178 profileKeys.insert( 0, profileKey );
182 std::sort( profileKeys.begin(), profileKeys.end() );
186 mProfileComboBox->blockSignals(
true );
187 mProfileComboBox->clear();
188 const auto constProfileKeys = profileKeys;
189 for (
const QString &profileKey : constProfileKeys )
191 QString profileName, profileOptions;
192 profileOptions = createOptions( profileKey );
193 if ( sBuiltinProfiles.contains( profileKey ) )
195 profileName = sBuiltinProfiles[ profileKey ][ 1 ];
196 if ( profileOptions.isEmpty() )
197 profileOptions = sBuiltinProfiles[ profileKey ][ 2 ];
201 profileName = profileKey;
203 mOptionsMap[ profileKey ] = profileOptions;
204 mProfileComboBox->addItem( profileName, profileKey );
208 mProfileComboBox->blockSignals(
false );
211 mProfileComboBox->setCurrentIndex( mProfileComboBox->findData( mySettings.
value(
212 mProvider +
"/driverOptions/" + format.toLower() +
"/defaultProfile",
217 void QgsRasterFormatSaveOptionsWidget::updateOptions()
219 QString myOptions = mOptionsMap.value( currentProfileKey() );
220 QStringList myOptionsList = myOptions.trimmed().split(
' ', QString::SkipEmptyParts );
224 if ( mRasterLayer && mRasterLayer->
bandCount() != 3 &&
225 myOptions == PYRAMID_JPEG_YCBCR_COMPRESSION )
227 myOptions = PYRAMID_JPEG_COMPRESSION;
230 if ( mOptionsStackedWidget->currentIndex() == 0 )
232 mOptionsTable->setRowCount( 0 );
233 for (
int i = 0; i < myOptionsList.count(); i++ )
235 QStringList key_value = myOptionsList[i].split(
'=' );
236 if ( key_value.count() == 2 )
238 mOptionsTable->insertRow( i );
239 mOptionsTable->setItem( i, 0,
new QTableWidgetItem( key_value[0] ) );
240 mOptionsTable->setItem( i, 1,
new QTableWidgetItem( key_value[1] ) );
246 mOptionsLineEdit->setText( myOptions );
247 mOptionsLineEdit->setCursorPosition( 0 );
266 if ( mProvider == QLatin1String(
"gdal" ) && !mFormat.isEmpty() && ! mPyramids )
274 if ( helpCreationOptionsFormat )
276 message = helpCreationOptionsFormat( mFormat );
280 message = library->fileName() +
" does not have helpCreationOptionsFormat";
284 message = QStringLiteral(
"cannot load provider library %1" ).arg( mProvider );
287 if ( message.isEmpty() )
288 message = tr(
"Cannot get create options for driver %1" ).arg( mFormat );
290 else if ( mProvider == QLatin1String(
"gdal" ) && mPyramids )
292 message = tr(
"For details on pyramids options please see the following pages" );
293 message += QLatin1String(
"\n\nhttp://www.gdal.org/gdaladdo.html\n\nhttp://www.gdal.org/frmt_gtiff.html" );
296 message = tr(
"No help available" );
300 QTextEdit *textEdit =
new QTextEdit( dlg );
301 textEdit->setReadOnly(
true );
303 textEdit->setText( message );
304 dlg->
layout()->addWidget( textEdit );
305 dlg->resize( 600, 400 );
315 QStringList createOptions =
options();
318 QgsDebugMsg( QStringLiteral(
"layer: [%1] file: [%2] format: [%3]" ).arg( mRasterLayer ? mRasterLayer->
id() :
"none", mRasterFileName, mFormat ) );
322 bool tmpLayer =
false;
323 if ( !( mRasterLayer && rasterLayer->
dataProvider() ) && ! mRasterFileName.isNull() )
329 QString defaultProjectionOption = settings.
value( QStringLiteral(
"Projections/defaultBehavior" ),
"prompt" ).toString();
330 if ( settings.
value( QStringLiteral(
"Projections/defaultBehavior" ),
"prompt" ).toString() == QLatin1String(
"prompt" ) )
332 settings.
setValue( QStringLiteral(
"Projections/defaultBehavior" ),
"useProject" );
335 rasterLayer =
new QgsRasterLayer( mRasterFileName, QFileInfo( mRasterFileName ).baseName(), QStringLiteral(
"gdal" ) );
337 if ( defaultProjectionOption == QLatin1String(
"prompt" ) )
339 settings.
setValue( QStringLiteral(
"Projections/defaultBehavior" ), defaultProjectionOption );
343 if ( mProvider == QLatin1String(
"gdal" ) && mPyramids )
347 QgsDebugMsg( QStringLiteral(
"calling validate pyramids on layer's data provider" ) );
352 message = tr(
"cannot validate pyramid options" );
355 else if ( !createOptions.isEmpty() && mProvider == QLatin1String(
"gdal" ) && !mFormat.isEmpty() )
359 QgsDebugMsg( QStringLiteral(
"calling validate on layer's data provider" ) );
370 if ( validateCreationOptionsFormat )
372 message = validateCreationOptionsFormat( createOptions, mFormat );
376 message = library->fileName() +
" does not have validateCreationOptionsFormat";
380 message = QStringLiteral(
"cannot load provider library %1" ).arg( mProvider );
383 else if ( ! createOptions.isEmpty() )
385 QMessageBox::information(
this, QString(), tr(
"Cannot validate creation options." ), QMessageBox::Close );
393 if ( message.isNull() )
396 QMessageBox::information(
this, QString(), tr(
"Valid" ), QMessageBox::Close );
400 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 );
410 void QgsRasterFormatSaveOptionsWidget::optionsTableChanged()
412 QTableWidgetItem *key, *value;
414 for (
int i = 0; i < mOptionsTable->rowCount(); i++ )
416 key = mOptionsTable->item( i, 0 );
417 if ( ! key || key->text().isEmpty() )
419 value = mOptionsTable->item( i, 1 );
420 if ( ! value || value->text().isEmpty() )
422 options += key->text() +
'=' + value->text() +
' ';
424 options = options.trimmed();
425 mOptionsMap[ currentProfileKey()] =
options;
426 mOptionsLineEdit->setText( options );
427 mOptionsLineEdit->setCursorPosition( 0 );
430 void QgsRasterFormatSaveOptionsWidget::mOptionsLineEdit_editingFinished()
432 mOptionsMap[ currentProfileKey()] = mOptionsLineEdit->text().trimmed();
435 void QgsRasterFormatSaveOptionsWidget::mProfileNewButton_clicked()
437 QString profileName = QInputDialog::getText(
this, QString(), tr(
"Profile name:" ) );
438 if ( ! profileName.isEmpty() )
440 profileName = profileName.trimmed();
441 mOptionsMap[ profileName ] = QString();
442 mProfileComboBox->addItem( profileName, profileName );
443 mProfileComboBox->setCurrentIndex( mProfileComboBox->count() - 1 );
447 void QgsRasterFormatSaveOptionsWidget::mProfileDeleteButton_clicked()
449 int index = mProfileComboBox->currentIndex();
450 QString profileKey = currentProfileKey();
451 if ( index != -1 && ! sBuiltinProfiles.contains( profileKey ) )
453 mOptionsMap.remove( profileKey );
454 mProfileComboBox->removeItem( index );
458 void QgsRasterFormatSaveOptionsWidget::mProfileResetButton_clicked()
460 QString profileKey = currentProfileKey();
461 if ( sBuiltinProfiles.contains( profileKey ) )
463 mOptionsMap[ profileKey ] = sBuiltinProfiles[ profileKey ][ 2 ];
467 mOptionsMap[ profileKey ] = QString();
469 mOptionsLineEdit->setText( mOptionsMap.value( currentProfileKey() ) );
470 mOptionsLineEdit->setCursorPosition( 0 );
474 void QgsRasterFormatSaveOptionsWidget::optionsTableEnableDeleteButton()
476 mOptionsDeleteButton->setEnabled( mOptionsTable->currentRow() >= 0 );
479 void QgsRasterFormatSaveOptionsWidget::mOptionsAddButton_clicked()
481 mOptionsTable->insertRow( mOptionsTable->rowCount() );
483 int newRow = mOptionsTable->rowCount() - 1;
484 QTableWidgetItem *item =
new QTableWidgetItem();
485 mOptionsTable->setItem( newRow, 0, item );
486 mOptionsTable->setCurrentItem( item );
489 void QgsRasterFormatSaveOptionsWidget::mOptionsDeleteButton_clicked()
491 if ( mOptionsTable->currentRow() >= 0 )
493 mOptionsTable->removeRow( mOptionsTable->currentRow() );
495 QTableWidgetItem *item = mOptionsTable->item( mOptionsTable->currentRow(), 0 );
496 mOptionsTable->setCurrentItem( item );
497 optionsTableChanged();
501 QString QgsRasterFormatSaveOptionsWidget::settingsKey( QString profileName )
const 503 if ( !profileName.isEmpty() )
504 profileName =
"/profile_" + profileName;
506 profileName =
"/profile_default" + profileName;
507 return mProvider +
"/driverOptions/" + pseudoFormat().toLower() + profileName +
"/create";
510 QString QgsRasterFormatSaveOptionsWidget::currentProfileKey()
const 512 return mProfileComboBox->currentData().toString();
517 return mOptionsMap.value( currentProfileKey() ).trimmed().split(
' ', QString::SkipEmptyParts );
520 QString QgsRasterFormatSaveOptionsWidget::createOptions(
const QString &profileName )
const 523 return mySettings.
value( settingsKey( profileName ),
"" ).toString();
526 void QgsRasterFormatSaveOptionsWidget::deleteCreateOptions(
const QString &profileName )
529 mySettings.
remove( settingsKey( profileName ) );
532 void QgsRasterFormatSaveOptionsWidget::setCreateOptions()
535 QStringList myProfiles;
536 QMap< QString, QString >::const_iterator i = mOptionsMap.constBegin();
537 while ( i != mOptionsMap.constEnd() )
539 setCreateOptions( i.key(), i.value() );
540 myProfiles << i.key();
543 mySettings.
setValue( mProvider +
"/driverOptions/" + pseudoFormat().toLower() +
"/profiles",
545 mySettings.
setValue( mProvider +
"/driverOptions/" + pseudoFormat().toLower() +
"/defaultProfile",
546 currentProfileKey().trimmed() );
549 void QgsRasterFormatSaveOptionsWidget::setCreateOptions(
const QString &profileName,
const QString &
options )
552 mySettings.
setValue( settingsKey( profileName ), options.trimmed() );
555 void QgsRasterFormatSaveOptionsWidget::setCreateOptions(
const QString &profileName,
const QStringList &list )
557 setCreateOptions( profileName, list.join( QStringLiteral(
" " ) ) );
560 QStringList QgsRasterFormatSaveOptionsWidget::profiles()
const 563 return mySettings.
value( mProvider +
"/driverOptions/" + pseudoFormat().toLower() +
"/profiles",
"" ).toStringList();
566 void QgsRasterFormatSaveOptionsWidget::swapOptionsUI(
int newIndex )
570 if ( newIndex == -1 )
572 oldIndex = mOptionsStackedWidget->currentIndex();
573 newIndex = ( oldIndex + 1 ) % 2;
577 oldIndex = ( newIndex + 1 ) % 2;
581 mOptionsStackedWidget->setCurrentIndex( newIndex );
582 mOptionsStackedWidget->widget( newIndex )->setSizePolicy(
583 QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
584 mOptionsStackedWidget->widget( oldIndex )->setSizePolicy(
585 QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) );
586 layout()->activate();
591 void QgsRasterFormatSaveOptionsWidget::updateControls()
593 bool valid = mProvider == QLatin1String(
"gdal" ) && !mFormat.isEmpty();
594 mOptionsValidateButton->setEnabled( valid );
595 mOptionsHelpButton->setEnabled( valid );
599 bool QgsRasterFormatSaveOptionsWidget::eventFilter( QObject *obj, QEvent *event )
601 if ( event->type() == QEvent::MouseButtonPress )
603 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>( event );
604 if ( mouseEvent && ( mouseEvent->button() == Qt::RightButton ) )
606 QMenu *menu =
nullptr;
608 if ( mOptionsStackedWidget->currentIndex() == 0 )
609 text = tr(
"Use simple interface" );
611 text = tr(
"Use table interface" );
612 if ( obj->objectName() == QLatin1String(
"mOptionsLineEdit" ) )
614 menu = mOptionsLineEdit->createStandardContextMenu();
615 menu->addSeparator();
618 menu =
new QMenu(
this );
619 QAction *action =
new QAction( text, menu );
620 menu->addAction( action );
621 connect( action, &QAction::triggered,
this, &QgsRasterFormatSaveOptionsWidget::swapOptionsUI );
622 menu->exec( mouseEvent->globalPos() );
628 return QObject::eventFilter( obj, event );
634 mOptionsTable->horizontalHeader()->resizeSection( 0, mOptionsTable->width() - 115 );
640 mOptionsTable->blockSignals(
true );
641 mOptionsTable->clearContents();
644 QStringList optionsList = options.trimmed().split(
' ', QString::SkipEmptyParts );
645 const auto constOptionsList = optionsList;
646 for (
const QString &opt : constOptionsList )
648 int rowCount = mOptionsTable->rowCount();
649 mOptionsTable->insertRow( rowCount );
651 values = opt.split(
'=' );
652 if ( values.count() == 2 )
654 QTableWidgetItem *nameItem =
new QTableWidgetItem( values.at( 0 ) );
655 mOptionsTable->setItem( rowCount, 0, nameItem );
656 QTableWidgetItem *valueItem =
new QTableWidgetItem( values.at( 1 ) );
657 mOptionsTable->setItem( rowCount, 0, valueItem );
661 mOptionsMap[ currentProfileKey()] = options.trimmed();
662 mOptionsLineEdit->setText( options.trimmed() );
663 mOptionsLineEdit->setCursorPosition( 0 );
665 mOptionsTable->blockSignals(
false );
int bandCount() const
Returns the number of bands in this layer.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
A generic dialog with layout and button box.
virtual QString validatePyramidsConfigOptions(QgsRaster::RasterPyramidsFormat pyramidsFormat, const QStringList &configOptions, const QString &fileFormat)
Validates pyramid creation options for a specific dataset and destination format. ...
QgsRasterDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QVBoxLayout * layout()
Returns the central layout. Widgets added to it must have this dialog as parent.
virtual QString validateCreationOptions(const QStringList &createOptions, const QString &format)
Validates creation options for a specific dataset and destination format.