diff --git a/python/core/auto_generated/qgsbrowserproxymodel.sip.in b/python/core/auto_generated/qgsbrowserproxymodel.sip.in index 32cc5641ee5..c861d209aa7 100644 --- a/python/core/auto_generated/qgsbrowserproxymodel.sip.in +++ b/python/core/auto_generated/qgsbrowserproxymodel.sip.in @@ -133,19 +133,40 @@ filterByLayerType() is ``True``. .. seealso:: :py:func:`setFilterByLayerType` %End - void setDataItemProviderKeyFilter( const QStringList &filter ); + void setDataItemProviderKeyFilter( const QStringList &hiddenItemsFilter ); %Docstring -Sets the customization filters for data items based on item's data provider key +Sets a filter to hide data items based on on item's data provider key. -By default browser model shows all items from all available data items provider and few special -items (e.g. Favourites). To customize the behavior, set the filter to not load certain data items. +By default browser model shows all items from all available data item providers and few special +items (e.g. Favourites). +To customize the behavior, set the filter to not load certain data items. The items that are not based on data item providers have prefix "special:", for example -"special:Favourites", "special:Home", "PostGIS", "MSSQL" +"special:Favorites", "special:Home", "PostGIS", "MSSQL" All items created by the providers listed in filter are hidden from the layer tree. This filter is always evaluated. +:param hiddenItemsFilter: a list of data provider prefixes that will be hidden. + .. versionadded:: 3.12 +%End + + bool showLayers() const; +%Docstring +Returns ``True`` if layers must be shown, this flag is ``True`` by default. + +.. seealso:: :py:func:`setShowLayers` + +.. versionadded:: 3.14 +%End + + void setShowLayers( bool showLayers ); +%Docstring +Sets show layers to ``showLayers`` + +.. seealso:: :py:func:`showLayers` + +.. versionadded:: 3.14 %End protected: diff --git a/python/gui/auto_generated/qgsnewdatabasetablenamewidget.sip.in b/python/gui/auto_generated/qgsnewdatabasetablenamewidget.sip.in new file mode 100644 index 00000000000..b3d85393add --- /dev/null +++ b/python/gui/auto_generated/qgsnewdatabasetablenamewidget.sip.in @@ -0,0 +1,100 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsnewdatabasetablenamewidget.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + + + +class QgsNewDatabaseTableNameWidget : QWidget +{ +%Docstring +The QgsNewDatabaseTableNameWidget class embeds the browser view to +select a DB schema and a new table name. + +The table name is validated for uniqueness and the selected +data item provider, schema and table names can be retrieved with +getters. + +.. versionadded:: 3.14 +%End + +%TypeHeaderCode +#include "qgsnewdatabasetablenamewidget.h" +%End + public: + + explicit QgsNewDatabaseTableNameWidget( QgsBrowserGuiModel *browserModel = 0, + const QStringList &providersFilter = QStringList(), + QWidget *parent = 0 ); +%Docstring +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 parent: optional parent for this widget +%End + + QString schema(); +%Docstring +Returns the currently selected schema for the new table +%End + + QString table(); +%Docstring +Returns the current name of the new table +%End + + QString dataItemProviderName(); +%Docstring +Returns the currently selected data item provider name (which is NOT the data provider key!) for the new table +%End + + bool isValid() const; +%Docstring +Returns ``True`` if the widget contains a valid new table name +%End + + QString validationError(); +%Docstring +Returns the validation error or an empty string is the widget status is valid +%End + + signals: + + void validationChanged( bool isValid ); +%Docstring +This signal is emitted whenever the validation status of the widget changes. + +:param isValid: ``True`` if the current status of the widget is valid +%End + + void schemaNameChanged( const QString &schemaName ); +%Docstring +This signal is emitted when the user selects a schema. + +:param schemaName: the name of the selected schema +%End + + void tableNameChanged( const QString &tableName ); +%Docstring +This signal is emitted when the user enters a table name + +:param tableName: the name of the new table +%End + + +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/gui/qgsnewdatabasetablenamewidget.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/python/gui/gui_auto.sip b/python/gui/gui_auto.sip index 4ae3f128b81..1759dedec56 100644 --- a/python/gui/gui_auto.sip +++ b/python/gui/gui_auto.sip @@ -59,6 +59,7 @@ %Include auto_generated/qgsdataitemguiprovider.sip %Include auto_generated/qgsdataitemguiproviderregistry.sip %Include auto_generated/qgsdatasourceselectdialog.sip +%Include auto_generated/qgsnewdatabasetablenamewidget.sip %Include auto_generated/qgsdetaileditemdata.sip %Include auto_generated/qgsdetaileditemdelegate.sip %Include auto_generated/qgsdetaileditemwidget.sip diff --git a/src/core/qgsbrowserproxymodel.cpp b/src/core/qgsbrowserproxymodel.cpp index 3a7a8a9d79a..7cf62293922 100644 --- a/src/core/qgsbrowserproxymodel.cpp +++ b/src/core/qgsbrowserproxymodel.cpp @@ -153,9 +153,28 @@ bool QgsBrowserProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &s if ( !filterAcceptsProviderKey( sourceIndex ) || !filterRootAcceptsProviderKey( sourceIndex ) ) return false; + if ( ! mShowLayers ) + { + QgsDataItem *item = mModel->dataItem( sourceIndex ); + if ( qobject_cast< QgsLayerItem * >( item ) ) + { + return false; + } + } + return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex ); } +bool QgsBrowserProxyModel::showLayers() const +{ + return mShowLayers; +} + +void QgsBrowserProxyModel::setShowLayers( bool showLayers ) +{ + mShowLayers = showLayers; +} + QgsMapLayerType QgsBrowserProxyModel::layerType() const { return mLayerType; diff --git a/src/core/qgsbrowserproxymodel.h b/src/core/qgsbrowserproxymodel.h index c40d934687d..4fd32a3d693 100644 --- a/src/core/qgsbrowserproxymodel.h +++ b/src/core/qgsbrowserproxymodel.h @@ -144,19 +144,38 @@ class CORE_EXPORT QgsBrowserProxyModel : public QSortFilterProxyModel void setLayerType( QgsMapLayerType type ); /** - * Sets the customization filters for data items based on item's data provider key + * Sets a filter to hide data items based on on item's data provider key. * - * By default browser model shows all items from all available data items provider and few special - * items (e.g. Favourites). To customize the behavior, set the filter to not load certain data items. + * By default browser model shows all items from all available data item providers and few special + * items (e.g. Favourites). + * To customize the behavior, set the filter to not load certain data items. * The items that are not based on data item providers have prefix "special:", for example - * "special:Favourites", "special:Home", "PostGIS", "MSSQL" + * "special:Favorites", "special:Home", "PostGIS", "MSSQL" * * All items created by the providers listed in filter are hidden from the layer tree. * This filter is always evaluated. * + * \param hiddenItemsFilter a list of data provider prefixes that will be hidden. + * * \since QGIS 3.12 */ - void setDataItemProviderKeyFilter( const QStringList &filter ); + void setDataItemProviderKeyFilter( const QStringList &hiddenItemsFilter ); + + /** + * Returns TRUE if layers must be shown, this flag is TRUE by default. + * + * \see setShowLayers() + * \since QGIS 3.14 + */ + bool showLayers() const; + + /** + * Sets show layers to \a showLayers + * + * \see showLayers() + * \since QGIS 3.14 + */ + void setShowLayers( bool showLayers ); protected: @@ -172,6 +191,7 @@ class CORE_EXPORT QgsBrowserProxyModel : public QSortFilterProxyModel Qt::CaseSensitivity mCaseSensitivity = Qt::CaseInsensitive; bool mFilterByLayerType = false; + bool mShowLayers = true; QgsMapLayerType mLayerType = QgsMapLayerType::VectorLayer; //! Update filter @@ -194,6 +214,8 @@ class CORE_EXPORT QgsBrowserProxyModel : public QSortFilterProxyModel //! Root item accepts provider key. bool filterRootAcceptsProviderKey( const QModelIndex &sourceIndex ) const; + + }; #endif // QGSBROWSERPROXYMODEL_H diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 382510785f1..f507491d844 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -351,6 +351,7 @@ SET(QGIS_GUI_SRCS qgsdataitemguiproviderregistry.cpp qgsdatumtransformdialog.cpp qgsdatasourceselectdialog.cpp + qgsnewdatabasetablenamewidget.cpp qgsdetaileditemdata.cpp qgsdetaileditemdelegate.cpp qgsdetaileditemwidget.cpp @@ -563,6 +564,7 @@ SET(QGIS_GUI_HDRS qgsdataitemguiproviderregistry.h qgsdatasourcemanagerdialog.h qgsdatasourceselectdialog.h + qgsnewdatabasetablenamewidget.h qgsdatumtransformdialog.h qgsdetaileditemdata.h qgsdetaileditemdelegate.h diff --git a/src/gui/qgsnewdatabasetablenamewidget.cpp b/src/gui/qgsnewdatabasetablenamewidget.cpp new file mode 100644 index 00000000000..7b7443cb9d5 --- /dev/null +++ b/src/gui/qgsnewdatabasetablenamewidget.cpp @@ -0,0 +1,206 @@ +/*************************************************************************** + qgsnewdatabasetablenamewidget.cpp - QgsNewDatabaseTableNameWidget + + --------------------- + begin : 9.3.2020 + copyright : (C) 2020 by Alessandro Pasotti + email : elpaso at itopen dot it + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include + +#include "qgsnewdatabasetablenamewidget.h" +#include "qgsapplication.h" +#include "qgsdataitemproviderregistry.h" +#include "qgsdataitemprovider.h" + +QgsNewDatabaseTableNameWidget::QgsNewDatabaseTableNameWidget( + QgsBrowserGuiModel *browserModel, + const QStringList &providersFilter, + QWidget *parent ) + : QWidget( parent ) +{ + + + // Initalize the browser + if ( ! browserModel ) + { + mBrowserModel = new QgsBrowserGuiModel( this ); + mBrowserModel->initialize(); + } + else + { + mBrowserModel = browserModel; + mBrowserModel->initialize(); + } + + setupUi( this ); + + QStringList hiddenProviders + { + QStringLiteral( "special:Favorites" ), + QStringLiteral( "special:Drives" ), + QStringLiteral( "special:Volumes" ), + QStringLiteral( "special:Home" ), + QStringLiteral( "special:ProjectHome" ) + }; + + const auto providerList { QgsApplication::dataItemProviderRegistry()->providers() }; + for ( const auto &provider : providerList ) + { + if ( provider->capabilities() & QgsDataProvider::DataCapability::Database ) + { + if ( ! providersFilter.isEmpty() && ! providersFilter.contains( provider->name() ) ) + { + hiddenProviders.push_back( provider->name() ); + } + else + { + mShownProviders.insert( provider->name() ); + } + } + else + { + hiddenProviders.push_back( provider->name() ); + } + } + + mBrowserProxyModel.setBrowserModel( mBrowserModel ); + mBrowserProxyModel.setDataItemProviderKeyFilter( hiddenProviders ); + mBrowserProxyModel.setShowLayers( false ); + mBrowserTreeView->setHeaderHidden( true ); + mBrowserTreeView->setExpandsOnDoubleClick( false ); + mBrowserTreeView->setModel( &mBrowserProxyModel ); + mBrowserTreeView->setBrowserModel( mBrowserModel ); + + // Connections + connect( mNewTableName, &QLineEdit::textChanged, this, [ = ] + { + mTableName = mNewTableName->text(); + emit tableNameChanged( mTableName ); + validate(); + } ); + + connect( mBrowserTreeView, &QgsBrowserTreeView::clicked, this, [ = ]( const QModelIndex & index ) + { + if ( index.isValid() ) + { + const QgsDataItem *dataItem( mBrowserProxyModel.dataItem( index ) ); + if ( dataItem ) + { + const QgsDataCollectionItem *collectionItem = qobject_cast( dataItem ); + if ( collectionItem ) + { + if ( mShownProviders.contains( collectionItem->name() ) ) + { + if ( mDataProviderName != collectionItem->name() ) + { + mSchemaName.clear(); + mDataProviderName = collectionItem->name(); + } + } + else + { + mSchemaName = collectionItem->name(); + emit schemaNameChanged( mSchemaName ); + } + validate(); + } + } + } + } ); + + mValidationResults->hide(); + +} + +QString QgsNewDatabaseTableNameWidget::schema() +{ + return mSchemaName; +} + +QString QgsNewDatabaseTableNameWidget::table() +{ + return mTableName; +} + +QString QgsNewDatabaseTableNameWidget::dataItemProviderName() +{ + return mDataProviderName; +} + +void QgsNewDatabaseTableNameWidget::validate() +{ + // Check table uniqueness + mIsValid = ! mDataProviderName.isEmpty() && + mShownProviders.contains( mDataProviderName ) && + ! mSchemaName.isEmpty() && + ! mTableName.isEmpty() && + ! tableNames( ).contains( mTableName ); + + mValidationError.clear(); + + if ( ! mIsValid ) + { + + if ( mTableName.isEmpty() ) + { + mValidationError = tr( "Enter a unique name for the new table" ); + } + else if ( mSchemaName.isEmpty() ) + { + mValidationError = tr( "Select a database schema" ); + } + 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" ); + } + } + mValidationResults->setText( mValidationError ); + mValidationResults->setVisible( ! mIsValid ); + emit validationChanged( mIsValid ); +} + +QStringList QgsNewDatabaseTableNameWidget::tableNames() +{ + QStringList tableNames; + QModelIndex index { mBrowserTreeView->currentIndex() }; + if ( index.isValid() ) + { + for ( int row = 0; row < mBrowserProxyModel.rowCount( ); ++row ) + { + // Column 1 contains the + index = mBrowserProxyModel.index( row, 1, index ); + if ( index.isValid() ) + { + const QgsDataItem *dataItem { mBrowserProxyModel.dataItem( index ) }; + if ( dataItem ) + { + tableNames.push_back( dataItem->name() ); + } + } + } + } + return tableNames; +} + +bool QgsNewDatabaseTableNameWidget::isValid() const +{ + return mIsValid; +} + +QString QgsNewDatabaseTableNameWidget::validationError() +{ + return mValidationError; +} diff --git a/src/gui/qgsnewdatabasetablenamewidget.h b/src/gui/qgsnewdatabasetablenamewidget.h new file mode 100644 index 00000000000..caca3269490 --- /dev/null +++ b/src/gui/qgsnewdatabasetablenamewidget.h @@ -0,0 +1,124 @@ +/*************************************************************************** + qgsnewdatabasetablenamewidget.h - QgsNewDatabaseTableNameWidget + + --------------------- + begin : 9.3.2020 + copyright : (C) 2020 by Alessandro Pasotti + email : elpaso at itopen dot it + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef QGSNEWDATABASETABLENAMEWIDGET_H +#define QGSNEWDATABASETABLENAMEWIDGET_H + + +#include "ui_qgsnewdatabasetablenamewidget.h" + +#include "qgis_gui.h" +#include "qgsbrowserguimodel.h" +#include "qgsbrowserproxymodel.h" + +#include + +/** + * \ingroup gui + * The QgsNewDatabaseTableNameWidget class embeds the browser view to + * select a DB schema and a new table name. + * + * The table name is validated for uniqueness and the selected + * data item provider, schema and table names can be retrieved with + * getters. + * + * \since QGIS 3.14 + */ +class GUI_EXPORT QgsNewDatabaseTableNameWidget : public QWidget, private Ui::QgsNewDatabaseTableNameWidget +{ + Q_OBJECT + + public: + + /** + * 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 parent optional parent for this widget + */ + explicit QgsNewDatabaseTableNameWidget( QgsBrowserGuiModel *browserModel = nullptr, + const QStringList &providersFilter = QStringList(), + QWidget *parent = nullptr ); + + /** + * Returns the currently selected schema for the new table + */ + QString schema(); + + /** + * Returns the current name of the new table + */ + QString table(); + + /** + * Returns the currently selected data item provider name (which is NOT the data provider key!) for the new table + */ + QString dataItemProviderName(); + + /** + * Returns TRUE if the widget contains a valid new table name + */ + bool isValid() const; + + /** + * Returns the validation error or an empty string is the widget status is valid + */ + QString validationError(); + + signals: + + /** + * This signal is emitted whenever the validation status of the widget changes. + * + * \param isValid TRUE if the current status of the widget is valid + */ + void validationChanged( bool isValid ); + + /** + * This signal is emitted when the user selects a schema. + * + * \param schemaName the name of the selected schema + */ + void schemaNameChanged( const QString &schemaName ); + + /** + * This signal is emitted when the user enters a table name + * + * \param tableName the name of the new table + */ + void tableNameChanged( const QString &tableName ); + + + private: + + QgsBrowserProxyModel mBrowserProxyModel; + QgsBrowserGuiModel *mBrowserModel = nullptr; + void validate(); + QStringList tableNames(); + QString mDataProviderName; + QString mTableName; + QString mSchemaName; + QSet mShownProviders; + bool mIsValid = false; + QString mValidationError; + + // For testing: + friend class TestQgsNewDatabaseTableNameWidget; + +}; + +#endif // QGSNEWDATABASETABLENAMEWIDGET_H diff --git a/src/ui/qgsnewdatabasetablenamewidget.ui b/src/ui/qgsnewdatabasetablenamewidget.ui new file mode 100644 index 00000000000..03f4d23e116 --- /dev/null +++ b/src/ui/qgsnewdatabasetablenamewidget.ui @@ -0,0 +1,130 @@ + + + QgsNewDatabaseTableNameWidget + + + + 0 + 0 + 700 + 629 + + + + + 4 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + 3 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + New table name + + + + + + + + + + name of the new table + + + + + + + true + + + Validation results + + + + + + + + :/images/themes/default/mActionRefresh.svg:/images/themes/default/mActionRefresh.svg + + + Refresh + + + + + true + + + + :/images/themes/default/mActionFilter2.svg:/images/themes/default/mActionFilter2.svg + + + Filter Browser + + + Filter Browser + + + Filter Browser + + + + + + :/images/themes/default/mActionCollapseTree.svg:/images/themes/default/mActionCollapseTree.svg + + + Collapse All + + + Collapse All + + + + + + QgsBrowserTreeView + QTreeView +
qgsbrowsertreeview.h
+
+
+ + + + +
diff --git a/tests/src/gui/CMakeLists.txt b/tests/src/gui/CMakeLists.txt index d1642c64c38..5d4281409a7 100644 --- a/tests/src/gui/CMakeLists.txt +++ b/tests/src/gui/CMakeLists.txt @@ -161,3 +161,4 @@ ADD_QGIS_TEST(relationreferencewidget testqgsrelationreferencewidget.cpp) ADD_QGIS_TEST(featurelistcombobox testqgsfeaturelistcombobox.cpp) ADD_QGIS_TEST(texteditwrapper testqgstexteditwrapper.cpp) ADD_QGIS_TEST(tableeditorwidget testqgstableeditor.cpp) +ADD_QGIS_TEST(newdatabasetablewidget testqgsnewdatabasetablewidget.cpp) diff --git a/tests/src/gui/testqgsnewdatabasetablewidget.cpp b/tests/src/gui/testqgsnewdatabasetablewidget.cpp new file mode 100644 index 00000000000..f0115b5e351 --- /dev/null +++ b/tests/src/gui/testqgsnewdatabasetablewidget.cpp @@ -0,0 +1,164 @@ +/*************************************************************************** + testqgsfilefiledownloader.cpp + -------------------------------------- + Date : 09.03.2020 + Copyright : (C) 2020 Alessandro Pasotti + Email : elpaso at itopen dot it + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#include "qgstest.h" +#include +#include +#include + +#include "qgsnewdatabasetablenamewidget.h" +#include "qgsprovidermetadata.h" +#include "qgsproviderregistry.h" +#include "qgsabstractproviderconnection.h" + +class TestQgsNewDatabaseTableNameWidget: public QObject +{ + Q_OBJECT + 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. + void init(); // will be called before each testfunction is executed. + void cleanup(); // will be called after every testfunction. + + void testWidgetFilters(); + void testWidgetSignals(); + +}; + +void TestQgsNewDatabaseTableNameWidget::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); + // Add some connections to test with + QgsProviderMetadata *md { QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "postgres" ) ) }; + QgsAbstractProviderConnection *conn { md->createConnection( qgetenv( "QGIS_PGTEST_DB" ) ) }; + md->saveConnection( conn, QStringLiteral( "PG_1" ) ); + conn = md->createConnection( qgetenv( " QGIS_PGTEST_DB" ) ); + md->saveConnection( conn, QStringLiteral( "PG_2" ) ); +} + +void TestQgsNewDatabaseTableNameWidget::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsNewDatabaseTableNameWidget::init() +{ +} + +void TestQgsNewDatabaseTableNameWidget::cleanup() +{ +} + +void TestQgsNewDatabaseTableNameWidget::testWidgetFilters() +{ + std::unique_ptr w { qgis::make_unique( nullptr, QStringList{ "NOT_EXISTS" } ) }; + QCOMPARE( w->mBrowserProxyModel.rowCount(), 0 ); + std::unique_ptr w2 { qgis::make_unique( nullptr ) }; + QVERIFY( w2->mBrowserProxyModel.rowCount() > 0 ); + std::unique_ptr w3 { qgis::make_unique( nullptr, QStringList{ "PostGIS" } ) }; + QVERIFY( w3->mBrowserProxyModel.rowCount() > 0 ); +} + + +void TestQgsNewDatabaseTableNameWidget::testWidgetSignals() +{ + std::unique_ptr w { qgis::make_unique( nullptr, QStringList{ "PostGIS" } ) }; + + auto index = w->mBrowserModel->findPath( QStringLiteral( "pg:/PG_1" ) ); + QVERIFY( index.isValid() ); + w->mBrowserModel->dataItem( index )->populate( true ); + w->mBrowserTreeView->expandAll(); + + QVERIFY( ! w->isValid() ); + + QSignalSpy validationSpy( w.get(), SIGNAL( validationChanged( bool ) ) ); + QSignalSpy schemaSpy( w.get(), SIGNAL( schemaNameChanged( QString ) ) ); + QSignalSpy tableSpy( w.get(), SIGNAL( tableNameChanged( QString ) ) ); + + index = w->mBrowserProxyModel.mapToSource( w->mBrowserProxyModel.index( 0, 0 ) ); + QVERIFY( index.isValid() ); + QCOMPARE( w->mBrowserModel->data( index, Qt::DisplayRole ).toString(), QString( "PostGIS" ) ); + QRect rect = w->mBrowserTreeView->visualRect( w->mBrowserProxyModel.mapFromSource( index ) ); + QVERIFY( rect.isValid() ); + QTest::mouseClick( w->mBrowserTreeView->viewport(), Qt::LeftButton, 0, rect.topLeft() ); + + QVERIFY( ! w->isValid() ); + + QCOMPARE( validationSpy.count(), 1 ); + auto arguments = validationSpy.takeLast(); + QCOMPARE( arguments.at( 0 ).toBool(), false ); + QCOMPARE( schemaSpy.count(), 0 ); + + // Find qgis_test schema item + index = w->mBrowserModel->findPath( QStringLiteral( "pg:/PG_1/qgis_test" ), 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( validationSpy.count(), 1 ); + arguments = validationSpy.takeLast(); + QCOMPARE( arguments.at( 0 ).toBool(), false ); + QCOMPARE( schemaSpy.count(), 1 ); + arguments = schemaSpy.takeLast(); + QCOMPARE( arguments.at( 0 ).toString(), QString( "qgis_test" ) ); + + w->mNewTableName->setText( QStringLiteral( "someNewTableData" ) ); + QCOMPARE( tableSpy.count(), 1 ); + arguments = tableSpy.takeLast(); + QCOMPARE( arguments.at( 0 ).toString(), QString( "someNewTableData" ) ); + + QVERIFY( w->isValid() ); + + // Test unique + w->mNewTableName->setText( QStringLiteral( "someData" ) ); + QCOMPARE( tableSpy.count(), 1 ); + arguments = tableSpy.takeLast(); + QCOMPARE( arguments.at( 0 ).toString(), QString( "someData" ) ); + + QVERIFY( ! w->isValid() ); + + // Test getters + QCOMPARE( w->table(), QString( "someData" ) ); + QCOMPARE( w->schema(), QString( "qgis_test" ) ); + QCOMPARE( w->dataItemProviderName(), QString( "postgres" ) ); + +} + + +void TestQgsNewDatabaseTableNameWidget::testWidget() +{ + QDialog d; + QVBoxLayout layout; + d.setLayout( &layout ); + std::unique_ptr w { qgis::make_unique( nullptr, QStringList{ "PostGIS" } ) }; + d.layout()->addWidget( w.get() ); + + d.exec(); + +} + + +QGSTEST_MAIN( TestQgsNewDatabaseTableNameWidget ) +#include "testqgsnewdatabasetablewidget.moc" + +