Skip to content

Commit 101c98f

Browse files
committed
Move toolbox tree view to c++ class
1 parent 810cb9c commit 101c98f

File tree

9 files changed

+317
-60
lines changed

9 files changed

+317
-60
lines changed

python/gui/auto_generated/processing/qgsprocessingtoolboxmodel.sip.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,6 @@ A sort/filter proxy model for providers and algorithms shown within the Processi
365365
which automatically sorts the toolbox in a logical fashion and supports filtering
366366
the results.
367367

368-
If \recentLog is specified then it will be used to create a "Recently used" top
369-
level group containing recently used algorithms.
370-
371368
.. versionadded:: 3.2
372369
%End
373370

@@ -394,6 +391,9 @@ If ``registry`` is specified then the model will show providers and algorithms
394391
from the given registry. If no registry is specified, then the processing
395392
registry attached to QgsApplication.processingRegistry() will be used
396393
by the model.
394+
395+
If \recentLog is specified then it will be used to create a "Recently used" top
396+
level group containing recently used algorithms.
397397
%End
398398

399399
QgsProcessingToolboxModel *toolboxModel();
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/processing/qgsprocessingtoolboxtreeview.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
13+
class QgsProcessingToolboxTreeView : QTreeView
14+
{
15+
%Docstring
16+
Processing toolbox tree view, showing algorithms and providers in a tree structure.
17+
18+
.. versionadded:: 3.4
19+
20+
.. warning::
21+
22+
Not part of stable API and may change in future QGIS releases.
23+
%End
24+
25+
%TypeHeaderCode
26+
#include "qgsprocessingtoolboxtreeview.h"
27+
%End
28+
public:
29+
30+
QgsProcessingToolboxTreeView( QWidget *parent /TransferThis/ = 0,
31+
QgsProcessingRegistry *registry = 0,
32+
QgsProcessingRecentAlgorithmLog *recentLog = 0 );
33+
%Docstring
34+
Constructor for QgsProcessingToolboxTreeView, with the specified ``parent`` widget.
35+
36+
If ``registry`` is set, then the view will automatically be populated with algorithms
37+
and providers from the registry. Otherwise, users must manually call setRegistry()
38+
to associate a registry with the view.
39+
40+
If \recentLog is specified then it will be used to create a "Recently used" top
41+
level group containing recently used algorithms.
42+
%End
43+
44+
void setRegistry(
45+
QgsProcessingRegistry *registry,
46+
QgsProcessingRecentAlgorithmLog *recentLog = 0 );
47+
%Docstring
48+
Sets the processing ``registry`` associated with the view.
49+
50+
If \recentLog is specified then it will be used to create a "Recently used" top
51+
level group containing recently used algorithms.
52+
%End
53+
54+
const QgsProcessingAlgorithm *algorithmForIndex( const QModelIndex &index );
55+
%Docstring
56+
Returns the algorithm at the specified tree view ``index``, or a None
57+
if the index does not correspond to an algorithm.
58+
%End
59+
60+
const QgsProcessingAlgorithm *selectedAlgorithm();
61+
%Docstring
62+
Returns the currently selected algorithm in the tree view, or a None
63+
if no algorithm is currently selected.
64+
%End
65+
66+
void setFilters( QgsProcessingToolboxProxyModel::Filters filters );
67+
%Docstring
68+
Sets ``filters`` controlling the view's contents.
69+
%End
70+
71+
public slots:
72+
73+
void setFilterString( const QString &filter );
74+
%Docstring
75+
Sets a ``filter`` string, used to filter out the contents of the view
76+
to matching algorithms.
77+
%End
78+
79+
};
80+
81+
/************************************************************************
82+
* This file has been generated automatically from *
83+
* *
84+
* src/gui/processing/qgsprocessingtoolboxtreeview.h *
85+
* *
86+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
87+
************************************************************************/

python/gui/gui_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,4 +317,5 @@
317317
%Include auto_generated/processing/qgsprocessingalgorithmdialogbase.sip
318318
%Include auto_generated/processing/qgsprocessingrecentalgorithmlog.sip
319319
%Include auto_generated/processing/qgsprocessingtoolboxmodel.sip
320+
%Include auto_generated/processing/qgsprocessingtoolboxtreeview.sip
320321
%Include auto_generated/qgsadvanceddigitizingcanvasitem.sip

python/plugins/processing/gui/ProcessingToolbox.py

Lines changed: 11 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
import warnings
3131

3232
from qgis.PyQt import uic
33-
from qgis.PyQt.QtCore import Qt, QCoreApplication, QModelIndex, QItemSelectionModel
34-
from qgis.PyQt.QtWidgets import QToolButton, QMenu, QAction, QMessageBox
33+
from qgis.PyQt.QtCore import Qt, QCoreApplication
34+
from qgis.PyQt.QtWidgets import QToolButton, QMenu, QAction
3535
from qgis.utils import iface
3636
from qgis.core import (QgsApplication,
3737
QgsProcessingAlgorithm)
@@ -40,8 +40,7 @@
4040
QgsProcessingToolboxProxyModel)
4141

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

79-
self.model = QgsProcessingToolboxProxyModel(self,
80-
QgsApplication.processingRegistry(),
81-
QgsGui.instance().processingRecentAlgorithmLog())
82-
self.model.setFilters(QgsProcessingToolboxProxyModel.FilterToolbox)
83-
self.algorithmTree.setModel(self.model)
78+
self.algorithmTree.setRegistry(QgsApplication.processingRegistry(),
79+
QgsGui.instance().processingRecentAlgorithmLog())
80+
self.algorithmTree.setFilters(QgsProcessingToolboxProxyModel.FilterToolbox)
8481

8582
self.searchBox.setShowSearchIcon(True)
8683

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

123120
return False
124121

125-
def textChanged(self):
126-
text = self.searchBox.text().strip(' ').lower()
127-
self.model.setFilterString(text)
128-
if text:
129-
self.algorithmTree.expandAll()
130-
if not self.algorithmTree.selectionModel().hasSelection():
131-
# if previously selected item was hidden, auto select the first visible algorithm
132-
first_visible_index = self._findFirstVisibleAlgorithm(QModelIndex())
133-
if first_visible_index is not None:
134-
self.algorithmTree.selectionModel().setCurrentIndex(first_visible_index, QItemSelectionModel.ClearAndSelect)
135-
else:
136-
self.algorithmTree.collapseAll()
137-
138-
def _findFirstVisibleAlgorithm(self, parent_index):
139-
"""
140-
Returns the first visible algorithm in the tree widget
141-
"""
142-
for r in range(self.model.rowCount(parent_index)):
143-
proxy_index = self.model.index(r, 0, parent_index)
144-
source_index = self.model.mapToSource(proxy_index)
145-
if self.model.toolboxModel().isAlgorithm(source_index):
146-
return proxy_index
147-
index = self._findFirstVisibleAlgorithm(proxy_index)
148-
if index is not None:
149-
return index
150-
return None
151-
152122
def addProviderActions(self, provider):
153123
if provider.id() in ProviderActions.actions:
154124
toolbarButton = QToolButton()
@@ -176,22 +146,10 @@ def removeProvider(self, provider_id):
176146
if button:
177147
self.processingToolbar.removeChild(button)
178148

179-
def algorithm_for_index(self, index):
180-
source_index = self.model.mapToSource(index)
181-
if self.model.toolboxModel().isAlgorithm(source_index):
182-
return self.model.toolboxModel().algorithmForIndex(source_index)
183-
return None
184-
185-
def selected_algorithm(self):
186-
if self.algorithmTree.selectionModel().hasSelection():
187-
index = self.algorithmTree.selectionModel().selectedIndexes()[0]
188-
return self.algorithm_for_index(index)
189-
return None
190-
191149
def showPopupMenu(self, point):
192150
index = self.algorithmTree.indexAt(point)
193151
popupmenu = QMenu()
194-
alg = self.algorithm_for_index(index)
152+
alg = self.algorithmTree.algorithmForIndex(index)
195153
if alg is not None:
196154
executeAction = QAction(QCoreApplication.translate('ProcessingToolbox', 'Execute…'), popupmenu)
197155
executeAction.triggered.connect(self.executeAlgorithm)
@@ -224,7 +182,7 @@ def showPopupMenu(self, point):
224182
popupmenu.exec_(self.algorithmTree.mapToGlobal(point))
225183

226184
def editRenderingStyles(self):
227-
alg = self.selected_algorithm()
185+
alg = self.algorithmTree.selectedAlgorithm()
228186
if alg is not None:
229187
dlg = EditRenderingStylesDialog(alg)
230188
dlg.exec_()
@@ -233,14 +191,14 @@ def activateCurrent(self):
233191
self.executeAlgorithm()
234192

235193
def executeAlgorithmAsBatchProcess(self):
236-
alg = self.selected_algorithm()
194+
alg = self.algorithmTree.selectedAlgorithm()
237195
if alg is not None:
238196
dlg = BatchAlgorithmDialog(alg)
239197
dlg.show()
240198
dlg.exec_()
241199

242200
def executeAlgorithm(self):
243-
alg = self.selected_algorithm()
201+
alg = self.algorithmTree.selectedAlgorithm()
244202
if alg is not None:
245203
ok, message = alg.canExecute()
246204
if not ok:

python/plugins/processing/ui/ProcessingToolbox.ui

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
</widget>
5252
</item>
5353
<item>
54-
<widget class="QTreeView" name="algorithmTree">
54+
<widget class="QgsProcessingToolboxTreeView" name="algorithmTree">
5555
<property name="contextMenuPolicy">
5656
<enum>Qt::CustomContextMenu</enum>
5757
</property>
@@ -96,6 +96,11 @@ color: rgb(255, 255, 255);</string>
9696
<class>QgsFilterLineEdit</class>
9797
<extends>QLineEdit</extends>
9898
<header>qgis.gui</header>
99+
</customwidget>
100+
<customwidget>
101+
<class>QgsProcessingToolboxTreeView</class>
102+
<extends>QTreeView</extends>
103+
<header>qgis.gui</header>
99104
</customwidget>
100105
</customwidgets>
101106
<resources/>

src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ SET(QGIS_GUI_SRCS
199199
processing/qgsprocessingguiregistry.cpp
200200
processing/qgsprocessingrecentalgorithmlog.cpp
201201
processing/qgsprocessingtoolboxmodel.cpp
202+
processing/qgsprocessingtoolboxtreeview.cpp
202203

203204
qgisinterface.cpp
204205
qgsactionmenu.cpp
@@ -721,6 +722,7 @@ SET(QGIS_GUI_MOC_HDRS
721722
processing/qgsprocessingconfigurationwidgets.h
722723
processing/qgsprocessingrecentalgorithmlog.h
723724
processing/qgsprocessingtoolboxmodel.h
725+
processing/qgsprocessingtoolboxtreeview.h
724726
)
725727
SET_PROPERTY(GLOBAL PROPERTY QGIS_GUI_MOC_HDRS ${QGIS_GUI_MOC_HDRS})
726728

src/gui/processing/qgsprocessingtoolboxmodel.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,6 @@ class GUI_EXPORT QgsProcessingToolboxModel : public QAbstractItemModel
402402
* which automatically sorts the toolbox in a logical fashion and supports filtering
403403
* the results.
404404
*
405-
* If \recentLog is specified then it will be used to create a "Recently used" top
406-
* level group containing recently used algorithms.
407-
*
408405
* \ingroup gui
409406
* \since QGIS 3.2
410407
*/
@@ -429,6 +426,9 @@ class GUI_EXPORT QgsProcessingToolboxProxyModel: public QSortFilterProxyModel
429426
* from the given registry. If no registry is specified, then the processing
430427
* registry attached to QgsApplication::processingRegistry() will be used
431428
* by the model.
429+
*
430+
* If \recentLog is specified then it will be used to create a "Recently used" top
431+
* level group containing recently used algorithms.
432432
*/
433433
explicit QgsProcessingToolboxProxyModel( QObject *parent SIP_TRANSFERTHIS = nullptr,
434434
QgsProcessingRegistry *registry = nullptr,
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/***************************************************************************
2+
qgsprocessingtoolboxtreeview.cpp
3+
-------------------------------
4+
begin : July 2018
5+
copyright : (C) 2018 by Nyall Dawso
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsprocessingtoolboxtreeview.h"
17+
#include "qgsprocessingtoolboxmodel.h"
18+
19+
QgsProcessingToolboxTreeView::QgsProcessingToolboxTreeView( QWidget *parent,
20+
QgsProcessingRegistry *registry,
21+
QgsProcessingRecentAlgorithmLog *recentLog )
22+
: QTreeView( parent )
23+
{
24+
mModel = new QgsProcessingToolboxProxyModel( this, registry, recentLog );
25+
mToolboxModel = mModel->toolboxModel();
26+
setModel( mModel );
27+
}
28+
29+
void QgsProcessingToolboxTreeView::setRegistry( QgsProcessingRegistry *registry, QgsProcessingRecentAlgorithmLog *recentLog )
30+
{
31+
QgsProcessingToolboxProxyModel *newModel = new QgsProcessingToolboxProxyModel( this, registry, recentLog );
32+
mToolboxModel = mModel->toolboxModel();
33+
setModel( newModel );
34+
mModel->deleteLater();
35+
mModel = newModel;
36+
}
37+
38+
void QgsProcessingToolboxTreeView::setFilterString( const QString &filter )
39+
{
40+
const QString text = filter.trimmed().toLower();
41+
mModel->setFilterString( text );
42+
if ( !text.isEmpty() )
43+
{
44+
expandAll();
45+
if ( !selectedAlgorithm() )
46+
{
47+
// if previously selected item was hidden, auto select the first visible algorithm
48+
QModelIndex firstVisibleIndex = findFirstVisibleAlgorithm( QModelIndex() );
49+
if ( firstVisibleIndex.isValid() )
50+
selectionModel()->setCurrentIndex( firstVisibleIndex, QItemSelectionModel::ClearAndSelect );
51+
}
52+
}
53+
else
54+
{
55+
collapseAll();
56+
}
57+
}
58+
59+
const QgsProcessingAlgorithm *QgsProcessingToolboxTreeView::algorithmForIndex( const QModelIndex &index )
60+
{
61+
QModelIndex sourceIndex = mModel->mapToSource( index );
62+
if ( mToolboxModel->isAlgorithm( sourceIndex ) )
63+
return mToolboxModel->algorithmForIndex( sourceIndex );
64+
else
65+
return nullptr;
66+
}
67+
68+
const QgsProcessingAlgorithm *QgsProcessingToolboxTreeView::selectedAlgorithm()
69+
{
70+
if ( selectionModel()->hasSelection() )
71+
{
72+
QModelIndex index = selectionModel()->selectedIndexes().at( 0 );
73+
return algorithmForIndex( index );
74+
}
75+
else
76+
{
77+
return nullptr;
78+
}
79+
}
80+
81+
void QgsProcessingToolboxTreeView::setFilters( QgsProcessingToolboxProxyModel::Filters filters )
82+
{
83+
mModel->setFilters( filters );
84+
}
85+
86+
QModelIndex QgsProcessingToolboxTreeView::findFirstVisibleAlgorithm( const QModelIndex &parent )
87+
{
88+
for ( int r = 0; r < mModel->rowCount( parent ); ++r )
89+
{
90+
QModelIndex proxyIndex = mModel->index( r, 0, parent );
91+
QModelIndex sourceIndex = mModel->mapToSource( proxyIndex );
92+
if ( mToolboxModel->isAlgorithm( sourceIndex ) )
93+
return proxyIndex;
94+
95+
QModelIndex index = findFirstVisibleAlgorithm( proxyIndex );
96+
if ( index.isValid() )
97+
return index;
98+
}
99+
return QModelIndex();
100+
}
101+

0 commit comments

Comments
 (0)