mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-17 00:09:36 -04:00
Add new GUI widget QgsDatabaseSchemaComboBox for selection of
available schemas for a specific data connection (providers must implement the connections API)
This commit is contained in:
parent
2bdb0cc27a
commit
e8e13ecb6f
95
python/gui/auto_generated/qgsdatabaseschemacombobox.sip.in
Normal file
95
python/gui/auto_generated/qgsdatabaseschemacombobox.sip.in
Normal file
@ -0,0 +1,95 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsdatabaseschemacombobox.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsDatabaseSchemaComboBox : QWidget
|
||||
{
|
||||
%Docstring
|
||||
The QgsDatabaseSchemaComboBox class is a combo box which displays the list of schemas for a specific database connection.
|
||||
|
||||
.. warning::
|
||||
|
||||
The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
in order for the combobox to work correctly.
|
||||
|
||||
.. versionadded:: 3.14
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsdatabaseschemacombobox.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
explicit QgsDatabaseSchemaComboBox( const QString &provider, const QString &connection, QWidget *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsDatabaseSchemaComboBox, for the specified ``provider`` and ``connection``.
|
||||
|
||||
.. warning::
|
||||
|
||||
The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
in order for the model to work correctly.
|
||||
%End
|
||||
|
||||
explicit QgsDatabaseSchemaComboBox( QgsAbstractDatabaseProviderConnection *connection /Transfer/, QWidget *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsDatabaseSchemaComboBox, for the specified ``connection``.
|
||||
|
||||
Ownership of ``connection`` is transferred to the combobox.
|
||||
%End
|
||||
|
||||
QString currentSchema() const;
|
||||
%Docstring
|
||||
Returns the name of the current schema selected in the combo box.
|
||||
%End
|
||||
|
||||
QComboBox *comboBox();
|
||||
%Docstring
|
||||
Returns the combobox portion of the widget.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
void setSchema( const QString &schema );
|
||||
%Docstring
|
||||
Sets the current schema selected in the combo box.
|
||||
%End
|
||||
|
||||
void setConnectionName( const QString &connection, const QString &provider = QString() );
|
||||
%Docstring
|
||||
Sets the database connection name from which to retrieve the available schemas.
|
||||
|
||||
Optionally the ``provider`` can be reset too.
|
||||
%End
|
||||
|
||||
void refreshSchemas();
|
||||
%Docstring
|
||||
Refreshes the list of available schemas.
|
||||
%End
|
||||
|
||||
signals:
|
||||
void schemaChanged( const QString &schema );
|
||||
%Docstring
|
||||
Emitted whenever the currently selected schema changes.
|
||||
%End
|
||||
|
||||
protected slots:
|
||||
void indexChanged( int i );
|
||||
void rowsChanged();
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsdatabaseschemacombobox.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -54,6 +54,7 @@
|
||||
%Include auto_generated/qgscredentialdialog.sip
|
||||
%Include auto_generated/qgscurveeditorwidget.sip
|
||||
%Include auto_generated/qgscustomdrophandler.sip
|
||||
%Include auto_generated/qgsdatabaseschemacombobox.sip
|
||||
%Include auto_generated/qgsdataitemguiprovider.sip
|
||||
%Include auto_generated/qgsdataitemguiproviderregistry.sip
|
||||
%Include auto_generated/qgsdatasourceselectdialog.sip
|
||||
|
@ -321,6 +321,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgscredentialdialog.cpp
|
||||
qgscustomdrophandler.cpp
|
||||
qgscurveeditorwidget.cpp
|
||||
qgsdatabaseschemacombobox.cpp
|
||||
qgsdataitemguiprovider.cpp
|
||||
qgsdataitemguiproviderregistry.cpp
|
||||
qgsdatumtransformdialog.cpp
|
||||
@ -525,6 +526,7 @@ SET(QGIS_GUI_HDRS
|
||||
qgscredentialdialog.h
|
||||
qgscurveeditorwidget.h
|
||||
qgscustomdrophandler.h
|
||||
qgsdatabaseschemacombobox.h
|
||||
qgsdataitemguiprovider.h
|
||||
qgsdataitemguiproviderregistry.h
|
||||
qgsdatasourcemanagerdialog.h
|
||||
|
135
src/gui/qgsdatabaseschemacombobox.cpp
Normal file
135
src/gui/qgsdatabaseschemacombobox.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/***************************************************************************
|
||||
qgsdatabaseschemacombobox.cpp
|
||||
--------------------------------
|
||||
Date : March 2020
|
||||
Copyright : (C) 2020 Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgsdatabaseschemacombobox.h"
|
||||
#include "qgsdatabaseschemamodel.h"
|
||||
#include <QHBoxLayout>
|
||||
|
||||
QgsDatabaseSchemaComboBox::QgsDatabaseSchemaComboBox( const QString &provider, const QString &connection, QWidget *parent )
|
||||
: QWidget( parent )
|
||||
, mProvider( provider )
|
||||
{
|
||||
mModel = new QgsDatabaseSchemaModel( provider, connection, this );
|
||||
init();
|
||||
}
|
||||
|
||||
QgsDatabaseSchemaComboBox::QgsDatabaseSchemaComboBox( QgsAbstractDatabaseProviderConnection *connection, QWidget *parent )
|
||||
: QWidget( parent )
|
||||
{
|
||||
mModel = new QgsDatabaseSchemaModel( connection, this );
|
||||
init();
|
||||
}
|
||||
|
||||
void QgsDatabaseSchemaComboBox::init()
|
||||
{
|
||||
mComboBox = new QComboBox();
|
||||
|
||||
mSortModel = new QSortFilterProxyModel( this );
|
||||
mSortModel->setSourceModel( mModel );
|
||||
mSortModel->setSortRole( Qt::DisplayRole );
|
||||
mSortModel->setSortLocaleAware( true );
|
||||
mSortModel->setSortCaseSensitivity( Qt::CaseInsensitive );
|
||||
mSortModel->setDynamicSortFilter( true );
|
||||
mSortModel->sort( 0 );
|
||||
|
||||
mComboBox->setModel( mSortModel );
|
||||
|
||||
QHBoxLayout *l = new QHBoxLayout();
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
l->addWidget( mComboBox );
|
||||
setLayout( l );
|
||||
|
||||
connect( mComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::activated ), this, &QgsDatabaseSchemaComboBox::indexChanged );
|
||||
connect( mSortModel, &QAbstractItemModel::rowsInserted, this, &QgsDatabaseSchemaComboBox::rowsChanged );
|
||||
connect( mSortModel, &QAbstractItemModel::rowsRemoved, this, &QgsDatabaseSchemaComboBox::rowsChanged );
|
||||
}
|
||||
|
||||
void QgsDatabaseSchemaComboBox::setSchema( const QString &schema )
|
||||
{
|
||||
if ( schema == currentSchema() )
|
||||
return;
|
||||
|
||||
if ( schema.isEmpty() )
|
||||
{
|
||||
mComboBox->setCurrentIndex( -1 );
|
||||
emit schemaChanged( QString() );
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList idx = mSortModel->match( mSortModel->index( 0, 0 ), Qt::DisplayRole, schema, Qt::MatchFixedString | Qt::MatchCaseSensitive );
|
||||
if ( !idx.empty() )
|
||||
{
|
||||
QModelIndex proxyIdx = idx.at( 0 );
|
||||
if ( proxyIdx.isValid() )
|
||||
{
|
||||
mComboBox->setCurrentIndex( proxyIdx.row() );
|
||||
emit schemaChanged( currentSchema() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
mComboBox->setCurrentIndex( -1 );
|
||||
emit schemaChanged( QString() );
|
||||
}
|
||||
|
||||
void QgsDatabaseSchemaComboBox::setConnectionName( const QString &connection, const QString &provider )
|
||||
{
|
||||
if ( !provider.isEmpty() )
|
||||
mProvider = provider;
|
||||
|
||||
const QString oldSchema = currentSchema();
|
||||
QgsDatabaseSchemaModel *oldModel = mModel;
|
||||
mModel = new QgsDatabaseSchemaModel( mProvider, connection, this );
|
||||
mSortModel->setSourceModel( mModel );
|
||||
oldModel->deleteLater();
|
||||
if ( currentSchema() != oldSchema )
|
||||
setSchema( oldSchema );
|
||||
}
|
||||
|
||||
void QgsDatabaseSchemaComboBox::refreshSchemas()
|
||||
{
|
||||
const QString oldSchema = currentSchema();
|
||||
mModel->refresh();
|
||||
setSchema( oldSchema );
|
||||
}
|
||||
|
||||
QString QgsDatabaseSchemaComboBox::currentSchema() const
|
||||
{
|
||||
const QModelIndex proxyIndex = mSortModel->index( mComboBox->currentIndex(), 0 );
|
||||
if ( !proxyIndex.isValid() )
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
return mSortModel->data( proxyIndex, Qt::DisplayRole ).toString();
|
||||
}
|
||||
|
||||
void QgsDatabaseSchemaComboBox::indexChanged( int i )
|
||||
{
|
||||
Q_UNUSED( i )
|
||||
emit schemaChanged( currentSchema() );
|
||||
}
|
||||
|
||||
void QgsDatabaseSchemaComboBox::rowsChanged()
|
||||
{
|
||||
if ( mComboBox->count() == 1 )
|
||||
{
|
||||
//currently selected connection item has changed
|
||||
emit schemaChanged( currentSchema() );
|
||||
}
|
||||
else if ( mComboBox->count() == 0 )
|
||||
{
|
||||
emit schemaChanged( QString() );
|
||||
}
|
||||
}
|
104
src/gui/qgsdatabaseschemacombobox.h
Normal file
104
src/gui/qgsdatabaseschemacombobox.h
Normal file
@ -0,0 +1,104 @@
|
||||
/***************************************************************************
|
||||
qgsdatabaseschemacombobox.h
|
||||
--------------------------------
|
||||
Date : March 2020
|
||||
Copyright : (C) 2020 Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSDATABASESCHEMACOMBOBOX_H
|
||||
#define QGSDATABASESCHEMACOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
#include "qgis_gui.h"
|
||||
#include "qgis_sip.h"
|
||||
|
||||
class QgsDatabaseSchemaModel;
|
||||
class QSortFilterProxyModel;
|
||||
class QgsAbstractDatabaseProviderConnection;
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* \brief The QgsDatabaseSchemaComboBox class is a combo box which displays the list of schemas for a specific database connection.
|
||||
*
|
||||
* \warning The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
* in order for the combobox to work correctly.
|
||||
*
|
||||
* \since QGIS 3.14
|
||||
*/
|
||||
class GUI_EXPORT QgsDatabaseSchemaComboBox : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsDatabaseSchemaComboBox, for the specified \a provider and \a connection.
|
||||
*
|
||||
* \warning The provider must support the connection API methods in its QgsProviderMetadata implementation
|
||||
* in order for the model to work correctly.
|
||||
*/
|
||||
explicit QgsDatabaseSchemaComboBox( const QString &provider, const QString &connection, QWidget *parent SIP_TRANSFERTHIS = nullptr );
|
||||
|
||||
/**
|
||||
* Constructor for QgsDatabaseSchemaComboBox, for the specified \a connection.
|
||||
*
|
||||
* Ownership of \a connection is transferred to the combobox.
|
||||
*/
|
||||
explicit QgsDatabaseSchemaComboBox( QgsAbstractDatabaseProviderConnection *connection SIP_TRANSFER, QWidget *parent SIP_TRANSFERTHIS = nullptr );
|
||||
|
||||
/**
|
||||
* Returns the name of the current schema selected in the combo box.
|
||||
*/
|
||||
QString currentSchema() const;
|
||||
|
||||
/**
|
||||
* Returns the combobox portion of the widget.
|
||||
*/
|
||||
QComboBox *comboBox() { return mComboBox; }
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* Sets the current schema selected in the combo box.
|
||||
*/
|
||||
void setSchema( const QString &schema );
|
||||
|
||||
/**
|
||||
* Sets the database connection name from which to retrieve the available schemas.
|
||||
*
|
||||
* Optionally the \a provider can be reset too.
|
||||
*/
|
||||
void setConnectionName( const QString &connection, const QString &provider = QString() );
|
||||
|
||||
/**
|
||||
* Refreshes the list of available schemas.
|
||||
*/
|
||||
void refreshSchemas();
|
||||
|
||||
signals:
|
||||
//! Emitted whenever the currently selected schema changes.
|
||||
void schemaChanged( const QString &schema );
|
||||
|
||||
protected slots:
|
||||
void indexChanged( int i );
|
||||
void rowsChanged();
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
QString mProvider;
|
||||
QgsDatabaseSchemaModel *mModel = nullptr;
|
||||
QSortFilterProxyModel *mSortModel = nullptr;
|
||||
QComboBox *mComboBox = nullptr;
|
||||
};
|
||||
|
||||
#endif // QGSDATABASESCHEMACOMBOBOX_H
|
@ -306,6 +306,7 @@ IF (ENABLE_PGTEST)
|
||||
ADD_PYTHON_TEST(PyQgsDbManagerPostgis test_db_manager_postgis.py)
|
||||
ADD_PYTHON_TEST(PyQgsDatabaseSchemaModel test_qgsdatabaseschemamodel.py)
|
||||
ADD_PYTHON_TEST(PyQgsDatabaseTableModel test_qgsdatabasetablemodel.py)
|
||||
ADD_PYTHON_TEST(PyQgsDatabaseSchemaComboBox test_qgsdatabaseschemacombobox.py)
|
||||
ADD_PYTHON_TEST(PyQgsProviderConnectionPostgres test_qgsproviderconnection_postgres.py)
|
||||
ENDIF (ENABLE_PGTEST)
|
||||
|
||||
|
122
tests/src/python/test_qgsdatabaseschemacombobox.py
Normal file
122
tests/src/python/test_qgsdatabaseschemacombobox.py
Normal file
@ -0,0 +1,122 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsDatabaseSchemaComboBox
|
||||
|
||||
.. note:: 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.
|
||||
"""
|
||||
__author__ = 'Nyall Dawson'
|
||||
__date__ = '8/03/2020'
|
||||
__copyright__ = 'Copyright 2020, The QGIS Project'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
import tempfile
|
||||
import shutil
|
||||
import os
|
||||
|
||||
from qgis.core import (
|
||||
QgsVectorLayer,
|
||||
QgsProviderRegistry
|
||||
)
|
||||
from qgis.gui import QgsDatabaseSchemaComboBox
|
||||
from qgis.PyQt.QtCore import QCoreApplication
|
||||
from qgis.PyQt.QtTest import QSignalSpy
|
||||
|
||||
from qgis.testing import unittest
|
||||
from utilities import unitTestDataPath, start_app
|
||||
|
||||
start_app()
|
||||
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
|
||||
|
||||
class TestQgsDatabaseSchemaComboBox(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Run before all tests"""
|
||||
|
||||
QCoreApplication.setOrganizationName("QGIS_Test")
|
||||
QCoreApplication.setOrganizationDomain(cls.__name__)
|
||||
QCoreApplication.setApplicationName(cls.__name__)
|
||||
start_app()
|
||||
cls.postgres_conn = "service='qgis_test'"
|
||||
if 'QGIS_PGTEST_DB' in os.environ:
|
||||
cls.postgres_conn = os.environ['QGIS_PGTEST_DB']
|
||||
cls.uri = cls.postgres_conn + ' sslmode=disable'
|
||||
|
||||
def testCombo(self):
|
||||
""" test combobox functionality """
|
||||
conn = QgsProviderRegistry.instance().providerMetadata('postgres').createConnection(self.uri, {})
|
||||
self.assertTrue(conn)
|
||||
|
||||
m = QgsDatabaseSchemaComboBox(conn)
|
||||
spy = QSignalSpy(m.schemaChanged)
|
||||
self.assertGreaterEqual(m.comboBox().count(), 3)
|
||||
|
||||
text = [m.comboBox().itemText(i) for i in range(m.comboBox().count())]
|
||||
self.assertIn('CamelCaseSchema', text)
|
||||
self.assertIn('qgis_test', text)
|
||||
self.assertLess(text.index('CamelCaseSchema'), text.index('qgis_test'))
|
||||
self.assertEqual(m.currentSchema(), 'CamelCaseSchema')
|
||||
|
||||
m.setSchema('qgis_test')
|
||||
self.assertEqual(m.currentSchema(), 'qgis_test')
|
||||
self.assertEqual(len(spy), 1)
|
||||
self.assertEqual(spy[-1][0], 'qgis_test')
|
||||
|
||||
m.setSchema('')
|
||||
self.assertFalse(m.currentSchema())
|
||||
self.assertEqual(len(spy), 2)
|
||||
self.assertFalse(spy[-1][0])
|
||||
m.setSchema('')
|
||||
self.assertEqual(len(spy), 2)
|
||||
self.assertFalse(m.currentSchema())
|
||||
|
||||
m.setSchema('qgis_test')
|
||||
self.assertEqual(len(spy), 3)
|
||||
self.assertEqual(m.currentSchema(), 'qgis_test')
|
||||
self.assertEqual(spy[-1][0], 'qgis_test')
|
||||
|
||||
conn.createSchema('myNewSchema')
|
||||
text2 = [m.comboBox().itemText(i) for i in range(m.comboBox().count())]
|
||||
# schemas are not automatically refreshed
|
||||
self.assertEqual(text2, text)
|
||||
|
||||
# but setting a new connection should fix this!
|
||||
md = QgsProviderRegistry.instance().providerMetadata('postgres')
|
||||
conn2 = md.createConnection(self.uri, {})
|
||||
md.saveConnection(conn2, 'another')
|
||||
m.setConnectionName('another', 'postgres')
|
||||
# ideally there'd be no extra signal here, but it's a minor issue...
|
||||
self.assertEqual(len(spy), 4)
|
||||
self.assertEqual(m.currentSchema(), 'qgis_test')
|
||||
self.assertEqual(spy[-1][0], 'qgis_test')
|
||||
|
||||
text2 = [m.comboBox().itemText(i) for i in range(m.comboBox().count())]
|
||||
self.assertNotEqual(text2, text)
|
||||
self.assertIn('myNewSchema', text2)
|
||||
|
||||
m.setSchema('myNewSchema')
|
||||
self.assertEqual(len(spy), 5)
|
||||
self.assertEqual(m.currentSchema(), 'myNewSchema')
|
||||
self.assertEqual(spy[-1][0], 'myNewSchema')
|
||||
|
||||
# no auto drop
|
||||
conn.dropSchema('myNewSchema')
|
||||
self.assertEqual(len(spy), 5)
|
||||
self.assertEqual(m.currentSchema(), 'myNewSchema')
|
||||
self.assertEqual(spy[-1][0], 'myNewSchema')
|
||||
|
||||
m.refreshSchemas()
|
||||
text2 = [m.comboBox().itemText(i) for i in range(m.comboBox().count())]
|
||||
self.assertNotIn('myNewSchema', text2)
|
||||
self.assertEqual(len(spy), 6)
|
||||
self.assertFalse(m.currentSchema())
|
||||
self.assertFalse(spy[-1][0])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -32,7 +32,7 @@ start_app()
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
|
||||
|
||||
class TestQgsMapLayerComboBox(unittest.TestCase):
|
||||
class TestQgsProviderConnectionComboBox(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
Loading…
x
Reference in New Issue
Block a user