Run tools, show extra info
This commit is contained in:
parent
2ce29431a5
commit
f29abe0813
|
@ -1,2 +0,0 @@
|
|||
# action = json.loads(str(index.model().data(index.siblingAtColumn(2))))
|
||||
#² actionHandlers[action['handler']](action)
|
|
@ -3,17 +3,53 @@ if True:
|
|||
|
||||
def toolbarAction(act):
|
||||
print('show toolbar ' + act['toolbar'] + ' from workbenches ' + repr(act['workbenches']))
|
||||
def toolAction(act):
|
||||
print('start action for tool ' + act['toolbar'] + '.' + act['tool'] + ' from workbenches ' + repr(act['workbenches']))
|
||||
def subToolAction(act):
|
||||
print('start action for tool ' + act['toolbar'] + '.' + act['tool'] + '.' + act['subTool'] + ' from workbenches ' + repr(act['workbenches']))
|
||||
def documentObjectAction():
|
||||
print('select object ' + o.Document.Name + '.' + o.Name)
|
||||
def documentAction():
|
||||
print('switch to document ' + o.Document.Name)
|
||||
toolPath = act['toolbar'] + '.' + act['tool']
|
||||
if 'subTool' in act:
|
||||
toolPath = toolPath + '.' + act['subTool']
|
||||
def runTool():
|
||||
for the_toolbar in mw.findChildren(QtGui.QToolBar, act['toolbar']):
|
||||
for tbt in the_toolbar.findChildren(QtGui.QToolButton):
|
||||
if tbt.text() == act['tool']:
|
||||
action = None
|
||||
if 'subTool' in act:
|
||||
men = tbt.menu()
|
||||
if men:
|
||||
for mac in men.actions():
|
||||
if mac.text() == act['subTool']:
|
||||
action = mac
|
||||
break
|
||||
else:
|
||||
action = tbt.defaultAction()
|
||||
if 'showMenu' in act and act['showMenu']:
|
||||
print('Popup submenu of tool ' + toolPath + ' available in workbenches ' + repr(act['workbenches']))
|
||||
the_toolbar.show()
|
||||
tbt.showMenu()
|
||||
return True
|
||||
elif action is not None:
|
||||
print('Run action of tool ' + toolPath + ' available in workbenches ' + repr(act['workbenches']))
|
||||
action.trigger()
|
||||
return True
|
||||
return False
|
||||
if runTool():
|
||||
return
|
||||
else:
|
||||
for workbench in act['workbenches']:
|
||||
print('Activating workbench ' + workbench + ' to access tool ' + toolPath)
|
||||
Gui.activateWorkbench(workbench)
|
||||
if runTool():
|
||||
return
|
||||
print('Tool ' + toolPath + ' not found, was it offered by an extension that is no longer present?')
|
||||
def documentObjectAction(act):
|
||||
print('select object ' + act['document'] + '.' + act['object'])
|
||||
Gui.Selection.addSelection(act['document'], act['object'])
|
||||
def documentAction(act):
|
||||
# Todo: this should also select the document in the tree view
|
||||
print('switch to document ' + act['document'])
|
||||
App.setActiveDocument(act['document'])
|
||||
actionHandlers = {
|
||||
'toolbarAction': toolbarAction,
|
||||
'toolAction': toolAction,
|
||||
'toolAction': subToolAction,
|
||||
'subToolAction': subToolAction,
|
||||
'documentObjectAction': documentObjectAction,
|
||||
'documentAction': documentAction
|
||||
|
@ -48,14 +84,22 @@ if True:
|
|||
self.listView = QtGui.QListView(self)
|
||||
self.listView.setWindowFlags(QtGui.Qt.ToolTip)
|
||||
self.listView.setWindowFlag(QtGui.Qt.FramelessWindowHint)
|
||||
self.listView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
|
||||
self.listView.setModel(self.proxyModel)
|
||||
self.listView.setItemDelegate(itemDelegate) # https://stackoverflow.com/a/65930408/324969
|
||||
# make the QListView non-editable
|
||||
self.listView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
|
||||
# Create pane for showing extra info about the currently-selected tool
|
||||
#self.extraInfo = QtGui.QLabel()
|
||||
self.extraInfo = QtGui.QTextEdit()
|
||||
self.extraInfo.setReadOnly(True)
|
||||
self.extraInfo.setWindowFlags(QtGui.Qt.ToolTip)
|
||||
self.extraInfo.setWindowFlag(QtGui.Qt.FramelessWindowHint)
|
||||
self.extraInfo.setAlignment(QtCore.Qt.AlignTop)
|
||||
# Connect signals and slots
|
||||
self.textChanged.connect(self.filterModel)
|
||||
self.listView.clicked.connect(self.selectResult)
|
||||
self.listView.selectionModel().selectionChanged.connect(self.showExtraInfo)
|
||||
self.listView.clicked.connect(lambda x: self.selectResult('select', x))
|
||||
self.listView.selectionModel().selectionChanged.connect(self.onSelectionChanged)
|
||||
# Thanks to https://saurabhg.com/programming/search-box-using-qlineedit/ for indicating a few useful options
|
||||
ico = QtGui.QIcon(':/icons/help-browser.svg')
|
||||
#ico = QtGui.QIcon(':/icons/WhatsThis.svg')
|
||||
|
@ -69,15 +113,15 @@ if True:
|
|||
self.showList()
|
||||
super(SearchBox, self).focusInEvent(qFocusEvent)
|
||||
def focusOutEvent(self, qFocusEvent):
|
||||
self.listView.hide()
|
||||
self.hideList()
|
||||
super(SearchBox, self).focusOutEvent(qFocusEvent)
|
||||
def keyPressEvent(self, qKeyEvent):
|
||||
key = qKeyEvent.key()
|
||||
listMovementKeys = {
|
||||
QtCore.Qt.Key_Down: lambda current, nbRows: (current + 1) % nbRows,
|
||||
QtCore.Qt.Key_Up: lambda current, nbRows: (current - 1) % nbRows,
|
||||
QtCore.Qt.Key_PageDown: lambda current, nbRows: max(current + min(1, self.maxVisibleRows / 2), nbRows),
|
||||
QtCore.Qt.Key_PageUp: lambda current, nbRows: min(current - min(1, self.maxVisibleRows / 2), 0),
|
||||
QtCore.Qt.Key_PageDown: lambda current, nbRows: min(current + max(1, self.maxVisibleRows / 2), nbRows - 1),
|
||||
QtCore.Qt.Key_PageUp: lambda current, nbRows: max(current - max(1, self.maxVisibleRows / 2), 0),
|
||||
}
|
||||
acceptKeys = {
|
||||
QtCore.Qt.Key_Enter: 'select',
|
||||
|
@ -101,14 +145,67 @@ if True:
|
|||
elif key in acceptKeys:
|
||||
self.showList()
|
||||
if currentIndex.isValid():
|
||||
self.selectResult(acceptKeys[key], currentIndex, currentIndex.data())
|
||||
self.selectResult(acceptKeys[key], currentIndex)
|
||||
elif key in cancelKeys:
|
||||
self.listView.hide()
|
||||
self.hideList()
|
||||
self.clearFocus()
|
||||
else:
|
||||
self.showList()
|
||||
super(SearchBox, self).keyPressEvent(qKeyEvent)
|
||||
def showList(self):
|
||||
self.setFloatingWidgetsGeometry()
|
||||
self.listView.show()
|
||||
self.showExtraInfo()
|
||||
def hideList(self):
|
||||
self.listView.hide()
|
||||
self.hideExtraInfo()
|
||||
def hideExtraInfo(self):
|
||||
self.extraInfo.hide()
|
||||
def selectResult(self, mode, index):
|
||||
action = str(index.model().itemData(index.siblingAtColumn(2))[0])
|
||||
self.hideList()
|
||||
# TODO: allow other options, e.g. some items could act as combinators / cumulative filters
|
||||
self.setText('')
|
||||
self.filterModel(self.text())
|
||||
# TODO: emit index relative to the base model
|
||||
self.resultSelected.emit(index, action)
|
||||
def filterModel(self, userInput):
|
||||
def matches(s):
|
||||
return userInput.lower() in s.lower()
|
||||
def filterGroup(group):
|
||||
if matches(group['text']):
|
||||
# If a group matches, include the entire subtree (might need to disable this if it causes too much noise)
|
||||
return group
|
||||
else:
|
||||
subitems = filterGroups(group['subitems'])
|
||||
if len(subitems) > 0 or matches(group['text']):
|
||||
return { 'text': group['text'], 'icon': group['icon'], 'action': group['action'], 'toolTipHTML':group['toolTipHTML'], 'subitems': subitems }
|
||||
else:
|
||||
return None
|
||||
def filterGroups(groups):
|
||||
groups = (filterGroup(group) for group in groups)
|
||||
return [group for group in groups if group is not None]
|
||||
def addGroups(filteredGroups, depth=0):
|
||||
for group in filteredGroups:
|
||||
mdl.appendRow([QtGui.QStandardItem(group['icon'] or QtGui.QIcon(), group['text']),
|
||||
QtGui.QStandardItem(str(depth)),
|
||||
QtGui.QStandardItem(group['action']),
|
||||
QtGui.QStandardItem(group['toolTipHTML'])])
|
||||
addGroups(group['subitems'], depth+1)
|
||||
mdl = QtGui.QStandardItemModel()
|
||||
mdl.appendColumn([])
|
||||
addGroups(filterGroups(self.itemGroups))
|
||||
self.proxyModel.setSourceModel(mdl)
|
||||
# TODO: try to find the already-highlighted item
|
||||
nbRows = self.listView.model().rowCount()
|
||||
if nbRows > 0:
|
||||
index = self.listView.model().index(0, 0)
|
||||
self.listView.setCurrentIndex(index)
|
||||
self.setExtraInfo(index)
|
||||
else:
|
||||
self.clearExtraInfo()
|
||||
#self.showList()
|
||||
def setFloatingWidgetsGeometry(self):
|
||||
def getScreenPosition(widget):
|
||||
geo = widget.geometry()
|
||||
parent = widget.parent()
|
||||
|
@ -123,174 +220,46 @@ if True:
|
|||
# TODO: this can still bump into the bottom of the screen, in that case we should flip
|
||||
w = max(siz.width(), hint_w)
|
||||
h = 100
|
||||
extraw = w # choose a preferred width that doesn't change all the time,
|
||||
# self.extraInfo.sizeHint().width() would change for every item.
|
||||
extrax = x - extraw
|
||||
if screen is not None:
|
||||
scr = screen.geometry()
|
||||
x = min(scr.x() + scr.width() - hint_w, x)
|
||||
extraleftw = x - scr.x()
|
||||
extrarightw = scr.x() + scr.width() - x
|
||||
# flip the extraInfo if it doesn't fit on the screen
|
||||
if extraleftw < extraw and extrarightw > extraleftw:
|
||||
extrax = x + w
|
||||
extraw = min(extrarightw, extraw)
|
||||
else:
|
||||
extrax = x - extraw
|
||||
extraw = min(extraleftw, extraw)
|
||||
self.listView.setGeometry(x, y, w, h)
|
||||
self.listView.show()
|
||||
def selectResult(self):
|
||||
self.listView.hide()
|
||||
# TODO: allow other options, e.g. some items could act as combinators / cumulative filters
|
||||
self.setText('')
|
||||
self.filterModel(self.text())
|
||||
self.resultSelected.emit("TODO: index", "TODO: str")
|
||||
def filterModel(self, userInput):
|
||||
def matches(s):
|
||||
return userInput.lower() in s.lower()
|
||||
def filterGroup(group):
|
||||
if matches(group['text']):
|
||||
# If a group matches, include the entire subtree (might need to disable this if it causes too much noise)
|
||||
return group
|
||||
else:
|
||||
subitems = filterGroups(group['subitems'])
|
||||
if len(subitems) > 0 or matches(group['text']):
|
||||
return { 'text': group['text'], 'icon': group['icon'], 'action': group['action'], 'subitems': subitems }
|
||||
else:
|
||||
return None
|
||||
def filterGroups(groups):
|
||||
groups = (filterGroup(group) for group in groups)
|
||||
return [group for group in groups if group is not None]
|
||||
def addGroups(filteredGroups, depth=0):
|
||||
for group in filteredGroups:
|
||||
mdl.appendRow([QtGui.QStandardItem(group['icon'] or QtGui.QIcon(), group['text']),
|
||||
QtGui.QStandardItem(str(depth)),
|
||||
QtGui.QStandardItem(group['action'])])
|
||||
addGroups(group['subitems'], depth+1)
|
||||
mdl = QtGui.QStandardItemModel()
|
||||
mdl.appendColumn([])
|
||||
addGroups(filterGroups(self.itemGroups))
|
||||
self.extraInfo.setGeometry(extrax, y, extraw, h)
|
||||
def onSelectionChanged(self, selected, deselected):
|
||||
# The list has .setSelectionMode(QtGui.QAbstractItemView.SingleSelection),
|
||||
# so there is always at most one index in selected.indexes() and at most one
|
||||
# index in deselected.indexes()
|
||||
selected = selected.indexes()
|
||||
deselected = deselected.indexes()
|
||||
if len(selected) > 0:
|
||||
index = selected[0]
|
||||
self.setExtraInfo(index)
|
||||
# Poor attempt to circumvent a glitch where the extra info pane stays visible after pressing Return
|
||||
if not self.listView.isHidden():
|
||||
self.showExtraInfo()
|
||||
elif len(deselected) > 0:
|
||||
self.hideExtraInfo()
|
||||
def setExtraInfo(self, index):
|
||||
toolTipHTML = str(index.model().itemData(index.siblingAtColumn(3))[0])
|
||||
self.extraInfo.setText(toolTipHTML)
|
||||
self.setFloatingWidgetsGeometry()
|
||||
def clearExtraInfo(self, index):
|
||||
self.extraInfo.setText('')
|
||||
def showExtraInfo(self):
|
||||
self.extraInfo.show()
|
||||
|
||||
print('setSourceModel for userInput ' + repr(userInput) + ' with ' + str(mdl.rowCount()) + ' rows.')
|
||||
self.proxyModel.setSourceModel(mdl)
|
||||
#print('TODO: do the actual filtering')
|
||||
#flt = QtCore.QSortFilterProxyModel()
|
||||
#flt.setSourceModel(self.model)
|
||||
#flt.setFilterCaseSensitivity(QtCore.Qt.CaseSensitivity.CaseInsensitive)
|
||||
#flt.setFilterWildcard(query)
|
||||
#self.listView.setModel(flt)
|
||||
# TODO: try to find the already-highlighted item
|
||||
nbRows = self.listView.model().rowCount()
|
||||
if nbRows > 0:
|
||||
index = self.listView.model().index(0, 0)
|
||||
self.listView.setCurrentIndex(index)
|
||||
#self.showList()
|
||||
def showExtraInfo(selected, deselected):
|
||||
print('show extra info...', repr(selected))
|
||||
pass
|
||||
#mdl = QtCore.QStringListModel(['aaa', 'aab', 'aac', 'bxy', 'bac'])
|
||||
#sbx = SearchBox(mdl, 10, None)
|
||||
#sbx.show()
|
||||
|
||||
# Inspired by https://stackoverflow.com/a/7767999/324969
|
||||
#class SearchQCompleter(QtGui.QCompleter):
|
||||
# def __init__(self, model, itemDelegate):
|
||||
# super(SearchQCompleter, self).__init__()
|
||||
# super(SearchQCompleter, self).setModel(QtCore.QIdentityProxyModel())
|
||||
# #https://stackoverflow.com/a/65930408/324969
|
||||
# super(SearchQCompleter, self).popup().setItemDelegate(itemDelegate)
|
||||
# self.setModel(model)
|
||||
#
|
||||
# def setModel(self, itemGroups):
|
||||
# self.itemGroups = itemGroups
|
||||
# self.filterModel('')
|
||||
#
|
||||
# def filterModel(self, userInput):
|
||||
# def matches(s):
|
||||
# return userInput.lower() in s.lower()
|
||||
# def filterGroup(group):
|
||||
# if matches(group['text']):
|
||||
# # If a group matches, include the entire subtree (might need to disable this if it causes too much noise)
|
||||
# return group
|
||||
# else:
|
||||
# subitems = filterGroups(group['subitems'])
|
||||
# if len(subitems) > 0 or matches(group['text']):
|
||||
# return { 'text': group['text'], 'icon': group['icon'], 'action': group['action'], 'subitems': subitems }
|
||||
# else:
|
||||
# return None
|
||||
# def filterGroups(groups):
|
||||
# groups = (filterGroup(group) for group in groups)
|
||||
# return [group for group in groups if group is not None]
|
||||
# def addGroups(filteredGroups, depth=0):
|
||||
# for group in filteredGroups:
|
||||
# mdl.appendRow([QtGui.QStandardItem(group['icon'] or QtGui.QIcon(), group['text']),
|
||||
# QtGui.QStandardItem(str(depth)),
|
||||
# QtGui.QStandardItem(group['action'])])
|
||||
# addGroups(group['subitems'], depth+1)
|
||||
# mdl = QtGui.QStandardItemModel()
|
||||
# mdl.appendColumn([])
|
||||
# addGroups(filterGroups(itemGroups))
|
||||
#
|
||||
# print('setSourceModel for userInput ' + repr(userInput) + ' with ' + str(mdl.rowCount()) + ' rows.')
|
||||
# self.model().setSourceModel(mdl)
|
||||
# # https://stackoverflow.com/a/65930408/324969
|
||||
#
|
||||
# # the splitPath(self, path) method is called every time the input string changes, before
|
||||
# # drawing the completion list, we latch onto this method to also update the model to contain
|
||||
# # the appropriate results, as given by the custom filterAcceptsRow method above.
|
||||
# def splitPath(self, path):
|
||||
# self.filterModel(path)
|
||||
# # Pretend that the user endered the empty string, so that all items from the filteredProxyModel match.
|
||||
# return ''
|
||||
#
|
||||
#class SearchBox(QtGui.QLineEdit):
|
||||
# resultSelected = QtCore.Signal(int, str)
|
||||
# def __init__(self, itemGroups):
|
||||
# super(SearchBox, self).__init__()
|
||||
# qom = SearchQCompleter(itemGroups, IndentedItemDelegate())
|
||||
# qom.setMaxVisibleItems(20)
|
||||
# #qom.setCompletionMode(QtGui.QCompleter.CompletionMode.PopupCompletion)
|
||||
# # Thanks to https://saurabhg.com/programming/search-box-using-qlineedit/ for indicating a few useful options
|
||||
# ico = QtGui.QIcon(':/icons/help-browser.svg')
|
||||
# #ico = QtGui.QIcon(':/icons/WhatsThis.svg')
|
||||
# self.addAction(ico, QtGui.QLineEdit.LeadingPosition)
|
||||
# self.setClearButtonEnabled(True)
|
||||
# self.setPlaceholderText('Search tools, prefs & tree')
|
||||
# self.setFixedWidth(200)
|
||||
# # Signals & slots for enter / click
|
||||
# def completerActivated(index):
|
||||
# print('fooooooooooooo')
|
||||
# print(qom.model().rowCount(), index.row())
|
||||
# # TODO: run the action!
|
||||
# result = str(qom.model().data(index.siblingAtColumn(1)))
|
||||
# print('res='+result)
|
||||
# self.clear()
|
||||
# self.completer().setCompletionPrefix('')
|
||||
# self.resultSelected.emit(str(index), result)
|
||||
# def returnPressed():
|
||||
# #self.clear()
|
||||
# #self.completer().setCompletionPrefix('')
|
||||
# pass
|
||||
# #text = sea.text()
|
||||
# #self.clear()
|
||||
# #self.resultSelected.emit('text returnPressed' + text)
|
||||
# self.returnPressed.connect(returnPressed)
|
||||
# #QtCore.QObject.connect(self.completer(), QtCore.SIGNAL('activated(QModelIndex)'), completerActivated) #, QtCore.Qt.ConnectionType.QueuedConnection)
|
||||
# qom.activated.connect(completerActivated, QtCore.Qt.ConnectionType.DirectConnection) #, QtCore.Qt.ConnectionType.QueuedConnection)
|
||||
# #self.completer().activated.connect(returnPressedOrCompleterActivated)
|
||||
# def textChanged():
|
||||
# print('textChanged')
|
||||
# # Workaround: Clear completion prefix and still show the completion box when doing backspace after typing a single character
|
||||
# if self.text() == '':
|
||||
# self.completer().setCompletionPrefix(self.text())
|
||||
# self.completer().complete()
|
||||
# self.textChanged.connect(textChanged)
|
||||
# QtCore.QObject.connect(qom.popup(), QtCore.SIGNAL('clicked(QModelIndex)'), lambda x: print(x))
|
||||
# self.setCompleter(qom)
|
||||
# def focusInEvent(self, e):
|
||||
# super(SearchBox, self).focusInEvent(e)
|
||||
# self.completer().setCompletionPrefix(self.text())
|
||||
# self.completer().complete()
|
||||
# self.completer().setCurrentRow(1) # Does not work
|
||||
# #d=QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Down, QtCore.Qt.NoModifier)
|
||||
# #QtCore.QCoreApplication.postEvent(self, d)
|
||||
# def mousePressEvent(self, e):
|
||||
# super(SearchBox, self).mousePressEvent(e)
|
||||
# self.completer().setCompletionPrefix(self.text())
|
||||
# self.completer().complete()
|
||||
# self.completer().setCurrentRow(1) # Does not work
|
||||
# #d=QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Down, QtCore.Qt.NoModifier)
|
||||
# #QtCore.QCoreApplication.postEvent(self, d)
|
||||
#
|
||||
mw = Gui.getMainWindow()
|
||||
mdi = mw.findChild(QtGui.QMdiArea)
|
||||
|
||||
|
@ -299,7 +268,8 @@ if True:
|
|||
mwx = QtGui.QMainWindow()
|
||||
mbr = mw.findChildren(QtGui.QToolBar, 'File')[0]
|
||||
|
||||
all_tbs = set()
|
||||
def getAllToolbars():
|
||||
all_tbs = dict()
|
||||
for wbname, workbench in Gui.listWorkbenches().items():
|
||||
try:
|
||||
tbs = workbench.listToolbars()
|
||||
|
@ -307,7 +277,10 @@ if True:
|
|||
continue
|
||||
# careful, tbs contains all the toolbars of the workbench, including shared toolbars
|
||||
for tb in tbs:
|
||||
all_tbs.add(tb)
|
||||
if tb not in all_tbs:
|
||||
all_tbs[tb] = set()
|
||||
all_tbs[tb].add(wbname)
|
||||
return all_tbs
|
||||
|
||||
import json
|
||||
def serializeIcon(icon):
|
||||
|
@ -331,7 +304,8 @@ if True:
|
|||
'workbenches': tool['workbenches'],
|
||||
'toolbar': tool['toolbar'],
|
||||
'text': tool['text'],
|
||||
'icon': serializeIcon(tool['icon'])
|
||||
'icon': serializeIcon(tool['icon']),
|
||||
'toolTipHTML': tool['toolTipHTML']
|
||||
}
|
||||
|
||||
def deserializeIcon(iconPixmaps):
|
||||
|
@ -352,54 +326,43 @@ if True:
|
|||
'workbenches': tool['workbenches'],
|
||||
'toolbar': tool['toolbar'],
|
||||
'text': tool['text'],
|
||||
'icon': deserializeIcon(tool['icon'])
|
||||
'icon': deserializeIcon(tool['icon']),
|
||||
'toolTipHTML': tool['toolTipHTML']
|
||||
}
|
||||
|
||||
#serialized = serializeTools([{'workbenches': ['wb1', 'wb2'], 'toolbar': 'tbr', 'text': 'aa', 'icon': ic}])
|
||||
#serialized = serializeTools([])
|
||||
|
||||
#TODO:save in App.getUserAppDataDir() ################################################################################################################
|
||||
# TODO: save serialized tools in App.getUserAppDataDir() ################################################################################################################
|
||||
# + never cache the document objects
|
||||
|
||||
def GatherTools():
|
||||
itemGroups = []
|
||||
for toolbarName in all_tbs:
|
||||
all_tbs = getAllToolbars()
|
||||
for toolbarName, toolbarIsInWorkbenches in all_tbs.items():
|
||||
toolbarIsInWorkbenches = sorted(list(toolbarIsInWorkbenches))
|
||||
for the_toolbar in mw.findChildren(QtGui.QToolBar, toolbarName):
|
||||
group = []
|
||||
|
||||
for tbt in the_toolbar.findChildren(QtGui.QToolButton):
|
||||
text = tbt.text()
|
||||
act = tbt.defaultAction()
|
||||
if text != '':
|
||||
# TODO: there also is the tooltip
|
||||
icon = tbt.icon()
|
||||
#sim.appendRow([QtGui.QStandardItem(icon, 't:' + text), QtGui.QStandardItem('tool')])
|
||||
men = tbt.menu()
|
||||
subgroup = []
|
||||
if men:
|
||||
subgroup = []
|
||||
for mac in men.actions():
|
||||
if mac.text():
|
||||
#all_actions.append(mac.trigger)
|
||||
action = { 'handler': 'subToolAction', 'workbenches': [], 'toolbar': toolbarName, 'tool': text, 'subtool': mac.text() }
|
||||
#print('whaaaat', str(len(all_actions)))
|
||||
subgroup.append({'icon':mac.icon(), 'text':mac.text(), 'action':json.dumps(action), 'subitems':[]})
|
||||
#all_actions.append(tbt.actions().trigger)
|
||||
#global lalala
|
||||
#lalala=tbt
|
||||
#print('whuuuut', str(len(all_actions)))
|
||||
action = { 'handler': 'toolAction', 'workbenches': [], 'toolbar': toolbarName, 'tool': text }
|
||||
group.append({'icon':icon, 'text':text, 'action': json.dumps(action), 'subitems': subgroup})
|
||||
|
||||
#viu = mw.findChildren(QtGui.QToolBar, 'View')[0]
|
||||
#tbt = viu.findChildren(QtGui.QToolButton)
|
||||
#men = tbt[3].menu()
|
||||
#acs = men.actions() # QtGui.QAction list
|
||||
#act = tbt[2].defaultAction() # QtGui.QAction
|
||||
#act.trigger()
|
||||
action = { 'handler': 'toolbarAction', 'workbenches': [], 'toolbar': toolbarName }
|
||||
action = { 'handler': 'subToolAction', 'workbenches': toolbarIsInWorkbenches, 'toolbar': toolbarName, 'tool': text, 'subTool': mac.text() }
|
||||
subgroup.append({'icon':mac.icon(), 'text':mac.text(), 'toolTipHTML': mac.toolTip(), 'action':json.dumps(action), 'subitems':[]})
|
||||
# The default action of a menu changes dynamically, instead of triggering the last action, just show the menu.
|
||||
action = { 'handler': 'toolAction', 'workbenches': toolbarIsInWorkbenches, 'toolbar': toolbarName, 'tool': text, 'showMenu': bool(men) }
|
||||
group.append({'icon':icon, 'text':text, 'toolTipHTML': tbt.toolTip(), 'action': json.dumps(action), 'subitems': subgroup})
|
||||
# TODO: move the 'workbenches' field to the itemgroup
|
||||
action = { 'handler': 'toolbarAction', 'workbenches': toolbarIsInWorkbenches, 'toolbar': toolbarName }
|
||||
itemGroups.append({
|
||||
'icon': QtGui.QIcon(':/icons/Group.svg'),
|
||||
'text': toolbarName,
|
||||
'toolTipHTML': '<p>Display toolbar ' + toolbarName + '</p><p>This toolbar appears in the following workbenches: <ul>' + ''.join(['<li>' + wb + '</li>' for wb in toolbarIsInWorkbenches]) + '</ul></p>',
|
||||
'action': json.dumps(action),
|
||||
'subitems': group
|
||||
})
|
||||
|
@ -407,21 +370,24 @@ if True:
|
|||
def document(doc):
|
||||
group = []
|
||||
for o in doc.Objects:
|
||||
#all_actions.append(lambda: Gui.Selection.addSelection(o.Document.Name, o.Name))
|
||||
#all_actions.append(lambda: )
|
||||
action = { 'handler': 'documentObjectAction', 'document': o.Document.Name, 'object': o.Name }
|
||||
item = {
|
||||
'icon': o.ViewObject.Icon if o.ViewObject and o.ViewObject.Icon else None,
|
||||
'text': o.Label + ' (' + o.Name + ')',
|
||||
# TODO: preview of the object
|
||||
'toolTipHTML': '<p>' + o.Label + '</p><p><code>App.getDocument(' + repr(o.Document.Name) + ').getObject(' + repr(o.Name) + ')</code></p><p>' + '</p><p><img src="data:image/png;base64,.............."></p>',
|
||||
'action': json.dumps(action),
|
||||
'subitems': []
|
||||
}
|
||||
group.append(item)
|
||||
|
||||
# Todo: this should also select the document in the tree view
|
||||
action = { 'handler': 'documentAction', 'document': o.Document.Name }
|
||||
action = { 'handler': 'documentAction', 'document': doc.Name }
|
||||
itemGroups.append({
|
||||
'icon': QtGui.QIcon(':/icons/Document.svg'),
|
||||
'text': doc.Label + ' (' + doc.Name + ')',
|
||||
# TODO: preview of the document
|
||||
'toolTipHTML': '<p>' + doc.Label + '</p><p><code>App.getDocument(' + repr(doc.Name) + ')</code></p><p><img src="data:image/png;base64,.............."></p>',
|
||||
'action':json.dumps(action),
|
||||
'subitems': group })
|
||||
if App.ActiveDocument:
|
||||
|
@ -435,6 +401,7 @@ if True:
|
|||
return {
|
||||
'icon': serializeIcon(itemGroup['icon']),
|
||||
'text': itemGroup['text'],
|
||||
'toolTipHTML': itemGroup['toolTipHTML'],
|
||||
'action': itemGroup['action'],
|
||||
'subitems': serializeItemGroups(itemGroup['subitems'])
|
||||
}
|
||||
|
@ -443,10 +410,10 @@ if True:
|
|||
def serialize(itemGroups):
|
||||
return json.dumps(serializeItemGroups(itemGroups))
|
||||
def deserializeItemGroup(itemGroup):
|
||||
#print('dIG' + text + " : " + repr(itemGroup['icon'])[:100] + "......................." + repr(itemGroup['icon'])[-100:])
|
||||
return {
|
||||
'icon': deserializeIcon(itemGroup['icon']),
|
||||
'text': itemGroup['text'],
|
||||
'toolTipHTML': itemGroup['toolTipHTML'],
|
||||
'action': itemGroup['action'],
|
||||
'subitems': deserializeItemGroups(itemGroup['subitems'])
|
||||
}
|
||||
|
@ -460,7 +427,10 @@ if True:
|
|||
|
||||
#
|
||||
sea = SearchBox(itemGroups)
|
||||
sea.resultSelected.connect(lambda x, y: print('aaa' + repr(y) + 'end'))
|
||||
def onResultSelected(index, metadata):
|
||||
action = json.loads(metadata)
|
||||
actionHandlers[action['handler']](action)
|
||||
sea.resultSelected.connect(onResultSelected)
|
||||
wax = QtGui.QWidgetAction(None)
|
||||
wax.setDefaultWidget(sea)
|
||||
#mbr.addWidget(sea)
|
||||
|
|
|
@ -191,3 +191,153 @@
|
|||
# return True
|
||||
#filteredProxyModel = FilterProxyModel()
|
||||
#filteredProxyModel.setSourceModel(mdl)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#mdl = QtCore.QStringListModel(['aaa', 'aab', 'aac', 'bxy', 'bac'])
|
||||
#sbx = SearchBox(mdl, 10, None)
|
||||
#sbx.show()
|
||||
|
||||
# Inspired by https://stackoverflow.com/a/7767999/324969
|
||||
#class SearchQCompleter(QtGui.QCompleter):
|
||||
# def __init__(self, model, itemDelegate):
|
||||
# super(SearchQCompleter, self).__init__()
|
||||
# super(SearchQCompleter, self).setModel(QtCore.QIdentityProxyModel())
|
||||
# #https://stackoverflow.com/a/65930408/324969
|
||||
# super(SearchQCompleter, self).popup().setItemDelegate(itemDelegate)
|
||||
# self.setModel(model)
|
||||
#
|
||||
# def setModel(self, itemGroups):
|
||||
# self.itemGroups = itemGroups
|
||||
# self.filterModel('')
|
||||
#
|
||||
# def filterModel(self, userInput):
|
||||
# def matches(s):
|
||||
# return userInput.lower() in s.lower()
|
||||
# def filterGroup(group):
|
||||
# if matches(group['text']):
|
||||
# # If a group matches, include the entire subtree (might need to disable this if it causes too much noise)
|
||||
# return group
|
||||
# else:
|
||||
# subitems = filterGroups(group['subitems'])
|
||||
# if len(subitems) > 0 or matches(group['text']):
|
||||
# return { 'text': group['text'], 'icon': group['icon'], 'action': group['action'], 'subitems': subitems }
|
||||
# else:
|
||||
# return None
|
||||
# def filterGroups(groups):
|
||||
# groups = (filterGroup(group) for group in groups)
|
||||
# return [group for group in groups if group is not None]
|
||||
# def addGroups(filteredGroups, depth=0):
|
||||
# for group in filteredGroups:
|
||||
# mdl.appendRow([QtGui.QStandardItem(group['icon'] or QtGui.QIcon(), group['text']),
|
||||
# QtGui.QStandardItem(str(depth)),
|
||||
# QtGui.QStandardItem(group['action'])])
|
||||
# addGroups(group['subitems'], depth+1)
|
||||
# mdl = QtGui.QStandardItemModel()
|
||||
# mdl.appendColumn([])
|
||||
# addGroups(filterGroups(itemGroups))
|
||||
#
|
||||
# print('setSourceModel for userInput ' + repr(userInput) + ' with ' + str(mdl.rowCount()) + ' rows.')
|
||||
# self.model().setSourceModel(mdl)
|
||||
# # https://stackoverflow.com/a/65930408/324969
|
||||
#
|
||||
# # the splitPath(self, path) method is called every time the input string changes, before
|
||||
# # drawing the completion list, we latch onto this method to also update the model to contain
|
||||
# # the appropriate results, as given by the custom filterAcceptsRow method above.
|
||||
# def splitPath(self, path):
|
||||
# self.filterModel(path)
|
||||
# # Pretend that the user endered the empty string, so that all items from the filteredProxyModel match.
|
||||
# return ''
|
||||
#
|
||||
#class SearchBox(QtGui.QLineEdit):
|
||||
# resultSelected = QtCore.Signal(int, str)
|
||||
# def __init__(self, itemGroups):
|
||||
# super(SearchBox, self).__init__()
|
||||
# qom = SearchQCompleter(itemGroups, IndentedItemDelegate())
|
||||
# qom.setMaxVisibleItems(20)
|
||||
# #qom.setCompletionMode(QtGui.QCompleter.CompletionMode.PopupCompletion)
|
||||
# # Thanks to https://saurabhg.com/programming/search-box-using-qlineedit/ for indicating a few useful options
|
||||
# ico = QtGui.QIcon(':/icons/help-browser.svg')
|
||||
# #ico = QtGui.QIcon(':/icons/WhatsThis.svg')
|
||||
# self.addAction(ico, QtGui.QLineEdit.LeadingPosition)
|
||||
# self.setClearButtonEnabled(True)
|
||||
# self.setPlaceholderText('Search tools, prefs & tree')
|
||||
# self.setFixedWidth(200)
|
||||
# # Signals & slots for enter / click
|
||||
# def completerActivated(index):
|
||||
# print('fooooooooooooo')
|
||||
# print(qom.model().rowCount(), index.row())
|
||||
# # TODO: run the action!
|
||||
# result = str(qom.model().data(index.siblingAtColumn(1)))
|
||||
# print('res='+result)
|
||||
# self.clear()
|
||||
# self.completer().setCompletionPrefix('')
|
||||
# self.resultSelected.emit(str(index), result)
|
||||
# def returnPressed():
|
||||
# #self.clear()
|
||||
# #self.completer().setCompletionPrefix('')
|
||||
# pass
|
||||
# #text = sea.text()
|
||||
# #self.clear()
|
||||
# #self.resultSelected.emit('text returnPressed' + text)
|
||||
# self.returnPressed.connect(returnPressed)
|
||||
# #QtCore.QObject.connect(self.completer(), QtCore.SIGNAL('activated(QModelIndex)'), completerActivated) #, QtCore.Qt.ConnectionType.QueuedConnection)
|
||||
# qom.activated.connect(completerActivated, QtCore.Qt.ConnectionType.DirectConnection) #, QtCore.Qt.ConnectionType.QueuedConnection)
|
||||
# #self.completer().activated.connect(returnPressedOrCompleterActivated)
|
||||
# def textChanged():
|
||||
# print('textChanged')
|
||||
# # Workaround: Clear completion prefix and still show the completion box when doing backspace after typing a single character
|
||||
# if self.text() == '':
|
||||
# self.completer().setCompletionPrefix(self.text())
|
||||
# self.completer().complete()
|
||||
# self.textChanged.connect(textChanged)
|
||||
# QtCore.QObject.connect(qom.popup(), QtCore.SIGNAL('clicked(QModelIndex)'), lambda x: print(x))
|
||||
# self.setCompleter(qom)
|
||||
# def focusInEvent(self, e):
|
||||
# super(SearchBox, self).focusInEvent(e)
|
||||
# self.completer().setCompletionPrefix(self.text())
|
||||
# self.completer().complete()
|
||||
# self.completer().setCurrentRow(1) # Does not work
|
||||
# #d=QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Down, QtCore.Qt.NoModifier)
|
||||
# #QtCore.QCoreApplication.postEvent(self, d)
|
||||
# def mousePressEvent(self, e):
|
||||
# super(SearchBox, self).mousePressEvent(e)
|
||||
# self.completer().setCompletionPrefix(self.text())
|
||||
# self.completer().complete()
|
||||
# self.completer().setCurrentRow(1) # Does not work
|
||||
# #d=QtGui.QKeyEvent(QtCore.QEvent.KeyPress, QtCore.Qt.Key_Down, QtCore.Qt.NoModifier)
|
||||
# #QtCore.QCoreApplication.postEvent(self, d)
|
||||
#
|
||||
|
||||
#sim.appendRow([QtGui.QStandardItem(icon, 't:' + text), QtGui.QStandardItem('tool')])
|
||||
|
||||
#all_actions.append(mac.trigger)
|
||||
|
||||
#print('whaaaat', str(len(all_actions)))
|
||||
|
||||
#all_actions.append(tbt.actions().trigger)
|
||||
#global lalala
|
||||
#lalala=tbt
|
||||
#print('whuuuut', str(len(all_actions)))
|
||||
|
||||
#viu = mw.findChildren(QtGui.QToolBar, 'View')[0]
|
||||
#tbt = viu.findChildren(QtGui.QToolButton)
|
||||
#men = tbt[3].menu()
|
||||
#acs = men.actions() # QtGui.QAction list
|
||||
#act = tbt[2].defaultAction() # QtGui.QAction
|
||||
#act.trigger()
|
||||
|
|
Loading…
Reference in New Issue
Block a user