Skip to content
Permalink
Browse files
refactor mssql provider gui with enhanced filtering UX
  • Loading branch information
3nids committed Nov 9, 2021
1 parent e010cd9 commit 29ff1bd2554ebcd9121bfe297088f174dad939c7
@@ -33,6 +33,7 @@
#include "qgsproject.h"
#include "qgsgui.h"
#include "qgsiconutils.h"
#include "qgsdbfilterproxymodel.h"

#include <QFileDialog>
#include <QInputDialog>
@@ -124,9 +125,8 @@ void QgsMssqlSourceSelectDelegate::setModelData( QWidget *editor, QAbstractItemM
}

QgsMssqlSourceSelect::QgsMssqlSourceSelect( 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, &QgsMssqlSourceSelect::btnConnect_clicked );
@@ -136,10 +136,6 @@ QgsMssqlSourceSelect::QgsMssqlSourceSelect( QWidget *parent, Qt::WindowFlags fl,
connect( btnDelete, &QPushButton::clicked, this, &QgsMssqlSourceSelect::btnDelete_clicked );
connect( btnSave, &QPushButton::clicked, this, &QgsMssqlSourceSelect::btnSave_clicked );
connect( btnLoad, &QPushButton::clicked, this, &QgsMssqlSourceSelect::btnLoad_clicked );
connect( mSearchGroupBox, &QGroupBox::toggled, this, &QgsMssqlSourceSelect::mSearchGroupBox_toggled );
connect( mSearchTableEdit, &QLineEdit::textChanged, this, &QgsMssqlSourceSelect::mSearchTableEdit_textChanged );
connect( mSearchColumnComboBox, &QComboBox::currentTextChanged, this, &QgsMssqlSourceSelect::mSearchColumnComboBox_currentIndexChanged );
connect( mSearchModeComboBox, &QComboBox::currentTextChanged, this, &QgsMssqlSourceSelect::mSearchModeComboBox_currentIndexChanged );
connect( cmbConnections, static_cast<void ( QComboBox::* )( int )>( &QComboBox::activated ), this, &QgsMssqlSourceSelect::cmbConnections_activated );
connect( mTablesTreeView, &QTreeView::clicked, this, &QgsMssqlSourceSelect::mTablesTreeView_clicked );
connect( mTablesTreeView, &QTreeView::doubleClicked, this, &QgsMssqlSourceSelect::mTablesTreeView_doubleClicked );
@@ -168,24 +164,10 @@ QgsMssqlSourceSelect::QgsMssqlSourceSelect( QWidget *parent, Qt::WindowFlags fl,

populateConnectionList();

mSearchModeComboBox->addItem( tr( "Wildcard" ) );
mSearchModeComboBox->addItem( tr( "RegExp" ) );
mTableModel = new QgsMssqlTableModel( this );
setSourceModel( mTableModel );

mSearchColumnComboBox->addItem( tr( "All" ) );
mSearchColumnComboBox->addItem( tr( "Schema" ) );
mSearchColumnComboBox->addItem( tr( "Table" ) );
mSearchColumnComboBox->addItem( tr( "Type" ) );
mSearchColumnComboBox->addItem( tr( "Geometry column" ) );
mSearchColumnComboBox->addItem( tr( "Primary key column" ) );
mSearchColumnComboBox->addItem( tr( "SRID" ) );
mSearchColumnComboBox->addItem( tr( "Sql" ) );

mProxyModel.setParent( this );
mProxyModel.setFilterKeyColumn( -1 );
mProxyModel.setFilterCaseSensitivity( Qt::CaseInsensitive );
mProxyModel.setSourceModel( &mTableModel );

mTablesTreeView->setModel( &mProxyModel );
mTablesTreeView->setModel( proxyModel() );
mTablesTreeView->setSortingEnabled( true );
mTablesTreeView->setEditTriggers( QAbstractItemView::CurrentChanged );
mTablesTreeView->setItemDelegate( new QgsMssqlSourceSelectDelegate( this ) );
@@ -195,28 +177,13 @@ QgsMssqlSourceSelect::QgsMssqlSourceSelect( QWidget *parent, Qt::WindowFlags fl,
const QgsSettings settings;
mTablesTreeView->setSelectionMode( QAbstractItemView::ExtendedSelection );


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

mHoldDialogOpen->setChecked( settings.value( QStringLiteral( "Windows/MSSQLSourceSelect/HoldDialogOpen" ), false ).toBool() );

for ( int i = 0; i < mTableModel.columnCount(); i++ )
for ( int i = 0; i < mTableModel->columnCount(); i++ )
{
mTablesTreeView->setColumnWidth( i, settings.value( QStringLiteral( "Windows/MSSQLSourceSelect/columnWidths/%1" ).arg( i ), mTablesTreeView->columnWidth( i ) ).toInt() );
}

//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 );
}

@@ -321,71 +288,9 @@ void QgsMssqlSourceSelect::mTablesTreeView_doubleClicked( const QModelIndex & )
addButtonClicked();
}

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

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

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

void QgsMssqlSourceSelect::mSearchColumnComboBox_currentIndexChanged( const QString &text )
{
if ( text == tr( "All" ) )
{
mProxyModel.setFilterKeyColumn( -1 );
}
else if ( text == tr( "Schema" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmSchema );
}
else if ( text == tr( "Table" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmTable );
}
else if ( text == tr( "Type" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmType );
}
else if ( text == tr( "Geometry column" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmGeomCol );
}
else if ( text == tr( "Primary key column" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmPkCol );
}
else if ( text == tr( "SRID" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmSrid );
}
else if ( text == tr( "Sql" ) )
{
mProxyModel.setFilterKeyColumn( QgsMssqlTableModel::DbtmSql );
}
}

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

void QgsMssqlSourceSelect::setLayerType( const QgsMssqlLayerProperty &layerProperty )
{
mTableModel.setGeometryTypesForTable( layerProperty );
mTableModel->setGeometryTypesForTable( layerProperty );
}

QgsMssqlSourceSelect::~QgsMssqlSourceSelect()
@@ -399,7 +304,7 @@ QgsMssqlSourceSelect::~QgsMssqlSourceSelect()
QgsSettings settings;
settings.setValue( QStringLiteral( "Windows/MSSQLSourceSelect/HoldDialogOpen" ), mHoldDialogOpen->isChecked() );

for ( int i = 0; i < mTableModel.columnCount(); i++ )
for ( int i = 0; i < mTableModel->columnCount(); i++ )
{
settings.setValue( QStringLiteral( "Windows/MSSQLSourceSelect/columnWidths/%1" ).arg( i ), mTablesTreeView->columnWidth( i ) );
}
@@ -441,7 +346,7 @@ void QgsMssqlSourceSelect::addButtonClicked()
if ( idx.column() != QgsMssqlTableModel::DbtmTable )
continue;

const QString uri = mTableModel.layerURI( mProxyModel.mapToSource( idx ), mConnInfo, mUseEstimatedMetadata, disableInvalidGeometryHandling );
const QString uri = mTableModel->layerURI( proxyModel()->mapToSource( idx ), mConnInfo, mUseEstimatedMetadata, disableInvalidGeometryHandling );
if ( uri.isNull() )
continue;

@@ -472,10 +377,10 @@ void QgsMssqlSourceSelect::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 );

