Skip to content
Permalink
Browse files

Move toolbox tree view to c++ class

  • Loading branch information
nyalldawson committed Jul 8, 2018
1 parent 810cb9c commit 101c98fd174fbd0482031c679239897c6fbb228e
@@ -365,9 +365,6 @@ A sort/filter proxy model for providers and algorithms shown within the Processi
which automatically sorts the toolbox in a logical fashion and supports filtering
the results.

If \recentLog is specified then it will be used to create a "Recently used" top
level group containing recently used algorithms.

.. versionadded:: 3.2
%End

@@ -394,6 +391,9 @@ If ``registry`` is specified then the model will show providers and algorithms
from the given registry. If no registry is specified, then the processing
registry attached to QgsApplication.processingRegistry() will be used
by the model.

If \recentLog is specified then it will be used to create a "Recently used" top
level group containing recently used algorithms.
%End

QgsProcessingToolboxModel *toolboxModel();
@@ -0,0 +1,87 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/processing/qgsprocessingtoolboxtreeview.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsProcessingToolboxTreeView : QTreeView
{
%Docstring
Processing toolbox tree view, showing algorithms and providers in a tree structure.

.. versionadded:: 3.4

.. warning::

Not part of stable API and may change in future QGIS releases.
%End

%TypeHeaderCode
#include "qgsprocessingtoolboxtreeview.h"
%End
public:

QgsProcessingToolboxTreeView( QWidget *parent /TransferThis/ = 0,
QgsProcessingRegistry *registry = 0,
QgsProcessingRecentAlgorithmLog *recentLog = 0 );
%Docstring
Constructor for QgsProcessingToolboxTreeView, with the specified ``parent`` widget.

If ``registry`` is set, then the view will automatically be populated with algorithms
and providers from the registry. Otherwise, users must manually call setRegistry()
to associate a registry with the view.

If \recentLog is specified then it will be used to create a "Recently used" top
level group containing recently used algorithms.
%End

void setRegistry(
QgsProcessingRegistry *registry,
QgsProcessingRecentAlgorithmLog *recentLog = 0 );
%Docstring
Sets the processing ``registry`` associated with the view.

If \recentLog is specified then it will be used to create a "Recently used" top
level group containing recently used algorithms.
%End

const QgsProcessingAlgorithm *algorithmForIndex( const QModelIndex &index );
%Docstring
Returns the algorithm at the specified tree view ``index``, or a None
if the index does not correspond to an algorithm.
%End

const QgsProcessingAlgorithm *selectedAlgorithm();
%Docstring
Returns the currently selected algorithm in the tree view, or a None
if no algorithm is currently selected.
%End

void setFilters( QgsProcessingToolboxProxyModel::Filters filters );
%Docstring
Sets ``filters`` controlling the view's contents.
%End

public slots:

void setFilterString( const QString &filter );
%Docstring
Sets a ``filter`` string, used to filter out the contents of the view
to matching algorithms.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/processing/qgsprocessingtoolboxtreeview.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -317,4 +317,5 @@
%Include auto_generated/processing/qgsprocessingalgorithmdialogbase.sip
%Include auto_generated/processing/qgsprocessingrecentalgorithmlog.sip
%Include auto_generated/processing/qgsprocessingtoolboxmodel.sip
%Include auto_generated/processing/qgsprocessingtoolboxtreeview.sip
%Include auto_generated/qgsadvanceddigitizingcanvasitem.sip
@@ -30,8 +30,8 @@
import warnings

from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt, QCoreApplication, QModelIndex, QItemSelectionModel
from qgis.PyQt.QtWidgets import QToolButton, QMenu, QAction, QMessageBox
from qgis.PyQt.QtCore import Qt, QCoreApplication
from qgis.PyQt.QtWidgets import QToolButton, QMenu, QAction
from qgis.utils import iface
from qgis.core import (QgsApplication,
QgsProcessingAlgorithm)
@@ -40,8 +40,7 @@
QgsProcessingToolboxProxyModel)

from processing.gui.Postprocessing import handleAlgorithmResults
from processing.core.ProcessingLog import ProcessingLog
from processing.core.ProcessingConfig import ProcessingConfig, settingsWatcher
from processing.core.ProcessingConfig import ProcessingConfig
from processing.gui.MessageDialog import MessageDialog
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.BatchAlgorithmDialog import BatchAlgorithmDialog
@@ -76,15 +75,13 @@ def __init__(self):
self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.processingToolbar.setIconSize(iface.iconSize(True))

