Edit on GitHub

starplast.help_search

The search field beside the Help menu, and the exact place each result takes you.

spaCR has a box directly to the right of its Help menu that searches everything the program can do; this is Starplast's, built the same way so the two tools work alike. Type, and a list drops down of menu commands, panels and tabs, strategies, settings, information slots, datasets and pages of the guide (starplast.help_index decides what is in it and how it is ranked). Down and Return, or a click, go to the thing itself:

action the menu command is carried out; a submenu is opened where it lives in the menu bar panel the dock is shown and raised, on the named tab; Preferences, a guided workflow or the slot tree is opened on the right page setting the panel or Preferences tab holding the control is opened, the control scrolled into view, focused and outlined for a moment; a display choice is applied strategy the Strategies tab is raised with that strategy selected and its card showing slot the slot tree opens on the slot's organism with the slot selected dataset a card with what the dataset provides, its coverage, citation and source link doc the page, from this checkout when there is one, scrolled to the heading tutorial the tutorial page in the browser, at the section

A CHILD OF THE WINDOW, NOT A POPUP WINDOW, for spaCR's reason: a Qt.Popup grabs the keyboard the moment it appears, so the next letter typed would go to the list instead of the box. As a child, the caret stays in the box, and the list is a glass pane drawn inside the window -- translucent on any display, compositor or not. Ctrl+Shift+H puts the caret in the box, spaCR's key for the same field.

The index is built the first time something is typed, not when the window opens: reading every registry costs a fraction of a second nobody should pay for a window they only wanted to look at.

FIELD_NAME = 'HelpSearchField'
LIST_NAME = 'HelpSearchResultList'
NOTE_NAME = 'HelpSearchNote'
SHORTCUT = 'Ctrl+Shift+H'
DEBOUNCE_MS = 120
RESULT_LIMIT = 24
ENTRY_ROLE = 257
HIGHLIGHT_MS = 1600
def open_action(window, e) -> str:

Carry out a menu command, or open a submenu where it sits in the menu bar.

def open_panel(window, e) -> str:

Show a dock on the named tab, or open Preferences, a workflow or the slot tree.

def highlight(widget: PyQt6.QtWidgets.QWidget, ms: int = 1600) -> None:

Outline a control for a moment, so the eye lands on what the search found.

def reveal(widget: PyQt6.QtWidgets.QWidget) -> None:

Scroll every scroll area holding widget until it is in view, focus it, and outline it.

def open_setting(window, e) -> str:

Land on the control that holds a setting, or apply a display choice.

def open_strategy(window, e) -> str:

Raise the Strategies tab with the strategy selected and its card showing; its Guide is the first tab behind Details.

def open_slot(window, e) -> str:

Open the slot tree on the slot's organism, with the slot selected and scrolled to.

def dataset_card(window, key: str) -> PyQt6.QtWidgets.QDialog:

A glass card saying what one dataset is: provides, coverage, citation, columns, source.

def open_dataset(window, e) -> str:

Show the dataset's card.

class DocViewer(PyQt6.QtWidgets.QDialog):

A page of the guide, read from this checkout and scrolled to one heading.

Local rather than the browser: it works offline, it is the version that matches the code running, and it can land on the heading itself. The published page is one button away.

DocViewer(path: str, heading: str, url: str, parent=None)
view
def heading_block(self):

The text block holding the heading, or an invalid block when it is not on the page.

def scroll_to_heading(self) -> bool:

Put the heading at the top of the view. True when the heading was found.

def open_doc(window, e) -> str:

The guide page at the heading: from this checkout when present, else the published page.

def open_tutorial(window, e) -> str:

The tutorial page in the browser, at its section.

OPENERS = {'action': <function open_action>, 'panel': <function open_panel>, 'setting': <function open_setting>, 'strategy': <function open_strategy>, 'slot': <function open_slot>, 'dataset': <function open_dataset>, 'doc': <function open_doc>, 'tutorial': <function open_tutorial>}
def open_entry(window, e) -> str:

Take the user to e; returns what the status bar says about it.

class HelpSearchField(PyQt6.QtWidgets.QLineEdit):

The box beside the Help menu: it owns the result list, the index and the keyboard.

Up, Down, Page Up and Page Down steer the list while the caret stays in the box; Return opens the highlighted row; Escape closes the list, and a second Escape gives the window its focus back.

HelpSearchField(window: PyQt6.QtWidgets.QMainWindow, parent=None)
def opened(unknown):

pyqtSignal(*types, name: str = ..., revision: int = ..., arguments: Sequence = ...) -> PYQT_SIGNAL

types is normally a sequence of individual types. Each type is either a type object or a string that is the name of a C++ type. Alternatively each type could itself be a sequence of types each describing a different overloaded signal. name is the optional C++ name of the signal. If it is not specified then the name of the class attribute that is bound to the signal is used. revision is the optional revision of the signal that is exported to QML. If it is not specified then 0 is used. arguments is the optional sequence of the names of the signal's arguments.

def index(self) -> list:

The index, built on first use.

def set_index(self, entries) -> None:

Use entries instead of building an index, and search again.

def invalidate(self) -> None:

Forget the index, so the next search reads the window again (after menus change).

def results(self) -> list:

What the list is showing, best first.

def popup(self) -> PyQt6.QtWidgets.QFrame:

The result pane, so a caller can ask whether it is up.

def note(self) -> str:

The line above the list, shown when nothing matched.

def refresh(self) -> None:

Search for whatever is in the box and show the list.

def place_popup(self) -> None:

Size the pane to its rows and hang it under the box, inside the window.

def hide_popup(self) -> None:

Put the list away.

def activate_current(self) -> None:

Open whatever row is highlighted.

def keyPressEvent(self, event: PyQt6.QtGui.QKeyEvent) -> None:

Steer the list from the box, and let Escape give the window back.

def focusOutEvent(self, event) -> None:

Close the list when the caret leaves the box; the list never takes focus itself.

def field_of(window) -> HelpSearchField | None:

The field installed on window, if there is one.

def install( window: PyQt6.QtWidgets.QMainWindow) -> HelpSearchField:

Put the search field directly to the right of the Help menu. Idempotent.

def focus_field(window) -> bool:

Put the caret in the search box and select what is in it. True when there was a box.