From 26019aa60b3ea6aafd09c257226493d2e5a38d36 Mon Sep 17 00:00:00 2001 From: Suzanne Soy Date: Wed, 6 Oct 2021 01:51:34 +0100 Subject: [PATCH] Fixed shortcuts, used proper Qt shortcuts, circumvented a bug in Qt shortcuts where home & end do not work by reverting some of the old code --- InitGui.py | 5 ++- SearchBox.py | 106 ++++++++++++++++++++++++++++++---------------- SearchBoxLight.py | 24 ++++++----- TODO.py | 6 +-- 4 files changed, 90 insertions(+), 51 deletions(-) diff --git a/InitGui.py b/InitGui.py index be0bcb3..32ed7e7 100644 --- a/InitGui.py +++ b/InitGui.py @@ -15,10 +15,11 @@ def addToolSearchBox(): mbr = mbr[0] # Create search box widget sea = SearchBoxLight.SearchBoxLight(getItemGroups = lambda: __import__('GetItemGroups').getItemGroups(), - getToolTip = lambda groupId, setParent: __import__('GetItemGroups').getToolTip(groupId, setParent), - getItemDelegate = lambda: __import__('IndentedItemDelegate').IndentedItemDelegate()) + getToolTip = lambda groupId, setParent: __import__('GetItemGroups').getToolTip(groupId, setParent), + getItemDelegate = lambda: __import__('IndentedItemDelegate').IndentedItemDelegate()) sea.resultSelected.connect(lambda index, groupId: __import__('GetItemGroups').onResultSelected(index, groupId)) wax = QtGui.QWidgetAction(None) + wax.setWhatsThis('Use this search bar to find tools, document objects, preferences and more') wax.setDefaultWidget(sea) #mbr.addWidget(sea) mbr.addAction(wax) diff --git a/SearchBox.py b/SearchBox.py index 2a20aa4..b7ffa5d 100644 --- a/SearchBox.py +++ b/SearchBox.py @@ -76,6 +76,24 @@ class SearchBox(QtGui.QLineEdit): # Connect signals and slots self.listView.clicked.connect(lambda x: self.selectResult('select', x)) self.listView.selectionModel().selectionChanged.connect(self.onSelectionChanged) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Down), self).activated.connect(self.listDown) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Up), self).activated.connect(self.listUp) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_PageDown), self).activated.connect(self.listPageDown) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_PageUp), self).activated.connect(self.listPageUp) + + # Home and End do not work, for some reason. + #QtGui.QShortcut(QtGui.QKeySequence.MoveToEndOfDocument, self).activated.connect(self.listEnd) + #QtGui.QShortcut(QtGui.QKeySequence.MoveToStartOfDocument, self).activated.connect(self.listStart) + #QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_End), self).activated.connect(self.listEnd) + #QtGui.QShortcut(QtGui.QKeySequence('Home'), self).activated.connect(self.listStart) + + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Enter), self).activated.connect(self.listAccept) + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), self).activated.connect(self.listAccept) + QtGui.QShortcut(QtGui.QKeySequence('Ctrl+Return'), self).activated.connect(self.listAcceptToggle) + QtGui.QShortcut(QtGui.QKeySequence('Ctrl+Enter'), self).activated.connect(self.listAcceptToggle) + QtGui.QShortcut(QtGui.QKeySequence('Ctrl+Space'), self).activated.connect(self.listAcceptToggle) + + QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self).activated.connect(self.listCancel) # Initialize the model with the full list (assuming the text() is empty) #self.proxyFilterModel(self.text()) # This is done by refreshItemGroups on focusInEvent, because the initial loading from cache can take time self.firstShowList = True @@ -111,46 +129,62 @@ class SearchBox(QtGui.QLineEdit): self.hideList() super(SearchBoxLight, self).focusOutEvent(qFocusEvent) + @staticmethod + def movementKey(self, rowUpdate): + currentIndex = self.listView.currentIndex() + self.showList() + if self.listView.isEnabled(): + currentRow = currentIndex.row() + nbRows = self.listView.model().rowCount() + if nbRows > 0: + newRow = rowUpdate(currentRow, nbRows) + index = self.listView.model().index(newRow, 0) + self.listView.setCurrentIndex(index) + + @staticmethod + def proxyListDown(self): self.movementKey(lambda current, nbRows: (current + 1) % nbRows) + @staticmethod + def proxyListUp(self): self.movementKey(lambda current, nbRows: (current - 1) % nbRows) + @staticmethod + def proxyListPageDown(self): self.movementKey(lambda current, nbRows: min(current + max(1, self.maxVisibleRows / 2), nbRows - 1)) + @staticmethod + def proxyListPageUp(self): self.movementKey(lambda current, nbRows: max(current - max(1, self.maxVisibleRows / 2), 0)) + @staticmethod + def proxyListEnd(self): self.movementKey(lambda current, nbRows: nbRows - 1) + @staticmethod + def proxyListStart(self): self.movementKey(lambda current, nbRows: 0) + + @staticmethod + def acceptKey(self, mode): + currentIndex = self.listView.currentIndex() + self.showList() + if currentIndex.isValid(): + self.selectResult(mode, currentIndex) + + @staticmethod + def proxyListAccept(self): self.acceptKey('select') + @staticmethod + def proxyListAcceptToggle(self): self.acceptKey('toggle') + + @staticmethod + def cancelKey(self): + self.hideList() + self.clearFocus() + + # QKeySequence::Cancel + @staticmethod + def proxyListCancel(self): self.cancelKey() + @staticmethod def proxyKeyPressEvent(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: min(current + max(1, self.maxVisibleRows / 2), nbRows - 1), - QtCore.Qt.Key_PageUp: lambda current, nbRows: max(current - max(1, self.maxVisibleRows / 2), 0), - QtCore.Qt.Key_Home: lambda current, nbRows: 0, - QtCore.Qt.Key_End: lambda current, nbRows: nbRows - 1, - } - acceptKeys = { - QtCore.Qt.Key_Enter: 'select', - QtCore.Qt.Key_Return: 'select', - # space on a toolbar/category should toggle the entire category in the search results - QtCore.Qt.Key_Space: 'toggle', - } - cancelKeys = { - QtCore.Qt.Key_Escape: True, - } - - currentIndex = self.listView.currentIndex() - if key in listMovementKeys: - self.showList() - if self.listView.isEnabled(): - currentRow = currentIndex.row() - nbRows = self.listView.model().rowCount() - if nbRows > 0: - newRow = listMovementKeys[key](currentRow, nbRows) - index = self.listView.model().index(newRow, 0) - self.listView.setCurrentIndex(index) - elif key in acceptKeys: - self.showList() - if currentIndex.isValid(): - self.selectResult(acceptKeys[key], currentIndex) - elif key in cancelKeys: - self.hideList() - self.clearFocus() + modifiers = qKeyEvent.modifiers() + self.showList() + if key == QtCore.Qt.Key_Home and modifiers & QtCore.Qt.CTRL != 0: + self.listStart() + elif key == QtCore.Qt.Key_End and modifiers & QtCore.Qt.CTRL != 0: + self.listEnd() else: - self.showList() super(SearchBoxLight, self).keyPressEvent(qKeyEvent) @staticmethod diff --git a/SearchBoxLight.py b/SearchBoxLight.py index edab237..3df035b 100644 --- a/SearchBoxLight.py +++ b/SearchBoxLight.py @@ -34,13 +34,17 @@ class SearchBoxLight(QtGui.QLineEdit): SearchBox.SearchBox.lazyInit(self) return getattr(SearchBox.SearchBox, name)(*args, **kwargs) return types.MethodType(f, self) - def focusInEvent(self, *args, **kwargs): - self.proxyFocusInEvent(*args, **kwargs) - def focusOutEvent(self, *args, **kwargs): - self.proxyFocusOutEvent(*args, **kwargs) - def keyPressEvent(self, *args, **kwargs): - self.proxyKeyPressEvent(*args, **kwargs) - def onSelectionChanged(self, *args, **kwargs): - self.proxyOnSelectionChanged(*args, **kwargs) - def filterModel(self, *args, **kwargs): - self.proxyFilterModel(*args, **kwargs) + def focusInEvent(self, *args, **kwargs): return self.proxyFocusInEvent(*args, **kwargs) + def focusOutEvent(self, *args, **kwargs): return self.proxyFocusOutEvent(*args, **kwargs) + def keyPressEvent(self, *args, **kwargs): return self.proxyKeyPressEvent(*args, **kwargs) + def onSelectionChanged(self, *args, **kwargs): return self.proxyOnSelectionChanged(*args, **kwargs) + def filterModel(self, *args, **kwargs): return self.proxyFilterModel(*args, **kwargs) + def listDown(self, *args, **kwargs): return self.proxyListDown(*args, **kwargs) + def listUp(self, *args, **kwargs): return self.proxyListUp(*args, **kwargs) + def listPageDown(self, *args, **kwargs): return self.proxyListPageDown(*args, **kwargs) + def listPageUp(self, *args, **kwargs): return self.proxyListPageUp(*args, **kwargs) + def listEnd(self, *args, **kwargs): return self.proxyListEnd(*args, **kwargs) + def listStart(self, *args, **kwargs): return self.proxyListStart(*args, **kwargs) + def listAccept(self, *args, **kwargs): return self.proxyListAccept(*args, **kwargs) + def listAcceptToggle(self, *args, **kwargs): return self.proxyListAcceptToggle(*args, **kwargs) + def listCancel(self, *args, **kwargs): return self.proxyListCancel(*args, **kwargs) diff --git a/TODO.py b/TODO.py index 68ffcf1..9ab37c2 100644 --- a/TODO.py +++ b/TODO.py @@ -18,8 +18,8 @@ OK turn this into a standalone mod OK Optimize so that it's not so slow OK speed up startup to show the box instantly and do the slow loading on first click. OK One small bug: when the 3D view is initialized, it causes a loss of focus on the drop-down. We restore it, but the currently-selected index is left unchanged, so the down or up arrow has to be pressed twice. -* split into several files, try to keep the absolute minimum of code possible in the main file to speed up startup +OK split into several files, try to keep the absolute minimum of code possible in the main file to speed up startup OK segfault when reloading -* Disable the spacebar shortcut (can't type space in the search field…) -* Possibly disable the home and end, and use ctrl+home and ctrl+end instead? +OK Disable the spacebar shortcut (can't type space in the search field…) +OK Possibly disable the home and end, and use ctrl+home and ctrl+end instead? """ \ No newline at end of file