mTableModel.setConnectionName( cmbConnections->currentText() );
mTableModel->setConnectionName( cmbConnections->currentText() );
// populate the table list
const QgsSettings settings;
const QString key = "/MSSQL/connections/" + cmbConnections->currentText();
@@ -579,7 +484,7 @@ void QgsMssqlSourceSelect::btnConnect_clicked()

layer.type = type;
layer.srid = srid;
mTableModel.addTableEntry( layer );
mTableModel->addTableEntry( layer );
}

if ( mColumnTypeThread )
@@ -589,14 +494,14 @@ void QgsMssqlSourceSelect::btnConnect_clicked()
}

//if we have only one schema item, expand it by default
const int numTopLevelItems = mTableModel.invisibleRootItem()->rowCount();
if ( numTopLevelItems < 2 || mTableModel.tableCount() < 20 )
const int numTopLevelItems = mTableModel->invisibleRootItem()->rowCount();
if ( numTopLevelItems < 2 || mTableModel->tableCount() < 20 )
{
//expand all the toplevel items
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 ) ) ) );
}
}
}
@@ -660,11 +565,11 @@ void QgsMssqlSourceSelect::setSql( const QModelIndex &index )
return;
}

const QModelIndex idx = mProxyModel.mapToSource( index );
const QString tableName = mTableModel.itemFromIndex( idx.sibling( idx.row(), QgsMssqlTableModel::DbtmTable ) )->text();
const QModelIndex idx = proxyModel()->mapToSource( index );
const QString tableName = mTableModel->itemFromIndex( idx.sibling( idx.row(), QgsMssqlTableModel::DbtmTable ) )->text();
const bool disableInvalidGeometryHandling = QgsMssqlConnection::isInvalidGeometryHandlingDisabled( cmbConnections->currentText() );
const QgsVectorLayer::LayerOptions options { QgsProject::instance()->transformContext() };
std::unique_ptr< QgsVectorLayer > vlayer = std::make_unique< QgsVectorLayer>( mTableModel.layerURI( idx, mConnInfo, mUseEstimatedMetadata, disableInvalidGeometryHandling ), tableName, QStringLiteral( "mssql" ), options );
std::unique_ptr< QgsVectorLayer > vlayer = std::make_unique< QgsVectorLayer>( mTableModel->layerURI( idx, mConnInfo, mUseEstimatedMetadata, disableInvalidGeometryHandling ), tableName, QStringLiteral( "mssql" ), options );

if ( !vlayer->isValid() )
{
@@ -675,7 +580,7 @@ void QgsMssqlSourceSelect::setSql( const QModelIndex &index )
QgsQueryBuilder gb( vlayer.get(), this );
if ( gb.exec() )
{
mTableModel.setSql( mProxyModel.mapToSource( index ), gb.sql() );
mTableModel->setSql( proxyModel()->mapToSource( index ), gb.sql() );
}
}

