Skip to content

Commit

Permalink
[browser] Ensure "File Properties" action is always present for
Browse files Browse the repository at this point in the history
items which represent a file
  • Loading branch information
nyalldawson committed Jul 27, 2021
1 parent cb0095f commit b36bb62
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 23 deletions.
13 changes: 13 additions & 0 deletions python/gui/auto_generated/qgsdataitemguiprovider.sip.in
Expand Up @@ -98,6 +98,19 @@ The ``context`` argument gives the wider context under which the context menu is
and contains accessors for useful objects like the application message bar.

The base class method has no effect.
%End

virtual int precedenceWhenPopulatingMenus() const;
%Docstring
Returns the provider's precedence to use when populating context menus via calls to :py:func:`~QgsDataItemGuiProvider.populateContextMenu`.

Providers which return larger values will be called AFTER other providers when the menu is being populated.
This allows them to nicely insert their corresponding menu items in the desired location with respect to
existing items added by other providers.

The default implementation returns 0.

.. versionadded:: 3.22
%End

virtual bool rename( QgsDataItem *item, const QString &name, QgsDataItemGuiContext context );
Expand Down
58 changes: 37 additions & 21 deletions src/app/browser/qgsinbuiltdataitemproviders.cpp
Expand Up @@ -417,6 +417,43 @@ void QgsAppDirectoryItemGuiProvider::showProperties( QgsDirectoryItem *item, Qgs
}


//
// QgsAppFileItemGuiProvider
//

QString QgsAppFileItemGuiProvider::name()
{
return QStringLiteral( "file_items" );
}

void QgsAppFileItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *menu, const QList<QgsDataItem *> &, QgsDataItemGuiContext )
{
if ( !( item->capabilities2() & Qgis::BrowserItemCapability::ItemRepresentsFile ) )
return;


if ( QgsGui::nativePlatformInterface()->capabilities() & QgsNative::NativeFilePropertiesDialog )
{
if ( QFileInfo::exists( item->path() ) )
{
if ( !menu->isEmpty() )
menu->addSeparator();

QAction *action = menu->addAction( tr( "File Properties…" ) );
connect( action, &QAction::triggered, this, [ = ]
{
QgsGui::nativePlatformInterface()->showFileProperties( item->path() );
} );
}
}
}

int QgsAppFileItemGuiProvider::precedenceWhenPopulatingMenus() const
{
// we want this provider to be called last -- file items should naturally always appear at the bottom of the menu.
return std::numeric_limits< int >::max();
}

//
// QgsProjectHomeItemGuiProvider
//
Expand Down Expand Up @@ -626,18 +663,6 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
showPropertiesForItem( layerItem, context );
} );
menu->addAction( propertiesAction );

if ( QgsGui::nativePlatformInterface()->capabilities() & QgsNative::NativeFilePropertiesDialog )
{
if ( QFileInfo::exists( item->path() ) )
{
QAction *action = menu->addAction( tr( "File Properties…" ) );
connect( action, &QAction::triggered, this, [ = ]
{
QgsGui::nativePlatformInterface()->showFileProperties( item->path() );
} );
}
}
}

bool QgsLayerItemGuiProvider::handleDoubleClick( QgsDataItem *item, QgsDataItemGuiContext )
Expand Down Expand Up @@ -788,15 +813,6 @@ void QgsProjectItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *m
}
} );
menu->addAction( extractAction );

if ( QgsGui::nativePlatformInterface()->capabilities() & QgsNative::NativeFilePropertiesDialog )
{
QAction *action = menu->addAction( tr( "File Properties…" ) );
connect( action, &QAction::triggered, this, [projectPath]
{
QgsGui::nativePlatformInterface()->showFileProperties( projectPath );
} );
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/app/browser/qgsinbuiltdataitemproviders.h
Expand Up @@ -54,6 +54,21 @@ class QgsAppDirectoryItemGuiProvider : public QObject, public QgsDataItemGuiProv
void showProperties( QgsDirectoryItem *item, QgsDataItemGuiContext context );
};

class QgsAppFileItemGuiProvider : public QObject, public QgsDataItemGuiProvider
{
Q_OBJECT

public:

QgsAppFileItemGuiProvider() = default;

QString name() override;

void populateContextMenu( QgsDataItem *item, QMenu *menu,
const QList<QgsDataItem *> &selectedItems, QgsDataItemGuiContext context ) override;
int precedenceWhenPopulatingMenus() const override;
};


class QgsProjectHomeItemGuiProvider : public QObject, public QgsDataItemGuiProvider
{
Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.cpp
Expand Up @@ -1222,6 +1222,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
mTemporalControllerWidget->setMapCanvas( mMapCanvas );

QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsAppDirectoryItemGuiProvider() );
QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsAppFileItemGuiProvider() );
QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsProjectHomeItemGuiProvider() );
QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsProjectItemGuiProvider() );
QgsGui::instance()->dataItemGuiProviderRegistry()->addProvider( new QgsFavoritesItemGuiProvider() );
Expand Down
8 changes: 6 additions & 2 deletions src/gui/qgsbrowserwidget.cpp
Expand Up @@ -258,8 +258,12 @@ void QgsBrowserWidget::showContextMenu( QPoint pt )

QgsDataItemGuiContext context = createContext();

const QList< QgsDataItemGuiProvider * > providers = QgsGui::instance()->dataItemGuiProviderRegistry()->providers();
for ( QgsDataItemGuiProvider *provider : providers )
QList< QgsDataItemGuiProvider * > providers = QgsGui::instance()->dataItemGuiProviderRegistry()->providers();
std::sort( providers.begin(), providers.end(), []( QgsDataItemGuiProvider * a, QgsDataItemGuiProvider * b )
{
return a->precedenceWhenPopulatingMenus() < b->precedenceWhenPopulatingMenus();
} );
for ( QgsDataItemGuiProvider *provider : std::as_const( providers ) )
{
provider->populateContextMenu( item, menu, selectedItems, context );
}
Expand Down
5 changes: 5 additions & 0 deletions src/gui/qgsdataitemguiprovider.cpp
Expand Up @@ -43,6 +43,11 @@ void QgsDataItemGuiProvider::populateContextMenu( QgsDataItem *, QMenu *, const

}

int QgsDataItemGuiProvider::precedenceWhenPopulatingMenus() const
{
return 0;
}

bool QgsDataItemGuiProvider::rename( QgsDataItem *, const QString &, QgsDataItemGuiContext )
{
return false;
Expand Down
13 changes: 13 additions & 0 deletions src/gui/qgsdataitemguiprovider.h
Expand Up @@ -120,6 +120,19 @@ class GUI_EXPORT QgsDataItemGuiProvider
virtual void populateContextMenu( QgsDataItem *item, QMenu *menu,
const QList<QgsDataItem *> &selectedItems, QgsDataItemGuiContext context );

/**
* Returns the provider's precedence to use when populating context menus via calls to populateContextMenu().
*
* Providers which return larger values will be called AFTER other providers when the menu is being populated.
* This allows them to nicely insert their corresponding menu items in the desired location with respect to
* existing items added by other providers.
*
* The default implementation returns 0.
*
* \since QGIS 3.22
*/
virtual int precedenceWhenPopulatingMenus() const;

/**
* Sets a new \a name for the item, and returns TRUE if the item was successfully renamed.
*
Expand Down

0 comments on commit b36bb62

Please sign in to comment.