Skip to content

Keyboard shortcuts#134

Open
osn07 wants to merge 11 commits into
toolsforexperiments:masterfrom
osn07:keyboard-shortcuts
Open

Keyboard shortcuts#134
osn07 wants to merge 11 commits into
toolsforexperiments:masterfrom
osn07:keyboard-shortcuts

Conversation

@osn07
Copy link
Copy Markdown
Contributor

@osn07 osn07 commented May 7, 2026

Adds customizable keyboard shortcuts that a user can execute to streamline instrumentserver workflow

osn07 added 4 commits May 4, 2026 22:57
…es a user's individual shortcut preferences. ShortcutEditorDialog handles UI interactions and updates a KSM class instance accordingly. base_instrument.py was updated to implement these new classes and add a button to edit keyboard shortcuts.
…to Station or Log. alert column on right side indicates three states: ok (white), unsaved (orange), and duplicate (red). alert displays tooltip for each tooltip. ServerGui now holds a shortcut editor and shortcut manager, which is passed to an instrument tab when opened.
@osn07 osn07 force-pushed the keyboard-shortcuts branch from 2525bff to c64a489 Compare May 7, 2026 04:03
Comment thread src/instrumentserver/gui/base_instrument.py Outdated

@staticmethod
def _matches_any_pattern(name: str, patterns: List[str]) -> bool:
def _matches_any_pattern(name: str, patterns: Optional[List[str]]) -> bool:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why add the Optional but not a None argument? is this really optional?


# Indicates if a column is using delegates.
self.delegateColumns = delegateColumns
self.delegateColumns: List[int] = delegateColumns or []
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does changing the default change the behaviour downstream?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default set in the param list is None. the variable is used later in for loops, but if it is None, will this not raise an error? if it is empty, the loop will just exit immediately

Comment thread src/instrumentserver/gui/base_instrument.py
when Save is clicked. Use 'Save to file' / 'Load from file' to persist across sessions.

Each row has a small colored indicator dot in the rightmost column:
- white : saved and unique
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't been able to make it white even when saved

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it transparent? it just looks normal to me

Comment thread src/instrumentserver/server/application.py Outdated
else QtCore.Qt.SortOrder.DescendingOrder
)
header.setSortIndicator(col, new_order)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need all these new slots?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the first three and refactored the code accordingly. As for the final four, they act as thin wrappers. They need to resolve what the currently selected item is to execute, something the right-click (for trash/star item) implicitly does

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was the refactor needed though?

@marcosfrenkel
Copy link
Copy Markdown
Collaborator

On top of the specific coding things 2 things are left on this:

  • Make sure we can fully navigate the interface with arrow keys; being able to press the right arrow key and edit the value of a parameter directly.
  • Make the config aspect of the shortcuts be in the config of the server itself instead of having its own dedicated file

@marcosfrenkel
Copy link
Copy Markdown
Collaborator

A few things that should probably become issues:

  • when hovering over buttons, there should be the hotkey in parenthesis.
  • the shortcuts seem to be applying to the functions/parameters sections inconsistently

modelKwargs["sub_port"] = kwargs.pop("sub_port")

shortcutManager = kwargs.pop("shortcutManager", None)
print(shortcutManager)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove print statement

Comment on lines +241 to 243
if not patterns:
return False
for pattern in patterns:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patterns is a list of strings, how is not [] different than iterating over []?

Comment on lines 911 to +935
@QtCore.Slot()
def promoteStar(self) -> None:
self.proxyModel.onToggleStar()
def _starCurrentItem(self) -> None:
proxy_index = self.view.currentIndex()
if not proxy_index.isValid():
return
source_index = self.proxyModel.mapToSource(proxy_index)
if source_index.column() != 0:
source_index = source_index.sibling(source_index.row(), 0)
item = self.model.itemFromIndex(source_index)
if isinstance(item, ItemBase):
self.view.lastSelectedItem = item
self.view.itemStarToggle.emit(item)

@QtCore.Slot()
def refreshAll(self) -> None:
self.model.refreshAll()
def _trashCurrentItem(self) -> None:
proxy_index = self.view.currentIndex()
if not proxy_index.isValid():
return
source_index = self.proxyModel.mapToSource(proxy_index)
if source_index.column() != 0:
source_index = source_index.sibling(source_index.row(), 0)
item = self.model.itemFromIndex(source_index)
if isinstance(item, ItemBase):
self.view.lastSelectedItem = item
self.view.itemTrashToggle.emit(item)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these 2 functions, instead of being the same one with a flag for star/trash? all the code is exactly the same except the last line

else QtCore.Qt.SortOrder.DescendingOrder
)
header.setSortIndicator(col, new_order)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was the refactor needed though?


from instrumentserver import QtCore, QtGui, QtWidgets, getInstrumentserverPath

_ICON_DIR = getInstrumentserverPath("resource", "icons")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Load icons the same way we do in the rest of the project:

self.starIcon = QtGui.QIcon(":/icons/star.svg")

when Save is clicked. Use 'Save to file' / 'Load from file' to persist across sessions.

Each row has a small colored indicator dot in the rightmost column:
- white : saved and unique
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it transparent? it just looks normal to me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants