diff --git a/.gitignore b/.gitignore
index d31f8283e40..ff8aec0d3bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,7 +23,7 @@
/CMakeLists.txt.user
/CMakeLists.txt.user.*
api_doc
-build*
+*build*
debian/*.debhelper
debian/*.substvars
desktop.ini
diff --git a/images/images.qrc b/images/images.qrc
index f8baa88fd4a..52e09ddc6b1 100644
--- a/images/images.qrc
+++ b/images/images.qrc
@@ -135,6 +135,7 @@
themes/default/mActionAddWcsLayer.svg
themes/default/mActionAddWfsLayer.svg
themes/default/mActionAddWmsLayer.svg
+ themes/default/mActionAddGeonodeLayer.svg
themes/default/mActionAddDelimitedTextLayer.svg
themes/default/mActionAddVirtualLayer.svg
themes/default/mActionAlignBottom.svg
@@ -356,6 +357,7 @@
themes/default/mIconFieldInteger.svg
themes/default/mIconFieldText.svg
themes/default/mIconFieldTime.svg
+ themes/default/mIconGeonode.svg
themes/default/mIconInfo.svg
themes/default/mIconImport.gif
themes/default/mIconLabelQuadrantCenter.svg
diff --git a/images/themes/default/mActionAddGeonodeLayer.svg b/images/themes/default/mActionAddGeonodeLayer.svg
new file mode 100644
index 00000000000..1b42b6c6115
--- /dev/null
+++ b/images/themes/default/mActionAddGeonodeLayer.svg
@@ -0,0 +1,407 @@
+
+
+
diff --git a/images/themes/default/mIconGeonode.svg b/images/themes/default/mIconGeonode.svg
new file mode 100644
index 00000000000..e2c81d7654d
--- /dev/null
+++ b/images/themes/default/mIconGeonode.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 6109cafd823..a3e4c169e86 100755
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -112,6 +112,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/fieldformatter
${CMAKE_SOURCE_DIR}/src/core/dxf
${CMAKE_SOURCE_DIR}/src/core/geometry
+ ${CMAKE_SOURCE_DIR}/src/core/geonode
${CMAKE_SOURCE_DIR}/src/core/gps
${CMAKE_SOURCE_DIR}/src/core/layertree
${CMAKE_SOURCE_DIR}/src/core/layout
@@ -141,6 +142,7 @@ IF (WITH_GUI)
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets/core
${CMAKE_SOURCE_DIR}/src/gui/effects
+ ${CMAKE_SOURCE_DIR}/src/gui/geonode
${CMAKE_SOURCE_DIR}/src/gui/layertree
${CMAKE_SOURCE_DIR}/src/gui/layout
${CMAKE_SOURCE_DIR}/src/gui/locator
diff --git a/python/core/core_auto.sip b/python/core/core_auto.sip
index e91b847b576..4ad20561b89 100644
--- a/python/core/core_auto.sip
+++ b/python/core/core_auto.sip
@@ -280,6 +280,8 @@
%Include fieldformatter/qgsrelationreferencefieldformatter.sip
%Include fieldformatter/qgsvaluemapfieldformatter.sip
%Include fieldformatter/qgsvaluerelationfieldformatter.sip
+%Include geonode/qgsgeonodeconnection.sip
+%Include geonode/qgsgeonoderequest.sip
%Include gps/qgsqtlocationconnection.sip
%Include gps/qgsgpsconnectionregistry.sip
%Include qgsapplication.sip
diff --git a/python/core/geonode/qgsdataitemprovider.sip b/python/core/geonode/qgsdataitemprovider.sip
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/python/core/geonode/qgsgeonodeconnection.sip b/python/core/geonode/qgsgeonodeconnection.sip
new file mode 100644
index 00000000000..62010a85c85
--- /dev/null
+++ b/python/core/geonode/qgsgeonodeconnection.sip
@@ -0,0 +1,86 @@
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/core/geonode/qgsgeonodeconnection.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
+
+
+
+
+class QgsGeoNodeConnection : QObject
+{
+%Docstring
+!
+ GeoNode Connections management
+%End
+
+%TypeHeaderCode
+#include "qgsgeonodeconnection.h"
+%End
+ public:
+ explicit QgsGeoNodeConnection( const QString &connName );
+%Docstring
+Constructor
+%End
+
+ ~QgsGeoNodeConnection();
+%Docstring
+Destructor
+%End
+
+ QString connName() const;
+%Docstring
+ :rtype: str
+%End
+ void setConnName( const QString &connName );
+
+ QgsDataSourceUri uri();
+%Docstring
+ :rtype: QgsDataSourceUri
+%End
+ void setUri( const QgsDataSourceUri &uri );
+
+ static QStringList connectionList();
+%Docstring
+Retrieve all geonode connection
+ :rtype: list of str
+%End
+
+ static void deleteConnection( const QString &name );
+%Docstring
+Delete connection with name, name
+%End
+
+ static QString selectedConnection();
+%Docstring
+Get selected connection
+ :rtype: str
+%End
+
+ static void setSelectedConnection( const QString &name );
+%Docstring
+Set selected connection
+%End
+
+ static QString pathGeoNodeConnection();
+%Docstring
+ :rtype: str
+%End
+
+ static QString pathGeoNodeConnectionDetails();
+%Docstring
+ :rtype: str
+%End
+
+};
+
+
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/core/geonode/qgsgeonodeconnection.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
diff --git a/python/core/geonode/qgsgeonoderequest.sip b/python/core/geonode/qgsgeonoderequest.sip
new file mode 100644
index 00000000000..21cf76b008a
--- /dev/null
+++ b/python/core/geonode/qgsgeonoderequest.sip
@@ -0,0 +1,121 @@
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/core/geonode/qgsgeonoderequest.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
+
+
+
+
+struct QgsServiceLayerDetail
+{
+%TypeHeaderCode
+#include
+%End
+ QUuid uuid;
+ QString name;
+ QString typeName;
+ QString title;
+ QString wmsURL;
+ QString wfsURL;
+ QString xyzURL;
+};
+
+class QgsGeoNodeRequest : QObject
+{
+
+%TypeHeaderCode
+#include "qgsgeonoderequest.h"
+%End
+ public:
+ explicit QgsGeoNodeRequest( bool forceRefresh, QObject *parent = 0 );
+ QgsGeoNodeRequest( const QString &baseUrl, /*const QgsWmsAuthorization &auth,*/ bool forceRefresh, QObject *parent = 0 );
+ virtual ~QgsGeoNodeRequest();
+
+ bool request( QString endPoint );
+%Docstring
+ :rtype: bool
+%End
+
+ bool getLayers();
+%Docstring
+ :rtype: bool
+%End
+
+ QList parseLayers( QByteArray layerResponse );
+%Docstring
+ :rtype: list of QgsServiceLayerDetail
+%End
+
+ QStringList serviceUrls( QString serviceType );
+%Docstring
+ :rtype: list of str
+%End
+
+ QgsStringMap serviceUrlData( QString serviceType );
+%Docstring
+ :rtype: QgsStringMap
+%End
+
+ QString lastError() const;
+%Docstring
+ :rtype: str
+%End
+
+ QByteArray response() const;
+%Docstring
+ :rtype: QByteArray
+%End
+
+ QNetworkReply *reply() const;
+%Docstring
+ :rtype: QNetworkReply
+%End
+
+ void abort();
+%Docstring
+Abort network request immediately
+%End
+
+ QString getProtocol() const;
+%Docstring
+ :rtype: str
+%End
+ void setProtocol( const QString &protocol );
+
+ signals:
+ void statusChanged( const QString &statusQString );
+%Docstring
+ emit a signal to be caught by qgisapp and display a statusQString on status bar
+%End
+
+ void requestFinished();
+%Docstring
+ emit a signal once the request is finished
+%End
+
+ protected slots:
+ void replyFinished();
+ void replyProgress( qint64, qint64 );
+
+ protected:
+
+
+
+
+
+
+
+
+
+};
+
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/core/geonode/qgsgeonoderequest.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
diff --git a/python/core/qgsdataitemprovider.sip b/python/core/qgsdataitemprovider.sip
index f62452c2ffe..69aa1157ce2 100644
--- a/python/core/qgsdataitemprovider.sip
+++ b/python/core/qgsdataitemprovider.sip
@@ -49,6 +49,11 @@ Caller takes responsibility of deleting created items.
:rtype: QgsDataItem
%End
+ virtual QVector createDataItems( const QString &path, QgsDataItem *parentItem );
+%Docstring
+Caller takes responsibility of deleting created items.
+ :rtype: list of QgsDataItem
+%End
};
/************************************************************************
diff --git a/python/gui/geonode/qgsgeonodenewconnection.sip b/python/gui/geonode/qgsgeonodenewconnection.sip
new file mode 100644
index 00000000000..2f8ba33ebdf
--- /dev/null
+++ b/python/gui/geonode/qgsgeonodenewconnection.sip
@@ -0,0 +1,51 @@
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/gui/geonode/qgsgeonodenewconnection.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
+
+
+
+
+class QgsGeoNodeNewConnection : QDialog
+{
+%Docstring
+*************************************************************************
+ *
+ 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. *
+ *
+**************************************************************************
+%End
+
+%TypeHeaderCode
+#include "qgsgeonodenewconnection.h"
+%End
+ public:
+ QgsGeoNodeNewConnection( QWidget *parent = 0, const QString &connName = QString::null, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
+%Docstring
+Constructor
+%End
+
+ public slots:
+ virtual void accept();
+
+ void okButtonBehavior( const QString & );
+ void testConnection();
+%Docstring
+Test the connection using the parameters supplied
+%End
+
+};
+
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/gui/geonode/qgsgeonodenewconnection.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
diff --git a/python/gui/geonode/qgsgeonodesourceselect.sip b/python/gui/geonode/qgsgeonodesourceselect.sip
new file mode 100644
index 00000000000..dc27ff92c51
--- /dev/null
+++ b/python/gui/geonode/qgsgeonodesourceselect.sip
@@ -0,0 +1,64 @@
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/gui/geonode/qgsgeonodesourceselect.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
+
+
+
+
+class QgsGeonodeItemDelegate : QItemDelegate
+{
+%Docstring
+*************************************************************************
+ *
+ 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. *
+ *
+**************************************************************************
+%End
+
+%TypeHeaderCode
+#include "qgsgeonodesourceselect.h"
+%End
+ public:
+ explicit QgsGeonodeItemDelegate( QObject *parent = 0 );
+};
+
+class QgsGeoNodeSourceSelect: QDialog
+{
+
+%TypeHeaderCode
+#include "qgsgeonodesourceselect.h"
+%End
+ public:
+
+ QgsGeoNodeSourceSelect( QWidget *parent, Qt::WindowFlags fl, bool embeddedMode = false );
+ ~QgsGeoNodeSourceSelect();
+
+ signals:
+ void connectionsChanged();
+ void addRasterLayer( const QString &rasterLayerPath,
+ const QString &baseName,
+ const QString &providerKey );
+ void addRasterLayer();
+
+ void addWfsLayer(
+ const QString &uri,
+ const QString &layerName,
+ const QString &providerKey );
+
+};
+
+
+/************************************************************************
+ * This file has been generated automatically from *
+ * *
+ * src/gui/geonode/qgsgeonodesourceselect.h *
+ * *
+ * Do not edit manually ! Edit header and run scripts/sipify.pl again *
+ ************************************************************************/
diff --git a/python/gui/gui_auto.sip b/python/gui/gui_auto.sip
index 071eb2153b1..4254fec5449 100644
--- a/python/gui/gui_auto.sip
+++ b/python/gui/gui_auto.sip
@@ -40,6 +40,8 @@
%Include auth/qgsauthtrustedcasdialog.sip
%Include editorwidgets/core/qgseditorwidgetfactory.sip
%Include editorwidgets/core/qgseditorwidgetautoconf.sip
+%Include geonode/qgsgeonodenewconnection.sip
+%Include geonode/qgsgeonodesourceselect.sip
%Include layertree/qgslayertreeembeddedconfigwidget.sip
%Include layertree/qgslayertreeembeddedwidgetregistry.sip
%Include layout/qgslayoutviewmouseevent.sip
diff --git a/python/gui/qgsmanageconnectionsdialog.sip b/python/gui/qgsmanageconnectionsdialog.sip
index 6b0c695f367..0c7114c31e3 100644
--- a/python/gui/qgsmanageconnectionsdialog.sip
+++ b/python/gui/qgsmanageconnectionsdialog.sip
@@ -31,6 +31,7 @@ class QgsManageConnectionsDialog : QDialog
DB2,
WCS,
Oracle,
+ GeoNode
};
QgsManageConnectionsDialog( QWidget *parent /TransferThis/ = 0, Mode mode = Export, Type type = WMS, const QString &fileName = "" );
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 7f7838624c7..3b969ab8763 100755
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -510,6 +510,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/gui/symbology
${CMAKE_SOURCE_DIR}/src/gui/attributetable
${CMAKE_SOURCE_DIR}/src/gui/auth
+ ${CMAKE_SOURCE_DIR}/src/gui/geonode
${CMAKE_SOURCE_DIR}/src/gui/ogr
${CMAKE_SOURCE_DIR}/src/gui/raster
${CMAKE_SOURCE_DIR}/src/gui/editorwidgets
@@ -556,6 +557,7 @@ INCLUDE_DIRECTORIES(
../gui/symbology
../gui/attributetable
../gui/auth
+ ../gui/geonode
../gui/ogr
../gui/raster
../gui/editorwidgets
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index 8ff143c7e2f..7a68b8148c8 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -294,6 +294,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsuserprofile.h"
#include "qgssublayersdialog.h"
+#include "geonode/qgsgeonodesourceselect.h"
#include "ogr/qgsvectorlayersaveasdialog.h"
#include "qgsosmdownloaddialog.h"
@@ -811,9 +812,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
endProfile();
+ functionProfile( &QgisApp::createMenus, this, QStringLiteral( "Create menus" ) );
functionProfile( &QgisApp::createActions, this, QStringLiteral( "Create actions" ) );
functionProfile( &QgisApp::createActionGroups, this, QStringLiteral( "Create action group" ) );
- functionProfile( &QgisApp::createMenus, this, QStringLiteral( "Create menus" ) );
functionProfile( &QgisApp::createToolBars, this, QStringLiteral( "Toolbars" ) );
functionProfile( &QgisApp::createStatusBar, this, QStringLiteral( "Status bar" ) );
functionProfile( &QgisApp::createCanvasTools, this, QStringLiteral( "Create canvas tools" ) );
@@ -1049,6 +1050,11 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
mActionInstallFromZip = nullptr;
}
+ // add geonode menu under web menu
+ addPluginToWebMenu( mGeonodeMenu->title(), mActionAddGeonodeLayer );
+ mActionAddGeonodeLayer = new QAction( tr( "Add GeoNode Layers..." ), this );
+ mGeonodeMenu->addAction( mActionAddGeonodeLayer );
+
// Set icon size of toolbars
if ( settings.contains( QStringLiteral( "IconSize" ) ) )
{
@@ -1904,6 +1910,8 @@ void QgisApp::createActions()
connect( mActionLabeling, &QAction::triggered, this, &QgisApp::labeling );
connect( mActionStatisticalSummary, &QAction::triggered, this, &QgisApp::showStatisticsDockWidget );
+ // Web Menu Items
+
// Layer Menu Items
connect( mActionDataSourceManager, &QAction::triggered, this, [ = ]() { dataSourceManager(); } );
@@ -1929,6 +1937,7 @@ void QgisApp::createActions()
connect( mActionAddAmsLayer, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "arcgismapserver" ) ); } );
connect( mActionAddDelimitedText, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "delimitedtext" ) ); } );
connect( mActionAddVirtualLayer, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "virtual" ) ); } );
+ connect( mActionAddGeonodeLayer, &QAction::triggered, this, [ = ] { dataSourceManager( QStringLiteral( "geonode" ) ); } );
connect( mActionOpenTable, &QAction::triggered, this, &QgisApp::attributeTable );
connect( mActionOpenFieldCalc, &QAction::triggered, this, &QgisApp::fieldCalculator );
connect( mActionToggleEditing, &QAction::triggered, this, [ = ] { toggleEditing(); } );
@@ -2204,6 +2213,12 @@ void QgisApp::createMenus()
mToolbarMenu = new QMenu( tr( "Toolbars" ), this );
mToolbarMenu->setObjectName( QStringLiteral( "mToolbarMenu" ) );
+ // Geonode Submenu
+ mGeonodeMenu = new QMenu( tr( "GeoNode" ), this );
+ mGeonodeMenu->setObjectName( QStringLiteral( "mGeonodeMenu" ) );
+ // Geonode Action
+ mActionAddGeonodeLayer = new QAction( tr( "Add GeoNode Layers..." ), this );
+
// Get platform for menu layout customization (Gnome, Kde, Mac, Win)
QDialogButtonBox::ButtonLayout layout =
QDialogButtonBox::ButtonLayout( style()->styleHint( QStyle::SH_DialogButtonLayout, nullptr, this ) );
@@ -4556,6 +4571,20 @@ void QgisApp::askUserForOGRSublayers( QgsVectorLayer *layer )
}
}
+void QgisApp::addGeonodeLayer()
+{
+ QgsGeoNodeSourceSelect *geonodes = new QgsGeoNodeSourceSelect( this, 0, true );
+ if ( !geonodes )
+ {
+ QMessageBox::warning( this, tr( "Geonode" ), tr( "Cannot get Geonode select dialog." ) );
+ return;
+ }
+ connect( geonodes, static_cast( &QgsGeoNodeSourceSelect::addRasterLayer ), this, static_cast( &QgisApp::addRasterLayer ) );
+ connect( geonodes, &QgsGeoNodeSourceSelect::addWfsLayer, this, &QgisApp::addVectorLayer );
+ geonodes->exec();
+ delete geonodes;
+}
+
void QgisApp::addDatabaseLayer()
{
#ifdef HAVE_POSTGRESQL
diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h
index 38f7138114e..b4c7f91f241 100644
--- a/src/app/qgisapp.h
+++ b/src/app/qgisapp.h
@@ -437,6 +437,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QAction *actionShowBookmarks() { return mActionShowBookmarks; }
QAction *actionDraw() { return mActionDraw; }
+ QAction *actionAddGeonodeLayer() { return mActionAddGeonodeLayer; }
+
QAction *actionDataSourceManager() { return mActionDataSourceManager; }
QAction *actionNewVectorLayer() { return mActionNewVectorLayer; }
QAction *actionNewSpatialLiteLayer() { return mActionNewSpatiaLiteLayer; }
@@ -885,6 +887,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void sponsors();
//! About QGIS
void about();
+ //! Add a Geonode layer to the map
+ void addGeonodeLayer();
//#ifdef HAVE_POSTGRESQL
//! Add a databaselayer to the map
void addDatabaseLayer();
@@ -1731,6 +1735,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QAction *mActionPluginSeparator1 = nullptr;
QAction *mActionPluginSeparator2 = nullptr;
QAction *mActionRasterSeparator = nullptr;
+ QAction *mActionAddGeonodeLayer = nullptr;
// action groups ----------------------------------
QActionGroup *mMapToolGroup = nullptr;
@@ -1743,6 +1748,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
#endif
QMenu *mPanelMenu = nullptr;
QMenu *mToolbarMenu = nullptr;
+ QMenu *mGeonodeMenu = nullptr;
// docks ------------------------------------------
QgsDockWidget *mLayerTreeDock = nullptr;
diff --git a/src/app/qgisappinterface.cpp b/src/app/qgisappinterface.cpp
index 8582c468fe2..e510148348f 100644
--- a/src/app/qgisappinterface.cpp
+++ b/src/app/qgisappinterface.cpp
@@ -648,6 +648,10 @@ QAction *QgisAppInterface::actionNewBookmark() { return qgis->actionNewBookmark(
QAction *QgisAppInterface::actionShowBookmarks() { return qgis->actionShowBookmarks(); }
QAction *QgisAppInterface::actionDraw() { return qgis->actionDraw(); }
+//! Web menu actions
+QAction *QgisAppInterface::actionAddGeonodeLayer() { return qgis->actionAddGeonodeLayer(); }
+
+//! Layer menu actions
QAction *QgisAppInterface::actionNewVectorLayer() { return qgis->actionNewVectorLayer(); }
QAction *QgisAppInterface::actionAddOgrLayer() { return qgis->actionAddOgrLayer(); }
QAction *QgisAppInterface::actionAddRasterLayer() { return qgis->actionAddRasterLayer(); }
diff --git a/src/app/qgisappinterface.h b/src/app/qgisappinterface.h
index d659533d50c..0db1f28937a 100644
--- a/src/app/qgisappinterface.h
+++ b/src/app/qgisappinterface.h
@@ -396,6 +396,9 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
virtual QAction *actionShowBookmarks() override;
virtual QAction *actionDraw() override;
+ //! Web menu actions
+ virtual QAction *actionAddGeonodeLayer();
+
//! Layer menu actions
virtual QAction *actionNewVectorLayer() override;
virtual QAction *actionAddOgrLayer() override;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7f8db89fdce..2159a442ce7 100755
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -450,7 +450,6 @@ SET(QGIS_CORE_SRCS
geometry/qgswkbptr.cpp
geometry/qgswkbtypes.cpp
-
fieldformatter/qgsdatetimefieldformatter.cpp
fieldformatter/qgsfallbackfieldformatter.cpp
fieldformatter/qgskeyvaluefieldformatter.cpp
@@ -459,6 +458,9 @@ SET(QGIS_CORE_SRCS
fieldformatter/qgsvaluemapfieldformatter.cpp
fieldformatter/qgsvaluerelationfieldformatter.cpp
+ geonode/qgsgeonodeconnection.cpp
+ geonode/qgsgeonoderequest.cpp
+
${CMAKE_CURRENT_BINARY_DIR}/qgscontexthelp_texts.cpp
${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp
@@ -701,7 +703,11 @@ SET(QGIS_CORE_MOC_HDRS
layertree/qgslayertreemodellegendnode.h
layertree/qgslayertreenode.h
layertree/qgslayertreeregistrybridge.h
+
qgsuserprofilemanager.h
+
+ geonode/qgsgeonodeconnection.h
+ geonode/qgsgeonoderequest.h
)
IF (NOT WITH_QTWEBKIT)
@@ -1075,6 +1081,9 @@ SET(QGIS_CORE_HDRS
fieldformatter/qgsvaluemapfieldformatter.h
fieldformatter/qgsvaluerelationfieldformatter.h
+ geonode/qgsgeonodeconnection.h
+ geonode/qgsgeonoderequest.h
+
metadata/qgslayermetadata.h
metadata/qgslayermetadatavalidator.h
)
@@ -1089,6 +1098,7 @@ ENDIF (QT_MOBILITY_LOCATION_FOUND OR Qt5Positioning_FOUND)
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
+ ${LIBZIP_INCLUDE_DIR}
annotations
auth
composer
@@ -1097,6 +1107,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/expression
fieldformatter
geometry
+ geonode
layertree
layout
metadata
diff --git a/src/core/geonode/qgsgeonodeconnection.cpp b/src/core/geonode/qgsgeonodeconnection.cpp
new file mode 100644
index 00000000000..f92decde9a2
--- /dev/null
+++ b/src/core/geonode/qgsgeonodeconnection.cpp
@@ -0,0 +1,117 @@
+/***************************************************************************
+ qgsgeonodeconnection.cpp
+ ---------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************
+ * *
+ * 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 "qgssettings.h"
+#include "qgsgeonodeconnection.h"
+#include "qgslogger.h"
+#include "qgsdatasourceuri.h"
+
+const QString QgsGeoNodeConnection::mPathGeoNodeConnection = "qgis/connections-geonode";
+const QString QgsGeoNodeConnection::mPathGeoNodeConnectionDetails = "qgis/GeoNode";
+
+QgsGeoNodeConnection::QgsGeoNodeConnection( const QString &connName )
+ : mConnName( connName )
+{
+ QgsSettings settings;
+
+
+// settings.Section
+ QString key = "qgis/connections-geonode/" + mConnName;
+ QString credentialsKey = "qgis/geonode/" + mConnName;
+
+ QStringList connStringParts;
+
+ mUri.setParam( QStringLiteral( "url" ), settings.value( key + "/url", "", QgsSettings::Providers ).toString() );
+
+ // Check for credentials and prepend to the connection info
+ QString username = settings.value( credentialsKey + "/username", "", QgsSettings::Providers ).toString();
+ QString password = settings.value( credentialsKey + "/password", "", QgsSettings::Providers ).toString();
+ if ( !username.isEmpty() )
+ {
+ mUri.setParam( QStringLiteral( "username" ), username );
+ mUri.setParam( QStringLiteral( "password" ), password );
+ }
+
+ QString authcfg = settings.value( credentialsKey + "/authcfg", "", QgsSettings::Providers ).toString();
+ if ( !authcfg.isEmpty() )
+ {
+ mUri.setParam( QStringLiteral( "authcfg" ), authcfg );
+ }
+
+ QgsDebugMsg( QString( "encodedUri: '%1'." ).arg( QString( mUri.encodedUri() ) ) );
+}
+
+QgsGeoNodeConnection::~QgsGeoNodeConnection()
+{
+
+}
+
+QgsDataSourceUri QgsGeoNodeConnection::uri()
+{
+ return mUri;
+}
+
+QStringList QgsGeoNodeConnection::connectionList()
+{
+ QgsSettings settings;
+ // Add Section manually
+ settings.beginGroup( "providers/qgis/connections-geonode" );
+ return settings.childGroups();
+}
+
+void QgsGeoNodeConnection::deleteConnection( const QString &name )
+{
+ QgsSettings settings;
+ // Add Section manually
+ settings.remove( "providers/qgis/connections-geonode/" + name );
+ settings.remove( "providers/qgis/geonode/" + name );
+}
+
+QString QgsGeoNodeConnection::selectedConnection()
+{
+ QgsSettings settings;
+ return settings.value( "qgis/connections-geonode/selected", "", QgsSettings::Providers ).toString();
+}
+
+void QgsGeoNodeConnection::setSelectedConnection( const QString &name )
+{
+ QgsSettings settings;
+ settings.setValue( "qgis/connections-geonode/selected", name, QgsSettings::Providers );
+}
+
+QString QgsGeoNodeConnection::pathGeoNodeConnection()
+{
+ return mPathGeoNodeConnection;
+}
+
+QString QgsGeoNodeConnection::pathGeoNodeConnectionDetails()
+{
+ return mPathGeoNodeConnectionDetails;
+}
+
+QString QgsGeoNodeConnection::connName() const
+{
+ return mConnName;
+}
+
+void QgsGeoNodeConnection::setConnName( const QString &connName )
+{
+ mConnName = connName;
+}
+
+void QgsGeoNodeConnection::setUri( const QgsDataSourceUri &uri )
+{
+ mUri = uri;
+}
diff --git a/src/core/geonode/qgsgeonodeconnection.h b/src/core/geonode/qgsgeonodeconnection.h
new file mode 100644
index 00000000000..67f05478a2c
--- /dev/null
+++ b/src/core/geonode/qgsgeonodeconnection.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ qgsgeonodeconnection.h
+ ---------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSGEONODECONNECTION_H
+#define QGSGEONODECONNECTION_H
+
+#include "qgis_core.h"
+#include "qgsdatasourceuri.h"
+
+
+/*!
+ * \brief GeoNode Connections management
+ */
+class CORE_EXPORT QgsGeoNodeConnection : public QObject
+{
+ Q_OBJECT
+
+ public:
+ //! Constructor
+ explicit QgsGeoNodeConnection( const QString &connName );
+
+ //! Destructor
+ ~QgsGeoNodeConnection();
+
+ QString connName() const;
+ void setConnName( const QString &connName );
+
+ QgsDataSourceUri uri();
+ void setUri( const QgsDataSourceUri &uri );
+
+ //! Retrieve all geonode connection
+ static QStringList connectionList();
+
+ //! Delete connection with name, name
+ static void deleteConnection( const QString &name );
+
+ //! Get selected connection
+ static QString selectedConnection();
+
+ //! Set selected connection
+ static void setSelectedConnection( const QString &name );
+
+ static QString pathGeoNodeConnection();
+
+ static QString pathGeoNodeConnectionDetails();
+
+ private:
+ // Path in QSetting
+ static const QString mPathGeoNodeConnection;
+ static const QString mPathGeoNodeConnectionDetails;
+
+ //! The connection name
+ QString mConnName;
+
+ //! Property of mUri
+ QgsDataSourceUri mUri;
+};
+
+
+#endif //QGSGEONODECONNECTION_H
diff --git a/src/core/geonode/qgsgeonoderequest.cpp b/src/core/geonode/qgsgeonoderequest.cpp
new file mode 100644
index 00000000000..2ecc8327810
--- /dev/null
+++ b/src/core/geonode/qgsgeonoderequest.cpp
@@ -0,0 +1,420 @@
+/***************************************************************************
+ qgsgeonoderequest.h
+ ---------------------
+ begin : Jul 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************
+ * *
+ * 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 "qgsnetworkaccessmanager.h"
+#include "qgssettings.h"
+#include "qgsmessagelog.h"
+#include "qgslogger.h"
+#include "qgsgeonoderequest.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+QgsGeoNodeRequest::QgsGeoNodeRequest( bool forceRefresh, QObject *parent )
+ : QObject( parent )
+ , mForceRefresh( forceRefresh )
+{
+
+}
+
+QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, /*const QgsWmsAuthorization &auth,*/ bool forceRefresh, QObject *parent )
+ : QObject( parent )
+ , mBaseUrl( baseUrl )
+ , mGeoNodeReply( nullptr )
+ , mIsAborted( false )
+ , mForceRefresh( forceRefresh )
+{
+
+}
+
+QgsGeoNodeRequest::~QgsGeoNodeRequest()
+{
+ abort();
+}
+
+void QgsGeoNodeRequest::abort()
+{
+ mIsAborted = true;
+ if ( mGeoNodeReply )
+ {
+ mGeoNodeReply->deleteLater();
+ mGeoNodeReply = nullptr;
+ }
+}
+
+bool QgsGeoNodeRequest::getLayers()
+{
+ return request( QStringLiteral( "/api/layers/" ) );
+}
+
+void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
+{
+ QString msg = tr( "%1 of %2 bytes of request downloaded." ).arg( bytesReceived ).arg( bytesTotal < 0 ? QStringLiteral( "unknown number of" ) : QString::number( bytesTotal ) );
+ QgsDebugMsg( msg );
+ QgsMessageLog::logMessage( QStringLiteral( "Reply in progress" ), tr( "GeoNode" ) );
+ QgsMessageLog::logMessage( msg, tr( "GeoNode" ) );
+ emit statusChanged( msg );
+}
+
+QString QgsGeoNodeRequest::getProtocol() const
+{
+ return mProtocol;
+}
+
+void QgsGeoNodeRequest::setProtocol( const QString &protocol )
+{
+ mProtocol = protocol;
+}
+
+
+void QgsGeoNodeRequest::replyFinished()
+{
+ QgsMessageLog::logMessage( QStringLiteral( "Reply finished" ), tr( "GeoNode" ) );
+ if ( !mIsAborted && mGeoNodeReply )
+ {
+ if ( mGeoNodeReply->error() == QNetworkReply::NoError )
+ {
+ QgsDebugMsg( "reply OK" );
+ QVariant redirect = mGeoNodeReply->attribute( QNetworkRequest::RedirectionTargetAttribute );
+ if ( !redirect.isNull() )
+ {
+
+ emit statusChanged( QStringLiteral( "GeoNode request redirected." ) );
+
+ const QUrl &toUrl = redirect.toUrl();
+ mGeoNodeReply->request();
+ if ( toUrl == mGeoNodeReply->url() )
+ {
+ mError = tr( "Redirect loop detected: %1" ).arg( toUrl.toString() );
+ QgsMessageLog::logMessage( mError, tr( "GeoNode" ) );
+ mHttpGeoNodeResponse.clear();
+ }
+ else
+ {
+ QNetworkRequest request( toUrl );
+
+ request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
+ request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
+
+ mGeoNodeReply->deleteLater();
+ mGeoNodeReply = nullptr;
+
+ QgsDebugMsg( QString( "redirected getcapabilities: %1 forceRefresh=%2" ).arg( redirect.toString() ).arg( mForceRefresh ) );
+ mGeoNodeReply = QgsNetworkAccessManager::instance()->get( request );
+
+ connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
+ connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
+ return;
+ }
+ }
+ else
+ {
+ const QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();
+
+ if ( nam->cache() )
+ {
+ QNetworkCacheMetaData cmd = nam->cache()->metaData( mGeoNodeReply->request().url() );
+
+ QNetworkCacheMetaData::RawHeaderList hl;
+ Q_FOREACH ( const QNetworkCacheMetaData::RawHeader &h, cmd.rawHeaders() )
+ {
+ if ( h.first != "Cache-Control" )
+ hl.append( h );
+ }
+ cmd.setRawHeaders( hl );
+
+ QgsDebugMsg( QString( "expirationDate:%1" ).arg( cmd.expirationDate().toString() ) );
+ if ( cmd.expirationDate().isNull() )
+ {
+ QgsSettings settings;
+ cmd.setExpirationDate( QDateTime::currentDateTime().addSecs( settings.value( QStringLiteral( "qgis/defaultCapabilitiesExpiry" ), "24", QgsSettings::Providers ).toInt() * 60 * 60 ) );
+ }
+
+ nam->cache()->updateMetaData( cmd );
+ }
+ else
+ {
+ QgsDebugMsg( "No cache for capabilities!" );
+ }
+
+ mHttpGeoNodeResponse = mGeoNodeReply->readAll();
+
+ if ( mHttpGeoNodeResponse.isEmpty() )
+ {
+ mError = tr( "empty of capabilities: %1" ).arg( mGeoNodeReply->errorString() );
+ }
+ }
+ }
+ else
+ {
+ mError = tr( "Request failed: %1" ).arg( mGeoNodeReply->errorString() );
+ QgsMessageLog::logMessage( mError, tr( "GeoNode" ) );
+ mHttpGeoNodeResponse.clear();
+ }
+ }
+
+ if ( mGeoNodeReply )
+ {
+ mGeoNodeReply->deleteLater();
+ mGeoNodeReply = nullptr;
+ }
+
+ emit requestFinished();
+
+}
+
+QList QgsGeoNodeRequest::parseLayers( QByteArray layerResponse )
+{
+ QList layers;
+ if ( layerResponse.isEmpty() )
+ {
+ return layers;
+ }
+
+ QJsonDocument jsonDocument = QJsonDocument::fromJson( layerResponse );
+ QJsonObject jsonObject = jsonDocument.object();
+ QVariantMap jsonVariantMap = jsonObject.toVariantMap();
+ QVariantList layerList = jsonVariantMap["objects"].toList();
+ qint16 majorVersion;
+ qint16 minorVersion;
+ if ( jsonVariantMap.contains( QStringLiteral( "geonode_version" ) ) )
+ {
+ QStringList geonodeVersionSplit = jsonVariantMap["geonode_version"].toString().split( "." );
+ majorVersion = geonodeVersionSplit[0].toInt();
+ minorVersion = geonodeVersionSplit[1].toInt();
+ }
+ else
+ {
+ majorVersion = 2;
+ minorVersion = 6;
+ }
+
+ if ( majorVersion == 2 && minorVersion == 6 )
+ {
+ Q_FOREACH ( QVariant layer, layerList )
+ {
+ QgsServiceLayerDetail layerStruct;
+ QVariantMap layerMap = layer.toMap();
+ // Find WMS and WFS. XYZ is not available
+ // Trick to get layer's typename from distribution_url or detail_url
+ QString layerTypeName = layerMap["detail_url"].toString().split( "/" ).last();
+ if ( layerTypeName.length() == 0 )
+ {
+ layerTypeName = layerMap["distribution_url"].toString().split( "/" ).last();
+ }
+ // On this step, layerTypeName is in WORKSPACE%3ALAYERNAME or WORKSPACE:LAYERNAME format
+ if ( layerTypeName.contains( "%3A" ) )
+ {
+ layerTypeName.replace( "%3A", ":" );
+ }
+ // On this step, layerTypeName is in WORKSPACE:LAYERNAME format
+ QStringList splitURL = layerTypeName.split( ":" );
+ QString layerWorkspace = splitURL[0];
+ QString layerName = splitURL[1];
+
+ layerStruct.name = layerName;
+ layerStruct.typeName = layerTypeName;
+ layerStruct.uuid = layerMap["uuid"].toString();
+ layerStruct.title = layerMap["title"].toString();;
+
+ // WMS url : BASE_URI/geoserver/WORKSPACE/wms
+ layerStruct.wmsURL = mBaseUrl + "/geoserver/" + layerWorkspace + "/wms";
+ // WFS url : BASE_URI/geoserver/WORKSPACE/wfs
+ layerStruct.wfsURL = mBaseUrl + "/geoserver/" + layerWorkspace + "/wfs";
+ // XYZ url : set to empty string
+ layerStruct.xyzURL = "";
+
+ layers.append( layerStruct );
+ }
+ }
+ // Geonode version 2.7 or newer
+ else if ( ( majorVersion == 2 && minorVersion >= 7 ) || ( majorVersion >= 3 ) )
+ {
+ Q_FOREACH ( QVariant layer, layerList )
+ {
+ QgsServiceLayerDetail layerStruct;
+ QVariantMap layerMap = layer.toMap();
+ // Find WMS, WFS, and XYZ link
+ QVariantList layerLinks = layerMap["links"].toList();
+ layerStruct.wmsURL = QStringLiteral( "" );
+ layerStruct.wfsURL = QStringLiteral( "" );
+ layerStruct.xyzURL = QStringLiteral( "" );
+ Q_FOREACH ( QVariant link, layerLinks )
+ {
+ QVariantMap linkMap = link.toMap();
+ if ( linkMap.contains( "link_type" ) )
+ {
+ if ( linkMap["link_type"] == "OGC:WMS" )
+ {
+ layerStruct.wmsURL = linkMap["url"].toString();
+ }
+ if ( linkMap["link_type"] == "OGC:WFS" )
+ {
+ layerStruct.wfsURL = linkMap["url"].toString();
+ }
+ if ( linkMap["link_type"] == "image" )
+ {
+ if ( linkMap.contains( "name" ) && linkMap["name"] == "Tiles" )
+ {
+ layerStruct.xyzURL = linkMap["url"].toString();
+ }
+ }
+ }
+ }
+ if ( layerMap["typename"].toString().length() == 0 )
+ {
+ QStringList splitURL = layerMap["detail_url"].toString().split( "/" );
+ layerStruct.typeName = splitURL[ splitURL.length() - 1];
+ }
+ layerStruct.uuid = layerMap["uuid"].toString();
+ layerStruct.name = layerMap["name"].toString();
+ layerStruct.typeName = layerMap["typename"].toString();
+ layerStruct.title = layerMap["title"].toString();
+ layers.append( layerStruct );
+ }
+ }
+ return layers;
+}
+
+
+QStringList QgsGeoNodeRequest::serviceUrls( QString serviceType )
+{
+ QStringList urls;
+ bool success = getLayers();
+
+ if ( !success )
+ {
+ return urls;
+ }
+
+ QList layers = parseLayers( this->response() );
+
+ Q_FOREACH ( QgsServiceLayerDetail layer, layers )
+ {
+ QString url;
+ if ( serviceType.toLower() == "wms" )
+ {
+ url = layer.wmsURL;
+ }
+ else if ( serviceType.toLower() == "wfs" )
+ {
+ url = layer.wfsURL;
+ }
+ else if ( serviceType.toLower() == "xyz" )
+ {
+ url = layer.xyzURL;
+ }
+ else
+ {
+ url = "";
+ }
+
+ if ( !url.contains( QLatin1String( "://" ) ) && url.length() > 0 )
+ {
+ url.prepend( getProtocol() );
+ }
+ if ( !urls.contains( url ) && url.length() > 0 )
+ {
+ urls.append( url );
+ }
+ }
+
+ return urls;
+}
+
+
+QgsStringMap QgsGeoNodeRequest::serviceUrlData( QString serviceType )
+{
+ QgsStringMap urls;
+ bool success = getLayers();
+
+ if ( !success )
+ {
+ return urls;
+ }
+ QList layers = parseLayers( this->response() );
+
+ Q_FOREACH ( QgsServiceLayerDetail layer, layers )
+ {
+ QString url;
+
+ if ( serviceType.toLower() == "wms" )
+ {
+ url = layer.wmsURL;
+ }
+ else if ( serviceType.toLower() == "wfs" )
+ {
+ url = layer.wfsURL;
+ }
+ else if ( serviceType.toLower() == "xyz" )
+ {
+ url = layer.xyzURL;
+ }
+ else
+ {
+ url = "";
+ }
+
+ QString layerName = layer.name;
+ if ( !url.contains( QLatin1String( "://" ) ) && url.length() > 0 )
+ {
+ url.prepend( getProtocol() );
+ }
+ if ( !urls.contains( url ) && url.length() > 0 )
+ {
+ urls.insert( layerName, url );
+ }
+ }
+
+ return urls;
+}
+
+
+bool QgsGeoNodeRequest::request( QString endPoint )
+{
+ abort();
+ mIsAborted = false;
+ QgsMessageLog::logMessage( mBaseUrl, tr( "GeoNode" ) );
+ QString url = mBaseUrl + endPoint;
+ QgsMessageLog::logMessage( url, tr( "GeoNode" ) );
+ setProtocol( url.split( "://" )[0] );
+ QUrl layerUrl( url );
+ layerUrl.setScheme( getProtocol() );
+
+ mError.clear();
+
+ QNetworkRequest request( url );
+ // Add authentication check here
+
+ request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
+ request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
+
+ mGeoNodeReply = QgsNetworkAccessManager::instance()->get( request );
+
+ connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
+ connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
+
+ QEventLoop loop;
+ connect( this, &QgsGeoNodeRequest::requestFinished, &loop, &QEventLoop::quit );
+
+ loop.exec( QEventLoop::ExcludeUserInputEvents );
+
+ return mError.isEmpty();
+}
diff --git a/src/core/geonode/qgsgeonoderequest.h b/src/core/geonode/qgsgeonoderequest.h
new file mode 100644
index 00000000000..aedbce7a963
--- /dev/null
+++ b/src/core/geonode/qgsgeonoderequest.h
@@ -0,0 +1,112 @@
+/***************************************************************************
+ qgsgeonoderequest.h
+ ---------------------
+ begin : Jul 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+#ifndef QGSGEONODEREQUEST_H
+#define QGSGEONODEREQUEST_H
+
+#include "qgis.h"
+#include "qgis_core.h"
+#include
+
+
+#include
+#include
+
+struct CORE_EXPORT QgsServiceLayerDetail
+{
+#ifdef SIP_RUN
+ % TypeHeaderCode
+#include
+ % End
+#endif
+ QUuid uuid;
+ QString name;
+ QString typeName;
+ QString title;
+ QString wmsURL;
+ QString wfsURL;
+ QString xyzURL;
+};
+
+class CORE_EXPORT QgsGeoNodeRequest : public QObject
+{
+ Q_OBJECT
+ public:
+ explicit QgsGeoNodeRequest( bool forceRefresh, QObject *parent = nullptr );
+ QgsGeoNodeRequest( const QString &baseUrl, /*const QgsWmsAuthorization &auth,*/ bool forceRefresh, QObject *parent = nullptr );
+ virtual ~QgsGeoNodeRequest();
+
+ bool request( QString endPoint );
+
+ bool getLayers();
+
+ QList parseLayers( QByteArray layerResponse );
+
+ // Obtain list of unique URL in the geonode
+ QStringList serviceUrls( QString serviceType );
+
+ // Obtain map of layer name and url for a service type
+ QgsStringMap serviceUrlData( QString serviceType );
+
+ QString lastError() const { return mError; }
+
+ QByteArray response() const { return mHttpGeoNodeResponse; }
+
+ QNetworkReply *reply() const { return mGeoNodeReply; }
+
+ //! Abort network request immediately
+ void abort();
+
+ QString getProtocol() const;
+ void setProtocol( const QString &protocol );
+
+ signals:
+ //! \brief emit a signal to be caught by qgisapp and display a statusQString on status bar
+ void statusChanged( const QString &statusQString );
+
+ //! \brief emit a signal once the request is finished
+ void requestFinished();
+
+ protected slots:
+ void replyFinished();
+ void replyProgress( qint64, qint64 );
+
+ protected:
+
+ //! URL part of URI (httpuri)
+ QString mProtocol;
+
+ //! URL part of URI (httpuri)
+ QString mBaseUrl;
+
+// QgsWmsAuthorization mAuth;
+
+ //! The reply to the geonode request
+ QNetworkReply *mGeoNodeReply = nullptr;
+
+ //! The error message associated with the last error.
+ QString mError;
+
+ //! The mime type of the message
+ QString mErrorFormat;
+
+ //! Response
+ QByteArray mHttpGeoNodeResponse;
+
+ bool mIsAborted;
+ bool mForceRefresh;
+
+};
+
+#endif // QGSGEONODEREQUEST_H
diff --git a/src/core/qgsdataitemprovider.h b/src/core/qgsdataitemprovider.h
index 9f2ddc1da24..1cfe038115c 100644
--- a/src/core/qgsdataitemprovider.h
+++ b/src/core/qgsdataitemprovider.h
@@ -18,6 +18,7 @@
#include "qgis_core.h"
#include "qgis.h"
+#include "qgsdataitem.h"
class QgsDataItem;
@@ -50,6 +51,9 @@ class CORE_EXPORT QgsDataItemProvider
//! Caller takes responsibility of deleting created items.
virtual QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) = 0 SIP_FACTORY;
+ //! Create a vector of instances of QgsDataItem (or null) for given path and parent item.
+ //! Caller takes responsibility of deleting created items.
+ virtual QVector createDataItems( const QString &path, QgsDataItem *parentItem ) { Q_UNUSED( path ); Q_UNUSED( parentItem ); return QVector(); }
};
#endif // QGSDATAITEMPROVIDER_H
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 8b98c620211..50c510d63ef 100755
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -150,6 +150,9 @@ SET(QGIS_GUI_SRCS
editorwidgets/qgsvaluerelationsearchwidgetwrapper.cpp
editorwidgets/qgsvaluerelationwidgetfactory.cpp
+ geonode/qgsgeonodenewconnection.cpp
+ geonode/qgsgeonodesourceselect.cpp
+
layertree/qgscustomlayerorderwidget.cpp
layertree/qgslayertreeembeddedconfigwidget.cpp
layertree/qgslayertreeembeddedwidgetregistry.cpp
@@ -642,6 +645,9 @@ SET(QGIS_GUI_MOC_HDRS
editorwidgets/qgsvaluerelationsearchwidgetwrapper.h
editorwidgets/qgsvaluerelationwidgetwrapper.h
+ geonode/qgsgeonodenewconnection.h
+ geonode/qgsgeonodesourceselect.h
+
layertree/qgscustomlayerorderwidget.h
layertree/qgslayertreeembeddedconfigwidget.h
layertree/qgslayertreeembeddedwidgetsimpl.h
@@ -759,6 +765,9 @@ SET(QGIS_GUI_HDRS
editorwidgets/qgsvaluemapwidgetfactory.h
editorwidgets/qgsvaluerelationwidgetfactory.h
+ geonode/qgsgeonodenewconnection.h
+ geonode/qgsgeonodesourceselect.h
+
layertree/qgslayertreeembeddedconfigwidget.h
layertree/qgslayertreeembeddedwidgetregistry.h
@@ -809,6 +818,7 @@ SET(QGIS_GUI_UI_HDRS
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgssqlcomposerdialogbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgssublayersdialogbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgstablewidgetuibase.h
+ ${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgeonodesourceselectbase.h
)
IF(ENABLE_MODELTEST)
@@ -828,12 +838,14 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/gui/layertree
${CMAKE_SOURCE_DIR}/src/gui/layout
${CMAKE_SOURCE_DIR}/src/gui/effects
+ ${CMAKE_SOURCE_DIR}/src/gui/geonode
${CMAKE_SOURCE_DIR}/src/gui/ogr
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/annotations
${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/composer
${CMAKE_SOURCE_DIR}/src/core/fieldformatter
+ ${CMAKE_SOURCE_DIR}/src/core/geonode
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/layertree
${CMAKE_SOURCE_DIR}/src/core/layout
diff --git a/src/gui/geonode/qgsgeonodenewconnection.cpp b/src/gui/geonode/qgsgeonodenewconnection.cpp
new file mode 100644
index 00000000000..c5509c6c056
--- /dev/null
+++ b/src/gui/geonode/qgsgeonodenewconnection.cpp
@@ -0,0 +1,266 @@
+/***************************************************************************
+ qgsgeonodenewconnection.cpp
+ -------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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
+#include
+#include "qgslogger.h"
+
+#include "qgsgeonodenewconnection.h"
+#include "qgsauthmanager.h"
+#include "qgsdatasourceuri.h"
+#include "qgsgeonodeconnection.h"
+#include "qgssettings.h"
+#include "qgsgeonoderequest.h"
+
+QgsGeoNodeNewConnection::QgsGeoNodeNewConnection( QWidget *parent, const QString &connName, Qt::WindowFlags fl )
+ : QDialog( parent, fl )
+ , mOriginalConnName( connName )
+ , mAuthConfigSelect( nullptr )
+{
+ setupUi( this );
+
+ mBaseKey = QgsGeoNodeConnection::pathGeoNodeConnection();
+ mCredentialsBaseKey = QgsGeoNodeConnection::pathGeoNodeConnection();
+
+ mAuthConfigSelect = new QgsAuthConfigSelect( this );
+ tabAuth->insertTab( 1, mAuthConfigSelect, tr( "Configurations" ) );
+
+ cmbDpiMode->clear();
+ cmbDpiMode->addItem( tr( "all" ) );
+ cmbDpiMode->addItem( tr( "off" ) );
+ cmbDpiMode->addItem( tr( "QGIS" ) );
+ cmbDpiMode->addItem( tr( "UMN" ) );
+ cmbDpiMode->addItem( tr( "GeoServer" ) );
+
+ cmbVersion->clear();
+ cmbVersion->addItem( tr( "Auto-detect" ) );
+ cmbVersion->addItem( tr( "1.0" ) );
+ cmbVersion->addItem( tr( "1.1" ) );
+ cmbVersion->addItem( tr( "2.0" ) );
+
+ if ( !connName.isEmpty() )
+ {
+ // populate the dialog with the information stored for the connection
+ // populate the fields with the stored setting parameters
+ QgsSettings settings;
+
+ QString key = mBaseKey + '/' + connName;
+ QString credentialsKey = mCredentialsBaseKey + '/' + connName;
+ txtName->setText( connName );
+ txtUrl->setText( settings.value( key + "/url", "", QgsSettings::Providers ).toString() );
+
+ cbxIgnoreGetMapURI->setChecked( settings.value( key + "/wms/ignoreGetMapURI", false, QgsSettings::Providers ).toBool() );
+ cbxWfsIgnoreAxisOrientation->setChecked( settings.value( key + "/wfs/ignoreAxisOrientation", false, QgsSettings::Providers ).toBool() );
+ cbxWmsIgnoreAxisOrientation->setChecked( settings.value( key + "/wms/ignoreAxisOrientation", false, QgsSettings::Providers ).toBool() );
+ cbxWfsInvertAxisOrientation->setChecked( settings.value( key + "/wfs/invertAxisOrientation", false, QgsSettings::Providers ).toBool() );
+ cbxWmsInvertAxisOrientation->setChecked( settings.value( key + "/wms/invertAxisOrientation", false, QgsSettings::Providers ).toBool() );
+ cbxIgnoreGetFeatureInfoURI->setChecked( settings.value( key + "/wms/ignoreGetFeatureInfoURI", false, QgsSettings::Providers ).toBool() );
+ cbxSmoothPixmapTransform->setChecked( settings.value( key + "/wms/smoothPixmapTransform", false, QgsSettings::Providers ).toBool() );
+
+ int dpiIdx;
+ switch ( settings.value( key + "/dpiMode", 7, QgsSettings::Providers ).toInt() )
+ {
+ case 0: // off
+ dpiIdx = 1;
+ break;
+ case 1: // QGIS
+ dpiIdx = 2;
+ break;
+ case 2: // UMN
+ dpiIdx = 3;
+ break;
+ case 4: // GeoServer
+ dpiIdx = 4;
+ break;
+ default: // other => all
+ dpiIdx = 0;
+ break;
+ }
+ cmbDpiMode->setCurrentIndex( dpiIdx );
+
+ QString version = settings.value( key + "/version", QLatin1String( "1.0.0" ), QgsSettings::Providers ).toString();
+ int versionIdx = 0; // AUTO
+ if ( version == QLatin1String( "1.0.0" ) )
+ versionIdx = 1;
+ else if ( version == QLatin1String( "1.1.0" ) )
+ versionIdx = 2;
+ else if ( version == QLatin1String( "2.0.0" ) )
+ versionIdx = 3;
+ cmbVersion->setCurrentIndex( versionIdx );
+
+ txtReferer->setText( settings.value( key + "/referer", "", QgsSettings::Providers ).toString() );
+ txtMaxNumFeatures->setText( settings.value( key + "/maxnumfeatures", QgsSettings::Providers ).toString() );
+
+ txtUserName->setText( settings.value( credentialsKey + "/username", "", QgsSettings::Providers ).toString() );
+ txtPassword->setText( settings.value( credentialsKey + "/password", "", QgsSettings::Providers ).toString() );
+
+ QString authcfg = settings.value( credentialsKey + "/authcfg", "", QgsSettings::Providers ).toString();
+ mAuthConfigSelect->setConfigId( authcfg );
+ if ( !authcfg.isEmpty() )
+ {
+ tabAuth->setCurrentIndex( tabAuth->indexOf( mAuthConfigSelect ) );
+ }
+ }
+
+ // Adjust height
+ int w = width();
+ adjustSize();
+ resize( w, height() );
+
+ buttonBox->button( QDialogButtonBox::Ok )->setDisabled( true );
+ connect( txtName, &QLineEdit::textChanged, this, &QgsGeoNodeNewConnection::okButtonBehavior );
+ connect( txtUrl, &QLineEdit::textChanged, this, &QgsGeoNodeNewConnection::okButtonBehavior );
+ connect( btnConnect, &QPushButton::clicked, this, &QgsGeoNodeNewConnection::testConnection );
+}
+
+void QgsGeoNodeNewConnection::accept()
+{
+ QgsSettings settings;
+ QString key = mBaseKey + '/' + txtName->text();
+ QString credentialsKey = mCredentialsBaseKey + '/' + txtName->text();
+
+ // warn if entry was renamed to an existing connection
+ if ( ( mOriginalConnName.isNull() || mOriginalConnName.compare( txtName->text(), Qt::CaseInsensitive ) != 0 ) &&
+ settings.contains( key + "/url", QgsSettings::Providers ) &&
+ QMessageBox::question( this,
+ tr( "Save connection" ),
+ tr( "Should the existing connection %1 be overwritten?" ).arg( txtName->text() ),
+ QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Cancel )
+ {
+ return;
+ }
+
+ if ( !txtPassword->text().isEmpty() &&
+ QMessageBox::question( this,
+ tr( "Saving passwords" ),
+ trUtf8( "WARNING: You have entered a password. It will be stored in unsecured plain text in your project files and your home directory (Unix-like OS) or user profile (Windows). If you want to avoid this, press Cancel and either:\n\na) Don't provide a password in the connection settings — it will be requested interactively when needed;\nb) Use the Configuration tab to add your credentials in an HTTP Basic Authentication method and store them in an encrypted database." ),
+ QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Cancel )
+ {
+ return;
+ }
+
+ // on rename delete original entry first
+ if ( !mOriginalConnName.isNull() && mOriginalConnName != key )
+ {
+ // Manually add Section here
+ settings.remove( "providers/" + mBaseKey + '/' + mOriginalConnName );
+ settings.remove( "providers/qgis//" + mCredentialsBaseKey + '/' + mOriginalConnName );
+ settings.sync();
+ }
+
+ if ( !txtUrl->text().contains( "://" ) &&
+ QMessageBox::information(
+ this,
+ tr( "Invalid URL" ),
+ tr( "Your URL doesn't contains protocol (e.g. http or https). Please add the protocol." ) ) == QMessageBox::Ok )
+ {
+ return;
+ }
+ QUrl url( txtUrl->text() );
+
+ settings.setValue( key + "/url", url.toString(), QgsSettings::Providers );
+
+ settings.setValue( key + "/wfs/ignoreAxisOrientation", cbxWfsIgnoreAxisOrientation->isChecked(), QgsSettings::Providers );
+ settings.setValue( key + "/wms/ignoreAxisOrientation", cbxWmsIgnoreAxisOrientation->isChecked(), QgsSettings::Providers );
+ settings.setValue( key + "/wfs/invertAxisOrientation", cbxWfsInvertAxisOrientation->isChecked(), QgsSettings::Providers );
+ settings.setValue( key + "/wms/invertAxisOrientation", cbxWmsInvertAxisOrientation->isChecked(), QgsSettings::Providers );
+
+ settings.setValue( key + "/wms/ignoreGetMapURI", cbxIgnoreGetMapURI->isChecked(), QgsSettings::Providers );
+ settings.setValue( key + "/wms/smoothPixmapTransform", cbxSmoothPixmapTransform->isChecked(), QgsSettings::Providers );
+ settings.setValue( key + "/wms/ignoreGetFeatureInfoURI", cbxIgnoreGetFeatureInfoURI->isChecked(), QgsSettings::Providers );
+
+ int dpiMode = 0;
+ switch ( cmbDpiMode->currentIndex() )
+ {
+ case 0: // all => QGIS|UMN|GeoServer
+ dpiMode = 7;
+ break;
+ case 1: // off
+ dpiMode = 0;
+ break;
+ case 2: // QGIS
+ dpiMode = 1;
+ break;
+ case 3: // UMN
+ dpiMode = 2;
+ break;
+ case 4: // GeoServer
+ dpiMode = 4;
+ break;
+ }
+
+ settings.setValue( key + "/wms/dpiMode", dpiMode, QgsSettings::Providers );
+ settings.setValue( key + "/wms/referer", txtReferer->text(), QgsSettings::Providers );
+
+ QString version = QStringLiteral( "auto" );
+ switch ( cmbVersion->currentIndex() )
+ {
+ case 0:
+ version = QStringLiteral( "auto" );
+ break;
+ case 1:
+ version = QStringLiteral( "1.0.0" );
+ break;
+ case 2:
+ version = QStringLiteral( "1.1.0" );
+ break;
+ case 3:
+ version = QStringLiteral( "2.0.0" );
+ break;
+ }
+
+ settings.setValue( key + "/wfs/version", version, QgsSettings::Providers );
+ settings.setValue( key + "/wfs/maxnumfeatures", txtMaxNumFeatures->text(), QgsSettings::Providers );
+
+ settings.setValue( credentialsKey + "/username", txtUserName->text(), QgsSettings::Providers );
+ settings.setValue( credentialsKey + "/password", txtPassword->text(), QgsSettings::Providers );
+
+ settings.setValue( credentialsKey + "/authcfg", mAuthConfigSelect->configId(), QgsSettings::Providers );
+
+ settings.setValue( mBaseKey + "/selected", txtName->text(), QgsSettings::Providers );
+
+ QDialog::accept();
+}
+
+void QgsGeoNodeNewConnection::okButtonBehavior( const QString &text )
+{
+ Q_UNUSED( text );
+ buttonBox->button( QDialogButtonBox::Ok )->setDisabled( txtName->text().isEmpty() || txtUrl->text().isEmpty() );
+ buttonBox->button( QDialogButtonBox::Ok )->setEnabled( !txtName->text().isEmpty() && !txtUrl->text().isEmpty() );
+}
+
+void QgsGeoNodeNewConnection::testConnection()
+{
+ QApplication::setOverrideCursor( Qt::BusyCursor );
+ QString url = txtUrl->text();
+ QgsGeoNodeRequest geonodeRequest( url, true );
+ bool success = geonodeRequest.getLayers();
+ QApplication::restoreOverrideCursor();
+
+ if ( success )
+ {
+ QMessageBox::information( this,
+ tr( "Test connection" ),
+ tr( "\nConnection to %1 was successful, \n\n%1 is a valid geonode instance.\n\n" ).arg( txtUrl->text() ) );
+ }
+ else
+ {
+ QMessageBox::information( this,
+ tr( "Test connection" ),
+ tr( "\nConnection failed, \n\nplease check whether %1 is a valid geonode instance.\n\n" ).arg( txtUrl->text() ) );
+ }
+}
diff --git a/src/gui/geonode/qgsgeonodenewconnection.h b/src/gui/geonode/qgsgeonodenewconnection.h
new file mode 100644
index 00000000000..3af65c842cb
--- /dev/null
+++ b/src/gui/geonode/qgsgeonodenewconnection.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ qgsgeonodenewconnection.h
+ -------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSGEONODENEWCONNECTION_H
+#define QGSGEONODENEWCONNECTION_H
+
+#include "ui_qgsnewgeonodeconnectionbase.h"
+#include "qgis_gui.h"
+#include "qgsguiutils.h"
+#include "qgsauthconfigselect.h"
+
+class GUI_EXPORT QgsGeoNodeNewConnection : public QDialog, private Ui::QgsNewGeoNodeConnectionBase
+{
+ Q_OBJECT
+
+ public:
+ //! Constructor
+ QgsGeoNodeNewConnection( QWidget *parent = nullptr, const QString &connName = QString::null, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
+
+ public slots:
+ void accept() override;
+ void okButtonBehavior( const QString & );
+ //! Test the connection using the parameters supplied
+ void testConnection();
+
+ private:
+ QString mBaseKey;
+ QString mCredentialsBaseKey;
+ QString mOriginalConnName; //store initial name to delete entry in case of rename
+ QgsAuthConfigSelect *mAuthConfigSelect = nullptr;
+};
+
+#endif //QGSGEONODENEWCONNECTION_H
diff --git a/src/gui/geonode/qgsgeonodesourceselect.cpp b/src/gui/geonode/qgsgeonodesourceselect.cpp
new file mode 100644
index 00000000000..800483b769f
--- /dev/null
+++ b/src/gui/geonode/qgsgeonodesourceselect.cpp
@@ -0,0 +1,505 @@
+/***************************************************************************
+ qgsgeonodesourceselect.cpp
+ -------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 "qgslogger.h"
+#include "qgsmessagelog.h"
+#include "qgsproviderregistry.h"
+
+#include "qgsgeonodesourceselect.h"
+#include "qgsgeonodeconnection.h"
+#include "qgsgeonoderequest.h"
+
+#include "qgsgeonodenewconnection.h"
+#include "qgsmanageconnectionsdialog.h"
+
+#include
+#include
+#include
+#include
+
+enum
+{
+ MODEL_IDX_TITLE,
+ MODEL_IDX_NAME,
+ MODEL_IDX_TYPE,
+ MODEL_IDX_WEB_SERVICE
+};
+
+QgsGeoNodeSourceSelect::QgsGeoNodeSourceSelect( QWidget *parent, Qt::WindowFlags fl, bool embeddedMode )
+ : QDialog( parent, fl )
+{
+ setupUi( this );
+
+ if ( embeddedMode != QgsProviderRegistry::WidgetMode::None )
+ {
+ // For some obscure reasons hiding does not work!
+ // buttonBox->button( QDialogButtonBox::Close )->hide();
+ buttonBox->removeButton( buttonBox->button( QDialogButtonBox::Close ) );
+ }
+
+ mAddButton = new QPushButton( tr( "&Add" ) );
+ mAddButton->setEnabled( false );
+
+ buttonBox->addButton( mAddButton, QDialogButtonBox::ActionRole );
+
+ populateConnectionList();
+
+ connect( buttonBox, &QDialogButtonBox::rejected, this, &QgsGeoNodeSourceSelect::reject );
+ connect( btnNew, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::addConnectionsEntryList );
+ connect( btnEdit, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::modifyConnectionsEntryList );
+ connect( btnDelete, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::deleteConnectionsEntryList );
+ connect( btnConnect, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::connectToGeonodeConnection );
+ connect( btnSave, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::saveGeonodeConnection );
+ connect( btnLoad, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::loadGeonodeConnection );
+ connect( lineFilter, &QLineEdit::textChanged, this, &QgsGeoNodeSourceSelect::filterChanged );
+ connect( treeView, &QTreeView::clicked, this, &QgsGeoNodeSourceSelect::treeViewSelectionChanged );
+ connect( mAddButton, &QPushButton::clicked, this, &QgsGeoNodeSourceSelect::addButtonClicked );
+
+ mItemDelegate = new QgsGeonodeItemDelegate( treeView );
+ treeView->setItemDelegate( mItemDelegate );
+
+ mModel = new QStandardItemModel();
+ mModel->setHorizontalHeaderItem( MODEL_IDX_TITLE, new QStandardItem( tr( "Title" ) ) );
+ mModel->setHorizontalHeaderItem( MODEL_IDX_NAME, new QStandardItem( tr( "Name" ) ) );
+ mModel->setHorizontalHeaderItem( MODEL_IDX_TYPE, new QStandardItem( tr( "Type" ) ) );
+ mModel->setHorizontalHeaderItem( MODEL_IDX_WEB_SERVICE, new QStandardItem( tr( "Web Service" ) ) );
+
+ mModelProxy = new QSortFilterProxyModel( this );
+ mModelProxy->setSourceModel( mModel );
+ mModelProxy->setSortCaseSensitivity( Qt::CaseInsensitive );
+ treeView->setModel( mModelProxy );
+}
+
+QgsGeoNodeSourceSelect::~QgsGeoNodeSourceSelect() {}
+
+void QgsGeoNodeSourceSelect::addConnectionsEntryList()
+{
+ QgsGeoNodeNewConnection *nc = new QgsGeoNodeNewConnection( this );
+
+ if ( nc->exec() )
+ {
+ populateConnectionList();
+ emit connectionsChanged();
+ }
+
+ delete nc;
+}
+
+void QgsGeoNodeSourceSelect::modifyConnectionsEntryList()
+{
+ QgsGeoNodeNewConnection *nc = new QgsGeoNodeNewConnection( this, cmbConnections->currentText() );
+ nc->setWindowTitle( tr( "Modify GeoNode connection" ) );
+
+ if ( nc->exec() )
+ {
+ populateConnectionList();
+ emit connectionsChanged();
+ }
+}
+
+void QgsGeoNodeSourceSelect::deleteConnectionsEntryList()
+{
+ QString msg = tr( "Are you sure you want to remove the %1 connection and all associated settings?" )
+ .arg( cmbConnections->currentText() );
+ QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Delete" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
+ if ( result == QMessageBox::Ok )
+ {
+ QgsGeoNodeConnection::deleteConnection( cmbConnections->currentText() );
+ cmbConnections->removeItem( cmbConnections->currentIndex() );
+ if ( mModel )
+ {
+ mModel->removeRows( 0, mModel->rowCount() );
+ }
+ emit connectionsChanged();
+
+ if ( cmbConnections->count() > 0 )
+ {
+ // Connections available - enable various buttons
+ btnConnect->setEnabled( true );
+ btnEdit->setEnabled( true );
+ btnDelete->setEnabled( true );
+ btnSave->setEnabled( true );
+ }
+ else
+ {
+ // No connections available - disable various buttons
+ btnConnect->setEnabled( false );
+ btnEdit->setEnabled( false );
+ btnDelete->setEnabled( false );
+ btnSave->setEnabled( false );
+ }
+ }
+}
+
+void QgsGeoNodeSourceSelect::populateConnectionList()
+{
+ cmbConnections->clear();
+ cmbConnections->addItems( QgsGeoNodeConnection::connectionList() );
+
+ setConnectionListPosition();
+}
+
+void QgsGeoNodeSourceSelect::setConnectionListPosition()
+{
+ QString toSelect = QgsGeoNodeConnection::selectedConnection();
+
+ cmbConnections->setCurrentIndex( cmbConnections->findText( toSelect ) );
+
+ if ( cmbConnections->currentIndex() < 0 )
+ {
+ if ( toSelect.isNull() )
+ cmbConnections->setCurrentIndex( 0 );
+ else
+ cmbConnections->setCurrentIndex( cmbConnections->count() - 1 );
+ }
+
+ if ( cmbConnections->count() == 0 )
+ {
+ // No connections - disable various buttons
+ btnConnect->setEnabled( false );
+ btnEdit->setEnabled( false );
+ btnDelete->setEnabled( false );
+ btnSave->setEnabled( false );
+ }
+ else
+ {
+ // Connections - enable various buttons
+ btnConnect->setEnabled( true );
+ btnEdit->setEnabled( true );
+ btnDelete->setEnabled( true );
+ btnSave->setEnabled( true );
+ }
+}
+
+void QgsGeoNodeSourceSelect::connectToGeonodeConnection()
+{
+ QApplication::setOverrideCursor( Qt::BusyCursor );
+ QgsGeoNodeConnection connection( cmbConnections->currentText() );
+
+ QString url = connection.uri().param( "url" );
+ QgsGeoNodeRequest geonodeRequest( url, true );
+
+ QApplication::setOverrideCursor( Qt::WaitCursor );
+ bool success = geonodeRequest.getLayers();
+ QApplication::restoreOverrideCursor();
+
+ if ( success )
+ {
+ QgsMessageLog::logMessage( QStringLiteral( "Success" ), tr( "GeoNode" ) );
+ }
+ else
+ {
+ QgsMessageLog::logMessage( QStringLiteral( "Failed" ), tr( "GeoNode" ) );
+ }
+
+ QByteArray ba = geonodeRequest.response();
+
+ QList layers = geonodeRequest.parseLayers( ba );
+
+ if ( mModel )
+ {
+ mModel->removeRows( 0, mModel->rowCount() );
+ }
+
+ if ( !layers.isEmpty() )
+ {
+ Q_FOREACH ( const QgsServiceLayerDetail &layer, layers )
+ {
+ QUuid uuid = layer.uuid;
+
+ QString layerName = layer.name;
+
+ QString wmsURL = layer.wmsURL;
+ QString wfsURL = layer.wfsURL;
+ QString xyzURL = layer.xyzURL;
+
+ if ( wmsURL.length() > 0 )
+ {
+ QStandardItem *titleItem = new QStandardItem( layer.title );
+ QStandardItem *nameItem;
+ if ( layer.name > 0 )
+ {
+ nameItem = new QStandardItem( layer.name );
+ }
+ else
+ {
+ nameItem = new QStandardItem( layer.title );
+ }
+ QStandardItem *serviceTypeItem = new QStandardItem( tr( "Layer" ) );
+ QStandardItem *webServiceTypeItem = new QStandardItem( tr( "WMS" ) );
+
+ QString typeName = layer.typeName;
+
+ titleItem->setData( uuid, Qt::UserRole + 1 );
+ titleItem->setData( wmsURL, Qt::UserRole + 2 );
+ titleItem->setData( typeName, Qt::UserRole + 3 );
+ typedef QList< QStandardItem * > StandardItemList;
+ mModel->appendRow( StandardItemList() << titleItem << nameItem << serviceTypeItem << webServiceTypeItem );
+ }
+ else
+ {
+ qDebug() << "Layer " << layer.title << " does not have WMS url.";
+ }
+ if ( wfsURL.length() > 0 )
+ {
+ QStandardItem *titleItem = new QStandardItem( layer.title );
+ QStandardItem *nameItem;
+ if ( layer.name.length() > 0 )
+ {
+ nameItem = new QStandardItem( layer.name );
+ }
+ else
+ {
+ nameItem = new QStandardItem( layer.title );
+ }
+ QStandardItem *serviceTypeItem = new QStandardItem( tr( "Layer" ) );
+ QStandardItem *webServiceTypeItem = new QStandardItem( tr( "WFS" ) );
+
+ QString typeName = layer.typeName;
+
+ titleItem->setData( uuid, Qt::UserRole + 1 );
+ titleItem->setData( wfsURL, Qt::UserRole + 2 );
+ titleItem->setData( typeName, Qt::UserRole + 3 );
+ typedef QList< QStandardItem * > StandardItemList;
+ mModel->appendRow( StandardItemList() << titleItem << nameItem << serviceTypeItem << webServiceTypeItem );
+ }
+ else
+ {
+ qDebug() << "Layer " << layer.title << " does not have WFS url.";
+ }
+ if ( xyzURL.length() > 0 )
+ {
+ QStandardItem *titleItem = new QStandardItem( layer.title );
+ QStandardItem *nameItem;
+ if ( layer.name.length() > 0 )
+ {
+ nameItem = new QStandardItem( layer.name );
+ }
+ else
+ {
+ nameItem = new QStandardItem( layer.title );
+ }
+ QStandardItem *serviceTypeItem = new QStandardItem( tr( "Layer" ) );
+ QStandardItem *webServiceTypeItem = new QStandardItem( tr( "XYZ" ) );
+
+ QString typeName = layer.typeName;
+
+ titleItem->setData( uuid, Qt::UserRole + 1 );
+ titleItem->setData( xyzURL, Qt::UserRole + 2 );
+ titleItem->setData( typeName, Qt::UserRole + 3 );
+ typedef QList< QStandardItem * > StandardItemList;
+ mModel->appendRow( StandardItemList() << titleItem << nameItem << serviceTypeItem << webServiceTypeItem );
+ }
+ else
+ {
+ qDebug() << "Layer " << layer.title << " does not have XYZ url.";
+ }
+ }
+ }
+
+ else
+ {
+ QMessageBox *box = new QMessageBox( QMessageBox::Critical, tr( "Error" ), tr( "Cannot get any feature services" ), QMessageBox::Ok, this );
+ box->setAttribute( Qt::WA_DeleteOnClose );
+ box->setModal( true );
+ box->setObjectName( QStringLiteral( "GeonodeCapabilitiesErrorBox" ) );
+ box->open();
+ }
+
+ treeView->resizeColumnToContents( MODEL_IDX_TITLE );
+ treeView->resizeColumnToContents( MODEL_IDX_NAME );
+ treeView->resizeColumnToContents( MODEL_IDX_TYPE );
+ treeView->resizeColumnToContents( MODEL_IDX_WEB_SERVICE );
+ for ( int i = MODEL_IDX_TITLE; i < MODEL_IDX_WEB_SERVICE; i++ )
+ {
+ if ( treeView->columnWidth( i ) > 210 )
+ {
+ treeView->setColumnWidth( i, 210 );
+ }
+ }
+ QApplication::restoreOverrideCursor();
+}
+
+void QgsGeoNodeSourceSelect::saveGeonodeConnection()
+{
+ QgsManageConnectionsDialog dlg( this, QgsManageConnectionsDialog::Export, QgsManageConnectionsDialog::GeoNode );
+ dlg.exec();
+}
+
+void QgsGeoNodeSourceSelect::loadGeonodeConnection()
+{
+ QString fileName = QFileDialog::getOpenFileName( this, tr( "Load connections" ), QDir::homePath(),
+ tr( "XML files (*.xml *XML)" ) );
+ if ( fileName.isEmpty() )
+ {
+ return;
+ }
+
+ QgsManageConnectionsDialog dlg( this, QgsManageConnectionsDialog::Import, QgsManageConnectionsDialog::GeoNode, fileName );
+ dlg.exec();
+ populateConnectionList();
+ emit connectionsChanged();
+}
+
+void QgsGeoNodeSourceSelect::filterChanged( const QString &text )
+{
+ QRegExp::PatternSyntax mySyntax = QRegExp::PatternSyntax( QRegExp::RegExp );
+ Qt::CaseSensitivity myCaseSensitivity = Qt::CaseInsensitive;
+ QRegExp myRegExp( text, myCaseSensitivity, mySyntax );
+ mModelProxy->setFilterRegExp( myRegExp );
+ mModelProxy->sort( mModelProxy->sortColumn(), mModelProxy->sortOrder() );
+}
+
+void QgsGeoNodeSourceSelect::treeViewSelectionChanged()
+{
+ QModelIndex currentIndex = treeView->selectionModel()->currentIndex();
+ if ( !currentIndex.isValid() )
+ {
+ qDebug() << "Current index is invalid";
+ return;
+ }
+ mAddButton->setEnabled( false );
+ QModelIndexList modelIndexList = treeView->selectionModel()->selectedRows();
+ for ( int i = 0; i < modelIndexList.size(); i++ )
+ {
+ QModelIndex idx = mModelProxy->mapToSource( modelIndexList[i] );
+ if ( !idx.isValid() )
+ {
+ continue;
+ }
+ int row = idx.row();
+ QString typeItem = mModel->item( row, MODEL_IDX_TYPE )->text();
+ if ( typeItem == tr( "Layer" ) )
+ {
+ // Enable if there is a layer selected
+ mAddButton->setEnabled( true );
+ return;
+ }
+ }
+
+}
+
+void QgsGeoNodeSourceSelect::addButtonClicked()
+{
+ qDebug() << "Add button clicked";
+ QApplication::setOverrideCursor( Qt::BusyCursor );
+ // Get selected entry in treeview
+ QModelIndex currentIndex = treeView->selectionModel()->currentIndex();
+ if ( !currentIndex.isValid() )
+ {
+ qDebug() << "Current index is invalid";
+ return;
+ }
+
+ QgsGeoNodeConnection connection( cmbConnections->currentText() );
+ QModelIndexList modelIndexList = treeView->selectionModel()->selectedRows();
+ for ( int i = 0; i < modelIndexList.size(); i++ )
+ {
+ QModelIndex idx = mModelProxy->mapToSource( modelIndexList[i] );
+ if ( !idx.isValid() )
+ {
+ continue;
+ }
+ int row = idx.row();
+
+ qDebug() << "Model index row " << row;
+
+ QString typeItem = mModel->item( row, MODEL_IDX_TYPE )->text();
+ if ( typeItem == tr( "Map" ) )
+ {
+ qDebug() << "Skip adding map.";
+ continue;
+ }
+ QString serviceURL = mModel->item( row, MODEL_IDX_TITLE )->data( Qt::UserRole + 2 ).toString();
+ QString titleName = mModel->item( row, MODEL_IDX_TITLE )->text();
+ QString layerName = mModel->item( row, MODEL_IDX_NAME )->text();
+ QString webServiceType = mModel->item( row, MODEL_IDX_WEB_SERVICE )->text();
+
+ if ( cbxUseTitleLayerName->isChecked() && !titleName.isEmpty() )
+ {
+ QString layerName = titleName;
+ }
+
+ qDebug() << "Layer name: " << layerName << " Type: " << webServiceType;
+
+ if ( webServiceType == "WMS" )
+ {
+ qDebug() << "Adding WMS layer of " << layerName;
+ QgsDataSourceUri uri;
+ uri.setParam( QStringLiteral( "url" ), serviceURL );
+
+ // Set static first, to see that it works. Need to think about the UI also.
+ QString format( "image/png" );
+ QString crs( "EPSG:4326" );
+ QString styles( "" );
+ QString contextualWMSLegend( "0" );
+
+ uri.setParam( QStringLiteral( "contextualWMSLegend" ), contextualWMSLegend );
+ uri.setParam( QStringLiteral( "layers" ), layerName );
+ uri.setParam( QStringLiteral( "styles" ), styles );
+ uri.setParam( QStringLiteral( "format" ), format );
+ uri.setParam( QStringLiteral( "crs" ), crs );
+
+ QgsDebugMsg( "Add WMS from GeoNode : " + uri.encodedUri() );
+ emit addRasterLayer( uri.encodedUri(), layerName, QStringLiteral( "wms" ) );
+ }
+ else if ( webServiceType == "WFS" )
+ {
+ qDebug() << "Adding WFS layer of " << layerName;
+
+ // Set static first, to see that it works. Need to think about the UI also.
+ QString typeName = mModel->item( row, 0 )->data( Qt::UserRole + 3 ).toString();
+ QString crs( "EPSG:4326" );
+
+ // typeName, titleName, sql,
+ // Build url for WFS
+ // restrictToRequestBBOX='1' srsname='EPSG:26719' typename='geonode:cab_mun' url='http://demo.geonode.org/geoserver/geonode/wms' table=\"\" sql="
+ QString uri;
+ uri += QStringLiteral( " restrictToRequestBBOX='1'" );
+ uri += QStringLiteral( " srsname='%1'" ).arg( crs );
+ if ( serviceURL.contains( "qgis-server" ) )
+ {
+ // I need to do this since the typename used in qgis-server is without the workspace.
+ QString qgisServerTypeName = QString( typeName ).split( ":" ).last();
+ uri += QStringLiteral( " typename='%1'" ).arg( qgisServerTypeName );
+ }
+ else
+ {
+ uri += QStringLiteral( " typename='%1'" ).arg( typeName );
+ }
+ uri += QStringLiteral( " url='%1'" ).arg( serviceURL );
+ uri += QStringLiteral( " table=\"\"" );
+ uri += QStringLiteral( " sql=" );
+
+ QgsMessageLog::logMessage( "Add WFS from GeoNode : " + uri + " and typename: " + typeName, tr( "GeoNode" ) );
+ emit addWfsLayer( uri, typeName, "WFS" );
+ }
+ else if ( webServiceType == "XYZ" )
+ {
+ QgsDebugMsg( "XYZ Url: " + serviceURL );
+ QgsDebugMsg( "Add XYZ from GeoNode : " + serviceURL );
+ QgsDataSourceUri uri;
+ uri.setParam( QStringLiteral( "url" ), serviceURL );
+ uri.setParam( QStringLiteral( "type" ), QStringLiteral( "xyz" ) );
+ uri.setParam( QStringLiteral( "zmin" ), "0" );
+ uri.setParam( QStringLiteral( "zmax" ), "18" );
+ emit addRasterLayer( uri.encodedUri(), layerName, QStringLiteral( "wms" ) );
+ }
+ }
+
+ QApplication::restoreOverrideCursor();
+}
diff --git a/src/gui/geonode/qgsgeonodesourceselect.h b/src/gui/geonode/qgsgeonodesourceselect.h
new file mode 100644
index 00000000000..005b65e220f
--- /dev/null
+++ b/src/gui/geonode/qgsgeonodesourceselect.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ qgsgeonodesourceselect.h
+ -------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSGEONODESOURCESELECT_H
+#define QGSGEONODESOURCESELECT_H
+
+#include
+#include
+#include
+#include "ui_qgsgeonodesourceselectbase.h"
+#include "qgis_gui.h"
+
+class GUI_EXPORT QgsGeonodeItemDelegate : public QItemDelegate
+{
+ Q_OBJECT
+
+ public:
+ explicit QgsGeonodeItemDelegate( QObject *parent = nullptr ) : QItemDelegate( parent ) { }
+};
+
+class GUI_EXPORT QgsGeoNodeSourceSelect: public QDialog, private Ui::QgsGeonodeSourceSelectBase
+{
+ Q_OBJECT
+
+ public:
+
+ QgsGeoNodeSourceSelect( QWidget *parent, Qt::WindowFlags fl, bool embeddedMode = false );
+ ~QgsGeoNodeSourceSelect();
+
+ signals:
+ void connectionsChanged();
+ void addRasterLayer( const QString &rasterLayerPath,
+ const QString &baseName,
+ const QString &providerKey );
+ void addRasterLayer();
+
+ void addWfsLayer(
+ const QString &uri,
+ const QString &layerName,
+ const QString &providerKey );
+
+ private:
+ QgsGeoNodeSourceSelect(); //default constructor is forbidden
+
+ /** Stores the available CRS for a server connections.
+ The first string is the typename, the corresponding list
+ stores the CRS for the typename in the form 'EPSG:XXXX'*/
+ QMap mAvailableCRS;
+ QString mUri; // data source URI
+ QgsGeonodeItemDelegate *mItemDelegate = nullptr;
+ QStandardItemModel *mModel = nullptr;
+ QSortFilterProxyModel *mModelProxy = nullptr;
+ QPushButton *mBuildQueryButton = nullptr;
+ QPushButton *mAddButton = nullptr;
+ QModelIndex mSQLIndex;
+
+ private slots:
+ void addConnectionsEntryList();
+ void modifyConnectionsEntryList();
+ void deleteConnectionsEntryList();
+ void connectToGeonodeConnection();
+ void saveGeonodeConnection();
+ void loadGeonodeConnection();
+ void filterChanged( const QString &text );
+ void treeViewSelectionChanged();
+ void addButtonClicked();
+
+ void populateConnectionList();
+ void setConnectionListPosition();
+
+};
+
+
+#endif
diff --git a/src/gui/qgsdatasourcemanagerdialog.cpp b/src/gui/qgsdatasourcemanagerdialog.cpp
index 197bd72e7d0..7deb320924c 100644
--- a/src/gui/qgsdatasourcemanagerdialog.cpp
+++ b/src/gui/qgsdatasourcemanagerdialog.cpp
@@ -24,6 +24,7 @@
#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 ),
@@ -98,6 +99,14 @@ QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QWidget *parent, QgsMapC
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()
@@ -148,6 +157,15 @@ void QgsDataSourceManagerDialog::vectorLayersAdded( const QStringList &layerQStr
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 )
{
diff --git a/src/gui/qgsdatasourcemanagerdialog.h b/src/gui/qgsdatasourcemanagerdialog.h
index 0deb9cf9e95..0f1c12342bd 100644
--- a/src/gui/qgsdatasourcemanagerdialog.h
+++ b/src/gui/qgsdatasourcemanagerdialog.h
@@ -114,6 +114,8 @@ class GUI_EXPORT QgsDataSourceManagerDialog : public QgsOptionsDialogBase, priva
void providerDialogsRefreshRequested();
private:
+ //! Add a provider dialog
+ QDialog *addDialog( QDialog *dialog, QString const key, QString const name, QString const icon, QString title = QString() );
// Return the dialog from the provider
QgsAbstractDataSourceWidget *providerDialog( const QString providerKey, const QString providerName, const QString icon, QString title = QString() );
QgsAbstractDataSourceWidget *addDbProviderDialog( QString const providerKey, QString const providerName, QString const icon, QString title = QString() );
diff --git a/src/gui/qgsmanageconnectionsdialog.cpp b/src/gui/qgsmanageconnectionsdialog.cpp
index f30c0df9fae..b53f53c1ab6 100644
--- a/src/gui/qgsmanageconnectionsdialog.cpp
+++ b/src/gui/qgsmanageconnectionsdialog.cpp
@@ -130,6 +130,9 @@ void QgsManageConnectionsDialog::doExportImport()
case DB2:
doc = saveDb2Connections( items );
break;
+ case GeoNode:
+ doc = saveGeonodeConnections( items );
+ break;
}
QFile file( mFileName );
@@ -195,6 +198,9 @@ void QgsManageConnectionsDialog::doExportImport()
case DB2:
loadDb2Connections( doc, items );
break;
+ case GeoNode:
+ loadGeonodeConnections( doc, items );
+ break;
}
// clear connections list and close window
listConnections->clear();
@@ -233,6 +239,9 @@ bool QgsManageConnectionsDialog::populateConnections()
case DB2:
settings.beginGroup( QStringLiteral( "/DB2/connections" ) );
break;
+ case GeoNode:
+ settings.beginGroup( QStringLiteral( "/qgis/connections-geonode" ) );
+ break;
}
QStringList keys = settings.childGroups();
QStringList::Iterator it = keys.begin();
@@ -336,6 +345,14 @@ bool QgsManageConnectionsDialog::populateConnections()
return false;
}
break;
+ case GeoNode:
+ if ( root.tagName() != QLatin1String( "qgsGeoNodeConnections" ) )
+ {
+ QMessageBox::information( this, tr( "Loading connections" ),
+ tr( "The file is not a GeoNode connections exchange file." ) );
+ return false;
+ }
+ break;
}
QDomElement child = root.firstChildElement();
@@ -580,6 +597,31 @@ QDomDocument QgsManageConnectionsDialog::saveDb2Connections( const QStringList &
return doc;
}
+QDomDocument QgsManageConnectionsDialog::saveGeonodeConnections( const QStringList &connections )
+{
+ QDomDocument doc( QStringLiteral( "connections" ) );
+ QDomElement root = doc.createElement( QStringLiteral( "qgsGeoNodeConnections" ) );
+ root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0" ) );
+ doc.appendChild( root );
+
+ QgsSettings settings;
+ QString path;
+ for ( int i = 0; i < connections.count(); ++i )
+ {
+ path = QStringLiteral( "/qgis/connections-geonode/" );
+ QDomElement el = doc.createElement( QStringLiteral( "geonode" ) );
+ el.setAttribute( QStringLiteral( "name" ), connections[ i ] );
+ el.setAttribute( QStringLiteral( "url" ), settings.value( path + connections[ i ] + "/url", "" ).toString() );
+
+ path = QStringLiteral( "/qgis/GeoNode/" );
+ el.setAttribute( QStringLiteral( "username" ), settings.value( path + connections[ i ] + "/username", "" ).toString() );
+ el.setAttribute( QStringLiteral( "password" ), settings.value( path + connections[ i ] + "/password", "" ).toString() );
+ root.appendChild( el );
+ }
+
+ return doc;
+}
+
void QgsManageConnectionsDialog::loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service )
{
QDomElement root = doc.documentElement();
@@ -1103,6 +1145,87 @@ void QgsManageConnectionsDialog::loadDb2Connections( const QDomDocument &doc, co
child = child.nextSiblingElement();
}
}
+
+void QgsManageConnectionsDialog::loadGeonodeConnections( const QDomDocument &doc, const QStringList &items )
+{
+ QDomElement root = doc.documentElement();
+ if ( root.tagName() != QLatin1String( "qgsGeoNodeConnections" ) )
+ {
+ QMessageBox::information( this, tr( "Loading connections" ),
+ tr( "The file is not a GeoNode connections exchange file." ) );
+ return;
+ }
+
+ QString connectionName;
+ QgsSettings settings;
+ settings.beginGroup( QStringLiteral( "/qgis/connections-geonode" ) );
+ QStringList keys = settings.childGroups();
+ settings.endGroup();
+ QDomElement child = root.firstChildElement();
+ bool prompt = true;
+ bool overwrite = true;
+
+ while ( !child.isNull() )
+ {
+ connectionName = child.attribute( QStringLiteral( "name" ) );
+ if ( !items.contains( connectionName ) )
+ {
+ child = child.nextSiblingElement();
+ continue;
+ }
+
+ // check for duplicates
+ if ( keys.contains( connectionName ) && prompt )
+ {
+ int res = QMessageBox::warning( this,
+ tr( "Loading connections" ),
+ tr( "Connection with name '%1' already exists. Overwrite?" )
+ .arg( connectionName ),
+ QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel );
+
+ switch ( res )
+ {
+ case QMessageBox::Cancel:
+ return;
+ case QMessageBox::No:
+ child = child.nextSiblingElement();
+ continue;
+ case QMessageBox::Yes:
+ overwrite = true;
+ break;
+ case QMessageBox::YesToAll:
+ prompt = false;
+ overwrite = true;
+ break;
+ case QMessageBox::NoToAll:
+ prompt = false;
+ overwrite = false;
+ break;
+ }
+ }
+
+ if ( keys.contains( connectionName ) && !overwrite )
+ {
+ child = child.nextSiblingElement();
+ continue;
+ }
+
+ // no dups detected or overwrite is allowed
+ settings.beginGroup( QStringLiteral( "/qgis/connections-geonode" ) );
+ settings.setValue( QString( '/' + connectionName + "/url" ), child.attribute( QStringLiteral( "url" ) ) );
+ settings.endGroup();
+
+ if ( !child.attribute( QStringLiteral( "username" ) ).isEmpty() )
+ {
+ settings.beginGroup( "/qgis/GeoNode/" + connectionName );
+ settings.setValue( QStringLiteral( "/username" ), child.attribute( QStringLiteral( "username" ) ) );
+ settings.setValue( QStringLiteral( "/password" ), child.attribute( QStringLiteral( "password" ) ) );
+ settings.endGroup();
+ }
+ child = child.nextSiblingElement();
+ }
+}
+
void QgsManageConnectionsDialog::selectAll()
{
listConnections->selectAll();
diff --git a/src/gui/qgsmanageconnectionsdialog.h b/src/gui/qgsmanageconnectionsdialog.h
index 835b0ccc4b0..36f907223d8 100644
--- a/src/gui/qgsmanageconnectionsdialog.h
+++ b/src/gui/qgsmanageconnectionsdialog.h
@@ -47,6 +47,7 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
DB2,
WCS,
Oracle,
+ GeoNode
};
// constructor
@@ -69,6 +70,7 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
QDomDocument saveMssqlConnections( const QStringList &connections );
QDomDocument saveOracleConnections( const QStringList &connections );
QDomDocument saveDb2Connections( const QStringList &connections );
+ QDomDocument saveGeonodeConnections( const QStringList &connections );
void loadOWSConnections( const QDomDocument &doc, const QStringList &items, const QString &service );
void loadWfsConnections( const QDomDocument &doc, const QStringList &items );
@@ -76,6 +78,7 @@ class GUI_EXPORT QgsManageConnectionsDialog : public QDialog, private Ui::QgsMan
void loadMssqlConnections( const QDomDocument &doc, const QStringList &items );
void loadOracleConnections( const QDomDocument &doc, const QStringList &items );
void loadDb2Connections( const QDomDocument &doc, const QStringList &items );
+ void loadGeonodeConnections( const QDomDocument &doc, const QStringList &items );
QString mFileName;
Mode mDialogMode;
diff --git a/src/gui/qgsnewhttpconnection.cpp b/src/gui/qgsnewhttpconnection.cpp
index 3795080a029..c9fc668aeef 100644
--- a/src/gui/qgsnewhttpconnection.cpp
+++ b/src/gui/qgsnewhttpconnection.cpp
@@ -171,6 +171,7 @@ QgsNewHttpConnection::QgsNewHttpConnection(
if ( mBaseKey != QLatin1String( "qgis/connections-wfs/" ) )
{
+ lblVersion->setVisible( false );
cmbVersion->setVisible( false );
mGroupBox->layout()->removeWidget( cmbVersion );
lblMaxNumFeatures->setVisible( false );
diff --git a/src/providers/ows/CMakeLists.txt b/src/providers/ows/CMakeLists.txt
index da2deac23c2..e43c2cf3c48 100644
--- a/src/providers/ows/CMakeLists.txt
+++ b/src/providers/ows/CMakeLists.txt
@@ -1,21 +1,25 @@
SET(OWS_SRCS
qgsowsprovider.cpp
qgsowsdataitems.cpp
-)
+ qgsgeonodedataitems.cpp)
SET(OWS_MOC_HDRS
qgsowsprovider.h
qgsowsdataitems.h
+ qgsgeonodedataitems.h
)
INCLUDE_DIRECTORIES (
+ ${CMAKE_SOURCE_DIR}/src/gui/geonode
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry
+ ${CMAKE_SOURCE_DIR}/src/core/geonode
${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/gui
${CMAKE_SOURCE_DIR}/src/gui/auth
+ ${CMAKE_BINARY_DIR}/src/app
${CMAKE_BINARY_DIR}/src/core
${CMAKE_BINARY_DIR}/src/gui
${CMAKE_BINARY_DIR}/src/ui
@@ -30,6 +34,8 @@ ADD_LIBRARY (owsprovider MODULE ${OWS_SRCS} ${OWS_MOC_SRCS})
TARGET_LINK_LIBRARIES (owsprovider
qgis_core
+ qgis_gui
+ qgis_app
)
IF (WITH_GUI)
diff --git a/src/providers/ows/qgsgeonodedataitems.cpp b/src/providers/ows/qgsgeonodedataitems.cpp
new file mode 100644
index 00000000000..ec9c565fbc1
--- /dev/null
+++ b/src/providers/ows/qgsgeonodedataitems.cpp
@@ -0,0 +1,273 @@
+/***************************************************************************
+ qgsgeonodedataitems.cpp
+ ---------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************
+ * *
+ * 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 "qgsowsdataitems.h"
+#include "qgslogger.h"
+#include "qgsgeonodedataitems.h"
+#include "qgsproviderregistry.h"
+#include "qgsnewhttpconnection.h"
+#include "qgsgeonodenewconnection.h"
+#include "qgsgeonoderequest.h"
+
+typedef QList dataItemProviders_t();
+
+QgsGeoNodeConnectionItem::QgsGeoNodeConnectionItem( QgsDataItem *parent, QString name, QString path, QgsGeoNodeConnection *conn )
+ : QgsDataCollectionItem( parent, name, path )
+ , mGeoNodeName( parent->name() )
+ , mUri( conn->uri().uri() )
+ , mConnection( conn )
+{
+ mIconName = QStringLiteral( "mIconConnect.png" );
+}
+
+QVector QgsGeoNodeConnectionItem::createChildren()
+{
+ QVector services;
+
+ QString url = mConnection->uri().param( "url" );
+ QgsGeoNodeRequest geonodeRequest( url, true );
+
+ QStringList wmsUrl = geonodeRequest.serviceUrls( QStringLiteral( "WMS" ) );
+ QStringList wfsUrl = geonodeRequest.serviceUrls( QStringLiteral( "WFS" ) );
+ QStringList xyzUrl = geonodeRequest.serviceUrls( QStringLiteral( "XYZ" ) );
+
+ if ( !wmsUrl.isEmpty() )
+ {
+ QString path = mPath + "/wms";
+ QgsDataItem *service = new QgsGeoNodeServiceItem( this, mConnection, QStringLiteral( "WMS" ), path );
+ services.append( service );
+ }
+
+ if ( !wfsUrl.isEmpty() )
+ {
+ QString path = mPath + "/wfs";
+ QgsDataItem *service = new QgsGeoNodeServiceItem( this, mConnection, QStringLiteral( "WFS" ), path );
+ services.append( service );
+ }
+
+ if ( !xyzUrl.isEmpty() )
+ {
+ QString path = mPath + "/xyz";
+ QgsDataItem *service = new QgsGeoNodeServiceItem( this, mConnection, QStringLiteral( "XYZ" ), path );
+ services.append( service );
+ }
+
+ return services;
+}
+
+QList QgsGeoNodeConnectionItem::actions()
+{
+ QAction *actionEdit = new QAction( tr( "Edit..." ), this );
+ QAction *actionDelete = new QAction( tr( "Delete" ), this );
+ connect( actionEdit, &QAction::triggered, this, &QgsGeoNodeConnectionItem::editConnection );
+ connect( actionDelete, &QAction::triggered, this, &QgsGeoNodeConnectionItem::deleteConnection );
+ return QList() << actionEdit << actionDelete;
+}
+
+void QgsGeoNodeConnectionItem::editConnection()
+{
+ QgsGeoNodeNewConnection *nc = new QgsGeoNodeNewConnection( nullptr, mConnection->connName() );
+ nc->setWindowTitle( tr( "Modify GeoNode connection" ) );
+
+ if ( nc->exec() )
+ {
+ // the parent should be updated
+ mParent->refresh();
+ }
+}
+
+QgsGeoNodeServiceItem::QgsGeoNodeServiceItem( QgsDataItem *parent, QgsGeoNodeConnection *conn, QString serviceName, QString path )
+ : QgsDataCollectionItem( parent, serviceName, path )
+ , mName( conn->connName() )
+ , mServiceName( serviceName )
+ , mConnection( conn )
+{
+ if ( serviceName == QStringLiteral( "WMS" ) || serviceName == QStringLiteral( "XYZ" ) )
+ {
+ mIconName = QStringLiteral( "mIconWms.svg" );
+ }
+ else
+ {
+ mIconName = QStringLiteral( "mIconWfs.svg" );
+ }
+}
+
+QVector QgsGeoNodeServiceItem::createChildren()
+{
+ QVector children;
+ QHash serviceItems; // service/provider key
+
+ int layerCount = 0;
+ // Try to open with service provider
+ bool skipProvider = false;
+
+ QgsGeoNodeConnectionItem *parentItem = dynamic_cast( mParent );
+ QString pathPrefix = parentItem->mGeoNodeName.toLower() + ":/";
+
+ while ( !skipProvider )
+ {
+ const QString &key = mServiceName != QString( "WFS" ) ? QString( "WMS" ).toLower() : mServiceName;
+ std::unique_ptr< QLibrary > library( QgsProviderRegistry::instance()->createProviderLibrary( key ) );
+ if ( !library )
+ {
+ skipProvider = true;
+ continue;
+ }
+
+ dataItemProviders_t *dataItemProvidersFn = reinterpret_cast< dataItemProviders_t * >( cast_to_fptr( library->resolve( "dataItemProviders" ) ) );
+ dataItem_t *dItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) );
+ if ( !dItem && !dataItemProvidersFn )
+ {
+ skipProvider = true;
+ continue;
+ }
+
+ QString path = pathPrefix + mName;
+
+ QVector items;
+ Q_FOREACH ( QgsDataItemProvider *pr, dataItemProvidersFn() )
+ {
+ items = pr->name().startsWith( mServiceName ) ? pr->createDataItems( path, this ) : items;
+ if ( !items.isEmpty() )
+ {
+ break;
+ }
+ }
+
+ if ( items.isEmpty() )
+ {
+ skipProvider = true;
+ continue;
+ }
+
+ if ( mServiceName == QStringLiteral( "XYZ" ) )
+ {
+ return items;
+ }
+
+ Q_FOREACH ( QgsDataItem *item, items )
+ {
+ item->populate( true ); // populate in foreground - this is already run in a thread
+
+ layerCount += item->rowCount();
+ if ( item->rowCount() > 0 )
+ {
+ serviceItems.insert( item, key );
+ }
+ else
+ {
+ //delete item;
+ }
+ }
+
+ skipProvider = true;
+ }
+
+ Q_FOREACH ( QgsDataItem *item, serviceItems.keys() )
+ {
+ QString providerKey = serviceItems.value( item );
+
+ // Add layers directly to service item
+ Q_FOREACH ( QgsDataItem *subItem, item->children() )
+ {
+ if ( subItem->path().endsWith( QString( "error" ) ) )
+ {
+ continue;
+ }
+ item->removeChildItem( subItem );
+ subItem->setParent( this );
+ replacePath( subItem, providerKey.toLower() + ":/", pathPrefix );
+ children.append( subItem );
+ }
+
+ delete item;
+ }
+
+ return children;
+}
+
+// reset path recursively
+void QgsGeoNodeServiceItem::replacePath( QgsDataItem *item, QString before, QString after )
+{
+ item->setPath( item->path().replace( before, after ) );
+ Q_FOREACH ( QgsDataItem *subItem, item->children() )
+ {
+ replacePath( subItem, before, after );
+ }
+}
+
+QgsGeoNodeRootItem::QgsGeoNodeRootItem( QgsDataItem *parent, QString name, QString path ) : QgsDataCollectionItem( parent, name, path )
+{
+ mCapabilities |= Fast;
+ {
+ mIconName = QStringLiteral( "mIconGeonode.svg" );
+ }
+ populate();
+}
+
+QVector QgsGeoNodeRootItem::createChildren()
+{
+ QVector connections;
+
+ Q_FOREACH ( const QString &connName, QgsGeoNodeConnection::connectionList() )
+ {
+ QgsGeoNodeConnection *connection = nullptr;
+ connection = new QgsGeoNodeConnection( connName );
+ QString path = mPath + "/" + connName;
+ QgsDataItem *conn = new QgsGeoNodeConnectionItem( this, connName, path, connection );
+ connections.append( conn );
+ }
+ return connections;
+}
+
+QList QgsGeoNodeRootItem::actions()
+{
+ QAction *actionNew = new QAction( tr( "New Connection..." ), this );
+ connect( actionNew, &QAction::triggered, this, &QgsGeoNodeRootItem::newConnection );
+ return QList() << actionNew;
+}
+
+void QgsGeoNodeRootItem::newConnection()
+{
+ QgsGeoNodeNewConnection *nc = new QgsGeoNodeNewConnection( nullptr );
+
+ if ( nc->exec() )
+ {
+ refresh();
+ }
+}
+
+
+QgsDataItem *QgsGeoNodeDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
+{
+ QgsDebugMsg( "thePath = " + path );
+ if ( path.isEmpty() )
+ {
+ return new QgsGeoNodeRootItem( parentItem, QStringLiteral( "GeoNode" ), QStringLiteral( "geonode:" ) );
+ }
+
+ // path schema: geonode:/connection name (used by OWS)
+ if ( path.startsWith( QLatin1String( "geonode:/" ) ) )
+ {
+ QString connectionName = path.split( '/' ).last();
+ if ( QgsGeoNodeConnection::connectionList().contains( connectionName ) )
+ {
+ QgsGeoNodeConnection *connection = new QgsGeoNodeConnection( connectionName );
+ return new QgsGeoNodeConnectionItem( parentItem, QStringLiteral( "GeoNode" ), path, connection );
+ }
+ }
+
+ return nullptr;
+}
diff --git a/src/providers/ows/qgsgeonodedataitems.h b/src/providers/ows/qgsgeonodedataitems.h
new file mode 100644
index 00000000000..7d51b128f05
--- /dev/null
+++ b/src/providers/ows/qgsgeonodedataitems.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ qgsgeonodedataitems.h
+ ---------------------
+ begin : Feb 2017
+ copyright : (C) 2017 by Muhammad Yarjuna Rohmat, Ismail Sunni
+ email : rohmat at kartoza dot com, ismail at kartoza dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSGEONODEDATAITEMS_H
+#define QGSGEONODEDATAITEMS_H
+
+#include "qgsdataitem.h"
+#include "qgsdataitemprovider.h"
+#include "qgsdataprovider.h"
+#include "qgsdatasourceuri.h"
+#include "qgsgeonodeconnection.h"
+
+class QgsGeoNodeConnectionItem : public QgsDataCollectionItem
+{
+ Q_OBJECT
+ public:
+ QgsGeoNodeConnectionItem( QgsDataItem *parent, QString name, QString path, QgsGeoNodeConnection *conn );
+ QVector createChildren() override;
+ virtual QList actions() override;
+
+ QString mGeoNodeName;
+
+ private:
+ void editConnection();
+ void deleteConnection()
+ {
+ QgsGeoNodeConnection::deleteConnection( mParent->name() );
+ mParent->refresh();
+ };
+
+ QString mUri;
+ QgsGeoNodeConnection *mConnection = nullptr;
+};
+
+class QgsGeoNodeServiceItem : public QgsDataCollectionItem
+{
+ Q_OBJECT
+ public:
+ QgsGeoNodeServiceItem( QgsDataItem *parent, QgsGeoNodeConnection *conn, QString serviceName, QString path );
+ QVector createChildren() override;
+
+ private:
+ void replacePath( QgsDataItem *item, QString before, QString after );
+ QString mName;
+ QString mServiceName;
+ QString mUri;
+ QgsGeoNodeConnection *mConnection = nullptr;
+};
+
+class QgsGeoNodeRootItem : public QgsDataCollectionItem
+{
+ Q_OBJECT
+ public:
+ QgsGeoNodeRootItem( QgsDataItem *parent, QString name, QString path );
+
+ QVector createChildren() override;
+
+ virtual QList actions() override;
+
+ private slots:
+ void newConnection();
+};
+
+//! Provider for Geonode root data item
+class QgsGeoNodeDataItemProvider : public QgsDataItemProvider
+{
+ public:
+ virtual QString name() override { return QStringLiteral( "GeoNode" ); }
+
+ virtual int capabilities() override { return QgsDataProvider::Net; }
+
+ virtual QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
+};
+
+#endif //QGSGEONODEDATAITEMS_H
diff --git a/src/providers/ows/qgsowsdataitems.cpp b/src/providers/ows/qgsowsdataitems.cpp
index c58302c79c4..1ed5b2b018a 100644
--- a/src/providers/ows/qgsowsdataitems.cpp
+++ b/src/providers/ows/qgsowsdataitems.cpp
@@ -23,6 +23,9 @@
#include "qgsnewhttpconnection.h"
#include "qgsowssourceselect.h"
#endif
+#include "qgsgeonodeconnection.h"
+#include "qgsgeonodenewconnection.h"
+#include "qgsgeonodedataitems.h"
#include "qgsapplication.h"
@@ -259,12 +262,14 @@ void QgsOWSRootItem::newConnection()
static QStringList extensions = QStringList();
static QStringList wildcards = QStringList();
-QGISEXTERN int dataCapabilities()
+QGISEXTERN QList dataItemProviders()
{
- return QgsDataProvider::Net;
+ return QList()
+ << new QgsOwsDataItemProvider
+ << new QgsGeoNodeDataItemProvider;
}
-QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
+QgsDataItem *QgsOwsDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
{
if ( path.isEmpty() )
{
@@ -272,13 +277,3 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
}
return nullptr;
}
-
-//QGISEXTERN QgsOWSSourceSelect * selectWidget( QWidget * parent, Qt::WindowFlags fl )
-QGISEXTERN QDialog *selectWidget( QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
-{
- Q_UNUSED( parent );
- Q_UNUSED( fl );
- Q_UNUSED( widgetMode );
- //return new QgsOWSSourceSelect( parent, fl, widgetMode );
- return nullptr;
-}
diff --git a/src/providers/ows/qgsowsdataitems.h b/src/providers/ows/qgsowsdataitems.h
index 05a07653dc0..ac99d861150 100644
--- a/src/providers/ows/qgsowsdataitems.h
+++ b/src/providers/ows/qgsowsdataitems.h
@@ -16,7 +16,11 @@
#define QGSOWSDATAITEMS_H
#include "qgsdataitem.h"
+#include "qgsdataitemprovider.h"
+#include "qgsdataprovider.h"
#include "qgsdatasourceuri.h"
+#include "qgsgeonodeconnection.h"
+
class QgsOWSConnectionItem : public QgsDataCollectionItem
{
Q_OBJECT
@@ -63,4 +67,15 @@ class QgsOWSRootItem : public QgsDataCollectionItem
#endif
};
+//! Provider for ows root data item
+class QgsOwsDataItemProvider : public QgsDataItemProvider
+{
+ public:
+ virtual QString name() override { return QStringLiteral( "OWS" ); }
+
+ virtual int capabilities() override { return QgsDataProvider::Net; }
+
+ virtual QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
+};
+
#endif // QGSOWSDATAITEMS_H
diff --git a/src/providers/wfs/CMakeLists.txt b/src/providers/wfs/CMakeLists.txt
index 328a118ffdb..370b808b6e5 100644
--- a/src/providers/wfs/CMakeLists.txt
+++ b/src/providers/wfs/CMakeLists.txt
@@ -49,6 +49,7 @@ INCLUDE_DIRECTORIES (
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/symbology # needed by qgsvectorfilewriter.h
+ ${CMAKE_SOURCE_DIR}/src/core/geonode
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/gui
${CMAKE_SOURCE_DIR}/src/gui/auth
diff --git a/src/providers/wfs/qgswfsdataitems.cpp b/src/providers/wfs/qgswfsdataitems.cpp
index e04fa463179..cfcbdce2111 100644
--- a/src/providers/wfs/qgswfsdataitems.cpp
+++ b/src/providers/wfs/qgswfsdataitems.cpp
@@ -12,6 +12,7 @@
* (at your option) any later version. *
* *
***************************************************************************/
+#include "qgsdataitemprovider.h"
#include "qgsdataprovider.h"
#include "qgslogger.h"
#include "qgswfsconstants.h"
@@ -20,6 +21,8 @@
#include "qgswfsdataitems.h"
#include "qgswfsdatasourceuri.h"
#include "qgssettings.h"
+#include "qgsgeonodeconnection.h"
+#include "qgsgeonoderequest.h"
#ifdef HAVE_GUI
#include "qgsnewhttpconnection.h"
@@ -192,6 +195,84 @@ void QgsWfsRootItem::newConnection()
}
#endif
+
+//////
+
+
+QgsDataItem *QgsWfsDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
+{
+ QgsDebugMsg( "thePath = " + path );
+ if ( path.isEmpty() )
+ {
+ return new QgsWfsRootItem( parentItem, QStringLiteral( "WFS" ), QStringLiteral( "wfs:" ) );
+ }
+
+ // path schema: wfs:/connection name (used by OWS)
+ if ( path.startsWith( QLatin1String( "wfs:/" ) ) )
+ {
+ QString connectionName = path.split( '/' ).last();
+ if ( QgsWfsConnection::connectionList().contains( connectionName ) )
+ {
+ QgsWfsConnection connection( connectionName );
+ return new QgsWfsConnectionItem( parentItem, QStringLiteral( "WFS" ), path, connection.uri().uri() );
+ }
+ }
+ else if ( path.startsWith( QLatin1String( "geonode:/" ) ) )
+ {
+ QString connectionName = path.split( '/' ).last();
+ if ( QgsGeoNodeConnection::connectionList().contains( connectionName ) )
+ {
+ QgsGeoNodeConnection connection( connectionName );
+
+ QString url = connection.uri().param( "url" );
+ QgsGeoNodeRequest geonodeRequest( url, true );
+
+ QgsWFSDataSourceURI sourceUri( geonodeRequest.serviceUrls( QStringLiteral( "WFS" ) )[0] );
+
+ QgsDebugMsg( QString( "WFS full uri: '%1'." ).arg( QString( sourceUri.uri() ) ) );
+
+ return new QgsWfsConnectionItem( parentItem, QStringLiteral( "WFS" ), path, sourceUri.uri() );
+ }
+ }
+
+ return nullptr;
+}
+
+QVector QgsWfsDataItemProvider::createDataItems( const QString &path, QgsDataItem *parentItem )
+{
+ QVector items;
+ if ( path.startsWith( QLatin1String( "geonode:/" ) ) )
+ {
+ QString connectionName = path.split( '/' ).last();
+ if ( QgsGeoNodeConnection::connectionList().contains( connectionName ) )
+ {
+ QgsGeoNodeConnection connection( connectionName );
+
+ QString url = connection.uri().param( "url" );
+ QgsGeoNodeRequest geonodeRequest( url, true );
+
+ QStringList encodedUris( geonodeRequest.serviceUrls( QStringLiteral( "WFS" ) ) );
+
+ if ( !encodedUris.isEmpty() )
+ {
+ Q_FOREACH ( QString encodedUri, encodedUris )
+ {
+ QgsWFSDataSourceURI uri( encodedUri );
+ QgsDebugMsg( QString( "WFS full uri: '%1'." ).arg( QString( uri.uri() ) ) );
+
+ QgsDataItem *item = new QgsWfsConnectionItem( parentItem, QStringLiteral( "WFS" ), path, uri.uri() );
+ if ( item )
+ {
+ items.append( item );
+ }
+ }
+ }
+ }
+ }
+
+ return items;
+}
+
// ---------------------------------------------------------------------------
#ifdef HAVE_GUI
@@ -227,3 +308,9 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
return nullptr;
}
+
+QGISEXTERN QList dataItemProviders()
+{
+ return QList()
+ << new QgsWfsDataItemProvider;
+}
diff --git a/src/providers/wfs/qgswfsdataitems.h b/src/providers/wfs/qgswfsdataitems.h
index 286cef47869..85ce3cba506 100644
--- a/src/providers/wfs/qgswfsdataitems.h
+++ b/src/providers/wfs/qgswfsdataitems.h
@@ -16,6 +16,8 @@
#define QGSWFSDATAITEMS_H
#include "qgsdataitem.h"
+#include "qgsdataitemprovider.h"
+#include "qgsdataprovider.h"
#include "qgsdatasourceuri.h"
#include "qgswfscapabilities.h"
@@ -80,4 +82,18 @@ class QgsWfsLayerItem : public QgsLayerItem
};
+//! Provider for WFS root data item
+class QgsWfsDataItemProvider : public QgsDataItemProvider
+{
+ public:
+ virtual QString name() override { return QStringLiteral( "WFS" ); }
+
+ virtual int capabilities() override { return QgsDataProvider::Net; }
+
+ virtual QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
+
+ virtual QVector createDataItems( const QString &path, QgsDataItem *parentItem ) override;
+};
+
+
#endif // QGSWFSDATAITEMS_H
diff --git a/src/providers/wms/CMakeLists.txt b/src/providers/wms/CMakeLists.txt
index 0a00cecd006..98a88488867 100644
--- a/src/providers/wms/CMakeLists.txt
+++ b/src/providers/wms/CMakeLists.txt
@@ -38,6 +38,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry
+ ${CMAKE_SOURCE_DIR}/src/core/geonode
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/gui
diff --git a/src/providers/wms/qgswmsdataitems.cpp b/src/providers/wms/qgswmsdataitems.cpp
index d44c11150e8..fee211cb4d3 100644
--- a/src/providers/wms/qgswmsdataitems.cpp
+++ b/src/providers/wms/qgswmsdataitems.cpp
@@ -28,6 +28,9 @@
#include "qgstilescalewidget.h"
#include "qgsxyzconnectiondialog.h"
#endif
+#include "qgsgeonodeconnection.h"
+#include "qgsgeonoderequest.h"
+#include "qgssettings.h"
#include
@@ -565,3 +568,89 @@ void QgsXyzLayerItem::deleteConnection()
mParent->refresh();
}
#endif
+
+// ---------------------------------------------------------------------------
+
+
+QVector QgsWmsDataItemProvider::createDataItems( const QString &path, QgsDataItem *parentItem )
+{
+ QVector items;
+ if ( path.startsWith( QLatin1String( "geonode:/" ) ) )
+ {
+ QString connectionName = path.split( '/' ).last();
+ if ( QgsGeoNodeConnection::connectionList().contains( connectionName ) )
+ {
+ QgsGeoNodeConnection connection( connectionName );
+
+ QString url = connection.uri().param( "url" );
+ QgsGeoNodeRequest geonodeRequest( url, true );
+
+ QStringList encodedUris( geonodeRequest.serviceUrls( QStringLiteral( "WMS" ) ) );
+
+ if ( !encodedUris.isEmpty() )
+ {
+ Q_FOREACH ( QString encodedUri, encodedUris )
+ {
+ QgsDebugMsg( encodedUri );
+ QgsDataSourceUri uri;
+ QgsSettings settings;
+ QString key( connection.pathGeoNodeConnection() + "/" + connectionName );
+
+ QString dpiMode = settings.value( key + "/wms/dpiMode", "all", QgsSettings::Providers ).toString();
+ uri.setParam( QStringLiteral( "url" ), encodedUri );
+ if ( !dpiMode.isEmpty() )
+ {
+ uri.setParam( QStringLiteral( "dpiMode" ), dpiMode );
+ }
+
+ QgsDebugMsg( QString( "WMS full uri: '%1'." ).arg( QString( uri.encodedUri() ) ) );
+
+ QgsDataItem *item = new QgsWMSConnectionItem( parentItem, QStringLiteral( "WMS" ), path, uri.encodedUri() );
+ if ( item )
+ {
+ items.append( item );
+ }
+ }
+ }
+ }
+ }
+
+ return items;
+}
+
+QVector QgsXyzTileDataItemProvider::createDataItems( const QString &path, QgsDataItem *parentItem )
+{
+ QVector items;
+ if ( path.startsWith( QLatin1String( "geonode:/" ) ) )
+ {
+ QString connectionName = path.split( '/' ).last();
+ if ( QgsGeoNodeConnection::connectionList().contains( connectionName ) )
+ {
+ QgsGeoNodeConnection connection( connectionName );
+
+ QString url = connection.uri().param( "url" );
+ QgsGeoNodeRequest geonodeRequest( url, true );
+
+ QgsStringMap urlData( geonodeRequest.serviceUrlData( QStringLiteral( "XYZ" ) ) );
+
+ if ( !urlData.isEmpty() )
+ {
+ Q_FOREACH ( QString layerName, urlData.keys() )
+ {
+ QgsDebugMsg( urlData[ layerName] );
+ QgsDataSourceUri uri;
+ uri.setParam( QStringLiteral( "type" ), QStringLiteral( "xyz" ) );
+ uri.setParam( QStringLiteral( "url" ), urlData[ layerName ] );
+
+ QgsDataItem *item = new QgsXyzLayerItem( parentItem, layerName, path, uri.encodedUri() );
+ if ( item )
+ {
+ items.append( item );
+ }
+ }
+ }
+ }
+ }
+
+ return items;
+}
diff --git a/src/providers/wms/qgswmsdataitems.h b/src/providers/wms/qgswmsdataitems.h
index facd17c9fdb..9293b639401 100644
--- a/src/providers/wms/qgswmsdataitems.h
+++ b/src/providers/wms/qgswmsdataitems.h
@@ -19,6 +19,7 @@
#include "qgsdataitemprovider.h"
#include "qgsdatasourceuri.h"
#include "qgswmsprovider.h"
+#include "qgsgeonodeconnection.h"
class QgsWmsCapabilitiesDownload;
@@ -122,6 +123,8 @@ class QgsWmsDataItemProvider : public QgsDataItemProvider
virtual int capabilities() override { return QgsDataProvider::Net; }
virtual QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
+
+ virtual QVector createDataItems( const QString &path, QgsDataItem *parentItem ) override;
};
@@ -177,6 +180,8 @@ class QgsXyzTileDataItemProvider : public QgsDataItemProvider
return new QgsXyzTileRootItem( parentItem, QStringLiteral( "XYZ Tiles" ), QStringLiteral( "xyz:" ) );
return nullptr;
}
+
+ virtual QVector createDataItems( const QString &path, QgsDataItem *parentItem ) override;
};
diff --git a/src/ui/qgsgeonodesourceselectbase.ui b/src/ui/qgsgeonodesourceselectbase.ui
new file mode 100644
index 00000000000..e931c65f4fe
--- /dev/null
+++ b/src/ui/qgsgeonodesourceselectbase.ui
@@ -0,0 +1,217 @@
+
+
+ QgsGeonodeSourceSelectBase
+
+
+
+ 0
+ 0
+ 592
+ 439
+
+
+
+ Add Geonode Layer
+
+
+ -
+
+
+ Geonode connections
+
+
+
-
+
+
+ -
+
+
-
+
+
+ false
+
+
+ Connect to selected service
+
+
+ C&onnect
+
+
+
+ -
+
+
+ Create a new service connection
+
+
+ &New
+
+
+
+ -
+
+
+ false
+
+
+ Edit selected service connection
+
+
+ Edit
+
+
+
+ -
+
+
+ false
+
+
+ Remove connection to selected service
+
+
+ Remove
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Expanding
+
+
+
+ 171
+ 30
+
+
+
+
+ -
+
+
+ Load connections from file
+
+
+ Load
+
+
+
+ -
+
+
+ Save connections to file
+
+
+ Save
+
+
+
+
+
+
+
+
+ -
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ true
+
+
+ QAbstractItemView::ExtendedSelection
+
+
+ true
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ Use title for layer name
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+ Filter
+
+
+ lineFilter
+
+
+
+ -
+
+
+ true
+
+
+ Display WFS FeatureTypes containing this word in the title, name or abstract
+
+
+ Display WFS FeatureTypes containing this word in the title, name or abstract
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close|QDialogButtonBox::Help
+
+
+
+
+
+
+ cmbConnections
+ btnConnect
+ btnNew
+ btnEdit
+ btnDelete
+ btnLoad
+ btnSave
+ lineFilter
+ treeView
+ cbxUseTitleLayerName
+
+
+
+
diff --git a/src/ui/qgsnewgeonodeconnectionbase.ui b/src/ui/qgsnewgeonodeconnectionbase.ui
new file mode 100644
index 00000000000..437f7f8201a
--- /dev/null
+++ b/src/ui/qgsnewgeonodeconnectionbase.ui
@@ -0,0 +1,355 @@
+
+
+ QgsNewGeoNodeConnectionBase
+
+
+
+ 0
+ 0
+ 448
+ 475
+
+
+
+ Create a new Geonode connection
+
+
+ true
+
+
+ true
+
+
+ -
+
+
+ Connection details
+
+
+
-
+
+
+ WFS Options
+
+
+
-
+
+
+ Version
+
+
+
+ -
+
+
+ <html><head/><body><p>Select protocol version</p></body></html>
+
+
+
+ -
+
+
+ Max. number of features
+
+
+
+ -
+
+
+ <html><head/><body><p>Enter a number to limit the maximum number of features retrieved in a single GetFeature request. If let to empty, server default will apply.</p></body></html>
+
+
+
+
+
+
+ -
+
+
+ &Test Connection
+
+
+
+ -
+
+
+ Ignore axis orientation (WFS 1.1/WFS 2.0)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 0
+
+
+
+ Authentication
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ If the service requires basic authentication, enter a user name and optional password
+
+
+ Qt::PlainText
+
+
+ true
+
+
+
+ -
+
+
+ &User name
+
+
+ txtUserName
+
+
+
+ -
+
+
+ -
+
+
+ Password
+
+
+ txtPassword
+
+
+
+ -
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+ -
+
+
+ Ignore axis orientation (WMS 1.3/WMTS)
+
+
+
+ -
+
+
+ Invert axis orientation
+
+
+
+ -
+
+
+ WMS Options
+
+
+
-
+
+
+ -
+
+
+ Referer
+
+
+ txtReferer
+
+
+
+ -
+
+
+ -
+
+
+ DPI-Mode
+
+
+ cmbDpiMode
+
+
+
+
+
+
+ -
+
+
+ Invert axis orientation
+
+
+
+ -
+
+
+ Ignore GetFeatureInfo URI reported in capabilities
+
+
+
+ -
+
+
-
+
+
+ Name
+
+
+ true
+
+
+ 5
+
+
+ txtName
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Name of the new connection
+
+
+ true
+
+
+
+ -
+
+
+ URL
+
+
+ 5
+
+
+ txtUrl
+
+
+
+ -
+
+
+ HTTP address of the Web Map Server
+
+
+
+
+
+ -
+
+
+ Ignore GetMap/GetTile URI reported in capabilities
+
+
+
+ -
+
+
+ Smooth pixmap transform
+
+
+
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ QgsPasswordLineEdit
+ QLineEdit
+
+
+
+
+ tabAuth
+ txtUserName
+ txtPassword
+
+
+
+
+ buttonBox
+ accepted()
+ QgsNewGeoNodeConnectionBase
+ accept()
+
+
+ 421
+ 453
+
+
+ 430
+ 98
+
+
+
+
+ buttonBox
+ rejected()
+ QgsNewGeoNodeConnectionBase
+ reject()
+
+
+ 330
+ 453
+
+
+ 426
+ 38
+
+
+
+
+
diff --git a/src/ui/qgsnewhttpconnectionbase.ui b/src/ui/qgsnewhttpconnectionbase.ui
index 1e1adad5106..d7b895be73a 100644
--- a/src/ui/qgsnewhttpconnectionbase.ui
+++ b/src/ui/qgsnewhttpconnectionbase.ui
@@ -229,7 +229,7 @@
-
-
+
Version
diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt
index de87bf719f2..b9117ffa3a3 100755
--- a/tests/src/core/CMakeLists.txt
+++ b/tests/src/core/CMakeLists.txt
@@ -14,6 +14,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/layout
+ ${CMAKE_SOURCE_DIR}/src/core/geonode
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/effects
${CMAKE_SOURCE_DIR}/src/core/layertree
@@ -117,6 +118,7 @@ SET(TESTS
testqgsgeometryimport.cpp
testqgsgeometry.cpp
testqgsgeometryutils.cpp
+ testqgsgeonodeconnection.cpp
testqgsgml.cpp
testqgsgradients.cpp
testqgsgraduatedsymbolrenderer.cpp
diff --git a/tests/src/core/testqgsgeonodeconnection.cpp b/tests/src/core/testqgsgeonodeconnection.cpp
new file mode 100644
index 00000000000..2ae016f3d4a
--- /dev/null
+++ b/tests/src/core/testqgsgeonodeconnection.cpp
@@ -0,0 +1,126 @@
+/***************************************************************************
+ testqgsgeonodeconnection.cpp
+ --------------------------------------
+ Date : Saturday, 25 March 2017
+ Copyright: (C) 2017
+ Email: ismail@kartoza.com
+ ***************************************************************************
+ *
+ * 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 "qgstest.h"
+#include
+
+#include
+#include
+#include
+#include
+
+//#include "qgis_core.h"
+#include "qgsgeonodeconnection.h"
+#include "qgssettings.h"
+
+/** \ingroup UnitTests
+ * This is a unit test for the QgsGeoConnection class.
+ */
+
+class TestQgsGeoNodeConnection: public QObject
+{
+ Q_OBJECT
+
+ private slots:
+ // will be called before the first testfunction is executed.
+ void initTestCase();
+ // will be called after the last testfunction was executed.
+ void cleanupTestCase()
+ {
+ QgsGeoNodeConnection::deleteConnection( mGeoNodeConnectionName );
+ QgsGeoNodeConnection::deleteConnection( mDemoGeoNodeName );
+ QgsGeoNodeConnection::deleteConnection( mKartozaGeoNodeQGISServerName );
+ }
+ // will be called before each testfunction is executed.
+ void init() {}
+ // will be called after every testfunction.
+ void cleanup() {}
+
+ // Check if we can create geonode connection from database.
+ void testCreation();
+
+ private:
+ QString mGeoNodeConnectionName;
+ QString mGeoNodeConnectionURL;
+
+ QString mDemoGeoNodeName;
+ QString mDemoGeoNodeURL;
+
+ QString mKartozaGeoNodeQGISServerName;
+ QString mKartozaGeoNodeQGISServerURL;
+
+ QString mKartozaGeoNodeGeoServerName;
+ QString mKartozaGeoNodeGeoServerURL;
+
+ bool mSkipRemoteTest;
+};
+
+// Runs before all unit tests
+void TestQgsGeoNodeConnection::initTestCase()
+{
+ std::cout << "CTEST_FULL_OUTPUT" << std::endl;
+ mGeoNodeConnectionName = QStringLiteral( "ThisIsAGeoNodeConnection" );
+ mGeoNodeConnectionURL = QStringLiteral( "www.thisisageonodeurl.com" );
+ mDemoGeoNodeName = QStringLiteral( "Demo GeoNode" );
+ mDemoGeoNodeURL = QStringLiteral( "demo.geonode.org" );
+ mKartozaGeoNodeQGISServerName = QStringLiteral( "Staging Kartoza GeoNode QGIS Server" );
+ mKartozaGeoNodeQGISServerURL = QStringLiteral( "staging.geonode.kartoza.com" );
+ mKartozaGeoNodeGeoServerName = QStringLiteral( "Staging Kartoza GeoNode GeoServer" );
+ mKartozaGeoNodeGeoServerURL = QStringLiteral( "staginggs.geonode.kartoza.com" );
+
+ // Change it to skip remote testing
+ mSkipRemoteTest = true;
+
+ // Add Demo GeoNode Connection
+ QgsSettings settings;
+
+ // Testing real server, demo.geonode.org. Need to be changed later.
+ settings.setValue( QgsGeoNodeConnection::pathGeoNodeConnection() + QStringLiteral( "/%1/url" ).arg( mDemoGeoNodeName ), mDemoGeoNodeURL, QgsSettings::Providers );
+ // Testing real server, staging.geonode.kartoza.com. Need to be changed later.
+ settings.setValue( QgsGeoNodeConnection::pathGeoNodeConnection() + QStringLiteral( "/%1/url" ).arg( mKartozaGeoNodeQGISServerName ), mKartozaGeoNodeQGISServerURL, QgsSettings::Providers );
+ // Testing real server, staginggs.geonode.kartoza.com. Need to be changed later.
+ settings.setValue( QgsGeoNodeConnection::pathGeoNodeConnection() + QStringLiteral( "/%1/url" ).arg( mKartozaGeoNodeGeoServerName ), mKartozaGeoNodeGeoServerURL, QgsSettings::Providers );
+}
+
+// Test the creation of geonode connection
+void TestQgsGeoNodeConnection::testCreation()
+{
+ if ( mSkipRemoteTest )
+ {
+ QSKIP( "Skip remote test for faster testing" );
+ }
+
+ QStringList connectionList = QgsGeoNodeConnection::connectionList();
+ int numberOfConnection = connectionList.count();
+ // Verify if the demo.geonode.org is created properly
+ QVERIFY( connectionList.contains( mDemoGeoNodeName ) );
+ QVERIFY( !connectionList.contains( mGeoNodeConnectionName ) );
+
+ // Add new GeoNode Connection
+ QgsSettings settings;
+
+ settings.setValue( QgsGeoNodeConnection::pathGeoNodeConnection() + QStringLiteral( "/%1/url" ).arg( mGeoNodeConnectionName ), mGeoNodeConnectionURL, QgsSettings::Providers );
+
+ QStringList newConnectionList = QgsGeoNodeConnection::connectionList();
+ int newNumberOfConnection = newConnectionList.count();
+
+ // Check the number is increased by 1
+ QCOMPARE( numberOfConnection + 1, newNumberOfConnection );
+
+ // Verify if the new connection is created properly
+ QVERIFY( newConnectionList.contains( mGeoNodeConnectionName ) );
+}
+
+QGSTEST_MAIN( TestQgsGeoNodeConnection )
+#include "testqgsgeonodeconnection.moc"