Skip to content

Commit

Permalink
[FEATURE] Allow customization of the items shown in browser (#33679)
Browse files Browse the repository at this point in the history
* [FEATURE] Allow customization of the items show is browser. User can select in Interface Customization dialog to hide some of the items in the browser panel

Funded by Limerick City and County Council
  • Loading branch information
PeterPetrik committed Jan 15, 2020
1 parent a9ed83f commit ecd90c6
Show file tree
Hide file tree
Showing 17 changed files with 338 additions and 53 deletions.
3 changes: 1 addition & 2 deletions python/core/auto_generated/qgsbrowsermodel.sip.in
Expand Up @@ -55,6 +55,7 @@ Constructor for QgsBrowserModel, with the specified ``parent`` object.
PathRole,
CommentRole,
SortRole,
ProviderKeyRole,
};

virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
Expand Down Expand Up @@ -161,7 +162,6 @@ and on Linux the "/" root directory.

.. versionadded:: 3.6
%End

signals:

void stateChanged( const QModelIndex &index, QgsDataItem::State oldState );
Expand Down Expand Up @@ -232,7 +232,6 @@ Delayed initialization, needed because the provider registry must be already pop
.. seealso:: :py:func:`initialized`
%End


protected:
void addRootItems();
%Docstring
Expand Down
15 changes: 15 additions & 0 deletions python/core/auto_generated/qgsbrowserproxymodel.sip.in
Expand Up @@ -131,6 +131,21 @@ filterByLayerType() is ``True``.
.. seealso:: :py:func:`layerType`

.. seealso:: :py:func:`setFilterByLayerType`
%End

void setDataItemProviderKeyFilter( const QStringList &filter );
%Docstring
Sets the customization filters for data items based on item's data provider key

By default browser model shows all items from all available data items provider and few special
items (e.g. Favourites). To customize the behavious, set the filter to not load certain data items.
The items that are not based on data item providers have prefix "special:", for example
"special:Favourites", "special:Home", "PostGIS", "MSSQL"

All items created by the providers listed in filter are hidden from the layer tree.
This filter is always evaluated.

.. versionadded:: 3.12
%End

protected:
Expand Down
49 changes: 41 additions & 8 deletions python/core/auto_generated/qgsdataitem.sip.in
Expand Up @@ -52,9 +52,10 @@ Parent/children hierarchy is not based on QObject.
};


QgsDataItem( QgsDataItem::Type type, QgsDataItem *parent /TransferThis/, const QString &name, const QString &path );
QgsDataItem( QgsDataItem::Type type, QgsDataItem *parent /TransferThis/, const QString &name, const QString &path, const QString &providerKey = QString() );
%Docstring
Create new data item.
Creates new data item
``providerKey`` added in QGIS 3.12
%End
~QgsDataItem();

Expand Down Expand Up @@ -300,6 +301,27 @@ Sets the ``name`` of the item (the displayed text for the item).

QString path() const;
void setPath( const QString &path );

QString providerKey() const;
%Docstring
Returns the provider key that created this item (e.g. "PostGIS")

If key has a prefix "special:", it marks that the item was not created with a provider,
but manually. For example "special:Favorites", "special:Home"

.. versionadded:: 3.12
%End

void setProviderKey( const QString &value );
%Docstring
Sets the provider key that created this item (e.g. "PostGIS")

If key has a prefix "special:", it marks that the item was not created with a provider,
but manually. For example "special:Favorites"

.. versionadded:: 3.12
%End

static QString pathComponent( const QString &component );
%Docstring
Create path component replacing path separators
Expand Down Expand Up @@ -525,7 +547,6 @@ Use QgsDataItemGuiProvider.deleteLayer instead

protected:


