mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
Make use of nice new tech for the new spatialite layer dialog:
- Use a provider connection combo box to list connections - Use database provider connection functions to store a new connection
This commit is contained in:
parent
2cbdcaf926
commit
35c11288a0
@ -33,6 +33,17 @@ The QgsProviderConnectionComboBox class is a combo box which displays the list o
|
||||
%Docstring
|
||||
Constructor for QgsProviderConnectionComboBox, for the specified ``provider``.
|
||||
|
||||
.. warning::
|
||||
|
||||
The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
in order for the model to work correctly.
|
||||
%End
|
||||
|
||||
|
||||
void setProvider( const QString &provider );
|
||||
%Docstring
|
||||
Sets the provider to be used.
|
||||
|
||||
.. warning::
|
||||
|
||||
The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
|
@ -22,12 +22,16 @@
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsabstractdatabaseproviderconnection.h"
|
||||
#include "qgisapp.h" // <- for theme icons
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgsfileutils.h"
|
||||
#include "qgsprojectionselectiondialog.h"
|
||||
#include "qgsproviderconnectionmodel.h"
|
||||
#include "qgsprovidermetadata.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsspatialiteutils.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgssettings.h"
|
||||
@ -51,7 +55,7 @@ QgsNewSpatialiteLayerDialog::QgsNewSpatialiteLayerDialog( QWidget *parent, Qt::W
|
||||
connect( mGeometryTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewSpatialiteLayerDialog::mGeometryTypeBox_currentIndexChanged );
|
||||
connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsNewSpatialiteLayerDialog::mTypeBox_currentIndexChanged );
|
||||
connect( pbnFindSRID, &QPushButton::clicked, this, &QgsNewSpatialiteLayerDialog::pbnFindSRID_clicked );
|
||||
connect( toolButtonNewDatabase, &QToolButton::clicked, this, &QgsNewSpatialiteLayerDialog::toolButtonNewDatabase_clicked );
|
||||
connect( toolButtonNewDatabase, &QToolButton::clicked, this, &QgsNewSpatialiteLayerDialog::createDb );
|
||||
connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsNewSpatialiteLayerDialog::buttonBox_accepted );
|
||||
connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsNewSpatialiteLayerDialog::buttonBox_rejected );
|
||||
|
||||
@ -75,20 +79,7 @@ QgsNewSpatialiteLayerDialog::QgsNewSpatialiteLayerDialog( QWidget *parent, Qt::W
|
||||
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) ), tr( "Whole number" ), "integer" );
|
||||
mTypeBox->addItem( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) ), tr( "Decimal number" ), "real" );
|
||||
|
||||
// Populate the database list from the stored connections
|
||||
QgsSettings settings;
|
||||
settings.beginGroup( QStringLiteral( "SpatiaLite/connections" ) );
|
||||
QStringList keys = settings.childGroups();
|
||||
QStringList::Iterator it = keys.begin();
|
||||
mDatabaseComboBox->clear();
|
||||
while ( it != keys.end() )
|
||||
{
|
||||
// retrieving the SQLite DB name and full path
|
||||
QString text = settings.value( *it + "/sqlitepath", "###unknown###" ).toString();
|
||||
mDatabaseComboBox->addItem( text );
|
||||
++it;
|
||||
}
|
||||
settings.endGroup();
|
||||
mDatabaseComboBox->setProvider( QStringLiteral( "spatialite" ) );
|
||||
|
||||
mOkButton = buttonBox->button( QDialogButtonBox::Ok );
|
||||
mOkButton->setEnabled( false );
|
||||
@ -132,26 +123,6 @@ void QgsNewSpatialiteLayerDialog::mTypeBox_currentIndexChanged( int index )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsNewSpatialiteLayerDialog::toolButtonNewDatabase_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName( this, tr( "New SpatiaLite Database File" ),
|
||||
QDir::homePath(),
|
||||
tr( "SpatiaLite" ) + " (*.sqlite *.db *.sqlite3 *.db3 *.s3db)", nullptr, QFileDialog::DontConfirmOverwrite );
|
||||
|
||||
if ( fileName.isEmpty() )
|
||||
return;
|
||||
|
||||
if ( !fileName.endsWith( QLatin1String( ".sqlite" ), Qt::CaseInsensitive ) && !fileName.endsWith( QLatin1String( ".db" ), Qt::CaseInsensitive ) )
|
||||
{
|
||||
fileName += QLatin1String( ".sqlite" );
|
||||
}
|
||||
|
||||
mDatabaseComboBox->insertItem( 0, fileName );
|
||||
mDatabaseComboBox->setCurrentIndex( 0 );
|
||||
|
||||
createDb();
|
||||
}
|
||||
|
||||
QString QgsNewSpatialiteLayerDialog::selectedType() const
|
||||
{
|
||||
return mGeometryTypeBox->currentData( Qt::UserRole ).toString();
|
||||
@ -206,11 +177,14 @@ void QgsNewSpatialiteLayerDialog::mRemoveAttributeButton_clicked()
|
||||
|
||||
void QgsNewSpatialiteLayerDialog::pbnFindSRID_clicked()
|
||||
{
|
||||
const QgsDataSourceUri dbUri = mDatabaseComboBox->currentConnectionUri();
|
||||
const QString dbPath = dbUri.database();
|
||||
|
||||
// first get list of supported SRID from the selected SpatiaLite database
|
||||
// to build filter for projection selector
|
||||
sqlite3_database_unique_ptr database;
|
||||
bool status = true;
|
||||
int rc = database.open_v2( mDatabaseComboBox->currentText(), SQLITE_OPEN_READONLY, nullptr );
|
||||
int rc = database.open_v2( dbPath, SQLITE_OPEN_READONLY, nullptr );
|
||||
if ( rc != SQLITE_OK )
|
||||
{
|
||||
QMessageBox::warning( this, tr( "SpatiaLite Database" ), tr( "Unable to open the database" ) );
|
||||
@ -274,10 +248,15 @@ void QgsNewSpatialiteLayerDialog::selectionChanged()
|
||||
|
||||
bool QgsNewSpatialiteLayerDialog::createDb()
|
||||
{
|
||||
QString dbPath = mDatabaseComboBox->currentText();
|
||||
QString dbPath = QFileDialog::getSaveFileName( this, tr( "New SpatiaLite Database File" ),
|
||||
QDir::homePath(),
|
||||
tr( "SpatiaLite" ) + " (*.sqlite *.db *.sqlite3 *.db3 *.s3db)", nullptr, QFileDialog::DontConfirmOverwrite );
|
||||
|
||||
if ( dbPath.isEmpty() )
|
||||
return false;
|
||||
|
||||
QgsFileUtils::ensureFileNameHasExtension( dbPath, QStringList() << QStringLiteral( ".sqlite" ) << QLatin1String( ".db" ) << QLatin1String( ".sqlite3" )
|
||||
<< QLatin1String( ".db3" ) << QLatin1String( ".s3db" ) );
|
||||
QFile newDb( dbPath );
|
||||
if ( newDb.exists() )
|
||||
{
|
||||
@ -316,24 +295,21 @@ bool QgsNewSpatialiteLayerDialog::createDb()
|
||||
if ( !fi.exists() )
|
||||
{
|
||||
pbnFindSRID->setEnabled( false );
|
||||
return false;
|
||||
}
|
||||
|
||||
QString key = "/SpatiaLite/connections/" + fi.fileName() + "/sqlitepath";
|
||||
|
||||
QgsSettings settings;
|
||||
if ( !settings.contains( key ) )
|
||||
else
|
||||
{
|
||||
settings.setValue( QStringLiteral( "SpatiaLite/connections/selected" ), fi.fileName() + tr( "@" ) + fi.canonicalFilePath() );
|
||||
settings.setValue( key, fi.canonicalFilePath() );
|
||||
|
||||
// Reload connections to refresh browser panel
|
||||
QgisApp::instance()->reloadConnections();
|
||||
QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "spatialite" ) ) };
|
||||
std::unique_ptr<QgsAbstractDatabaseProviderConnection> conn( static_cast<QgsAbstractDatabaseProviderConnection *>( md->createConnection( QStringLiteral( "dbname='%1'" ).arg( dbPath ), QVariantMap() ) ) );
|
||||
if ( conn )
|
||||
{
|
||||
md->saveConnection( conn.get(), fi.fileName() );
|
||||
mDatabaseComboBox->setConnection( fi.fileName() );
|
||||
pbnFindSRID->setEnabled( true );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
pbnFindSRID->setEnabled( true );
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsNewSpatialiteLayerDialog::buttonBox_accepted()
|
||||
@ -349,6 +325,9 @@ void QgsNewSpatialiteLayerDialog::buttonBox_rejected()
|
||||
|
||||
bool QgsNewSpatialiteLayerDialog::apply()
|
||||
{
|
||||
const QgsDataSourceUri dbUri = mDatabaseComboBox->currentConnectionUri();
|
||||
const QString dbPath = dbUri.database();
|
||||
|
||||
// Build up the sql statement for creating the table
|
||||
QString sql = QStringLiteral( "create table %1(" ).arg( quotedIdentifier( leLayerName->text() ) );
|
||||
QString delim;
|
||||
@ -369,16 +348,16 @@ bool QgsNewSpatialiteLayerDialog::apply()
|
||||
// complete the create table statement
|
||||
sql += ')';
|
||||
|
||||
QgsDebugMsg( QStringLiteral( "Creating table in database %1" ).arg( mDatabaseComboBox->currentText() ) );
|
||||
QgsDebugMsg( QStringLiteral( "Creating table in database %1" ).arg( dbPath ) );
|
||||
QgsDebugMsg( sql );
|
||||
|
||||
spatialite_database_unique_ptr database;
|
||||
int rc = database.open( mDatabaseComboBox->currentText() );
|
||||
int rc = database.open( dbPath );
|
||||
if ( rc != SQLITE_OK )
|
||||
{
|
||||
QMessageBox::warning( this,
|
||||
tr( "SpatiaLite Database" ),
|
||||
tr( "Unable to open the database: %1" ).arg( mDatabaseComboBox->currentText() ) );
|
||||
tr( "Unable to open the database: %1" ).arg( dbPath ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -433,8 +412,10 @@ bool QgsNewSpatialiteLayerDialog::apply()
|
||||
}
|
||||
|
||||
const QgsVectorLayer::LayerOptions options { QgsProject::instance()->transformContext() };
|
||||
QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "dbname='%1' table='%2'%3 sql=" )
|
||||
.arg( mDatabaseComboBox->currentText(),
|
||||
const QString uri = QStringLiteral( "dbname='%1' table='%2'%3 sql=" ).arg( dbPath, leLayerName->text(),
|
||||
mGeometryTypeBox->currentIndex() != 0 ? QStringLiteral( "(%1)" ).arg( leGeometryColumn->text() ) : QString() );
|
||||
QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "%1 table='%2'%3 sql=" )
|
||||
.arg( mDatabaseComboBox->currentConnectionUri(),
|
||||
leLayerName->text(),
|
||||
mGeometryTypeBox->currentIndex() != 0 ? QStringLiteral( "(%1)" ).arg( leGeometryColumn->text() ) : QString() ),
|
||||
leLayerName->text(), QStringLiteral( "spatialite" ), options );
|
||||
|
@ -44,7 +44,6 @@ class APP_EXPORT QgsNewSpatialiteLayerDialog: public QDialog, private Ui::QgsNew
|
||||
void mGeometryTypeBox_currentIndexChanged( int index );
|
||||
void mTypeBox_currentIndexChanged( int index );
|
||||
void pbnFindSRID_clicked();
|
||||
void toolButtonNewDatabase_clicked();
|
||||
void nameChanged( const QString & );
|
||||
void selectionChanged();
|
||||
void checkOk();
|
||||
|
@ -19,6 +19,25 @@
|
||||
QgsProviderConnectionComboBox::QgsProviderConnectionComboBox( const QString &provider, QWidget *parent )
|
||||
: QComboBox( parent )
|
||||
{
|
||||
setProvider( provider );
|
||||
}
|
||||
|
||||
QgsProviderConnectionComboBox::QgsProviderConnectionComboBox( QWidget *parent )
|
||||
: QComboBox( parent )
|
||||
{
|
||||
}
|
||||
|
||||
void QgsProviderConnectionComboBox::setProvider( const QString &provider )
|
||||
{
|
||||
if ( mSortModel )
|
||||
{
|
||||
disconnect( this, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::activated ), this, &QgsProviderConnectionComboBox::indexChanged );
|
||||
disconnect( mSortModel, &QAbstractItemModel::rowsInserted, this, &QgsProviderConnectionComboBox::rowsChanged );
|
||||
disconnect( mSortModel, &QAbstractItemModel::rowsRemoved, this, &QgsProviderConnectionComboBox::rowsChanged );
|
||||
delete mSortModel;
|
||||
delete mModel;
|
||||
}
|
||||
|
||||
mModel = new QgsProviderConnectionModel( provider, this );
|
||||
|
||||
mSortModel = new QgsProviderConnectionComboBoxSortModel( this );
|
||||
|
@ -60,6 +60,16 @@ class GUI_EXPORT QgsProviderConnectionComboBox : public QComboBox
|
||||
*/
|
||||
explicit QgsProviderConnectionComboBox( const QString &provider, QWidget *parent SIP_TRANSFERTHIS = nullptr );
|
||||
|
||||
explicit QgsProviderConnectionComboBox( QWidget *parent = nullptr ) SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Sets the provider to be used.
|
||||
*
|
||||
* \warning The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
* in order for the model to work correctly.
|
||||
*/
|
||||
void setProvider( const QString &provider );
|
||||
|
||||
/**
|
||||
* Sets whether an optional empty connection ("not set") option is present in the combobox.
|
||||
* \see allowEmptyConnection()
|
||||
|
@ -70,7 +70,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="mDatabaseComboBox">
|
||||
<widget class="QgsProviderConnectionComboBox" name="mDatabaseComboBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -448,6 +448,12 @@
|
||||
<header>qgscollapsiblegroupbox.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsProviderConnectionComboBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qgsproviderconnectioncombobox.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
|
@ -116,6 +116,20 @@ class TestQgsProviderConnectionComboBox(unittest.TestCase):
|
||||
|
||||
md.deleteConnection('aaa_qgis_test2')
|
||||
|
||||
def testComboSetProvider(self):
|
||||
""" test combobox functionality with empty entry """
|
||||
m = QgsProviderConnectionComboBox('ogr')
|
||||
|
||||
md = QgsProviderRegistry.instance().providerMetadata('ogr')
|
||||
conn = md.createConnection(self.gpkg_path, {})
|
||||
md.saveConnection(conn, 'qgis_test_zzz')
|
||||
|
||||
self.assertEqual(m.count(), 1)
|
||||
m.setProvider('ogr')
|
||||
self.assertEqual(m.count(), 1)
|
||||
|
||||
md.deleteConnection('qgis_test_zzz')
|
||||
|
||||
def testComboWithEmpty(self):
|
||||
""" test combobox functionality with empty entry """
|
||||
m = QgsProviderConnectionComboBox('ogr')
|
||||
|
Loading…
x
Reference in New Issue
Block a user