Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] QGIS - GeoNode Integration #5153

Merged
merged 60 commits into from
Sep 12, 2017
Merged

Conversation

nyalldawson
Copy link
Collaborator

This is a reworked version of #4995 - implementing integration of GeoNode connections and servers into the browser panel and unified data source manager, building off @ismailsunni's original work.

Changes from #4995 include:

  • refactoring GeoNode source select to fully take advantage of @elpaso's outstanding recent work on abstracting away provider source select dialogs. Now, there are no geonode related changes in the gui library and the "source select" and "new connection" dialogs have been pushed down to the app library.

  • GeoNode now uses the QgsDataItemProviderRegistry to integrate with browser

  • All GeoNode specific changes have been removed from QgsDataSourceManagerDialog

  • Some non-blocking methods have been added to QgsGeoNodeRequest, and used to avoid blocking the data source manager when connecting to GeoNode servers.

  • As discussed in previous PRs/during the hackfest - no interface has been added for handling other geoCMS servers. I've made some basic steps toward this (mostly be restructing the code), but I'm happy to leave the QgsGeoNodeRequest and QgsGeoNodeConnection classes in core for 3.0 and we can revisit when there's interest in integrating other CMS providers.

  • There's some GeoNode specific changes to the WFS/WMS provider data items - Ideally these should be removed, but given that they are isolated to providers and don't affect the 3.0 API I think it's acceptable to leave these for now.

Assuming Travis is happy, I consider this ready to merge, but would value other opinions (@elpaso, @wonder-sk), and obviously testing by @timlinux and @ismailsunni !

@timlinux
Copy link
Member

timlinux commented Sep 8, 2017

Thanks so much for helping us with this @nyalldawson ! We will test now!

@timlinux
Copy link
Member

timlinux commented Sep 8, 2017

Just come feedback that I tested under Mac OS and it is working very nicely!

Copy link
Contributor

@elpaso elpaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the improvements here! I've left a couple of comments.


