Skip to content
Permalink
Browse files

[addlayerbutton] Virtual Layers support added

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 811e4dfd475dcb1d31f9207efa4fe24ee31c03da
@@ -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();
}

@@ -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()
@@ -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 );
@@ -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 )
@@ -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;
}
@@ -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
@@ -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>
@@ -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() )
@@ -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 )
@@ -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() )
@@ -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
@@ -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 )
@@ -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() )
{
@@ -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 )
@@ -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
{
@@ -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
@@ -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

0 comments on commit 811e4df

Please sign in to comment.
You can’t perform that action at this time.