mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[geonode] Don't block data source manager while connecting to a server
Also add missing docstrings
This commit is contained in:
parent
1a19283634
commit
e1562df16b
@ -12,15 +12,43 @@ struct QgsGeoNodeStyle
|
|||||||
%TypeHeaderCode
|
%TypeHeaderCode
|
||||||
#include <qgsgeonoderequest.h>
|
#include <qgsgeonoderequest.h>
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QString id;
|
QString id;
|
||||||
|
%Docstring
|
||||||
|
Unique style ID
|
||||||
|
%End
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
|
%Docstring
|
||||||
|
Style name
|
||||||
|
%End
|
||||||
|
|
||||||
QString title;
|
QString title;
|
||||||
|
%Docstring
|
||||||
|
Style title
|
||||||
|
%End
|
||||||
|
|
||||||
QDomDocument body;
|
QDomDocument body;
|
||||||
|
%Docstring
|
||||||
|
DOM documenting containing style
|
||||||
|
%End
|
||||||
|
|
||||||
QString styleUrl;
|
QString styleUrl;
|
||||||
|
%Docstring
|
||||||
|
Associated URL
|
||||||
|
%End
|
||||||
};
|
};
|
||||||
|
|
||||||
class QgsGeoNodeRequest : QObject
|
class QgsGeoNodeRequest : QObject
|
||||||
{
|
{
|
||||||
|
%Docstring
|
||||||
|
Request handler for GeoNode servers.
|
||||||
|
|
||||||
|
QgsGeoNodeRequest handles requesting and parsing service details from a GeoNode
|
||||||
|
server instance, for instance requesting all available layers or layer styles.
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
%End
|
||||||
|
|
||||||
%TypeHeaderCode
|
%TypeHeaderCode
|
||||||
#include "qgsgeonoderequest.h"
|
#include "qgsgeonoderequest.h"
|
||||||
@ -30,110 +58,192 @@ class QgsGeoNodeRequest : QObject
|
|||||||
struct ServiceLayerDetail
|
struct ServiceLayerDetail
|
||||||
{
|
{
|
||||||
QUuid uuid;
|
QUuid uuid;
|
||||||
|
%Docstring
|
||||||
|
Unique identifier (generate on the client side, not at the GeoNode server)
|
||||||
|
%End
|
||||||
QString name;
|
QString name;
|
||||||
|
%Docstring
|
||||||
|
Layer name
|
||||||
|
%End
|
||||||
QString typeName;
|
QString typeName;
|
||||||
|
%Docstring
|
||||||
|
Layer type name
|
||||||
|
%End
|
||||||
QString title;
|
QString title;
|
||||||
|
%Docstring
|
||||||
|
Layer title
|
||||||
|
%End
|
||||||
QString wmsURL;
|
QString wmsURL;
|
||||||
|
%Docstring
|
||||||
|
WMS URL for layer
|
||||||
|
%End
|
||||||
QString wfsURL;
|
QString wfsURL;
|
||||||
|
%Docstring
|
||||||
|
WFS URL for layer
|
||||||
|
%End
|
||||||
QString xyzURL;
|
QString xyzURL;
|
||||||
|
%Docstring
|
||||||
|
XYZ tileserver URL for layer
|
||||||
|
%End
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit QgsGeoNodeRequest( bool forceRefresh, QObject *parent = 0 );
|
QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent = 0 );
|
||||||
%Docstring
|
%Docstring
|
||||||
Constructor for QgsGeoNodeRequest.
|
Constructor for QgsGeoNodeRequest.
|
||||||
|
|
||||||
If ``forceRefresh`` is false, then cached copies of the request may be reused.
|
If ``forceRefresh`` is false, then cached copies of the request may be reused.
|
||||||
%End
|
%End
|
||||||
QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent = 0 );
|
|
||||||
virtual ~QgsGeoNodeRequest();
|
virtual ~QgsGeoNodeRequest();
|
||||||
|
|
||||||
bool request( const QString &endPoint );
|
void request( const QString &endPoint );
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Triggers a new request to the GeoNode server, with the requested ``endPoint``.
|
||||||
|
Any existing request will be aborted.
|
||||||
|
|
||||||
|
Calling this method does not block while waiting for a result.
|
||||||
|
|
||||||
|
\warning When using the non-blocking methods in this class, sending
|
||||||
|
overlapping requests results in undefined behavior. Use separate instances
|
||||||
|
of QgsGeoNodeRequest instead to avoid this.
|
||||||
|
|
||||||
|
.. seealso:: requestBlocking()
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool requestBlocking( const QString &endPoint );
|
||||||
|
%Docstring
|
||||||
|
Triggers a new request to the GeoNode server, with the requested ``endPoint``.
|
||||||
|
Any existing request will be aborted.
|
||||||
|
|
||||||
|
Calling this method will block while waiting for a result. It should not be
|
||||||
|
used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
|
||||||
|
.. seealso:: request()
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> getLayers();
|
void fetchLayers();
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Triggers a new request to fetch the list of available layers from the
|
||||||
|
server. When complete, the layersFetched() signal will be emitted
|
||||||
|
with the result.
|
||||||
|
|
||||||
|
This method is non-blocking and returns immediately.
|
||||||
|
|
||||||
|
\warning When using the non-blocking methods in this class, sending
|
||||||
|
overlapping requests results in undefined behavior. Use separate instances
|
||||||
|
of QgsGeoNodeRequest instead to avoid this.
|
||||||
|
|
||||||
|
.. seealso:: layersFetched()
|
||||||
|
.. seealso:: fetchLayersBlocking()
|
||||||
|
%End
|
||||||
|
|
||||||
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> fetchLayersBlocking();
|
||||||
|
%Docstring
|
||||||
|
Requests the list of available layers from the server.
|
||||||
|
|
||||||
|
This method is blocking and will wait for results from the server before returning.
|
||||||
|
Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
|
||||||
|
.. seealso:: fetchLayers()
|
||||||
:rtype: list of QgsGeoNodeRequest.ServiceLayerDetail
|
:rtype: list of QgsGeoNodeRequest.ServiceLayerDetail
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QList<QgsGeoNodeStyle> getStyles( const QString &layerName );
|
QList<QgsGeoNodeStyle> fetchStylesBlocking( const QString &layerName );
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Requests the list of available styles for the layer
|
||||||
|
with matching ``layerName`` from the server.
|
||||||
|
|
||||||
|
This method is blocking and will wait for results from the server before returning.
|
||||||
|
Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
:rtype: list of QgsGeoNodeStyle
|
:rtype: list of QgsGeoNodeStyle
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QgsGeoNodeStyle getDefaultStyle( const QString &layerName );
|
QgsGeoNodeStyle fetchDefaultStyleBlocking( const QString &layerName );
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Requests the default style for the layer with matching ``layerName`` from the server.
|
||||||
|
|
||||||
|
This method is blocking and will wait for results from the server before returning.
|
||||||
|
Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
:rtype: QgsGeoNodeStyle
|
:rtype: QgsGeoNodeStyle
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QgsGeoNodeStyle getStyle( const QString &styleID );
|
QgsGeoNodeStyle fetchStyleBlocking( const QString &styleId );
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Requests the details for the style with matching ``styleId`` from the server.
|
||||||
|
|
||||||
|
This method is blocking and will wait for results from the server before returning.
|
||||||
|
Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
:rtype: QgsGeoNodeStyle
|
:rtype: QgsGeoNodeStyle
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QStringList serviceUrls( const QString &serviceType );
|
QStringList fetchServiceUrlsBlocking( const QString &serviceType );
|
||||||
%Docstring
|
%Docstring
|
||||||
Obtain list of unique URLs in the geonode
|
Requests the list of unique URLs for available services with matching ``serviceType`` from the server.
|
||||||
|
|
||||||
|
This method is blocking and will wait for results from the server before returning.
|
||||||
|
Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
:rtype: list of str
|
:rtype: list of str
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QgsStringMap serviceUrlData( const QString &serviceType );
|
QgsStringMap fetchServiceUrlDataBlocking( const QString &serviceType );
|
||||||
%Docstring
|
%Docstring
|
||||||
Obtain map of layer name and url for a service type
|
Obtains a map of layer name to URL for available services with matching ``serviceType`` from the server.
|
||||||
|
|
||||||
|
This method is blocking and will wait for results from the server before returning.
|
||||||
|
Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
:rtype: QgsStringMap
|
:rtype: QgsStringMap
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QString lastError() const;
|
QString lastError() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Returns the most recent error string for any encountered errors, or an empty string if
|
||||||
|
no errors have been encountered.
|
||||||
:rtype: str
|
:rtype: str
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QByteArray response() const;
|
QByteArray lastResponse() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
|
Returns the most recent response obtained from the server.
|
||||||
:rtype: QByteArray
|
:rtype: QByteArray
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QNetworkReply *reply() const;
|
QString protocol() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
:rtype: QNetworkReply
|
Returns the network protocol (e.g. 'http') used for connecting with the server.
|
||||||
|
.. seealso:: setProtocol()
|
||||||
|
:rtype: str
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
void setProtocol( const QString &protocol );
|
||||||
|
%Docstring
|
||||||
|
Sets the network ``protocol`` (e.g. 'http') used for connecting with the server.
|
||||||
|
.. seealso:: protocol()
|
||||||
|
%End
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
void abort();
|
void abort();
|
||||||
%Docstring
|
%Docstring
|
||||||
Abort network request immediately
|
Aborts any active network request immediately.
|
||||||
%End
|
%End
|
||||||
|
|
||||||
QString getProtocol() const;
|
|
||||||
%Docstring
|
|
||||||
:rtype: str
|
|
||||||
%End
|
|
||||||
void setProtocol( const QString &protocol );
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void statusChanged( const QString &statusQString );
|
void statusChanged( const QString &statusQString );
|
||||||
%Docstring
|
%Docstring
|
||||||
emit a signal to be caught by qgisapp and display a statusQString on status bar
|
Emitted when the status of an ongoing request is changed.
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void requestFinished();
|
void requestFinished();
|
||||||
%Docstring
|
%Docstring
|
||||||
emit a signal once the request is finished
|
Emitted when the existing request has been completed.
|
||||||
%End
|
%End
|
||||||
|
|
||||||
protected slots:
|
void layersFetched( const QList<QgsGeoNodeRequest::ServiceLayerDetail> &layers );
|
||||||
void replyFinished();
|
%Docstring
|
||||||
void replyProgress( qint64, qint64 );
|
Emitted when the result of a fetchLayers call has been received and processed.
|
||||||
|
%End
|
||||||
protected:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,9 +38,9 @@ QVector<QgsDataItem *> QgsGeoNodeConnectionItem::createChildren()
|
|||||||
QString url = mConnection->uri().param( QStringLiteral( "url" ) );
|
QString url = mConnection->uri().param( QStringLiteral( "url" ) );
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest geonodeRequest( url, true );
|
||||||
|
|
||||||
QStringList wmsUrl = geonodeRequest.serviceUrls( QStringLiteral( "WMS" ) );
|
QStringList wmsUrl = geonodeRequest.fetchServiceUrlsBlocking( QStringLiteral( "WMS" ) );
|
||||||
QStringList wfsUrl = geonodeRequest.serviceUrls( QStringLiteral( "WFS" ) );
|
QStringList wfsUrl = geonodeRequest.fetchServiceUrlsBlocking( QStringLiteral( "WFS" ) );
|
||||||
QStringList xyzUrl = geonodeRequest.serviceUrls( QStringLiteral( "XYZ" ) );
|
QStringList xyzUrl = geonodeRequest.fetchServiceUrlsBlocking( QStringLiteral( "XYZ" ) );
|
||||||
|
|
||||||
if ( !wmsUrl.isEmpty() )
|
if ( !wmsUrl.isEmpty() )
|
||||||
{
|
{
|
||||||
|
@ -249,7 +249,7 @@ void QgsGeoNodeNewConnection::testConnection()
|
|||||||
QString url = txtUrl->text();
|
QString url = txtUrl->text();
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest geonodeRequest( url, true );
|
||||||
|
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = geonodeRequest.getLayers();
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = geonodeRequest.fetchLayersBlocking();
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
||||||
if ( !layers.empty() )
|
if ( !layers.empty() )
|
||||||
|
@ -72,6 +72,11 @@ QgsGeoNodeSourceSelect::QgsGeoNodeSourceSelect( QWidget *parent, Qt::WindowFlags
|
|||||||
treeView->setModel( mModelProxy );
|
treeView->setModel( mModelProxy );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsGeoNodeSourceSelect::~QgsGeoNodeSourceSelect()
|
||||||
|
{
|
||||||
|
emit abortRequests();
|
||||||
|
}
|
||||||
|
|
||||||
void QgsGeoNodeSourceSelect::addConnectionsEntryList()
|
void QgsGeoNodeSourceSelect::addConnectionsEntryList()
|
||||||
{
|
{
|
||||||
QgsGeoNodeNewConnection nc( this );
|
QgsGeoNodeNewConnection nc( this );
|
||||||
@ -147,141 +152,146 @@ void QgsGeoNodeSourceSelect::showHelp()
|
|||||||
|
|
||||||
void QgsGeoNodeSourceSelect::connectToGeonodeConnection()
|
void QgsGeoNodeSourceSelect::connectToGeonodeConnection()
|
||||||
{
|
{
|
||||||
QApplication::setOverrideCursor( Qt::BusyCursor );
|
|
||||||
QgsGeoNodeConnection connection( cmbConnections->currentText() );
|
QgsGeoNodeConnection connection( cmbConnections->currentText() );
|
||||||
|
|
||||||
QString url = connection.uri().param( QStringLiteral( "url" ) );
|
QString url = connection.uri().param( QStringLiteral( "url" ) );
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest *geonodeRequest = new QgsGeoNodeRequest( url, true );
|
||||||
|
connect( this, &QgsGeoNodeSourceSelect::abortRequests, geonodeRequest, &QgsGeoNodeRequest::abort );
|
||||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
connect( geonodeRequest, &QgsGeoNodeRequest::requestFinished, geonodeRequest, [geonodeRequest]
|
||||||
const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = geonodeRequest.getLayers();
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
|
|
||||||
if ( !layers.empty() )
|
|
||||||
{
|
{
|
||||||
QgsDebugMsg( QStringLiteral( "Success, non empty layers %1" ).arg( layers.count( ) ) );
|
QApplication::restoreOverrideCursor();
|
||||||
}
|
geonodeRequest->deleteLater();
|
||||||
else
|
} );
|
||||||
|
connect( geonodeRequest, &QgsGeoNodeRequest::layersFetched, this, [ = ]( const QList< QgsGeoNodeRequest::ServiceLayerDetail > layers )
|
||||||
{
|
{
|
||||||
QgsMessageLog::logMessage( QStringLiteral( "Failed, empty layers" ), tr( "GeoNode" ) );
|
if ( !layers.empty() )
|
||||||
}
|
|
||||||
|
|
||||||
if ( mModel )
|
|
||||||
{
|
|
||||||
mModel->removeRows( 0, mModel->rowCount() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !layers.isEmpty() )
|
|
||||||
{
|
|
||||||
for ( const QgsGeoNodeRequest::ServiceLayerDetail &layer : layers )
|
|
||||||
{
|
{
|
||||||
QUuid uuid = layer.uuid;
|
QgsDebugMsg( QStringLiteral( "Success, non empty layers %1" ).arg( layers.count( ) ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QgsMessageLog::logMessage( QStringLiteral( "Failed, empty layers" ), tr( "GeoNode" ) );
|
||||||
|
}
|
||||||
|
|
||||||
QString wmsURL = layer.wmsURL;
|
if ( mModel )
|
||||||
QString wfsURL = layer.wfsURL;
|
{
|
||||||
QString xyzURL = layer.xyzURL;
|
mModel->removeRows( 0, mModel->rowCount() );
|
||||||
|
}
|
||||||
|
|
||||||
if ( !wmsURL.isEmpty() )
|
if ( !layers.isEmpty() )
|
||||||
|
{
|
||||||
|
for ( const QgsGeoNodeRequest::ServiceLayerDetail &layer : layers )
|
||||||
{
|
{
|
||||||
QStandardItem *titleItem = new QStandardItem( layer.title );
|
QUuid uuid = layer.uuid;
|
||||||
QStandardItem *nameItem;
|
|
||||||
if ( !layer.name.isEmpty() )
|
QString wmsURL = layer.wmsURL;
|
||||||
|
QString wfsURL = layer.wfsURL;
|
||||||
|
QString xyzURL = layer.xyzURL;
|
||||||
|
|
||||||
|
if ( !wmsURL.isEmpty() )
|
||||||
{
|
{
|
||||||
nameItem = new QStandardItem( layer.name );
|
QStandardItem *titleItem = new QStandardItem( layer.title );
|
||||||
|
QStandardItem *nameItem;
|
||||||
|
if ( !layer.name.isEmpty() )
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
nameItem = new QStandardItem( layer.title );
|
QgsDebugMsgLevel( QStringLiteral( "Layer %1 does not have WMS url." ).arg( layer.title ), 3 );
|
||||||
}
|
}
|
||||||
QStandardItem *serviceTypeItem = new QStandardItem( tr( "Layer" ) );
|
if ( !wfsURL.isEmpty() )
|
||||||
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
|
|
||||||
{
|
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Layer %1 does not have WMS url." ).arg( layer.title ), 3 );
|
|
||||||
}
|
|
||||||
if ( !wfsURL.isEmpty() )
|
|
||||||
{
|
|
||||||
QStandardItem *titleItem = new QStandardItem( layer.title );
|
|
||||||
QStandardItem *nameItem;
|
|
||||||
if ( !layer.name.isEmpty() )
|
|
||||||
{
|
{
|
||||||
nameItem = new QStandardItem( layer.name );
|
QStandardItem *titleItem = new QStandardItem( layer.title );
|
||||||
|
QStandardItem *nameItem;
|
||||||
|
if ( !layer.name.isEmpty() )
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
nameItem = new QStandardItem( layer.title );
|
QgsDebugMsgLevel( QStringLiteral( "Layer %1 does not have WFS url." ).arg( layer.title ), 3 );
|
||||||
}
|
}
|
||||||
QStandardItem *serviceTypeItem = new QStandardItem( tr( "Layer" ) );
|
if ( !xyzURL.isEmpty() )
|
||||||
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
|
|
||||||
{
|
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Layer %1 does not have WFS url." ).arg( layer.title ), 3 );
|
|
||||||
}
|
|
||||||
if ( !xyzURL.isEmpty() )
|
|
||||||
{
|
|
||||||
QStandardItem *titleItem = new QStandardItem( layer.title );
|
|
||||||
QStandardItem *nameItem;
|
|
||||||
if ( !layer.name.isEmpty() )
|
|
||||||
{
|
{
|
||||||
nameItem = new QStandardItem( layer.name );
|
QStandardItem *titleItem = new QStandardItem( layer.title );
|
||||||
|
QStandardItem *nameItem;
|
||||||
|
if ( !layer.name.isEmpty() )
|
||||||
|
{
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
nameItem = new QStandardItem( layer.title );
|
QgsDebugMsgLevel( QStringLiteral( "Layer %1 does not have XYZ url." ).arg( layer.title ), 3 );
|
||||||
}
|
}
|
||||||
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
|
|
||||||
{
|
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Layer %1 does not have XYZ url." ).arg( layer.title ), 3 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
QMessageBox::critical( this, tr( "Connect to GeoNode" ), tr( "Cannot get any feature services" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
QMessageBox::critical( this, tr( "Connect to GeoNode" ), tr( "Cannot get any feature services" ) );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
QApplication::restoreOverrideCursor();
|
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::setOverrideCursor( Qt::BusyCursor );
|
||||||
|
geonodeRequest->fetchLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsGeoNodeSourceSelect::saveGeonodeConnection()
|
void QgsGeoNodeSourceSelect::saveGeonodeConnection()
|
||||||
|
@ -42,11 +42,16 @@ class QgsGeoNodeSourceSelect: public QgsAbstractDataSourceWidget, private Ui::Qg
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
QgsGeoNodeSourceSelect( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::None );
|
QgsGeoNodeSourceSelect( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::None );
|
||||||
|
~QgsGeoNodeSourceSelect();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void addButtonClicked() override;
|
void addButtonClicked() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void abortRequests();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Stores the available CRS for a server connections.
|
/** Stores the available CRS for a server connections.
|
||||||
|
@ -27,13 +27,6 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDomDocument>
|
#include <QDomDocument>
|
||||||
|
|
||||||
QgsGeoNodeRequest::QgsGeoNodeRequest( bool forceRefresh, QObject *parent )
|
|
||||||
: QObject( parent )
|
|
||||||
, mForceRefresh( forceRefresh )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent )
|
QgsGeoNodeRequest::QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent )
|
||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
, mBaseUrl( baseUrl )
|
, mBaseUrl( baseUrl )
|
||||||
@ -57,27 +50,51 @@ void QgsGeoNodeRequest::abort()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::getLayers()
|
void QgsGeoNodeRequest::fetchLayers()
|
||||||
{
|
{
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
|
request( QStringLiteral( "/api/layers/" ) );
|
||||||
bool success = request( QStringLiteral( "/api/layers/" ) );
|
QObject *obj = new QObject( this );
|
||||||
if ( !success )
|
|
||||||
|
connect( this, &QgsGeoNodeRequest::requestFinished, obj, [obj, this ]
|
||||||
{
|
{
|
||||||
return layers;
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
|
||||||
}
|
if ( mError.isEmpty() )
|
||||||
return parseLayers( this->response() );
|
{
|
||||||
|
layers = parseLayers( this->lastResponse() );
|
||||||
|
}
|
||||||
|
emit layersFetched( layers );
|
||||||
|
|
||||||
|
obj->deleteLater();
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsGeoNodeStyle QgsGeoNodeRequest::getDefaultStyle( const QString &layerName )
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::fetchLayersBlocking()
|
||||||
|
{
|
||||||
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers;
|
||||||
|
|
||||||
|
QEventLoop loop;
|
||||||
|
connect( this, &QgsGeoNodeRequest::requestFinished, &loop, &QEventLoop::quit );
|
||||||
|
QObject *obj = new QObject( this );
|
||||||
|
connect( this, &QgsGeoNodeRequest::layersFetched, obj, [&]( const QList<QgsGeoNodeRequest::ServiceLayerDetail> &fetched )
|
||||||
|
{
|
||||||
|
layers = fetched;
|
||||||
|
} );
|
||||||
|
fetchLayers();
|
||||||
|
loop.exec( QEventLoop::ExcludeUserInputEvents );
|
||||||
|
delete obj;
|
||||||
|
return layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsGeoNodeStyle QgsGeoNodeRequest::fetchDefaultStyleBlocking( const QString &layerName )
|
||||||
{
|
{
|
||||||
QgsGeoNodeStyle defaultStyle;
|
QgsGeoNodeStyle defaultStyle;
|
||||||
bool success = request( QStringLiteral( "/api/layers?name=" ) + layerName );
|
bool success = requestBlocking( QStringLiteral( "/api/layers?name=" ) + layerName );
|
||||||
if ( !success )
|
if ( !success )
|
||||||
{
|
{
|
||||||
return defaultStyle;
|
return defaultStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
|
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
|
||||||
const QJsonObject jsonObject = jsonDocument.object();
|
const QJsonObject jsonObject = jsonDocument.object();
|
||||||
const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
|
const QList<QVariant> layers = jsonObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
|
||||||
if ( layers.count() < 1 )
|
if ( layers.count() < 1 )
|
||||||
@ -92,16 +109,16 @@ QgsGeoNodeStyle QgsGeoNodeRequest::getDefaultStyle( const QString &layerName )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QgsGeoNodeStyle> QgsGeoNodeRequest::getStyles( const QString &layerName )
|
QList<QgsGeoNodeStyle> QgsGeoNodeRequest::fetchStylesBlocking( const QString &layerName )
|
||||||
{
|
{
|
||||||
QList<QgsGeoNodeStyle> geoNodeStyles;
|
QList<QgsGeoNodeStyle> geoNodeStyles;
|
||||||
bool success = request( QStringLiteral( "/api/styles?layer__name=" ) + layerName );
|
bool success = requestBlocking( QStringLiteral( "/api/styles?layer__name=" ) + layerName );
|
||||||
if ( !success )
|
if ( !success )
|
||||||
{
|
{
|
||||||
return geoNodeStyles;
|
return geoNodeStyles;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
|
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
|
||||||
const QJsonObject jsobObject = jsonDocument.object();
|
const QJsonObject jsobObject = jsonDocument.object();
|
||||||
const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
|
const QList<QVariant> styles = jsobObject.toVariantMap().value( QStringLiteral( "objects" ) ).toList();
|
||||||
|
|
||||||
@ -120,9 +137,9 @@ QList<QgsGeoNodeStyle> QgsGeoNodeRequest::getStyles( const QString &layerName )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsGeoNodeStyle QgsGeoNodeRequest::getStyle( const QString &styleID )
|
QgsGeoNodeStyle QgsGeoNodeRequest::fetchStyleBlocking( const QString &styleId )
|
||||||
{
|
{
|
||||||
QString endPoint = QStringLiteral( "/api/styles/" ) + styleID;
|
QString endPoint = QStringLiteral( "/api/styles/" ) + styleId;
|
||||||
|
|
||||||
return retrieveStyle( endPoint );
|
return retrieveStyle( endPoint );
|
||||||
}
|
}
|
||||||
@ -134,7 +151,7 @@ void QgsGeoNodeRequest::replyProgress( qint64 bytesReceived, qint64 bytesTotal )
|
|||||||
emit statusChanged( msg );
|
emit statusChanged( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsGeoNodeRequest::getProtocol() const
|
QString QgsGeoNodeRequest::protocol() const
|
||||||
{
|
{
|
||||||
return mProtocol;
|
return mProtocol;
|
||||||
}
|
}
|
||||||
@ -159,7 +176,6 @@ void QgsGeoNodeRequest::replyFinished()
|
|||||||
emit statusChanged( QStringLiteral( "GeoNode request redirected." ) );
|
emit statusChanged( QStringLiteral( "GeoNode request redirected." ) );
|
||||||
|
|
||||||
const QUrl &toUrl = redirect.toUrl();
|
const QUrl &toUrl = redirect.toUrl();
|
||||||
mGeoNodeReply->request();
|
|
||||||
if ( toUrl == mGeoNodeReply->url() )
|
if ( toUrl == mGeoNodeReply->url() )
|
||||||
{
|
{
|
||||||
mError = tr( "Redirect loop detected: %1" ).arg( toUrl.toString() );
|
mError = tr( "Redirect loop detected: %1" ).arg( toUrl.toString() );
|
||||||
@ -237,7 +253,6 @@ void QgsGeoNodeRequest::replyFinished()
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit requestFinished();
|
emit requestFinished();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &layerResponse )
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> QgsGeoNodeRequest::parseLayers( const QByteArray &layerResponse )
|
||||||
@ -354,12 +369,12 @@ QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle( const QString &styleUrl )
|
|||||||
{
|
{
|
||||||
QgsGeoNodeStyle geoNodeStyle;
|
QgsGeoNodeStyle geoNodeStyle;
|
||||||
|
|
||||||
bool success = request( styleUrl );
|
bool success = requestBlocking( styleUrl );
|
||||||
if ( !success )
|
if ( !success )
|
||||||
{
|
{
|
||||||
return geoNodeStyle;
|
return geoNodeStyle;
|
||||||
}
|
}
|
||||||
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->response() );
|
const QJsonDocument jsonDocument = QJsonDocument::fromJson( this->lastResponse() );
|
||||||
const QJsonObject jsonObject = jsonDocument.object();
|
const QJsonObject jsonObject = jsonDocument.object();
|
||||||
|
|
||||||
const QVariantMap jsonMap = jsonObject.toVariantMap();
|
const QVariantMap jsonMap = jsonObject.toVariantMap();
|
||||||
@ -368,13 +383,13 @@ QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle( const QString &styleUrl )
|
|||||||
geoNodeStyle.title = jsonMap.value( QStringLiteral( "title" ) ).toString();
|
geoNodeStyle.title = jsonMap.value( QStringLiteral( "title" ) ).toString();
|
||||||
geoNodeStyle.styleUrl = jsonMap.value( QStringLiteral( "style_url" ) ).toString();
|
geoNodeStyle.styleUrl = jsonMap.value( QStringLiteral( "style_url" ) ).toString();
|
||||||
|
|
||||||
success = request( geoNodeStyle.styleUrl );
|
success = requestBlocking( geoNodeStyle.styleUrl );
|
||||||
if ( !success )
|
if ( !success )
|
||||||
{
|
{
|
||||||
return geoNodeStyle;
|
return geoNodeStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
success = geoNodeStyle.body.setContent( this->response() );
|
success = geoNodeStyle.body.setContent( this->lastResponse() );
|
||||||
if ( !success )
|
if ( !success )
|
||||||
{
|
{
|
||||||
return geoNodeStyle;
|
return geoNodeStyle;
|
||||||
@ -383,11 +398,11 @@ QgsGeoNodeStyle QgsGeoNodeRequest::retrieveStyle( const QString &styleUrl )
|
|||||||
return geoNodeStyle;
|
return geoNodeStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList QgsGeoNodeRequest::serviceUrls( const QString &serviceType )
|
QStringList QgsGeoNodeRequest::fetchServiceUrlsBlocking( const QString &serviceType )
|
||||||
{
|
{
|
||||||
QStringList urls;
|
QStringList urls;
|
||||||
|
|
||||||
const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = getLayers();
|
const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = fetchLayersBlocking();
|
||||||
|
|
||||||
if ( layers.empty() )
|
if ( layers.empty() )
|
||||||
{
|
{
|
||||||
@ -415,7 +430,7 @@ QStringList QgsGeoNodeRequest::serviceUrls( const QString &serviceType )
|
|||||||
|
|
||||||
if ( !url.contains( QLatin1String( "://" ) ) )
|
if ( !url.contains( QLatin1String( "://" ) ) )
|
||||||
{
|
{
|
||||||
url.prepend( getProtocol() );
|
url.prepend( protocol() );
|
||||||
}
|
}
|
||||||
if ( !urls.contains( url ) )
|
if ( !urls.contains( url ) )
|
||||||
{
|
{
|
||||||
@ -426,11 +441,11 @@ QStringList QgsGeoNodeRequest::serviceUrls( const QString &serviceType )
|
|||||||
return urls;
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsStringMap QgsGeoNodeRequest::serviceUrlData( const QString &serviceType )
|
QgsStringMap QgsGeoNodeRequest::fetchServiceUrlDataBlocking( const QString &serviceType )
|
||||||
{
|
{
|
||||||
QgsStringMap urls;
|
QgsStringMap urls;
|
||||||
|
|
||||||
const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = getLayers();
|
const QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = fetchLayersBlocking();
|
||||||
|
|
||||||
if ( layers.empty() )
|
if ( layers.empty() )
|
||||||
{
|
{
|
||||||
@ -460,7 +475,7 @@ QgsStringMap QgsGeoNodeRequest::serviceUrlData( const QString &serviceType )
|
|||||||
QString layerName = layer.name;
|
QString layerName = layer.name;
|
||||||
if ( !url.contains( QLatin1String( "://" ) ) )
|
if ( !url.contains( QLatin1String( "://" ) ) )
|
||||||
{
|
{
|
||||||
url.prepend( getProtocol() );
|
url.prepend( protocol() );
|
||||||
}
|
}
|
||||||
if ( !urls.contains( url ) )
|
if ( !urls.contains( url ) )
|
||||||
{
|
{
|
||||||
@ -471,7 +486,7 @@ QgsStringMap QgsGeoNodeRequest::serviceUrlData( const QString &serviceType )
|
|||||||
return urls;
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsGeoNodeRequest::request( const QString &endPoint )
|
void QgsGeoNodeRequest::request( const QString &endPoint )
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
mIsAborted = false;
|
mIsAborted = false;
|
||||||
@ -480,25 +495,35 @@ bool QgsGeoNodeRequest::request( const QString &endPoint )
|
|||||||
QgsDebugMsg( "Requesting to " + url );
|
QgsDebugMsg( "Requesting to " + url );
|
||||||
setProtocol( url.split( QStringLiteral( "://" ) ).at( 0 ) );
|
setProtocol( url.split( QStringLiteral( "://" ) ).at( 0 ) );
|
||||||
QUrl layerUrl( url );
|
QUrl layerUrl( url );
|
||||||
layerUrl.setScheme( getProtocol() );
|
layerUrl.setScheme( protocol() );
|
||||||
|
|
||||||
mError.clear();
|
mError.clear();
|
||||||
|
|
||||||
|
mGeoNodeReply = requestUrl( url );
|
||||||
|
connect( mGeoNodeReply, &QNetworkReply::finished, this, &QgsGeoNodeRequest::replyFinished, Qt::DirectConnection );
|
||||||
|
connect( mGeoNodeReply, &QNetworkReply::downloadProgress, this, &QgsGeoNodeRequest::replyProgress, Qt::DirectConnection );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsGeoNodeRequest::requestBlocking( const QString &endPoint )
|
||||||
|
{
|
||||||
|
request( endPoint );
|
||||||
|
|
||||||
|
QEventLoop loop;
|
||||||
|
connect( this, &QgsGeoNodeRequest::requestFinished, &loop, &QEventLoop::quit );
|
||||||
|
loop.exec( QEventLoop::ExcludeUserInputEvents );
|
||||||
|
|
||||||
|
return mError.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply *QgsGeoNodeRequest::requestUrl( const QString &url )
|
||||||
|
{
|
||||||
QNetworkRequest request( url );
|
QNetworkRequest request( url );
|
||||||
// Add authentication check here
|
// Add authentication check here
|
||||||
|
|
||||||
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
|
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, mForceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache );
|
||||||
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
|
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
|
||||||
|
|
||||||
mGeoNodeReply = QgsNetworkAccessManager::instance()->get( request );
|
return 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,12 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* \class QgsGeoNodeStyle
|
||||||
|
* \brief Encapsulates information about a GeoNode layer style.
|
||||||
|
* \since QGIS 3.0
|
||||||
|
*/
|
||||||
struct CORE_EXPORT QgsGeoNodeStyle
|
struct CORE_EXPORT QgsGeoNodeStyle
|
||||||
{
|
{
|
||||||
#ifdef SIP_RUN
|
#ifdef SIP_RUN
|
||||||
@ -29,26 +35,56 @@ struct CORE_EXPORT QgsGeoNodeStyle
|
|||||||
#include <qgsgeonoderequest.h>
|
#include <qgsgeonoderequest.h>
|
||||||
% End
|
% End
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//! Unique style ID
|
||||||
QString id;
|
QString id;
|
||||||
|
|
||||||
|
//! Style name
|
||||||
QString name;
|
QString name;
|
||||||
|
|
||||||
|
//! Style title
|
||||||
QString title;
|
QString title;
|
||||||
|
|
||||||
|
//! DOM documenting containing style
|
||||||
QDomDocument body;
|
QDomDocument body;
|
||||||
|
|
||||||
|
//! Associated URL
|
||||||
QString styleUrl;
|
QString styleUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* \class QgsGeoNodeRequest
|
||||||
|
* \brief Request handler for GeoNode servers.
|
||||||
|
*
|
||||||
|
* QgsGeoNodeRequest handles requesting and parsing service details from a GeoNode
|
||||||
|
* server instance, for instance requesting all available layers or layer styles.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.0
|
||||||
|
*/
|
||||||
class CORE_EXPORT QgsGeoNodeRequest : public QObject
|
class CORE_EXPORT QgsGeoNodeRequest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service layer details for an individual layer from a GeoNode connection.
|
||||||
|
*/
|
||||||
struct ServiceLayerDetail
|
struct ServiceLayerDetail
|
||||||
{
|
{
|
||||||
|
//! Unique identifier (generate on the client side, not at the GeoNode server)
|
||||||
QUuid uuid;
|
QUuid uuid;
|
||||||
|
//! Layer name
|
||||||
QString name;
|
QString name;
|
||||||
|
//! Layer type name
|
||||||
QString typeName;
|
QString typeName;
|
||||||
|
//! Layer title
|
||||||
QString title;
|
QString title;
|
||||||
|
//! WMS URL for layer
|
||||||
QString wmsURL;
|
QString wmsURL;
|
||||||
|
//! WFS URL for layer
|
||||||
QString wfsURL;
|
QString wfsURL;
|
||||||
|
//! XYZ tileserver URL for layer
|
||||||
QString xyzURL;
|
QString xyzURL;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,54 +93,155 @@ class CORE_EXPORT QgsGeoNodeRequest : public QObject
|
|||||||
*
|
*
|
||||||
* If \a forceRefresh is false, then cached copies of the request may be reused.
|
* If \a forceRefresh is false, then cached copies of the request may be reused.
|
||||||
*/
|
*/
|
||||||
explicit QgsGeoNodeRequest( bool forceRefresh, QObject *parent = nullptr );
|
|
||||||
QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent = nullptr );
|
QgsGeoNodeRequest( const QString &baseUrl, bool forceRefresh, QObject *parent = nullptr );
|
||||||
|
|
||||||
virtual ~QgsGeoNodeRequest();
|
virtual ~QgsGeoNodeRequest();
|
||||||
|
|
||||||
bool request( const QString &endPoint );
|
/**
|
||||||
|
* Triggers a new request to the GeoNode server, with the requested \a endPoint.
|
||||||
|
* Any existing request will be aborted.
|
||||||
|
*
|
||||||
|
* Calling this method does not block while waiting for a result.
|
||||||
|
*
|
||||||
|
* \warning When using the non-blocking methods in this class, sending
|
||||||
|
* overlapping requests results in undefined behavior. Use separate instances
|
||||||
|
* of QgsGeoNodeRequest instead to avoid this.
|
||||||
|
*
|
||||||
|
* \see requestBlocking()
|
||||||
|
*/
|
||||||
|
void request( const QString &endPoint );
|
||||||
|
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> getLayers();
|
/**
|
||||||
|
* Triggers a new request to the GeoNode server, with the requested \a endPoint.
|
||||||
|
* Any existing request will be aborted.
|
||||||
|
*
|
||||||
|
* Calling this method will block while waiting for a result. It should not be
|
||||||
|
* used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*
|
||||||
|
* \see request()
|
||||||
|
*/
|
||||||
|
bool requestBlocking( const QString &endPoint );
|
||||||
|
|
||||||
QList<QgsGeoNodeStyle> getStyles( const QString &layerName );
|
/**
|
||||||
|
* Triggers a new request to fetch the list of available layers from the
|
||||||
|
* server. When complete, the layersFetched() signal will be emitted
|
||||||
|
* with the result.
|
||||||
|
*
|
||||||
|
* This method is non-blocking and returns immediately.
|
||||||
|
*
|
||||||
|
* \warning When using the non-blocking methods in this class, sending
|
||||||
|
* overlapping requests results in undefined behavior. Use separate instances
|
||||||
|
* of QgsGeoNodeRequest instead to avoid this.
|
||||||
|
*
|
||||||
|
* \see layersFetched()
|
||||||
|
* \see fetchLayersBlocking()
|
||||||
|
*/
|
||||||
|
void fetchLayers();
|
||||||
|
|
||||||
QgsGeoNodeStyle getDefaultStyle( const QString &layerName );
|
/**
|
||||||
|
* Requests the list of available layers from the server.
|
||||||
|
*
|
||||||
|
* This method is blocking and will wait for results from the server before returning.
|
||||||
|
* Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*
|
||||||
|
* \see fetchLayers()
|
||||||
|
*/
|
||||||
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> fetchLayersBlocking();
|
||||||
|
|
||||||
QgsGeoNodeStyle getStyle( const QString &styleID );
|
/**
|
||||||
|
* Requests the list of available styles for the layer
|
||||||
|
* with matching \a layerName from the server.
|
||||||
|
*
|
||||||
|
* This method is blocking and will wait for results from the server before returning.
|
||||||
|
* Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
QList<QgsGeoNodeStyle> fetchStylesBlocking( const QString &layerName );
|
||||||
|
|
||||||
//! Obtain list of unique URLs in the geonode
|
/**
|
||||||
QStringList serviceUrls( const QString &serviceType );
|
* Requests the default style for the layer with matching \a layerName from the server.
|
||||||
|
*
|
||||||
|
* This method is blocking and will wait for results from the server before returning.
|
||||||
|
* Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*/
|
||||||
|
QgsGeoNodeStyle fetchDefaultStyleBlocking( const QString &layerName );
|
||||||
|
|
||||||
//! Obtain map of layer name and url for a service type
|
/**
|
||||||
QgsStringMap serviceUrlData( const QString &serviceType );
|
* Requests the details for the style with matching \a styleId from the server.
|
||||||
|
*
|
||||||
|
* This method is blocking and will wait for results from the server before returning.
|
||||||
|
* Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*/
|
||||||
|
QgsGeoNodeStyle fetchStyleBlocking( const QString &styleId );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the list of unique URLs for available services with matching \a serviceType from the server.
|
||||||
|
*
|
||||||
|
* This method is blocking and will wait for results from the server before returning.
|
||||||
|
* Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*/
|
||||||
|
QStringList fetchServiceUrlsBlocking( const QString &serviceType );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains a map of layer name to URL for available services with matching \a serviceType from the server.
|
||||||
|
*
|
||||||
|
* This method is blocking and will wait for results from the server before returning.
|
||||||
|
* Accordingly it should not be used from any code which potentially blocks operation in the main GUI thread.
|
||||||
|
*/
|
||||||
|
QgsStringMap fetchServiceUrlDataBlocking( const QString &serviceType );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most recent error string for any encountered errors, or an empty string if
|
||||||
|
* no errors have been encountered.
|
||||||
|
*/
|
||||||
QString lastError() const { return mError; }
|
QString lastError() const { return mError; }
|
||||||
|
|
||||||
QByteArray response() const { return mHttpGeoNodeResponse; }
|
/**
|
||||||
|
* Returns the most recent response obtained from the server.
|
||||||
|
*/
|
||||||
|
QByteArray lastResponse() const { return mHttpGeoNodeResponse; }
|
||||||
|
|
||||||
QNetworkReply *reply() const { return mGeoNodeReply; }
|
/**
|
||||||
|
* Returns the network protocol (e.g. 'http') used for connecting with the server.
|
||||||
|
* \see setProtocol()
|
||||||
|
*/
|
||||||
|
QString protocol() const;
|
||||||
|
|
||||||
//! Abort network request immediately
|
/**
|
||||||
void abort();
|
* Sets the network \a protocol (e.g. 'http') used for connecting with the server.
|
||||||
|
* \see protocol()
|
||||||
QString getProtocol() const;
|
*/
|
||||||
void setProtocol( const QString &protocol );
|
void setProtocol( const QString &protocol );
|
||||||
|
|
||||||
private:
|
public slots:
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> parseLayers( const QByteArray &layerResponse );
|
|
||||||
QgsGeoNodeStyle retrieveStyle( const QString &styleUrl );
|
/**
|
||||||
|
* Aborts any active network request immediately.
|
||||||
|
*/
|
||||||
|
void abort();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
//! \brief emit a signal to be caught by qgisapp and display a statusQString on status bar
|
|
||||||
|
/**
|
||||||
|
* Emitted when the status of an ongoing request is changed.
|
||||||
|
*/
|
||||||
void statusChanged( const QString &statusQString );
|
void statusChanged( const QString &statusQString );
|
||||||
|
|
||||||
//! \brief emit a signal once the request is finished
|
/**
|
||||||
|
* Emitted when the existing request has been completed.
|
||||||
|
*/
|
||||||
void requestFinished();
|
void requestFinished();
|
||||||
|
|
||||||
protected slots:
|
/**
|
||||||
|
* Emitted when the result of a fetchLayers call has been received and processed.
|
||||||
|
*/
|
||||||
|
void layersFetched( const QList<QgsGeoNodeRequest::ServiceLayerDetail> &layers );
|
||||||
|
|
||||||
|
private slots:
|
||||||
void replyFinished();
|
void replyFinished();
|
||||||
void replyProgress( qint64, qint64 );
|
void replyProgress( qint64, qint64 );
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
|
||||||
//! URL part of URI (httpuri)
|
//! URL part of URI (httpuri)
|
||||||
QString mProtocol;
|
QString mProtocol;
|
||||||
@ -112,8 +249,6 @@ class CORE_EXPORT QgsGeoNodeRequest : public QObject
|
|||||||
//! URL part of URI (httpuri)
|
//! URL part of URI (httpuri)
|
||||||
QString mBaseUrl;
|
QString mBaseUrl;
|
||||||
|
|
||||||
// QgsWmsAuthorization mAuth;
|
|
||||||
|
|
||||||
//! The reply to the geonode request
|
//! The reply to the geonode request
|
||||||
QNetworkReply *mGeoNodeReply = nullptr;
|
QNetworkReply *mGeoNodeReply = nullptr;
|
||||||
|
|
||||||
@ -129,6 +264,11 @@ class CORE_EXPORT QgsGeoNodeRequest : public QObject
|
|||||||
bool mIsAborted = false;
|
bool mIsAborted = false;
|
||||||
bool mForceRefresh = false;
|
bool mForceRefresh = false;
|
||||||
|
|
||||||
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> parseLayers( const QByteArray &layerResponse );
|
||||||
|
QgsGeoNodeStyle retrieveStyle( const QString &styleUrl );
|
||||||
|
|
||||||
|
QNetworkReply *requestUrl( const QString &url );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QGSGEONODEREQUEST_H
|
#endif // QGSGEONODEREQUEST_H
|
||||||
|
@ -227,7 +227,7 @@ QgsDataItem *QgsWfsDataItemProvider::createDataItem( const QString &path, QgsDat
|
|||||||
QString url = connection.uri().param( "url" );
|
QString url = connection.uri().param( "url" );
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest geonodeRequest( url, true );
|
||||||
|
|
||||||
QgsWFSDataSourceURI sourceUri( geonodeRequest.serviceUrls( QStringLiteral( "WFS" ) )[0] );
|
QgsWFSDataSourceURI sourceUri( geonodeRequest.fetchServiceUrlsBlocking( QStringLiteral( "WFS" ) )[0] );
|
||||||
|
|
||||||
QgsDebugMsg( QString( "WFS full uri: '%1'." ).arg( QString( sourceUri.uri() ) ) );
|
QgsDebugMsg( QString( "WFS full uri: '%1'." ).arg( QString( sourceUri.uri() ) ) );
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ QVector<QgsDataItem *> QgsWfsDataItemProvider::createDataItems( const QString &p
|
|||||||
QString url = connection.uri().param( "url" );
|
QString url = connection.uri().param( "url" );
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest geonodeRequest( url, true );
|
||||||
|
|
||||||
QStringList encodedUris( geonodeRequest.serviceUrls( QStringLiteral( "WFS" ) ) );
|
QStringList encodedUris( geonodeRequest.fetchServiceUrlsBlocking( QStringLiteral( "WFS" ) ) );
|
||||||
|
|
||||||
if ( !encodedUris.isEmpty() )
|
if ( !encodedUris.isEmpty() )
|
||||||
{
|
{
|
||||||
|
@ -566,7 +566,7 @@ QVector<QgsDataItem *> QgsWmsDataItemProvider::createDataItems( const QString &p
|
|||||||
QString url = connection.uri().param( "url" );
|
QString url = connection.uri().param( "url" );
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest geonodeRequest( url, true );
|
||||||
|
|
||||||
QStringList encodedUris( geonodeRequest.serviceUrls( QStringLiteral( "WMS" ) ) );
|
QStringList encodedUris( geonodeRequest.fetchServiceUrlsBlocking( QStringLiteral( "WMS" ) ) );
|
||||||
|
|
||||||
if ( !encodedUris.isEmpty() )
|
if ( !encodedUris.isEmpty() )
|
||||||
{
|
{
|
||||||
@ -612,7 +612,7 @@ QVector<QgsDataItem *> QgsXyzTileDataItemProvider::createDataItems( const QStrin
|
|||||||
QString url = connection.uri().param( "url" );
|
QString url = connection.uri().param( "url" );
|
||||||
QgsGeoNodeRequest geonodeRequest( url, true );
|
QgsGeoNodeRequest geonodeRequest( url, true );
|
||||||
|
|
||||||
QgsStringMap urlData( geonodeRequest.serviceUrlData( QStringLiteral( "XYZ" ) ) );
|
QgsStringMap urlData( geonodeRequest.fetchServiceUrlDataBlocking( QStringLiteral( "XYZ" ) ) );
|
||||||
|
|
||||||
if ( !urlData.isEmpty() )
|
if ( !urlData.isEmpty() )
|
||||||
{
|
{
|
||||||
|
@ -129,7 +129,7 @@ void TestQgsGeoNodeConnection::testLayerAPI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QgsGeoNodeRequest geonodeRequest( mKartozaGeoNodeQGISServerURL, true );
|
QgsGeoNodeRequest geonodeRequest( mKartozaGeoNodeQGISServerURL, true );
|
||||||
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = geonodeRequest.getLayers();
|
QList<QgsGeoNodeRequest::ServiceLayerDetail> layers = geonodeRequest.fetchLayersBlocking();
|
||||||
QString msg = QStringLiteral( "Number of layers: %1" ).arg( layers.count() );
|
QString msg = QStringLiteral( "Number of layers: %1" ).arg( layers.count() );
|
||||||
QgsDebugMsg( msg );
|
QgsDebugMsg( msg );
|
||||||
QVERIFY( layers.count() > 0 );
|
QVERIFY( layers.count() > 0 );
|
||||||
@ -144,17 +144,17 @@ void TestQgsGeoNodeConnection::testStyleAPI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QgsGeoNodeRequest geonodeRequest( mKartozaGeoNodeQGISServerURL, true );
|
QgsGeoNodeRequest geonodeRequest( mKartozaGeoNodeQGISServerURL, true );
|
||||||
QgsGeoNodeStyle defaultStyle = geonodeRequest.getDefaultStyle( QStringLiteral( "airports" ) );
|
QgsGeoNodeStyle defaultStyle = geonodeRequest.fetchDefaultStyleBlocking( QStringLiteral( "airports" ) );
|
||||||
QVERIFY( !defaultStyle.name.isEmpty() );
|
QVERIFY( !defaultStyle.name.isEmpty() );
|
||||||
QVERIFY( defaultStyle.body.toString().startsWith( QStringLiteral( "<qgis" ) ) );
|
QVERIFY( defaultStyle.body.toString().startsWith( QStringLiteral( "<qgis" ) ) );
|
||||||
QVERIFY( defaultStyle.body.toString().contains( QStringLiteral( "</qgis>" ) ) );
|
QVERIFY( defaultStyle.body.toString().contains( QStringLiteral( "</qgis>" ) ) );
|
||||||
|
|
||||||
QgsGeoNodeStyle geoNodeStyle = geonodeRequest.getStyle( "76" );
|
QgsGeoNodeStyle geoNodeStyle = geonodeRequest.fetchStyleBlocking( "76" );
|
||||||
QVERIFY( !geoNodeStyle.name.isEmpty() );
|
QVERIFY( !geoNodeStyle.name.isEmpty() );
|
||||||
QVERIFY( geoNodeStyle.body.toString().startsWith( QStringLiteral( "<qgis" ) ) );
|
QVERIFY( geoNodeStyle.body.toString().startsWith( QStringLiteral( "<qgis" ) ) );
|
||||||
QVERIFY( geoNodeStyle.body.toString().contains( QStringLiteral( "</qgis>" ) ) );
|
QVERIFY( geoNodeStyle.body.toString().contains( QStringLiteral( "</qgis>" ) ) );
|
||||||
|
|
||||||
QList<QgsGeoNodeStyle> geoNodeStyles = geonodeRequest.getStyles( QStringLiteral( "airports" ) );
|
QList<QgsGeoNodeStyle> geoNodeStyles = geonodeRequest.fetchStylesBlocking( QStringLiteral( "airports" ) );
|
||||||
QgsDebugMsg( geoNodeStyles.count() );
|
QgsDebugMsg( geoNodeStyles.count() );
|
||||||
QVERIFY( geoNodeStyles.count() == 2 );
|
QVERIFY( geoNodeStyles.count() == 2 );
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user