Skip to content

Commit

Permalink
Add a model for schemas from a database connection
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Mar 9, 2020
1 parent 2eb4eaf commit a0a57d5
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 1 deletion.
69 changes: 69 additions & 0 deletions python/core/auto_generated/qgsdatabaseschemamodel.sip.in
@@ -0,0 +1,69 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsdatabaseschemamodel.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsDatabaseSchemaModel : QAbstractItemModel
{
%Docstring
A model containing schemas from a database connection.

This class does not automatically subscribe to database updates. Schemas are queried
from the database initially upon model construction. In order
to update the listed schemas, QgsDatabaseSchemaModel.refresh() must be manually
called.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgsdatabaseschemamodel.h"
%End
public:

explicit QgsDatabaseSchemaModel( const QString &provider, const QString &connection, QObject *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsDatabaseSchemaModel, for the specified ``provider`` and ``connection`` name.

.. warning::

The ``provider`` must support the connection API methods in its QgsProviderMetadata implementation
in order for the model to work correctly.
%End

explicit QgsDatabaseSchemaModel( QgsAbstractDatabaseProviderConnection *connection /Transfer/, QObject *parent /TransferThis/ = 0 );

virtual QModelIndex parent( const QModelIndex &child ) const;

virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const;

virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const;

virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const;

virtual QModelIndex index( int row, int column, const QModelIndex &parent ) const;


public slots:

void refresh();
%Docstring
Refreshes the schema list by querying the underlying connection.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsdatabaseschemamodel.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -36,6 +36,7 @@
%Include auto_generated/qgscoordinatetransformcontext.sip
%Include auto_generated/qgscredentials.sip
%Include auto_generated/qgsdartmeasurement.sip
%Include auto_generated/qgsdatabaseschemamodel.sip
%Include auto_generated/qgsdatadefinedsizelegend.sip
%Include auto_generated/qgsdataitem.sip
%Include auto_generated/qgsdataitemprovider.sip
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -227,6 +227,7 @@ SET(QGIS_CORE_SRCS
qgscoordinateutils.cpp
qgscredentials.cpp
qgsdartmeasurement.cpp
qgsdatabaseschemamodel.cpp
qgsdatadefinedsizelegend.cpp
qgsdataitem.cpp
qgsdataitemprovider.cpp
Expand Down Expand Up @@ -727,6 +728,7 @@ SET(QGIS_CORE_HDRS
qgscoordinateutils.h
qgscredentials.h
qgsdartmeasurement.h
qgsdatabaseschemamodel.h
qgsdatadefinedsizelegend.h
qgsdataitem.h
qgsdataitemprovider.h
Expand Down
120 changes: 120 additions & 0 deletions src/core/qgsdatabaseschemamodel.cpp
@@ -0,0 +1,120 @@
/***************************************************************************
qgsdatabaseschemamodel.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 "qgsdatabaseschemamodel.h"
#include "qgsproviderregistry.h"
#include "qgsprovidermetadata.h"
#include "qgsabstractdatabaseproviderconnection.h"

QgsDatabaseSchemaModel::QgsDatabaseSchemaModel( const QString &provider, const QString &connection, QObject *parent )
: QAbstractItemModel( parent )
{
QgsProviderMetadata *metadata = QgsProviderRegistry::instance()->providerMetadata( provider );
Q_ASSERT( metadata );

mConnection.reset( dynamic_cast<QgsAbstractDatabaseProviderConnection *>( metadata->createConnection( connection ) ) );
Q_ASSERT( mConnection );
init();
}

QgsDatabaseSchemaModel::QgsDatabaseSchemaModel( QgsAbstractDatabaseProviderConnection *connection, QObject *parent )
: QAbstractItemModel( parent )
, mConnection( connection )
{
Q_ASSERT( mConnection );
init();
}

void QgsDatabaseSchemaModel::init()
{
Q_ASSERT( mConnection->capabilities() & QgsAbstractDatabaseProviderConnection::Capability::Schemas );
mSchemas = mConnection->schemas();
}

QModelIndex QgsDatabaseSchemaModel::parent( const QModelIndex &child ) const
{
Q_UNUSED( child )
return QModelIndex();
}


int QgsDatabaseSchemaModel::rowCount( const QModelIndex &parent ) const
{
if ( parent.isValid() )
return 0;

return mSchemas.count();
}

int QgsDatabaseSchemaModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return 1;
}


QVariant QgsDatabaseSchemaModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() )
return QVariant();

const QString schemaName = mSchemas.value( index.row() );
switch ( role )
{
case Qt::DisplayRole:
case Qt::ToolTipRole:
{
return schemaName;
}
}

return QVariant();
}

QModelIndex QgsDatabaseSchemaModel::index( int row, int column, const QModelIndex &parent ) const
{
if ( hasIndex( row, column, parent ) )
{
return createIndex( row, column, row );
}

return QModelIndex();
}

void QgsDatabaseSchemaModel::refresh()
{
const QStringList newSchemas = mConnection->schemas();
const QStringList oldSchemas = mSchemas;

for ( const QString &oldSchema : oldSchemas )
{
if ( !newSchemas.contains( oldSchema ) )
{
int r = mSchemas.indexOf( oldSchema );
beginRemoveRows( QModelIndex(), r, r );
mSchemas.removeAt( r );
endRemoveRows();
}
}

for ( const QString &newSchema : newSchemas )
{
if ( !mSchemas.contains( newSchema ) )
{
beginInsertRows( QModelIndex(), mSchemas.count(), mSchemas.count() );
mSchemas.append( newSchema );
endInsertRows();
}
}
}
78 changes: 78 additions & 0 deletions src/core/qgsdatabaseschemamodel.h
@@ -0,0 +1,78 @@
/***************************************************************************
qgsdatabaseschemamodel.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 QGSDATABASESCHEMAMODEL_H
#define QGSDATABASESCHEMAMODEL_H

#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QStringList>
#include <memory>

#include "qgis_core.h"
#include "qgis_sip.h"

class QgsProviderMetadata;
class QgsAbstractDatabaseProviderConnection;

/**
* \ingroup core
* \class QgsDatabaseSchemaModel
* \brief A model containing schemas from a database connection.
*
* This class does not automatically subscribe to database updates. Schemas are queried
* from the database initially upon model construction. In order
* to update the listed schemas, QgsDatabaseSchemaModel::refresh() must be manually
* called.
*
* \since QGIS 3.14
*/
class CORE_EXPORT QgsDatabaseSchemaModel : public QAbstractItemModel
{
Q_OBJECT

public:

/**
* Constructor for QgsDatabaseSchemaModel, for the specified \a provider and \a connection name.
*
* \warning The \a provider must support the connection API methods in its QgsProviderMetadata implementation
* in order for the model to work correctly.
*/
explicit QgsDatabaseSchemaModel( const QString &provider, const QString &connection, QObject *parent SIP_TRANSFERTHIS = nullptr );

explicit QgsDatabaseSchemaModel( QgsAbstractDatabaseProviderConnection *connection SIP_TRANSFER, QObject *parent SIP_TRANSFERTHIS = nullptr );

// QAbstractItemModel interface
QModelIndex parent( const QModelIndex &child ) const override;
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
QModelIndex index( int row, int column, const QModelIndex &parent ) const override;

public slots:

/**
* Refreshes the schema list by querying the underlying connection.
*/
void refresh();

private:
void init();
std::unique_ptr< QgsAbstractDatabaseProviderConnection > mConnection;
QStringList mSchemas;
};

#endif // QGSDATABASESCHEMAMODEL_H
3 changes: 2 additions & 1 deletion tests/src/python/CMakeLists.txt
Expand Up @@ -186,7 +186,6 @@ ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidge
ADD_PYTHON_TEST(PyQgsProjectMetadata test_qgsprojectmetadata.py)
ADD_PYTHON_TEST(PyQgsPropertyOverrideButton test_qgspropertyoverridebutton.py)
ADD_PYTHON_TEST(PyQgsProviderConnectionModel test_qgsproviderconnectionmodel.py)
ADD_PYTHON_TEST(PyQgsProviderConnectionPostgres test_qgsproviderconnection_postgres.py)
ADD_PYTHON_TEST(PyQgsProviderConnectionGpkg test_qgsproviderconnection_ogr_gpkg.py)
ADD_PYTHON_TEST(TestQgsRandomMarkerSymbolLayer test_qgsrandommarkersymbollayer.py)
ADD_PYTHON_TEST(PyQgsRange test_qgsrange.py)
Expand Down Expand Up @@ -304,6 +303,8 @@ IF (ENABLE_PGTEST)
ADD_PYTHON_TEST(PyQgsAuthManagerPasswordPostgresTest test_authmanager_password_postgres.py)
ADD_PYTHON_TEST(PyQgsAuthManagerOgrPostgresTest test_authmanager_ogr_postgres.py)
ADD_PYTHON_TEST(PyQgsDbManagerPostgis test_db_manager_postgis.py)
ADD_PYTHON_TEST(PyQgsDatabaseSchemaModel test_qgsdatabaseschemamodel.py)
ADD_PYTHON_TEST(PyQgsProviderConnectionPostgres test_qgsproviderconnection_postgres.py)
ENDIF (ENABLE_PGTEST)

IF (ENABLE_MSSQLTEST)
Expand Down

0 comments on commit a0a57d5

Please sign in to comment.