Skip to content

Commit

Permalink
[api] Add a new capability for QgsDataItems to indicate that the
Browse files Browse the repository at this point in the history
item path directly corresponds to an on-disk file path
  • Loading branch information
nyalldawson committed Jul 27, 2021
1 parent f17016f commit cb0095f
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 21 deletions.
5 changes: 4 additions & 1 deletion python/core/auto_additions/qgis.py
Expand Up @@ -219,7 +219,10 @@
QgsDataItem.Delete = Qgis.BrowserItemCapability.Delete
QgsDataItem.Delete.is_monkey_patched = True
QgsDataItem.Delete.__doc__ = "Item can be deleted"
Qgis.BrowserItemCapability.__doc__ = 'Browser item capabilities.\n\n.. versionadded:: 3.20\n\n' + '* ``NoCapabilities``: ' + Qgis.BrowserItemCapability.NoCapabilities.__doc__ + '\n' + '* ``SetCrs``: ' + Qgis.BrowserItemCapability.SetCrs.__doc__ + '\n' + '* ``Fertile``: ' + Qgis.BrowserItemCapability.Fertile.__doc__ + '\n' + '* ``Fast``: ' + Qgis.BrowserItemCapability.Fast.__doc__ + '\n' + '* ``Collapse``: ' + Qgis.BrowserItemCapability.Collapse.__doc__ + '\n' + '* ``Rename``: ' + Qgis.BrowserItemCapability.Rename.__doc__ + '\n' + '* ``Delete``: ' + Qgis.BrowserItemCapability.Delete.__doc__
QgsDataItem.ItemRepresentsFile = Qgis.BrowserItemCapability.ItemRepresentsFile
QgsDataItem.ItemRepresentsFile.is_monkey_patched = True
QgsDataItem.ItemRepresentsFile.__doc__ = "Item's path() directly represents a file on disk (since QGIS 3.22)"
Qgis.BrowserItemCapability.__doc__ = 'Browser item capabilities.\n\n.. versionadded:: 3.20\n\n' + '* ``NoCapabilities``: ' + Qgis.BrowserItemCapability.NoCapabilities.__doc__ + '\n' + '* ``SetCrs``: ' + Qgis.BrowserItemCapability.SetCrs.__doc__ + '\n' + '* ``Fertile``: ' + Qgis.BrowserItemCapability.Fertile.__doc__ + '\n' + '* ``Fast``: ' + Qgis.BrowserItemCapability.Fast.__doc__ + '\n' + '* ``Collapse``: ' + Qgis.BrowserItemCapability.Collapse.__doc__ + '\n' + '* ``Rename``: ' + Qgis.BrowserItemCapability.Rename.__doc__ + '\n' + '* ``Delete``: ' + Qgis.BrowserItemCapability.Delete.__doc__ + '\n' + '* ``ItemRepresentsFile``: ' + Qgis.BrowserItemCapability.ItemRepresentsFile.__doc__
# --
Qgis.BrowserItemCapability.baseClass = Qgis
QgsLayerItem.LayerType = Qgis.BrowserLayerType
Expand Down
1 change: 1 addition & 0 deletions python/core/auto_generated/qgis.sip.in
Expand Up @@ -182,6 +182,7 @@ The development version
Collapse,
Rename,
Delete,
ItemRepresentsFile,
};
typedef QFlags<Qgis::BrowserItemCapability> BrowserItemCapabilities;

Expand Down
6 changes: 6 additions & 0 deletions src/app/qgsappbrowserproviders.cpp
Expand Up @@ -87,6 +87,7 @@ QgsQlrDataItem::QgsQlrDataItem( QgsDataItem *parent, const QString &name, const
setState( Qgis::BrowserItemState::Populated ); // no children
setIconName( QStringLiteral( ":/images/icons/qgis-icon-16x16.png" ) );
setToolTip( QDir::toNativeSeparators( path ) );
mCapabilities |= Qgis::BrowserItemCapability::ItemRepresentsFile;
}

bool QgsQlrDataItem::hasDragEnabled() const
Expand Down Expand Up @@ -206,6 +207,7 @@ QgsQptDataItem::QgsQptDataItem( QgsDataItem *parent, const QString &name, const
setState( Qgis::BrowserItemState::Populated ); // no children
setIconName( QStringLiteral( "/mIconQptFile.svg" ) );
setToolTip( QDir::toNativeSeparators( path ) );
mCapabilities |= Qgis::BrowserItemCapability::ItemRepresentsFile;
}

