Skip to content

Commit

Permalink
Merge pull request #5369 from nyalldawson/toolbox_order
Browse files Browse the repository at this point in the history
[processing] Always list native algorithms before 3rd party providers
  • Loading branch information
nyalldawson committed Oct 19, 2017
2 parents 325168e + 4ce1662 commit 8927fb5
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 28 deletions.
16 changes: 15 additions & 1 deletion python/core/processing/qgsprocessingprovider.sip
Expand Up @@ -56,8 +56,22 @@ class QgsProcessingProvider : QObject

virtual QString name() const = 0;
%Docstring
Returns the full provider name, which is used to describe the provider within the GUI.
Returns the provider name, which is used to describe the provider within the GUI.
This string should be short (e.g. "Lastools") and localised.
.. seealso:: longName()
.. seealso:: id()
:rtype: str
%End

virtual QString longName() const;
%Docstring
Returns the a longer version of the provider name, which can include extra details
such as version numbers. E.g. "Lastools LIDAR tools (version 2.2.1)".
This string should be localised.

The default implementation returns the same string as name().

.. seealso:: name()
.. seealso:: id()
:rtype: str
%End
Expand Down
3 changes: 3 additions & 0 deletions python/plugins/processing/algs/gdal/GdalAlgorithmProvider.py 100644 → 100755
Expand Up @@ -122,6 +122,9 @@ def setActive(self, active):
ProcessingConfig.setSettingValue('ACTIVATE_GDAL', active)

def name(self):
return 'GDAL'

def longName(self):
version = GdalUtils.readableVersion()
return 'GDAL ({})'.format(version)

Expand Down
84 changes: 59 additions & 25 deletions python/plugins/processing/gui/ProcessingToolbox.py 100644 → 100755
Expand Up @@ -58,6 +58,14 @@

class ProcessingToolbox(BASE, WIDGET):

ALG_ITEM = 'ALG_ITEM'
PROVIDER_ITEM = 'PROVIDER_ITEM'
GROUP_ITEM = 'GROUP_ITEM'

NAME_ROLE = Qt.UserRole
TAG_ROLE = Qt.UserRole + 1
TYPE_ROLE = Qt.UserRole + 2

def __init__(self):
super(ProcessingToolbox, self).__init__(None)
self.tipWasClosed = False
Expand Down Expand Up @@ -143,10 +151,10 @@ def _filterItem(self, item, text):
return show
elif isinstance(item, (TreeAlgorithmItem, TreeActionItem)):
# hide if every part of text is not contained somewhere in either the item text or item user role
item_text = [item.text(0).lower(), item.data(0, Qt.UserRole).lower()]
item_text = [item.text(0).lower(), item.data(0, ProcessingToolbox.NAME_ROLE).lower()]
if isinstance(item, TreeAlgorithmItem):
item_text.append(item.alg.id())
item_text.extend(item.data(0, Qt.UserRole + 1))
item_text.extend(item.data(0, ProcessingToolbox.TAG_ROLE))