self.model = QgsProcessingToolboxProxyModel(self,
QgsApplication.processingRegistry(),
QgsGui.instance().processingRecentAlgorithmLog())
self.model.setFilters(QgsProcessingToolboxProxyModel.FilterToolbox)
self.algorithmTree.setModel(self.model)
self.algorithmTree.setRegistry(QgsApplication.processingRegistry(),
QgsGui.instance().processingRecentAlgorithmLog())
self.algorithmTree.setFilters(QgsProcessingToolboxProxyModel.FilterToolbox)

self.searchBox.setShowSearchIcon(True)

self.searchBox.textChanged.connect(self.textChanged)
self.searchBox.textChanged.connect(self.algorithmTree.setFilterString)
self.searchBox.returnPressed.connect(self.activateCurrent)
self.algorithmTree.customContextMenuRequested.connect(
self.showPopupMenu)
@@ -122,33 +119,6 @@ def disabledProviders(self):

return False

def textChanged(self):
text = self.searchBox.text().strip(' ').lower()
self.model.setFilterString(text)
if text:
self.algorithmTree.expandAll()
if not self.algorithmTree.selectionModel().hasSelection():
# if previously selected item was hidden, auto select the first visible algorithm
first_visible_index = self._findFirstVisibleAlgorithm(QModelIndex())
if first_visible_index is not None:
self.algorithmTree.selectionModel().setCurrentIndex(first_visible_index, QItemSelectionModel.ClearAndSelect)
else:
self.algorithmTree.collapseAll()

def _findFirstVisibleAlgorithm(self, parent_index):
"""
Returns the first visible algorithm in the tree widget
"""
for r in range(self.model.rowCount(parent_index)):
proxy_index = self.model.index(r, 0, parent_index)
source_index = self.model.mapToSource(proxy_index)
if self.model.toolboxModel().isAlgorithm(source_index):
return proxy_index
index = self._findFirstVisibleAlgorithm(proxy_index)
if index is not None:
return index
return None

def addProviderActions(self, provider):
if provider.id() in ProviderActions.actions:
toolbarButton = QToolButton()
@@ -176,22 +146,10 @@ def removeProvider(self, provider_id):
if button:
self.processingToolbar.removeChild(button)

def algorithm_for_index(self, index):
source_index = self.model.mapToSource(index)
if self.model.toolboxModel().isAlgorithm(source_index):
return self.model.toolboxModel().algorithmForIndex(source_index)
return None

def selected_algorithm(self):
if self.algorithmTree.selectionModel().hasSelection():
index = self.algorithmTree.selectionModel().selectedIndexes()[0]
return self.algorithm_for_index(index)
return None

def showPopupMenu(self, point):
index = self.algorithmTree.indexAt(point)
popupmenu = QMenu()
alg = self.algorithm_for_index(index)
alg = self.algorithmTree.algorithmForIndex(index)
if alg is not None:
executeAction = QAction(QCoreApplication.translate('ProcessingToolbox', 'Execute…'), popupmenu)
executeAction.triggered.connect(self.executeAlgorithm)
@@ -224,7 +182,7 @@ def showPopupMenu(self, point):
popupmenu.exec_(self.algorithmTree.mapToGlobal(point))

def editRenderingStyles(self):
alg = self.selected_algorithm()
alg = self.algorithmTree.selectedAlgorithm()
if alg is not None:
dlg = EditRenderingStylesDialog(alg)
dlg.exec_()
@@ -233,14 +191,14 @@ def activateCurrent(self):
self.executeAlgorithm()

def executeAlgorithmAsBatchProcess(self):
alg = self.selected_algorithm()
alg = self.algorithmTree.selectedAlgorithm()
if alg is not None:
dlg = BatchAlgorithmDialog(alg)
dlg.show()
dlg.exec_()

