Skip to content

Commit

Permalink
[addlayerbutton] Virtual Layers support added
Browse files Browse the repository at this point in the history
Some changes in connections are required to keep in sync
the available layers lists in the virtual layer dialog.

(Modeless support is on the way)
  • Loading branch information
elpaso committed Jun 2, 2017
1 parent 6c66738 commit 811e4df
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 107 deletions.
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1602,8 +1602,8 @@ void QgisApp::dataSourceManager()
connect( mDataSourceManagerDialog, &QgsDataSourceManagerDialog::showProgress, this, &QgisApp::showProgress );
connect( mDataSourceManagerDialog, &QgsDataSourceManagerDialog::showStatusMessage, this, &QgisApp::showStatusMessage );
connect( mDataSourceManagerDialog, &QgsDataSourceManagerDialog::addDatabaseLayers, this, &QgisApp::addDatabaseLayers );
connect( mDataSourceManagerDialog, &QgsDataSourceManagerDialog::replaceSelectedVectorLayer, this, &QgisApp::replaceSelectedVectorLayer );
}
// TODO: handle docked
mDataSourceManagerDialog->exec();
}

Expand Down
7 changes: 7 additions & 0 deletions src/app/qgsdatasourcemanagerdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QgsMapCanvas *mapCanvas,
connect( dlg, SIGNAL( addVectorLayer( QString, QString, QString ) ), this, SLOT( vectorLayerAdded( QString, QString, QString ) ) );
}

dlg = providerDialog( QStringLiteral( "virtual" ), tr( "Virtual" ), QStringLiteral( "/mActionAddVirtualLayer.svg" ) );

if ( dlg )
{
connect( dlg, SIGNAL( addVectorLayer( QString, QString, QString ) ), this, SLOT( vectorLayerAdded( QString, QString, QString ) ) );
connect( dlg, SIGNAL( replaceVectorLayer( QString, QString, QString, QString ) ), this, SIGNAL( replaceSelectedVectorLayer( QString, QString, QString, QString ) ) );
}
}

QgsDataSourceManagerDialog::~QgsDataSourceManagerDialog()
Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsdatasourcemanagerdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class QgsDataSourceManagerDialog : public QgsOptionsDialogBase
//! For signal forwarding to QgisApp
void addRasterLayer( QString const &uri, QString const &baseName, QString const &providerKey );
void addVectorLayer( const QString &vectorLayerPath, const QString &baseName, const QString &providerKey );
//! Replace the selected layer by a vector layer defined by uri, layer name, data source uri
void replaceSelectedVectorLayer( const QString &oldId, const QString &uri, const QString &layerName, const QString &provider );
void addWfsLayer( const QString &uri, const QString &typeName );
void addAfsLayer( const QString &uri, const QString &typeName );
void addVectorLayers( const QStringList &layerQStringList, const QString &enc, const QString &dataSourceType );
Expand Down
34 changes: 20 additions & 14 deletions src/providers/virtual/qgsembeddedlayerselectdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,30 @@ email : hugo dot mercier at oslandia dot com
#include <qgsvectordataprovider.h>

QgsEmbeddedLayerSelectDialog::QgsEmbeddedLayerSelectDialog( QWidget *parent, QgsLayerTreeView *tv )
: QDialog( parent )
: QDialog( parent ),
mTreeView( tv )
{
setupUi( this );
updateLayersList( );
}

QStringList QgsEmbeddedLayerSelectDialog::layers() const
{
QStringList ids;
QModelIndexList selected = mLayers->selectionModel()->selectedRows();
for ( int i = 0; i < selected.size(); i++ )
{
QgsVectorLayer *l = static_cast<QgsVectorLayer *>( mLayers->item( selected[i].row() )->data( Qt::UserRole ).value<void *>() );
ids << l->id();
}
return ids;
}

void QgsEmbeddedLayerSelectDialog::updateLayersList( )
{
// populate list
QList<QgsLayerTreeLayer *> layers = tv->layerTreeModel()->rootGroup()->findLayers();
mLayers->clear( );
QList<QgsLayerTreeLayer *> layers = mTreeView->layerTreeModel()->rootGroup()->findLayers();
Q_FOREACH ( const QgsLayerTreeLayer *l, layers )
{
if ( l->layer() && l->layer()->type() == QgsMapLayer::VectorLayer )
Expand All @@ -48,15 +66,3 @@ QgsEmbeddedLayerSelectDialog::QgsEmbeddedLayerSelectDialog( QWidget *parent, Qgs
}
}
}