public:
static QIcon iconPoint();
static QIcon iconLine();
Expand Down Expand Up @@ -556,7 +577,10 @@ A Collection: logical collection of layers or subcollections, e.g. GRASS locatio
#include "qgsdataitem.h"
%End
public:
QgsDataCollectionItem( QgsDataItem *parent, const QString &name, const QString &path = QString() );
QgsDataCollectionItem( QgsDataItem *parent, const QString &name, const QString &path = QString(), const QString &providerKey = QString() );
%Docstring
Constructor
%End
~QgsDataCollectionItem();

void addChild( QgsDataItem *item /Transfer/ );
Expand Down Expand Up @@ -605,14 +629,15 @@ A directory: contains subdirectories and layers

QgsDirectoryItem( QgsDataItem *parent, const QString &name, const QString &path );

QgsDirectoryItem( QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path );
QgsDirectoryItem( QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path, const QString &providerKey = QString() );
%Docstring
Constructor.

:param parent:
:param name: directory name
:param dirPath: path to directory in file system
:param path: item path in the tree, it may be dirPath or dirPath with some prefix, e.g. favorites: *
:param path: item path in the tree, it may be dirPath or dirPath with some prefix, e.g. favorites:
:param providerKey: key of the provider that created this item
%End

virtual void setState( State state );
Expand Down Expand Up @@ -662,13 +687,14 @@ Data item that can be used to represent QGIS projects.
%End
public:

QgsProjectItem( QgsDataItem *parent, const QString &name, const QString &path );
QgsProjectItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &providerKey = QString() );
%Docstring
A data item holding a reference to a QGIS project file.

:param parent: The parent data item.
:param name: The name of the of the project. Displayed to the user.
:param path: The full path to the project.
:param providerKey: key of the provider that created this item
%End

virtual bool hasDragEnabled() const;
Expand Down Expand Up @@ -782,7 +808,14 @@ A zip file: contains layers, using GDAL/OGR VSIFILE mechanism

public:
QgsZipItem( QgsDataItem *parent, const QString &name, const QString &path );
QgsZipItem( QgsDataItem *parent, const QString &name, const QString &filePath, const QString &path );
%Docstring
Constructor
%End

QgsZipItem( QgsDataItem *parent, const QString &name, const QString &filePath, const QString &path, const QString &providerKey = QString() );
%Docstring
Constructor
%End

virtual QVector<QgsDataItem *> createChildren();

Expand Down
16 changes: 14 additions & 2 deletions python/gui/auto_generated/qgsbrowserdockwidget.sip.in
Expand Up @@ -58,6 +58,20 @@ Returns the message bar associated with the dock.
.. seealso:: :py:func:`setMessageBar`

.. versionadded:: 3.6
%End

void setDisabledDataItemsKeys( const QStringList &filter );
%Docstring
Sets the customization for data items based on item's data provider key

By default browser model shows all items from all available data items provider and few special
items (e.g. Favourites). To customize the behavior, set the filter to not load certain data items.
The items that are not based on data item providers (e.g. Favourites, Home) have
prefix "special:"

Used in the proxy browser model to hide items

.. versionadded:: 3.12
%End

public slots:
Expand Down Expand Up @@ -190,8 +204,6 @@ Show event override

};