@@ -17,13 +17,13 @@
#ifndef QGSMSSQLSOURCESELECT_H
#define QGSMSSQLSOURCESELECT_H

#include "ui_qgsdbsourceselectbase.h"
#include "qgsguiutils.h"
#include "qgsdbfilterproxymodel.h"
#include "qgsmssqltablemodel.h"
#include "qgshelp.h"
#include "qgsproviderregistry.h"
#include "qgsabstractdatasourcewidget.h"
#include "qgsdbsourceselectbase.h"
#include "qgsmssqltablemodel.h"


#include <QMap>
#include <QPair>
@@ -58,7 +58,7 @@ class QgsMssqlSourceSelectDelegate : public QItemDelegate
* for MSSQL databases. The user can then connect and add
* tables from the database to the map canvas.
*/
class QgsMssqlSourceSelect : public QgsAbstractDataSourceWidget, private Ui::QgsDbSourceSelectBase
class QgsMssqlSourceSelect : public QgsDbSourceSelectBase
{
Q_OBJECT

@@ -108,10 +108,6 @@ class QgsMssqlSourceSelect : public QgsAbstractDataSourceWidget, private Ui::Qgs
void btnSave_clicked();
//! Loads the selected connections from file
void btnLoad_clicked();
void mSearchGroupBox_toggled( bool );
void mSearchTableEdit_textChanged( const QString &text );
void mSearchColumnComboBox_currentIndexChanged( const QString &text );
void mSearchModeComboBox_currentIndexChanged( const QString &text );
void setSql( const QModelIndex &index );
//! Store the selected database
void cmbConnections_activated( int );
@@ -149,8 +145,7 @@ class QgsMssqlSourceSelect : public QgsAbstractDataSourceWidget, private Ui::Qgs
QMap<QString, QPair<QString, QIcon> > mLayerIcons;

//! Model that acts as datasource for mTableTreeWidget
QgsMssqlTableModel mTableModel;
QgsDatabaseFilterProxyModel mProxyModel;
QgsMssqlTableModel *mTableModel = nullptr;

QPushButton *mBuildQueryButton = nullptr;

@@ -22,19 +22,49 @@
#include "qgsdatasourceuri.h"
#include "qgsiconutils.h"

QgsMssqlTableModel::QgsMssqlTableModel()
QgsMssqlTableModel::QgsMssqlTableModel( QObject *parent )
: QgsAbstractDbTableModel( parent )
{
QStringList headerLabels;
headerLabels << tr( "Schema" );
headerLabels << tr( "Table" );
headerLabels << tr( "Type" );
headerLabels << tr( "Geometry column" );
headerLabels << tr( "SRID" );
headerLabels << tr( "Primary key column" );
headerLabels << tr( "Select at id" );
headerLabels << tr( "Sql" );
headerLabels << tr( "View" );
setHorizontalHeaderLabels( headerLabels );
mColumns << tr( "Schema" )
<< tr( "Table" )
<< tr( "Type" )
<< tr( "Geometry column" )
<< tr( "SRID" )
<< tr( "Primary key column" )
<< tr( "Select at id" )
<< tr( "Sql" )
<< tr( "View" );
setHorizontalHeaderLabels( mColumns );
}

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

int QgsMssqlTableModel::defaultSearchColumn() const
{
return static_cast<int>( DbtmTable );
}

bool QgsMssqlTableModel::searchableColumn( int column ) const
{
Columns col = static_cast<Columns>( column );
switch ( col )
{
case DbtmSchema:
case DbtmTable:
case DbtmGeomCol:
case DbtmType:
case DbtmSrid:
case DbtmSql:
return true;

case DbtmPkCol:
case DbtmSelectAtId:
case DbtmView:
return false;
}
}

void QgsMssqlTableModel::addTableEntry( const QgsMssqlLayerProperty &layerProperty )
@@ -248,9 +278,9 @@ void QgsMssqlTableModel::setGeometryTypesForTable( QgsMssqlLayerProperty layerPr
}

QList<QStandardItem *> row;
row.reserve( DbtmColumns );
row.reserve( columnCount() );

for ( int j = 0; j < DbtmColumns; j++ )
for ( int j = 0; j < columnCount(); j++ )
{
row << itemFromIndex( currentChildIndex.sibling( i, j ) );
}
@@ -323,7 +353,7 @@ bool QgsMssqlTableModel::setData( const QModelIndex &idx, const QVariant &value,
if ( ok && !pkCols.isEmpty() )
ok = pkCols.contains( idx.sibling( idx.row(), DbtmPkCol ).data().toString() );

for ( int i = 0; i < DbtmColumns; i++ )
for ( int i = 0; i < columnCount(); i++ )
{
QStandardItem *item = itemFromIndex( idx.sibling( idx.row(), i ) );
if ( ok )
Loading

0 comments on commit 29ff1bd

Please sign in to comment.