Skip to content
Permalink
Browse files
refactor spatialite provider gui with enhanced filtering UX
  • Loading branch information
3nids committed Nov 9, 2021
1 parent 7c6753c commit e010cd92104abaa6c7a0d8b7ab86135fd53b3d8f
@@ -30,6 +30,8 @@ email : a.furieri@lqt.it
#include "qgsgui.h"
#include "qgsprovidermetadata.h"
#include "qgsspatialiteproviderconnection.h"
#include "qgsspatialitetablemodel.h"
#include "qgsdbfilterproxymodel.h"

#include <QInputDialog>
#include <QMessageBox>
@@ -44,18 +46,13 @@ email : a.furieri@lqt.it
#endif

QgsSpatiaLiteSourceSelect::QgsSpatiaLiteSourceSelect( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode theWidgetMode ):
QgsAbstractDataSourceWidget( parent, fl, theWidgetMode )
QgsDbSourceSelectBase( parent, fl, theWidgetMode )
{
setupUi( this );
QgsGui::instance()->enableAutoGeometryRestore( this );

connect( btnConnect, &QPushButton::clicked, this, &QgsSpatiaLiteSourceSelect::btnConnect_clicked );
connect( btnNew, &QPushButton::clicked, this, &QgsSpatiaLiteSourceSelect::btnNew_clicked );
connect( btnDelete, &QPushButton::clicked, this, &QgsSpatiaLiteSourceSelect::btnDelete_clicked );
connect( mSearchGroupBox, &QGroupBox::toggled, this, &QgsSpatiaLiteSourceSelect::mSearchGroupBox_toggled );
connect( mSearchTableEdit, &QLineEdit::textChanged, this, &QgsSpatiaLiteSourceSelect::mSearchTableEdit_textChanged );
connect( mSearchColumnComboBox, &QComboBox::currentTextChanged, this, &QgsSpatiaLiteSourceSelect::mSearchColumnComboBox_currentIndexChanged );
connect( mSearchModeComboBox, &QComboBox::currentTextChanged, this, &QgsSpatiaLiteSourceSelect::mSearchModeComboBox_currentIndexChanged );
connect( cbxAllowGeometrylessTables, &QCheckBox::stateChanged, this, &QgsSpatiaLiteSourceSelect::cbxAllowGeometrylessTables_stateChanged );
connect( cmbConnections, static_cast<void ( QComboBox::* )( int )>( &QComboBox::activated ), this, &QgsSpatiaLiteSourceSelect::cmbConnections_activated );
connect( mTablesTreeView, &QTreeView::clicked, this, &QgsSpatiaLiteSourceSelect::mTablesTreeView_clicked );
@@ -90,39 +87,14 @@ QgsSpatiaLiteSourceSelect::QgsSpatiaLiteSourceSelect( QWidget *parent, Qt::Windo

populateConnectionList();

mSearchModeComboBox->addItem( tr( "Wildcard" ) );
mSearchModeComboBox->addItem( tr( "RegExp" ) );

mSearchColumnComboBox->addItem( tr( "All" ) );
mSearchColumnComboBox->addItem( tr( "Table" ) );
mSearchColumnComboBox->addItem( tr( "Type" ) );
mSearchColumnComboBox->addItem( tr( "Geometry column" ) );
mSearchColumnComboBox->addItem( tr( "Sql" ) );

mProxyModel.setParent( this );
mProxyModel.setFilterKeyColumn( -1 );
mProxyModel.setFilterCaseSensitivity( Qt::CaseInsensitive );
mProxyModel.setDynamicSortFilter( true );
mProxyModel.setSourceModel( &mTableModel );
mTablesTreeView->setModel( &mProxyModel );
mTableModel = new QgsSpatiaLiteTableModel( this );
setSourceModel( mTableModel );

mTablesTreeView->setModel( proxyModel() );
mTablesTreeView->setSortingEnabled( true );

connect( mTablesTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsSpatiaLiteSourceSelect::treeWidgetSelectionChanged );

//for Qt < 4.3.2, passing -1 to include all model columns
//in search does not seem to work
mSearchColumnComboBox->setCurrentIndex( 1 );

//hide the search options by default
//they will be shown when the user ticks
//the search options group box
mSearchLabel->setVisible( false );
mSearchColumnComboBox->setVisible( false );
mSearchColumnsLabel->setVisible( false );
mSearchModeComboBox->setVisible( false );
mSearchModeLabel->setVisible( false );
mSearchTableEdit->setVisible( false );

cbxAllowGeometrylessTables->setDisabled( true );
}

@@ -188,59 +160,9 @@ void QgsSpatiaLiteSourceSelect::mTablesTreeView_doubleClicked( const QModelIndex
setSql( index );
}

void QgsSpatiaLiteSourceSelect::mSearchGroupBox_toggled( bool checked )
{
if ( mSearchTableEdit->text().isEmpty() )
return;

mSearchTableEdit_textChanged( checked ? mSearchTableEdit->text() : QString() );
}

void QgsSpatiaLiteSourceSelect::mSearchTableEdit_textChanged( const QString &text )
{
if ( mSearchModeComboBox->currentText() == tr( "Wildcard" ) )
{
mProxyModel._setFilterWildcard( text );
}
else if ( mSearchModeComboBox->currentText() == tr( "RegExp" ) )
{
mProxyModel._setFilterRegExp( text );
}
}

void QgsSpatiaLiteSourceSelect::mSearchColumnComboBox_currentIndexChanged( const QString &text )
{
if ( text == tr( "All" ) )
{
mProxyModel.setFilterKeyColumn( -1 );
}
else if ( text == tr( "Table" ) )
{
mProxyModel.setFilterKeyColumn( 0 );
}
else if ( text == tr( "Type" ) )
{
mProxyModel.setFilterKeyColumn( 1 );
}
else if ( text == tr( "Geometry column" ) )
{
mProxyModel.setFilterKeyColumn( 2 );
}
else if ( text == tr( "Sql" ) )
{
mProxyModel.setFilterKeyColumn( 3 );
}
}

void QgsSpatiaLiteSourceSelect::mSearchModeComboBox_currentIndexChanged( const QString &text )
{
Q_UNUSED( text )
mSearchTableEdit_textChanged( mSearchTableEdit->text() );
}

void QgsSpatiaLiteSourceSelect::setLayerType( const QString &table, const QString &column, const QString &type )
{
mTableModel.setGeometryTypesForTable( table, column, type );
mTableModel->setGeometryTypesForTable( table, column, type );
mTablesTreeView->sortByColumn( 0, Qt::AscendingOrder );
}

@@ -324,9 +246,9 @@ bool QgsSpatiaLiteSourceSelect::newConnection( QWidget *parent )

QString QgsSpatiaLiteSourceSelect::layerURI( const QModelIndex &index )
{
const QString tableName = mTableModel.itemFromIndex( index.sibling( index.row(), 0 ) )->text();
QString geomColumnName = mTableModel.itemFromIndex( index.sibling( index.row(), 2 ) )->text();
QString sql = mTableModel.itemFromIndex( index.sibling( index.row(), 3 ) )->text();
const QString tableName = mTableModel->itemFromIndex( index.sibling( index.row(), 0 ) )->text();
QString geomColumnName = mTableModel->itemFromIndex( index.sibling( index.row(), 2 ) )->text();
QString sql = mTableModel->itemFromIndex( index.sibling( index.row(), 3 ) )->text();

if ( geomColumnName.contains( QLatin1String( " AS " ) ) )
{
@@ -404,7 +326,7 @@ void QgsSpatiaLiteSourceSelect::addButtonClicked()
//top level items only contain the schema names
continue;
}
currentItem = mTableModel.itemFromIndex( mProxyModel.mapToSource( *selected_it ) );
currentItem = mTableModel->itemFromIndex( proxyModel()->mapToSource( *selected_it ) );
if ( !currentItem )
{
continue;
@@ -416,7 +338,7 @@ void QgsSpatiaLiteSourceSelect::addButtonClicked()
if ( !dbInfo[currentSchemaName].contains( currentRow ) )
{
dbInfo[currentSchemaName][currentRow] = true;
m_selectedTables << layerURI( mProxyModel.mapToSource( *selected_it ) );
m_selectedTables << layerURI( proxyModel()->mapToSource( *selected_it ) );
}
}

@@ -483,19 +405,19 @@ void QgsSpatiaLiteSourceSelect::btnConnect_clicked()
return;
}

const QModelIndex rootItemIndex = mTableModel.indexFromItem( mTableModel.invisibleRootItem() );
mTableModel.removeRows( 0, mTableModel.rowCount( rootItemIndex ), rootItemIndex );
const QModelIndex rootItemIndex = mTableModel->indexFromItem( mTableModel->invisibleRootItem() );
mTableModel->removeRows( 0, mTableModel->rowCount( rootItemIndex ), rootItemIndex );

// populate the table list
// get the list of suitable tables and columns and populate the UI

mTableModel.setSqliteDb( subKey );
mTableModel->setSqliteDb( subKey );

const QList<QgsSpatiaLiteConnection::TableEntry> tables = conn.tables();
const auto constTables = tables;
for ( const QgsSpatiaLiteConnection::TableEntry &table : constTables )
{
mTableModel.addTableEntry( table.type, table.tableName, table.column, QString() );
mTableModel->addTableEntry( table.type, table.tableName, table.column, QString() );
}

if ( cmbConnections->count() > 0 )
@@ -506,10 +428,10 @@ void QgsSpatiaLiteSourceSelect::btnConnect_clicked()
mTablesTreeView->sortByColumn( 0, Qt::AscendingOrder );

//expand all the toplevel items
const int numTopLevelItems = mTableModel.invisibleRootItem()->rowCount();
const int numTopLevelItems = mTableModel->invisibleRootItem()->rowCount();
for ( int i = 0; i < numTopLevelItems; ++i )
{
mTablesTreeView->expand( mProxyModel.mapFromSource( mTableModel.indexFromItem( mTableModel.invisibleRootItem()->child( i ) ) ) );
mTablesTreeView->expand( proxyModel()->mapFromSource( mTableModel->indexFromItem( mTableModel->invisibleRootItem()->child( i ) ) ) );
}
mTablesTreeView->resizeColumnToContents( 0 );
mTablesTreeView->resizeColumnToContents( 1 );
@@ -529,8 +451,8 @@ QString QgsSpatiaLiteSourceSelect::connectionInfo()

void QgsSpatiaLiteSourceSelect::setSql( const QModelIndex &index )
{
const QModelIndex idx = mProxyModel.mapToSource( index );
const auto item { mTableModel.itemFromIndex( idx.sibling( idx.row(), 0 ) ) };
const QModelIndex idx = proxyModel()->mapToSource( index );
const auto item { mTableModel->itemFromIndex( idx.sibling( idx.row(), 0 ) ) };
if ( !item )
{
return;
@@ -551,7 +473,7 @@ void QgsSpatiaLiteSourceSelect::setSql( const QModelIndex &index )
QgsQueryBuilder *gb = new QgsQueryBuilder( vlayer, this );
if ( gb->exec() )
{
mTableModel.setSql( mProxyModel.mapToSource( index ), gb->sql() );
mTableModel->setSql( proxyModel()->mapToSource( index ), gb->sql() );
}

delete gb;
@@ -17,14 +17,12 @@
#ifndef QGSSPATIALITESOURCESELECT_H
#define QGSSPATIALITESOURCESELECT_H

#include "ui_qgsdbsourceselectbase.h"

#include "qgsguiutils.h"
#include "qgsdbfilterproxymodel.h"
#include "qgsspatialitetablemodel.h"
#include "qgshelp.h"
#include "qgsproviderregistry.h"
#include "qgsabstractdatasourcewidget.h"
#include "qgsdbsourceselectbase.h"


#include <QThread>
#include <QMap>
@@ -33,6 +31,7 @@
#include <QIcon>
#include <QFileDialog>

class QgsSpatiaLiteTableModel;
class QStringList;
class QTableWidgetItem;
class QPushButton;
@@ -45,7 +44,7 @@ class QPushButton;
* for SpatiaLite/SQLite databases. The user can then connect and add
* tables from the database to the map canvas.
*/
class QgsSpatiaLiteSourceSelect: public QgsAbstractDataSourceWidget, private Ui::QgsDbSourceSelectBase
class QgsSpatiaLiteSourceSelect: public QgsDbSourceSelectBase
{
Q_OBJECT

@@ -84,10 +83,6 @@ class QgsSpatiaLiteSourceSelect: public QgsAbstractDataSourceWidget, private Ui:
void btnNew_clicked();
//! Deletes the selected connection
void btnDelete_clicked();
void mSearchGroupBox_toggled( bool );
void mSearchTableEdit_textChanged( const QString &text );
void mSearchColumnComboBox_currentIndexChanged( const QString &text );
void mSearchModeComboBox_currentIndexChanged( const QString &text );
void cbxAllowGeometrylessTables_stateChanged( int );
void setSql( const QModelIndex &index );
void cmbConnections_activated( int );
@@ -125,8 +120,7 @@ class QgsSpatiaLiteSourceSelect: public QgsAbstractDataSourceWidget, private Ui:
// Storage for the range of layer type icons
QMap < QString, QPair < QString, QIcon > >mLayerIcons;
//! Model that acts as datasource for mTableTreeWidget
QgsSpatiaLiteTableModel mTableModel;
QgsDatabaseFilterProxyModel mProxyModel;
QgsSpatiaLiteTableModel *mTableModel;

QString layerURI( const QModelIndex &index );
QPushButton *mBuildQueryButton = nullptr;
@@ -19,14 +19,29 @@
#include "qgsapplication.h"
#include "qgsiconutils.h"

QgsSpatiaLiteTableModel::QgsSpatiaLiteTableModel()
QgsSpatiaLiteTableModel::QgsSpatiaLiteTableModel( QObject *parent )
{
QStringList headerLabels;
headerLabels << tr( "Table" );
headerLabels << tr( "Type" );
headerLabels << tr( "Geometry column" );
headerLabels << tr( "Sql" );
setHorizontalHeaderLabels( headerLabels );
mColumns << tr( "Table" )
<< tr( "Type" )
<< tr( "Geometry column" )
<< tr( "Sql" );
setHorizontalHeaderLabels( mColumns );
}

QStringList QgsSpatiaLiteTableModel::columns() const
{
return mColumns;
}

int QgsSpatiaLiteTableModel::defaultSearchColumn() const
{
return 0;
}

bool QgsSpatiaLiteTableModel::searchableColumn( int column ) const
{
Q_UNUSED( column )
return true;
}

void QgsSpatiaLiteTableModel::addTableEntry( const QString &type, const QString &tableName, const QString &geometryColName, const QString &sql )
@@ -18,21 +18,28 @@
#ifndef QGSSPATIALITETABLEMODEL_H
#define QGSSPATIALITETABLEMODEL_H

#include <QStandardItemModel>
class QIcon;
#include "qgswkbtypes.h"
#include "qgsabstractdbtablemodel.h"

class QIcon;


/**
* A model that holds the tables of a database in a hierarchy where the
* SQLite DB is the root elements that contain the individual tables as children.
*
* The tables have the following columns: Type, Tablename, Geometry Column
*/
class QgsSpatiaLiteTableModel: public QStandardItemModel
class QgsSpatiaLiteTableModel: public QgsAbstractDbTableModel
{
Q_OBJECT public:

QgsSpatiaLiteTableModel();
QgsSpatiaLiteTableModel( QObject *parent = nullptr );

QStringList columns() const override;
int defaultSearchColumn() const override;
bool searchableColumn( int column ) const override;

//! Adds entry for one database table to the model
void addTableEntry( const QString &type, const QString &tableName, const QString &geometryColName, const QString &sql );
//! Sets an sql statement that belongs to a cell specified by a model index
@@ -58,6 +65,7 @@ class QgsSpatiaLiteTableModel: public QStandardItemModel
//! Number of tables in the model
int mTableCount = 0;
QString mSqliteDb;
QStringList mColumns;

QIcon iconForType( QgsWkbTypes::Type type ) const;
QString displayStringForType( QgsWkbTypes::Type type ) const;

0 comments on commit e010cd9

Please sign in to comment.