bool QgsQptDataItem::hasDragEnabled() const
Expand Down Expand Up @@ -249,6 +251,7 @@ QgsPyDataItem::QgsPyDataItem( QgsDataItem *parent, const QString &name, const QS
setState( Qgis::BrowserItemState::Populated ); // no children
setIconName( QStringLiteral( "/mIconPythonFile.svg" ) );
setToolTip( QDir::toNativeSeparators( path ) );
mCapabilities |= Qgis::BrowserItemCapability::ItemRepresentsFile;
}

bool QgsPyDataItem::hasDragEnabled() const
Expand Down Expand Up @@ -351,6 +354,7 @@ QgsStyleXmlDataItem::QgsStyleXmlDataItem( QgsDataItem *parent, const QString &na
setState( Qgis::BrowserItemState::Populated ); // no children
setIconName( QStringLiteral( "/mActionStyleManager.svg" ) );
setToolTip( QStringLiteral( "<b>%1</b><br>%2" ).arg( tr( "QGIS style library" ), QDir::toNativeSeparators( path ) ) );
mCapabilities |= Qgis::BrowserItemCapability::ItemRepresentsFile;
}

bool QgsStyleXmlDataItem::hasDragEnabled() const
Expand Down Expand Up @@ -470,6 +474,7 @@ QgsProjectRootDataItem::QgsProjectRootDataItem( QgsDataItem *parent, const QStri
: QgsProjectItem( parent, QFileInfo( path ).completeBaseName(), path )
{
mCapabilities = Qgis::BrowserItemCapability::Collapse | Qgis::BrowserItemCapability::Fertile; // collapse by default to avoid costly population on startup
mCapabilities |= Qgis::BrowserItemCapability::ItemRepresentsFile;
setState( Qgis::BrowserItemState::NotPopulated );
}

Expand Down Expand Up @@ -1282,6 +1287,7 @@ QgsHtmlDataItem::QgsHtmlDataItem( QgsDataItem *parent, const QString &name, cons
setState( Qgis::BrowserItemState::Populated ); // no children
setIconName( QStringLiteral( "/mIconHtml.svg" ) );
setToolTip( QDir::toNativeSeparators( path ) );
mCapabilities |= Qgis::BrowserItemCapability::ItemRepresentsFile;
}

bool QgsHtmlDataItem::handleDoubleClick()
Expand Down
30 changes: 16 additions & 14 deletions src/core/browser/qgsdirectoryitem.cpp
Expand Up @@ -253,21 +253,20 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()

const QList<QgsDataItemProvider *> providers = QgsApplication::dataItemProviderRegistry()->providers();

QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
const auto constEntries = entries;
for ( const QString &subdir : constEntries )
const QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
for ( const QString &subdir : entries )
{
if ( mRefreshLater )
{
deleteLater( children );
return children;
}

QString subdirPath = dir.absoluteFilePath( subdir );
const QString subdirPath = dir.absoluteFilePath( subdir );

QgsDebugMsgLevel( QStringLiteral( "creating subdir: %1" ).arg( subdirPath ), 2 );

QString path = mPath + '/' + subdir; // may differ from subdirPath
const QString path = mPath + '/' + subdir; // may differ from subdirPath
if ( QgsDirectoryItem::hiddenPath( path ) )
continue;

Expand All @@ -293,9 +292,8 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
children.append( item );
}

QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
const auto constFileEntries = fileEntries;
for ( const QString &name : constFileEntries )
const QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
for ( const QString &name : fileEntries )
{
if ( mRefreshLater )
{
Expand Down Expand Up @@ -331,6 +329,11 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
QgsDataItem *item = provider->createDataItem( path, this );
if ( item )
{
// 3rd party providers may not correctly set the ItemRepresentsFile capability, so force it here if we
// see that the item's path does match the original file path
if ( item->path() == path )
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );

children.append( item );
createdItem = true;
}
Expand All @@ -344,6 +347,7 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
fileInfo.suffix().compare( QLatin1String( "qgz" ), Qt::CaseInsensitive ) == 0 )
{
QgsDataItem *item = new QgsProjectItem( this, fileInfo.completeBaseName(), path );
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );
children.append( item );
continue;
}
Expand Down Expand Up @@ -523,9 +527,8 @@ QgsDirectoryParamWidget::QgsDirectoryParamWidget( const QString &path, QWidget *
QList<QTreeWidgetItem *> items;

QDir dir( path );
QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
const auto constEntries = entries;
for ( const QString &name : constEntries )
const QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
for ( const QString &name : entries )
{
QFileInfo fi( dir.absoluteFilePath( name ) );
QStringList texts;
Expand Down Expand Up @@ -595,9 +598,8 @@ QgsDirectoryParamWidget::QgsDirectoryParamWidget( const QString &path, QWidget *

// hide columns that are not requested
QgsSettings settings;
QList<QVariant> lst = settings.value( QStringLiteral( "dataitem/directoryHiddenColumns" ) ).toList();
const auto constLst = lst;
for ( const QVariant &colVariant : constLst )
const QList<QVariant> lst = settings.value( QStringLiteral( "dataitem/directoryHiddenColumns" ) ).toList();
for ( const QVariant &colVariant : lst )
{
setColumnHidden( colVariant.toInt(), true );
}
Expand Down
21 changes: 15 additions & 6 deletions src/core/browser/qgsfilebaseddataitemprovider.cpp
Expand Up @@ -226,9 +226,8 @@ int QgsFileBasedDataItemProvider::capabilities() const
return QgsDataProvider::File | QgsDataProvider::Dir;
}

QgsDataItem *QgsFileBasedDataItemProvider::createDataItem( const QString &pathIn, QgsDataItem *parentItem )
QgsDataItem *QgsFileBasedDataItemProvider::createDataItem( const QString &path, QgsDataItem *parentItem )
{
QString path( pathIn );
if ( path.isEmpty() )
return nullptr;

Expand All @@ -240,7 +239,9 @@ QgsDataItem *QgsFileBasedDataItemProvider::createDataItem( const QString &pathIn
if ( suffix.compare( QLatin1String( "gpkg" ), Qt::CaseInsensitive ) == 0 )
{
// Geopackage is special -- it gets a dedicated collection item type
return new QgsGeoPackageCollectionItem( parentItem, name, path );
QgsGeoPackageCollectionItem *item = new QgsGeoPackageCollectionItem( parentItem, name, path );
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );
return item;
}
else if ( suffix == QLatin1String( "txt" ) )
{
Expand Down Expand Up @@ -285,7 +286,9 @@ QgsDataItem *QgsFileBasedDataItemProvider::createDataItem( const QString &pathIn
uq.addQueryItem( QStringLiteral( "type" ), QStringLiteral( "mbtiles" ) );
uq.addQueryItem( QStringLiteral( "url" ), path );
const QString encodedUri = uq.toString();
return new QgsVectorTileLayerItem( parentItem, name, path, encodedUri );
QgsVectorTileLayerItem *item = new QgsVectorTileLayerItem( parentItem, name, path, encodedUri );
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );
return item;
}
else
{
Expand All @@ -296,6 +299,7 @@ QgsDataItem *QgsFileBasedDataItemProvider::createDataItem( const QString &pathIn
const QString encodedUri = uq.toString();
QgsLayerItem *item = new QgsLayerItem( parentItem, name, path, encodedUri, Qgis::BrowserLayerType::Raster, QStringLiteral( "wms" ) );
item->setState( Qgis::BrowserItemState::Populated );
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );
return item;
}
}
Expand Down Expand Up @@ -331,11 +335,16 @@ QgsDataItem *QgsFileBasedDataItemProvider::createDataItem( const QString &pathIn
|| ( !( queryFlags & Qgis::SublayerQueryFlag::FastScan ) && !QgsProviderUtils::sublayerDetailsAreIncomplete( sublayers, QgsProviderUtils::SublayerCompletenessFlag::IgnoreUnknownFeatureCount ) ) )
)
{
return new QgsProviderSublayerItem( parentItem, name, sublayers.at( 0 ), false );
QgsProviderSublayerItem *item = new QgsProviderSublayerItem( parentItem, name, sublayers.at( 0 ), false );
if ( item->path() == path )
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );
return item;
}
else if ( !sublayers.empty() )
{
return new QgsFileDataCollectionItem( parentItem, name, path, sublayers );
QgsFileDataCollectionItem *item = new QgsFileDataCollectionItem( parentItem, name, path, sublayers );
item->setCapabilities( item->capabilities2() | Qgis::BrowserItemCapability::ItemRepresentsFile );
return item;
}
else
{
Expand Down
1 change: 1 addition & 0 deletions src/core/qgis.h
Expand Up @@ -268,6 +268,7 @@ class CORE_EXPORT Qgis
Collapse = 1 << 3, //!< The collapse/expand status for this items children should be ignored in order to avoid undesired network connections (wms etc.)
Rename = 1 << 4, //!< Item can be renamed
Delete = 1 << 5, //!< Item can be deleted
ItemRepresentsFile = 1 << 6, //!< Item's path() directly represents a file on disk (since QGIS 3.22)
};
Q_ENUM( BrowserItemCapability )
Q_DECLARE_FLAGS( BrowserItemCapabilities, BrowserItemCapability )
Expand Down

0 comments on commit cb0095f

Please sign in to comment.