From cddca2f8501ab1c98ec776316a7c5cba9f384757 Mon Sep 17 00:00:00 2001 From: nirvn Date: Thu, 7 Dec 2017 11:22:03 +0700 Subject: [PATCH 1/5] [file widget] add a save file mode to allow file creation --- src/gui/qgsfilewidget.cpp | 12 ++++++++++++ src/gui/qgsfilewidget.h | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/gui/qgsfilewidget.cpp b/src/gui/qgsfilewidget.cpp index 960bd3ba132..df599d13ede 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 1c81aa523db..f1dcaf76d19 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,17 @@ class GUI_EXPORT QgsFileWidget : public QWidget */ void setFilter( const QString &filter ); + /** + * Sets whether a confirmation to overwrite an existing file 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 +185,7 @@ class GUI_EXPORT QgsFileWidget : public QWidget QString mDialogTitle; QString mFilter; QString mDefaultRoot; + bool mConfirmOverwrite = true; StorageMode mStorageMode = GetFile; RelativeStorage mRelativeStorage = Absolute; From c2acb5feeca1ece4b47dff2cf70bbc87599268b6 Mon Sep 17 00:00:00 2001 From: nirvn Date: Thu, 7 Dec 2017 10:40:17 +0700 Subject: [PATCH 2/5] [ui] use qgsfilewidget in the create shapefile layer dialog --- python/gui/qgsfilewidget.sip | 13 ++++++++++ src/gui/qgsnewvectorlayerdialog.cpp | 37 +++++++++++++-------------- src/gui/qgsnewvectorlayerdialog.h | 1 - src/ui/qgsnewvectorlayerdialogbase.ui | 25 +++++++++--------- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/python/gui/qgsfilewidget.sip b/python/gui/qgsfilewidget.sip index 180840ab3d8..2e7b61c6376 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,18 @@ 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 + \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/qgsnewvectorlayerdialog.cpp b/src/gui/qgsnewvectorlayerdialog.cpp index 8905d56b08b..3e8c2c22993 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 003e64e0a8a..f8c177c4d23 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/ui/qgsnewvectorlayerdialogbase.ui b/src/ui/qgsnewvectorlayerdialogbase.ui index aa65bc93b5e..f5a98c050cc 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 From 38c96fe3732e7df12c5818129caf25823b7903c4 Mon Sep 17 00:00:00 2001 From: nirvn Date: Thu, 7 Dec 2017 11:34:44 +0700 Subject: [PATCH 3/5] [ui] use qgsfilewidget in the create geopackage layer dialog --- src/gui/qgsnewgeopackagelayerdialog.cpp | 63 ++++++++----------- src/gui/qgsnewgeopackagelayerdialog.h | 6 +- src/ui/qgsnewgeopackagelayerdialogbase.ui | 21 +++---- .../test_qgsnewgeopackagelayerdialog.py | 6 +- 4 files changed, 38 insertions(+), 58 deletions(-) diff --git a/src/gui/qgsnewgeopackagelayerdialog.cpp b/src/gui/qgsnewgeopackagelayerdialog.cpp index 0da9df6d938..b17a5e2b8eb 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 fb6f6f678ab..c2982a7d0c4 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/ui/qgsnewgeopackagelayerdialogbase.ui b/src/ui/qgsnewgeopackagelayerdialogbase.ui index 121f392ab9f..0acbae0dbc7 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/tests/src/python/test_qgsnewgeopackagelayerdialog.py b/tests/src/python/test_qgsnewgeopackagelayerdialog.py index 41aefec87c8..63de1a3c117 100644 --- a/tests/src/python/test_qgsnewgeopackagelayerdialog.py +++ b/tests/src/python/test_qgsnewgeopackagelayerdialog.py @@ -63,7 +63,7 @@ class TestPyQgsNewGeoPackageLayerDialog(unittest.TestCase): 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 @@ class TestPyQgsNewGeoPackageLayerDialog(unittest.TestCase): 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 @@ class TestPyQgsNewGeoPackageLayerDialog(unittest.TestCase): 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) From 09e830bf08e991a9946448981da616361e2475b3 Mon Sep 17 00:00:00 2001 From: nirvn Date: Thu, 7 Dec 2017 12:13:57 +0700 Subject: [PATCH 4/5] [ui] use qgsfilewidget in the save vector as dialog --- src/gui/ogr/qgsvectorlayersaveasdialog.cpp | 55 ++++++++++------------ src/gui/ogr/qgsvectorlayersaveasdialog.h | 2 - src/ui/qgsvectorlayersaveasdialogbase.ui | 31 +++++------- 3 files changed, 37 insertions(+), 51 deletions(-) diff --git a/src/gui/ogr/qgsvectorlayersaveasdialog.cpp b/src/gui/ogr/qgsvectorlayersaveasdialog.cpp index 8d3b0c1b7bc..fe397bf63cb 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 a3cb1764fd3..2baf88fbc9a 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/ui/qgsvectorlayersaveasdialogbase.ui b/src/ui/qgsvectorlayersaveasdialogbase.ui index 10aa968819e..f4d9b7bb310 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 From de0ac14ae11a18b125f9d056446f262748991896 Mon Sep 17 00:00:00 2001 From: nirvn Date: Thu, 7 Dec 2017 15:58:27 +0700 Subject: [PATCH 5/5] [ui] use qgsfilewidget in the save raster as dialog --- python/gui/qgsfilewidget.sip | 3 +- src/gui/qgsfilewidget.h | 3 +- src/gui/qgsrasterlayersaveasdialog.cpp | 169 ++++++++++++----------- src/gui/qgsrasterlayersaveasdialog.h | 2 - src/ui/qgsrasterlayersaveasdialogbase.ui | 26 ++-- 5 files changed, 99 insertions(+), 104 deletions(-) diff --git a/python/gui/qgsfilewidget.sip b/python/gui/qgsfilewidget.sip index 2e7b61c6376..3af4645cfdd 100644 --- a/python/gui/qgsfilewidget.sip +++ b/python/gui/qgsfilewidget.sip @@ -100,7 +100,8 @@ returns the filters used for QDialog.getOpenFileName void setConfirmOverwrite( bool confirmOverwrite ); %Docstring - Sets whether a confirmation to overwrite an existing file will appear + 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 diff --git a/src/gui/qgsfilewidget.h b/src/gui/qgsfilewidget.h index f1dcaf76d19..15771846579 100644 --- a/src/gui/qgsfilewidget.h +++ b/src/gui/qgsfilewidget.h @@ -122,7 +122,8 @@ class GUI_EXPORT QgsFileWidget : public QWidget void setFilter( const QString &filter ); /** - * Sets whether a confirmation to overwrite an existing file will appear + * 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; } diff --git a/src/gui/qgsrasterlayersaveasdialog.cpp b/src/gui/qgsrasterlayersaveasdialog.cpp index ff104324371..48fb3cf8510 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 d56b92ac383..3cd0748b0b9 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/qgsrasterlayersaveasdialogbase.ui b/src/ui/qgsrasterlayersaveasdialogbase.ui index 63ed1e57aec..5ce54fd3b96 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