hide = bool(text) and not all(
any(part in t for t in item_text)
Expand Down Expand Up @@ -356,20 +364,37 @@ def addProvider(self, provider_id):
def fillTreeUsingProviders(self):
self.algorithmTree.clear()
self.disabledProviderItems = {}
disabled = []

# TODO - replace with proper model for toolbox!

# first add qgis/native providers, since they create top level groups
for provider in QgsApplication.processingRegistry().providers():
if provider.id() in ('qgis', 'native'):
self.addAlgorithmsFromProvider(provider, self.algorithmTree.invisibleRootItem())
else:
if provider.isActive():
providerItem = TreeProviderItem(provider, self.algorithmTree, self)
else:
disabled.append(provider)
continue
self.algorithmTree.sortItems(0, Qt.AscendingOrder)
for provider in disabled:
providerItem = TreeProviderItem(provider, self.algorithmTree, self)
providerItem.setHidden(True)
self.disabledProviderItems[provider.id()] = providerItem

for provider in QgsApplication.processingRegistry().providers():
if provider.id() in ('qgis', 'native'):
# already added
continue
else:
providerItem = TreeProviderItem(provider, self.algorithmTree, self)

if not provider.isActive():
providerItem.setHidden(True)
self.disabledProviderItems[provider.id()] = providerItem

# insert non-native providers at end of tree, alphabetically

for i in range(self.algorithmTree.invisibleRootItem().childCount()):
child = self.algorithmTree.invisibleRootItem().child(i)
if isinstance(child, TreeProviderItem):
if child.text(0) > providerItem.text(0):
break

self.algorithmTree.insertTopLevelItem(i + 1, providerItem)

def addAlgorithmsFromProvider(self, provider, parent):
groups = {}
Expand All @@ -393,12 +418,9 @@ def addAlgorithmsFromProvider(self, provider, parent):
break

if not groupItem:
groupItem = QTreeWidgetItem()
name = alg.group()
groupItem = TreeGroupItem(alg.group())
if not active:
groupItem.setForeground(0, Qt.darkGray)
groupItem.setText(0, name)
groupItem.setToolTip(0, name)
groupItem.setInactive()
if provider.id() in ('qgis', 'native'):
groupItem.setIcon(0, provider.icon())
groups[alg.group()] = groupItem
Expand All @@ -414,8 +436,7 @@ def addAlgorithmsFromProvider(self, provider, parent):
if action.group in groups:
groupItem = groups[action.group]
else:
groupItem = QTreeWidgetItem()
groupItem.setText(0, action.group)
groupItem = TreeGroupItem(action.group)
groups[action.group] = groupItem
algItem = TreeActionItem(action)
groupItem.addChild(algItem)
Expand All @@ -431,11 +452,8 @@ def activateProvider():
label.setStyleSheet("QLabel {background-color: white; color: grey;}")
label.linkActivated.connect(activateProvider)
self.algorithmTree.setItemWidget(parent, 0, label)

else:
text += QCoreApplication.translate("TreeProviderItem", " [{0} geoalgorithms]").format(count)
parent.setText(0, text)
parent.setToolTip(0, parent.text(0))

for groupItem in list(groups.values()):
parent.addChild(groupItem)
Expand All @@ -456,8 +474,22 @@ def __init__(self, alg):
self.setIcon(0, icon)
self.setToolTip(0, name)
self.setText(0, name)
self.setData(0, Qt.UserRole, nameEn)
self.setData(0, Qt.UserRole + 1, alg.tags())
self.setData(0, ProcessingToolbox.NAME_ROLE, nameEn)
self.setData(0, ProcessingToolbox.TAG_ROLE, alg.tags())
self.setData(0, ProcessingToolbox.TYPE_ROLE, ProcessingToolbox.ALG_ITEM)


class TreeGroupItem(QTreeWidgetItem):

def __init__(self, name):
QTreeWidgetItem.__init__(self)
self.setToolTip(0, name)
self.setText(0, name)
self.setData(0, ProcessingToolbox.NAME_ROLE, name)
self.setData(0, ProcessingToolbox.TYPE_ROLE, ProcessingToolbox.GROUP_ITEM)

def setInactive(self):
self.setForeground(0, Qt.darkGray)


class TreeActionItem(QTreeWidgetItem):
Expand All @@ -467,17 +499,19 @@ def __init__(self, action):
self.action = action
self.setText(0, action.i18n_name)
self.setIcon(0, action.getIcon())
self.setData(0, Qt.UserRole, action.name)
self.setData(0, ProcessingToolbox.NAME_ROLE, action.name)


class TreeProviderItem(QTreeWidgetItem):

def __init__(self, provider, tree, toolbox):
QTreeWidgetItem.__init__(self, tree)
QTreeWidgetItem.__init__(self, None)
self.tree = tree
self.toolbox = toolbox
self.provider = provider
self.setIcon(0, self.provider.icon())
self.setData(0, ProcessingToolbox.TYPE_ROLE, ProcessingToolbox.PROVIDER_ITEM)
self.setToolTip(0, self.provider.longName())
self.populate()

def refresh(self):
Expand Down
5 changes: 5 additions & 0 deletions src/core/processing/qgsprocessingprovider.cpp
Expand Up @@ -39,6 +39,11 @@ QString QgsProcessingProvider::svgIconPath() const
return QgsApplication::iconPath( QStringLiteral( "processingAlgorithm.svg" ) );
}

QString QgsProcessingProvider::longName() const
{
return name();
}

void QgsProcessingProvider::refreshAlgorithms()
{
qDeleteAll( mAlgorithms );
Expand Down
17 changes: 15 additions & 2 deletions src/core/processing/qgsprocessingprovider.h
Expand Up @@ -70,12 +70,25 @@ class CORE_EXPORT QgsProcessingProvider : public QObject
virtual QString id() const = 0;

/**
* Returns the full provider name, which is used to describe the provider within the GUI.
* This string should be localised.
* Returns the provider name, which is used to describe the provider within the GUI.
* This string should be short (e.g. "Lastools") and localised.
* \see longName()
* \see id()
*/
virtual QString name() const = 0;

/**
* Returns the a longer version of the provider name, which can include extra details
* such as version numbers. E.g. "Lastools LIDAR tools (version 2.2.1)".
* This string should be localised.
*
* The default implementation returns the same string as name().
*
* \see name()
* \see id()
*/
virtual QString longName() const;

/**
* Returns true if the provider can be activated, or false if it cannot be activated (e.g. due to
* missing external dependencies).
Expand Down

0 comments on commit 8927fb5

Please sign in to comment.