QStringList QgsEmbeddedLayerSelectDialog::layers() const
{
QStringList ids;
QModelIndexList selected = mLayers->selectionModel()->selectedRows();
for ( int i = 0; i < selected.size(); i++ )
{
QgsVectorLayer *l = static_cast<QgsVectorLayer *>( mLayers->item( selected[i].row() )->data( Qt::UserRole ).value<void *>() );
ids << l->id();
}
return ids;
}
6 changes: 6 additions & 0 deletions src/providers/virtual/qgsembeddedlayerselectdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ class QgsEmbeddedLayerSelectDialog : public QDialog, private Ui::QgsEmbeddedLaye

//! Returns the list of layer ids selected
QStringList layers() const;

public slots:
void updateLayersList( );

private:
QgsLayerTreeView *mTreeView = nullptr;
};

#endif
191 changes: 119 additions & 72 deletions src/providers/virtual/qgsvirtuallayersourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ email : hugo dot mercier at oslandia dot com
#include "qgsembeddedlayerselectdialog.h"

#include <QUrl>
#include <QWidget>
#include <Qsci/qscilexer.h>
#include <QMessageBox>
#include <QTextStream>
Expand All @@ -40,16 +41,22 @@ QgsVirtualLayerSourceSelect::QgsVirtualLayerSourceSelect( QWidget *parent, Qt::W
: QDialog( parent, fl )
, mSrid( 0 )
, mWidgetMode( widgetMode )
, mTreeView( nullptr )
{
Q_UNUSED( widgetMode );
setupUi( this );

QObject::connect( mTestButton, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onTestQuery );
QObject::connect( mBrowseCRSBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onBrowseCRS );
QObject::connect( mAddLayerBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onAddLayer );
QObject::connect( mRemoveLayerBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onRemoveLayer );
QObject::connect( mImportLayerBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onImportLayer );
QObject::connect( mLayersTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &QgsVirtualLayerSourceSelect::onTableRowChanged );
if ( mWidgetMode != QgsProviderRegistry::WidgetMode::None )
{
buttonBox->removeButton( buttonBox->button( QDialogButtonBox::Cancel ) );
buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Add" ) );
}

connect( mTestButton, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onTestQuery );
connect( mBrowseCRSBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onBrowseCRS );
connect( mAddLayerBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onAddLayer );
connect( mRemoveLayerBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onRemoveLayer );
connect( mImportLayerBtn, &QAbstractButton::clicked, this, &QgsVirtualLayerSourceSelect::onImportLayer );
connect( mLayersTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &QgsVirtualLayerSourceSelect::onTableRowChanged );

// prepare provider list
Q_FOREACH ( const QString &pk, QgsProviderRegistry::instance()->providerList() )
Expand All @@ -62,73 +69,28 @@ QgsVirtualLayerSourceSelect::QgsVirtualLayerSourceSelect( QWidget *parent, Qt::W
mProviderList << pk;
}
}

QgsLayerTreeView *treeView = parent->findChild<QgsLayerTreeView *>( QStringLiteral( "theLayerTreeView" ) );
if ( treeView )
// It needs to find the layertree view without relying on the parent
// being the main window
for ( const QWidget *widget : qApp->allWidgets( ) )
{
QgsLayerTreeModel *model = qobject_cast<QgsLayerTreeModel *>( treeView->model() );
Q_FOREACH ( QgsLayerTreeLayer *layer, model->rootGroup()->findLayers() )
if ( ! mTreeView )
{
if ( layer->layer()->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( layer->layer() )->providerType() == QLatin1String( "virtual" ) )
{
// store layer's id as user data
mLayerNameCombo->addItem( layer->layer()->name(), layer->layer()->id() );
}
mTreeView = widget->findChild<QgsLayerTreeView *>( QStringLiteral( "theLayerTreeView" ) );
}
}

if ( mLayerNameCombo->count() == 0 )
mLayerNameCombo->addItem( QStringLiteral( "virtual_layer" ) );

// select the current layer, if any
if ( treeView )
{
QList<QgsMapLayer *> selected = treeView->selectedLayers();
if ( selected.size() == 1 && selected[0]->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( selected[0] )->providerType() == QLatin1String( "virtual" ) )
{
mLayerNameCombo->setCurrentIndex( mLayerNameCombo->findData( selected[0]->id() ) );
}
}

QObject::connect( mLayerNameCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsVirtualLayerSourceSelect::onLayerComboChanged );
updateLayersList();
connect( mLayerNameCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsVirtualLayerSourceSelect::onLayerComboChanged );
onLayerComboChanged( mLayerNameCombo->currentIndex() );

// configure auto completion with SQL functions
QsciAPIs *apis = new QsciAPIs( mQueryEdit->lexer() );

Q_INIT_RESOURCE( sqlfunctionslist );
QFile fFile( QStringLiteral( ":/sqlfunctions/list.txt" ) );
if ( fFile.open( QIODevice::ReadOnly ) )
{
QTextStream in( &fFile );
while ( !in.atEnd() )
{
apis->add( in.readLine().toLower() + "()" );
}
fFile.close();
}

// configure auto completion with table and column names
Q_FOREACH ( QgsMapLayer *l, QgsProject::instance()->mapLayers() )
// prepare embedded layer selection dialog and
// connect to model changes in the treeview
if ( mTreeView )
{
if ( l->type() == QgsMapLayer::VectorLayer )
{
apis->add( l->name() );
QgsVectorLayer *vl = static_cast<QgsVectorLayer *>( l );
Q_FOREACH ( const QgsField &f, vl->fields().toList() )
{
apis->add( f.name() );
}
}
mEmbeddedSelectionDialog = new QgsEmbeddedLayerSelectDialog( this, mTreeView );
connect( mTreeView->model(), &QAbstractItemModel::rowsInserted, this, &QgsVirtualLayerSourceSelect::updateLayersList );
connect( mTreeView->model(), &QAbstractItemModel::rowsRemoved, this, &QgsVirtualLayerSourceSelect::updateLayersList );
connect( mTreeView->model(), &QAbstractItemModel::dataChanged, this, &QgsVirtualLayerSourceSelect::updateLayersList );
}

apis->prepare();
mQueryEdit->lexer()->setAPIs( apis );

mQueryEdit->setWrapMode( QsciScintilla::WrapWord );

// prepare embedded layer selection dialog
mEmbeddedSelectionDialog = new QgsEmbeddedLayerSelectDialog( this, treeView );
}

