diff --git a/python/gui/qgsfilewidget.sip b/python/gui/qgsfilewidget.sip index 180840ab3d89..3af4645cfdd4 100644 --- a/python/gui/qgsfilewidget.sip +++ b/python/gui/qgsfilewidget.sip @@ -31,6 +31,7 @@ class QgsFileWidget : QWidget GetFile, GetDirectory, GetMultipleFiles, + SaveFile, }; enum RelativeStorage @@ -97,6 +98,19 @@ returns the filters used for QDialog.getOpenFileName \param filter Only files that match the given filter are shown, it may be an empty string. If you want multiple filters, separate them with ';;', %End + void setConfirmOverwrite( bool confirmOverwrite ); +%Docstring + Sets whether a confirmation to overwrite an existing file will appear. + By default, a confirmation will appear. + \param confirmOverwrite If set to true, an overwrite confirmation will be shown +%End + + bool confirmOverwrite() const; +%Docstring + Returns whether a confirmation will be shown when overwriting an existing file + :rtype: bool +%End + bool fileWidgetButtonVisible() const; %Docstring determines if the tool button is shown diff --git a/src/gui/ogr/qgsvectorlayersaveasdialog.cpp b/src/gui/ogr/qgsvectorlayersaveasdialog.cpp index 8d3b0c1b7bca..fe397bf63cb5 100644 --- a/src/gui/ogr/qgsvectorlayersaveasdialog.cpp +++ b/src/gui/ogr/qgsvectorlayersaveasdialog.cpp @@ -73,8 +73,6 @@ void QgsVectorLayerSaveAsDialog::setup() { setupUi( this ); connect( mFormatComboBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged ); - connect( leFilename, &QLineEdit::textChanged, this, &QgsVectorLayerSaveAsDialog::leFilename_textChanged ); - connect( browseFilename, &QPushButton::clicked, this, &QgsVectorLayerSaveAsDialog::browseFilename_clicked ); connect( mCrsSelector, &QgsProjectionSelectionWidget::crsChanged, this, &QgsVectorLayerSaveAsDialog::mCrsSelector_crsChanged ); connect( mSymbologyExportComboBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsVectorLayerSaveAsDialog::mSymbologyExportComboBox_currentIndexChanged ); connect( mGeometryTypeComboBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsVectorLayerSaveAsDialog::mGeometryTypeComboBox_currentIndexChanged ); @@ -139,6 +137,24 @@ void QgsVectorLayerSaveAsDialog::setup() mExtentGroupBox->setCheckable( true ); mExtentGroupBox->setChecked( false ); mExtentGroupBox->setCollapsed( true ); + + mFilename->setStorageMode( QgsFileWidget::SaveFile ); + mFilename->setDialogTitle( tr( "Select layer as..." ) ); + mFilename->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() ); + mFilename->setConfirmOverwrite( false ); + connect( mFilename, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath ) + { + QgsSettings settings; + QFileInfo tmplFileInfo( filePath ); + settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), tmplFileInfo.absolutePath() ); + if ( !filePath.isEmpty() && leLayername->isEnabled() ) + { + QFileInfo fileInfo( filePath ); + leLayername->setText( fileInfo.baseName() ); + } + buttonBox->button( QDialogButtonBox::Ok )->setEnabled( + !filePath.isEmpty() && QFileInfo( filePath ).absoluteDir().exists() ); + } ); } QList > QgsVectorLayerSaveAsDialog::createControls( const QMap &options ) @@ -352,8 +368,9 @@ void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( int idx ) { Q_UNUSED( idx ); - browseFilename->setEnabled( true ); - leFilename->setEnabled( true ); + mFilename->setEnabled( true ); + mFilename->setFilter( QgsVectorFileWriter::filterForDriver( format() ) ); + bool selectAllFields = true; bool fieldsAsDisplayedValues = false; @@ -379,9 +396,9 @@ void QgsVectorLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( int idx ) if ( !leLayername->isEnabled() ) leLayername->setText( QString() ); else if ( leLayername->text().isEmpty() && - !leFilename->text().isEmpty() ) + !mFilename->filePath().isEmpty() ) { - QString layerName = QFileInfo( leFilename->text() ).baseName(); + QString layerName = QFileInfo( mFilename->filePath() ).baseName(); leLayername->setText( layerName ); } @@ -626,30 +643,6 @@ void QgsVectorLayerSaveAsDialog::mAttributeTable_itemChanged( QTableWidgetItem * mReplaceRawFieldValuesStateChangedSlotEnabled = true; } -void QgsVectorLayerSaveAsDialog::leFilename_textChanged( const QString &text ) -{ - buttonBox->button( QDialogButtonBox::Ok )->setEnabled( - !text.isEmpty() && QFileInfo( text ).absoluteDir().exists() ); - - if ( leLayername->isEnabled() ) - { - QString layerName = QFileInfo( text ).baseName(); - leLayername->setText( layerName ); - } -} - -void QgsVectorLayerSaveAsDialog::browseFilename_clicked() -{ - QgsSettings settings; - QString dirName = leFilename->text().isEmpty() ? settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() : leFilename->text(); - QString filterString = QgsVectorFileWriter::filterForDriver( format() ); - QString outputFile = QFileDialog::getSaveFileName( nullptr, tr( "Save layer as..." ), dirName, filterString, nullptr, QFileDialog::DontConfirmOverwrite ); - if ( !outputFile.isNull() ) - { - leFilename->setText( outputFile ); - } -} - void QgsVectorLayerSaveAsDialog::mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs ) { mCRS = crs.srsid(); @@ -658,7 +651,7 @@ void QgsVectorLayerSaveAsDialog::mCrsSelector_crsChanged( const QgsCoordinateRef QString QgsVectorLayerSaveAsDialog::filename() const { - return leFilename->text(); + return mFilename->filePath(); } QString QgsVectorLayerSaveAsDialog::layername() const diff --git a/src/gui/ogr/qgsvectorlayersaveasdialog.h b/src/gui/ogr/qgsvectorlayersaveasdialog.h index a3cb1764fd3f..2baf88fbc9a7 100644 --- a/src/gui/ogr/qgsvectorlayersaveasdialog.h +++ b/src/gui/ogr/qgsvectorlayersaveasdialog.h @@ -126,8 +126,6 @@ class GUI_EXPORT QgsVectorLayerSaveAsDialog : public QDialog, private Ui::QgsVec private slots: void mFormatComboBox_currentIndexChanged( int idx ); - void leFilename_textChanged( const QString &text ); - void browseFilename_clicked(); void mCrsSelector_crsChanged( const QgsCoordinateReferenceSystem &crs ); void showHelp(); void mSymbologyExportComboBox_currentIndexChanged( const QString &text ); diff --git a/src/gui/qgsfilewidget.cpp b/src/gui/qgsfilewidget.cpp index 960bd3ba132c..df599d13edec 100644 --- a/src/gui/qgsfilewidget.cpp +++ b/src/gui/qgsfilewidget.cpp @@ -262,6 +262,17 @@ void QgsFileWidget::openFileDialog() title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Select a directory" ); fileName = QFileDialog::getExistingDirectory( this, title, QFileInfo( oldPath ).absoluteFilePath(), QFileDialog::ShowDirsOnly ); break; + case SaveFile: + title = !mDialogTitle.isEmpty() ? mDialogTitle : tr( "Create or select a file" ); + if ( !confirmOverwrite() ) + { + fileName = QFileDialog::getSaveFileName( this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter, nullptr, QFileDialog::DontConfirmOverwrite ); + } + else + { + fileName = QFileDialog::getSaveFileName( this, title, QFileInfo( oldPath ).absoluteFilePath(), mFilter ); + } + break; } if ( fileName.isEmpty() && fileNames.isEmpty( ) ) @@ -283,6 +294,7 @@ void QgsFileWidget::openFileDialog() switch ( mStorageMode ) { case GetFile: + case SaveFile: settings.setValue( QStringLiteral( "UI/lastFileNameWidgetDir" ), QFileInfo( fileName ).absolutePath() ); break; case GetDirectory: diff --git a/src/gui/qgsfilewidget.h b/src/gui/qgsfilewidget.h index 1c81aa523db2..15771846579e 100644 --- a/src/gui/qgsfilewidget.h +++ b/src/gui/qgsfilewidget.h @@ -65,6 +65,7 @@ class GUI_EXPORT QgsFileWidget : public QWidget GetFile, //! Select a single file GetDirectory, //! Select a directory GetMultipleFiles, //! Select multiple files + SaveFile, //! Select a single new or pre-existing file }; /** @@ -120,6 +121,18 @@ class GUI_EXPORT QgsFileWidget : public QWidget */ void setFilter( const QString &filter ); + /** + * Sets whether a confirmation to overwrite an existing file will appear. + * By default, a confirmation will appear. + * \param confirmOverwrite If set to true, an overwrite confirmation will be shown + */ + void setConfirmOverwrite( bool confirmOverwrite ) { mConfirmOverwrite = confirmOverwrite; } + + /** + * Returns whether a confirmation will be shown when overwriting an existing file + */ + bool confirmOverwrite() const { return mConfirmOverwrite; } + //! determines if the tool button is shown bool fileWidgetButtonVisible() const; //! determines if the tool button is shown @@ -173,6 +186,7 @@ class GUI_EXPORT QgsFileWidget : public QWidget QString mDialogTitle; QString mFilter; QString mDefaultRoot; + bool mConfirmOverwrite = true; StorageMode mStorageMode = GetFile; RelativeStorage mRelativeStorage = Absolute; diff --git a/src/gui/qgsnewgeopackagelayerdialog.cpp b/src/gui/qgsnewgeopackagelayerdialog.cpp index 0da9df6d938e..b17a5e2b8eb5 100644 --- a/src/gui/qgsnewgeopackagelayerdialog.cpp +++ b/src/gui/qgsnewgeopackagelayerdialog.cpp @@ -51,8 +51,6 @@ QgsNewGeoPackageLayerDialog::QgsNewGeoPackageLayerDialog( QWidget *parent, Qt::W connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewGeoPackageLayerDialog::mRemoveAttributeButton_clicked ); connect( mFieldTypeBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsNewGeoPackageLayerDialog::mFieldTypeBox_currentIndexChanged ); connect( mGeometryTypeBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsNewGeoPackageLayerDialog::mGeometryTypeBox_currentIndexChanged ); - connect( mSelectDatabaseButton, &QToolButton::clicked, this, &QgsNewGeoPackageLayerDialog::mSelectDatabaseButton_clicked ); - connect( mDatabaseEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::mDatabaseEdit_textChanged ); connect( mTableNameEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::mTableNameEdit_textChanged ); connect( mTableNameEdit, &QLineEdit::textEdited, this, &QgsNewGeoPackageLayerDialog::mTableNameEdit_textEdited ); connect( mLayerIdentifierEdit, &QLineEdit::textEdited, this, &QgsNewGeoPackageLayerDialog::mLayerIdentifierEdit_textEdited ); @@ -102,12 +100,29 @@ QgsNewGeoPackageLayerDialog::QgsNewGeoPackageLayerDialog( QWidget *parent, Qt::W connect( mFieldNameEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::fieldNameChanged ); connect( mAttributeView, &QTreeWidget::itemSelectionChanged, this, &QgsNewGeoPackageLayerDialog::selectionChanged ); connect( mTableNameEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::checkOk ); - connect( mDatabaseEdit, &QLineEdit::textChanged, this, &QgsNewGeoPackageLayerDialog::checkOk ); mAddAttributeButton->setEnabled( false ); mRemoveAttributeButton->setEnabled( false ); mCheckBoxCreateSpatialIndex->setChecked( true ); + + mDatabase->setStorageMode( QgsFileWidget::SaveFile ); + mDatabase->setFilter( tr( "GeoPackage" ) + " (*.gpkg)" ); + mDatabase->setDialogTitle( tr( "Select Existing or Create a New GeoPackage Database File..." ) ); + mDatabase->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() ); + mDatabase->setConfirmOverwrite( false ); + connect( mDatabase, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath ) + { + QgsSettings settings; + QFileInfo tmplFileInfo( filePath ); + settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), tmplFileInfo.absolutePath() ); + if ( !filePath.isEmpty() && !mTableNameEdited ) + { + QFileInfo fileInfo( filePath ); + mTableNameEdit->setText( fileInfo.baseName() ); + } + checkOk(); + } ); } QgsNewGeoPackageLayerDialog::~QgsNewGeoPackageLayerDialog() @@ -123,10 +138,7 @@ void QgsNewGeoPackageLayerDialog::setCrs( const QgsCoordinateReferenceSystem &cr void QgsNewGeoPackageLayerDialog::lockDatabasePath() { - mDatabaseEdit->setReadOnly( true ); - mSelectDatabaseButton->hide(); - mSelectDatabaseButton->deleteLater(); - mSelectDatabaseButton = nullptr; + mDatabase->setReadOnly( true ); } void QgsNewGeoPackageLayerDialog::mFieldTypeBox_currentIndexChanged( int ) @@ -150,34 +162,6 @@ void QgsNewGeoPackageLayerDialog::mGeometryTypeBox_currentIndexChanged( int ) mCrsSelector->setEnabled( isSpatial ); } -void QgsNewGeoPackageLayerDialog::mSelectDatabaseButton_clicked() -{ - QString fileName = QFileDialog::getSaveFileName( this, tr( "Select existing or create new GeoPackage Database File" ), - QDir::homePath(), - tr( "GeoPackage" ) + " (*.gpkg)", - nullptr, - QFileDialog::DontConfirmOverwrite ); - - if ( fileName.isEmpty() ) - return; - - if ( !fileName.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) ) - { - fileName += QLatin1String( ".gpkg" ); - } - - mDatabaseEdit->setText( fileName ); -} - -void QgsNewGeoPackageLayerDialog::mDatabaseEdit_textChanged( const QString &text ) -{ - if ( !text.isEmpty() && !mTableNameEdited ) - { - QFileInfo fileInfo( text ); - mTableNameEdit->setText( fileInfo.baseName() ); - } -} - void QgsNewGeoPackageLayerDialog::mTableNameEdit_textChanged( const QString &text ) { mTableNameEdited = !text.isEmpty(); @@ -201,7 +185,7 @@ void QgsNewGeoPackageLayerDialog::mLayerIdentifierEdit_textEdited( const QString void QgsNewGeoPackageLayerDialog::checkOk() { - bool ok = !mDatabaseEdit->text().isEmpty() && + bool ok = !mDatabase->filePath().isEmpty() && !mTableNameEdit->text().isEmpty(); mOkButton->setEnabled( ok ); } @@ -258,7 +242,10 @@ void QgsNewGeoPackageLayerDialog::buttonBox_rejected() bool QgsNewGeoPackageLayerDialog::apply() { - QString fileName( mDatabaseEdit->text() ); + QString fileName( mDatabase->filePath() ); + if ( !fileName.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) ) + fileName += QLatin1String( ".gpkg" ); + bool createNewDb = false; if ( QFile( fileName ).exists( fileName ) ) @@ -490,7 +477,7 @@ bool QgsNewGeoPackageLayerDialog::apply() } hDS.reset(); - QString uri( QStringLiteral( "%1|layername=%2" ).arg( mDatabaseEdit->text(), tableName ) ); + QString uri( QStringLiteral( "%1|layername=%2" ).arg( fileName, tableName ) ); QString userVisiblelayerName( layerIdentifier.isEmpty() ? tableName : layerIdentifier ); QgsVectorLayer *layer = new QgsVectorLayer( uri, userVisiblelayerName, QStringLiteral( "ogr" ) ); if ( layer->isValid() ) diff --git a/src/gui/qgsnewgeopackagelayerdialog.h b/src/gui/qgsnewgeopackagelayerdialog.h index fb6f6f678abd..c2982a7d0c4b 100644 --- a/src/gui/qgsnewgeopackagelayerdialog.h +++ b/src/gui/qgsnewgeopackagelayerdialog.h @@ -54,13 +54,13 @@ class GUI_EXPORT QgsNewGeoPackageLayerDialog: public QDialog, private Ui::QgsNew * Returns the database path * \since QGIS 3.0 */ - QString databasePath() const { return mDatabaseEdit->text(); } + QString databasePath() const { return mDatabase->filePath(); } /** * Sets the initial database \a path * \since QGIS 3.0 */ - void setDatabasePath( const QString &path ) { mDatabaseEdit->setText( path ); } + void setDatabasePath( const QString &path ) { mDatabase->setFilePath( path ); } /** * Sets the database path widgets to a locked and read-only mode. @@ -82,8 +82,6 @@ class GUI_EXPORT QgsNewGeoPackageLayerDialog: public QDialog, private Ui::QgsNew void mRemoveAttributeButton_clicked(); void mFieldTypeBox_currentIndexChanged( int index ); void mGeometryTypeBox_currentIndexChanged( int index ); - void mSelectDatabaseButton_clicked(); - void mDatabaseEdit_textChanged( const QString &text ); void mTableNameEdit_textChanged( const QString &text ); void mTableNameEdit_textEdited( const QString &text ); void mLayerIdentifierEdit_textEdited( const QString &text ); diff --git a/src/gui/qgsnewvectorlayerdialog.cpp b/src/gui/qgsnewvectorlayerdialog.cpp index 8905d56b08b9..3e8c2c22993b 100644 --- a/src/gui/qgsnewvectorlayerdialog.cpp +++ b/src/gui/qgsnewvectorlayerdialog.cpp @@ -17,6 +17,7 @@ #include "qgsnewvectorlayerdialog.h" #include "qgsapplication.h" +#include "qgsfilewidget.h" #include "qgis.h" #include "qgslogger.h" #include "qgscoordinatereferencesystem.h" @@ -35,10 +36,9 @@ QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFla : QDialog( parent, fl ) { setupUi( this ); + connect( mAddAttributeButton, &QToolButton::clicked, this, &QgsNewVectorLayerDialog::mAddAttributeButton_clicked ); connect( mRemoveAttributeButton, &QToolButton::clicked, this, &QgsNewVectorLayerDialog::mRemoveAttributeButton_clicked ); - connect( mFileNameEdit, &QLineEdit::textChanged, this, &QgsNewVectorLayerDialog::checkOk ); - connect( mBrowseFileName, &QToolButton::clicked, this, &QgsNewVectorLayerDialog::selectFileName ); connect( mFileFormatComboBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsNewVectorLayerDialog::mFileFormatComboBox_currentIndexChanged ); connect( mTypeBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsNewVectorLayerDialog::mTypeBox_currentIndexChanged ); connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsNewVectorLayerDialog::showHelp ); @@ -100,6 +100,18 @@ QgsNewVectorLayerDialog::QgsNewVectorLayerDialog( QWidget *parent, Qt::WindowFla mAddAttributeButton->setEnabled( false ); mRemoveAttributeButton->setEnabled( false ); + + mFileName->setStorageMode( QgsFileWidget::SaveFile ); + mFileName->setFilter( QgsVectorFileWriter::filterForDriver( mFileFormatComboBox->currentData( Qt::UserRole ).toString() ) ); + mFileName->setDialogTitle( tr( "Select Layer as..." ) ); + mFileName->setDefaultRoot( settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString() ); + connect( mFileName, &QgsFileWidget::fileChanged, this, [ = ] + { + QgsSettings settings; + QFileInfo tmplFileInfo( mFileName->filePath() ); + settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), tmplFileInfo.absolutePath() ); + checkOk(); + } ); } QgsNewVectorLayerDialog::~QgsNewVectorLayerDialog() @@ -224,29 +236,14 @@ void QgsNewVectorLayerDialog::selectionChanged() mRemoveAttributeButton->setDisabled( mAttributeView->selectedItems().isEmpty() ); } -void QgsNewVectorLayerDialog::selectFileName() -{ - QString fileformat = mFileFormatComboBox->currentData( Qt::UserRole ).toString(); - QgsSettings settings; - QString lastUsedDir = settings.value( QStringLiteral( "UI/lastVectorFileFilterDir" ), QDir::homePath() ).toString(); - QString filterString = QgsVectorFileWriter::filterForDriver( fileformat ); - QString fileName = QFileDialog::getSaveFileName( nullptr, tr( "Save Layer as..." ), lastUsedDir, filterString ); - if ( fileName.isEmpty() ) - return; - - if ( fileformat == QLatin1String( "ESRI Shapefile" ) && !fileName.endsWith( QLatin1String( ".shp" ), Qt::CaseInsensitive ) ) - fileName += QLatin1String( ".shp" ); - mFileNameEdit->setText( fileName ); -} - QString QgsNewVectorLayerDialog::filename() const { - return mFileNameEdit->text(); + return mFileName->filePath(); } void QgsNewVectorLayerDialog::checkOk() { - bool ok = ( !mFileNameEdit->text().isEmpty() && mAttributeView->topLevelItemCount() > 0 ); + bool ok = ( !mFileName->filePath().isEmpty() && mAttributeView->topLevelItemCount() > 0 ); mOkButton->setEnabled( ok ); } @@ -271,6 +268,8 @@ QString QgsNewVectorLayerDialog::runAndCreateLayer( QWidget *parent, QString *pE QgsSettings settings; QString filterString = QgsVectorFileWriter::filterForDriver( fileformat ); QString fileName = geomDialog.filename(); + if ( fileformat == QLatin1String( "ESRI Shapefile" ) && !fileName.endsWith( QLatin1String( ".shp" ), Qt::CaseInsensitive ) ) + fileName += QLatin1String( ".shp" ); settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), QFileInfo( fileName ).absolutePath() ); settings.setValue( QStringLiteral( "UI/encoding" ), enc ); diff --git a/src/gui/qgsnewvectorlayerdialog.h b/src/gui/qgsnewvectorlayerdialog.h index 003e64e0a8ad..f8c177c4d23d 100644 --- a/src/gui/qgsnewvectorlayerdialog.h +++ b/src/gui/qgsnewvectorlayerdialog.h @@ -67,7 +67,6 @@ class GUI_EXPORT QgsNewVectorLayerDialog: public QDialog, private Ui::QgsNewVect void setCrs( const QgsCoordinateReferenceSystem &crs ); private slots: - void selectFileName(); void mAddAttributeButton_clicked(); void mRemoveAttributeButton_clicked(); void mFileFormatComboBox_currentIndexChanged( int index ); diff --git a/src/gui/qgsrasterlayersaveasdialog.cpp b/src/gui/qgsrasterlayersaveasdialog.cpp index ff104324371a..48fb3cf8510b 100644 --- a/src/gui/qgsrasterlayersaveasdialog.cpp +++ b/src/gui/qgsrasterlayersaveasdialog.cpp @@ -44,8 +44,6 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer *rasterLa { setupUi( this ); connect( mRawModeRadioButton, &QRadioButton::toggled, this, &QgsRasterLayerSaveAsDialog::mRawModeRadioButton_toggled ); - connect( mBrowseButton, &QPushButton::clicked, this, &QgsRasterLayerSaveAsDialog::mBrowseButton_clicked ); - connect( mSaveAsLineEdit, &QLineEdit::textChanged, this, &QgsRasterLayerSaveAsDialog::mSaveAsLineEdit_textChanged ); connect( mFormatComboBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsRasterLayerSaveAsDialog::mFormatComboBox_currentIndexChanged ); connect( mResolutionRadioButton, &QRadioButton::toggled, this, &QgsRasterLayerSaveAsDialog::mResolutionRadioButton_toggled ); connect( mOriginalResolutionPushButton, &QPushButton::clicked, this, &QgsRasterLayerSaveAsDialog::mOriginalResolutionPushButton_clicked ); @@ -161,6 +159,59 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer *rasterLa QgsSettings settings; restoreGeometry( settings.value( QStringLiteral( "Windows/RasterLayerSaveAs/geometry" ) ).toByteArray() ); + + if ( mTileModeCheckBox->isChecked() ) + { + mFilename->setStorageMode( QgsFileWidget::GetDirectory ); + mFilename->setDialogTitle( tr( "Select output directory" ) ); + } + else + { + mFilename->setStorageMode( QgsFileWidget::SaveFile ); + mFilename->setDialogTitle( tr( "Select output file" ) ); + } + mFilename->setDefaultRoot( settings.value( QStringLiteral( "UI/lastRasterFileDir" ), QDir::homePath() ).toString() ); + connect( mFilename, &QgsFileWidget::fileChanged, this, [ = ]( const QString & filePath ) + { + QgsSettings settings; + QFileInfo tmplFileInfo( filePath ); + settings.setValue( QStringLiteral( "UI/lastRasterFileDir" ), tmplFileInfo.absolutePath() ); + + if ( mTileModeCheckBox->isChecked() ) + { + QString fileName = filePath; + Q_FOREVER + { + // TODO: would not it be better to select .vrt file instead of directory? + //fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), QString(), tr( "VRT" ) + " (*.vrt *.VRT)" ); + if ( fileName.isEmpty() ) + break; // canceled + + // Check if directory is empty + QDir dir( fileName ); + QString baseName = QFileInfo( fileName ).baseName(); + QStringList filters; + filters << QStringLiteral( "%1.*" ).arg( baseName ); + QStringList files = dir.entryList( filters ); + if ( files.isEmpty() ) + break; + + if ( QMessageBox::warning( this, tr( "Warning" ), + tr( "The directory %1 contains files which will be overwritten: %2" ).arg( dir.absolutePath(), files.join( QStringLiteral( ", " ) ) ), + QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Ok ) + break; + + fileName = QFileDialog::getExistingDirectory( this, tr( "Select output directory" ), tmplFileInfo.absolutePath() ); + } + } + + QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok ); + if ( !okButton ) + { + return; + } + okButton->setEnabled( tmplFileInfo.absoluteDir().exists() ); + } ); } QgsRasterLayerSaveAsDialog::~QgsRasterLayerSaveAsDialog() @@ -241,84 +292,6 @@ void QgsRasterLayerSaveAsDialog::setValidators() mMaximumSizeYLineEdit->setValidator( new QIntValidator( this ) ); } -void QgsRasterLayerSaveAsDialog::mBrowseButton_clicked() -{ - QString fileName; - - QgsSettings settings; - QString dirName = mSaveAsLineEdit->text().isEmpty() ? settings.value( QStringLiteral( "UI/lastRasterFileDir" ), QDir::homePath() ).toString() : mSaveAsLineEdit->text(); - - if ( mTileModeCheckBox->isChecked() ) - { - Q_FOREVER - { - // TODO: would not it be better to select .vrt file instead of directory? - fileName = QFileDialog::getExistingDirectory( this, tr( "Select output directory" ), dirName ); - //fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), QString(), tr( "VRT" ) + " (*.vrt *.VRT)" ); - - if ( fileName.isEmpty() ) - break; // canceled - - // Check if directory is empty - QDir dir( fileName ); - QString baseName = QFileInfo( fileName ).baseName(); - QStringList filters; - filters << QStringLiteral( "%1.*" ).arg( baseName ); - QStringList files = dir.entryList( filters ); - if ( files.isEmpty() ) - break; - - if ( QMessageBox::warning( this, tr( "Warning" ), - tr( "The directory %1 contains files which will be overwritten: %2" ).arg( dir.absolutePath(), files.join( QStringLiteral( ", " ) ) ), - QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Ok ) - break; - - fileName.clear(); - } - } - else - { - QStringList extensions = QgsRasterFileWriter::extensionsForFormat( outputFormat() ); - QString filter; - QString defaultExt; - if ( extensions.empty() ) - filter = tr( "All files (*.*)" ); - else - { - filter = QStringLiteral( "%1 (*.%2);;%3" ).arg( mFormatComboBox->currentText(), - extensions.join( QStringLiteral( " *." ) ), - tr( "All files (*.*)" ) ); - defaultExt = extensions.at( 0 ); - } - - fileName = QFileDialog::getSaveFileName( this, tr( "Select output file" ), dirName, filter ); - - // ensure the user never omits the extension from the file name - QFileInfo fi( fileName ); - if ( !fileName.isEmpty() && fi.suffix().isEmpty() ) - { - fileName += '.' + defaultExt; - } - } - - if ( !fileName.isEmpty() ) - { - mSaveAsLineEdit->setText( fileName ); - } -} - -void QgsRasterLayerSaveAsDialog::mSaveAsLineEdit_textChanged( const QString &text ) -{ - QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok ); - if ( !okButton ) - { - return; - } - - okButton->setEnabled( QFileInfo( text ).absoluteDir().exists() ); -} - - void QgsRasterLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( const QString & ) { //gdal-specific @@ -327,6 +300,18 @@ void QgsRasterLayerSaveAsDialog::mFormatComboBox_currentIndexChanged( const QStr mCreateOptionsWidget->setFormat( outputFormat() ); mCreateOptionsWidget->update(); } + + QStringList extensions = QgsRasterFileWriter::extensionsForFormat( outputFormat() ); + QString filter; + if ( extensions.empty() ) + filter = tr( "All files (*.*)" ); + else + { + filter = QStringLiteral( "%1 (*.%2);;%3" ).arg( mFormatComboBox->currentText(), + extensions.join( QStringLiteral( " *." ) ), + tr( "All files (*.*)" ) ); + } + mFilename->setFilter( filter ); } int QgsRasterLayerSaveAsDialog::nColumns() const @@ -371,7 +356,22 @@ bool QgsRasterLayerSaveAsDialog::addToCanvas() const QString QgsRasterLayerSaveAsDialog::outputFileName() const { - return mSaveAsLineEdit->text(); + QStringList extensions = QgsRasterFileWriter::extensionsForFormat( outputFormat() ); + QString defaultExt; + if ( !extensions.empty() ) + { + defaultExt = extensions.at( 0 ); + } + + // ensure the user never omits the extension from the file name + QString fileName = mFilename->filePath(); + QFileInfo fi( fileName ); + if ( !fileName.isEmpty() && fi.suffix().isEmpty() ) + { + fileName += '.' + defaultExt; + } + + return fileName; } QString QgsRasterLayerSaveAsDialog::outputFormat() const @@ -398,8 +398,7 @@ void QgsRasterLayerSaveAsDialog::hideFormat() void QgsRasterLayerSaveAsDialog::hideOutput() { mSaveAsLabel->hide(); - mSaveAsLineEdit->hide(); - mBrowseButton->hide(); + mFilename->hide(); QPushButton *okButton = mButtonBox->button( QDialogButtonBox::Ok ); if ( okButton ) { @@ -710,10 +709,14 @@ void QgsRasterLayerSaveAsDialog::mTileModeCheckBox_toggled( bool toggled ) // Show / hide tile options mTilesGroupBox->show(); + mFilename->setStorageMode( QgsFileWidget::GetDirectory ); + mFilename->setDialogTitle( tr( "Select output directory" ) ); } else { mTilesGroupBox->hide(); + mFilename->setStorageMode( QgsFileWidget::SaveFile ); + mFilename->setDialogTitle( tr( "Select output file" ) ); } } diff --git a/src/gui/qgsrasterlayersaveasdialog.h b/src/gui/qgsrasterlayersaveasdialog.h index d56b92ac3838..3cd0748b0b9d 100644 --- a/src/gui/qgsrasterlayersaveasdialog.h +++ b/src/gui/qgsrasterlayersaveasdialog.h @@ -90,8 +90,6 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast private slots: void mRawModeRadioButton_toggled( bool ); - void mBrowseButton_clicked(); - void mSaveAsLineEdit_textChanged( const QString &text ); void mFormatComboBox_currentIndexChanged( const QString &text ); void mResolutionRadioButton_toggled( bool ) { toggleResolutionSize(); } void mOriginalResolutionPushButton_clicked() { setOriginalResolution(); } diff --git a/src/ui/qgsnewgeopackagelayerdialogbase.ui b/src/ui/qgsnewgeopackagelayerdialogbase.ui index 121f392ab9f6..0acbae0dbc7e 100644 --- a/src/ui/qgsnewgeopackagelayerdialogbase.ui +++ b/src/ui/qgsnewgeopackagelayerdialogbase.ui @@ -149,7 +149,7 @@ - + 0 @@ -161,16 +161,6 @@ - - - - <html><head/><body><p>Select an existing or create a new database</p></body></html> - - - - - - @@ -478,11 +468,16 @@
qgsscrollarea.h
1 + + QgsFileWidget + QWidget +
qgsfilewidget.h
+ 1 +
scrollArea - mDatabaseEdit - mSelectDatabaseButton + mDatabase mTableNameEdit mLayerIdentifierEdit mLayerDescriptionEdit diff --git a/src/ui/qgsnewvectorlayerdialogbase.ui b/src/ui/qgsnewvectorlayerdialogbase.ui index aa65bc93b5e2..f5a98c050ccc 100644 --- a/src/ui/qgsnewvectorlayerdialogbase.ui +++ b/src/ui/qgsnewvectorlayerdialogbase.ui @@ -279,23 +279,23 @@
- + - + true - + true - + @@ -305,20 +305,13 @@ - + Include Z dimension - - - - ... - - - @@ -331,9 +324,15 @@
qgsprojectionselectionwidget.h
1 + + QgsFileWidget + QWidget +
qgsfilewidget.h
+ 1 +
- mFileNameEdit + mFileName mFileEncoding mFileFormatComboBox mGeometryTypeBox diff --git a/src/ui/qgsrasterlayersaveasdialogbase.ui b/src/ui/qgsrasterlayersaveasdialogbase.ui index 63ed1e57aec0..5ce54fd3b969 100644 --- a/src/ui/qgsrasterlayersaveasdialogbase.ui +++ b/src/ui/qgsrasterlayersaveasdialogbase.ui @@ -107,28 +107,15 @@ datasets with maximum width and height specified below. Save as - mSaveAsLineEdit + mFilename
- + true - - - - - - - - - true - - - Browse... - @@ -717,14 +704,19 @@ datasets with maximum width and height specified below.
qgsrasterpyramidsoptionswidget.h
1 + + QgsFileWidget + QWidget +
qgsfilewidget.h
+ 1 +
mRawModeRadioButton mRenderedModeRadioButton mFormatComboBox mTileModeCheckBox - mSaveAsLineEdit - mBrowseButton + mFilename mCrsSelector mAddToCanvas mScrollArea diff --git a/src/ui/qgsvectorlayersaveasdialogbase.ui b/src/ui/qgsvectorlayersaveasdialogbase.ui index 10aa968819e4..f4d9b7bb3104 100644 --- a/src/ui/qgsvectorlayersaveasdialogbase.ui +++ b/src/ui/qgsvectorlayersaveasdialogbase.ui @@ -31,22 +31,12 @@
- + false - - - - false - - - Browse - - - @@ -57,7 +47,7 @@ - + @@ -66,11 +56,11 @@ File name - leFilename + mFilename - + Qt::StrongFocus @@ -83,11 +73,11 @@ Layer name - leFilename + leLayername - + false @@ -468,11 +458,16 @@ QWidget
qgsscalewidget.h
+ + QgsFileWidget + QWidget +
qgsfilewidget.h
+ 1 +
mFormatComboBox - leFilename - browseFilename + mFilename leLayername mCrsSelector scrollArea diff --git a/tests/src/python/test_qgsnewgeopackagelayerdialog.py b/tests/src/python/test_qgsnewgeopackagelayerdialog.py index 41aefec87c84..63de1a3c1173 100644 --- a/tests/src/python/test_qgsnewgeopackagelayerdialog.py +++ b/tests/src/python/test_qgsnewgeopackagelayerdialog.py @@ -63,7 +63,7 @@ def test(self): dialog = QgsNewGeoPackageLayerDialog() dialog.setProperty("hideDialogs", True) - mDatabaseEdit = dialog.findChild(QLineEdit, "mDatabaseEdit") + mDatabase = dialog.findChild(QLineEdit, "mDatabase") buttonBox = dialog.findChild(QDialogButtonBox, "buttonBox") ok_button = buttonBox.button(QDialogButtonBox.Ok) mTableNameEdit = dialog.findChild(QLineEdit, "mTableNameEdit") @@ -86,7 +86,7 @@ def test(self): self.assertFalse(ok_button.isEnabled()) dbname = os.path.join(self.basetestpath, 'test.gpkg') - mDatabaseEdit.setText(dbname) + mDatabase.setFilePath(dbname) self.assertEqual(mTableNameEdit.text(), 'test') self.assertEqual(mLayerIdentifierEdit.text(), 'test') self.assertTrue(ok_button.isEnabled()) @@ -261,7 +261,7 @@ def test(self): QgsProject.instance().removeAllMapLayers() # Try invalid path - mDatabaseEdit.setText('/this/is/invalid/test.gpkg') + mDatabase.setFilePath('/this/is/invalid/test.gpkg') self.accepted = False QTest.mouseClick(ok_button, Qt.LeftButton) self.assertFalse(self.accepted)