Skip to content

redsun.qt

Session

QtSession

QtSession(
    config: Source | Sequence[Source] | None = None,
    *,
    log_level: int | str | None = None,
    profile: ProfileKind | None = None,
    profile_dir: str | Path | None = None,
)

Bases: DesktopSession[QMainWindow], Session

Application container whose views are attached to a Qt main window.

Subclass this rather than redsun.Session to build against Qt: it accepts the placements Qt attaches and refuses the rest when the declarations are read. Importing it needs the Qt bindings.

The base container builds the components; this one puts them in a window. Constructing the container touches no toolkit object and reads no file: the application, the async backend and the window are all made by build.

class MyApp(QtSession):
    image: AsView[ImageView]


MyApp().run()

Prepare an empty container, to be filled by build.

The keywords are those of Session.

main_window property

main_window: QModelMainWindow

The window the views are attached to.

It is built against model, so a menu bar or a toolbar filled from that application's registries can be asked for on it.

Raises:

Type Description
RuntimeError

If read before build, which is where it is created.

view_arguments property

view_arguments: Mapping[str, object]

The main window, as every view's parent.

app property

app: QApplication

The toolkit application this session runs on, and keeps alive.

The session keeps a reference to one it created until it is released.

Raises:

Type Description
RuntimeError

If read before build, which is where it is put in place.

model property

model: Application

The application this session's commands and menus are registered on.

Raises:

Type Description
RuntimeError

If read before build, which is where it is created.

start_runtime

start_runtime() -> None

Put the toolkit in place, before the first component is built.

A QApplication has to exist before any widget is constructed, so it is made here. The hooks were resolved by the step before this one, so one may supply the QApplication itself. The session's own application follows, because the components are built out of its store, and the actions section is registered on it at once, so a hook dressing the window finds every command it may put in a menu. The window comes next, since every view is built as its child. The colour scheme is asked for before any widget exists to be painted in the wrong one, and a configure_application hook runs last, so one restyling the application does so over a scheme already in force. Each of them registers how it is given back as it is taken, so shutdown frees the name without this class defining one.

Raises:

Type Description
HookError

If a create_application hook returns anything but a QApplication.

build_views

build_views() -> None

Build the views as children of the main window.

A view that fails after handing itself to the window as a child would be shown with it, so what it left behind is deleted.

present

present() -> None

Put every view where it asks to be in the window, and ready the window to show.

A view that failed to build and asked for a dock or the centre is replaced there by a widget naming it and the reason. When any component failed to build or to be set up, a button in the status bar counts them and lists them with their tracebacks.

restore_layout

restore_layout() -> None

Put the window back where this user last left it.

Runs once every dock exists, since Qt places a dock by object name and ignores one it has not seen. A session this user has never run finds nothing saved and keeps the layout its views asked for. Each dock the saved layout keeps away from the edge its placement asks for is logged.

save_layout

save_layout() -> None

Remember where this user left the window.

run asks for this as the session ends, so a window that was shown is the only one that writes.

make_store

make_store() -> Store

Return the application's store, which is the session's too.

Sharing it is what lets a command registered on the application be filled from the components this session built.

open_span

open_span() -> AbstractContextManager[
    Callable[[str], None]
]

Open the span a QtHook.DURING_BUILD hook wraps the build in.

Without one, reporting stays where it was and nothing brackets the build. The runtime step has run by now, so the QApplication a hook is handed exists.

run

run() -> NoReturn

Build, show the window, and hand over to the event loop.

An exception no slot caught is logged with its traceback, and the window carries on.

Qt

Bases: Frontend

Qt frontend, attached by redsun.qt.attach.

check_view classmethod

check_view(view: type, where: str) -> None