void QgsVirtualLayerSourceSelect::onLayerComboChanged( int idx )
Expand Down Expand Up @@ -167,7 +129,9 @@ void QgsVirtualLayerSourceSelect::onLayerComboChanged( int idx )
mGeometryField->setText( def.geometryField() );
}

// add embedded layers
// Clear embedded layers table
mLayersTable->model()->removeRows( 0, mLayersTable->model()->rowCount( ) );
// Add embedded layers
Q_FOREACH ( const QgsVirtualLayerDefinition::SourceLayer &l, def.sourceLayers() )
{
if ( ! l.isReferenced() )
Expand Down Expand Up @@ -274,6 +238,76 @@ void QgsVirtualLayerSourceSelect::onTableRowChanged( const QModelIndex &current,
mRemoveLayerBtn->setEnabled( current.row() != -1 );
}

void QgsVirtualLayerSourceSelect::updateLayersList()
{
mLayerNameCombo->clear();

if ( mTreeView )
{
QgsLayerTreeModel *model = qobject_cast<QgsLayerTreeModel *>( mTreeView->model() );
Q_FOREACH ( QgsLayerTreeLayer *layer, model->rootGroup()->findLayers() )
{
if ( layer->layer()->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( layer->layer() )->providerType() == QLatin1String( "virtual" ) )
{
// store layer's id as user data
mLayerNameCombo->addItem( layer->layer()->name(), layer->layer()->id() );
}
}
}

if ( mLayerNameCombo->count() == 0 )
mLayerNameCombo->addItem( QStringLiteral( "virtual_layer" ) );

// select the current layer, if any
if ( mTreeView )
{
QList<QgsMapLayer *> selected = mTreeView->selectedLayers();
if ( selected.size() == 1 && selected[0]->type() == QgsMapLayer::VectorLayer && static_cast<QgsVectorLayer *>( selected[0] )->providerType() == QLatin1String( "virtual" ) )
{
mLayerNameCombo->setCurrentIndex( mLayerNameCombo->findData( selected[0]->id() ) );
}
}

// configure auto completion with SQL functions
QsciAPIs *apis = new QsciAPIs( mQueryEdit->lexer() );

Q_INIT_RESOURCE( sqlfunctionslist );
QFile fFile( QStringLiteral( ":/sqlfunctions/list.txt" ) );
if ( fFile.open( QIODevice::ReadOnly ) )
{
QTextStream in( &fFile );
while ( !in.atEnd() )
{
apis->add( in.readLine().toLower() + "()" );
}
fFile.close();
}

// configure auto completion with table and column names
Q_FOREACH ( QgsMapLayer *l, QgsProject::instance()->mapLayers() )
{
if ( l->type() == QgsMapLayer::VectorLayer )
{
apis->add( l->name() );
QgsVectorLayer *vl = static_cast<QgsVectorLayer *>( l );
Q_FOREACH ( const QgsField &f, vl->fields().toList() )
{
apis->add( f.name() );
}
}
}

apis->prepare();
mQueryEdit->lexer()->setAPIs( apis );
mQueryEdit->setWrapMode( QsciScintilla::WrapWord );

// Update the layer selection list
if ( mEmbeddedSelectionDialog )
{
mEmbeddedSelectionDialog->updateLayersList();
}
}

void QgsVirtualLayerSourceSelect::addEmbeddedLayer( const QString &name, const QString &provider, const QString &encoding, const QString &source )
{
// insert a new row
Expand All @@ -293,7 +327,7 @@ void QgsVirtualLayerSourceSelect::addEmbeddedLayer( const QString &name, const Q

void QgsVirtualLayerSourceSelect::onImportLayer()
{
if ( mEmbeddedSelectionDialog->exec() == QDialog::Accepted )
if ( mEmbeddedSelectionDialog && mEmbeddedSelectionDialog->exec() == QDialog::Accepted )
{
QStringList ids = mEmbeddedSelectionDialog->layers();
Q_FOREACH ( const QString &id, ids )
Expand All @@ -307,6 +341,8 @@ void QgsVirtualLayerSourceSelect::onImportLayer()
void QgsVirtualLayerSourceSelect::on_buttonBox_accepted()
{
QString layerName = QStringLiteral( "virtual_layer" );
QString id;
bool replace = false;
int idx = mLayerNameCombo->currentIndex();
if ( idx != -1 && !mLayerNameCombo->currentText().isEmpty() )
{
Expand All @@ -315,20 +351,31 @@ void QgsVirtualLayerSourceSelect::on_buttonBox_accepted()

QgsVirtualLayerDefinition def = getVirtualLayerDef();


if ( idx != -1 )
{
QString id( mLayerNameCombo->itemData( idx ).toString() );
id = ( mLayerNameCombo->itemData( idx ).toString() );
if ( !id.isEmpty() && mLayerNameCombo->currentText() == QgsProject::instance()->mapLayer( id )->name() )
{
int r = QMessageBox::warning( nullptr, tr( "Warning" ), tr( "A virtual layer of this name already exists, would you like to overwrite it?" ), QMessageBox::Yes | QMessageBox::No );
if ( r == QMessageBox::Yes )
{
emit replaceVectorLayer( id, def.toString(), layerName, QStringLiteral( "virtual" ) );
return;
replace = true;
}
}
}
emit addVectorLayer( def.toString(), layerName, QStringLiteral( "virtual" ) );
if ( replace )
{
emit replaceVectorLayer( id, def.toString(), layerName, QStringLiteral( "virtual" ) );
}
else
{
emit addVectorLayer( def.toString(), layerName, QStringLiteral( "virtual" ) );
}
if ( mWidgetMode == QgsProviderRegistry::WidgetMode::None )
{
accept( );
}
}

QGISEXTERN QgsVirtualLayerSourceSelect *selectWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
Expand Down
4 changes: 3 additions & 1 deletion src/providers/virtual/qgsvirtuallayersourceselect.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ email : hugo dot mercier at oslandia dot com
#include <qgsvirtuallayerdefinition.h>
#include "qgsproviderregistry.h"


class QgsVectorLayer;
class QMainWindow;
class QgsEmbeddedLayerSelectDialog;
class QgsLayerTreeView;

class QgsVirtualLayerSourceSelect : public QDialog, private Ui::QgsVirtualLayerSourceSelectBase
{
Expand All @@ -46,6 +46,7 @@ class QgsVirtualLayerSourceSelect : public QDialog, private Ui::QgsVirtualLayerS
void onRemoveLayer();
void onImportLayer();
void onTableRowChanged( const QModelIndex &current, const QModelIndex &previous );
void updateLayersList();

signals:
//! Source, name, provider
Expand All @@ -60,6 +61,7 @@ class QgsVirtualLayerSourceSelect : public QDialog, private Ui::QgsVirtualLayerS
QgsEmbeddedLayerSelectDialog *mEmbeddedSelectionDialog = nullptr;
QgsProviderRegistry::WidgetMode mWidgetMode = QgsProviderRegistry::WidgetMode::None;
void addEmbeddedLayer( const QString &name, const QString &provider, const QString &encoding, const QString &source );
QgsLayerTreeView *mTreeView = nullptr;
};

#endif
Loading

0 comments on commit 811e4df

Please sign in to comment.