/************************************************************************
* This file has been generated automatically from *
* *
Expand Down
4 changes: 4 additions & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -1300,6 +1300,10 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh

QgsApplication::dataItemProviderRegistry()->addProvider( new QgsProjectDataItemProvider() );

// now when all data item providers are registered, customize both browsers
QgsCustomization::instance()->updateBrowserWidget( mBrowserWidget );
QgsCustomization::instance()->updateBrowserWidget( mBrowserWidget2 );

// Create the plugin registry and load plugins
// load any plugins that were running in the last session
mSplash->showMessage( tr( "Restoring loaded plugins" ), Qt::AlignHCenter | Qt::AlignBottom );
Expand Down
68 changes: 68 additions & 0 deletions src/app/qgscustomization.cpp
Expand Up @@ -19,6 +19,9 @@
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsstatusbar.h"
#include "qgsbrowserdockwidget.h"
#include "qgsdataitemprovider.h"
#include "qgsdataitemproviderregistry.h"
#include "qgsgui.h"

#include <QAction>
Expand Down Expand Up @@ -359,6 +362,7 @@ void QgsCustomizationDialog::init()
}

treeWidget->insertTopLevelItems( 0, QgsCustomization::instance()->mMainWindowItems );
treeWidget->addTopLevelItem( QgsCustomization::instance()->mBrowserItem );

for ( int i = 0; i < treeWidget->topLevelItemCount(); i++ )
treeWidget->expandItem( treeWidget->topLevelItem( i ) );
Expand Down Expand Up @@ -696,6 +700,42 @@ void QgsCustomization::createTreeItemStatus()
mMainWindowItems << topItem;
}

void QgsCustomization::createTreeItemBrowser()
{
if ( mBrowserItem )
return;

QStringList data;
data << QStringLiteral( "Browser" );
mBrowserItem = new QTreeWidgetItem( data );
QVector<QStringList> items;

items << QStringList( {QStringLiteral( "special:Home" ), tr( "Home Folder" )} );
items << QStringList( {QStringLiteral( "special:ProjectHome" ), tr( "Project tHome Folder" )} );
items << QStringList( {QStringLiteral( "special:Favorites" ), tr( "Favorites Folder" )} );
items << QStringList( {QStringLiteral( "special:Drives" ), tr( "Drive Folders (e.g. C:\\)" )} );
items << QStringList( {QStringLiteral( "special:Volumes" ), tr( "Volume Folder (MacOS only)" )} );

const auto constProviders = QgsApplication::dataItemProviderRegistry()->providers();
for ( QgsDataItemProvider *pr : constProviders )
{
int capabilities = pr->capabilities();
if ( capabilities != QgsDataProvider::NoDataCapabilities )
{
QStringList item;
item << QStringLiteral( "%1" ).arg( pr->name() ) << QObject::tr( "Data Item Provider: %1" ).arg( pr->name() );
items << item;
}
}

for ( const QStringList &strs : items )
{
QTreeWidgetItem *item = new QTreeWidgetItem( mBrowserItem, strs );
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable );
item->setCheckState( 0, Qt::Checked );
}
}

QgsCustomization *QgsCustomization::sInstance = nullptr;
QgsCustomization *QgsCustomization::instance()
{
Expand Down Expand Up @@ -975,6 +1015,34 @@ void QgsCustomization::removeFromLayout( QLayout *layout, QWidget *widget )
}
}

void QgsCustomization::updateBrowserWidget( QgsBrowserDockWidget *widget )
{
createTreeItemBrowser();

if ( !widget )
return;

if ( !mEnabled )
return;

if ( !mBrowserItem )
return;

QStringList disabledDataItems;
mSettings->beginGroup( QStringLiteral( "Customization/Browser" ) );
for ( int i = 0; i < mBrowserItem->childCount(); ++i )
{
const QTreeWidgetItem *item = mBrowserItem->child( i );
if ( item && !mSettings->value( item->text( 0 ), true ).toBool() )
{
disabledDataItems << item->text( 0 );
}
}
mSettings->endGroup();

widget->setDisabledDataItemsKeys( disabledDataItems );
}

void QgsCustomization::preNotify( QObject *receiver, QEvent *event, bool *done )
{
if ( event->type() == QEvent::Show || event->type() == QEvent::MouseButtonPress )
Expand Down
6 changes: 5 additions & 1 deletion src/app/qgscustomization.h
Expand Up @@ -31,6 +31,7 @@ class QTreeWidgetItem;
class QEvent;
class QMouseEvent;
class QSettings;
class QgsBrowserDockWidget;

class APP_EXPORT QgsCustomizationDialog : public QMainWindow, private Ui::QgsCustomizationDialogBase
{
Expand Down Expand Up @@ -129,6 +130,7 @@ class APP_EXPORT QgsCustomization : public QObject
static void customizeWidget( const QString &path, QWidget *widget, QSettings *settings );
static void removeFromLayout( QLayout *layout, QWidget *widget );

void updateBrowserWidget( QgsBrowserDockWidget *model );
void updateMainWindow( QMenu *toolBarMenu );

// make sure to enable/disable before creating QgisApp in order to get it customized (or not)
Expand Down Expand Up @@ -162,10 +164,12 @@ class APP_EXPORT QgsCustomization : public QObject
void createTreeItemToolbars();
void createTreeItemDocks();
void createTreeItemStatus();
void createTreeItemBrowser();
void addTreeItemMenu( QTreeWidgetItem *parentItem, const QMenu *menu, const QAction *action = nullptr );
void addTreeItemActions( QTreeWidgetItem *parentItem, const QList<QAction *> &actions );
QList<QTreeWidgetItem *> mMainWindowItems;
friend class QgsCustomizationDialog; // in order to access mMainWindowItems
QTreeWidgetItem *mBrowserItem = nullptr;
friend class QgsCustomizationDialog; // in order to access mMainWindowItems and mBrowserItem

private:
static QgsCustomization *sInstance;
Expand Down
15 changes: 11 additions & 4 deletions src/core/qgsbrowsermodel.cpp
Expand Up @@ -88,7 +88,9 @@ void QgsBrowserModel::addRootItems()
updateProjectHome();

// give the home directory a prominent third place
QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, tr( "Home" ), QDir::homePath(), QStringLiteral( HOME_PREFIX ) + QDir::homePath() );
QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, tr( "Home" ), QDir::homePath(),
QStringLiteral( HOME_PREFIX ) + QDir::homePath(),
QStringLiteral( "special:Home" ) );
item->setSortKey( QStringLiteral( " 2" ) );
setupItemConnections( item );
mRootItems << item;
Expand All @@ -110,7 +112,7 @@ void QgsBrowserModel::addRootItems()
if ( QgsDirectoryItem::hiddenPath( path ) )
continue;

QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, path, path );
QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, path, QString(), path, QStringLiteral( "special:Drives" ) );
item->setSortKey( QStringLiteral( " 3 %1" ).arg( path ) );
mDriveItems.insert( path, item );

Expand All @@ -120,7 +122,7 @@ void QgsBrowserModel::addRootItems()

#ifdef Q_OS_MAC
QString path = QString( "/Volumes" );
QgsDirectoryItem *vols = new QgsDirectoryItem( nullptr, path, path );
QgsDirectoryItem *vols = new QgsDirectoryItem( nullptr, path, QString(), path, QStringLiteral( "special:Volumes" ) );
mRootItems << vols;
#endif

Expand All @@ -140,6 +142,8 @@ void QgsBrowserModel::addRootItems()
QgsDataItem *item = pr->createDataItem( QString(), nullptr ); // empty path -> top level
if ( item )
{
// make sure the top level key is set always
item->setProviderKey( pr->name() );
// Forward the signal from the root items to the model (and then to the app)
connect( item, &QgsDataItem::connectionsChanged, this, &QgsBrowserModel::connectionsChanged );
QgsDebugMsgLevel( "Add new top level item : " + item->name(), 4 );
Expand Down Expand Up @@ -194,7 +198,6 @@ void QgsBrowserModel::initialize()
}
}


Qt::ItemFlags QgsBrowserModel::flags( const QModelIndex &index ) const
{
if ( !index.isValid() )
Expand Down Expand Up @@ -263,6 +266,10 @@ QVariant QgsBrowserModel::data( const QModelIndex &index, int role ) const
}
return QVariant();
}
else if ( role == QgsBrowserModel::ProviderKeyRole )
{
return item->providerKey();
}
else
{
// unsupported role
Expand Down

0 comments on commit ecd90c6

Please sign in to comment.