Refuse a view whose constructor does not start (name: str, parent: QWidget.

The session passes both by keyword, so neither may sit after a /, and neither may sit after a *, so a missing parent shows in the first line of the signature.

Raises:

Type Description
TypeError

If the constructor starts any other way.

read_placement classmethod

read_placement(value: object) -> Placement

Return the Qt placement a session file's value names.

left, right, top or bottom is a dock against that edge and central the main area; {dock: <edge>, group: <name>} a dock tabbed with its group, {menu: <name>} an entry in that menu and {toolbar: <name>} an entry in that toolbar.

Raises:

Type Description
ValueError

If value is none of these.

thread_of classmethod

thread_of(consumer: object) -> SlotThread

Run a widget's slots on the main thread, the only one it may be used from.

QtHook

Bases: StrEnum

The points a Qt session calls a hook at.

A member is its own string, so the attribute name declaring a hook, the key of a hooks configuration entry and a member here are the same thing said three ways.

CREATE_APPLICATION class-attribute instance-attribute

CREATE_APPLICATION = 'create_application'

Makes the QApplication from the command-line arguments, when none exists yet.

CONFIGURE_APPLICATION class-attribute instance-attribute

CONFIGURE_APPLICATION = 'configure_application'

Receives the QApplication before any view is made.

DURING_BUILD class-attribute instance-attribute

DURING_BUILD = 'during_build'

Receives the QApplication and wraps the build steps.

CONFIGURE_MAIN_VIEW class-attribute instance-attribute

CONFIGURE_MAIN_VIEW = 'configure_main_view'

Receives the main window once it is made, before it is shown.

CONFIRM_CLOSE class-attribute instance-attribute

CONFIRM_CLOSE = 'confirm_close'

Answers whether the window may close.

Placements

Dock dataclass

Dock(area: Area, group: str | None = None)

Bases: Placement

A panel against one edge of the window, tabbed with the docks of its group.

Raises:

Type Description
ValueError

If area names no edge of the window.

area instance-attribute

area: Area

Edge the panel sits against.

group class-attribute instance-attribute

group: str | None = None

Name of the docks it is tabbed with on the same edge; None for none.

Area module-attribute

Area: TypeAlias = Literal['left', 'right', 'top', 'bottom']

Central dataclass

Central()

Bases: Placement

The main area of the window, shared when more than one view asks.

MenuItem dataclass

MenuItem(menu: str)

Bases: Placement

An entry in a named menu of the menu bar.

menu instance-attribute

menu: str

Name of the menu.

ToolBarItem dataclass

ToolBarItem(toolbar: str)

Bases: Placement

An entry in a named toolbar.

toolbar instance-attribute

toolbar: str

Name of the toolbar.

attach

attach(
    window: QMainWindow,
    views: Mapping[str, AttachableComponent],
    placements: Mapping[str, Placement] | None = None,
) -> None

Attach every view of views to window where it asks to be.

placements gives, by name, the placement a view's declaration chose; any other view is placed where its placement asks. Docks of one edge and group are tabbed together, in the order of views.

Raises:

Type Description
TypeError

If a view asks for a placement Qt does not attach, or is not the toolkit type that placement demands.

Colour scheme

ColorSchemeMode

Bases: StrEnum

What a session asks the platform for, in the order the control cycles.

SYSTEM asks for nothing, which is Qt's unset state rather than a scheme of its own: the platform keeps deciding, and a user changing their own setting is followed.

SYSTEM class-attribute instance-attribute

SYSTEM = 'system'

The platform decides.

LIGHT class-attribute instance-attribute

LIGHT = 'light'

The light scheme.

DARK class-attribute instance-attribute

DARK = 'dark'

The dark scheme.

glyph property

glyph: str

The character the control shows while this mode is asked for.

from_config classmethod

from_config(declared: str | None) -> Self

Return the mode the color_scheme key names, or SYSTEM for None.

Raises:

Type Description
ValueError

If the key names no mode the control offers.

apply

apply() -> None

Ask the platform for this scheme, or stop asking under SYSTEM.

Raises:

Type Description
RuntimeError

If no application exists yet to carry a colour scheme.

next

next() -> ColorSchemeMode

Return the mode after this one, wrapping past the last.

ColorSchemeButton

ColorSchemeButton(
    mode: ColorSchemeMode = ColorSchemeMode.SYSTEM,
    parent: QWidget | None = None,
)

Bases: QToolButton

Cycles the colour scheme, system to light to dark and back.

The glyph is the mode asked for rather than the scheme in force, so it stays right while system follows a user changing their own setting.

Show mode, without applying it: the session already did.

TOOLBAR class-attribute

TOOLBAR: str = 'redsun.color-scheme'

Object name of the toolbar pin_to puts the control in.

mode property

mode: ColorSchemeMode

The mode asked for, which the glyph shows.

pin_to classmethod

pin_to(window: QMainWindow, mode: ColorSchemeMode) -> Self

Return a control at the right of a toolbar of its own on window.

An expanding spacer takes the width before it, which is what pins the control to the right edge; nothing else goes in this toolbar, so a view asking for a toolbar keeps its own.

Raises:

Type Description
RuntimeError

If window refuses a toolbar.

cycle

cycle() -> None

Move to the next mode and ask the platform for it.

Actions

ActionError

Bases: RuntimeError

An actions configuration entry cannot be turned into an action.

SAVE_MENU module-attribute

SAVE_MENU: Final[str] = 'redsun/file'

The menu a session's own actions join, which a window may show by name.

ASK_ON_CLOSE module-attribute

ASK_ON_CLOSE: Final[str] = 'ask_on_close'

The settings key holding whether the close prompt still appears.