Propagate STAC connection authcfg to assets

The authcfg is now added to the layer uri and used for asset downloading and preview
This commit is contained in:
uclaros 2025-08-08 09:59:48 +03:00 committed by Martin Dobias
parent 52a7ac096a
commit fa4192dbe9
9 changed files with 62 additions and 20 deletions

View File

@ -98,6 +98,8 @@ QgsMimeDataUtils::UriList QgsStacItemItem::mimeUris() const
if ( !mStacItem ) if ( !mStacItem )
return uris; return uris;
const QString authcfg = stacController()->authCfg();
const QMap<QString, QgsStacAsset> assets = mStacItem->assets(); const QMap<QString, QgsStacAsset> assets = mStacItem->assets();
for ( auto it = assets.constBegin(); it != assets.constEnd(); ++it ) for ( auto it = assets.constBegin(); it != assets.constEnd(); ++it )
{ {
@ -116,6 +118,8 @@ QgsMimeDataUtils::UriList QgsStacItemItem::mimeUris() const
it->href().startsWith( QLatin1String( "ftp" ), Qt::CaseInsensitive ) ) it->href().startsWith( QLatin1String( "ftp" ), Qt::CaseInsensitive ) )
{ {
uri.uri = QStringLiteral( "/vsicurl/%1" ).arg( it->href() ); uri.uri = QStringLiteral( "/vsicurl/%1" ).arg( it->href() );
if ( !authcfg.isEmpty() )
uri.uri.append( QStringLiteral( " authcfg='%1'" ).arg( authcfg ) );
} }
else if ( it->href().startsWith( QLatin1String( "s3://" ), Qt::CaseInsensitive ) ) else if ( it->href().startsWith( QLatin1String( "s3://" ), Qt::CaseInsensitive ) )
{ {
@ -131,12 +135,16 @@ QgsMimeDataUtils::UriList QgsStacItemItem::mimeUris() const
uri.layerType = QStringLiteral( "pointcloud" ); uri.layerType = QStringLiteral( "pointcloud" );
uri.providerKey = QStringLiteral( "copc" ); uri.providerKey = QStringLiteral( "copc" );
uri.uri = it->href(); uri.uri = it->href();
if ( !authcfg.isEmpty() )
uri.uri.append( QStringLiteral( " authcfg='%1'" ).arg( authcfg ) );
} }
else if ( it->href().endsWith( QLatin1String( "/ept.json" ) ) ) else if ( it->href().endsWith( QLatin1String( "/ept.json" ) ) )
{ {
uri.layerType = QStringLiteral( "pointcloud" ); uri.layerType = QStringLiteral( "pointcloud" );
uri.providerKey = QStringLiteral( "ept" ); uri.providerKey = QStringLiteral( "ept" );
uri.uri = it->href(); uri.uri = it->href();
if ( !authcfg.isEmpty() )
uri.uri.append( QStringLiteral( " authcfg='%1'" ).arg( authcfg ) );
} }
uri.name = it->title().isEmpty() ? url.fileName() : it->title(); uri.name = it->title().isEmpty() ? url.fileName() : it->title();
uris.append( uri ); uris.append( uri );
@ -160,12 +168,12 @@ void QgsStacItemItem::updateToolTip()
mToolTip = QStringLiteral( "STAC Item:\n%1\n%2" ).arg( name, mPath ); mToolTip = QStringLiteral( "STAC Item:\n%1\n%2" ).arg( name, mPath );
} }
QgsStacController *QgsStacItemItem::stacController() QgsStacController *QgsStacItemItem::stacController() const
{ {
QgsDataItem *item = this; const QgsDataItem *item = this;
while ( item ) while ( item )
{ {
if ( QgsStacConnectionItem *ci = qobject_cast<QgsStacConnectionItem *>( item ) ) if ( const QgsStacConnectionItem *ci = qobject_cast<const QgsStacConnectionItem *>( item ) )
return ci->controller(); return ci->controller();
item = item->parent(); item = item->parent();
} }

View File

@ -62,7 +62,7 @@ class CORE_EXPORT QgsStacItemItem : public QgsDataItem
QVariant sortKey() const override { return QStringLiteral( "2 %1" ).arg( mName ); } QVariant sortKey() const override { return QStringLiteral( "2 %1" ).arg( mName ); }
void updateToolTip(); void updateToolTip();
QgsStacController *stacController(); QgsStacController *stacController() const;
//! takes ownership //! takes ownership
void setStacItem( std::unique_ptr< QgsStacItem > item ); void setStacItem( std::unique_ptr< QgsStacItem > item );

View File

@ -163,10 +163,12 @@ void QgsStacDataItemGuiProvider::loadConnections( QgsDataItem *item )
void QgsStacDataItemGuiProvider::showDetails( QgsDataItem *item ) void QgsStacDataItemGuiProvider::showDetails( QgsDataItem *item )
{ {
QgsStacObject *obj = nullptr; QgsStacObject *obj = nullptr;
QString authcfg;
if ( QgsStacItemItem *itemItem = qobject_cast<QgsStacItemItem *>( item ) ) if ( QgsStacItemItem *itemItem = qobject_cast<QgsStacItemItem *>( item ) )
{ {
obj = itemItem->stacItem(); obj = itemItem->stacItem();
authcfg = itemItem->stacController()->authCfg();
} }
else if ( QgsStacCatalogItem *catalogItem = qobject_cast<QgsStacCatalogItem *>( item ) ) else if ( QgsStacCatalogItem *catalogItem = qobject_cast<QgsStacCatalogItem *>( item ) )
{ {
@ -176,6 +178,7 @@ void QgsStacDataItemGuiProvider::showDetails( QgsDataItem *item )
if ( obj ) if ( obj )
{ {
QgsStacObjectDetailsDialog d; QgsStacObjectDetailsDialog d;
d.setAuthcfg( authcfg );
d.setStacObject( obj ); d.setStacObject( obj );
d.exec(); d.exec();
} }

View File

@ -137,7 +137,7 @@ void QgsStacItemListModel::setCollections( const QVector<QgsStacCollection *> &c
} }
} }
void QgsStacItemListModel::addItems( const QVector<QgsStacItem *> &items ) void QgsStacItemListModel::addItems( const QVector<QgsStacItem *> &items, const QString &authcfg )
{ {
int nextItemIndex = mItems.count(); int nextItemIndex = mItems.count();
beginInsertRows( QModelIndex(), mItems.size(), mItems.size() + items.size() - 1 ); beginInsertRows( QModelIndex(), mItems.size(), mItems.size() + items.size() - 1 );
@ -153,11 +153,15 @@ void QgsStacItemListModel::addItems( const QVector<QgsStacItem *> &items )
{ {
const QString href = it->href(); const QString href = it->href();
QgsNetworkContentFetcher *f = new QgsNetworkContentFetcher(); QgsNetworkContentFetcher *f = new QgsNetworkContentFetcher();
f->fetchContent( href ); f->fetchContent( href, authcfg );
connect( f, &QgsNetworkContentFetcher::finished, this, [this, f, href, nextItemIndex] { connect( f, &QgsNetworkContentFetcher::finished, this, [this, f, href, nextItemIndex] {
if ( f->reply()->error() == QNetworkReply::NoError ) if ( f->reply()->error() == QNetworkReply::NoError )
{ {
const QImage img = QImage::fromData( f->reply()->readAll() ); const QByteArray data = f->reply()->readAll();
const QImage img = QImage::fromData( data );
if ( img.isNull() )
return;
QImage previewImage( img.size(), QImage::Format_ARGB32 ); QImage previewImage( img.size(), QImage::Format_ARGB32 );
previewImage.fill( Qt::transparent ); previewImage.fill( Qt::transparent );
QPainter previewPainter( &previewImage ); QPainter previewPainter( &previewImage );

View File

@ -54,7 +54,7 @@ class QgsStacItemListModel : public QAbstractListModel
//! Builds collection dictionary. Does not take ownership //! Builds collection dictionary. Does not take ownership
void setCollections( const QVector<QgsStacCollection *> &collections ); void setCollections( const QVector<QgsStacCollection *> &collections );
//! Add items to the model. Takes ownership //! Add items to the model. Takes ownership
void addItems( const QVector<QgsStacItem *> &items ); void addItems( const QVector<QgsStacItem *> &items, const QString &authcfg );
//! Returns all items in the model. Does not transfer ownership //! Returns all items in the model. Does not transfer ownership
QVector<QgsStacItem *> items() const; QVector<QgsStacItem *> items() const;

View File

@ -18,6 +18,8 @@
#include "qgsgui.h" #include "qgsgui.h"
#include "qgsapplication.h" #include "qgsapplication.h"
#include "qgsstacitem.h" #include "qgsstacitem.h"
#include "qgsauthmanager.h"
#include <QDesktopServices> #include <QDesktopServices>
///@cond PRIVATE ///@cond PRIVATE
@ -42,7 +44,16 @@ void QgsStacObjectDetailsDialog::setStacObject( QgsStacObject *stacObject )
{ {
if ( it->roles().contains( QLatin1String( "thumbnail" ) ) ) if ( it->roles().contains( QLatin1String( "thumbnail" ) ) )
{ {
thumbnails.append( QStringLiteral( "<img src=\"%1\" border=1><br>" ).arg( it->href() ) ); QString uri = it->href();
if ( !mAuthcfg.isEmpty() )
{
QStringList connectionItems;
connectionItems << uri;
QgsApplication::authManager()->updateDataSourceUriItems( connectionItems, mAuthcfg );
uri = connectionItems.first();
}
thumbnails.append( QStringLiteral( "<img src=\"%1\" border=1><br>" ).arg( uri ) );
} }
} }
} }
@ -60,4 +71,9 @@ void QgsStacObjectDetailsDialog::setStacObject( QgsStacObject *stacObject )
mWebView->setHtml( html ); mWebView->setHtml( html );
} }
void QgsStacObjectDetailsDialog::setAuthcfg( const QString &authcfg )
{
mAuthcfg = authcfg;
}
///@endcond ///@endcond

View File

@ -32,6 +32,11 @@ class QgsStacObjectDetailsDialog : public QDialog, private Ui::QgsStacObjectDeta
explicit QgsStacObjectDetailsDialog( QWidget *parent = nullptr ); explicit QgsStacObjectDetailsDialog( QWidget *parent = nullptr );
void setStacObject( QgsStacObject *stacObject ); void setStacObject( QgsStacObject *stacObject );
void setAuthcfg( const QString &authcfg );
private:
QString mAuthcfg;
}; };
///@endcond ///@endcond

View File

@ -73,7 +73,7 @@ QgsStacSourceSelect::QgsStacSourceSelect( QWidget *parent, Qt::WindowFlags fl, Q
mItemsView->setContextMenuPolicy( Qt::CustomContextMenu ); mItemsView->setContextMenuPolicy( Qt::CustomContextMenu );
connect( mItemsView, &QListView::customContextMenuRequested, this, &QgsStacSourceSelect::showItemsContextMenu ); connect( mItemsView, &QListView::customContextMenuRequested, this, &QgsStacSourceSelect::showItemsContextMenu );
connect( mItemsView, &QListView::doubleClicked, this, &QgsStacSourceSelect::onItemDoubleClicked ); connect( mItemsView, &QListView::doubleClicked, this, &QgsStacSourceSelect::showItemDetails );
connect( mItemsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsStacSourceSelect::onCurrentItemChanged ); connect( mItemsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsStacSourceSelect::onCurrentItemChanged );
connect( mItemsView->verticalScrollBar(), &QScrollBar::valueChanged, this, &QgsStacSourceSelect::onItemsViewScroll ); connect( mItemsView->verticalScrollBar(), &QScrollBar::valueChanged, this, &QgsStacSourceSelect::onItemsViewScroll );
@ -138,9 +138,10 @@ void QgsStacSourceSelect::onItemsViewScroll( int value )
} }
} }
void QgsStacSourceSelect::onItemDoubleClicked( const QModelIndex &index ) void QgsStacSourceSelect::showItemDetails( const QModelIndex &index )
{ {
QgsStacObjectDetailsDialog details( this ); QgsStacObjectDetailsDialog details( this );
details.setAuthcfg( mStac->authCfg() );
details.setStacObject( index.data( QgsStacItemListModel::Role::StacObject ).value<QgsStacObject *>() ); details.setStacObject( index.data( QgsStacItemListModel::Role::StacObject ).value<QgsStacObject *>() );
details.exec(); details.exec();
} }
@ -372,7 +373,7 @@ void QgsStacSourceSelect::onItemCollectionRequestFinished( int requestId, QStrin
mNextPageUrl = col->nextUrl(); mNextPageUrl = col->nextUrl();
const QVector<QgsStacItem *> items = col->takeItems(); const QVector<QgsStacItem *> items = col->takeItems();
mItemsModel->addItems( items ); mItemsModel->addItems( items, mStac->authCfg() );
for ( QgsStacItem *i : items ) for ( QgsStacItem *i : items )
{ {
@ -565,9 +566,7 @@ void QgsStacSourceSelect::showItemsContextMenu( QPoint point )
QAction *detailsAction = new QAction( tr( "Details…" ), menu ); QAction *detailsAction = new QAction( tr( "Details…" ), menu );
connect( detailsAction, &QAction::triggered, this, [this, index] { connect( detailsAction, &QAction::triggered, this, [this, index] {
QgsStacObjectDetailsDialog details( this ); showItemDetails( index );
details.setStacObject( index.data( QgsStacItemListModel::Role::StacObject ).value<QgsStacObject *>() );
details.exec();
} ); } );
@ -623,19 +622,26 @@ void QgsStacSourceSelect::showFootprints( bool enable )
void QgsStacSourceSelect::loadUri( const QgsMimeDataUtils::Uri &uri ) void QgsStacSourceSelect::loadUri( const QgsMimeDataUtils::Uri &uri )
{ {
QString layerUri = uri.uri;
const QString authcfg = mStac->authCfg();
if ( !authcfg.isEmpty() )
{
layerUri += QStringLiteral( " authcfg='%1'" ).arg( authcfg );
}
if ( uri.layerType == QLatin1String( "raster" ) ) if ( uri.layerType == QLatin1String( "raster" ) )
{ {
Q_NOWARN_DEPRECATED_PUSH Q_NOWARN_DEPRECATED_PUSH
emit addRasterLayer( uri.uri, uri.name, uri.providerKey ); emit addRasterLayer( layerUri, uri.name, uri.providerKey );
Q_NOWARN_DEPRECATED_POP Q_NOWARN_DEPRECATED_POP
emit addLayer( Qgis::LayerType::Raster, uri.uri, uri.name, uri.providerKey ); emit addLayer( Qgis::LayerType::Raster, layerUri, uri.name, uri.providerKey );
} }
else if ( uri.layerType == QLatin1String( "pointcloud" ) ) else if ( uri.layerType == QLatin1String( "pointcloud" ) )
{ {
Q_NOWARN_DEPRECATED_PUSH Q_NOWARN_DEPRECATED_PUSH
emit addPointCloudLayer( uri.uri, uri.name, uri.providerKey ); emit addPointCloudLayer( layerUri, uri.name, uri.providerKey );
Q_NOWARN_DEPRECATED_POP Q_NOWARN_DEPRECATED_POP
emit addLayer( Qgis::LayerType::PointCloud, uri.uri, uri.name, uri.providerKey ); emit addLayer( Qgis::LayerType::PointCloud, layerUri, uri.name, uri.providerKey );
} }
} }
///@endcond ///@endcond

View File

@ -82,7 +82,7 @@ class GUI_EXPORT QgsStacSourceSelect : public QgsAbstractDataSourceWidget, priva
void onItemsViewScroll( int value ); void onItemsViewScroll( int value );
//! Called when double clicking a result item //! Called when double clicking a result item
void onItemDoubleClicked( const QModelIndex &index ); void showItemDetails( const QModelIndex &index );
//! Enables Add Layers button based on current item, updates rubber bands //! Enables Add Layers button based on current item, updates rubber bands
void onCurrentItemChanged( const QModelIndex &current, const QModelIndex &previous ); void onCurrentItemChanged( const QModelIndex &current, const QModelIndex &previous );