def executeAlgorithm(self):
alg = self.selected_algorithm()
alg = self.algorithmTree.selectedAlgorithm()
if alg is not None:
ok, message = alg.canExecute()
if not ok:
@@ -51,7 +51,7 @@
</widget>
</item>
<item>
<widget class="QTreeView" name="algorithmTree">
<widget class="QgsProcessingToolboxTreeView" name="algorithmTree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
@@ -96,6 +96,11 @@ color: rgb(255, 255, 255);</string>
<class>QgsFilterLineEdit</class>
<extends>QLineEdit</extends>
<header>qgis.gui</header>
</customwidget>
<customwidget>
<class>QgsProcessingToolboxTreeView</class>
<extends>QTreeView</extends>
<header>qgis.gui</header>
</customwidget>
</customwidgets>
<resources/>
@@ -199,6 +199,7 @@ SET(QGIS_GUI_SRCS
processing/qgsprocessingguiregistry.cpp
processing/qgsprocessingrecentalgorithmlog.cpp
processing/qgsprocessingtoolboxmodel.cpp
processing/qgsprocessingtoolboxtreeview.cpp

qgisinterface.cpp
qgsactionmenu.cpp
@@ -721,6 +722,7 @@ SET(QGIS_GUI_MOC_HDRS
processing/qgsprocessingconfigurationwidgets.h
processing/qgsprocessingrecentalgorithmlog.h
processing/qgsprocessingtoolboxmodel.h
processing/qgsprocessingtoolboxtreeview.h
)
SET_PROPERTY(GLOBAL PROPERTY QGIS_GUI_MOC_HDRS ${QGIS_GUI_MOC_HDRS})

@@ -402,9 +402,6 @@ class GUI_EXPORT QgsProcessingToolboxModel : public QAbstractItemModel
* which automatically sorts the toolbox in a logical fashion and supports filtering
* the results.
*
* If \recentLog is specified then it will be used to create a "Recently used" top
* level group containing recently used algorithms.
*
* \ingroup gui
* \since QGIS 3.2
*/
@@ -429,6 +426,9 @@ class GUI_EXPORT QgsProcessingToolboxProxyModel: public QSortFilterProxyModel
* from the given registry. If no registry is specified, then the processing
* registry attached to QgsApplication::processingRegistry() will be used
* by the model.
*
* If \recentLog is specified then it will be used to create a "Recently used" top
* level group containing recently used algorithms.
*/
explicit QgsProcessingToolboxProxyModel( QObject *parent SIP_TRANSFERTHIS = nullptr,
QgsProcessingRegistry *registry = nullptr,
@@ -0,0 +1,101 @@
/***************************************************************************
qgsprocessingtoolboxtreeview.cpp
-------------------------------
begin : July 2018
copyright : (C) 2018 by Nyall Dawso
email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsprocessingtoolboxtreeview.h"
#include "qgsprocessingtoolboxmodel.h"

QgsProcessingToolboxTreeView::QgsProcessingToolboxTreeView( QWidget *parent,
QgsProcessingRegistry *registry,
QgsProcessingRecentAlgorithmLog *recentLog )
: QTreeView( parent )
{
mModel = new QgsProcessingToolboxProxyModel( this, registry, recentLog );
mToolboxModel = mModel->toolboxModel();
setModel( mModel );
}

void QgsProcessingToolboxTreeView::setRegistry( QgsProcessingRegistry *registry, QgsProcessingRecentAlgorithmLog *recentLog )
{
QgsProcessingToolboxProxyModel *newModel = new QgsProcessingToolboxProxyModel( this, registry, recentLog );
mToolboxModel = mModel->toolboxModel();
setModel( newModel );
mModel->deleteLater();
mModel = newModel;
}

void QgsProcessingToolboxTreeView::setFilterString( const QString &filter )
{
const QString text = filter.trimmed().toLower();
mModel->setFilterString( text );
if ( !text.isEmpty() )
{
expandAll();
if ( !selectedAlgorithm() )
{
// if previously selected item was hidden, auto select the first visible algorithm
QModelIndex firstVisibleIndex = findFirstVisibleAlgorithm( QModelIndex() );
if ( firstVisibleIndex.isValid() )
selectionModel()->setCurrentIndex( firstVisibleIndex, QItemSelectionModel::ClearAndSelect );
}
}
else
{
collapseAll();
}
}

const QgsProcessingAlgorithm *QgsProcessingToolboxTreeView::algorithmForIndex( const QModelIndex &index )
{
QModelIndex sourceIndex = mModel->mapToSource( index );
if ( mToolboxModel->isAlgorithm( sourceIndex ) )
return mToolboxModel->algorithmForIndex( sourceIndex );
else
return nullptr;
}

const QgsProcessingAlgorithm *QgsProcessingToolboxTreeView::selectedAlgorithm()
{
if ( selectionModel()->hasSelection() )
{
QModelIndex index = selectionModel()->selectedIndexes().at( 0 );
return algorithmForIndex( index );
}
else
{
return nullptr;
}
}

void QgsProcessingToolboxTreeView::setFilters( QgsProcessingToolboxProxyModel::Filters filters )
{
mModel->setFilters( filters );
}

QModelIndex QgsProcessingToolboxTreeView::findFirstVisibleAlgorithm( const QModelIndex &parent )
{
for ( int r = 0; r < mModel->rowCount( parent ); ++r )
{
QModelIndex proxyIndex = mModel->index( r, 0, parent );
QModelIndex sourceIndex = mModel->mapToSource( proxyIndex );
if ( mToolboxModel->isAlgorithm( sourceIndex ) )
return proxyIndex;

QModelIndex index = findFirstVisibleAlgorithm( proxyIndex );
if ( index.isValid() )
return index;
}
return QModelIndex();
}

0 comments on commit 101c98f

Please sign in to comment.
You can’t perform that action at this time.