30#include "moc_qgsstacdataitems.cpp"
32using namespace Qt::StringLiterals;
44 :
QgsDataItem(
Qgis::BrowserItemType::Custom, parent, name, QString(
"%1/%2" ).arg( parent->path(), name ), u
"special:Stac"_s )
50 mIcon = metadata->icon();
54 mIconName = u
"downloading_svg.svg"_s;
65 if (
const QgsStacConnectionItem *ci = qobject_cast<const QgsStacConnectionItem *>( item ) )
66 return ci->controller();
78void QgsStacAssetItem::updateToolTip()
80 QString title = mStacAsset->title();
81 if ( title.isNull() || title.isEmpty() )
85 mToolTip = u
"STAC Asset:\n%1\n%2"_s.arg( title, mStacAsset->href() );
93QgsStacAssetLayerItem *QgsStacAssetLayerItem::createItemForAsset(
QgsDataItem *parent,
const QString &name,
const QgsStacAsset *asset,
const QString &authcfg )
96 QUrl url( asset->
href() );
97 if ( url.isLocalFile() )
103 uri = asset->
uri( authcfg );
115 else if ( uri.
layerType ==
"pointcloud"_L1 )
120 return new QgsStacAssetLayerItem( parent, name, asset, uri, layerType, uri.
providerKey );
123QgsStacAssetLayerItem::QgsStacAssetLayerItem(
126 :
QgsLayerItem( parent, name, QString(
"%1/%2" ).arg( parent->path(), name ), uri.uri, layerType, providerKey )
127 , mStacAsset( asset )
137bool QgsStacAssetLayerItem::hasDragEnabled()
const
147 if (
const QgsStacConnectionItem *ci = qobject_cast<const QgsStacConnectionItem *>( item ) )
148 return ci->controller();
160bool QgsStacAssetLayerItem::equal(
const QgsDataItem * )
165void QgsStacAssetLayerItem::updateToolTip()
167 QString title = mStacAsset->title();
168 if ( title.isNull() || title.isEmpty() )
172 mToolTip = u
"STAC Asset:\n%1\n%2"_s.arg( title, mStacAsset->href() );
179QgsStacFetchMoreItem::QgsStacFetchMoreItem(
QgsDataItem *parent,
const QString &name )
180 :
QgsDataItem(
Qgis::BrowserItemType::Custom, parent, name, QString() )
185bool QgsStacFetchMoreItem::handleDoubleClick()
187 if ( QgsStacCatalogItem *catalog = qobject_cast<QgsStacCatalogItem *>( mParent ) )
189 catalog->fetchMoreChildren();
202QgsStacItemItem::QgsStacItemItem(
QgsDataItem *parent,
const QString &name,
const QString &path )
203 :
QgsDataItem(
Qgis::BrowserItemType::Custom, parent, name.isEmpty() ? path : name, path, u
"special:Stac"_s )
205 mIconName = u
"mActionPropertiesWidget.svg"_s;
210QVector<QgsDataItem *> QgsStacItemItem::createChildren()
213 const QString authcfg = controller->
authCfg();
218 return {
new QgsErrorItem(
this, error, path() + u
"/error"_s ) };
221 QVector<QgsDataItem *> contents;
222 contents.reserve( mStacItem->assets().size() );
223 const QMap<QString, QgsStacAsset> assets = mStacItem->assets();
224 for (
auto it = assets.constBegin(); it != assets.constEnd(); ++it )
226 if ( it.value().uri( authcfg ).isValid() && it.value().isCloudOptimized() )
229 QgsStacAssetLayerItem *assetItem = QgsStacAssetLayerItem::createItemForAsset(
this, it.key(), &it.value(), authcfg );
230 contents.append( assetItem );
234 QgsStacAssetItem *assetItem =
new QgsStacAssetItem(
this, it.key(), &it.value() );
235 contents.append( assetItem );
241bool QgsStacItemItem::hasDragEnabled()
const
246 const QMap<QString, QgsStacAsset> assets = mStacItem->assets();
247 for (
auto it = assets.constBegin(); it != assets.constEnd(); ++it )
249 if ( it->isCloudOptimized() )
262 const QString authcfg = stacController()->authCfg();
264 const QMap<QString, QgsStacAsset> assets = mStacItem->assets();
265 for (
auto it = assets.constBegin(); it != assets.constEnd(); ++it )
282void QgsStacItemItem::updateToolTip()
284 QString name = mName;
287 name = mStacItem->properties().value( u
"title"_s, mName ).toString();
289 mToolTip = u
"STAC Item:\n%1\n%2"_s.arg( name, mPath );
297 if (
const QgsStacConnectionItem *ci = qobject_cast<const QgsStacConnectionItem *>( item ) )
298 return ci->controller();
305void QgsStacItemItem::setStacItem( std::unique_ptr<QgsStacItem> item )
307 mStacItem = std::move( item );
313 return mStacItem.get();
316void QgsStacItemItem::itemRequestFinished(
int requestId, QString error )
320 setStacItem( std::move(
object ) );
323 mIconName = u
"mActionPropertiesWidget.svg"_s;
324 QString name = mStacItem->properties().value( u
"title"_s, QString() ).toString();
325 if ( name.isEmpty() )
326 name = mStacItem->id();
331 mIconName = u
"/mIconDelete.svg"_s;
341QgsStacCatalogItem::QgsStacCatalogItem(
QgsDataItem *parent,
const QString &name,
const QString &path )
344 mIconName = u
"mIconFolder.svg"_s;
347 if ( name.isEmpty() )
349 mName = path.mid( path.lastIndexOf(
'/' ) + 1 );
355bool QgsStacCatalogItem::isCatalog()
const
357 return !mIsCollection;
360bool QgsStacCatalogItem::isCollection()
const
362 return mIsCollection;
370 if (
const QgsStacConnectionItem *ci = qobject_cast< const QgsStacConnectionItem *>( item ) )
371 return ci->controller();
383 if (
const QgsStacConnectionItem *ci = qobject_cast< const QgsStacConnectionItem *>( item ) )
384 return ci->mStacCatalog.get();
391QgsStacFetchMoreItem *QgsStacCatalogItem::fetchMoreItem()
const
395 if ( QgsStacFetchMoreItem *moreItem = qobject_cast< QgsStacFetchMoreItem *>( item ) )
403void QgsStacCatalogItem::childrenCreated()
409 for (
QgsDataItem *child : std::as_const( mChildren ) )
411 if ( QgsStacItemItem *item = qobject_cast<QgsStacItemItem *>( child ) )
416 const int requestId = stacController()->fetchStacObjectAsync( item->
path() );
417 item->setProperty(
"requestId", requestId );
422void QgsStacCatalogItem::onControllerFinished(
int requestId,
const QString &error )
424 for (
QgsDataItem *child : std::as_const( mChildren ) )
429 if ( QgsStacItemItem *item = qobject_cast<QgsStacItemItem *>( child ) )
431 if ( item->property(
"requestId" ).toInt() == requestId )
433 item->itemRequestFinished( requestId, error );
439QVector<QgsDataItem *> QgsStacCatalogItem::createChildren()
444 const QString authcfg = controller->
authCfg();
447 return {
new QgsErrorItem(
this, error, path() + u
"/error"_s ) };
451 const bool supportsCollections = root && root->
conformsTo( u
"https://api.stacspec.org/v1.0.0/collections"_s );
452 const bool supportsItems = root && root->
conformsTo( u
"https://api.stacspec.org/v1.0.0/ogcapi-features"_s );
455 QVector<QgsDataItem *> contents;
456 const QVector< QgsStacLink > links = mStacCatalog->links();
459 bool useItemsEndpoint =
false;
460 bool useCollectionsEndpoint =
false;
461 if ( supportsCollections || supportsItems )
465 if ( link.relation() ==
"items"_L1 )
467 useItemsEndpoint =
true;
469 else if ( link.relation() ==
"data"_L1 && link.href().endsWith(
"/collections"_L1 ) )
471 useCollectionsEndpoint =
true;
474 if ( supportsItems == useItemsEndpoint && supportsCollections == useCollectionsEndpoint )
482 if ( link.relation() ==
"self"_L1 || link.relation() ==
"root"_L1 || link.relation() ==
"parent"_L1 || link.relation() ==
"collection"_L1 )
485 if ( link.relation() ==
"child"_L1 && !useCollectionsEndpoint )
488 QgsStacCatalogItem *
c =
new QgsStacCatalogItem(
this, link.title(), link.href() );
489 contents.append(
c );
491 else if ( link.relation() ==
"data"_L1 && link.href().endsWith(
"/collections"_L1 ) )
495 std::unique_ptr< QgsStacCollectionList > cols( controller->
fetchCollections( link.href(), &error ) );
498 contents.append( createCollections( cols->takeCollections() ) );
499 itemsCount = cols->numberMatched();
504 contents.append(
new QgsErrorItem(
this, error, path() + u
"/error"_s ) );
507 else if ( link.relation() ==
"item"_L1 && !useItemsEndpoint )
514 QgsStacItemItem *i =
new QgsStacItemItem(
this, link.title(), link.href() );
515 contents.append( i );
517 else if ( link.relation() ==
"items"_L1 && useItemsEndpoint )
521 std::unique_ptr< QgsStacItemCollection > ic( controller->
fetchItemCollection( link.href(), &error ) );
524 contents.append( createItems( ic->takeItems() ) );
525 mFetchMoreUrl = ic->nextUrl();
526 itemsCount = ic->numberMatched();
531 contents.append(
new QgsErrorItem(
this, error, path() + u
"/error"_s ) );
542 const QMap<QString, QgsStacAsset> assets = collection->assets();
543 for (
auto it = assets.constBegin(); it != assets.constEnd(); ++it )
545 if ( it.value().uri( authcfg ).isValid() && it.value().isCloudOptimized() )
548 QgsStacAssetLayerItem *assetItem = QgsStacAssetLayerItem::createItemForAsset(
this, it.key(), &it.value(), authcfg );
549 contents.append( assetItem );
553 QgsStacAssetItem *assetItem =
new QgsStacAssetItem(
this, it.key(), &it.value() );
554 contents.append( assetItem );
559 QgsStacFetchMoreItem *moreItem =
nullptr;
560 if ( !mFetchMoreUrl.isEmpty() )
562 if ( itemsCount >= 0 )
563 moreItem =
new QgsStacFetchMoreItem(
this, tr(
"Double-click to fetch more (%L1 total items)..." ).arg( itemsCount ) );
565 moreItem =
new QgsStacFetchMoreItem(
this, tr(
"Double-click to fetch more items..." ) );
569 moreItem =
new QgsStacFetchMoreItem(
this, tr(
"%1 more items" ).arg( itemsCount -
MAX_DISPLAYED_ITEMS ) );
573 contents.append( moreItem );
578bool QgsStacCatalogItem::equal(
const QgsDataItem *other )
584void QgsStacCatalogItem::updateToolTip()
586 mToolTip = u
"STAC Catalog:\n%1\n%2"_s.arg( mName, mPath );
589 const int pos = mToolTip.indexOf(
':' );
590 mToolTip.replace( 0, pos, u
"STAC Collection"_s );
594void QgsStacCatalogItem::setStacCatalog( std::unique_ptr<QgsStacCatalog> catalog )
596 mStacCatalog = std::move( catalog );
599 if ( mName.isEmpty() && !mStacCatalog->title().isEmpty() )
600 setName( mStacCatalog->title() );
604 mIsCollection =
true;
605 mIconName = u
"mIconFolderOpen.svg"_s;
613 return mStacCatalog.get();
616QVector< QgsDataItem * > QgsStacCatalogItem::createItems(
const QVector<QgsStacItem *> items )
618 QVector< QgsDataItem * > contents;
619 contents.reserve( items.size() );
625 std::unique_ptr< QgsStacItem > object( item );
627 const QString name = item->properties().value( u
"title"_s, item->id() ).toString();
629 QgsStacItemItem *i =
new QgsStacItemItem(
this, name, item->url() );
630 i->setStacItem( std::move(
object ) );
632 contents.append( i );
637QVector<QgsDataItem *> QgsStacCatalogItem::createCollections(
const QVector<QgsStacCollection *> collections )
639 QVector< QgsDataItem * > contents;
640 contents.reserve( collections.size() );
646 std::unique_ptr< QgsStacCollection > object( col );
648 const QString name = col->title().isEmpty() ? col->id() : col->title();
650 QgsStacCatalogItem *i =
new QgsStacCatalogItem(
this, name, col->url() );
651 i->setStacCatalog( std::move(
object ) );
652 contents.append( i );
657void QgsStacCatalogItem::fetchMoreChildren()
659 if ( mFetchMoreUrl.isEmpty() )
662 QgsStacFetchMoreItem *moreItem = fetchMoreItem();
665 std::unique_ptr< QgsStacItemCollection > ic(
c->fetchItemCollection( mFetchMoreUrl ) );
668 populate( createItems( ic->takeItems() ) );
670 mFetchMoreUrl = ic->nextUrl();
671 if ( !ic->nextUrl().isEmpty() && moreItem )
673 const int numberMatched = ic->numberMatched();
674 if ( numberMatched > -1 )
676 moreItem->setName( tr(
"Double-click to fetch more (%L1 total items)..." ).arg( numberMatched ) );
682 removeChildItem( moreItem );
692QgsStacConnectionItem::QgsStacConnectionItem(
QgsDataItem *parent,
const QString &connectionName )
693 : QgsStacCatalogItem( parent, connectionName, QString() )
694 , mConnName( connectionName )
697 mIconName = u
"mIconConnect.svg"_s;
702 mController->setAuthCfg( data.
authCfg );
705 mToolTip = u
"Connection:\n%1\n%2"_s.arg( connectionName, mPath );
710 return mController.get();
718QgsStacRootItem::QgsStacRootItem(
QgsDataItem *parent,
const QString &name,
const QString &path )
722 mIconName = u
"mIconStac.svg"_s;
726QVector<QgsDataItem *> QgsStacRootItem::createChildren()
728 QVector<QgsDataItem *> connections;
730 for (
const QString &connName : connectionList )
732 QgsDataItem *conn =
new QgsStacConnectionItem(
this, connName );
733 connections.append( conn );
738void QgsStacRootItem::onConnectionsChanged()
748QString QgsStacDataItemProvider::name()
753QString QgsStacDataItemProvider::dataProviderKey()
const
755 return u
"special:Stac"_s;
765 if ( path.isEmpty() )
766 return new QgsStacRootItem( parentItem, QObject::tr(
"STAC" ), u
"stac:"_s );
Provides global constants and enumerations for use throughout the application.
@ NetworkSources
Network/internet source.
@ NotPopulated
Children not yet created.
@ Populating
Creating children in separate thread (populating or refreshing).
@ Populated
Children created.
@ ReadOnly
Item is read only.
@ Collapse
The collapse/expand status for this items children should be ignored in order to avoid undesired netw...
@ Fast
CreateChildren() is fast enough to be run in main thread when refreshing items, most root items (wms,...
QFlags< DataItemProviderCapability > DataItemProviderCapabilities
Capabilities for data item providers.
@ Collection
STAC collection.
BrowserLayerType
Browser item layer types.
@ Vector
Generic vector layer.
@ PointCloud
Point cloud layer.
A browser item that represents a root group of connections from a single data provider.
A browser item for collections of data.
Base class for all items in the model.
Qgis::BrowserItemState state() const
virtual void childrenCreated()
QgsDataItem * parent() const
Gets item parent.
A browser item that can be used to report problems (e.g.
A browser item that represents a layer that can be opened with one of the providers.
QList< QgsMimeDataUtils::Uri > UriList
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Stores data associated with a STAC asset.
QString href() const
Returns the URI to the asset object.
QgsMimeDataUtils::Uri uri(const QString &authcfg=QString()) const
Returns a uri for the asset if it is a cloud optimized file like COG or COPC.
Stores data associated with a STAC Catalog.
bool conformsTo(const QString &conformanceClass) const
Checks if the catalog is a STAC API conforming to the specified conformanceClass.
Stores data associated with a STAC Collection.
static QStringList connectionList()
Returns list of existing connections, unless the hidden ones.
static Data connection(const QString &name)
Returns connection details.
std::unique_ptr< QgsStacItemCollection > fetchItemCollection(const QUrl &url, QString *error=nullptr)
Fetches a feature collection from url using a blocking network request.
QString authCfg() const
Returns the authentication config id which will be used during the request.
std::unique_ptr< T > fetchStacObject(const QUrl &url, QString *error=nullptr)
Fetches a STAC object from url using a blocking network request.
std::unique_ptr< T > takeStacObject(int requestId)
Returns the STAC object fetched with the specified requestId.
std::unique_ptr< QgsStacCollectionList > fetchCollections(const QUrl &url, QString *error=nullptr)
Fetches collections from url using a blocking network request.
void finishedStacObjectRequest(int id, QString errorMessage)
This signal is fired when an async request initiated with fetchStacObjectAsync is finished.
Stores data associated with a STAC Item.
Stores data associated with a STAC link.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
constexpr int MAX_DISPLAYED_ITEMS
QString uri
Identifier of the data source recognized by its providerKey.
QString providerKey
For "vector" / "raster" type: provider id.
QString layerType
Type of URI.
bool isValid() const
Returns whether the object contains valid data.
Represents decoded data of a connection.
QString authCfg
Authentication configuration id.