Skip to content

Commit

Permalink
Merge pull request #5212 from boundlessgeo/browser_homogenize
Browse files Browse the repository at this point in the history
Geopackage: browser homogenize
  • Loading branch information
elpaso authored Sep 19, 2017
2 parents e05f266 + a5647c7 commit b089248
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 54 deletions.
16 changes: 16 additions & 0 deletions python/core/qgsdataitemprovider.sip
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@





class QgsDataItemProvider
{
%Docstring
Expand Down Expand Up @@ -54,6 +56,20 @@ Caller takes responsibility of deleting created items.
Caller takes responsibility of deleting created items.
:rtype: list of QgsDataItem
%End

virtual bool handlesDirectoryPath( const QString &path );
%Docstring
Returns true if the provider will handle the directory at the specified ``path``.

If the provider indicates that it will handle the directory, the default creation and
population of directory items for the path will be avoided and it is left to the
provider to correctly populate relevant entries for the path.

The default implementation returns false for all paths.

.. versionadded:: 3.0
:rtype: bool
%End
};

/************************************************************************
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9690,7 +9690,7 @@ bool QgisApp::setActiveLayer( QgsMapLayer *layer )

void QgisApp::reloadConnections()
{
emit( connectionsChanged( ) );
emit connectionsChanged( );
}


Expand Down
30 changes: 26 additions & 4 deletions src/core/qgsdataitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,16 @@ void QgsDataItem::refresh()

void QgsDataItem::refreshConnections()
{
refresh();
emit connectionsChanged();
// Walk up until the root node is reached
if ( mParent )
{
mParent->refreshConnections();
}
else
{
refresh();
emit connectionsChanged();
}
}

void QgsDataItem::refresh( const QVector<QgsDataItem *> &children )
Expand Down Expand Up @@ -695,6 +703,8 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
QVector<QgsDataItem *> children;
QDir dir( mDirPath );

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

QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
Q_FOREACH ( const QString &subdir, entries )
{
Expand All @@ -711,6 +721,19 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
QString path = mPath + '/' + subdir; // may differ from subdirPath
if ( QgsDirectoryItem::hiddenPath( path ) )
continue;

bool handledByProvider = false;
for ( QgsDataItemProvider *provider : providers )
{
if ( provider->handlesDirectoryPath( path ) )
{
handledByProvider = true;
break;
}
}
if ( handledByProvider )
continue;

QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );
// propagate signals up to top

Expand Down Expand Up @@ -747,7 +770,7 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
}
}

Q_FOREACH ( QgsDataItemProvider *provider, QgsApplication::dataItemProviderRegistry()->providers() )
for ( QgsDataItemProvider *provider : providers )
{
int capabilities = provider->capabilities();

Expand Down Expand Up @@ -1312,7 +1335,6 @@ QVector<QgsDataItem *> QgsZipItem::createChildren()
// the item comes with zipped file name, set the name to relative path within zip file
item->setName( fileName );
children.append( item );
break;
}
else
{
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsdataitemprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@
#include "qgsdataitemprovider.h"

// no implementation currently

bool QgsDataItemProvider::handlesDirectoryPath( const QString & )
{
return false;
}
17 changes: 17 additions & 0 deletions src/core/qgsdataitemprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ class QgsDataItem;

class QString;

//! handlesDirectoryPath function
typedef bool handlesDirectoryPath_t( const QString &path ) SIP_SKIP;


/** \ingroup core
* This is the interface for those who want to add custom data items to the browser tree.
*
Expand Down Expand Up @@ -54,6 +58,19 @@ class CORE_EXPORT QgsDataItemProvider
//! Create a vector of instances of QgsDataItem (or null) for given path and parent item.
//! Caller takes responsibility of deleting created items.
virtual QVector<QgsDataItem *> createDataItems( const QString &path, QgsDataItem *parentItem ) { Q_UNUSED( path ); Q_UNUSED( parentItem ); return QVector<QgsDataItem *>(); }

/**
* Returns true if the provider will handle the directory at the specified \a path.
*
* If the provider indicates that it will handle the directory, the default creation and
* population of directory items for the path will be avoided and it is left to the
* provider to correctly populate relevant entries for the path.
*
* The default implementation returns false for all paths.
*
* \since QGIS 3.0
*/
virtual bool handlesDirectoryPath( const QString &path );
};

