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 Q_FOREACH ( QWidget *widget, widgets )
130 widget->setVisible(
false );
131 mOptionsStackedWidget->setVisible(
true );
132 Q_FOREACH ( QWidget *widget, mOptionsStackedWidget->findChildren<QWidget *>() )
133 widget->setVisible(
true );
144 Q_FOREACH ( QWidget *widget, widgets )
145 widget->setVisible(
true );
147 mProfileButtons->setVisible(
false );
155 QString QgsRasterFormatSaveOptionsWidget::pseudoFormat()
const 157 return mPyramids ? QStringLiteral(
"_pyramids" ) : mFormat;
163 QString format = pseudoFormat();
164 QStringList profileKeys = profiles();
165 QMapIterator<QString, QStringList> it( sBuiltinProfiles );
166 while ( it.hasNext() )
169 QString profileKey = it.key();
170 if ( ! profileKeys.contains( profileKey ) && !it.value().isEmpty() )
173 if ( it.value()[0].isEmpty() || it.value()[0] == format )
175 profileKeys.insert( 0, profileKey );
179 std::sort( profileKeys.begin(), profileKeys.end() );
183 mProfileComboBox->blockSignals(
true );
184 mProfileComboBox->clear();
185 Q_FOREACH (
const QString &profileKey, profileKeys )
187 QString profileName, profileOptions;
188 profileOptions = createOptions( profileKey );
189 if ( sBuiltinProfiles.contains( profileKey ) )
191 profileName = sBuiltinProfiles[ profileKey ][ 1 ];
192 if ( profileOptions.isEmpty() )
193 profileOptions = sBuiltinProfiles[ profileKey ][ 2 ];
197 profileName = profileKey;
199 mOptionsMap[ profileKey ] = profileOptions;
200 mProfileComboBox->addItem( profileName, profileKey );
204 mProfileComboBox->blockSignals(
false );
207 mProfileComboBox->setCurrentIndex( mProfileComboBox->findData( mySettings.
value(
208 mProvider +
"/driverOptions/" + format.toLower() +
"/defaultProfile",
213 void QgsRasterFormatSaveOptionsWidget::updateOptions()
215 QString myOptions = mOptionsMap.value( currentProfileKey() );
216 QStringList myOptionsList = myOptions.trimmed().split(
' ', QString::SkipEmptyParts );
220 if ( mRasterLayer && mRasterLayer->
bandCount() != 3 &&
221 myOptions == PYRAMID_JPEG_YCBCR_COMPRESSION )
223 myOptions = PYRAMID_JPEG_COMPRESSION;
226 if ( mOptionsStackedWidget->currentIndex() == 0 )
228 mOptionsTable->setRowCount( 0 );
229 for (
int i = 0; i < myOptionsList.count(); i++ )
231 QStringList key_value = myOptionsList[i].split(
'=' );
232 if ( key_value.count() == 2 )
234 mOptionsTable->insertRow( i );
235 mOptionsTable->setItem( i, 0,
new QTableWidgetItem( key_value[0] ) );
236 mOptionsTable->setItem( i, 1,
new QTableWidgetItem( key_value[1] ) );
242 mOptionsLineEdit->setText( myOptions );
243 mOptionsLineEdit->setCursorPosition( 0 );
262 if ( mProvider == QLatin1String(
"gdal" ) && !mFormat.isEmpty() && ! mPyramids )
270 if ( helpCreationOptionsFormat )
272 message = helpCreationOptionsFormat( mFormat );
276 message = library->fileName() +
" does not have helpCreationOptionsFormat";
280 message = QStringLiteral(
"cannot load provider library %1" ).arg( mProvider );
283 if ( message.isEmpty() )
284 message = tr(
"Cannot get create options for driver %1" ).arg( mFormat );
286 else if ( mProvider == QLatin1String(
"gdal" ) && mPyramids )
288 message = tr(
"For details on pyramids options please see the following pages" );
289 message += QLatin1String(
"\n\nhttp://www.gdal.org/gdaladdo.html\n\nhttp://www.gdal.org/frmt_gtiff.html" );
292 message = tr(
"No help available" );
296 QTextEdit *textEdit =
new QTextEdit( dlg );
297 textEdit->setReadOnly(
true );
299 textEdit->setText( message );
300 dlg->
layout()->addWidget( textEdit );
301 dlg->resize( 600, 400 );
311 QStringList createOptions =
options();
314 QgsDebugMsg( QStringLiteral(
"layer: [%1] file: [%2] format: [%3]" ).arg( mRasterLayer ? mRasterLayer->
id() :
"none", mRasterFileName, mFormat ) );
318 bool tmpLayer =
false;
319 if ( !( mRasterLayer && rasterLayer->
dataProvider() ) && ! mRasterFileName.isNull() )
325 QString defaultProjectionOption = settings.
value( QStringLiteral(
"Projections/defaultBehavior" ),
"prompt" ).toString();
326 if ( settings.
value( QStringLiteral(
"Projections/defaultBehavior" ),
"prompt" ).toString() == QLatin1String(
"prompt" ) )
328 settings.
setValue( QStringLiteral(
"Projections/defaultBehavior" ),
"useProject" );
331 rasterLayer =
new QgsRasterLayer( mRasterFileName, QFileInfo( mRasterFileName ).baseName(), QStringLiteral(
"gdal" ) );
333 if ( defaultProjectionOption == QLatin1String(
"prompt" ) )
335 settings.
setValue( QStringLiteral(
"Projections/defaultBehavior" ), defaultProjectionOption );
339 if ( mProvider == QLatin1String(
"gdal" ) && mPyramids )
343 QgsDebugMsg( QStringLiteral(
"calling validate pyramids on layer's data provider" ) );
348 message = tr(
"cannot validate pyramid options" );
351 else if ( !createOptions.isEmpty() && mProvider == QLatin1String(
"gdal" ) && !mFormat.isEmpty() )
355 QgsDebugMsg( QStringLiteral(
"calling validate on layer's data provider" ) );
366 if ( validateCreationOptionsFormat )
368 message = validateCreationOptionsFormat( createOptions, mFormat );
372 message = library->fileName() +
" does not have validateCreationOptionsFormat";
376 message = QStringLiteral(
"cannot load provider library %1" ).arg( mProvider );
379 else if ( ! createOptions.isEmpty() )
381 QMessageBox::information(
this, QString(), tr(
"Cannot validate creation options." ), QMessageBox::Close );
389 if ( message.isNull() )
392 QMessageBox::information(
this, QString(), tr(
"Valid" ), QMessageBox::Close );
396 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 );
406 void QgsRasterFormatSaveOptionsWidget::optionsTableChanged()
408 QTableWidgetItem *key, *value;
410 for (
int i = 0; i < mOptionsTable->rowCount(); i++ )
412 key = mOptionsTable->item( i, 0 );
413 if ( ! key || key->text().isEmpty() )
415 value = mOptionsTable->item( i, 1 );
416 if ( ! value || value->text().isEmpty() )
418 options += key->text() +
'=' + value->text() +
' ';
420 options = options.trimmed();
421 mOptionsMap[ currentProfileKey()] =
options;
422 mOptionsLineEdit->setText( options );
423 mOptionsLineEdit->setCursorPosition( 0 );
426 void QgsRasterFormatSaveOptionsWidget::mOptionsLineEdit_editingFinished()
428 mOptionsMap[ currentProfileKey()] = mOptionsLineEdit->text().trimmed();
431 void QgsRasterFormatSaveOptionsWidget::mProfileNewButton_clicked()
433 QString profileName = QInputDialog::getText(
this, QString(), tr(
"Profile name:" ) );
434 if ( ! profileName.isEmpty() )
436 profileName = profileName.trimmed();
437 mOptionsMap[ profileName ] = QString();
438 mProfileComboBox->addItem( profileName, profileName );
439 mProfileComboBox->setCurrentIndex( mProfileComboBox->count() - 1 );
443 void QgsRasterFormatSaveOptionsWidget::mProfileDeleteButton_clicked()
445 int index = mProfileComboBox->currentIndex();
446 QString profileKey = currentProfileKey();
447 if ( index != -1 && ! sBuiltinProfiles.contains( profileKey ) )
449 mOptionsMap.remove( profileKey );
450 mProfileComboBox->removeItem( index );
454 void QgsRasterFormatSaveOptionsWidget::mProfileResetButton_clicked()
456 QString profileKey = currentProfileKey();
457 if ( sBuiltinProfiles.contains( profileKey ) )
459 mOptionsMap[ profileKey ] = sBuiltinProfiles[ profileKey ][ 2 ];
463 mOptionsMap[ profileKey ] = QString();
465 mOptionsLineEdit->setText( mOptionsMap.value( currentProfileKey() ) );
466 mOptionsLineEdit->setCursorPosition( 0 );
470 void QgsRasterFormatSaveOptionsWidget::optionsTableEnableDeleteButton()
472 mOptionsDeleteButton->setEnabled( mOptionsTable->currentRow() >= 0 );
475 void QgsRasterFormatSaveOptionsWidget::mOptionsAddButton_clicked()
477 mOptionsTable->insertRow( mOptionsTable->rowCount() );
479 int newRow = mOptionsTable->rowCount() - 1;
480 QTableWidgetItem *item =
new QTableWidgetItem();
481 mOptionsTable->setItem( newRow, 0, item );
482 mOptionsTable->setCurrentItem( item );
485 void QgsRasterFormatSaveOptionsWidget::mOptionsDeleteButton_clicked()
487 if ( mOptionsTable->currentRow() >= 0 )
489 mOptionsTable->removeRow( mOptionsTable->currentRow() );
491 QTableWidgetItem *item = mOptionsTable->item( mOptionsTable->currentRow(), 0 );
492 mOptionsTable->setCurrentItem( item );
493 optionsTableChanged();
497 QString QgsRasterFormatSaveOptionsWidget::settingsKey( QString profileName )
const 499 if ( !profileName.isEmpty() )
500 profileName =
"/profile_" + profileName;
502 profileName =
"/profile_default" + profileName;
503 return mProvider +
"/driverOptions/" + pseudoFormat().toLower() + profileName +
"/create";
506 QString QgsRasterFormatSaveOptionsWidget::currentProfileKey()
const 508 return mProfileComboBox->currentData().toString();
513 return mOptionsMap.value( currentProfileKey() ).trimmed().split(
' ', QString::SkipEmptyParts );
516 QString QgsRasterFormatSaveOptionsWidget::createOptions(
const QString &profileName )
const 519 return mySettings.
value( settingsKey( profileName ),
"" ).toString();
522 void QgsRasterFormatSaveOptionsWidget::deleteCreateOptions(
const QString &profileName )
525 mySettings.
remove( settingsKey( profileName ) );
528 void QgsRasterFormatSaveOptionsWidget::setCreateOptions()
531 QStringList myProfiles;
532 QMap< QString, QString >::const_iterator i = mOptionsMap.constBegin();
533 while ( i != mOptionsMap.constEnd() )
535 setCreateOptions( i.key(), i.value() );
536 myProfiles << i.key();
539 mySettings.
setValue( mProvider +
"/driverOptions/" + pseudoFormat().toLower() +
"/profiles",
541 mySettings.
setValue( mProvider +
"/driverOptions/" + pseudoFormat().toLower() +
"/defaultProfile",
542 currentProfileKey().trimmed() );
545 void QgsRasterFormatSaveOptionsWidget::setCreateOptions(
const QString &profileName,
const QString &
options )
548 mySettings.
setValue( settingsKey( profileName ), options.trimmed() );
551 void QgsRasterFormatSaveOptionsWidget::setCreateOptions(
const QString &profileName,
const QStringList &list )
553 setCreateOptions( profileName, list.join( QStringLiteral(
" " ) ) );
556 QStringList QgsRasterFormatSaveOptionsWidget::profiles()
const 559 return mySettings.
value( mProvider +
"/driverOptions/" + pseudoFormat().toLower() +
"/profiles",
"" ).toStringList();
562 void QgsRasterFormatSaveOptionsWidget::swapOptionsUI(
int newIndex )
566 if ( newIndex == -1 )
568 oldIndex = mOptionsStackedWidget->currentIndex();
569 newIndex = ( oldIndex + 1 ) % 2;
573 oldIndex = ( newIndex + 1 ) % 2;
577 mOptionsStackedWidget->setCurrentIndex( newIndex );
578 mOptionsStackedWidget->widget( newIndex )->setSizePolicy(
579 QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
580 mOptionsStackedWidget->widget( oldIndex )->setSizePolicy(
581 QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) );
582 layout()->activate();
587 void QgsRasterFormatSaveOptionsWidget::updateControls()
589 bool valid = mProvider == QLatin1String(
"gdal" ) && !mFormat.isEmpty();
590 mOptionsValidateButton->setEnabled( valid );
591 mOptionsHelpButton->setEnabled( valid );
595 bool QgsRasterFormatSaveOptionsWidget::eventFilter( QObject *obj, QEvent *event )
597 if ( event->type() == QEvent::MouseButtonPress )
599 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>( event );
600 if ( mouseEvent && ( mouseEvent->button() == Qt::RightButton ) )
602 QMenu *menu =
nullptr;
604 if ( mOptionsStackedWidget->currentIndex() == 0 )
605 text = tr(
"Use simple interface" );
607 text = tr(
"Use table interface" );
608 if ( obj->objectName() == QLatin1String(
"mOptionsLineEdit" ) )
610 menu = mOptionsLineEdit->createStandardContextMenu();
611 menu->addSeparator();
614 menu =
new QMenu(
this );
615 QAction *action =
new QAction( text, menu );
616 menu->addAction( action );
617 connect( action, &QAction::triggered,
this, &QgsRasterFormatSaveOptionsWidget::swapOptionsUI );
618 menu->exec( mouseEvent->globalPos() );
624 return QObject::eventFilter( obj, event );
630 mOptionsTable->horizontalHeader()->resizeSection( 0, mOptionsTable->width() - 115 );
636 mOptionsTable->blockSignals(
true );
637 mOptionsTable->clearContents();
640 QStringList optionsList = options.trimmed().split(
' ', QString::SkipEmptyParts );
641 Q_FOREACH (
const QString &opt, optionsList )
643 int rowCount = mOptionsTable->rowCount();
644 mOptionsTable->insertRow( rowCount );
646 values = opt.split(
'=' );
647 if ( values.count() == 2 )
649 QTableWidgetItem *nameItem =
new QTableWidgetItem( values.at( 0 ) );
650 mOptionsTable->setItem( rowCount, 0, nameItem );
651 QTableWidgetItem *valueItem =
new QTableWidgetItem( values.at( 1 ) );
652 mOptionsTable->setItem( rowCount, 0, valueItem );
656 mOptionsMap[ currentProfileKey()] = options.trimmed();
657 mOptionsLineEdit->setText( options.trimmed() );
658 mOptionsLineEdit->setCursorPosition( 0 );
660 mOptionsTable->blockSignals(
false );
This class is a composition of two QSettings instances:
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
int bandCount() const
Returns the number of bands in this layer.
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.