mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-22 00:06:12 -05:00
Create data item provider for QgsGdalCloudProviderConnections
Adds a browser data item provider which shows connections to cloud storage providers handled by GDAL's VSI handlers. Allows loading vector and raster layers from VSI cloud storage connections via the browser.
This commit is contained in:
parent
392eaac69a
commit
da2b387204
@ -1004,6 +1004,7 @@
|
||||
<file>themes/default/mIconSearchWrapAround.svg</file>
|
||||
<file>themes/default/mIconSearchRegex.svg</file>
|
||||
<file>themes/default/mActionReplace.svg</file>
|
||||
<file>themes/default/mIconCloud.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images/tips">
|
||||
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
|
||||
|
1
images/themes/default/mIconCloud.svg
Normal file
1
images/themes/default/mIconCloud.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" width="16" height="16"><defs><linearGradient id="d"><stop offset="0" style="stop-color:#cbd9ef;stop-opacity:1"/><stop offset="1" style="stop-color:#93b1d1;stop-opacity:1"/></linearGradient><linearGradient id="c"><stop offset="0" style="stop-color:#ccdaef;stop-opacity:1"/><stop offset="1" style="stop-color:#b3c5dd;stop-opacity:1"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#aec3dc;stop-opacity:1"/><stop offset="1" style="stop-color:#8babcd;stop-opacity:1"/></linearGradient><linearGradient id="a"><stop offset="0" style="stop-color:#aec5df;stop-opacity:1"/><stop offset="1" style="stop-color:#89aad1;stop-opacity:1"/></linearGradient><linearGradient xlink:href="#d" id="e" x1="5.406" x2="13.188" y1="4.938" y2="11.531" gradientUnits="userSpaceOnUse"/></defs><path d="M7.729 3.634a3.503 3.503 0 0 0-3.45 3.476v.168l-.158-.045a1.661 1.661 0 0 0-1.744.547 1.659 1.659 0 0 0-.336 1.385l.016.076-.06.047a1.54 1.54 0 0 0 .958 2.742H13.28c.776 0 1.43-.579 1.525-1.35.15-1.222-.852-1.502-1.205-1.646.25-.797-.023-1.331-.508-1.972a2.181 2.181 0 0 0-1.68-.786h-.091l-.141.01-.027-.097h.002a3.504 3.504 0 0 0-3.426-2.555Z" style="stroke:#476280;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1;fill:url(#e)"/><path d="M4.254 7.071c.099.854.09 1.11.42 1.757M14.355 9.43c-.64-.627-2.027-.672-2.027-.672" style="fill:none;fill-opacity:1;stroke:#476280;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"/></svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -308,6 +308,7 @@ set(QGIS_CORE_SRCS
|
||||
providers/arcgis/qgsarcgisrestutils.cpp
|
||||
|
||||
providers/gdal/qgsgdalcloudconnection.cpp
|
||||
providers/gdal/qgsgdalclouddataitems.cpp
|
||||
providers/gdal/qgsgdalproviderbase.cpp
|
||||
providers/gdal/qgsgdalprovider.cpp
|
||||
|
||||
@ -1815,6 +1816,7 @@ set(QGIS_CORE_HDRS
|
||||
providers/arcgis/qgsarcgisrestutils.h
|
||||
|
||||
providers/gdal/qgsgdalcloudconnection.h
|
||||
providers/gdal/qgsgdalclouddataitems.h
|
||||
providers/gdal/qgsgdalprovider.h
|
||||
|
||||
providers/memory/qgsmemoryfeatureiterator.h
|
||||
|
232
src/core/providers/gdal/qgsgdalclouddataitems.cpp
Normal file
232
src/core/providers/gdal/qgsgdalclouddataitems.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/***************************************************************************
|
||||
qgsgdalclouddataitems.cpp
|
||||
---------------------
|
||||
begin : June 2024
|
||||
copyright : (C) 2024 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgsgdalclouddataitems.h"
|
||||
#include "qgsprovidermetadata.h"
|
||||
#include "qgsgdalcloudconnection.h"
|
||||
#include "qgsproviderregistry.h"
|
||||
#include "qgsgdalutils.h"
|
||||
#include "qgsfilebaseddataitemprovider.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
//
|
||||
// QgsGdalCloudRootItem
|
||||
//
|
||||
|
||||
QgsGdalCloudRootItem::QgsGdalCloudRootItem( QgsDataItem *parent, QString name, QString path )
|
||||
: QgsConnectionsRootItem( parent, name, path, QStringLiteral( "cloud" ) )
|
||||
{
|
||||
mCapabilities |= Qgis::BrowserItemCapability::Fast;
|
||||
mIconName = QStringLiteral( "mIconCloud.svg" );
|
||||
populate();
|
||||
}
|
||||
|
||||
QVector<QgsDataItem *> QgsGdalCloudRootItem::createChildren()
|
||||
{
|
||||
QVector<QgsDataItem *> connections;
|
||||
|
||||
QList< QgsGdalUtils::VsiNetworkFileSystemDetails > vsiDetails = QgsGdalUtils::vsiNetworkFileSystems();
|
||||
std::sort( vsiDetails.begin(), vsiDetails.end(), []( const QgsGdalUtils::VsiNetworkFileSystemDetails & a, const QgsGdalUtils::VsiNetworkFileSystemDetails & b )
|
||||
{
|
||||
return QString::localeAwareCompare( a.name, b.name ) < 0;
|
||||
} );
|
||||
|
||||
const QStringList connectionList = QgsGdalCloudProviderConnection::connectionList();
|
||||
|
||||
for ( const QgsGdalUtils::VsiNetworkFileSystemDetails &handler : vsiDetails )
|
||||
{
|
||||
// only expose items for drivers with stored connections
|
||||
bool foundConnection = false;
|
||||
for ( const QString &connName : connectionList )
|
||||
{
|
||||
const QgsGdalCloudProviderConnection::Data connectionData = QgsGdalCloudProviderConnection::connection( connName );
|
||||
if ( connectionData.vsiHandler == handler.identifier )
|
||||
{
|
||||
foundConnection = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !foundConnection )
|
||||
continue;
|
||||
|
||||
QgsDataItem *conn = new QgsGdalCloudProviderItem( this, handler );
|
||||
connections.append( conn );
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
//
|
||||
// QgsGdalCloudProviderItem
|
||||
//
|
||||
|
||||
QgsGdalCloudProviderItem::QgsGdalCloudProviderItem( QgsDataItem *parent, const QgsGdalUtils::VsiNetworkFileSystemDetails &handler )
|
||||
: QgsDataCollectionItem( parent, handler.name, handler.identifier, handler.identifier )
|
||||
, mVsiHandler( handler )
|
||||
{
|
||||
mIconName = QStringLiteral( "mIconCloud.svg" );
|
||||
}
|
||||
|
||||
QVector<QgsDataItem *> QgsGdalCloudProviderItem::createChildren()
|
||||
{
|
||||
QVector<QgsDataItem *> connections;
|
||||
const auto connectionList = QgsGdalCloudProviderConnection::connectionList();
|
||||
for ( const QString &connName : connectionList )
|
||||
{
|
||||
const QgsGdalCloudProviderConnection::Data connectionData = QgsGdalCloudProviderConnection::connection( connName );
|
||||
if ( connectionData.vsiHandler != mVsiHandler.identifier )
|
||||
continue;
|
||||
|
||||
QgsDataItem *conn = new QgsGdalCloudConnectionItem( this, connName, mPath + '/' + connName );
|
||||
connections.append( conn );
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
|
||||
//
|
||||
// QgsGdalCloudConnectionItem
|
||||
//
|
||||
|
||||
QgsGdalCloudConnectionItem::QgsGdalCloudConnectionItem( QgsDataItem *parent, const QString &name, const QString &path )
|
||||
: QgsDataCollectionItem( parent, name, path )
|
||||
, mConnName( name )
|
||||
{
|
||||
mIconName = QStringLiteral( "mIconConnect.svg" );
|
||||
mCapabilities |= Qgis::BrowserItemCapability::Fertile;
|
||||
}
|
||||
|
||||
bool QgsGdalCloudConnectionItem::equal( const QgsDataItem *other )
|
||||
{
|
||||
const QgsGdalCloudConnectionItem *o = qobject_cast<const QgsGdalCloudConnectionItem *>( other );
|
||||
return ( type() == other->type() && o && mPath == o->mPath && mName == o->mName && mConnName == o->mConnName );
|
||||
}
|
||||
|
||||
QVector<QgsDataItem *> QgsGdalCloudConnectionItem::createChildren()
|
||||
{
|
||||
QVector<QgsDataItem *> children;
|
||||
|
||||
const QgsGdalCloudProviderConnection::Data connectionData = QgsGdalCloudProviderConnection::connection( mConnName );
|
||||
QgsGdalCloudProviderConnection conn = QgsGdalCloudProviderConnection( mConnName );
|
||||
const QList< QgsGdalCloudProviderConnection::DirectoryObject > objects = conn.contents( connectionData.rootPath );
|
||||
|
||||
QVariantMap extraUriParts;
|
||||
if ( !connectionData.credentialOptions.isEmpty() )
|
||||
{
|
||||
extraUriParts.insert( QStringLiteral( "credentialOptions" ), connectionData.credentialOptions );
|
||||
}
|
||||
|
||||
for ( const QgsGdalCloudProviderConnection::DirectoryObject &object : objects )
|
||||
{
|
||||
const QString subPath = connectionData.rootPath.isEmpty() ? object.name : ( connectionData.rootPath + '/' + object.name );
|
||||
if ( object.isDir )
|
||||
{
|
||||
QgsGdalCloudDirectoryItem *child = new QgsGdalCloudDirectoryItem( this,
|
||||
object.name, mPath + '/' + object.name, mConnName, subPath );
|
||||
children.append( child );
|
||||
}
|
||||
else if ( object.isFile )
|
||||
{
|
||||
const QString filePath = QStringLiteral( "/%1/%2/%3" ).arg( connectionData.vsiHandler, connectionData.container, subPath );
|
||||
// QgsFileBasedDataItemProvider uses paths for item uris by default, so we need to specify that the credentialOptions should be appended to the layer URIs
|
||||
if ( QgsDataItem *item = QgsFileBasedDataItemProvider::createLayerItemForPath( filePath, this, { QStringLiteral( "gdal" ), QStringLiteral( "ogr" )}, extraUriParts, Qgis::SublayerQueryFlag::FastScan ) )
|
||||
{
|
||||
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ReadOnly );
|
||||
children.append( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
//
|
||||
// QgsGdalCloudDirectoryItem
|
||||
//
|
||||
|
||||
QgsGdalCloudDirectoryItem::QgsGdalCloudDirectoryItem( QgsDataItem *parent, QString name, QString path, const QString &connectionName, const QString &directory )
|
||||
: QgsDataCollectionItem( parent, name, path, connectionName )
|
||||
, mConnName( connectionName )
|
||||
, mDirectory( directory )
|
||||
{
|
||||
mIconName = QStringLiteral( "mIconFolder.svg" );
|
||||
mCapabilities |= Qgis::BrowserItemCapability::Fertile;
|
||||
}
|
||||
|
||||
QVector<QgsDataItem *> QgsGdalCloudDirectoryItem::createChildren()
|
||||
{
|
||||
QVector<QgsDataItem *> children;
|
||||
|
||||
const QgsGdalCloudProviderConnection::Data connectionData = QgsGdalCloudProviderConnection::connection( mConnName );
|
||||
QgsGdalCloudProviderConnection conn = QgsGdalCloudProviderConnection( mConnName );
|
||||
|
||||
const QList< QgsGdalCloudProviderConnection::DirectoryObject > objects = conn.contents( mDirectory );
|
||||
|
||||
QVariantMap extraUriParts;
|
||||
if ( !connectionData.credentialOptions.isEmpty() )
|
||||
{
|
||||
extraUriParts.insert( QStringLiteral( "credentialOptions" ), connectionData.credentialOptions );
|
||||
}
|
||||
|
||||
for ( const QgsGdalCloudProviderConnection::DirectoryObject &object : objects )
|
||||
{
|
||||
const QString subPath = mDirectory + '/' + object.name;
|
||||
if ( object.isDir )
|
||||
{
|
||||
QgsGdalCloudDirectoryItem *child = new QgsGdalCloudDirectoryItem( this,
|
||||
object.name, mPath + '/' + object.name, mConnName, subPath );
|
||||
children.append( child );
|
||||
}
|
||||
else if ( object.isFile )
|
||||
{
|
||||
const QString filePath = QStringLiteral( "/%1/%2/%3" ).arg( connectionData.vsiHandler, connectionData.container, subPath );
|
||||
// QgsFileBasedDataItemProvider uses paths for item uris by default, so we need to specify that the credentialOptions should be appended to the layer URIs
|
||||
if ( QgsDataItem *item = QgsFileBasedDataItemProvider::createLayerItemForPath( filePath, this, { QStringLiteral( "gdal" ), QStringLiteral( "ogr" )}, extraUriParts, Qgis::SublayerQueryFlag::FastScan ) )
|
||||
{
|
||||
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ReadOnly );
|
||||
children.append( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
//
|
||||
// QgsGdalCloudDataItemProvider
|
||||
//
|
||||
|
||||
QString QgsGdalCloudDataItemProvider::name()
|
||||
{
|
||||
return QStringLiteral( "GDAL Cloud" );
|
||||
}
|
||||
|
||||
QString QgsGdalCloudDataItemProvider::dataProviderKey() const
|
||||
{
|
||||
return QStringLiteral( "cloud" );
|
||||
}
|
||||
|
||||
Qgis::DataItemProviderCapabilities QgsGdalCloudDataItemProvider::capabilities() const
|
||||
{
|
||||
return Qgis::DataItemProviderCapability::NetworkSources;
|
||||
}
|
||||
|
||||
QgsDataItem *QgsGdalCloudDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
|
||||
{
|
||||
if ( path.isEmpty() )
|
||||
return new QgsGdalCloudRootItem( parentItem, QObject::tr( "Cloud" ), QStringLiteral( "cloud:" ) );
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
///@endcond
|
89
src/core/providers/gdal/qgsgdalclouddataitems.h
Normal file
89
src/core/providers/gdal/qgsgdalclouddataitems.h
Normal file
@ -0,0 +1,89 @@
|
||||
/***************************************************************************
|
||||
qgsgdalclouddataitems.h
|
||||
---------------------
|
||||
begin : June 2024
|
||||
copyright : (C) 2024 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSGDALCLOUDDATAITEMS_H
|
||||
#define QGSGDALCLOUDDATAITEMS_H
|
||||
|
||||
#include "qgsconnectionsitem.h"
|
||||
#include "qgsdataitemprovider.h"
|
||||
#include "qgsgdalutils.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
#define SIP_NO_FILE
|
||||
|
||||
//! Root item for GDAL cloud connections
|
||||
class CORE_EXPORT QgsGdalCloudRootItem : public QgsConnectionsRootItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsGdalCloudRootItem( QgsDataItem *parent, QString name, QString path );
|
||||
|
||||
QVector<QgsDataItem *> createChildren() override;
|
||||
|
||||
QVariant sortKey() const override { return 8; }
|
||||
|
||||
};
|
||||
|
||||
//! Generic item for individual GDAL cloud providers, eg "Amazon S3", "Microsoft Azure"
|
||||
class CORE_EXPORT QgsGdalCloudProviderItem : public QgsDataCollectionItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsGdalCloudProviderItem( QgsDataItem *parent, const QgsGdalUtils::VsiNetworkFileSystemDetails &handler );
|
||||
QVector<QgsDataItem *> createChildren() override;
|
||||
const QgsGdalUtils::VsiNetworkFileSystemDetails &vsiHandler() const { return mVsiHandler; }
|
||||
|
||||
private:
|
||||
QgsGdalUtils::VsiNetworkFileSystemDetails mVsiHandler;
|
||||
|
||||
};
|
||||
|
||||
//! Item for a specific connection to a cloud container
|
||||
class CORE_EXPORT QgsGdalCloudConnectionItem : public QgsDataCollectionItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsGdalCloudConnectionItem( QgsDataItem *parent, const QString &name, const QString &path );
|
||||
bool equal( const QgsDataItem *other ) override;
|
||||
QVector<QgsDataItem *> createChildren() override;
|
||||
private:
|
||||
QString mConnName;
|
||||
};
|
||||
|
||||
//! Item for a directory within a cloud container
|
||||
class CORE_EXPORT QgsGdalCloudDirectoryItem : public QgsDataCollectionItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsGdalCloudDirectoryItem( QgsDataItem *parent, QString name, QString path, const QString &connectionName, const QString &directory );
|
||||
QVector<QgsDataItem *> createChildren() override;
|
||||
private:
|
||||
|
||||
QString mConnName;
|
||||
QString mDirectory;
|
||||
};
|
||||
|
||||
//! Provider for GDAL cloud root data item
|
||||
class QgsGdalCloudDataItemProvider : public QgsDataItemProvider
|
||||
{
|
||||
public:
|
||||
QString name() override;
|
||||
QString dataProviderKey() const override;
|
||||
Qgis::DataItemProviderCapabilities capabilities() const override;
|
||||
QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override;
|
||||
};
|
||||
|
||||
///@endcond
|
||||
|
||||
#endif // QGSGDALCLOUDDATAITEMS_H
|
@ -42,6 +42,7 @@
|
||||
#include "qgsproviderutils.h"
|
||||
#include "qgscplerrorhandler_p.h"
|
||||
#include "qgsmetadatautils.h"
|
||||
#include "qgsgdalclouddataitems.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QColor>
|
||||
@ -4627,6 +4628,14 @@ QList<Qgis::LayerType> QgsGdalProviderMetadata::supportedLayerTypes() const
|
||||
return { Qgis::LayerType::Raster };
|
||||
}
|
||||
|
||||
QList<QgsDataItemProvider *> QgsGdalProviderMetadata::dataItemProviders() const
|
||||
{
|
||||
return
|
||||
{
|
||||
new QgsGdalCloudDataItemProvider()
|
||||
};
|
||||
}
|
||||
|
||||
int QgsGdalProviderMetadata::listStyles( const QString &uri, QStringList &ids, QStringList &names,
|
||||
QStringList &descriptions, QString &errCause )
|
||||
{
|
||||
|
@ -410,6 +410,7 @@ class QgsGdalProviderMetadata final: public QgsProviderMetadata
|
||||
QStringList sidecarFilesForUri( const QString &uri ) const override;
|
||||
QList< Qgis::LayerType > supportedLayerTypes() const override;
|
||||
|
||||
QList< QgsDataItemProvider * > dataItemProviders() const override;
|
||||
int listStyles( const QString &uri, QStringList &ids, QStringList &names,
|
||||
QStringList &descriptions, QString &errCause ) override;
|
||||
bool styleExists( const QString &uri, const QString &styleId, QString &errCause SIP_OUT ) override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user