#endif // QGSDATAITEMPROVIDER_H
24 changes: 22 additions & 2 deletions src/core/qgsdataitemproviderregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,19 @@ typedef QList<QgsDataItemProvider *> *dataItemProviders_t();
class QgsDataItemProviderFromPlugin : public QgsDataItemProvider
{
public:
QgsDataItemProviderFromPlugin( const QString &name, dataCapabilities_t *capabilitiesFunc, dataItem_t *dataItemFunc )

/**
* QgsDataItemProviderFromPlugin constructor
* \param name plugin name
* \param capabilitiesFunc function pointer to the data capabilities
* \param dataItemFunc function pointer to the data items
* \param handlesDirectoryPathFunc function pointer to handlesDirectoryPath
*/
QgsDataItemProviderFromPlugin( const QString &name, dataCapabilities_t *capabilitiesFunc, dataItem_t *dataItemFunc, handlesDirectoryPath_t *handlesDirectoryPathFunc )
: mName( name )
, mCapabilitiesFunc( capabilitiesFunc )
, mDataItemFunc( dataItemFunc )
, mHandlesDirectoryPathFunc( handlesDirectoryPathFunc )
{
}

Expand All @@ -49,10 +58,19 @@ class QgsDataItemProviderFromPlugin : public QgsDataItemProvider

QgsDataItem *createDataItem( const QString &path, QgsDataItem *parentItem ) override { return mDataItemFunc( path, parentItem ); }

bool handlesDirectoryPath( const QString &path ) override
{
if ( mHandlesDirectoryPathFunc )
return mHandlesDirectoryPathFunc( path );
else
return false;
}

protected:
QString mName;
dataCapabilities_t *mCapabilitiesFunc = nullptr;
dataItem_t *mDataItemFunc = nullptr;
handlesDirectoryPath_t *mHandlesDirectoryPathFunc = nullptr;
};


Expand Down Expand Up @@ -93,7 +111,9 @@ QgsDataItemProviderRegistry::QgsDataItemProviderRegistry()
continue;
}

mProviders.append( new QgsDataItemProviderFromPlugin( library->fileName(), dataCapabilities, dataItem ) );
handlesDirectoryPath_t *handlesDirectoryPath = reinterpret_cast< handlesDirectoryPath_t * >( cast_to_fptr( library->resolve( "handlesDirectoryPath" ) ) );

mProviders.append( new QgsDataItemProviderFromPlugin( library->fileName(), dataCapabilities, dataItem, handlesDirectoryPath ) );
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/providers/gdal/qgsgdaldataitems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,32 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
#endif
}

// Filters out the OGR/GDAL supported formats that can contain multiple layers
// and should be treated like a DB: GeoPackage and SQLite
// NOTE: this formats are scanned for rasters too and they are handled
// by the "ogr" provider. For this reason they must
// be skipped by "gdal" provider or the rasters will be listed
// twice. ogrSupportedDbLayersExtensions must be kept in sync
// with the companion variable (same name) in the ogr provider
// class
// TODO: add more OGR supported multiple layers formats here!
QStringList ogrSupportedDbLayersExtensions;
ogrSupportedDbLayersExtensions << QLatin1String( "gpkg" ) << QLatin1String( "sqlite" ) << QLatin1String( "db" ) << QLatin1String( "gdb" );
QStringList ogrSupportedDbDriverNames;
ogrSupportedDbDriverNames << QLatin1String( "GPKG" ) << QLatin1String( "db" ) << QLatin1String( "gdb" );

// return item without testing if:
// scanExtSetting
// or zipfile and scan zip == "Basic scan"
if ( scanExtSetting ||
( ( is_vsizip || is_vsitar ) && scanZipSetting == QLatin1String( "basic" ) ) )
{
// Skip this layer if it's handled by ogr:
if ( ogrSupportedDbLayersExtensions.contains( suffix ) )
{
return nullptr;
}

// if this is a VRT file make sure it is raster VRT to avoid duplicates
if ( suffix == QLatin1String( "vrt" ) )
{
Expand Down Expand Up @@ -283,6 +303,15 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
return nullptr;
}

GDALDriverH hDriver = GDALGetDatasetDriver( hDS );
QString ogrDriverName = GDALGetDriverShortName( hDriver );

// Skip this layer if it's handled by ogr:
if ( ogrSupportedDbDriverNames.contains( ogrDriverName ) )
{
return nullptr;
}

QStringList sublayers = QgsGdalProvider::subLayers( hDS );

GDALClose( hDS );
Expand Down
Loading

0 comments on commit b089248

Please sign in to comment.