QGIS/src/gui/qgsdatasourcemanagerdialog.cpp
Muhammad Yarjuna Rohmat 5f66f36ff6 [FEATURE] QGIS - GeoNode Integration: Integrate with QGIS Browser Panel (#4816)
* add Geonode connection menu to the toolbar

* add header files for geonode-qgis client

* add action to launch geonode connection dialog from menubar

* Move to proper directory

* Add geonodeconnection class.

* Add unit test for geonode connection.

* Use const static to avoid typo.

* Get list layers from geonode.

* Add get maps method.

* Geonode connection dialog (#13)

* add new geonode connection dialog

* apply functionality to the geonode connection manager dialog

* add save and load geonode connection functionality

* edit baseKey and credentialBaseKey

* remove auto-connect slots

* Add unit test for geonode connection.

* Add wms url getter.

* Add uuid and layer name in the table.

* Add handler for the list layer clicked. WIP.

* Use new style connect, better hacky to get wms url.

* update gitignore

* Make QGIS able to add WMS layer from geonode. With hacky code.

* Fix Docstring.

* Show web service type (WMS/WFS) in layer table.

* fix http and toolbar menu

* add geonode data item to the browser panel as an extention of ows provider

* [WIP] Add WFS.

* Add geonode get service url.

* combobox functionality and test geonode connection

* Add WFS.

* Disable add button if it's a map. Currently we can't do anything for map.

* Add busy cursor when add layer.

* get service uri capabilitites

* add available layers to the geonode browser panel

* remove debugging footprint and replace old style connect

* add actions (new, edit, delete) to geonode browser panel

* fix getLayers by WMS url

* add Geonode connection menu to the toolbar

* Filter out invalid layer / map.

* Fix service url method.

* Add service url for XYZ for GeoNode QGIS Server backend.

* Add XYZ url to geonode connection  dialog.

* Add XYZ layer to QGIS.

* fix double geonode submenu

* add wfs/wms layers from browser panel using its native provider

* comply with qgis3 new class naming

* Handle different prefix for layer in GeoNode QGIS Server backend.

* base class for cms connection

* make geonode connection as a derived class from cms connection

* update cmakelists

* move geonode connection to geocms dir

* update CMakeLists

* Handle geonode 2.7 with new API.

* Handle multiple geoserver url in one geonode.

* Fix add xyz for qgis server. Fix add wms, wfs, xyz for geoserver in geonode 2.7

* Refactor serviceURL to return QStringList.

* add 'add geonode layer' icon

* add geonode to the data source manager dialog

* [GeoNode-Client] Fix add WFS layer.

* fix wms url parameter

* add xyz dataitems

* Use new style connect.

* [GeoNode Client] Handle qgis server specific typename to make add WFS works.

* Code improvement.

* [GeoNode Client] Make geonode dialog in add universal layer can add layer.

* Open universal add layer when click Add GeoNode layer.

* Make sure the geonode url has protocol.

* Handle geonode version in a better way.

* make sure the serviceUrl method has scheme in its urls

* add services option to the dialog

* remove version label if not wfs

* construct wms url with parameters for geonode connection

* handle layer from multi service urls for every wfs, wms, & xyz services

* fix new style connect using static_cast

* hode close button if dialog is in embedded mode

* fix xyz layer naming in the browser tree

* create base class for geocms dataitems

* fix compiling warning

* Use struct instead QVariantMap.

* tidy up code

* Tidy up code, use QgsStringMap instead QVariantMap.

* Add spellok for catalogue.

* update sip

* update sip

* Use naming convention for QgsGeoCmsConnection and use QUuid.

* Async by using GeoNodeRequest class.

* Move geonode to src/gui.

* Use stack not heap.

* Remove unused includes.

* Use signal to handle request.

* Use QStringLiteral.

* Switch to use Q_FOREACH.

* Use Q_FOREACH and addressing PR's review.

* Set private for data members.

* update sip

* Update sip.

* Update sip.

* Fix sip problem to make it buildable again.

* Remove geocms

* Tidy up code.

* Use QgsSetting Scope::Provider.

* Fix missing zip.h
2017-08-06 21:24:12 +02:00

244 lines
11 KiB
C++

/***************************************************************************
qgsdatasourcemanagerdialog.cpp - datasource manager dialog
---------------------
begin : May 19, 2017
copyright : (C) 2017 by Alessandro Pasotti
email : apasotti at itopen dot it
***************************************************************************
* *
* 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 <QMessageBox>
#include <QListWidgetItem>
#include "qgsdatasourcemanagerdialog.h"
#include "ui_qgsdatasourcemanagerdialog.h"
#include "qgsbrowserdockwidget.h"
#include "qgssettings.h"
#include "qgsproviderregistry.h"
#include "qgsabstractdatasourcewidget.h"
#include "qgsmapcanvas.h"
#include "qgsgeonodesourceselect.h"
QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QWidget *parent, QgsMapCanvas *canvas, Qt::WindowFlags fl ) :
QgsOptionsDialogBase( QStringLiteral( "Data Source Manager" ), parent, fl ),
ui( new Ui::QgsDataSourceManagerDialog ),
mPreviousRow( -1 ),
mMapCanvas( canvas )
{
ui->setupUi( this );
ui->verticalLayout_2->setSpacing( 6 );
ui->verticalLayout_2->setMargin( 0 );
ui->verticalLayout_2->setContentsMargins( 0, 0, 0, 0 );
// QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
// switching vertical tabs between icon/text to icon-only modes (splitter collapsed to left),
// and connecting QDialogButtonBox's accepted/rejected signals to dialog's accept/reject slots
initOptionsBase( true );
// Bind list index to the stacked dialogs
connect( ui->mOptionsListWidget, &QListWidget::currentRowChanged, this, &QgsDataSourceManagerDialog::setCurrentPage );
// BROWSER Add the browser widget to the first stacked widget page
mBrowserWidget = new QgsBrowserDockWidget( QStringLiteral( "Browser" ), this );
mBrowserWidget->setFeatures( QDockWidget::NoDockWidgetFeatures );
ui->mOptionsStackedWidget->addWidget( mBrowserWidget );
mPageNames.append( QStringLiteral( "browser" ) );
// Forward all browser signals
connect( mBrowserWidget, &QgsBrowserDockWidget::handleDropUriList, this, &QgsDataSourceManagerDialog::handleDropUriList );
connect( mBrowserWidget, &QgsBrowserDockWidget::openFile, this, &QgsDataSourceManagerDialog::openFile );
connect( mBrowserWidget, &QgsBrowserDockWidget::connectionsChanged, this, &QgsDataSourceManagerDialog::connectionsChanged );
connect( this, &QgsDataSourceManagerDialog::updateProjectHome, mBrowserWidget, &QgsBrowserDockWidget::updateProjectHome );
// Add data provider dialogs
QWidget *dlg = nullptr;
addVectorProviderDialog( QStringLiteral( "ogr" ), tr( "Vector" ), QStringLiteral( "/mActionAddOgrLayer.svg" ) );
addRasterProviderDialog( QStringLiteral( "gdal" ), tr( "Raster" ), QStringLiteral( "/mActionAddRasterLayer.svg" ) );
addVectorProviderDialog( QStringLiteral( "delimitedtext" ), tr( "Delimited Text" ), QStringLiteral( "/mActionAddDelimitedTextLayer.svg" ) );
#ifdef HAVE_POSTGRESQL
addDbProviderDialog( QStringLiteral( "postgres" ), tr( "PostgreSQL" ), QStringLiteral( "/mActionAddPostgisLayer.svg" ) );
#endif
addDbProviderDialog( QStringLiteral( "spatialite" ), tr( "SpatiaLite" ), QStringLiteral( "/mActionAddSpatiaLiteLayer.svg" ) );
addDbProviderDialog( QStringLiteral( "mssql" ), tr( "MSSQL" ), QStringLiteral( "/mActionAddMssqlLayer.svg" ) );
addDbProviderDialog( QStringLiteral( "DB2" ), tr( "DB2" ), QStringLiteral( "/mActionAddDb2Layer.svg" ) );
#ifdef HAVE_ORACLE
addDbProviderDialog( QStringLiteral( "oracle" ), tr( "Oracle" ), QStringLiteral( "/mActionAddOracleLayer.svg" ) );
#endif
dlg = addVectorProviderDialog( QStringLiteral( "virtual" ), tr( "Virtual Layer" ), QStringLiteral( "/mActionAddVirtualLayer.svg" ) );
// Apparently this is the only provider using replaceVectorLayer, we should
// move this in to the base abstract class when it is used by at least one
// additional provider.
if ( dlg )
{
connect( dlg, SIGNAL( replaceVectorLayer( QString, QString, QString, QString ) ), this, SIGNAL( replaceSelectedVectorLayer( QString, QString, QString, QString ) ) );
}
addRasterProviderDialog( QStringLiteral( "wms" ), tr( "WMS" ), QStringLiteral( "/mActionAddWmsLayer.svg" ) );
addRasterProviderDialog( QStringLiteral( "wcs" ), tr( "WCS" ), QStringLiteral( "/mActionAddWcsLayer.svg" ) );
addVectorProviderDialog( QStringLiteral( "WFS" ), tr( "WFS" ), QStringLiteral( "/mActionAddWfsLayer.svg" ) );
addRasterProviderDialog( QStringLiteral( "arcgismapserver" ), tr( "ArcGIS Map Server" ), QStringLiteral( "/mActionAddAmsLayer.svg" ) );
addVectorProviderDialog( QStringLiteral( "arcgisfeatureserver" ), tr( "ArcGIS Feature Server" ), QStringLiteral( "/mActionAddAfsLayer.svg" ) );
QDialog *geonodeDialog = new QgsGeoNodeSourceSelect( this, Qt::Widget, QgsProviderRegistry::WidgetMode::Embedded );
dlg = addDialog( geonodeDialog, QStringLiteral( "geonode" ), tr( "GeoNode" ), QStringLiteral( "/mActionAddGeonodeLayer.svg" ) );
if ( dlg )
{
connect( dlg, SIGNAL( addRasterLayer( QString, QString, QString ) ), this, SLOT( rasterLayerAdded( QString, QString, QString ) ) );
connect( dlg, SIGNAL( addWfsLayer( QString, QString, QString ) ), this, SLOT( vectorLayerAdded( QString, QString, QString ) ) );
}
}
QgsDataSourceManagerDialog::~QgsDataSourceManagerDialog()
{
delete ui;
}
void QgsDataSourceManagerDialog::openPage( QString pageName )
{
int pageIdx = mPageNames.indexOf( pageName );
if ( pageIdx != -1 )
{
QTimer::singleShot( 0, this, [ = ] { setCurrentPage( pageIdx ); } );
}
}
void QgsDataSourceManagerDialog::setCurrentPage( int index )
{
mPreviousRow = ui->mOptionsStackedWidget->currentIndex();
ui->mOptionsStackedWidget->setCurrentIndex( index );
setWindowTitle( tr( "Data Source Manager | %1" ).arg( ui->mOptionsListWidget->currentItem()->text() ) );
}
void QgsDataSourceManagerDialog::setPreviousPage()
{
int prevPage = mPreviousRow != -1 ? mPreviousRow : 0;
setCurrentPage( prevPage );
}
void QgsDataSourceManagerDialog::refresh()
{
mBrowserWidget->refresh();
emit providerDialogsRefreshRequested();
}
void QgsDataSourceManagerDialog::rasterLayerAdded( const QString &uri, const QString &baseName, const QString &providerKey )
{
emit addRasterLayer( uri, baseName, providerKey );
}
void QgsDataSourceManagerDialog::vectorLayerAdded( const QString &vectorLayerPath, const QString &baseName, const QString &providerKey )
{
emit addVectorLayer( vectorLayerPath, baseName, providerKey );
}
void QgsDataSourceManagerDialog::vectorLayersAdded( const QStringList &layerQStringList, const QString &enc, const QString &dataSourceType )
{
emit addVectorLayers( layerQStringList, enc, dataSourceType );
}
QDialog *QgsDataSourceManagerDialog::addDialog( QDialog *dialog, QString const key, QString const name, QString const icon, QString title )
{
mPageNames.append( key );
ui->mOptionsStackedWidget->addWidget( dialog );
QListWidgetItem *layerItem = new QListWidgetItem( name, ui->mOptionsListWidget );
layerItem->setToolTip( title.isEmpty() ? tr( "Add %1 layer" ).arg( name ) : title );
layerItem->setIcon( QgsApplication::getThemeIcon( icon ) );
return dialog;
}
QgsAbstractDataSourceWidget *QgsDataSourceManagerDialog::providerDialog( const QString providerKey, const QString providerName, const QString icon, QString title )
{
QgsAbstractDataSourceWidget *dlg = dynamic_cast<QgsAbstractDataSourceWidget *>( QgsProviderRegistry::instance()->createSelectionWidget( providerKey, this, Qt::Widget, QgsProviderRegistry::WidgetMode::Embedded ) );
if ( !dlg )
{
QMessageBox::warning( this, providerName, tr( "Cannot get %1 select dialog from provider %2." ).arg( providerName, providerKey ) );
return nullptr;
}
else
{
mPageNames.append( providerKey );
ui->mOptionsStackedWidget->addWidget( dlg );
QListWidgetItem *layerItem = new QListWidgetItem( providerName, ui->mOptionsListWidget );
layerItem->setToolTip( title.isEmpty() ? tr( "Add %1 layer" ).arg( providerName ) : title );
layerItem->setIcon( QgsApplication::getThemeIcon( icon ) );
// Set crs and extent from canvas
if ( mMapCanvas )
{
dlg->setMapCanvas( mMapCanvas );
}
connect( dlg, &QgsAbstractDataSourceWidget::rejected, this, &QgsDataSourceManagerDialog::reject );
connect( dlg, &QgsAbstractDataSourceWidget::accepted, this, &QgsDataSourceManagerDialog::accept );
return dlg;
}
}
QgsAbstractDataSourceWidget *QgsDataSourceManagerDialog::addDbProviderDialog( const QString providerKey, const QString providerName, const QString icon, QString title )
{
QgsAbstractDataSourceWidget *dlg = providerDialog( providerKey, providerName, icon, title );
if ( dlg )
{
connect( dlg, SIGNAL( addDatabaseLayers( QStringList const &, QString const & ) ),
this, SIGNAL( addDatabaseLayers( QStringList const &, QString const & ) ) );
connect( dlg, SIGNAL( progress( int, int ) ),
this, SIGNAL( showProgress( int, int ) ) );
connect( dlg, SIGNAL( progressMessage( QString ) ),
this, SIGNAL( showStatusMessage( QString ) ) );
connect( dlg, SIGNAL( connectionsChanged() ), this, SIGNAL( connectionsChanged() ) );
connect( this, SIGNAL( providerDialogsRefreshRequested() ), dlg, SLOT( refresh() ) );
}
return dlg;
}
QgsAbstractDataSourceWidget *QgsDataSourceManagerDialog::addRasterProviderDialog( const QString providerKey, const QString providerName, const QString icon, QString title )
{
QgsAbstractDataSourceWidget *dlg = providerDialog( providerKey, providerName, icon, title );
if ( dlg )
{
connect( dlg, SIGNAL( addRasterLayer( QString const &, QString const &, QString const & ) ),
this, SIGNAL( addRasterLayer( QString const &, QString const &, QString const & ) ) );
connect( dlg, SIGNAL( connectionsChanged() ), this, SIGNAL( connectionsChanged() ) );
connect( this, SIGNAL( providerDialogsRefreshRequested() ), dlg, SLOT( refresh() ) );
}
return dlg;
}
QgsAbstractDataSourceWidget *QgsDataSourceManagerDialog::addVectorProviderDialog( const QString providerKey, const QString providerName, const QString icon, QString title )
{
QgsAbstractDataSourceWidget *dlg = providerDialog( providerKey, providerName, icon, title );
if ( dlg )
{
connect( dlg, &QgsAbstractDataSourceWidget::addVectorLayer, this, [ = ]( const QString & vectorLayerPath, const QString & baseName )
{ this->vectorLayerAdded( vectorLayerPath, baseName, providerKey ); } );
connect( dlg, &QgsAbstractDataSourceWidget::addVectorLayers, this, &QgsDataSourceManagerDialog::vectorLayersAdded );
connect( this, SIGNAL( providerDialogsRefreshRequested() ), dlg, SLOT( refresh() ) );
}
return dlg;
}
void QgsDataSourceManagerDialog::showEvent( QShowEvent *e )
{
ui->mOptionsStackedWidget->currentWidget()->show();
QDialog::showEvent( e );
}