mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
[OAPIF provider] Integrate provider within WFS provider GUI
Funded by Planet
This commit is contained in:
parent
4a6b49fe8f
commit
681229a48a
@ -78,6 +78,15 @@ Returns the current connection url.
|
||||
|
||||
protected:
|
||||
|
||||
enum WfsVersionIndex
|
||||
{
|
||||
WFS_VERSION_MAX,
|
||||
WFS_VERSION_1_0,
|
||||
WFS_VERSION_1_1,
|
||||
WFS_VERSION_2_0,
|
||||
WFS_VERSION_API_FEATURES,
|
||||
};
|
||||
|
||||
virtual bool validate();
|
||||
%Docstring
|
||||
Returns ``True`` if dialog settings are valid, or ``False`` if current
|
||||
|
@ -73,6 +73,7 @@ QgsNewHttpConnection::QgsNewHttpConnection( QWidget *parent, ConnectionTypes typ
|
||||
cmbVersion->addItem( tr( "1.0" ) );
|
||||
cmbVersion->addItem( tr( "1.1" ) );
|
||||
cmbVersion->addItem( tr( "2.0" ) );
|
||||
cmbVersion->addItem( tr( "OGC API - Features" ) );
|
||||
connect( cmbVersion,
|
||||
static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ),
|
||||
this, &QgsNewHttpConnection::wfsVersionCurrentIndexChanged );
|
||||
@ -166,10 +167,11 @@ QgsNewHttpConnection::QgsNewHttpConnection( QWidget *parent, ConnectionTypes typ
|
||||
void QgsNewHttpConnection::wfsVersionCurrentIndexChanged( int index )
|
||||
{
|
||||
// For now 2019-06-06, leave paging checkable for some WFS version 1.1 servers with support
|
||||
cbxWfsFeaturePaging->setEnabled( index == 0 || index >= 2 );
|
||||
lblPageSize->setEnabled( cbxWfsFeaturePaging->isChecked() && ( index == 0 || index >= 2 ) );
|
||||
txtPageSize->setEnabled( cbxWfsFeaturePaging->isChecked() && ( index == 0 || index >= 2 ) );
|
||||
cbxWfsIgnoreAxisOrientation->setEnabled( index != 1 );
|
||||
cbxWfsFeaturePaging->setEnabled( index == WFS_VERSION_MAX || index >= WFS_VERSION_2_0 );
|
||||
lblPageSize->setEnabled( cbxWfsFeaturePaging->isChecked() && ( index == WFS_VERSION_MAX || index >= WFS_VERSION_1_1 ) );
|
||||
txtPageSize->setEnabled( cbxWfsFeaturePaging->isChecked() && ( index == WFS_VERSION_MAX || index >= WFS_VERSION_1_1 ) );
|
||||
cbxWfsIgnoreAxisOrientation->setEnabled( index != WFS_VERSION_1_0 && index != WFS_VERSION_API_FEATURES );
|
||||
cbxWfsInvertAxisOrientation->setEnabled( index != WFS_VERSION_API_FEATURES );
|
||||
}
|
||||
|
||||
void QgsNewHttpConnection::wfsFeaturePagingStateChanged( int state )
|
||||
@ -312,29 +314,27 @@ void QgsNewHttpConnection::updateServiceSpecificSettings()
|
||||
cmbDpiMode->setCurrentIndex( dpiIdx );
|
||||
|
||||
QString version = settings.value( wfsKey + "/version" ).toString();
|
||||
int versionIdx = 0; // AUTO
|
||||
int versionIdx = WFS_VERSION_MAX; // AUTO
|
||||
if ( version == QLatin1String( "1.0.0" ) )
|
||||
versionIdx = 1;
|
||||
versionIdx = WFS_VERSION_1_0;
|
||||
else if ( version == QLatin1String( "1.1.0" ) )
|
||||
versionIdx = 2;
|
||||
versionIdx = WFS_VERSION_1_1;
|
||||
else if ( version == QLatin1String( "2.0.0" ) )
|
||||
versionIdx = 3;
|
||||
versionIdx = WFS_VERSION_2_0;
|
||||
else if ( version == QLatin1String( "OGC_API_FEATURES" ) )
|
||||
versionIdx = WFS_VERSION_API_FEATURES;
|
||||
cmbVersion->setCurrentIndex( versionIdx );
|
||||
|
||||
// Enable/disable these items per WFS versions
|
||||
wfsVersionCurrentIndexChanged( versionIdx );
|
||||
|
||||
txtReferer->setText( settings.value( wmsKey + "/referer" ).toString() );
|
||||
txtMaxNumFeatures->setText( settings.value( wfsKey + "/maxnumfeatures" ).toString() );
|
||||
|
||||
// Only default to paging enabled if WFS 2.0.0 or higher
|
||||
bool pagingEnabled = settings.value( wfsKey + "/pagingenabled", ( versionIdx == 0 || versionIdx >= 3 ) ).toBool();
|
||||
bool pagingEnabled = settings.value( wfsKey + "/pagingenabled", ( versionIdx == WFS_VERSION_MAX || versionIdx >= WFS_VERSION_2_0 ) ).toBool();
|
||||
txtPageSize->setText( settings.value( wfsKey + "/pagesize" ).toString() );
|
||||
cbxWfsFeaturePaging->setChecked( pagingEnabled );
|
||||
|
||||
// Enable/disable these items per WFS versions
|
||||
// For now 2019-06-06, leave paging checkable for some WFS version 1.1 servers with support
|
||||
txtPageSize->setEnabled( pagingEnabled && ( versionIdx == 0 || versionIdx >= 2 ) );
|
||||
lblPageSize->setEnabled( pagingEnabled && ( versionIdx == 0 || versionIdx >= 2 ) );
|
||||
cbxWfsFeaturePaging->setEnabled( versionIdx == 0 || versionIdx >= 2 );
|
||||
cbxWfsIgnoreAxisOrientation->setEnabled( versionIdx != 1 );
|
||||
}
|
||||
|
||||
QUrl QgsNewHttpConnection::urlTrimmed() const
|
||||
@ -434,18 +434,21 @@ void QgsNewHttpConnection::accept()
|
||||
QString version = QStringLiteral( "auto" );
|
||||
switch ( cmbVersion->currentIndex() )
|
||||
{
|
||||
case 0:
|
||||
case WFS_VERSION_MAX:
|
||||
version = QStringLiteral( "auto" );
|
||||
break;
|
||||
case 1:
|
||||
case WFS_VERSION_1_0:
|
||||
version = QStringLiteral( "1.0.0" );
|
||||
break;
|
||||
case 2:
|
||||
case WFS_VERSION_1_1:
|
||||
version = QStringLiteral( "1.1.0" );
|
||||
break;
|
||||
case 3:
|
||||
case WFS_VERSION_2_0:
|
||||
version = QStringLiteral( "2.0.0" );
|
||||
break;
|
||||
case WFS_VERSION_API_FEATURES:
|
||||
version = QStringLiteral( "OGC_API_FEATURES" );
|
||||
break;
|
||||
}
|
||||
settings.setValue( wfsKey + "/version", version );
|
||||
|
||||
|
@ -103,6 +103,16 @@ class GUI_EXPORT QgsNewHttpConnection : public QDialog, private Ui::QgsNewHttpCo
|
||||
|
||||
protected:
|
||||
|
||||
//! Index of wfsVersionComboBox
|
||||
enum WfsVersionIndex
|
||||
{
|
||||
WFS_VERSION_MAX = 0,
|
||||
WFS_VERSION_1_0 = 1,
|
||||
WFS_VERSION_1_1 = 2,
|
||||
WFS_VERSION_2_0 = 3,
|
||||
WFS_VERSION_API_FEATURES = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns TRUE if dialog settings are valid, or FALSE if current
|
||||
* settings are not valid and the dialog should not be acceptable.
|
||||
|
@ -145,6 +145,11 @@ class CPLXMLTreeUniquePointer
|
||||
|
||||
void QgsWfsCapabilities::capabilitiesReplyFinished()
|
||||
{
|
||||
if ( mErrorCode != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
emit gotCapabilities();
|
||||
return;
|
||||
}
|
||||
const QByteArray &buffer = mResponse;
|
||||
|
||||
QgsDebugMsgLevel( QStringLiteral( "parsing capabilities: " ) + buffer, 4 );
|
||||
|
@ -19,11 +19,15 @@
|
||||
#include "qgsdataitemprovider.h"
|
||||
#include "qgsdataprovider.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsoapiflandingpagerequest.h"
|
||||
#include "qgsoapifcollection.h"
|
||||
#include "qgsoapifprovider.h"
|
||||
#include "qgswfsconstants.h"
|
||||
#include "qgswfsconnection.h"
|
||||
#include "qgswfscapabilities.h"
|
||||
#include "qgswfsdataitems.h"
|
||||
#include "qgswfsdatasourceuri.h"
|
||||
#include "qgswfsprovider.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsgeonodeconnection.h"
|
||||
#include "qgsgeonoderequest.h"
|
||||
@ -40,8 +44,8 @@
|
||||
// QgsWfsLayerItem
|
||||
//
|
||||
|
||||
QgsWfsLayerItem::QgsWfsLayerItem( QgsDataItem *parent, QString name, const QgsDataSourceUri &uri, QString featureType, QString title, QString crsString )
|
||||
: QgsLayerItem( parent, title, parent->path() + '/' + name, QString(), QgsLayerItem::Vector, QStringLiteral( "WFS" ) )
|
||||
QgsWfsLayerItem::QgsWfsLayerItem( QgsDataItem *parent, QString name, const QgsDataSourceUri &uri, QString featureType, QString title, QString crsString, const QString &providerKey )
|
||||
: QgsLayerItem( parent, title.isEmpty() ? featureType : title, parent->path() + '/' + name, QString(), QgsLayerItem::Vector, providerKey )
|
||||
{
|
||||
QgsSettings settings;
|
||||
bool useCurrentViewExtent = settings.value( QStringLiteral( "Windows/WFSSourceSelect/FeatureCurrentViewExtent" ), true ).toBool();
|
||||
@ -140,34 +144,82 @@ QgsWfsConnectionItem::QgsWfsConnectionItem( QgsDataItem *parent, QString name, Q
|
||||
mCapabilities |= Collapse;
|
||||
}
|
||||
|
||||
|
||||
QVector<QgsDataItem *> QgsWfsConnectionItem::createChildrenOapif()
|
||||
{
|
||||
QVector<QgsDataItem *> layers;
|
||||
QgsDataSourceUri uri( mUri );
|
||||
const bool synchronous = true;
|
||||
const bool forceRefresh = false;
|
||||
|
||||
QgsOapifLandingPageRequest landingPageRequest( uri );
|
||||
if ( landingPageRequest.request( synchronous, forceRefresh ) &&
|
||||
landingPageRequest.errorCode() == QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
QString url = landingPageRequest.collectionsUrl();
|
||||
while ( !url.isEmpty() )
|
||||
{
|
||||
QgsOapifCollectionsRequest collectionsRequest( uri, url );
|
||||
url.clear();
|
||||
if ( collectionsRequest.request( synchronous, forceRefresh ) &&
|
||||
collectionsRequest.errorCode() == QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
for ( const auto &collection : collectionsRequest.collections() )
|
||||
{
|
||||
QgsWfsLayerItem *layer = new QgsWfsLayerItem(
|
||||
this, mName, uri, collection.mId, collection.mTitle,
|
||||
QString(), QgsOapifProvider::OAPIF_PROVIDER_KEY );
|
||||
layers.append( layer );
|
||||
}
|
||||
url = collectionsRequest.nextUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
QVector<QgsDataItem *> QgsWfsConnectionItem::createChildren()
|
||||
{
|
||||
QgsDataSourceUri uri( mUri );
|
||||
QgsDebugMsg( "mUri = " + mUri );
|
||||
|
||||
QgsWfsCapabilities capabilities( mUri );
|
||||
|
||||
const bool synchronous = true;
|
||||
const bool forceRefresh = false;
|
||||
capabilities.requestCapabilities( synchronous, forceRefresh );
|
||||
|
||||
QVector<QgsDataItem *> layers;
|
||||
if ( capabilities.errorCode() == QgsWfsCapabilities::NoError )
|
||||
auto version = QgsWFSDataSourceURI( mUri ).version();
|
||||
if ( version == QLatin1String( "OGC_API_FEATURES" ) )
|
||||
{
|
||||
const auto featureTypes = capabilities.capabilities().featureTypes;
|
||||
for ( const QgsWfsCapabilities::FeatureType &featureType : featureTypes )
|
||||
{
|
||||
QgsWfsLayerItem *layer = new QgsWfsLayerItem( this, mName, uri, featureType.name, featureType.title, !featureType.crslist.isEmpty() ? featureType.crslist.first() : QString() );
|
||||
layers.append( layer );
|
||||
}
|
||||
return createChildrenOapif();
|
||||
}
|
||||
else
|
||||
{
|
||||
//layers.append( new QgsErrorItem( this, tr( "Failed to retrieve layers" ), mPath + "/error" ) );
|
||||
// TODO: show the error without adding child
|
||||
}
|
||||
QgsWfsCapabilities capabilities( mUri );
|
||||
if ( version == QgsWFSConstants::VERSION_AUTO )
|
||||
{
|
||||
capabilities.setLogErrors( false ); // as this might be a OAPIF server
|
||||
}
|
||||
capabilities.requestCapabilities( synchronous, forceRefresh );
|
||||
|
||||
return layers;
|
||||
QVector<QgsDataItem *> layers;
|
||||
if ( capabilities.errorCode() == QgsWfsCapabilities::NoError )
|
||||
{
|
||||
const auto featureTypes = capabilities.capabilities().featureTypes;
|
||||
for ( const QgsWfsCapabilities::FeatureType &featureType : featureTypes )
|
||||
{
|
||||
QgsWfsLayerItem *layer = new QgsWfsLayerItem(
|
||||
this, mName, uri, featureType.name, featureType.title,
|
||||
!featureType.crslist.isEmpty() ? featureType.crslist.first() : QString(),
|
||||
QgsWFSProvider::WFS_PROVIDER_KEY );
|
||||
layers.append( layer );
|
||||
}
|
||||
}
|
||||
else if ( version == QgsWFSConstants::VERSION_AUTO )
|
||||
{
|
||||
return createChildrenOapif();
|
||||
}
|
||||
|
||||
return layers;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -233,7 +285,7 @@ QgsDataItem *QgsWfsDataItemProvider::createDataItem( const QString &path, QgsDat
|
||||
QgsDebugMsgLevel( "WFS path = " + path, 4 );
|
||||
if ( path.isEmpty() )
|
||||
{
|
||||
return new QgsWfsRootItem( parentItem, QStringLiteral( "WFS" ), QStringLiteral( "wfs:" ) );
|
||||
return new QgsWfsRootItem( parentItem, QStringLiteral( "WFS / OGC API - Features" ), QStringLiteral( "wfs:" ) );
|
||||
}
|
||||
|
||||
// path schema: wfs:/connection name (used by OWS)
|
||||
|
@ -55,7 +55,7 @@ class QgsWfsConnectionItem : public QgsDataCollectionItem
|
||||
private:
|
||||
QString mUri;
|
||||
|
||||
QgsWfsCapabilities *mWfsCapabilities = nullptr;
|
||||
QVector<QgsDataItem *> createChildrenOapif();
|
||||
};
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ class QgsWfsLayerItem : public QgsLayerItem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QgsWfsLayerItem( QgsDataItem *parent, QString name, const QgsDataSourceUri &uri, QString featureType, QString title, QString crsString );
|
||||
QgsWfsLayerItem( QgsDataItem *parent, QString name, const QgsDataSourceUri &uri, QString featureType, QString title, QString crsString, const QString &providerKey );
|
||||
|
||||
QList<QMenu *> menus( QWidget *parent ) override;
|
||||
|
||||
|
@ -372,6 +372,10 @@ QString QgsWFSDataSourceURI::build( const QString &baseUri,
|
||||
uri.setSql( sql );
|
||||
if ( restrictToCurrentViewExtent )
|
||||
uri.mURI.setParam( QgsWFSConstants::URI_PARAM_RESTRICT_TO_REQUEST_BBOX, QStringLiteral( "1" ) );
|
||||
if ( uri.version() == QStringLiteral( "OGC_API_FEATURES" ) )
|
||||
{
|
||||
uri.setVersion( QString() );
|
||||
}
|
||||
return uri.uri();
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,15 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#include "qgswfsnewconnection.h"
|
||||
#include "qgswfsguiutils.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
QgsWFSNewConnection::QgsWFSNewConnection( QWidget *parent, const QString &connName ):
|
||||
QgsNewHttpConnection( parent, QgsNewHttpConnection::ConnectionWfs, QgsWFSConstants::CONNECTIONS_WFS, connName )
|
||||
{
|
||||
@ -26,28 +30,30 @@ QgsWFSNewConnection::QgsWFSNewConnection( QWidget *parent, const QString &connNa
|
||||
|
||||
QgsWFSNewConnection::~QgsWFSNewConnection()
|
||||
{
|
||||
if ( mCapabilities )
|
||||
if ( mCapabilities || mOAPIFLandingPage || mOAPIFApi )
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
delete mCapabilities;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsWFSNewConnection::versionDetectButton()
|
||||
QgsDataSourceUri QgsWFSNewConnection::createUri()
|
||||
{
|
||||
delete mCapabilities;
|
||||
|
||||
// Honor any defined authentication settings
|
||||
QgsDataSourceUri uri = QgsDataSourceUri();
|
||||
QgsDataSourceUri uri;
|
||||
uri.setParam( QStringLiteral( "url" ), urlTrimmed().toString() );
|
||||
uri.setUsername( authSettingsWidget()->username() );
|
||||
uri.setPassword( authSettingsWidget()->password() );
|
||||
uri.setAuthConfigId( authSettingsWidget()->configId() );
|
||||
return uri;
|
||||
}
|
||||
|
||||
mCapabilities = new QgsWfsCapabilities( uri.uri( false ) );
|
||||
connect( mCapabilities, &QgsWfsCapabilities::gotCapabilities, this, &QgsWFSNewConnection::capabilitiesReplyFinished );
|
||||
void QgsWFSNewConnection::versionDetectButton()
|
||||
{
|
||||
mCapabilities.reset( new QgsWfsCapabilities( createUri().uri( false ) ) );
|
||||
connect( mCapabilities.get(), &QgsWfsCapabilities::gotCapabilities, this, &QgsWFSNewConnection::capabilitiesReplyFinished );
|
||||
const bool synchronous = false;
|
||||
const bool forceRefresh = true;
|
||||
mCapabilities->setLogErrors( false ); // as this might be a OAPIF server
|
||||
if ( mCapabilities->requestCapabilities( synchronous, forceRefresh ) )
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
@ -59,8 +65,7 @@ void QgsWFSNewConnection::versionDetectButton()
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
|
||||
delete mCapabilities;
|
||||
mCapabilities = nullptr;
|
||||
mCapabilities.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,32 +79,136 @@ void QgsWFSNewConnection::capabilitiesReplyFinished()
|
||||
auto err = mCapabilities->errorCode();
|
||||
if ( err != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
QgsWfsGuiUtils::displayErrorMessageOnFailedCapabilities( mCapabilities, this );
|
||||
|
||||
delete mCapabilities;
|
||||
mCapabilities = nullptr;
|
||||
startOapifLandingPageRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &caps = mCapabilities->capabilities();
|
||||
int versionIdx = 0;
|
||||
int versionIdx = WFS_VERSION_MAX;
|
||||
wfsPageSizeLineEdit()->clear();
|
||||
if ( caps.version.startsWith( QLatin1String( "1.0" ) ) )
|
||||
{
|
||||
versionIdx = 1;
|
||||
versionIdx = WFS_VERSION_1_0;
|
||||
}
|
||||
else if ( caps.version.startsWith( QLatin1String( "1.1" ) ) )
|
||||
{
|
||||
versionIdx = 2;
|
||||
versionIdx = WFS_VERSION_1_1;
|
||||
}
|
||||
else if ( caps.version.startsWith( QLatin1String( "2.0" ) ) )
|
||||
{
|
||||
versionIdx = 3;
|
||||
versionIdx = WFS_VERSION_2_0;
|
||||
wfsPageSizeLineEdit()->setText( QString::number( caps.maxFeatures ) );
|
||||
}
|
||||
wfsVersionComboBox()->setCurrentIndex( versionIdx );
|
||||
wfsPagingEnabledCheckBox()->setChecked( caps.supportsPaging );
|
||||
|
||||
delete mCapabilities;
|
||||
mCapabilities = nullptr;
|
||||
mCapabilities.reset();
|
||||
}
|
||||
|
||||
void QgsWFSNewConnection::startOapifLandingPageRequest()
|
||||
{
|
||||
mOAPIFLandingPage.reset( new QgsOapifLandingPageRequest( createUri() ) );
|
||||
connect( mOAPIFLandingPage.get(), &QgsOapifLandingPageRequest::gotResponse, this, &QgsWFSNewConnection::oapifLandingPageReplyFinished );
|
||||
const bool synchronous = false;
|
||||
const bool forceRefresh = true;
|
||||
if ( mOAPIFLandingPage->request( synchronous, forceRefresh ) )
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox *box = new QMessageBox( QMessageBox::Critical, tr( "Error" ), tr( "Could not get landing page" ), QMessageBox::Ok, this );
|
||||
box->setAttribute( Qt::WA_DeleteOnClose );
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
|
||||
mOAPIFLandingPage.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsWFSNewConnection::oapifLandingPageReplyFinished()
|
||||
{
|
||||
if ( !mOAPIFLandingPage )
|
||||
return;
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if ( mOAPIFLandingPage->errorCode() != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
if ( mOAPIFLandingPage->errorCode() == QgsBaseNetworkRequest::ApplicationLevelError )
|
||||
{
|
||||
QMessageBox *box = new QMessageBox( QMessageBox::Critical, QObject::tr( "Invalid response" ), mOAPIFLandingPage->errorMessage(), QMessageBox::Ok, this );
|
||||
box->setAttribute( Qt::WA_DeleteOnClose );
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
}
|
||||
else if ( mCapabilities )
|
||||
{
|
||||
QgsMessageLog::logMessage( mCapabilities->errorMessage(), tr( "WFS" ) );
|
||||
QgsWfsGuiUtils::displayErrorMessageOnFailedCapabilities( mCapabilities.get(), this );
|
||||
}
|
||||
mCapabilities.reset();
|
||||
mOAPIFLandingPage.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
wfsVersionComboBox()->setCurrentIndex( WFS_VERSION_API_FEATURES );
|
||||
wfsPagingEnabledCheckBox()->setChecked( true );
|
||||
|
||||
mCapabilities.reset();
|
||||
|
||||
startOapifApiRequest();
|
||||
}
|
||||
|
||||
void QgsWFSNewConnection::startOapifApiRequest()
|
||||
{
|
||||
Q_ASSERT( mOAPIFLandingPage );
|
||||
mOAPIFApi.reset( new QgsOapifApiRequest( createUri(), mOAPIFLandingPage->apiUrl() ) );
|
||||
mOAPIFLandingPage.reset();
|
||||
|
||||
connect( mOAPIFApi.get(), &QgsOapifApiRequest::gotResponse, this, &QgsWFSNewConnection::oapifApiReplyFinished );
|
||||
const bool synchronous = false;
|
||||
const bool forceRefresh = true;
|
||||
if ( mOAPIFApi->request( synchronous, forceRefresh ) )
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox *box = new QMessageBox( QMessageBox::Critical, tr( "Error" ), tr( "Could not get API" ), QMessageBox::Ok, this );
|
||||
box->setAttribute( Qt::WA_DeleteOnClose );
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
|
||||
mOAPIFApi.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsWFSNewConnection::oapifApiReplyFinished()
|
||||
{
|
||||
if ( !mOAPIFApi )
|
||||
return;
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if ( mOAPIFApi->errorCode() != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
QMessageBox *box = new QMessageBox( QMessageBox::Critical, QObject::tr( "Invalid response" ), mOAPIFApi->errorMessage(), QMessageBox::Ok, this );
|
||||
box->setAttribute( Qt::WA_DeleteOnClose );
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
|
||||
mOAPIFApi.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
wfsPageSizeLineEdit()->clear();
|
||||
if ( mOAPIFApi->defaultLimit() > 0 && mOAPIFApi->maxLimit() > 0 )
|
||||
wfsPageSizeLineEdit()->setText( QString::number( std::min( std::max( 1000, mOAPIFApi->defaultLimit() ), mOAPIFApi->maxLimit() ) ) );
|
||||
else if ( mOAPIFApi->defaultLimit() > 0 )
|
||||
wfsPageSizeLineEdit()->setText( QString::number( mOAPIFApi->defaultLimit() ) );
|
||||
else if ( mOAPIFApi->maxLimit() > 0 )
|
||||
wfsPageSizeLineEdit()->setText( QString::number( mOAPIFApi->maxLimit() ) );
|
||||
|
||||
mOAPIFApi.reset();
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "qgsnewhttpconnection.h"
|
||||
#include "qgswfsconstants.h"
|
||||
#include "qgswfscapabilities.h"
|
||||
#include "qgsoapiflandingpagerequest.h"
|
||||
#include "qgsoapifapirequest.h"
|
||||
|
||||
class QgsWFSNewConnection : public QgsNewHttpConnection
|
||||
{
|
||||
@ -32,10 +34,17 @@ class QgsWFSNewConnection : public QgsNewHttpConnection
|
||||
private slots:
|
||||
void versionDetectButton();
|
||||
void capabilitiesReplyFinished();
|
||||
void oapifLandingPageReplyFinished();
|
||||
void oapifApiReplyFinished();
|
||||
|
||||
private:
|
||||
QgsWfsCapabilities *mCapabilities = nullptr;
|
||||
QgsDataSourceUri createUri();
|
||||
void startOapifLandingPageRequest();
|
||||
void startOapifApiRequest();
|
||||
|
||||
std::unique_ptr<QgsWfsCapabilities> mCapabilities;
|
||||
std::unique_ptr<QgsOapifLandingPageRequest> mOAPIFLandingPage;
|
||||
std::unique_ptr<QgsOapifApiRequest> mOAPIFApi;
|
||||
};
|
||||
|
||||
#endif //QGSWFSNEWCONNECTION_H
|
||||
|
@ -25,8 +25,8 @@ class QgsWfsSourceSelectProvider : public QgsSourceSelectProvider
|
||||
{
|
||||
public:
|
||||
|
||||
QString providerKey() const override { return QStringLiteral( "WFS" ); }
|
||||
QString text() const override { return QObject::tr( "WFS" ); }
|
||||
QString providerKey() const override { return QgsWFSProvider::WFS_PROVIDER_KEY; }
|
||||
QString text() const override { return QObject::tr( "WFS / OGC API - Features" ); }
|
||||
int ordering() const override { return QgsSourceSelectProvider::OrderRemoteProvider + 40; }
|
||||
QIcon icon() const override { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddWfsLayer.svg" ) ); }
|
||||
QgsAbstractDataSourceWidget *createDataSourceWidget( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::Widget, QgsProviderRegistry::WidgetMode widgetMode = QgsProviderRegistry::WidgetMode::Embedded ) const override
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmanageconnectionsdialog.h"
|
||||
#include "qgsoapifprovider.h"
|
||||
#include "qgssqlstatement.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsgui.h"
|
||||
@ -121,7 +122,6 @@ QgsWFSSourceSelect::~QgsWFSSourceSelect()
|
||||
|
||||
delete mItemDelegate;
|
||||
delete mProjectionSelector;
|
||||
delete mCapabilities;
|
||||
delete mModel;
|
||||
delete mModelProxy;
|
||||
delete mBuildQueryButton;
|
||||
@ -169,10 +169,7 @@ void QgsWFSSourceSelect::populateConnectionList()
|
||||
cmbConnections->setCurrentIndex( index );
|
||||
}
|
||||
|
||||
QgsWfsConnection connection( cmbConnections->currentText() );
|
||||
delete mCapabilities;
|
||||
mCapabilities = new QgsWfsCapabilities( connection.uri().uri() );
|
||||
connect( mCapabilities, &QgsWfsCapabilities::gotCapabilities, this, &QgsWFSSourceSelect::capabilitiesReplyFinished );
|
||||
changeConnection();
|
||||
}
|
||||
|
||||
QString QgsWFSSourceSelect::getPreferredCrs( const QSet<QString> &crsSet ) const
|
||||
@ -222,9 +219,16 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
|
||||
auto err = mCapabilities->errorCode();
|
||||
if ( err != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
QgsWfsGuiUtils::displayErrorMessageOnFailedCapabilities( mCapabilities, this );
|
||||
|
||||
emit enableButtons( false );
|
||||
if ( mVersion == QgsWFSConstants::VERSION_AUTO )
|
||||
{
|
||||
startOapifLandingPageRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsWfsGuiUtils::displayErrorMessageOnFailedCapabilities( mCapabilities.get(), this );
|
||||
mCapabilities.reset();
|
||||
emit enableButtons( false );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -248,7 +252,13 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
|
||||
mAvailableCRS.insert( featureType.name, featureType.crslist );
|
||||
}
|
||||
|
||||
if ( !mCaps.featureTypes.isEmpty() )
|
||||
resizeTreeViewAfterModelFill();
|
||||
}
|
||||
|
||||
|
||||
void QgsWFSSourceSelect::resizeTreeViewAfterModelFill()
|
||||
{
|
||||
if ( mModel->rowCount() > 0 )
|
||||
{
|
||||
treeView->resizeColumnToContents( MODEL_IDX_TITLE );
|
||||
treeView->resizeColumnToContents( MODEL_IDX_NAME );
|
||||
@ -276,6 +286,113 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
|
||||
}
|
||||
}
|
||||
|
||||
void QgsWFSSourceSelect::startOapifLandingPageRequest()
|
||||
{
|
||||
QgsWfsConnection connection( cmbConnections->currentText() );
|
||||
mOAPIFLandingPage.reset( new QgsOapifLandingPageRequest( connection.uri() ) );
|
||||
connect( mOAPIFLandingPage.get(), &QgsOapifLandingPageRequest::gotResponse, this, &QgsWFSSourceSelect::oapifLandingPageReplyFinished );
|
||||
const bool synchronous = false;
|
||||
const bool forceRefresh = true;
|
||||
mOAPIFLandingPage->request( synchronous, forceRefresh );
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
btnConnect->setEnabled( false );
|
||||
}
|
||||
|
||||
void QgsWFSSourceSelect::oapifLandingPageReplyFinished()
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
btnConnect->setEnabled( true );
|
||||
|
||||
if ( !mOAPIFLandingPage )
|
||||
return;
|
||||
|
||||
auto err = mOAPIFLandingPage->errorCode();
|
||||
if ( err != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
if ( mVersion == QgsWFSConstants::VERSION_AUTO && mCapabilities )
|
||||
{
|
||||
QgsWfsGuiUtils::displayErrorMessageOnFailedCapabilities( mCapabilities.get(), this );
|
||||
mCapabilities.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox *box = new QMessageBox( QMessageBox::Critical, tr( "Error" ), mOAPIFLandingPage->errorMessage(), QMessageBox::Ok, this );
|
||||
box->setAttribute( Qt::WA_DeleteOnClose );
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
}
|
||||
|
||||
mOAPIFLandingPage.reset();
|
||||
emit enableButtons( false );
|
||||
return;
|
||||
}
|
||||
mCapabilities.reset();
|
||||
|
||||
mAvailableCRS.clear();
|
||||
QString url( mOAPIFLandingPage->collectionsUrl() );
|
||||
mOAPIFLandingPage.reset();
|
||||
startOapifCollectionsRequest( url );
|
||||
}
|
||||
|
||||
void QgsWFSSourceSelect::startOapifCollectionsRequest( const QString &url )
|
||||
{
|
||||
QgsWfsConnection connection( cmbConnections->currentText() );
|
||||
mOAPIFCollections.reset( new QgsOapifCollectionsRequest( connection.uri(), url ) );
|
||||
connect( mOAPIFCollections.get(), &QgsOapifCollectionsRequest::gotResponse, this, &QgsWFSSourceSelect::oapifCollectionsReplyFinished );
|
||||
const bool synchronous = false;
|
||||
const bool forceRefresh = true;
|
||||
mOAPIFCollections->request( synchronous, forceRefresh );
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
btnConnect->setEnabled( false );
|
||||
}
|
||||
|
||||
void QgsWFSSourceSelect::oapifCollectionsReplyFinished()
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
btnConnect->setEnabled( true );
|
||||
if ( !mOAPIFCollections )
|
||||
return;
|
||||
|
||||
auto err = mOAPIFCollections->errorCode();
|
||||
if ( err != QgsBaseNetworkRequest::NoError )
|
||||
{
|
||||
QMessageBox *box = new QMessageBox( QMessageBox::Critical, tr( "Error" ), mOAPIFCollections->errorMessage(), QMessageBox::Ok, this );
|
||||
box->setAttribute( Qt::WA_DeleteOnClose );
|
||||
box->setModal( true );
|
||||
box->open();
|
||||
|
||||
mOAPIFCollections.reset();
|
||||
emit enableButtons( false );
|
||||
return;
|
||||
}
|
||||
|
||||
for ( const auto &collection : mOAPIFCollections->collections() )
|
||||
{
|
||||
// insert the typenames, titles and abstracts into the tree view
|
||||
QStandardItem *titleItem = new QStandardItem( collection.mTitle );
|
||||
QStandardItem *nameItem = new QStandardItem( collection.mId );
|
||||
QStandardItem *abstractItem = new QStandardItem( collection.mDescription );
|
||||
abstractItem->setToolTip( "<font color=black>" + collection.mDescription + "</font>" );
|
||||
abstractItem->setTextAlignment( Qt::AlignLeft | Qt::AlignTop );
|
||||
QStandardItem *filterItem = new QStandardItem();
|
||||
|
||||
typedef QList< QStandardItem * > StandardItemList;
|
||||
mModel->appendRow( StandardItemList() << titleItem << nameItem << abstractItem << filterItem );
|
||||
}
|
||||
|
||||
if ( !mOAPIFCollections->nextUrl().isEmpty() )
|
||||
{
|
||||
QString url( mOAPIFCollections->nextUrl() );
|
||||
mOAPIFCollections.reset();
|
||||
startOapifCollectionsRequest( url );
|
||||
return;
|
||||
}
|
||||
|
||||
mVersion = QStringLiteral( "OGC_API_FEATURES" );
|
||||
|
||||
resizeTreeViewAfterModelFill();
|
||||
}
|
||||
|
||||
void QgsWFSSourceSelect::addEntryToServerList()
|
||||
{
|
||||
auto nc = new QgsWFSNewConnection( this );
|
||||
@ -339,10 +456,24 @@ void QgsWFSSourceSelect::connectToServer()
|
||||
{
|
||||
mModel->removeRows( 0, mModel->rowCount() );
|
||||
}
|
||||
if ( mCapabilities )
|
||||
|
||||
QgsWfsConnection connection( cmbConnections->currentText() );
|
||||
|
||||
mVersion = QgsWFSDataSourceURI( connection.uri().uri() ).version();
|
||||
if ( mVersion == QLatin1String( "OGC_API_FEATURES" ) )
|
||||
{
|
||||
startOapifLandingPageRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
mCapabilities.reset( new QgsWfsCapabilities( connection.uri().uri() ) );
|
||||
connect( mCapabilities.get(), &QgsWfsCapabilities::gotCapabilities, this, &QgsWFSSourceSelect::capabilitiesReplyFinished );
|
||||
const bool synchronous = false;
|
||||
const bool forceRefresh = true;
|
||||
if ( mVersion == QgsWFSConstants::VERSION_AUTO )
|
||||
{
|
||||
mCapabilities->setLogErrors( false ); // as this might be a OAPIF server
|
||||
}
|
||||
mCapabilities->requestCapabilities( synchronous, forceRefresh );
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
}
|
||||
@ -386,7 +517,7 @@ void QgsWFSSourceSelect::addButtonClicked()
|
||||
mUri = QgsWFSDataSourceURI::build( connection.uri().uri( false ), typeName, pCrsString,
|
||||
sql, cbxFeatureCurrentViewExtent->isChecked() );
|
||||
|
||||
emit addVectorLayer( mUri, layerName );
|
||||
emit addVectorLayer( mUri, layerName, isOapif() ? QgsOapifProvider::OAPIF_PROVIDER_KEY : QgsWFSProvider::WFS_PROVIDER_KEY );
|
||||
}
|
||||
|
||||
if ( ! mHoldDialogOpen->isChecked() && widgetMode() == QgsProviderRegistry::WidgetMode::None )
|
||||
@ -689,12 +820,13 @@ void QgsWFSSourceSelect::cmbConnections_activated( int index )
|
||||
{
|
||||
Q_UNUSED( index )
|
||||
QgsWfsConnection::setSelectedConnection( cmbConnections->currentText() );
|
||||
changeConnection();
|
||||
}
|
||||
|
||||
QgsWfsConnection connection( cmbConnections->currentText() );
|
||||
|
||||
delete mCapabilities;
|
||||
mCapabilities = new QgsWfsCapabilities( connection.uri().uri() );
|
||||
connect( mCapabilities, &QgsWfsCapabilities::gotCapabilities, this, &QgsWFSSourceSelect::capabilitiesReplyFinished );
|
||||
void QgsWFSSourceSelect::changeConnection()
|
||||
{
|
||||
mCapabilities.reset();
|
||||
mOAPIFLandingPage.reset();
|
||||
}
|
||||
|
||||
void QgsWFSSourceSelect::btnSave_clicked()
|
||||
@ -720,6 +852,8 @@ void QgsWFSSourceSelect::btnLoad_clicked()
|
||||
|
||||
void QgsWFSSourceSelect::treeWidgetItemDoubleClicked( const QModelIndex &index )
|
||||
{
|
||||
if ( isOapif() )
|
||||
return;
|
||||
QgsDebugMsg( QStringLiteral( "double-click called" ) );
|
||||
buildQuery( index );
|
||||
}
|
||||
@ -729,7 +863,7 @@ void QgsWFSSourceSelect::treeWidgetCurrentRowChanged( const QModelIndex ¤t
|
||||
Q_UNUSED( previous )
|
||||
QgsDebugMsg( QStringLiteral( "treeWidget_currentRowChanged called" ) );
|
||||
changeCRSFilter();
|
||||
mBuildQueryButton->setEnabled( current.isValid() );
|
||||
mBuildQueryButton->setEnabled( !isOapif() && current.isValid() );
|
||||
emit enableButtons( current.isValid() );
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "ui_qgswfssourceselectbase.h"
|
||||
#include "qgshelp.h"
|
||||
#include "qgswfscapabilities.h"
|
||||
#include "qgsoapiflandingpagerequest.h"
|
||||
#include "qgsoapifcollection.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsabstractdatasourcewidget.h"
|
||||
#include "qgssqlcomposerdialog.h"
|
||||
@ -78,7 +80,9 @@ class QgsWFSSourceSelect: public QgsAbstractDataSourceWidget, private Ui::QgsWFS
|
||||
The first string is the typename, the corresponding list
|
||||
stores the CRS for the typename in the form 'EPSG:XXXX'*/
|
||||
QMap<QString, QStringList > mAvailableCRS;
|
||||
QgsWfsCapabilities *mCapabilities = nullptr;
|
||||
std::unique_ptr<QgsWfsCapabilities> mCapabilities;
|
||||
std::unique_ptr<QgsOapifLandingPageRequest> mOAPIFLandingPage;
|
||||
std::unique_ptr<QgsOapifCollectionsRequest> mOAPIFCollections;
|
||||
QString mUri; // data source URI
|
||||
QgsWFSItemDelegate *mItemDelegate = nullptr;
|
||||
QStandardItemModel *mModel = nullptr;
|
||||
@ -87,6 +91,7 @@ class QgsWFSSourceSelect: public QgsAbstractDataSourceWidget, private Ui::QgsWFS
|
||||
QgsWfsCapabilities::Capabilities mCaps;
|
||||
QModelIndex mSQLIndex;
|
||||
QgsSQLComposerDialog *mSQLComposerDialog = nullptr;
|
||||
QString mVersion;
|
||||
|
||||
/**
|
||||
* Returns the best suited CRS from a set of authority ids
|
||||
@ -114,6 +119,8 @@ class QgsWFSSourceSelect: public QgsAbstractDataSourceWidget, private Ui::QgsWFS
|
||||
void changeCRSFilter();
|
||||
void cmbConnections_activated( int index );
|
||||
void capabilitiesReplyFinished();
|
||||
void oapifLandingPageReplyFinished();
|
||||
void oapifCollectionsReplyFinished();
|
||||
void btnSave_clicked();
|
||||
void btnLoad_clicked();
|
||||
void treeWidgetItemDoubleClicked( const QModelIndex &index );
|
||||
@ -123,7 +130,11 @@ class QgsWFSSourceSelect: public QgsAbstractDataSourceWidget, private Ui::QgsWFS
|
||||
void updateSql();
|
||||
|
||||
void populateConnectionList();
|
||||
|
||||
void changeConnection();
|
||||
void startOapifLandingPageRequest();
|
||||
void startOapifCollectionsRequest( const QString &url );
|
||||
void resizeTreeViewAfterModelFill();
|
||||
bool isOapif() const { return mVersion == QLatin1String( "OGC_API_FEATURES" ); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -117,6 +117,8 @@ class TestPyQgsWFSProviderGUI(unittest.TestCase):
|
||||
QTest.mouseClick(btnConnect, Qt.LeftButton)
|
||||
# Depends on asynchronous signal
|
||||
QApplication.processEvents()
|
||||
# Second attempt for OAPIF request
|
||||
QApplication.processEvents()
|
||||
error_box = find_window('WFSCapabilitiesErrorBox')
|
||||
self.assertIsNotNone(error_box)
|
||||
# Close error box
|
||||
|
Loading…
x
Reference in New Issue
Block a user