mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-03 00:02:25 -05:00
New database table widget new signals & tests
This commit is contained in:
parent
d1404ac5ae
commit
b42bdddd87
@ -20,6 +20,11 @@ The table name is validated for uniqueness and the selected
|
||||
data item provider, schema and table names can be retrieved with
|
||||
getters.
|
||||
|
||||
.. warning::
|
||||
|
||||
The data provider that originated the data item provider
|
||||
must support the connections API
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
@ -35,8 +40,9 @@ getters.
|
||||
Constructs a new QgsNewDatabaseTableNameWidget
|
||||
|
||||
:param browserModel: an existing browser model (typically from app), if NULL an instance will be created
|
||||
:param providersFilter: optional white list of item provider names (not data providers!) that should be
|
||||
shown in the widget, if not specified all providers data items with database capabilities will be shown
|
||||
:param providersFilter: optional white list of data provider keys that should be
|
||||
shown in the widget, if not specified all providers data items with database
|
||||
capabilities will be shown
|
||||
:param parent: optional parent for this widget
|
||||
%End
|
||||
|
||||
@ -50,9 +56,9 @@ Returns the currently selected schema for the new table
|
||||
Returns the current name of the new table
|
||||
%End
|
||||
|
||||
QString dataItemProviderName();
|
||||
QString dataProviderKey();
|
||||
%Docstring
|
||||
Returns the currently selected data item provider name (which is NOT the data provider key!) for the new table
|
||||
Returns the currently selected data item provider key
|
||||
%End
|
||||
|
||||
bool isValid() const;
|
||||
@ -88,6 +94,14 @@ This signal is emitted when the user enters a table name
|
||||
:param tableName: the name of the new table
|
||||
%End
|
||||
|
||||
void providerKeyChanged( const QString &providerKey );
|
||||
%Docstring
|
||||
This signal is emitted when the selects a data provider or a schema name
|
||||
that has a different data provider than the previously selected one.
|
||||
|
||||
:param providerKey: the data provider key of the selected schema
|
||||
%End
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsdataitemproviderregistry.h"
|
||||
#include "qgsdataitemprovider.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsprovidermetadata.h"
|
||||
|
||||
QgsNewDatabaseTableNameWidget::QgsNewDatabaseTableNameWidget(
|
||||
QgsBrowserGuiModel *browserModel,
|
||||
@ -28,7 +30,6 @@ QgsNewDatabaseTableNameWidget::QgsNewDatabaseTableNameWidget(
|
||||
: QWidget( parent )
|
||||
{
|
||||
|
||||
|
||||
// Initalize the browser
|
||||
if ( ! browserModel )
|
||||
{
|
||||
@ -43,6 +44,8 @@ QgsNewDatabaseTableNameWidget::QgsNewDatabaseTableNameWidget(
|
||||
|
||||
setupUi( this );
|
||||
|
||||
mValidationResults->setStyleSheet( QStringLiteral( "* { font-weight: bold; color: red; }" ) );
|
||||
|
||||
QStringList hiddenProviders
|
||||
{
|
||||
QStringLiteral( "special:Favorites" ),
|
||||
@ -55,15 +58,26 @@ QgsNewDatabaseTableNameWidget::QgsNewDatabaseTableNameWidget(
|
||||
const auto providerList { QgsApplication::dataItemProviderRegistry()->providers() };
|
||||
for ( const auto &provider : providerList )
|
||||
{
|
||||
if ( provider->dataProviderKey().isEmpty() )
|
||||
{
|
||||
hiddenProviders.push_back( provider->name() );
|
||||
continue;
|
||||
}
|
||||
QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( provider->dataProviderKey() ) };
|
||||
if ( ! md )
|
||||
{
|
||||
hiddenProviders.push_back( provider->name() );
|
||||
continue;
|
||||
}
|
||||
if ( provider->capabilities() & QgsDataProvider::DataCapability::Database )
|
||||
{
|
||||
if ( ! providersFilter.isEmpty() && ! providersFilter.contains( provider->name() ) )
|
||||
if ( ! providersFilter.isEmpty() && ! providersFilter.contains( provider->dataProviderKey() ) )
|
||||
{
|
||||
hiddenProviders.push_back( provider->name() );
|
||||
}
|
||||
else
|
||||
{
|
||||
mShownProviders.insert( provider->name() );
|
||||
mShownProviders.insert( provider->dataProviderKey() );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -98,26 +112,41 @@ QgsNewDatabaseTableNameWidget::QgsNewDatabaseTableNameWidget(
|
||||
const QgsDataCollectionItem *collectionItem = qobject_cast<const QgsDataCollectionItem *>( dataItem );
|
||||
if ( collectionItem )
|
||||
{
|
||||
if ( mShownProviders.contains( collectionItem->name() ) )
|
||||
const QString providerKey { QgsApplication::dataItemProviderRegistry()->dataProviderKey( dataItem->providerKey() ) };
|
||||
if ( mShownProviders.contains( providerKey ) )
|
||||
{
|
||||
if ( mDataProviderName != collectionItem->name() )
|
||||
bool validationRequired { false };
|
||||
const QString oldSchema { mSchemaName };
|
||||
|
||||
if ( mDataProviderKey != providerKey )
|
||||
{
|
||||
mSchemaName.clear();
|
||||
mDataProviderName = collectionItem->name();
|
||||
emit providerKeyChanged( providerKey );
|
||||
mDataProviderKey = providerKey;
|
||||
validate();
|
||||
}
|
||||
|
||||
if ( collectionItem->layerCollection( ) )
|
||||
{
|
||||
mSchemaName = collectionItem->name(); // it may be cleared
|
||||
if ( oldSchema != collectionItem->name() )
|
||||
{
|
||||
emit schemaNameChanged( mSchemaName );
|
||||
validationRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( validationRequired )
|
||||
{
|
||||
validate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSchemaName = collectionItem->name();
|
||||
emit schemaNameChanged( mSchemaName );
|
||||
}
|
||||
validate();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
mValidationResults->hide();
|
||||
validate();
|
||||
|
||||
}
|
||||
|
||||
@ -131,16 +160,17 @@ QString QgsNewDatabaseTableNameWidget::table()
|
||||
return mTableName;
|
||||
}
|
||||
|
||||
QString QgsNewDatabaseTableNameWidget::dataItemProviderName()
|
||||
QString QgsNewDatabaseTableNameWidget::dataProviderKey()
|
||||
{
|
||||
return mDataProviderName;
|
||||
return mDataProviderKey;
|
||||
}
|
||||
|
||||
void QgsNewDatabaseTableNameWidget::validate()
|
||||
{
|
||||
const bool wasValid { mIsValid };
|
||||
// Check table uniqueness
|
||||
mIsValid = ! mDataProviderName.isEmpty() &&
|
||||
mShownProviders.contains( mDataProviderName ) &&
|
||||
mIsValid = ! mDataProviderKey.isEmpty() &&
|
||||
mShownProviders.contains( mDataProviderKey ) &&
|
||||
! mSchemaName.isEmpty() &&
|
||||
! mTableName.isEmpty() &&
|
||||
! tableNames( ).contains( mTableName );
|
||||
@ -149,27 +179,39 @@ void QgsNewDatabaseTableNameWidget::validate()
|
||||
|
||||
if ( ! mIsValid )
|
||||
{
|
||||
|
||||
if ( mTableName.isEmpty() )
|
||||
if ( mTableName.isEmpty() && mSchemaName.isEmpty() )
|
||||
{
|
||||
mValidationError = tr( "Enter a unique name for the new table" );
|
||||
mValidationError = tr( "Select a database schema and enter a unique name for the new table" );
|
||||
}
|
||||
else if ( ! mTableName.isEmpty() &&
|
||||
! mSchemaName.isEmpty() &&
|
||||
tableNames( ).contains( mTableName ) )
|
||||
{
|
||||
mValidationError = tr( "A table named '%1' already exists" ).arg( mTableName );
|
||||
}
|
||||
else if ( mSchemaName.isEmpty() )
|
||||
{
|
||||
mValidationError = tr( "Select a database schema" );
|
||||
}
|
||||
else if ( mTableName.isEmpty() )
|
||||
{
|
||||
mValidationError = tr( "Enter a unique name for the new table" );
|
||||
}
|
||||
else if ( tableNames( ).contains( mTableName ) )
|
||||
{
|
||||
mValidationError = tr( "A table named '%1' already exists" ).arg( mTableName );
|
||||
}
|
||||
else
|
||||
{
|
||||
mValidationError = tr( "Select a schema and enter a unique name for the new table" );
|
||||
mValidationError = tr( "Select a database schema and enter a unique name for the new table" );
|
||||
}
|
||||
}
|
||||
mValidationResults->setText( mValidationError );
|
||||
mValidationResults->setVisible( ! mIsValid );
|
||||
emit validationChanged( mIsValid );
|
||||
if ( wasValid != mIsValid )
|
||||
{
|
||||
emit validationChanged( mIsValid );
|
||||
}
|
||||
}
|
||||
|
||||
QStringList QgsNewDatabaseTableNameWidget::tableNames()
|
||||
@ -178,16 +220,34 @@ QStringList QgsNewDatabaseTableNameWidget::tableNames()
|
||||
QModelIndex index { mBrowserTreeView->currentIndex() };
|
||||
if ( index.isValid() )
|
||||
{
|
||||
for ( int row = 0; row < mBrowserProxyModel.rowCount( ); ++row )
|
||||
QgsDataItem *dataItem { mBrowserProxyModel.dataItem( index ) };
|
||||
if ( dataItem )
|
||||
{
|
||||
// Column 1 contains the
|
||||
index = mBrowserProxyModel.index( row, 1, index );
|
||||
if ( index.isValid() )
|
||||
const QString dataProviderKey { QgsApplication::dataItemProviderRegistry()->dataProviderKey( dataItem->providerKey() ) };
|
||||
if ( ! dataProviderKey.isEmpty() )
|
||||
{
|
||||
const QgsDataItem *dataItem { mBrowserProxyModel.dataItem( index ) };
|
||||
if ( dataItem )
|
||||
QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( dataProviderKey ) };
|
||||
if ( md )
|
||||
{
|
||||
tableNames.push_back( dataItem->name() );
|
||||
QgsDataItem *parentDataItem { dataItem->parent() };
|
||||
if ( parentDataItem )
|
||||
{
|
||||
QgsAbstractProviderConnection *conn { md->findConnection( parentDataItem->name() ) };
|
||||
const QString cacheKey { conn->uri() + dataItem->name() };
|
||||
if ( mTableNamesCache.contains( cacheKey ) )
|
||||
{
|
||||
tableNames = mTableNamesCache.value( cacheKey );
|
||||
}
|
||||
else if ( conn && static_cast<QgsAbstractDatabaseProviderConnection *>( conn ) )
|
||||
{
|
||||
const auto tables { static_cast<QgsAbstractDatabaseProviderConnection *>( conn )->tables( dataItem->name() ) };
|
||||
for ( const auto &tp : tables )
|
||||
{
|
||||
tableNames.push_back( tp.tableName() );
|
||||
}
|
||||
mTableNamesCache[ cacheKey ] = tableNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,9 @@
|
||||
* data item provider, schema and table names can be retrieved with
|
||||
* getters.
|
||||
*
|
||||
* \warning The data provider that originated the data item provider
|
||||
* must support the connections API
|
||||
*
|
||||
* \since QGIS 3.14
|
||||
*/
|
||||
class GUI_EXPORT QgsNewDatabaseTableNameWidget : public QWidget, private Ui::QgsNewDatabaseTableNameWidget
|
||||
@ -46,8 +49,9 @@ class GUI_EXPORT QgsNewDatabaseTableNameWidget : public QWidget, private Ui::Qgs
|
||||
* Constructs a new QgsNewDatabaseTableNameWidget
|
||||
*
|
||||
* \param browserModel an existing browser model (typically from app), if NULL an instance will be created
|
||||
* \param providersFilter optional white list of item provider names (not data providers!) that should be
|
||||
* shown in the widget, if not specified all providers data items with database capabilities will be shown
|
||||
* \param providersFilter optional white list of data provider keys that should be
|
||||
* shown in the widget, if not specified all providers data items with database
|
||||
* capabilities will be shown
|
||||
* \param parent optional parent for this widget
|
||||
*/
|
||||
explicit QgsNewDatabaseTableNameWidget( QgsBrowserGuiModel *browserModel = nullptr,
|
||||
@ -65,9 +69,9 @@ class GUI_EXPORT QgsNewDatabaseTableNameWidget : public QWidget, private Ui::Qgs
|
||||
QString table();
|
||||
|
||||
/**
|
||||
* Returns the currently selected data item provider name (which is NOT the data provider key!) for the new table
|
||||
* Returns the currently selected data item provider key
|
||||
*/
|
||||
QString dataItemProviderName();
|
||||
QString dataProviderKey();
|
||||
|
||||
/**
|
||||
* Returns TRUE if the widget contains a valid new table name
|
||||
@ -102,6 +106,14 @@ class GUI_EXPORT QgsNewDatabaseTableNameWidget : public QWidget, private Ui::Qgs
|
||||
*/
|
||||
void tableNameChanged( const QString &tableName );
|
||||
|
||||
/**
|
||||
* This signal is emitted when the selects a data provider or a schema name
|
||||
* that has a different data provider than the previously selected one.
|
||||
*
|
||||
* \param providerKey the data provider key of the selected schema
|
||||
*/
|
||||
void providerKeyChanged( const QString &providerKey );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@ -109,12 +121,16 @@ class GUI_EXPORT QgsNewDatabaseTableNameWidget : public QWidget, private Ui::Qgs
|
||||
QgsBrowserGuiModel *mBrowserModel = nullptr;
|
||||
void validate();
|
||||
QStringList tableNames();
|
||||
QString mDataProviderName;
|
||||
QString mDataProviderKey;
|
||||
QString mTableName;
|
||||
QString mSchemaName;
|
||||
//! List of data provider keys of shown providers
|
||||
QSet<QString> mShownProviders;
|
||||
bool mIsValid = false;
|
||||
QString mValidationError;
|
||||
//! Table names cache
|
||||
QMap<QString, QStringList> mTableNamesCache;
|
||||
|
||||
|
||||
// For testing:
|
||||
friend class TestQgsNewDatabaseTableNameWidget;
|
||||
|
@ -30,8 +30,6 @@ class TestQgsNewDatabaseTableNameWidget: public QObject
|
||||
public:
|
||||
TestQgsNewDatabaseTableNameWidget() = default;
|
||||
|
||||
void testWidget();
|
||||
|
||||
private slots:
|
||||
void initTestCase(); // will be called before the first testfunction is executed.
|
||||
void cleanupTestCase(); // will be called after the last testfunction was executed.
|
||||
@ -74,14 +72,14 @@ void TestQgsNewDatabaseTableNameWidget::testWidgetFilters()
|
||||
QCOMPARE( w->mBrowserProxyModel.rowCount(), 0 );
|
||||
std::unique_ptr<QgsNewDatabaseTableNameWidget> w2 { qgis::make_unique<QgsNewDatabaseTableNameWidget>( nullptr ) };
|
||||
QVERIFY( w2->mBrowserProxyModel.rowCount() > 0 );
|
||||
std::unique_ptr<QgsNewDatabaseTableNameWidget> w3 { qgis::make_unique<QgsNewDatabaseTableNameWidget>( nullptr, QStringList{ "PostGIS" } ) };
|
||||
std::unique_ptr<QgsNewDatabaseTableNameWidget> w3 { qgis::make_unique<QgsNewDatabaseTableNameWidget>( nullptr, QStringList{ "postgres" } ) };
|
||||
QVERIFY( w3->mBrowserProxyModel.rowCount() > 0 );
|
||||
}
|
||||
|
||||
|
||||
void TestQgsNewDatabaseTableNameWidget::testWidgetSignals()
|
||||
{
|
||||
std::unique_ptr<QgsNewDatabaseTableNameWidget> w { qgis::make_unique<QgsNewDatabaseTableNameWidget>( nullptr, QStringList{ "PostGIS" } ) };
|
||||
std::unique_ptr<QgsNewDatabaseTableNameWidget> w { qgis::make_unique<QgsNewDatabaseTableNameWidget>( nullptr, QStringList{ "postgres" } ) };
|
||||
|
||||
auto index = w->mBrowserModel->findPath( QStringLiteral( "pg:/PG_1" ) );
|
||||
QVERIFY( index.isValid() );
|
||||
@ -93,6 +91,7 @@ void TestQgsNewDatabaseTableNameWidget::testWidgetSignals()
|
||||
QSignalSpy validationSpy( w.get(), SIGNAL( validationChanged( bool ) ) );
|
||||
QSignalSpy schemaSpy( w.get(), SIGNAL( schemaNameChanged( QString ) ) );
|
||||
QSignalSpy tableSpy( w.get(), SIGNAL( tableNameChanged( QString ) ) );
|
||||
QSignalSpy providerSpy( w.get(), SIGNAL( providerKeyChanged( QString ) ) );
|
||||
|
||||
index = w->mBrowserProxyModel.mapToSource( w->mBrowserProxyModel.index( 0, 0 ) );
|
||||
QVERIFY( index.isValid() );
|
||||
@ -103,10 +102,12 @@ void TestQgsNewDatabaseTableNameWidget::testWidgetSignals()
|
||||
|
||||
QVERIFY( ! w->isValid() );
|
||||
|
||||
QCOMPARE( validationSpy.count(), 1 );
|
||||
auto arguments = validationSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toBool(), false );
|
||||
QCOMPARE( providerSpy.count(), 1 );
|
||||
QCOMPARE( tableSpy.count(), 0 );
|
||||
QCOMPARE( schemaSpy.count(), 0 );
|
||||
QCOMPARE( validationSpy.count(), 0 );
|
||||
auto arguments = providerSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toString(), QString( "postgres" ) );
|
||||
|
||||
// Find qgis_test schema item
|
||||
index = w->mBrowserModel->findPath( QStringLiteral( "pg:/PG_1/qgis_test" ), Qt::MatchFlag::MatchStartsWith );
|
||||
@ -115,9 +116,10 @@ void TestQgsNewDatabaseTableNameWidget::testWidgetSignals()
|
||||
rect = w->mBrowserTreeView->visualRect( w->mBrowserProxyModel.mapFromSource( index ) );
|
||||
QVERIFY( rect.isValid() );
|
||||
QTest::mouseClick( w->mBrowserTreeView->viewport(), Qt::LeftButton, 0, rect.center() );
|
||||
QCOMPARE( validationSpy.count(), 1 );
|
||||
arguments = validationSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toBool(), false );
|
||||
|
||||
QVERIFY( ! w->isValid() );
|
||||
|
||||
QCOMPARE( validationSpy.count(), 0 );
|
||||
QCOMPARE( schemaSpy.count(), 1 );
|
||||
arguments = schemaSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toString(), QString( "qgis_test" ) );
|
||||
@ -126,38 +128,49 @@ void TestQgsNewDatabaseTableNameWidget::testWidgetSignals()
|
||||
QCOMPARE( tableSpy.count(), 1 );
|
||||
arguments = tableSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toString(), QString( "someNewTableData" ) );
|
||||
|
||||
QCOMPARE( validationSpy.count(), 1 );
|
||||
arguments = validationSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toBool(), true );
|
||||
QVERIFY( w->isValid() );
|
||||
|
||||
// Test unique
|
||||
// Test getters
|
||||
QCOMPARE( w->table(), QString( "someNewTableData" ) );
|
||||
QCOMPARE( w->schema(), QString( "qgis_test" ) );
|
||||
QCOMPARE( w->dataProviderKey(), QString( "postgres" ) );
|
||||
|
||||
// Test unique and make it invalid again so we get a status change
|
||||
w->mNewTableName->setText( QStringLiteral( "someData" ) );
|
||||
QVERIFY( ! w->isValid() );
|
||||
QCOMPARE( tableSpy.count(), 1 );
|
||||
arguments = tableSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toString(), QString( "someData" ) );
|
||||
QCOMPARE( validationSpy.count(), 1 );
|
||||
arguments = validationSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toBool(), false );
|
||||
|
||||
QVERIFY( ! w->isValid() );
|
||||
// Now select another schema
|
||||
index = w->mBrowserModel->findPath( QStringLiteral( "pg:/PG_1/public" ), Qt::MatchFlag::MatchStartsWith );
|
||||
QVERIFY( index.isValid() );
|
||||
w->mBrowserTreeView->scrollTo( w->mBrowserProxyModel.mapFromSource( index ) );
|
||||
rect = w->mBrowserTreeView->visualRect( w->mBrowserProxyModel.mapFromSource( index ) );
|
||||
QVERIFY( rect.isValid() );
|
||||
QTest::mouseClick( w->mBrowserTreeView->viewport(), Qt::LeftButton, 0, rect.center() );
|
||||
QCOMPARE( w->schema(), QString( "public" ) );
|
||||
QVERIFY( w->isValid() );
|
||||
QCOMPARE( validationSpy.count(), 1 );
|
||||
arguments = validationSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toBool(), true );
|
||||
QCOMPARE( schemaSpy.count(), 1 );
|
||||
arguments = schemaSpy.takeLast();
|
||||
QCOMPARE( arguments.at( 0 ).toString(), QString( "public" ) );
|
||||
|
||||
// Test getters
|
||||
QCOMPARE( w->table(), QString( "someData" ) );
|
||||
QCOMPARE( w->schema(), QString( "qgis_test" ) );
|
||||
QCOMPARE( w->dataItemProviderName(), QString( "postgres" ) );
|
||||
QCOMPARE( w->schema(), QString( "public" ) );
|
||||
QCOMPARE( w->dataProviderKey(), QString( "postgres" ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TestQgsNewDatabaseTableNameWidget::testWidget()
|
||||
{
|
||||
QDialog d;
|
||||
QVBoxLayout layout;
|
||||
d.setLayout( &layout );
|
||||
std::unique_ptr<QgsNewDatabaseTableNameWidget> w { qgis::make_unique<QgsNewDatabaseTableNameWidget>( nullptr, QStringList{ "PostGIS" } ) };
|
||||
d.layout()->addWidget( w.get() );
|
||||
|
||||
d.exec();
|
||||
|
||||
}
|
||||
|
||||
|
||||
QGSTEST_MAIN( TestQgsNewDatabaseTableNameWidget )
|
||||
#include "testqgsnewdatabasetablewidget.moc"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user