if ( !encodedUris.isEmpty() )
{
Q_FOREACH ( QString encodedUri, encodedUris )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nyalldawson Do we prefer for range loops here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed (Also optimised some map/hash based loops, where the keys where being iterated and then the values retrieved immediately. In this case it's much more efficient to iterate over the original container and avoid the multiple value lookups)

@@ -192,6 +195,84 @@ void QgsWfsRootItem::newConnection()
}
#endif


//////
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed - it was just used throughout this file as an indicator of "new class"

@@ -0,0 +1,272 @@
/***************************************************************************
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this class looks very much like QgsNewHttpConnection can you extend that class instead of creating a new one?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion thanks - lets take a look if we can do that...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elpaso - done. There certainly was a lot of duplicate code there!

@timlinux I noticed when doing this that none of the WFS/WMS specific settings (all those options like 'invert axis orientation','wfs version', etc) are actually utilised when loading geonode layers. They were being stored but only used when reopening this dialog. Accordingly I've removed them from the geonode server connection settings dialog (since it made this change must easier!).

My question is - should these even be required here? In my view they are all settings designed to handle specific quirks of different WFS/WMS server implementations. Given that we know in this case the connection is to a geonode server, couldn't we avoid showing these options and instead just hardcode whatever options are required for optimal performance with geonode instances?

It's a lot less options for users to mess with, and in my opinion dropping these options actually increases the user perception that QGIS/GeoNode are tightly integrated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nyalldawson I've a limited knowledge of geonode, but AFAIK geonode supports different backends (GeoServer and QGIS Server, if I'm not wrong), so, if geonode just proxies the requests to WFS/WMS providers, it might makes sense to keep the options.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elpaso - right. I've fixed this now, so the settings are exposed again and respected when adding layers via the source select dialog. I've tightened up some of the code surrounding this and added some tests too.

However... in the process I found a bigger issue! (Yay! Coding! Gotta love it!) Turns out these service specific settings are ignored for ALL providers when adding layers from the browser. (e.g. adding a WMS layer doesn't respect the axis/dpi/referer/etc settings, which are correctly respected when adding the same from the source select dialog).

That bug's WAY out of scope here though, so I've run away from it.

Copy link
Contributor

@elpaso elpaso Sep 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nyalldawson

That bug's WAY out of scope here though, so I've run away from it.

I'd recommend that you file a ticked for that issue, maybe we can fix it in the next pre-release bugfix round.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @nyalldawson for picking up on that. 👍 to deal with it in a separate ticket.

QgsSettings settings;

// Testing real server, demo.geonode.org. Need to be changed later.
settings.setValue( QgsGeoNodeConnectionUtils::pathGeoNodeConnection() + QStringLiteral( "/%1/url" ).arg( mDemoGeoNodeName ), mDemoGeoNodeURL, QgsSettings::Providers );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if we could avoid pinging the network here: I think that all tests should be able to run on disconnected environments (not only for latency but for consistancy and reliability), why don't you follow the same route that WFS tests do? I.e. store the response in the test data folder and fake the connection to load responses from disk? @nyalldawson @m-kuhn do we have any good practice here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for you're review @elpaso. Yes I think having mocked responses would be nicer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@myarjunar Can you take care of doing this second request - I will get @nyalldawson to do the first. Thanks!

@elpaso
Copy link
Contributor

elpaso commented Sep 12, 2017

@nyalldawson I've got some (negative) feedback about the HTTP blocking calls scattered here and there in this PR: I also had concerns but I assumed that the blocking calls are only used in browser tree threads and for this reason they wouldn't block the GUI even with large datasets, is my assumption correct?

@nyalldawson
Copy link
Collaborator Author

@elpaso I've got some (negative) feedback about the HTTP blocking calls scattered here and there in this PR: I also had concerns but I assumed that the blocking calls are only used in browser tree threads and for this reason they wouldn't block the GUI even with large datasets, is my assumption correct?

Correct. QgsGeoNodeRequest has a number of blocking/non blocking methods. Some of these duplicate each other with a blocking and non-blocking version. I made sure everything which could block the UI (i.e. through the source select dialog) uses the non-blocking method. The others (e.g. those which are only used through the browser) I've left as the blocking methods. I also thought for Python code having these blocking methods still available (even when there's the non-blocking alternative) is probably a good move, since it makes things a bit easier for simple scripts.

@elpaso
Copy link
Contributor

elpaso commented Sep 12, 2017

@nyalldawson @timlinux
This looks much better now, thanks for all the efforts! +1 for merge.

There is just a (hopefully) last potential issue that I want to share, I've got some more feedback from overseas, the exchange team has concerns about the assumption that the WMS/WFS layers returned by geonode are from the same domain of the geonode API server. That might not always be the case and could lead to problems with OAuth2 authentication. I didn't check the details, but maybe it's worth considering.

Quoting @amirahav :

On the authentication side, I think things are going to be a bit more complicated - on any call to geonode itself the bearer token will have to be added as a header (like you would expect), however the current implementation of oauth2 in in Geoserver only accepts the bearer token as as query param (this makes it arguable if the implementation is within the spec, but, still that's how it's working).
Thinking back to how we implemented it back for some customers, we didn't have to worry about it because we didn't connect directly to Geoserver, however currently exchange/geonode exposes Geoserver directly, and is dependent on Geoserver authenticating against geonode.

I think the geonode API needs to be extended. Currently the QGIS code assume that Geoserver is running under the same domain as geonode, and constructs the query by parsing the geonode featurtype name. However I think the geonode API should include the full path of the service it's pointing to.

@Gustry
Copy link
Contributor

Gustry commented Sep 12, 2017

Thanks @elpaso for the comment. In this PR, we support both QGIS Server backend and Geoserver. We are using the Geonode api to retrieve URLs, so it might be fine because the geoserver URL will be given by Geonode. I can't speak about the OAuth2 authentication, I don't know.

For QGIS Server, we don't expose it to the public. All requests go into Geonode application as a proxy for QGIS Server.

@timlinux
Copy link
Member

Thanks everyone for your inputs and patience! Great to see this merged!

myarjunar and others added 17 commits September 13, 2017 05:47
…el (qgis#4816)

* add Geonode connection menu to the toolbar

* add header files for geonode-qgis client

* add action to launch geonode connection dialog from menubar

* Move to proper directory

* Add geonodeconnection class.

* Add unit test for geonode connection.

* Use const static to avoid typo.

* Get list layers from geonode.

* Add get maps method.

* Geonode connection dialog (#13)

* add new geonode connection dialog

* apply functionality to the geonode connection manager dialog

* add save and load geonode connection functionality

* edit baseKey and credentialBaseKey

* remove auto-connect slots

* Add unit test for geonode connection.

* Add wms url getter.

* Add uuid and layer name in the table.

* Add handler for the list layer clicked. WIP.

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

* update gitignore

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

* Fix Docstring.

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

* fix http and toolbar menu

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

* [WIP] Add WFS.

* Add geonode get service url.

* combobox functionality and test geonode connection

* Add WFS.

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

* Add busy cursor when add layer.

* get service uri capabilitites

* add available layers to the geonode browser panel

* remove debugging footprint and replace old style connect

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

* fix getLayers by WMS url

* add Geonode connection menu to the toolbar

* Filter out invalid layer / map.

* Fix service url method.

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

* Add XYZ url to geonode connection  dialog.

* Add XYZ layer to QGIS.

* fix double geonode submenu

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

* comply with qgis3 new class naming

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

* base class for cms connection

* make geonode connection as a derived class from cms connection

* update cmakelists

* move geonode connection to geocms dir

* update CMakeLists

* Handle geonode 2.7 with new API.

* Handle multiple geoserver url in one geonode.

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

* Refactor serviceURL to return QStringList.

* add 'add geonode layer' icon

* add geonode to the data source manager dialog

* [GeoNode-Client] Fix add WFS layer.

* fix wms url parameter

* add xyz dataitems

* Use new style connect.

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

* Code improvement.

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

* Open universal add layer when click Add GeoNode layer.

* Make sure the geonode url has protocol.

* Handle geonode version in a better way.

* make sure the serviceUrl method has scheme in its urls

* add services option to the dialog

* remove version label if not wfs

* construct wms url with parameters for geonode connection

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

* fix new style connect using static_cast

* hode close button if dialog is in embedded mode

* fix xyz layer naming in the browser tree

* create base class for geocms dataitems

* fix compiling warning

* Use struct instead QVariantMap.

* tidy up code

* Tidy up code, use QgsStringMap instead QVariantMap.

* Add spellok for catalogue.

* update sip

* update sip

* Use naming convention for QgsGeoCmsConnection and use QUuid.

* Async by using GeoNodeRequest class.

* Move geonode to src/gui.

* Use stack not heap.

* Remove unused includes.

* Use signal to handle request.

* Use QStringLiteral.

* Switch to use Q_FOREACH.

* Use Q_FOREACH and addressing PR's review.

* Set private for data members.

* update sip

* Update sip.

* Update sip.

* Fix sip problem to make it buildable again.

* Remove geocms

* Tidy up code.

* Use QgsSetting Scope::Provider.

* Fix missing zip.h
- avoid container detachments
- use QStringLiteral
Move utility functions to QgsGeoNodeConnectionUtils
QgsMessageLog should only be used for errors or warnings,
not 'everything is working ok' type debug messages
Avoids a lot of duplicate code.

Note that while this refactoring was done to allow WFS and WMS
settings to be simultaneously visible, I've removed the settings
from the GeoNode connection for now. Looking into this they were
being stored, but not used at all when loading the layers from
the GeoNode instance.
Instead of including these classes in app, we instead make a
shell data provider which implements only the dataItemProviders()
and sourceSelectProviders() methods.

Helps keep GeoNode GUI related code partitioned
@nyalldawson
Copy link
Collaborator Author

Thanks @elpaso for the comment. In this PR, we support both QGIS Server backend and Geoserver. We are using the Geonode api to retrieve URLs, so it might be fine because the geoserver URL will be given by Geonode. I can't speak about the OAuth2 authentication, I don't know.

For QGIS Server, we don't expose it to the public. All requests go into Geonode application as a proxy for QGIS Server.

Lets keep an eye on the bug tracker, and if this proves to be a limitation "in the wild" we can address at that stage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants