Skip to content

Commit 1a6d3bc

Browse files
committed
add new tab search widget and upgrad the original one
1 parent d7c3f32 commit 1a6d3bc

File tree

3 files changed

+151
-15
lines changed

3 files changed

+151
-15
lines changed

NodeGraphQt/widgets/properties_bin.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,7 @@ def add_node(self, node):
181181
Args:
182182
node (NodeGraphQt.NodeObject): node object.
183183
"""
184-
if self.limit() == 0:
185-
return
186-
if self._lock:
184+
if self.limit() == 0 or self._lock:
187185
return
188186

189187
itm_find = self._prop_list.findItems(node.id, QtCore.Qt.MatchExactly)

NodeGraphQt/widgets/tab_search.py

Lines changed: 145 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/python
2-
from NodeGraphQt import QtCore, QtWidgets
2+
from NodeGraphQt import QtCore, QtWidgets,QtGui
33

4-
from NodeGraphQt.widgets.stylesheet import STYLE_TABSEARCH, STYLE_TABSEARCH_LIST
4+
from NodeGraphQt.widgets.stylesheet import STYLE_TABSEARCH, STYLE_TABSEARCH_LIST, STYLE_QMENU
55

66

77
class TabSearchCompleter(QtWidgets.QCompleter):
@@ -22,17 +22,20 @@ def __init__(self, nodes=None, parent=None):
2222
def splitPath(self, path):
2323
self._local_completion_prefix = path
2424
self.updateModel()
25+
2526
if self._filter_model.rowCount() == 0:
2627
self._using_orig_model = False
27-
self._filter_model.setSourceModel(QtCore.QStringListModel([path]))
28-
return [path]
28+
self._filter_model.setSourceModel(QtCore.QStringListModel([]))
29+
return []
2930
return []
3031

31-
def updateModel(self):
32+
def updateModel(self,text=None):
3233
if not self._using_orig_model:
3334
self._filter_model.setSourceModel(self._source_model)
3435

35-
pattern = QtCore.QRegExp(self._local_completion_prefix,
36+
text = text or self._local_completion_prefix
37+
print(text)
38+
pattern = QtCore.QRegExp(text,
3639
QtCore.Qt.CaseInsensitive,
3740
QtCore.QRegExp.FixedString)
3841
self._filter_model.setFilterRegExp(pattern)
@@ -70,24 +73,35 @@ def __init__(self, parent=None, node_dict=None):
7073
popup.setStyleSheet(STYLE_TABSEARCH_LIST)
7174
popup.clicked.connect(self._on_search_submitted)
7275
self.returnPressed.connect(self._on_search_submitted)
76+
self.textChanged.connect(self._on_text_changed)
7377

7478
def __repr__(self):
7579
return '<{} at {}>'.format(self.__class__.__name__, hex(id(self)))
7680

7781
def _on_search_submitted(self, index=0):
7882
node_type = self._node_dict.get(self.text())
83+
if not node_type:
84+
model = self._completer.popup().model()
85+
text = model.data(model.index(0, 0))
86+
node_type = self._node_dict.get(text)
87+
7988
if node_type:
8089
self.search_submitted.emit(node_type)
90+
8191
self.close()
8292
self.parentWidget().clearFocus()
8393

94+
def _on_text_changed(self, text):
95+
if not text:
96+
# TODO: show all items
97+
pass
98+
8499
def showEvent(self, event):
85100
super(TabSearchWidget, self).showEvent(event)
86-
self.setSelection(0, len(self.text()))
87101
self.setFocus()
88-
if not self.text():
89-
self.completer().popup().show()
90-
self.completer().complete()
102+
self.setText("")
103+
self.completer().popup().show()
104+
self.completer().complete()
91105

92106
def mousePressEvent(self, event):
93107
if not self.text():
@@ -104,3 +118,124 @@ def set_nodes(self, node_dict=None):
104118
node_names = sorted(self._node_dict.keys())
105119
self._model.setStringList(node_names)
106120
self._completer.setModel(self._model)
121+
122+
123+
class TabSearchMenuWidget(QtWidgets.QLineEdit):
124+
search_submitted = QtCore.Signal(str)
125+
126+
def __init__(self, parent=None, node_dict=None):
127+
super(TabSearchMenuWidget, self).__init__(parent)
128+
self.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0)
129+
self.setStyleSheet(STYLE_TABSEARCH)
130+
self.setMinimumSize(200, 22)
131+
self.setTextMargins(2, 0, 2, 0)
132+
133+
self._node_dict = node_dict or {}
134+
if self._node_dict:
135+
self._generate_items_from_node_dict()
136+
137+
self.SearchMenu = QtWidgets.QMenu()
138+
searchWidget = QtWidgets.QWidgetAction(self)
139+
searchWidget.setDefaultWidget(self)
140+
self.SearchMenu.addAction(searchWidget)
141+
self.SearchMenu.setStyleSheet(STYLE_QMENU)
142+
143+
self._actions = []
144+
self._menus = {}
145+
self._searched_actions = []
146+
147+
self.returnPressed.connect(self._on_search_submitted)
148+
self.textChanged.connect(self._on_text_changed)
149+
150+
def __repr__(self):
151+
return '<{} at {}>'.format(self.__class__.__name__, hex(id(self)))
152+
153+
def _on_text_changed(self,text):
154+
self._clear_actions()
155+
156+
if not text:
157+
self._set_menu_visible(True)
158+
return
159+
160+
self._set_menu_visible(False)
161+
162+
self._searched_actions = [action for action in self._actions\
163+
if text.lower() in action.text().lower()]
164+
165+
self.SearchMenu.addActions(self._searched_actions)
166+
167+
def _clear_actions(self):
168+
for action in self._searched_actions:
169+
self.SearchMenu.removeAction(action)
170+
self._searched_actions = []
171+
172+
def _set_menu_visible(self,visible):
173+
for menu in self._menus.values():
174+
menu.menuAction().setVisible(visible)
175+
176+
def _close(self):
177+
self._set_menu_visible(False)
178+
self.SearchMenu.setVisible(False)
179+
self.SearchMenu.menuAction().setVisible(False)
180+
181+
def _show(self):
182+
self.SearchMenu.exec_(QtGui.QCursor.pos())
183+
self.setText("")
184+
self.setFocus()
185+
self._set_menu_visible(True)
186+
187+
def _on_search_submitted(self):
188+
action = self.sender()
189+
if type(action) is not QtWidgets.QAction:
190+
if len(self._searched_actions) > 0:
191+
action = self._searched_actions[0]
192+
else:
193+
self._close()
194+
return
195+
196+
text = action.text()
197+
node_type = self._node_dict.get(text)
198+
if node_type:
199+
self.search_submitted.emit(node_type)
200+
201+
self._close()
202+
203+
def _generate_items_from_node_dict(self):
204+
node_names = sorted(self._node_dict.keys())
205+
node_types = sorted(self._node_dict.values())
206+
207+
for node_type in node_types:
208+
menu_name = ".".join(node_type.split(".")[:-1])
209+
if menu_name not in self._menus.keys():
210+
new_menu = QtWidgets.QMenu(menu_name)
211+
new_menu.setStyleSheet(STYLE_QMENU)
212+
self._menus[menu_name] = new_menu
213+
self.SearchMenu.addMenu(new_menu)
214+
215+
for name in node_names:
216+
action = QtWidgets.QAction(name, self)
217+
action.setText(name)
218+
action.triggered.connect(self._on_search_submitted)
219+
self._actions.append(action)
220+
221+
menu_name = self._node_dict[name]
222+
menu_name = ".".join(menu_name.split(".")[:-1])
223+
224+
if menu_name in self._menus.keys():
225+
self._menus[menu_name].addAction(action)
226+
else:
227+
self.SearchMenu.addAction(action)
228+
229+
def set_nodes(self, node_dict=None):
230+
if not self._node_dict:
231+
self._node_dict = {}
232+
for name, node_types in node_dict.items():
233+
if len(node_types) == 1:
234+
self._node_dict[name] = node_types[0]
235+
continue
236+
for node_id in node_types:
237+
self._node_dict['{} ({})'.format(name, node_id)] = node_id
238+
self._generate_items_from_node_dict()
239+
240+
self._show()
241+

NodeGraphQt/widgets/viewer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from NodeGraphQt.qgraphics.slicer import SlicerPipe
1515
from NodeGraphQt.widgets.actions import BaseMenu
1616
from NodeGraphQt.widgets.scene import NodeScene
17-
from NodeGraphQt.widgets.tab_search import TabSearchWidget
17+
from NodeGraphQt.widgets.tab_search import TabSearchWidget, TabSearchMenuWidget
1818

1919
ZOOM_MIN = -0.95
2020
ZOOM_MAX = 2.0
@@ -73,7 +73,7 @@ def __init__(self, parent=None):
7373
self.scene().addItem(self._SLICER_PIPE)
7474

7575
self._undo_stack = QtWidgets.QUndoStack(self)
76-
self._search_widget = TabSearchWidget(self)
76+
self._search_widget = TabSearchMenuWidget(self)
7777
self._search_widget.search_submitted.connect(self._on_search_submitted)
7878

7979
# workaround fix for shortcuts from the non-native menu actions
@@ -652,6 +652,9 @@ def tab_search_set_nodes(self, nodes):
652652
self._search_widget.set_nodes(nodes)
653653

654654
def tab_search_toggle(self):
655+
if type(self._search_widget) is TabSearchMenuWidget:
656+
return
657+
655658
pos = self._previous_pos
656659
state = not self._search_widget.isVisible()
657660
if state:

0 commit comments

Comments
 (0)