composeui.core.view

The views: typed attrs classes that describe the UI, without a backend.

A renderer shows each view on a backend (see composeui.core.registry). Setting a field of a view pushes the change to its renderer. The widget catalog lists the views.

composeui.core.view.CHECKED_TEXTS: Mapping[bool, str] = {False: 'False', True: 'True'}

a check box cell’s text, by whether it’s checked, as str writes a boolean

composeui.core.view.GRID_POSITION = 'grid_position'

Field metadata key for a view field of a GridView: its cell, a GridPosition (or a tuple of its values)

composeui.core.view.OMIT = 'omit'

Field metadata key for fields that must skip (de)serialization but aren’t one of _OMITTED_TYPES - e.g. Validator fields, whose type (bare/Optional/list- wrapped Callable) isn’t a single class _is_omitted_type can match generically.

composeui.core.view.SEARCH_DELAY_MS = 300

the milliseconds a table’s filter bar waits after the last key typed in its search before it searches: one search for a word, not one per letter (Enter searches at once)

composeui.core.view.SOURCE_TABLE_JOB_ROWS = 100000

the rows from which a SourceTableView orders its source’s in a job, on Qt and Textual

composeui.core.view.STRETCH = 'stretch'

Field metadata key for a view field of a HorizontalView: its share of the row’s width, against its siblings’ (its view’s default_stretch when unset); 0 keeps it as wide as its content

composeui.core.view.UI_TEXT = 'ui_text'

Field metadata key for text the user reads rather than enters (labels, titles…): it belongs to the app’s code and language, not to a study, so it’s never saved or loaded

class composeui.core.view.ActionView[source]

Bases: View

An entry of a menu or a toolbar that the user triggers, for example Save.

triggered emits when the user triggers it. A checkable action (is_checkable) changes is_checked first, so the callbacks see the new state.

text: str
icon: str | None

an image file’s path; set by the app, not study data: never saved, loaded or reset (the web backend serves the file, so a study must not name one)

data: Any
shortcut: str | None
is_checkable: bool
is_checked: bool
triggered: Signal
__init__(*, is_visible=True, is_enabled=True, renderer=None, text='', icon=None, data=None, shortcut=None, is_checkable=False, is_checked=False, triggered=NOTHING)

Method generated by attrs for class ActionView.

Parameters:
Return type:

None

class composeui.core.view.Align[source]

Bases: Enum

Where a row packs its views when they leave some of its width free.

START = 1
END = 2
class composeui.core.view.ButtonVariant[source]

Bases: Enum

How much a button stands out, for the user to tell actions apart.

PRIMARY = 1

the page’s main action, e.g. submitting its form

SECONDARY = 2

an action beside the main one

DANGER = 3

an action destroying something, e.g. removing rows

class composeui.core.view.ButtonView[source]

Bases: View

A button the user clicks to act on what the page shows, e.g. to submit a form.

default_stretch: ClassVar[int] = 0

its share of a HorizontalView’s width when its field sets no STRETCH

text: str
variant: ButtonVariant
clicked: Signal

the user clicked the button

__init__(*, is_visible=True, is_enabled=True, renderer=None, text='', variant=ButtonVariant.PRIMARY, clicked=NOTHING)

Method generated by attrs for class ButtonView.

Parameters:
Return type:

None

class composeui.core.view.CellKind[source]

Bases: Enum

What the cells of a column show (see CellWidget).

CHECK_BOX = 1

a check box, checked when the cell’s text is “true”, ignoring case

COMBOBOX = 2

a combobox of CellWidget.options, showing the cell’s text

BUTTON = 3

the cell’s text, then a button

the cell’s text as a link

FILE_PATH = 5

a file’s path, then a “…” button picking one (see CellWidget.file_path)

FOLDER_PATH = 6

a folder’s path, then a “…” button picking one (see CellWidget.folder_path)

SAVE_PATH = 7

a path to save a file to, then a “…” button picking one (see CellWidget.save_path)

PATH_BY_KIND = 8

a path picked as the row’s kind says, by another cell (see CellWidget.path_by)

property is_path: bool

Tell whether its “…” button picks a path: a file’s, a folder’s, or one to save to.

class composeui.core.view.CellStyle[source]

Bases: object

How a table’s cell looks, by TableMixin.cell_styles: plain by default.

background: str | None

its color, as #rrggbb, the same in every theme, e.g. red for NaN; its text is black or white, whichever reads on it (text_color)

is_enabled: bool

False: grayed, and never edited, even in an editable column: its widget is disabled

mark: NodeMark | None

a mark before its text, e.g. a warning, named by the table’s mark_text

row_span: int

how many rows it covers, its own and those under it, which show nothing in its column; only while the table shows them right under it, unsorted and unfiltered

property text_color: str | None

Get the color of the text on background, black or white; None without one.

__init__(background=None, is_enabled=True, mark=None, row_span=1)

Method generated by attrs for class CellStyle.

Parameters:
Return type:

None

class composeui.core.view.CellWidget[source]

Bases: object

A widget in each cell of a table’s column, by TableMixin.cell_widgets.

A check box and a combobox edit their cell when the column is in editable_columns. Then cell_edited emits the new text, as for a typed edit; a check box’s text comes from CHECKED_TEXTS. Else they only show the cell’s text. A button and a link emit cell_clicked, and the user never types in their cells.

A file path cell is typed in, and its “…” button picks a file, as FilePathInputView’s does: the toolkit’s file dialog on Qt and Textual, an upload on the web, whose copy the session keeps while a cell holds its path. cell_edited then emits the file’s path. Its button is enabled only in an editable column. With server_roots, the web lists the server’s files in them instead, and refuses a path typed outside them: the cell keeps its text, and the status bar says why. A folder path cell and a save path cell pick as FolderPathInputView and SavePathInputView do: on the web, without server_roots, their path is typed, and they have no button. With base_folder, a relative path names a path in that folder, and a path picked in it shows relative to it, as in a path field.

path_by picks the widget of each cell by the row’s kind: the text of another cell of the row. When the user changes that cell, the path cell’s widget follows.

kind: CellKind
options: tuple[str, ...]

a combobox’s choices, the texts its cells take

text: str

a button’s text; a file path button’s name, as a tooltip and a screen reader show it

check_all: bool

whether a check box column’s header has a box checking or unchecking every shown row

extensions: dict[str, tuple[str, ...]]

the file types a file path’s dialog offers, by name: {"CSV": (".csv",)}; on the web, a file of another type is refused

server_roots: tuple[Path, ...]

the folders of the server whose files a file path’s “…” lists on the web, rather than uploading a copy; on Qt and Textual, the dialog opens in the first one while the cell is empty, and the user can leave it (see FilePathInputMixin.server_roots)

base_folder: Path | None

the folder of a path cell’s relative path (see PathInputMixin.base_folder)

confirms_overwrite: bool

whether a save path’s user agrees to replace a file that exists, before it’s picked

kind_column: int

for path_by: the column of the row’s kind, and the path widget of each kind

editors: dict[str, CellWidget]
translated(translate)[source]

Get it with a button’s text translated again, if it’s TranslatedText.

Parameters:

translate (Callable[[str], str])

Return type:

CellWidget

for_row(cells)[source]

Get the widget of a cell of the row cells: for path_by, its kind’s, if any.

A kind’s widget without a base_folder takes this one’s.

Parameters:

cells (Sequence[str])

Return type:

CellWidget | None

path(text)[source]

Get the path a path cell’s text names: from base_folder if relative.

Parameters:

text (str)

Return type:

Path

path_text(path)[source]

Get the text a path cell shows for path: relative to base_folder when inside it.

Parameters:

path (Path)

Return type:

str

start_folder()[source]

Get the folder a path cell’s dialog opens in while it’s empty, if any.

base_folder, else the first of server_roots.

Return type:

Path | None

classmethod check_box(*, check_all=False)[source]
Parameters:

check_all (bool)

Return type:

CellWidget

classmethod combobox(options=())[source]
Parameters:

options (Iterable[str])

Return type:

CellWidget

classmethod button(text='…')[source]
Parameters:

text (str)

Return type:

CellWidget

Return type:

CellWidget

classmethod file_path(extensions=None, text='Choose a file', server_roots=(), base_folder=None)[source]
Parameters:
  • extensions (Optional[dict[str, tuple[str, ...]]])

  • text (str)

  • server_roots (Iterable[Path])

  • base_folder (Optional[Path])

Return type:

CellWidget

classmethod folder_path(text='Choose a folder', server_roots=(), base_folder=None)[source]
Parameters:
  • text (str)

  • server_roots (Iterable[Path])

  • base_folder (Optional[Path])

Return type:

CellWidget

classmethod save_path(extensions=None, text='Save as', server_roots=(), base_folder=None, *, confirms_overwrite=True)[source]

Get a save path cell: picking a file that exists asks first, nothing is written.

Parameters:
  • extensions (Optional[dict[str, tuple[str, ...]]])

  • text (str)

  • server_roots (Iterable[Path])

  • base_folder (Optional[Path])

  • confirms_overwrite (bool)

Return type:

CellWidget

classmethod path_by(kind_column, editors, base_folder=None)[source]

Get a path cell whose widget is that of the row’s kind, the text of kind_column.

editors are file, folder or save path widgets, by kind. A row whose kind has none shows a plain cell. base_folder is that of the widgets that have none.

Parameters:
Return type:

CellWidget

__init__(kind, options=(), text='…', check_all=False, extensions=NOTHING, server_roots=(), base_folder=None, confirms_overwrite=True, kind_column=0, editors=NOTHING)

Method generated by attrs for class CellWidget.

Parameters:
Return type:

None

class composeui.core.view.ChartKind[source]

Bases: Enum

How a chart draws its series’ points.

LINE = 1

joined by a line, e.g. a result against time

SCATTER = 2

as dots, e.g. measurements over a model’s curve

BAR = 3

as bars, a group of one bar per series in each of the chart’s categories; the chart’s own kind only

class composeui.core.view.ChartView[source]

Bases: View

A chart of results, e.g. a quantity against time or a swept dimension.

The view holds data and labels. Each backend draws it in its own theme’s colors and fonts, unless a series has a color of its own (Series.color). Assign a new series list to redraw it, e.g. when a job adds points. The user’s zoom stays, where the backend has one.

A BAR chart draws a group of bars for each of its categories, a bar per series. A series’ x is the index of a category, and its y is the bar’s height.

A log axis (x_log, y_log) leaves out the values it can’t show, those <= 0. A point at such an x isn’t drawn, and such a y leaves a gap (see drawn_points). A reference line at such a value isn’t drawn either (see drawn_lines). So a job’s points never make the chart fail. A bar chart’s x, its categories, is never a log axis.

kind: ChartKind

how its series are drawn, unless one says otherwise (Series.kind)

title: str
x_title: str
y_title: str
x_unit: str

the x axis’ unit, shown as “Time (s)”, and with the values the user hovers

y_unit: str
series: list[Series]
reference_lines: list[ReferenceLine]

lines at values, e.g. a limit, drawn over the series

categories: list[str]

a BAR chart’s categories, by the index each series’ x names

x_log: bool
y_log: bool
save_image_text: str

the action saving the chart as a report’s image (see composeui.core.chartimage), where the backend has one: with the report extra installed

height: int | None

its height on screen, in pixels (a terminal’s rows of about 16), e.g. to keep a shape’s proportions; None: the backend’s own. The app’s layout, not a study’s

clicked: Signal[float, float]

the user clicked the chart at a point, as the axes’ values (x, then y), e.g. to pick a curve’s point; where the backend has a pointer: Qt and the web, not Textual

static kind_of(series, kind)[source]

Get how series is drawn on a chart of kind: a bar chart draws only bars.

Takes the chart’s kind, as a renderer refreshes it before the view holds it.

Parameters:
Return type:

ChartKind

static drawn_points(series, *, x_log, y_log)[source]

Get the points of series its axes can show: a log axis can’t show 0 or less.

A point whose x a log x axis can’t show is left out; a y a log y axis can’t show is NaN, a gap. As they are without a log axis.

Parameters:
Return type:

tuple[list[float], list[float]]

static step_points(xs, ys)[source]

Get the corners of a step line through the points: each y held until the next x.

A NaN y stays a gap, up to the next point.

Parameters:
Return type:

tuple[list[float], list[float]]

static held_value(xs, ys, x)[source]

Get the y a step line holds at x: the last point’s at or before it, x in order.

None before the first point; NaN in a gap.

Parameters:
Return type:

float | None

static drawn_lines(lines, *, x_log, y_log)[source]

Get the reference lines their axes can show: a log axis can’t show 0 or less.

Parameters:
Return type:

list[ReferenceLine]

static bar_heights(series, category_count, *, y_log=False)[source]

Get the height of a series’ bar in each category, NaN where it has none.

A point whose x isn’t a category’s index has no bar; the last of a category wins. On a log y axis, a height of 0 or less is no bar either.

Parameters:
Return type:

list[float]

static is_whole(values)[source]

Tell whether values are whole numbers, e.g. counts, their gaps (NaN) aside.

A series of them shows its hovered values as integers, e.g. “45280” rather than “4.528e+04”; another with 4 significant digits.

Parameters:

values (Sequence[float])

Return type:

bool

static bar_slot(index, series_count)[source]

Get the offset of a series’ bar from its category’s index, and its width.

In categories: the bar’s middle is at the offset, its group centered on the index.

Parameters:
  • index (int)

  • series_count (int)

Return type:

tuple[float, float]

static axis_label(title, unit)[source]

Get an axis’ label: its title with its unit, as “Time (s)”.

Parameters:
Return type:

str

__init__(*, is_visible=True, is_enabled=True, renderer=None, kind=ChartKind.LINE, title='', x_title='', y_title='', x_unit='', y_unit='', series=NOTHING, reference_lines=NOTHING, categories=NOTHING, x_log=False, y_log=False, save_image_text='Save Image', height=None, clicked=NOTHING)

Method generated by attrs for class ChartView.

Parameters:
Return type:

None

class composeui.core.view.CheckBoxMixin[source]

Bases: object

The fields of a check box: its text, its state and toggled.

text: str

shown next to the box

is_checked: bool
toggled: Signal[bool]

the user checked or unchecked the box; not emitted when is_checked is set in code

property shown_views: list[View]

Get the views shown only while the box is checked (see shows).

shows(*views)[source]

Show views only while the box is checked, from now on, e.g. an optional part.

They follow the box however it changes: as the user clicks it, as code sets is_checked, and as a study opens or New starts one.

Parameters:

views (View)

Return type:

None

__init__(*, text='', is_checked=False, toggled=NOTHING)

Method generated by attrs for class CheckBoxMixin.

Parameters:
Return type:

None

class composeui.core.view.CheckBoxView[source]

Bases: CheckBoxMixin, View

A check box with a text, for an option that is on or off.

__init__(*, is_visible=True, is_enabled=True, renderer=None, text='', is_checked=False, toggled=NOTHING)

Method generated by attrs for class CheckBoxView.

Parameters:
Return type:

None

class composeui.core.view.Column[source]

Bases: object

A column of a RecordTableView: a field of its records, under header.

field: str

the name of the records’ field the column shows

header: str
editable: bool

whether the user edits the column’s cells

sortable: bool

whether the user sorts the rows by the column

filterable: bool

whether the user searches and filters the column

widget: CellWidget | None

the widget in each of its cells (see CellWidget); a combobox without options, on an enum field, offers the enum’s members

__init__(field, header, editable=False, sortable=False, filterable=False, widget=None)

Method generated by attrs for class Column.

Parameters:
Return type:

None

class composeui.core.view.ComboBoxView[source]

Bases: ValuesGroupMixin[TValue], View

A drop-down list, for one choice among values.

__init__(*, is_visible=True, is_enabled=True, renderer=None, value=None, values=NOTHING, value_changed=NOTHING)

Method generated by attrs for class ComboBoxView.

Parameters:
Return type:

None

class composeui.core.view.ConsoleView[source]

Bases: View

Plain text that the app adds to as it comes, for example the output of a process.

append adds text: “n” ends a line, and “r” starts the line again, as a terminal shows a progress line. The view keeps the last max_lines lines and drops the oldest. Set text to replace the text, or call clear. The view shows the text as it is, never as markup, and scrolls to its end as text comes, unless the user scrolled up.

Its text is the app’s output, not study data: never saved, loaded or reset. For a single message to the user, such as an error, see LogView. The user saves the text to a file (export_text), named export_filename at first, or copies it all. The user searches the text too: plain text, any case, as find_in_lines finds it.

The text loses the escape sequences of a terminal, such as the ANSI codes coloring a solver’s output, so it reads, searches and saves as plain text. With ansi_colors, the view shows the colors and styles those codes ask for (line_styles).

max_lines: int

the most lines kept, the line being written not counted; the oldest go first

ansi_colors: bool

whether it shows the colors and styles of the text’s ANSI escape codes

texts: dict[str, str]

the texts of its controls, by what they’re for (see CONSOLE_TEXTS)

export_filename: str

the name offered for the file the text is saved to

property text: str

Get the lines kept, then the line being written.

property lines: Sequence[str]

Get the lines kept, each ended, the oldest first.

property last_line: str

Get the line being written: the text after the last line’s end.

property line_styles: Sequence[tuple[tuple[int, int, TextStyle], ...]]

Get the styled parts of each line kept, as lines: start, end and style.

property last_line_styles: Sequence[tuple[int, int, TextStyle]]

Get the styled parts of the line being written: start, end and style.

property line_count: int

Get how many lines have ended since the view was built, the dropped ones too.

append(text)[source]

Add text at the end, e.g. the output a process has written since the last call.

Parameters:

text (str)

Return type:

None

clear()[source]

Remove the whole text.

Return type:

None

export_text(path)[source]

Write the text to the file path, in UTF-8; the status bar says how it went.

Outside a main view, a failure raises OSError instead.

Parameters:

path (Path)

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, max_lines=10000, ansi_colors=False, texts=NOTHING, export_filename='output.txt')

Method generated by attrs for class ConsoleView.

Parameters:
Return type:

None

class composeui.core.view.ContentDialogView[source]

Bases: OkCancelDialogView, Generic[ContentT]

A modal holding a view, e.g. a table to pick a file from, with OK and Cancel.

Pass the view as content, or give a subclass its typed content default. Its text shows above it. The app sets is_accept_enabled, e.g. once a row is selected: OK can’t be pressed before. The answer comes through accepted or rejected. A button of the content acts without closing the dialog. To keep it open on OK too, e.g. to show the folder selected rather than open it, a subclass overrides accept and calls super().accept() only to close it.

content: ContentT
__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', text='', kind=DialogKind.MESSAGE, accept_text='OK', reject_text='Cancel', accepted=NOTHING, rejected=NOTHING, is_accept_enabled=True, log_view=NOTHING, accepting=NOTHING, content)

Method generated by attrs for class ContentDialogView.

Parameters:
Return type:

None

class composeui.core.view.DateInputMixin[source]

Bases: _InputView

A date, typed as date_format says or picked from a calendar.

Not every backend refuses a date typed out of minimum/maximum: Textual and the web mark it or keep it. So validate the date. The calendar offers only the dates in range.

value: date | None
minimum: date | None
maximum: date | None
date_format: str

how the date is typed and shown: its day dd, month MM and year yyyy between separators; a text the catalogs translate, so the main view’s language’s

month_names: list[str]

the calendar’s month names, January first, and its days’ short names, Monday first

day_names: list[str]
pick_text: str

the names of the button opening the calendar, and of its month buttons, as a screen reader reads them out

previous_month_text: str
next_month_text: str
value_changed: Signal[date | None]

the user typed or picked a new date (None once the field is emptied); not emitted when value is set in code

shown_text(value)[source]

Show value as date_format says, “” for no date.

Parameters:

value (date | None)

Return type:

str

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, date_format='MM/dd/yyyy', month_names=NOTHING, day_names=NOTHING, pick_text='Pick a date', previous_month_text='Previous month', next_month_text='Next month', value_changed=NOTHING)

Method generated by attrs for class DateInputMixin.

Parameters:
Return type:

None

class composeui.core.view.DateInputView[source]

Bases: DateInputMixin, View

A date, e.g. a booking’s first day: typed in the main view’s language’s format.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, date_format='MM/dd/yyyy', month_names=NOTHING, day_names=NOTHING, pick_text='Pick a date', previous_month_text='Previous month', next_month_text='Next month', value_changed=NOTHING)

Method generated by attrs for class DateInputView.

Parameters:
Return type:

None

class composeui.core.view.DialogButtonView[source]

Bases: ButtonView

A button of a dialog’s own, between Cancel and OK, e.g. Apply: a field of the dialog.

Clicking it fires clicked, and the dialog stays open. With closes, the dialog closes once clicked has fired, without accepted or rejected, unless the app’s work refused the change in it (OkCancelDialogView.refusing). With checks, it runs the dialog’s checks first, as OK does: it does nothing while one fails, and can’t be pressed meanwhile (is_blocked).

variant: ButtonVariant
closes: bool

whether clicking it closes the dialog

checks: bool

whether it runs the dialog’s checks first, and waits for them to pass

is_blocked: bool

set by its dialog: it checks, and a check fails, so it can’t be pressed

click()[source]

Act as the user’s click: through its dialog, which checks and closes as asked.

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, text='', clicked=NOTHING, variant=ButtonVariant.SECONDARY, closes=False, checks=True)

Method generated by attrs for class DialogButtonView.

Parameters:
Return type:

None

class composeui.core.view.DialogKind[source]

Bases: Enum

The kind of a DialogView: a message or a confirmation.

MESSAGE = 1

tells the user something: one button, accepting

CONFIRM = 2

asks the user to confirm: an accepting and a rejecting button

class composeui.core.view.DialogView[source]

Bases: View

A modal message or confirmation, shown from open until the user answers.

Nothing waits for the answer, since a web request can’t: it comes through accepted or rejected, once the dialog is closed. A dialog is what the app asks, not study data: never saved, loaded or reset.

title: str
text: str
kind: DialogKind
accept_text: str
reject_text: str

the rejecting button’s text; a message has no such button

accepted: Signal
rejected: Signal
open()[source]

Show the dialog; its answer comes through accepted or rejected.

Return type:

None

accept()[source]

Close the dialog with its accepting answer; ignored unless it’s open.

Return type:

None

reject()[source]

Close the dialog with its rejecting answer; ignored unless it’s open.

Return type:

None

dismiss()[source]

Close the dialog without a button (e.g. Escape): a confirmation is rejected.

A message has only one answer, so dismissing it accepts it.

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', text='', kind=DialogKind.MESSAGE, accept_text='OK', reject_text='Cancel', accepted=NOTHING, rejected=NOTHING)

Method generated by attrs for class DialogView.

Parameters:
Return type:

None

exception composeui.core.view.EditRefusedError[source]

Bases: Exception

Raised by a cell_edited callback to refuse the edit: the cell keeps its old text.

class composeui.core.view.ExpanderView[source]

Bases: View

A collapsible section: its title always shown, its view fields only while expanded.

Its view fields are laid out one above the other, as in a VerticalView, e.g. a record’s details above its Edit and Delete buttons.

title: str

shown in the header the user clicks to expand or collapse the section

is_expanded: bool
toggled: Signal[bool]

the user expanded or collapsed the section; not emitted when is_expanded is set in code

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', is_expanded=False, toggled=NOTHING)

Method generated by attrs for class ExpanderView.

Parameters:
Return type:

None

class composeui.core.view.FileMenu[source]

Bases: Menu

The File menu of the main view, with New, Open, Save, Save As and Exit.

An app without studies sets MainView.has_file_menu to False to leave it out.

new: NewAction
open_file: OpenFileAction
save: SaveAction
save_as: SaveAsAction
separator_exit: SeparatorAction
exit_app: ExitAppAction
title: str
__init__(*, is_visible=True, is_enabled=True, renderer=None, new=NOTHING, open_file=NOTHING, save=NOTHING, save_as=NOTHING, separator_exit=NOTHING, exit_app=NOTHING, title='File')

Method generated by attrs for class FileMenu.

Parameters:
Return type:

None

class composeui.core.view.FilePathInputMixin[source]

Bases: PathInputMixin

A file’s path, typed in the field or picked with the “…” button beside it.

text holds the path as typed, and path reads it as a path. On Qt and Textual, the button opens the toolkit’s file dialog. On the web, the browser’s picker uploads the file. The field then holds the path of the session’s copy, kept until the session ends. With server_roots, the web’s button instead lists the files on the server in those folders, and the field holds the path of the file picked there, not a copy. With has_reload, a reload button beside them emits reload_clicked, e.g. to read the file again once it changed.

extensions: dict[str, tuple[str, ...]]

the file types the dialog offers, by name: {"CSV": (".csv",)}; on the web, a file of another type is refused

has_reload: bool
browse_text: str

the names of the “…” and reload buttons, as a tooltip and a screen reader show them

reload_text: str
partial_folder_text: str
reload_clicked: Signal
__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, has_reload=False, browse_text='Choose a file', reload_text='Reload', partial_folder_text="This folder holds too many items to list them all: type the file's path.", reload_clicked=NOTHING)

Method generated by attrs for class FilePathInputMixin.

Parameters:
Return type:

None

class composeui.core.view.FilePathInputView[source]

Bases: FilePathInputMixin, View

A file’s path, e.g. a data file to read: typed, or picked from a file dialog.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, has_reload=False, browse_text='Choose a file', reload_text='Reload', partial_folder_text="This folder holds too many items to list them all: type the file's path.", reload_clicked=NOTHING)

Method generated by attrs for class FilePathInputView.

Parameters:
Return type:

None

class composeui.core.view.FileView[source]

Bases: View

The file path that the last file dialog of the main view gave.

filepath: Path | None
extensions: dict[str, tuple[str, ...]]
__init__(*, is_visible=True, is_enabled=True, renderer=None, filepath=None, extensions=NOTHING)

Method generated by attrs for class FileView.

Parameters:
Return type:

None

class composeui.core.view.Filter[source]

Bases: object

A column’s filter, parsed from the text the user typed (see parse_filter).

operator: FilterOperator
value: Any

the text a cell is compared with (casefolded), a compiled regular expression, or the value a cell’s is compared with

upper: Any

a range’s end

typed_ascii: bool

a text’s filter typed in ASCII characters alone, which SQLite folds as Python does (see SqliteSource)

matches(value, text)[source]

Tell whether a cell passes: its value (its text in a text column) and its text.

Parameters:
Return type:

bool

__init__(operator, value=None, upper=None, typed_ascii=True)

Method generated by attrs for class Filter.

Parameters:
Return type:

None

exception composeui.core.view.FilterError[source]

Bases: ValueError

A filter’s text that doesn’t parse: problem says why (see TableMixin.filter_error).

__init__(problem, text)[source]
Parameters:
Return type:

None

class composeui.core.view.FilterOperator[source]

Bases: Enum

How a filter compares a cell with its value.

CONTAINS = 'contains'
NOT_CONTAINS = '!'
TEXT_EQUAL = '=text'
TEXT_NOT_EQUAL = '!=text'
STARTS_WITH = 'start*'
ENDS_WITH = '*end'
MATCHES = '/regex/'
EMPTY = 'empty'
EQUAL = '='
NOT_EQUAL = '!='
LESS = '<'
LESS_OR_EQUAL = '<='
GREATER = '>'
GREATER_OR_EQUAL = '>='
RANGE = '..'
class composeui.core.view.FilterProblem[source]

Bases: Enum

Why a filter’s text doesn’t parse (see parse_filter).

EMPTY = 1

nothing typed

NOT_A_NUMBER = 2

not a number, for a number column

NOT_A_DATE = 3

not a date, for a date column

NOT_A_BOOLEAN = 4

neither true nor false, for a boolean column

REVERSED_RANGE = 5

a range whose start is after its end

NOT_A_PATTERN = 6

not a valid regular expression, for a text column’s /pattern/

class composeui.core.view.FloatInputMixin[source]

Bases: _InputView

The fields of a field for a decimal number: its value, range and decimals.

value: float | None
minimum: float | None
maximum: float | None
decimals: int | None

the most decimals the field shows (and, on Qt, takes); None: as many as str writes

static shown_text(value, decimals)[source]

Show value with at most decimals decimals, “” for no value.

The value is rounded, and trailing zeros are left out: with 0 decimals, 36.0 is “36”, and with 2, 3.14159 is “3.14” and 2.5 is “2.5”. Without decimals, the value shows as str writes it, e.g. “36.0”. Takes decimals, as a renderer refreshes it before the view holds it.

Parameters:
  • value (float | None)

  • decimals (int | None)

Return type:

str

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, decimals=None)

Method generated by attrs for class FloatInputMixin.

Parameters:
Return type:

None

class composeui.core.view.FloatInputView[source]

Bases: FloatInputMixin, View

A field where the user types a decimal number, for example a length.

value is None while the field is empty.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, decimals=None)

Method generated by attrs for class FloatInputView.

Parameters:
Return type:

None

class composeui.core.view.FolderPathInputMixin[source]

Bases: PathInputMixin

A folder’s path, typed in the field or picked with the “…” button beside it.

text holds the path as typed, and path reads it as a path. On Qt and Textual, the button opens the toolkit’s folder dialog. The browser can’t give the page a folder’s path: on the web, the user types it, and the field has no button. With server_roots, the web’s button lists the server’s folders in them: a folder’s item shows its folders, and “Choose this folder” puts the folder shown in the field.

browse_text: str

the name of the “…” button, as a tooltip and a screen reader show it

choose_folder_text: str

the button of the web’s list that picks the folder it shows

partial_folder_text: str
__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, browse_text='Choose a folder', choose_folder_text='Choose this folder', partial_folder_text="This folder holds too many items to list them all: type the folder's path.")

Method generated by attrs for class FolderPathInputMixin.

Parameters:
Return type:

None

class composeui.core.view.FolderPathInputView[source]

Bases: FolderPathInputMixin, View

A folder’s path, e.g. where to write results: typed, or picked from a folder dialog.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, browse_text='Choose a folder', choose_folder_text='Choose this folder', partial_folder_text="This folder holds too many items to list them all: type the folder's path.")

Method generated by attrs for class FolderPathInputView.

Parameters:
Return type:

None

class composeui.core.view.FormDialogView[source]

Bases: TypedFormDialogView[FormView]

A form dialog with a default empty FormView, with OK and Cancel.

Use TypedFormDialogView to declare a subclass with a more specific form type. Both classes use the same validation, signals, and renderers.

form: FormView
__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', text='', kind=DialogKind.MESSAGE, accept_text='OK', reject_text='Cancel', accepted=NOTHING, rejected=NOTHING, is_accept_enabled=True, log_view=NOTHING, accepting=NOTHING, form=NOTHING)

Method generated by attrs for class FormDialogView.

Parameters:
Return type:

None

class composeui.core.view.FormLabelRowView[source]

Bases: FormRowView

A row of a form with a label before its field, and a help button if it has help.

label: str
help: str

what to enter in the field, shown by a “?” button beside the label (a hint on Textual)

help_button_text: str

the “?” button’s name for screen readers

__init__(*, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class FormLabelRowView.

Parameters:
Return type:

None

class composeui.core.view.FormRowView[source]

Bases: LogMixin, View

A row of a form: a field, and the message of its check under it.

has_form_error: bool

set by FormView.validate while a cross-field check naming this row fails

property is_invalid: bool

Whether the row’s field shows as invalid: its own check or its form’s fails.

is_invalid_once(name, value)[source]

Get is_invalid once the attribute name is set to value.

For renderers: they are notified of a change before it lands in the view (see notify_renderer), so is_invalid itself still answers for the old value.

Parameters:
Return type:

bool

__init__(*, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class FormRowView.

Parameters:
Return type:

None

class composeui.core.view.FormView[source]

Bases: View

A form: its rows, one above the other, and the message of its cross-field checks.

Its FormRowView and FormView fields are its rows, in order (field_rows). Its other view fields, such as a table or a row of buttons, show in their place between the rows, as wide as the form (content_views). Its checks run on its rows only.

log_view: LogView
checked: Signal

the form’s cross-field checks ran (validate), passing or not

property content_views: list[View]

Get the views the form shows, in order: its rows and its other views, not its log.

property field_rows: list[FormRowView | FormView]

Get the rows of the form and its nested forms, in order.

add_validator(validator, *signals, rows=())[source]

Register a cross-field validator, re-run whenever any of signals fires.

Unlike LogMixin.set_validator (one validator per row, in that row’s own log), a form can have several independent cross-field checks. The form combines each failing (non-None) result into its shared log_view, instead of the last one winning. See PipeFormView in examples/pipeform.py: it has two independent checks spanning main_pipe and incident_pipe. It doesn’t run immediately: call validate afterward for an initial check.

rows are the rows that the check is about. While the check fails, each of them shows its field as invalid (FormRowView.has_form_error). So the user sees which values to fix, even though the message is in the form’s log. The form that last validated a row flags it, so name a row in the checks of one form only.

Parameters:
Return type:

None

validate(*_args)[source]

Re-run every registered validator and push the combined result to log_view.

Takes (and ignores) any positional args so it can be connected directly to signals of any arity, same as LogMixin.run_validator.

Parameters:

_args (Any)

Return type:

None

check()[source]

Run every check now: each row’s, then each form’s, nested forms first.

Return type:

None

property is_valid: bool

Whether no check shown fails: a row’s own, the form’s, or a nested form’s.

As last checked: a check that hasn’t run yet passes (see check).

__init__(*, is_visible=True, is_enabled=True, renderer=None, log_view=NOTHING, checked=NOTHING)

Method generated by attrs for class FormView.

Parameters:
Return type:

None

class composeui.core.view.GridPosition[source]

Bases: NamedTuple

A view’s cell in a GridView, counted from 0, spanning more cells to its right or below.

row: int

Alias for field number 0

column: int

Alias for field number 1

row_span: int

Alias for field number 2

column_span: int

Alias for field number 3

property cells: list[tuple[int, int]]

Get the (row, column) cells the view covers.

static __new__(_cls, row, column, row_span=1, column_span=1)

Create new instance of GridPosition(row, column, row_span, column_span)

Parameters:
exception composeui.core.view.GridPositionError[source]

Bases: ValueError

A GridView’s view field has no cell, or one outside the grid or another view’s.

class composeui.core.view.GridView[source]

Bases: View

Its view fields laid out in a grid: equally wide columns, rows as tall as their views.

Each field sets its cell with its GRID_POSITION metadata: chart: ChartView = attrs.field(factory=ChartView, metadata={GRID_POSITION: (1, 0)}), or GridPosition(1, 0, column_span=2) to span two columns. Cells no view takes are left empty, as are those of a hidden view. A view shorter than its row stays at its top. A view with no share of a row (default_stretch 0, e.g. a button) keeps its content’s width, at its cell’s start. On the web, a grid narrower than 42rem stacks its views in one column, row by row.

property positioned_views: list[tuple[View, GridPosition]]

Get the views in the grid with their cells, row by row.

property row_count: int

Get the number of rows: down to the lowest view’s last.

property column_count: int

Get the number of columns: up to the rightmost view’s last.

__init__(*, is_visible=True, is_enabled=True, renderer=None)

Method generated by attrs for class GridView.

Parameters:
Return type:

None

class composeui.core.view.GroupFormView[source]

Bases: FormView

A form in a box with a title, for example a group of related fields.

title: str
__init__(*, is_visible=True, is_enabled=True, renderer=None, log_view=NOTHING, checked=NOTHING, title='')

Method generated by attrs for class GroupFormView.

Parameters:
Return type:

None

class composeui.core.view.HeaderGroup[source]

Bases: object

A header over several columns, on a row above theirs, by TableMixin.header_groups.

E.g. “Coordinates” over “Standard space” and “Physical space”.

text: str
column: int

its first column

column_count: int

how many columns it covers, from column on

translated(translate)[source]

Get it with its text translated again, if it’s TranslatedText.

Parameters:

translate (Callable[[str], str])

Return type:

HeaderGroup

covers(column)[source]
Parameters:

column (int)

Return type:

bool

__init__(text, column, column_count)

Method generated by attrs for class HeaderGroup.

Parameters:
Return type:

None

class composeui.core.view.HorizontalView[source]

Bases: View

Its view fields laid out side by side, in a row.

Each field takes a share of the row’s width, set by its STRETCH metadata: rooms: TableView = attrs.field(factory=TableView, metadata={STRETCH: 3}). When the metadata is unset, the share is the view’s default_stretch (1). A view with a share of 0 keeps its content’s width, as a button does by default. When all views do, align packs them at the row’s start or end: a subclass sets align = Align.END. On the web, a row narrower than 42rem stacks its views, unless none takes a share.

align: ClassVar[Align] = 1

where the views go when none of them takes a share of the row’s free width

property stretched_views: list[tuple[View, int]]

Get the views in the row, in order, each with its share of the row’s width.

__init__(*, is_visible=True, is_enabled=True, renderer=None)

Method generated by attrs for class HorizontalView.

Parameters:
Return type:

None

class composeui.core.view.InputMixin[source]

Bases: _InputView

The fields of a field for one line of text: its text and its signals.

text: str
__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='')

Method generated by attrs for class InputMixin.

Parameters:
Return type:

None

class composeui.core.view.InputView[source]

Bases: InputMixin, View

A field where the user types one line of text, for example a name.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='')

Method generated by attrs for class InputView.

Parameters:
Return type:

None

class composeui.core.view.IntInputMixin[source]

Bases: _InputView

The fields of a field for a whole number: its value and its range.

value: int | None
minimum: int | None
maximum: int | None
__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None)

Method generated by attrs for class IntInputMixin.

Parameters:
Return type:

None

class composeui.core.view.IntInputView[source]

Bases: IntInputMixin, View

A whole number, e.g. an hour of the day; a spin box where the toolkit has one.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None)

Method generated by attrs for class IntInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelMixin[source]

Bases: object

The fields of a label: its text.

text: str
__init__(*, text='')

Method generated by attrs for class LabelMixin.

Parameters:

text (str)

Return type:

None

class composeui.core.view.LabelRowCheckBoxView[source]

Bases: FormLabelRowView, CheckBoxMixin

A row of a form with a label and a check box.

__init__(*, text='', is_checked=False, toggled=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowCheckBoxView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowComboBoxView[source]

Bases: FormLabelRowView, ValuesGroupMixin[TValue]

A row of a form with a label and a drop-down list.

__init__(*, value=None, values=NOTHING, value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowComboBoxView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowDateInputView[source]

Bases: FormLabelRowView, DateInputMixin

A row of a form with a label and a date field.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, date_format='MM/dd/yyyy', month_names=NOTHING, day_names=NOTHING, pick_text='Pick a date', previous_month_text='Previous month', next_month_text='Next month', value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowDateInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowFilePathInputView[source]

Bases: FormLabelRowView, FilePathInputMixin

A row of a form with a label and a file path field.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, has_reload=False, browse_text='Choose a file', reload_text='Reload', partial_folder_text="This folder holds too many items to list them all: type the file's path.", reload_clicked=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowFilePathInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowFloatInputView[source]

Bases: FormLabelRowView, FloatInputMixin

A row of a form with a label and a field for a decimal number.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, decimals=None, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowFloatInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowFolderPathInputView[source]

Bases: FormLabelRowView, FolderPathInputMixin

A row of a form with a label and a folder path field.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, browse_text='Choose a folder', choose_folder_text='Choose this folder', partial_folder_text="This folder holds too many items to list them all: type the folder's path.", is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowFolderPathInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowInputView[source]

Bases: FormLabelRowView, InputMixin

A row of a form with a label and a field for one line of text.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowIntInputView[source]

Bases: FormLabelRowView, IntInputMixin

A row of a form with a label and a field for a whole number.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowIntInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowRadioGroupView[source]

Bases: FormLabelRowView, ValuesGroupMixin[TValue]

A row of a form with a label and a group of radio buttons.

__init__(*, value=None, values=NOTHING, value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowRadioGroupView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowSavePathInputView[source]

Bases: FormLabelRowView, SavePathInputMixin

A row of a form with a label and a field of a path to save a file to.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, confirms_overwrite=True, browse_text='Save as', partial_folder_text="This folder holds too many items to list them all: type the file's path.", file_name_text='File name', save_text='Save', replace_question_text='{name} already exists. Replace it?', replace_text='Replace', is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowSavePathInputView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowSliderView[source]

Bases: FormLabelRowView, SliderMixin

A row of a form with a label and a slider.

__init__(*, value=0, minimum=0, maximum=100, step=1, value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowSliderView.

Parameters:
Return type:

None

class composeui.core.view.LabelRowTextAreaView[source]

Bases: FormLabelRowView, TextAreaMixin

A row of a form with a label and a field for several lines of text.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False, label='', help='', help_button_text='Help')

Method generated by attrs for class LabelRowTextAreaView.

Parameters:
Return type:

None

class composeui.core.view.LabelView[source]

Bases: LabelMixin, View

A line of read-only text, for example a caption.

__init__(*, is_visible=True, is_enabled=True, renderer=None, text='')

Method generated by attrs for class LabelView.

Parameters:
Return type:

None

class composeui.core.view.LanguageMenu[source]

Bases: Menu

A menu of the app’s languages, the one shown checked; triggering one shows it.

Make it a field of the main view. The main view gives it the languages it has catalogs for (MainView.languages), and keeps the shown one checked. The menu names each language in itself, whatever the language shown. The language isn’t study data: never saved, loaded or reset.

title: str
actions: list[ActionView]

each language’s action, its code as data; set with set_languages

names: ClassVar[Mapping[str, str]] = mappingproxy({'ar': 'العربية', 'bg': 'Български', 'ca': 'Català', 'cs': 'Čeština', 'da': 'Dansk', 'de': 'Deutsch', 'el': 'Ελληνικά', 'en': 'English', 'es': 'Español', 'et': 'Eesti', 'fa': 'فارسی', 'fi': 'Suomi', 'fr': 'Français', 'he': 'עברית', 'hi': 'हिन्दी', 'hr': 'Hrvatski', 'hu': 'Magyar', 'id': 'Bahasa Indonesia', 'it': 'Italiano', 'ja': '日本語', 'ko': '한국어', 'lt': 'Lietuvių', 'lv': 'Latviešu', 'nb': 'Norsk bokmål', 'nl': 'Nederlands', 'pl': 'Polski', 'pt': 'Português', 'ro': 'Română', 'ru': 'Русский', 'sk': 'Slovenčina', 'sl': 'Slovenščina', 'sr': 'Српски', 'sv': 'Svenska', 'th': 'ไทย', 'tr': 'Türkçe', 'uk': 'Українська', 'vi': 'Tiếng Việt', 'zh': '中文'})

the languages’ names, by code; a subclass extends it for a language it lacks: names = {**LanguageMenu.names, "eo": "Esperanto"}

property children_views: list[View]

Get the views in the fields of this view, in order.

set_languages(languages)[source]

Offer languages, by code, before the menu is rendered.

A language whose first letter no other one shares gets a Ctrl+Shift shortcut.

Parameters:

languages (Sequence[str])

Return type:

None

action(language)[source]

Get the action of language, e.g. “fr”.

Parameters:

language (str)

Return type:

ActionView

check(language)[source]

Check language’s action, else its base language’s: “fr-CA” checks French.

Parameters:

language (str)

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='Language', actions=NOTHING)

Method generated by attrs for class LanguageMenu.

Parameters:
Return type:

None

class composeui.core.view.LineStyle[source]

Bases: Enum

How a reference line is drawn; a terminal draws each solid.

SOLID = 1
DASHED = 2
DOTTED = 3
DASH_DOT = 4

dashes and dots in turn

class composeui.core.view.ListSource[source]

Bases: Generic[RecordT]

A TableSource of attrs records in memory: a row per record, a column per header.

Build it with the records’ type and the headers by field: ListSource(Room, {"name": T("Room"), "temperature": T("Temperature")}). A row’s id is its index in records, or its id_field when it has one: then new records keep a table’s selection on the same records. Assign new records to change the rows, which emits changed. It sorts, searches and filters as a RecordTableView does: an enum by its text, as shown.

__init__(record_type, headers, records=(), *, id_field=None)[source]
Parameters:
Return type:

None

property columns: Sequence[SourceColumn]
property changed: Signal
property records: Sequence[RecordT]
count()[source]
Return type:

int

ordered_ids(sort, search, filters)[source]
Parameters:
Return type:

list[Hashable]

cells(ids, columns)[source]
Parameters:
Return type:

dict[Hashable, list[Any]]

class composeui.core.view.ListView[source]

Bases: View, Generic[ItemT]

A view per record, laid out in a column, e.g. an expander per record.

A subclass builds a record’s view (build_item). Set items to the records, e.g. the model’s, to show them. A new record gets a view of its own, and a record gone takes its view along. A record still there keeps its view, told by its key (item_key). A changed record keeps its view if update_item shows the change in it. The view then keeps what the user did to it, e.g. an expander stays expanded. Else the record gets a new view. The records and their views are the model’s, not study data: never saved, loaded or reset.

item_views: list[View]

the records’ views, in the records’ order; made by setting items

property children_views: list[View]

Get the views in the fields of this view, in order.

property items: list[ItemT]

Get the records shown, in order.

build_item(item)[source]

Get a new view showing item; a subclass builds it.

Parameters:

item (ItemT)

Return type:

View

item_key(item)[source]

Get what tells item apart from the other records: the record itself by default.

A record changed, with the same key, keeps its view; e.g. a key of its name or id.

Parameters:

item (ItemT)

Return type:

Hashable

update_item(view, item)[source]

Show item, changed, in view, its view; return False to get a new view instead.

The default, so a subclass only shows a change in place where it’s worth it.

Parameters:
  • view (View)

  • item (ItemT)

Return type:

bool

__init__(*, is_visible=True, is_enabled=True, renderer=None)

Method generated by attrs for class ListView.

Parameters:
Return type:

None

class composeui.core.view.LogMixin[source]

Bases: object

The fields of a message that a check (validator) writes, e.g. an error.

log_message: str
log_type: LogType
validator: Callable[[], str | None] | None
checked: Signal

the row’s check ran (run_validator), passing or not, e.g. for a form dialog’s OK

set_validator(validator, *signals)[source]

Wire validator to run against this row whenever any of signals fires.

A failing (non-None) result is pushed into this row’s own log_message/log_type, and a passing (None) result clears them. It doesn’t run validator immediately: call run_validator afterward for an initial check. E.g. an empty required field should already show its error before the first edit.

Parameters:
Return type:

None

run_validator(*_args)[source]

Re-run validator, if set, and push its result into the row’s own log.

Takes (and ignores) any positional arguments, so it can be connected directly to signals of any arity. E.g. a per-keystroke text_edited: Signal[str], or a no-argument editing_finished: SignalNoArgs.

Parameters:

_args (Any)

Return type:

None

__init__(*, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING)

Method generated by attrs for class LogMixin.

Parameters:
Return type:

None

class composeui.core.view.LogType[source]

Bases: Enum

How a log message reads: an error, a warning or information.

ERROR = 1
WARNING = 2
INFO = 3
class composeui.core.view.LogView[source]

Bases: LogMixin, View

A message to the user, for example an error, styled by its log_type.

A new message replaces the last one. For a stream of output, see ConsoleView.

__init__(*, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING)

Method generated by attrs for class LogView.

Parameters:
Return type:

None

class composeui.core.view.MainView[source]

Bases: View

The root view of an app: its window, with the menus, the status bar and the content.

A subclass sets app_title, extension and translations_dir, and adds its views as fields. The main view saves and loads the state of its views (save_state, load_state), and runs work in threads with jobs.

width: ClassVar[PageWidth] = 1

the web content’s default width; a subclass sets it: width = PageWidth.WIDE

app_title: ClassVar[str] = ''

the app’s name, in the window’s title; a subclass sets it: app_title = T("Pipes")

extension: ClassVar[str] = ''

the extension of the app’s study files; a subclass sets it: extension = ".pipe"

app_icon: ClassVar[Path | None] = PosixPath('/home/runner/work/composeui/composeui/src/composeui/images/composeui.svg')

the app’s icon, an image file: the window’s on Qt, the browser tab’s and the header’s on the web. ComposeUI’s by default; a subclass sets its own, or None for none

has_file_menu: ClassVar[bool] = True

whether the window has file_menu, the studies’ New, Open, Save, Save As and Exit; an app without studies, e.g. a viewer, sets it to False and leaves it out

state_version: ClassVar[int] = 1

the version of the app’s state, saved with it: a subclass raises it when a change of its views would lose an older study’s state, and upgrades the state in migrate_state

title: str

app_title, in the main view’s language

state_filepath: Path | None
minimum_width: int
minimum_height: int
file_menu: FileMenu
file_view: FileView
status_bar: StatusBar
replace_file: ReplaceFileDialogView

the question before write_file replaces a file that exists

loaded: Signal

emitted once the views and the model’s data are in place: as the app starts, with the study of -f or a new one, and after New and Open (after Model.loaded). The app gives again then what a study doesn’t hold, such as the source of a large table

jobs: Jobs

functions run in threads, their results given back on the main thread

translations_dir: ClassVar[Path | None] = None

the directory of the app’s catalogs, <language>.json files (see composeui.core.translation); a subclass sets it, e.g. to Path(__file__).parent / "locales"

source_language: ClassVar[str] = 'en'

the language the app’s text is written in, shown until set_language

property children_views: list[View]

Get the views in the fields of this view, in order.

classmethod add_arguments(parser)[source]

Add the app’s own command-line options to parser, e.g. a file to show.

After the backend’s (-f, --language, --port…); apply_arguments gets their values. None by default.

Parameters:

parser (argparse.ArgumentParser)

Return type:

None

apply_arguments(args)[source]

Apply the app’s own command-line options (add_arguments), parsed in args.

Once the main view is wired and -f’s study is open: once on Qt and Textual, for every session on the web.

Parameters:

args (argparse.Namespace)

Return type:

None

property language: str

Get the language the text shows in: set with set_language, or the source’s.

property languages: list[str]

Get the languages the app shows: source_language, then the catalogs’.

set_language(language)[source]

Show the text of every view in language, e.g. “fr” or “fr-CA”.

From the app’s catalogs (translations_dir), then ComposeUI’s; text neither translates shows as written in the code.

Parameters:

language (str)

Return type:

None

load_state(filepath)[source]

Load the state saved in a json file; see load_state_data.

Parameters:

filepath (Path)

Return type:

None

file_data()[source]

Get what a study file holds: the views’ state (state_data) and its versions.

Return type:

dict[str, Any]

state_data_from_file(data)[source]

Get the views’ state from what a study file holds (file_data), upgraded.

A state of an older state_version goes through migrate_state. Raises InvalidStateError for a file of a newer ComposeUI or app, or not one at all.

Parameters:

data (Any)

Return type:

Any

migrate_state(data, version)[source]

Upgrade a state saved by an older state_version of the app, version.

Return the state as state_data gets it now. The app overrides it when it raises state_version, e.g. to move a renamed field’s value to its new name. Without an override, the state loads as it is: the fields it no longer has are skipped.

Parameters:
Return type:

Any

load_state_data(data)[source]

Load state, as state_data gets it: a study file’s from state_data_from_file.

Raises InvalidStateError, leaving this view unchanged, when the data doesn’t fit it (see check_state_data).

Parameters:

data (Any)

Return type:

None

check_state_data(data)[source]

Raise InvalidStateError if load_state_data can’t load data.

The data is applied to a newly built main view. Applying sets the fields one by one, so data that fails halfway would otherwise leave this view half loaded.

Parameters:

data (Any)

Return type:

None

state_data()[source]

Get the state save_state writes, before it’s turned into json.

Return type:

Any

reset_state()[source]

Set every view back to the state of a newly built main view (a new study).

The tree is reset in place, as load_state loads into it, so renderers and connected signals keep working.

Return type:

None

save_state(filepath)[source]

Save the current state into a json file, with its versions (file_data).

Parameters:

filepath (Path)

Return type:

None

ask_open_filepath(extensions)[source]
Parameters:

extensions (dict[str, tuple[str, ...]])

Return type:

Path | None

write_file(target, write)[source]

Call write(path) to write a file, once the user agrees to replace one that exists.

target is a save path field, whose path it writes, or a path. Nothing happens while the field is empty. A field asks with its own texts, and only once: not again when the user already agreed in its picker (SavePathInputMixin.is_replace_agreed). The app’s write writes the file; Cancel writes nothing. Give write the data as it is now, e.g. with functools.partial: the answer comes later.

Parameters:
Return type:

None

ask_save_filepath(extensions)[source]
Parameters:

extensions (dict[str, tuple[str, ...]])

Return type:

Path | None

render(renderer_type)[source]
Parameters:

renderer_type (RendererType)

Return type:

None

close()[source]
Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, state_filepath=None, minimum_width=720, minimum_height=480, file_menu=NOTHING, file_view=NOTHING, status_bar=NOTHING, replace_file=NOTHING, loaded=NOTHING)

Method generated by attrs for class MainView.

Parameters:
Return type:

None

class composeui.core.view.MapPoint[source]

Bases: object

A geographic position, given as latitude and longitude in degrees.

Both arguments are keyword-only. Latitude is limited to the range of a Web Mercator map.

latitude: float
longitude: float
__init__(*, latitude, longitude)

Method generated by attrs for class MapPoint.

Return type:

None

class composeui.core.view.MapView[source]

Bases: View

An interactive street map with geographic points drawn over its tiles.

Qt uses Qt Location, and the web uses deck.gl. Textual does not render this view. With center=None and zoom=None, the map fits its points and follows new data and widget sizes. Each explicit value overrides its automatic value. A user pan or zoom sets both values; new points then keep that viewport. Reset both to None to fit again. The study saves these settings, but not the points or tile settings.

MAX_ZOOM: ClassVar[int] = 19
title: str
center: MapPoint | None

None fits the points; otherwise the center to keep

zoom: float | None

None fits the points; otherwise an OpenStreetMap zoom level from 0 to 19

points: list[MapPoint]
height: int
tiles: bool

False draws only the points, without any network requests for tiles

user_agent: str

identifies the native app to the tile server; the web uses the browser’s identity

clicked: Signal[float, float]
viewport_changed: Signal

the user panned or zoomed; center and zoom already hold the new viewport

static point_bounds(points, center)[source]

Get the center and spans as fractions of the Web Mercator world.

With no center override, use the shortest longitude arc across the date line. With an override, use spans symmetric around that center.

Parameters:
Return type:

tuple[MapPoint, float, float]

static fitted_zoom(span_x, span_y, width, height)[source]

Fit Mercator spans in pixel dimensions with 32 pixels of padding on each side.

Clamp the zoom to 0 through 19; use 12 for a single location.

Parameters:
Return type:

float

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', center=None, zoom=None, points=NOTHING, height=400, tiles=True, user_agent='ComposeUI (+https://github.com/ehmoussi/composeui)', clicked=NOTHING, viewport_changed=NOTHING)

Method generated by attrs for class MapView.

Parameters:
Return type:

None

class composeui.core.view.MarkdownMixin[source]

Bases: object

The fields of a Markdown view: its text.

text: str

read-only Markdown, e.g. a help page; its links open in the browser

__init__(*, text='')

Method generated by attrs for class MarkdownMixin.

Parameters:

text (str)

Return type:

None

class composeui.core.view.MarkdownView[source]

Bases: MarkdownMixin, View

Read-only Markdown text, for example a help page.

Its links open in the browser. Raw HTML in the text is never read as markup.

__init__(*, is_visible=True, is_enabled=True, renderer=None, text='')

Method generated by attrs for class MarkdownView.

Parameters:
Return type:

None

class composeui.core.view.Menu[source]

Bases: View

A menu of the window, with an entry for each of its action fields.

Its ActionView and SeparatorAction fields are its entries, in order. title names it.

title: str
__init__(*, is_visible=True, is_enabled=True, renderer=None, title='')

Method generated by attrs for class Menu.

Parameters:
Return type:

None

class composeui.core.view.MetricView[source]

Bases: View

A figure read at a glance, e.g. the jobs running, and how much it changed.

A row of them in a HorizontalView makes a dashboard’s summary.

label: str

what the figure counts, e.g. “Running”

value: str

the figure as shown, formatted by the app, e.g. “3” or “12.5 GB”

delta: float | None

how much the figure changed; None shows no badge, else its sign colors the badge

delta_text: str

after the change in its badge, e.g. “since yesterday”

static badge(delta, delta_text)[source]

Get the badge’s text, e.g. “↑ 2 since yesterday”, a fall “↓ 2”, no change “→ 0”.

Takes both, as a renderer refreshes one before the view holds the new value.

Parameters:
Return type:

str

__init__(*, is_visible=True, is_enabled=True, renderer=None, label='', value='', delta=None, delta_text='')

Method generated by attrs for class MetricView.

Parameters:
Return type:

None

class composeui.core.view.NodeMark[source]

Bases: Enum

A mark of a tree node’s state, shown after its label.

DONE = 1

done, e.g. an analysis that ran: a green check

WARNING = 2

to look at, e.g. an analysis whose results are out of date: an orange “!”

ERROR = 3

failed, e.g. an analysis that stopped on an error: a red cross

class composeui.core.view.OkCancelDialogView[source]

Bases: DialogView

A modal showing a view above its buttons: Cancel, its own, then OK.

The base of ContentDialogView and TypedFormDialogView. Its own buttons are its DialogButtonView fields (buttons), e.g. Apply. Its own checks (add_check) are about any view it shows: while one fails, its message shows above the buttons, and OK can’t be pressed. The answer comes through accepted or rejected. To do the work of OK while the dialog is open, e.g. a save that the model may refuse, connect to accepting and do it in refusing: a refusal then keeps the dialog open. show_message tells the user something else there, e.g. that Apply saved the changes.

is_accept_enabled: bool

whether OK can be pressed, as the app or the form says; a failing check also stops it

has_failing_check: bool

a check of the dialog’s own failed when last run (validate)

log_view: LogView

the message of the dialog’s own checks, above its buttons

accepting: Signal

the user pressed OK and every check passed: the dialog is still open

property buttons: list[DialogButtonView]

Get the dialog’s own buttons, in order: they show between Cancel and OK.

property can_accept: bool

Whether OK can be pressed: enabled, and no check of the dialog’s own fails.

property is_valid: bool

Whether no check shown fails; as last checked: a check not run yet passes.

add_check(validator, *signals)[source]

Register a check of the dialog’s own, run again whenever any of signals fires.

validator returns the message to show, or None when it passes. Like a form’s (FormView.add_validator), but about any view the dialog shows. It doesn’t run now: call validate for a first check. OK runs every check.

Parameters:
Return type:

None

validate(*_args)[source]

Run the dialog’s own checks, and show the message of each failing one.

Takes (and ignores) any positional args, to be connected to signals of any arity.

Parameters:

_args (Any)

Return type:

None

refusing(message)[source]

Show the model’s refusal of the block’s change in the dialog, which stays open.

As View.refusing, but the message shows above the dialog’s buttons, as a failing check’s does, rather than in the status bar. In accepting, or in the clicked of a button of its own that closes, the refusal keeps the dialog open. The next click, or the next opening, takes the message away.

Parameters:

message (str)

Return type:

Iterator[None]

show_message(message)[source]

Show message above the dialog’s buttons, e.g. “Saved” after Apply: not an error.

It doesn’t keep the dialog open, nor stop OK. The next click, a check running again, or the next opening takes it away.

Parameters:

message (str)

Return type:

None

check()[source]

Run every check of the dialog now.

Return type:

None

accept()[source]

Close the dialog with its accepting answer, once every check passes.

Ignored unless it’s open; while a check fails, it stays open, showing why.

Return type:

None

click(button)[source]

Answer a click of button, one of its own: check, fire clicked, then close.

Ignored unless the dialog is open, or while a check fails and the button checks. It closes only for a button that closes, and unless clicked refused the change.

Parameters:

button (DialogButtonView)

Return type:

None

open()[source]

Show the dialog, without the message of an earlier answer.

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', text='', kind=DialogKind.MESSAGE, accept_text='OK', reject_text='Cancel', accepted=NOTHING, rejected=NOTHING, is_accept_enabled=True, log_view=NOTHING, accepting=NOTHING)

Method generated by attrs for class OkCancelDialogView.

Parameters:
Return type:

None

class composeui.core.view.Orientation[source]

Bases: Enum

How a splitter lays out its panes.

HORIZONTAL = 1

side by side, sharing its width

VERTICAL = 2

one above the other, sharing its height

class composeui.core.view.PageView[source]

Bases: View

A page of the app, shown while its Router is on the page’s route.

Its view fields are its content, laid out in a column. action is its entry in the router’s toolbar, which shows the page’s title and icon. The action isn’t content. It is navigation, not study data: never saved, loaded or reset.

width: ClassVar[PageWidth] = 1

how wide the page may grow; a subclass sets it: width = PageWidth.WIDE

route: ClassVar[str] = ''

names the page in its router; a subclass sets it: route = "results"

page_title: ClassVar[str] = ''

the title the page starts with: page_title = T("Results")

action: ActionView
property title: str

The page’s name in the toolbar.

property icon: str | None

The page’s icon in the toolbar, if the backend shows icons.

property content_views: list[View]

Get the views shown on the page, in order.

__init__(*, is_visible=True, is_enabled=True, renderer=None, action=NOTHING)

Method generated by attrs for class PageView.

Parameters:
Return type:

None

class composeui.core.view.PageWidth[source]

Bases: Enum

How wide the content of a main view or page may grow on the web.

NARROW = 1

a column of fields, easy to read

WIDE = 2

room for side by side views, e.g. tables

FULL = 3

the whole window

class composeui.core.view.PickFileAction[source]

Bases: ActionView

An action picking a file to open; file_picked emits its path.

On Qt and Textual, triggering it shows the file picker. On the web, the browser’s picker uploads the file: the path is then a copy, gone once file_picked’s callbacks have run. Unlike OpenFileAction, the file is the app’s to read, not a study.

extensions: dict[str, tuple[str, ...]]

the file types the picker offers, by name: {"Markdown": (".md", ".markdown")}; on the web, a file of another type is refused

file_picked: Signal[Path]
__init__(*, is_visible=True, is_enabled=True, renderer=None, text='', icon=None, data=None, shortcut=None, is_checkable=False, is_checked=False, triggered=NOTHING, extensions=NOTHING, file_picked=NOTHING)

Method generated by attrs for class PickFileAction.

Parameters:
Return type:

None

class composeui.core.view.ProgressBarView[source]

Bases: View

How far a long task has gone, e.g. a computation working through its cases.

value: int

steps done, from 0 to maximum; shown clamped to that range (see clamp)

maximum: int | None

steps the task takes; None while unknown, the bar then only showing that it runs

static clamp(value, maximum)[source]

Get value within the bar’s range of maximum steps: a count may overshoot.

Takes both, as a renderer refreshes one before the view holds the new value.

Parameters:
  • value (int)

  • maximum (int | None)

Return type:

int

__init__(*, is_visible=True, is_enabled=True, renderer=None, value=0, maximum=100)

Method generated by attrs for class ProgressBarView.

Parameters:
Return type:

None

class composeui.core.view.RadioGroupView[source]

Bases: ValuesGroupMixin[TValue], View

A group of radio buttons, for one choice among a few values.

__init__(*, is_visible=True, is_enabled=True, renderer=None, value=None, values=NOTHING, value_changed=NOTHING)

Method generated by attrs for class RadioGroupView.

Parameters:
Return type:

None

class composeui.core.view.RecordTableView[source]

Bases: TableView, Generic[RecordT]

A table of records, attrs instances, each a row with a cell per column.

Build it with its records’ type, so a study can save and load them: child(RecordTableView[Room], columns=[Column("name", T("Room"), editable=True)]). columns set the headers and the editable columns. The table formats each field in its cell (str, None as an empty cell): assign new records, not rows.

The user’s edit is parsed into the field’s type with CONVERTER. A cell that doesn’t parse refuses the edit, and the status bar says why. Else record_edited emits the old and the new record while records still holds the old one. Then the new record replaces the old one, unless the callbacks assigned records themselves. Refusing the edit works as with cell_edited (View.refusing).

columns: list[Column]
records: list[RecordT]
record_edited: Signal[RecordT, RecordT]

the user edited a record: the old one, then the new one

property record_type: type

Get the records’ type, from RecordTableView[Room] or a subclass’s base.

column_index(field)[source]

Get the index of the column showing field, e.g. to style its cells.

Raise ValueError when no column shows it.

Parameters:

field (str)

Return type:

int

property selected_record: RecordT | None

Get the first selected record, or None if no row is selected.

property selected_records: list[RecordT]

Get the selected records, as selected_rows lists them.

structure_records(data)[source]

Build records of record_type from their saved data.

Parameters:

data (Any)

Return type:

list[RecordT]

__init__(*, is_visible=True, is_enabled=True, renderer=None, headers=NOTHING, filter_texts=NOTHING, selection_mode=SelectionMode.SINGLE, rows=NOTHING, sortable_columns=NOTHING, filterable_columns=NOTHING, sort_column=None, sort_descending=False, search='', filters=NOTHING, selected_rows=NOTHING, selection_changed=NOTHING, row_activated=NOTHING, editable_columns=NOTHING, cell_edited=NOTHING, cell_widgets=NOTHING, file_texts=NOTHING, cell_clicked=NOTHING, cell_styles=NOTHING, header_groups=NOTHING, row_headers=NOTHING, done_text='Done', warning_text='Warning', error_text='Error', columns=NOTHING, records=NOTHING, record_edited=NOTHING)

Method generated by attrs for class RecordTableView.

Parameters:
Return type:

None

class composeui.core.view.ReferenceLine[source]

Bases: object

A line across a ChartView at a value, e.g. a capacity (“Max: 40”) or now.

It is no series: not in the legend, but labeled beside itself. The chart’s range takes it in, so it shows even away from the data.

value: float

where it crosses its axis: a y, or an x if vertical (a bar chart’s category index)

label: str

shown beside it, e.g. “Max: 40”; empty: none

vertical: bool

whether it stands at an x, across the y axis, rather than lying at a y

color: str | None

its color, as #rrggbb, the same in every theme; None: the theme’s text color

style: LineStyle

dashed by default: told apart from the series, which are solid

__init__(value, label='', vertical=False, color=None, style=LineStyle.DASHED)

Method generated by attrs for class ReferenceLine.

Parameters:
Return type:

None

class composeui.core.view.Router[source]

Bases: View

Pages shown one at a time, picked from a toolbar with an entry per page.

Its page fields are the pages, in toolbar order. It starts on the first page; triggering a page’s action navigates to the page, and only the shown page’s action is checked. Pages can’t be added or removed once built.

current_route: str

the shown page’s route; change it with navigate. Navigation, not study data: never saved, loaded or reset

route_changed: Signal[str]

a different page is shown, by its route

property pages: list[PageView]

Get the pages, in toolbar order.

property current_page: PageView | None

Get the shown page, or None without pages.

page(route)[source]

Get the page on route, or None if no page has it.

Parameters:

route (str)

Return type:

PageView | None

navigate(route)[source]

Show the page on route; raise ValueError if no page has it.

Parameters:

route (str)

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, current_route='', route_changed=NOTHING)

Method generated by attrs for class Router.

Parameters:
Return type:

None

class composeui.core.view.RowCheckBoxView[source]

Bases: FormRowView, CheckBoxMixin

A row of a form with a check box, without a label.

__init__(*, text='', is_checked=False, toggled=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowCheckBoxView.

Parameters:
Return type:

None

class composeui.core.view.RowComboBoxView[source]

Bases: FormRowView, ValuesGroupMixin[TValue]

A row of a form with a drop-down list, without a label.

__init__(*, value=None, values=NOTHING, value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowComboBoxView.

Parameters:
Return type:

None

class composeui.core.view.RowDateInputView[source]

Bases: FormRowView, DateInputMixin

A row of a form with a date field, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, date_format='MM/dd/yyyy', month_names=NOTHING, day_names=NOTHING, pick_text='Pick a date', previous_month_text='Previous month', next_month_text='Next month', value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowDateInputView.

Parameters:
Return type:

None

class composeui.core.view.RowFilePathInputView[source]

Bases: FormRowView, FilePathInputMixin

A row of a form with a file path field, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, has_reload=False, browse_text='Choose a file', reload_text='Reload', partial_folder_text="This folder holds too many items to list them all: type the file's path.", reload_clicked=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowFilePathInputView.

Parameters:
Return type:

None

class composeui.core.view.RowFloatInputView[source]

Bases: FormRowView, FloatInputMixin

A row of a form with a field for a decimal number, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, decimals=None, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowFloatInputView.

Parameters:
Return type:

None

class composeui.core.view.RowFolderPathInputView[source]

Bases: FormRowView, FolderPathInputMixin

A row of a form with a folder path field, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, browse_text='Choose a folder', choose_folder_text='Choose this folder', partial_folder_text="This folder holds too many items to list them all: type the folder's path.", is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowFolderPathInputView.

Parameters:
Return type:

None

class composeui.core.view.RowInputView[source]

Bases: FormRowView, InputMixin

A row of a form with a field for one line of text, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowInputView.

Parameters:
Return type:

None

class composeui.core.view.RowIntInputView[source]

Bases: FormRowView, IntInputMixin

A row of a form with a field for a whole number, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, value=None, minimum=None, maximum=None, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowIntInputView.

Parameters:
Return type:

None

class composeui.core.view.RowRadioGroupView[source]

Bases: FormRowView, ValuesGroupMixin[TValue]

A row of a form with a group of radio buttons, without a label.

__init__(*, value=None, values=NOTHING, value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowRadioGroupView.

Parameters:
Return type:

None

class composeui.core.view.RowSavePathInputView[source]

Bases: FormRowView, SavePathInputMixin

A row of a form with a field of a path to save a file to, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, confirms_overwrite=True, browse_text='Save as', partial_folder_text="This folder holds too many items to list them all: type the file's path.", file_name_text='File name', save_text='Save', replace_question_text='{name} already exists. Replace it?', replace_text='Replace', is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowSavePathInputView.

Parameters:
Return type:

None

class composeui.core.view.RowSliderView[source]

Bases: FormRowView, SliderMixin

A row of a form with a slider, without a label.

__init__(*, value=0, minimum=0, maximum=100, step=1, value_changed=NOTHING, is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowSliderView.

Parameters:
Return type:

None

class composeui.core.view.RowTextAreaView[source]

Bases: FormRowView, TextAreaMixin

A row of a form with a field for several lines of text, without a label.

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', is_visible=True, is_enabled=True, renderer=None, log_message='', log_type=LogType.ERROR, validator=None, checked=NOTHING, has_form_error=False)

Method generated by attrs for class RowTextAreaView.

Parameters:
Return type:

None

class composeui.core.view.SavePathInputMixin[source]

Bases: PathInputMixin

A path to save a file to, typed in the field or picked with the “…” button beside it.

text holds the path as typed, and path reads it as a path, with the first of extensions added if the name has none of them. On Qt and Textual, the button opens the toolkit’s save dialog. The browser can’t give the page a path: on the web, the user types it, and the field has no button. With server_roots, the web’s button lists the server’s folders in them and their files of extensions: a file’s item takes its name, and “Save” picks the folder shown with the name typed. With confirms_overwrite, a file that exists is picked only once the user agrees to replace it, and is_replace_agreed remembers it, for MainView.write_file not to ask again at save time.

extensions: dict[str, tuple[str, ...]]

the file types the dialog offers, by name: {"PDF": (".pdf",)}; the first one is added to a name that has none of them

confirms_overwrite: bool

whether the user agrees to replace a file that exists, before it’s picked

browse_text: str

the name of the “…” button, as a tooltip and a screen reader show it

partial_folder_text: str
file_name_text: str

the texts of the web’s list: the box of the file’s name, and the button saving it

save_text: str
replace_question_text: str

the question before replacing a file, its {name} the file’s, and its answer

replace_text: str
property path: Path | None

Get the path the field holds, the first extension added; None while it’s empty.

On the web, with server_roots, None too for a path typed outside them.

property is_replace_agreed: bool

Tell whether the user agreed in the picker to replace the file path names.

False once the field holds another path, e.g. typed since.

remember_pick(path)[source]

Remember the path picked in the picker: a file that exists, the user agreed to replace.

The renderers call it as the picker picks path, before the field shows it.

Parameters:

path (Path)

Return type:

None

__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, confirms_overwrite=True, browse_text='Save as', partial_folder_text="This folder holds too many items to list them all: type the file's path.", file_name_text='File name', save_text='Save', replace_question_text='{name} already exists. Replace it?', replace_text='Replace')

Method generated by attrs for class SavePathInputMixin.

Parameters:
Return type:

None

class composeui.core.view.SavePathInputView[source]

Bases: SavePathInputMixin, View

A path to save a file to, e.g. a report: typed, or picked from a save dialog.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='', server_roots=(), base_folder=None, parent_folder_text='Parent folder', cancel_text='Cancel', unreadable_folder_text="This folder can't be read.", path_picked=NOTHING, extensions=NOTHING, confirms_overwrite=True, browse_text='Save as', partial_folder_text="This folder holds too many items to list them all: type the file's path.", file_name_text='File name', save_text='Save', replace_question_text='{name} already exists. Replace it?', replace_text='Replace')

Method generated by attrs for class SavePathInputView.

Parameters:
Return type:

None

class composeui.core.view.SelectionMode[source]

Bases: Enum

How many of a table’s rows the user can select.

SINGLE = 1

one row at most: selecting another row replaces it

MULTIPLE = 2

any number of rows: selecting a row adds it, and selecting it again removes it

class composeui.core.view.SeparatorAction[source]

Bases: View

A line between two groups of entries in a menu or a toolbar.

__init__(*, is_visible=True, is_enabled=True, renderer=None)

Method generated by attrs for class SeparatorAction.

Parameters:
Return type:

None

class composeui.core.view.Series[source]

Bases: object

A curve of a ChartView: its points, x against y, under name in the legend.

A point whose x or y is NaN is not drawn: the curve has a gap there.

name: str

the legend’s entry

x: list[float]
y: list[float]
kind: ChartKind | None

how it is drawn, as a line or dots; None: as its chart’s kind

color: str | None

its color, as #rrggbb, the same in every theme, e.g. a logo’s or a code’s; None: the backend’s theme picks it

fill: bool

whether the area between its line and 0 is filled with its color, e.g. a shape

step: bool

whether its line holds each value until the next point, in steps, e.g. the jobs running over time; with fill, a step area. Dots are drawn as they are

classmethod bars(name, values)[source]

Make a BAR chart’s series: a bar per value, in its chart’s categories in order.

Parameters:
Return type:

Series

__init__(name, x, y, kind=None, color=None, fill=False, step=False)

Method generated by attrs for class Series.

Parameters:
Return type:

None

class composeui.core.view.SidebarView[source]

Bases: View

A column of views beside the pages, shown whatever the page, e.g. a form creating a record.

Make it a field of the main view, not of its router, rather than repeat a view on each page. Its view fields are its content, laid out in a column on the window’s left. Qt docks it, and Textual shows it left of the scrolling content. The web shows a column left of the pages, and on a phone a drawer that a button in the header opens. The user retracts it to a narrow strip, and back, with a button (is_expanded).

title: str

a heading above the content; none while empty

toggle_text: str

the button retracting and expanding the sidebar (opening the drawer on a phone), for screen readers and as its tooltip

is_expanded: bool

whether the content shows, else a narrow strip with the button bringing it back. Layout, not study data: never saved, loaded or reset

toggled: Signal[bool]

the user retracted or expanded the sidebar; not emitted when is_expanded is set in code

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', toggle_text='Sidebar', is_expanded=True, toggled=NOTHING)

Method generated by attrs for class SidebarView.

Parameters:
Return type:

None

class composeui.core.view.SliderMixin[source]

Bases: object

The fields of a slider: its value, its range and its step.

value: int

from minimum to maximum by step; shown at its nearest step (see position)

minimum: int
maximum: int

the last step, if maximum - minimum is not a whole number of steps, falls short of it

step: int
value_changed: Signal[int]

the user moved the handle; not emitted when value is set in code

static last_position(minimum, maximum, step)[source]

Get the steps from minimum to the last one at most maximum; 0 if none.

Parameters:
Return type:

int

static position(value, minimum, maximum, step)[source]

Get the handle’s position, in steps from minimum: value’s nearest, in range.

Takes them all, as a renderer refreshes one before the view holds the new value.

Parameters:
Return type:

int

__init__(*, value=0, minimum=0, maximum=100, step=1, value_changed=NOTHING)

Method generated by attrs for class SliderMixin.

Parameters:
Return type:

None

class composeui.core.view.SliderView[source]

Bases: SliderMixin, View

A whole number picked by dragging a handle, e.g. a number of workers.

Its value is shown beside the track, so that its row is no taller than a field’s.

__init__(*, is_visible=True, is_enabled=True, renderer=None, value=0, minimum=0, maximum=100, step=1, value_changed=NOTHING)

Method generated by attrs for class SliderView.

Parameters:
Return type:

None

class composeui.core.view.Sort[source]

Bases: object

The order of a table’s rows: by the values of the column named column.

column: str
descending: bool
__init__(column, descending=False)

Method generated by attrs for class Sort.

Parameters:
Return type:

None

class composeui.core.view.SourceColumn[source]

Bases: object

A column of a TableSource: the values it holds, under header.

name: str

the name the source knows the column by, e.g. a record’s field or a query’s column

header: str
type: Any

the type of its values, which sets how they sort and filter (see column_kind)

__init__(name, header, type=<class 'str'>)

Method generated by attrs for class SourceColumn.

Parameters:
Return type:

None

class composeui.core.view.SourceTableView[source]

Bases: View

A large table, whose rows a source keeps and the table reads a window at a time.

source (a TableSource) sorts, searches and filters the rows. For each sort_column, sort_descending, search and filters, the view asks it once for the ids of the rows shown, in order, and keeps only these ids (in an array when they are integers). rows gives the cells of the rows at some positions, formatted as column_formats says. It reads them from the source by windows of SOURCE_TABLE_WINDOW rows, and keeps the values of the last SOURCE_TABLE_CACHE rows. The source’s changed makes it read the order and the cells again. A source of SOURCE_TABLE_JOB_ROWS rows or more orders them in a job on Qt and Textual (is_ordering), and ordered emits once the rows have their new order.

The columns are the source’s, by name: sort_column, the keys of filters and of column_formats. A filter is the text the user typed (see parse_filter), and the search looks in the text columns. The user selects rows as selection_mode allows: selected_ids holds their ids, and selection_changed emits them when the user changes them. The ids the app sets are kept as they are. A new order (a search, a filter, the source’s changed) drops the selected rows it hides, and selection_changed emits. row_activated emits a row’s id (a double click, Enter).

A study saves the settings and selected_ids, as JSON values (e.g. integers), and never the rows or the source: the app gives the view its source again.

Each backend scrolls the rows, drawing only those around the view. A click on a column’s header sorts by it (sort_by). A click on a row selects it (select_at); on Qt and Textual, Shift extends the selection (extend_to), and a double click or Enter activates the row (activate_at). Ctrl+C copies the selected rows to the clipboard (selection_text). Export CSV writes the rows shown to a file (export_csv): Qt’s context menu, Textual’s key e, the web’s link under the rows.

While filterable_columns names columns, a filter bar shows above the rows, as a TableView’s: a search, “+ Filter” opening an editor of a column and a value, and the filters as chips. It counts the rows shown while some are hidden (count_text).

source: TableSource[Any] | None
column_formats: dict[str, str]

the format of each column’s values, by column name (e.g. ".6g"): format’s

texts: dict[str, str]

the text the web shows (see SOURCE_TABLE_TEXTS)

filter_texts: dict[str, str]

the text of the filter bar, by what it’s for (see FILTER_TEXTS)

filterable_columns: list[str]

the columns the user filters in the table’s bar, by name: none hides the bar

export_filename: str

the name Export CSV offers for the file; the app’s, not a study’s

selection_mode: SelectionMode
sort_column: str | None
sort_descending: bool
search: str

text the shown rows contain in a text column, ignoring case

filters: dict[str, str]

the filters by column name, as typed (see parse_filter)

selected_ids: list[Any]
selection_changed: Signal[list[Any]]
row_activated: Signal[Any]
ordered: Signal

the rows shown have a new order, e.g. to show row_count: a sort, a search, a filter, the source’s change

property headers: list[str]

Get the headers of the source’s columns, in its order.

property column_names: list[str]

Get the names of the source’s columns, in its order.

property row_count: int

Get the number of rows shown: the rows the search and the filters pass.

sort_by(column)[source]

Sort as a click on the column’s header does: ascending, descending, then not.

The source orders the rows once, for the column and the direction together.

Parameters:

column (str)

Return type:

None

property count_text: str

Count the rows shown, while the search or the filters hide some: else “”.

E.g. “1,234 of 1,000,000”, in filter_texts’ words.

filter_error(column, text)[source]

Say why text can’t filter column, translated; None if it can.

Parameters:
Return type:

str | None

filter_takes_pattern(column)[source]

Tell whether a regular expression filters column: a text column.

Parameters:

column (str)

Return type:

bool

filter_placeholder(column, *, is_pattern=False)[source]

Hint at what filters column, translated: a regular expression, or else text.

Parameters:
Return type:

str

filter_chip(column)[source]

Show the filter of column as its chip does: its header, then the text typed.

Parameters:

column (str)

Return type:

str

header(column)[source]

Get the header of the source’s column column, translated.

Parameters:

column (str)

Return type:

str

selection_text()[source]

Get the selected rows as Ctrl+C copies them: tab-separated text, a line per row.

The rows in their order, the cells as the table shows them, without the headers, as a spreadsheet takes them. A tab or a line break in a cell is a space. The rows are read from the source a window at a time, outside the table’s cache.

Return type:

str

csv_chunks()[source]

Get the rows shown as CSV, in pieces: the headers, then a window of rows each.

The rows in their order, each value in full, not as column_formats shows it: None as an empty cell, an enum by its value, a date as ISO. The order is the one shown at the call: a new order, while the pieces are read, changes none of them. The rows are read from the source a window at a time, outside the table’s cache.

Return type:

Iterator[str]

export_csv(path)[source]

Write the rows shown to the CSV file path, in UTF-8, as csv_chunks gives them.

In an app, a job writes them, the app staying responsive, and the status bar says when it’s done, or why it failed. Else they are written before the call returns.

Parameters:

path (Path)

Return type:

None

is_selected(row_id)[source]

Tell whether the row row_id is selected.

Parameters:

row_id (Any)

Return type:

bool

select_at(position)[source]

Select the row at position as the user’s click does, and say so if it changed.

One row at most selects it; any number of rows add it, or remove it if selected.

Parameters:

position (int)

Return type:

None

extend_to(position)[source]

Add the rows from the one selected last to position, as a Shift+click does.

One row at most, or none selected last: as select_at.

Parameters:

position (int)

Return type:

None

activate_at(position)[source]

Emit row_activated with the id of the row at position, as a double click.

Parameters:

position (int)

Return type:

None

ids(start, stop)[source]

Get the ids of the rows shown from position start to stop (excluded).

Parameters:
Return type:

list[Any]

rows(start, stop)[source]

Get the id and the formatted cells of the rows shown from start to stop.

A row gone from the source since the order was read has empty cells, until its changed reads the order again.

Parameters:
Return type:

list[tuple[Any, list[str]]]

property total: int

Get the number of the source’s rows, before the search and the filters.

property is_ordering: bool

Tell whether a job is ordering the rows, the old order shown meanwhile.

__init__(*, is_visible=True, is_enabled=True, renderer=None, source=None, column_formats=NOTHING, texts=NOTHING, filter_texts=NOTHING, filterable_columns=NOTHING, export_filename='table.csv', selection_mode=SelectionMode.SINGLE, sort_column=None, sort_descending=False, search='', filters=NOTHING, selected_ids=NOTHING, selection_changed=NOTHING, row_activated=NOTHING, ordered=NOTHING)

Method generated by attrs for class SourceTableView.

Parameters:
Return type:

None

class composeui.core.view.SplitterView[source]

Bases: View

Its view fields in panes, side by side, the user dragging the border between two.

E.g. a study tree beside its result. Each pane starts with its share of the width, set by its field’s STRETCH metadata as in a HorizontalView. The share is at least 1: every pane takes some width. sizes holds the shares. The user changes them by dragging a border, or with the arrow keys on it, and never shrinks a pane to nothing. A hidden pane leaves its width to the others. On the web, a splitter narrower than 42rem stacks its panes, as a row does.

A subclass that sets orientation = Orientation.VERTICAL lays out the panes one above the other instead, e.g. a chart above its table. The panes then share its height: the window’s spare height on Qt, a set height elsewhere (24 rows on Textual, 32rem on the web). Each pane scrolls within its share.

orientation: ClassVar[Orientation] = 1

how the panes are laid out: side by side, or one above the other

sizes: list[int]

each pane’s share of the width (the height, vertical), in order; once the user drags a border, the panes shown in percent of theirs. Layout, not study data: never saved, loaded or reset

border_text: str

names a border between two panes for a screen reader, on the web

resized: Signal[list[int]]

the user dragged a border (once dropped) or moved one with a key, giving the new sizes; not emitted when sizes is set in code

property panes: list[View]

Get the panes’ views, in order.

shares_of(lengths)[source]

Get the sizes of panes lengths wide (tall, vertical), as the user dragged them.

In any unit: a pane shown gets its percent of the shown panes’ length, at least 1; a hidden one keeps its share.

Parameters:

lengths (Sequence[float])

Return type:

list[int]

__init__(*, is_visible=True, is_enabled=True, renderer=None, sizes=NOTHING, border_text='Resize the panes', resized=NOTHING)

Method generated by attrs for class SplitterView.

Parameters:
Return type:

None

class composeui.core.view.StatusBar[source]

Bases: View

A line at the bottom of the window that shows a short message to the user.

show_message shows a message for timeout seconds.

message: str
message_changed: Signal[str]
timeout: float
show_message(message)[source]

Show message for timeout seconds.

With a timeout of 0, the message is not dismissed automatically.

Parameters:

message (str)

Return type:

None

clear_message()[source]

Remove the message from the status bar.

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None, message='', message_changed=NOTHING, timeout=3.0, timer=None)

Method generated by attrs for class StatusBar.

Parameters:
Return type:

None

composeui.core.view.T

alias of TranslatedText

class composeui.core.view.TabPage[source]

Bases: View

A tab of a TabView: its title on the tab, its view fields its content, in a column.

Hidden, its tab is too; disabled, its tab can’t be picked.

title: str
__init__(*, is_visible=True, is_enabled=True, renderer=None, title='')

Method generated by attrs for class TabPage.

Parameters:
Return type:

None

class composeui.core.view.TabView[source]

Bases: View

Views shown a tab at a time, picked from a row of tabs, e.g. a record’s details and history.

Its TabPage fields are the tabs, in order; it starts on the first. Distinct from pages: tabs live inside a page or a form, and have no address of their own.

current_index: int

the tab shown, counted from 0. Navigation, not study data: never saved, loaded or reset

current_changed: Signal[int]

the user picked another tab, by its index; not emitted when current_index is set in code

property tabs: list[TabPage]

Get the tabs, in order.

property current_tab: TabPage | None

Get the tab shown, or None without tabs.

__init__(*, is_visible=True, is_enabled=True, renderer=None, current_index=0, current_changed=NOTHING)

Method generated by attrs for class TabView.

Parameters:
Return type:

None

class composeui.core.view.TableMixin[source]

Bases: object

A table of text: the app formats each cell itself.

Each row has one cell per header. Assign new lists to update the table: changing a list in place doesn’t reach the renderer. The user selects rows as selection_mode allows. selected_rows holds their indexes, and selection_changed emits them when the user changes them. New rows keep each selected row selected when they hold it exactly once, wherever it moved, and drop it otherwise. row_activated emits a row’s index when the user opens it: a double click on a cell that doesn’t edit or click, or Enter, which also selects it on Textual and the web.

The user edits the cells of the columns in editable_columns (none by default). cell_edited emits the row, the column and the new text while rows still holds the old text. Then the edit replaces its row in rows, and keeps the selection. To refuse or reformat the edit, or to show what it changed elsewhere, assign rows from the callback instead. The table shows these rows, and doesn’t apply the edit on top. The edited row stays selected when they hold it as edited (e.g. renamed, then sorted), or else as it was (the edit refused). Raising EditRefusedError refuses the edit too, and the rows stay as they are, e.g. when the model refused the new text and changed nothing. A RefusedError caught by View.refusing in the callback does the same.

A column of cell_widgets shows a widget in each cell (see CellWidget). A check box, a combobox or a file path edits the cell. A button or a link emits cell_clicked with its row and column. A check box column’s header can check or uncheck every shown row (check_all), and each change is emitted as the user’s edit.

The user sorts the rows by a column of sortable_columns (sort_column, ascending unless sort_descending). The user also searches the text of filterable_columns (search), and filters each of them (filters, the text typed, see parse_filter). The table shows shown_rows, which these compute. The indexes that the table emits or takes stay those of rows, whatever the order. A search or a filter that hides a selected row deselects it, and selection_changed emits. New rows keep the order, the search and the filters.

Each cell of cell_styles looks as its CellStyle says: a background color, grayed and never edited, a mark, spanning the rows under it. Assign the styles with the rows they describe. They are by index in rows, so new rows keep the styles of the rows that were at their indexes. header_groups put a header over several columns, on a row above theirs. row_headers put a header before each row, e.g. the keys of a small key/value table of results.

headers: list[str]
filter_texts: dict[str, str]

the filter bar’s text, by what it’s for (see FILTER_TEXTS)

selection_mode: SelectionMode
rows: list[list[str]]
sortable_columns: list[int]
filterable_columns: list[int]
sort_column: int | None
sort_descending: bool
search: str

text the shown rows contain in a filterable column, ignoring case

filters: dict[int, str]

the filters by column, as typed (see parse_filter)

selected_rows: list[int]
shown_rows: list[int]

the indexes in rows of the rows shown, in their order: computed, never set

selection_changed: Signal[list[int]]
row_activated: Signal[int]

the user opened a row (a double click, Enter): its index in rows

editable_columns: list[int]
cell_edited: Signal[int, int, str]
cell_widgets: dict[int, CellWidget]

the widget in each cell of a column, by column: the app’s setup, not study data

file_texts: dict[str, str]

the texts of the web’s list of the server’s files, for a file path cell with server_roots, by what they’re for (see FILE_TEXTS)

cell_clicked: Signal[int, int]

the user clicked a button or a link cell: its row and its column

cell_styles: dict[tuple[int, int], CellStyle]

how each cell looks, by its index in rows and its column (see CellStyle): the app’s to set with the rows, not study data

header_groups: list[HeaderGroup]

headers over several columns, on a row above headers

row_headers: list[str]

a header before each row, by its index in rows; none shown while empty

done_text: str

each NodeMark’s name, for screen readers (web) and as a tooltip (Qt)

warning_text: str
error_text: str
sort_by(column)[source]

Sort as a click on the column’s header does: ascending, descending, then not.

Parameters:

column (int)

Return type:

None

filter_error(column, text)[source]

Say why text can’t filter column, translated; None if it can.

Parameters:
Return type:

str | None

filter_takes_pattern(column)[source]

Tell whether a regular expression filters column: a text column.

Parameters:

column (int)

Return type:

bool

filter_placeholder(column, *, is_pattern=False)[source]

Hint at what filters column, translated: a regular expression, or else text.

Parameters:
Return type:

str

filter_chip(column)[source]

Show a filter as its chip does: its column’s header, then the text typed.

Apart, as a label and its value: the header isn’t part of what’s typed. A regular expression without its slashes: “Room matches Room [1-3]”.

Parameters:

column (int)

Return type:

str

mark_text(mark)[source]

Get the name of mark in the main view’s language.

Parameters:

mark (NodeMark)

Return type:

str

cell_style(row, column)[source]

Get how a cell looks, by its index in rows: plain unless cell_styles say.

Parameters:
Return type:

CellStyle

cell_widget(row, column)[source]

Get the widget of a cell, by its index in rows: its row’s kind’s for path_by.

Parameters:
Return type:

CellWidget | None

is_cell_editable(row, column)[source]

Tell whether the user edits a cell: in editable_columns, and not disabled.

Parameters:
Return type:

bool

header_group(column)[source]

Get the group of header_groups over column, if any.

Parameters:

column (int)

Return type:

HeaderGroup | None

shown_cell_styles()[source]

Get how the shown cells look, by position in shown_rows and column.

A cell spans the shown rows right under it that follow it in rows, up to its row_span. Its style here says how many rows it spans as shown.

Return type:

dict[tuple[int, int], CellStyle]

is_checked(row, column)[source]

Tell whether a check box cell is checked: its text is “true”, ignoring case.

Parameters:
Return type:

bool

column_checked(column)[source]

Tell whether a check box column’s shown cells are all checked, none, or some (None).

Its disabled cells don’t count: the check-all box doesn’t change them.

Parameters:

column (int)

Return type:

bool | None

check_all(column, *, is_checked)[source]

Check or uncheck a check box column’s shown cells, as its header’s box does.

Each cell changing is the user’s edit: cell_edited emits it, and the edit applies unless its callbacks assigned rows or refused it. A disabled cell stays as it is.

Parameters:
Return type:

None

emit_cell_edited(row, column, text)[source]

Emit cell_edited for the user’s edit, rows still holding the old text.

Rows its callbacks assign keep the edited row selected as TableMixin says. Renderers call it; applying the edit afterwards is theirs.

Parameters:
Return type:

None

loadable(name, value)[source]

Get the part of a saved sort or filters (name) the table’s columns still take.

Parameters:
Return type:

Any

__init__(*, headers=NOTHING, filter_texts=NOTHING, selection_mode=SelectionMode.SINGLE, rows=NOTHING, sortable_columns=NOTHING, filterable_columns=NOTHING, sort_column=None, sort_descending=False, search='', filters=NOTHING, selected_rows=NOTHING, selection_changed=NOTHING, row_activated=NOTHING, editable_columns=NOTHING, cell_edited=NOTHING, cell_widgets=NOTHING, file_texts=NOTHING, cell_clicked=NOTHING, cell_styles=NOTHING, header_groups=NOTHING, row_headers=NOTHING, done_text='Done', warning_text='Warning', error_text='Error')

Method generated by attrs for class TableMixin.

Parameters:
Return type:

None

class composeui.core.view.TableSource[source]

Bases: Protocol[IdT]

The rows of a large table, each known by its id, which the table reads in windows.

The source sorts, searches and filters its rows itself (e.g. in SQL), so that a table never reads them all: it asks once for the ids of the rows it shows, in order, then for the cells of the rows on screen. changed says the rows changed, so the table reads them again. An id is a hashable value that stays its row’s own while the rows change (e.g. a primary key), so that a table’s selection stays on its rows. ListSource is a source of records in memory.

property columns: Sequence[SourceColumn]

Get the columns, in the order a table shows them.

property changed: Signal

Get the signal emitted once the rows changed.

count()[source]

Get the number of rows, before any search or filter.

Return type:

int

ordered_ids(sort, search, filters)[source]

Get the ids of the rows that search and filters pass, in the order of sort.

search keeps the rows where the cell of a text column contains it, ignoring case; a blank one keeps every row. filters holds a Filter by column name (see parse_filter), which a cell passes as Filter.matches says. sort orders the rows by a column’s values, text ignoring case, the empty cells last in both orders and equal cells in the source’s order. Without it, the rows keep the source’s order. Raise ValueError for a column the source doesn’t have.

Parameters:
Return type:

Sequence[IdT]

cells(ids, columns)[source]

Get the values of the rows ids in columns, by id; an id now gone is left out.

Raise ValueError for a column the source doesn’t have.

Parameters:
Return type:

Mapping[IdT, Sequence[Any]]

__init__(*args, **kwargs)
class composeui.core.view.TableView[source]

Bases: TableMixin, View

A table of text that the app formats cell by cell (see TableMixin).

__init__(*, is_visible=True, is_enabled=True, renderer=None, headers=NOTHING, filter_texts=NOTHING, selection_mode=SelectionMode.SINGLE, rows=NOTHING, sortable_columns=NOTHING, filterable_columns=NOTHING, sort_column=None, sort_descending=False, search='', filters=NOTHING, selected_rows=NOTHING, selection_changed=NOTHING, row_activated=NOTHING, editable_columns=NOTHING, cell_edited=NOTHING, cell_widgets=NOTHING, file_texts=NOTHING, cell_clicked=NOTHING, cell_styles=NOTHING, header_groups=NOTHING, row_headers=NOTHING, done_text='Done', warning_text='Warning', error_text='Error')

Method generated by attrs for class TableView.

Parameters:
Return type:

None

class composeui.core.view.TextAreaMixin[source]

Bases: _InputView

The fields of a field for several lines of text: its text and its signals.

text: str
__init__(*, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='')

Method generated by attrs for class TextAreaMixin.

Parameters:
Return type:

None

class composeui.core.view.TextAreaView[source]

Bases: TextAreaMixin, View

A field where the user types several lines of text, for example a comment.

editing_finished is emitted when the field loses the focus after a change: Enter starts a new line.

__init__(*, is_visible=True, is_enabled=True, renderer=None, placeholder='', editing_finished=NOTHING, text_changed=NOTHING, text_edited=NOTHING, text='')

Method generated by attrs for class TextAreaView.

Parameters:
Return type:

None

class composeui.core.view.TextStyle[source]

Bases: object

How a part of a console’s line looks, as its ANSI escape codes ask (see ConsoleView).

Colors are “#rrggbb”, None for the console’s own.

foreground: str | None
background: str | None
is_bold: bool
is_italic: bool
is_underlined: bool
__init__(foreground=None, background=None, is_bold=False, is_italic=False, is_underlined=False)

Method generated by attrs for class TextStyle.

Parameters:
  • foreground (str | None)

  • background (str | None)

  • is_bold (bool)

  • is_italic (bool)

  • is_underlined (bool)

Return type:

None

class composeui.core.view.ToolBar[source]

Bases: View

A row of actions at the top of the window, for the ones the user runs most.

Its ActionView and SeparatorAction fields are its entries, in order; a field of the main view, docked by the window. title names it, e.g. for a screen reader.

title: str
__init__(*, is_visible=True, is_enabled=True, renderer=None, title='')

Method generated by attrs for class ToolBar.

Parameters:
Return type:

None

class composeui.core.view.TreeNode[source]

Bases: object

A node of a TreeView: its text, and the nodes under it.

Its key, its label unless given, tells it apart from its siblings. The tree knows a node by its path (see TreeView). So nodes under different parents may share a key, e.g. a “Pipes” folder under each building.

label: str
children: tuple[TreeNode, ...]
key: str
icon: str | None

an image file’s path, before the label (not on Textual); set by the app, not study data: never saved or loaded, as ActionView.icon

mark: NodeMark | None
is_bold: bool
is_underlined: bool
__init__(label, children=(), key=NOTHING, icon=None, mark=None, is_bold=False, is_underlined=False)

Method generated by attrs for class TreeNode.

Parameters:
Return type:

None

composeui.core.view.TreePath

a node of a TreeView, by the keys from its top-level node down to it

alias of tuple[str, …]

class composeui.core.view.TreeView[source]

Bases: View

Nodes in a tree, e.g. a site’s buildings, their floors and their rooms.

A node is known by its path, the keys from its top-level node down to it (see TreeNode). The user expands and collapses the nodes that have children. expanded holds the paths of the expanded nodes, and toggled emits a node’s path and whether it is now expanded. The user selects one node: selected holds its path, and selection_changed emits it. Assign new nodes to update the tree: they keep the paths of expanded and selected still in them, and drop the others.

nodes: list[TreeNode]
expanded: list[tuple[str, ...]]
__init__(*, is_visible=True, is_enabled=True, renderer=None, nodes=NOTHING, expanded=NOTHING, selected=None, toggled=NOTHING, selection_changed=NOTHING, done_text='Done', warning_text='Warning', error_text='Error')

Method generated by attrs for class TreeView.

Parameters:
Return type:

None

selected: tuple[str, ...] | None
toggled: Signal[tuple[str, ...], bool]

the user expanded (True) or collapsed a node; not emitted when expanded is set in code

selection_changed: Signal[tuple[str, ...]]

the user selected a node; not emitted when selected is set in code

done_text: str

each NodeMark’s name, for screen readers (web) and as a tooltip (Qt)

warning_text: str
error_text: str
mark_text(mark)[source]

Get the name of mark in the main view’s language.

Parameters:

mark (NodeMark)

Return type:

str

node(path)[source]

Get the node at path, e.g. the selected one’s label; KeyError if none is there.

Parameters:

path (tuple[str, ...])

Return type:

TreeNode

expanded_with(path, *, is_expanded)[source]

Get expanded with the node at path expanded or collapsed, the others kept.

Parameters:
Return type:

list[tuple[str, …]]

class composeui.core.view.TypedFormDialogView[source]

Bases: OkCancelDialogView, Generic[FormT]

A modal holding a form, e.g. editing a record from its Edit button, with OK and Cancel.

Pass a form, or give a subclass its typed form default. Its text shows above it. OK can’t be pressed while a check of the form fails (is_accept_enabled). Accepting runs every check first, even one the user hasn’t triggered yet, and the dialog stays open while one fails. The answer comes through accepted or rejected. The form keeps its values, for the app to read, or to fill before opening the dialog again.

form: FormT
property is_valid: bool

Whether no check shown fails, the form’s or the dialog’s own.

open()[source]

Show the dialog, OK as the form’s checks last left it.

Return type:

None

check()[source]

Run every check now: the form’s, then the dialog’s own.

Return type:

None

property content: FormT

Get the view the dialog shows: its form.

__init__(*, is_visible=True, is_enabled=True, renderer=None, title='', text='', kind=DialogKind.MESSAGE, accept_text='OK', reject_text='Cancel', accepted=NOTHING, rejected=NOTHING, is_accept_enabled=True, log_view=NOTHING, accepting=NOTHING, form)

Method generated by attrs for class TypedFormDialogView.

Parameters:
Return type:

None

composeui.core.view.Validator

A zero-argument check: reads whatever state it needs itself (e.g. self.text via a bound method) and returns an error message, or None if it passes.

alias of Callable[[], str | None]

class composeui.core.view.ValuesGroupMixin[source]

Bases: Generic[TValue]

The fields of one choice among values: the choices by label, and the value selected.

value is None, or one of values; new values without it clear it. None selects nothing, unless None is one of values, such as a filter’s “All”: then it selects that choice, shown and saved as any other.

value: TValue | None
values: dict[str, TValue]
value_changed: Signal[TValue | None]
property options: list[tuple[str, str]]

Get each of values as its key (see serialize_value) and its label, in order.

serialize_value()[source]

Serialize value as its key: its label could be in another language on load.

None for nothing selected: a None value that isn’t one of values.

Return type:

str | None

deserialize_value(key)[source]

Look up a key previously produced by serialize_value back into a TValue.

A label is accepted too, as older state files saved it.

Parameters:

key (str | None)

Return type:

TValue | None

__init__(*, value=None, values=NOTHING, value_changed=NOTHING)

Method generated by attrs for class ValuesGroupMixin.

Parameters:
  • value (TValue | None)

  • values (dict[str, TValue])

  • value_changed (Signal[TValue | None])

Return type:

None

class composeui.core.view.VerticalView[source]

Bases: View

Its view fields laid out one above the other, in a column, as tall as their content.

A page is already a column: this one is for a column inside a HorizontalView, e.g. a table above its buttons, next to another table.

__init__(*, is_visible=True, is_enabled=True, renderer=None)

Method generated by attrs for class VerticalView.

Parameters:
Return type:

None

class composeui.core.view.View[source]

Bases: object

The base of every view: a part of the UI that a renderer shows on a backend.

Setting a field of a view pushes the change to its renderer. is_visible shows or hides the view, and is_enabled enables or disables it.

default_stretch: ClassVar[int] = 1

its share of a HorizontalView’s width when its field sets no STRETCH

is_visible: bool
is_enabled: bool
renderer: Renderer[Any, Any] | RendererContainer[Any] | None
tr(text)[source]

Translate text, as written in the code, into the main view’s language.

A view that keeps the translation, in a field or in a list or dict of one, shows it in the next language that MainView.set_language sets. Formatted text follows too.

Parameters:

text (str)

Return type:

TranslatedText

refusing(message)[source]

Show the model’s refusal of the block’s change in the main view’s status bar.

message shows the RefusedError’s message, translated (unless tr gave it), as {error}, e.g. self.tr("Can't add a room: {error}"). In a cell_edited callback, the edit is refused too: the cell keeps its old text.

Parameters:

message (str)

Return type:

Iterator[None]

retranslate()[source]

Update text that tr alone doesn’t follow, e.g. built from other text.

Called once while the view is built, before the rest of __attrs_post_init__. Then MainView.set_language calls it on every view once their text is translated, children before their parent.

Return type:

None

property children_views: list[View]

Get the views in the fields of this view, in order.

render(renderer_type)[source]
Parameters:

renderer_type (RendererType)

Return type:

None

__init__(*, is_visible=True, is_enabled=True, renderer=None)

Method generated by attrs for class View.

Parameters:
Return type:

None

composeui.core.view.as_pattern(text)[source]

Write a regular expression as a text column’s filter: between slashes.

Parameters:

text (str)

Return type:

str

composeui.core.view.child(cls, /, *args, **kwargs)[source]

Get a view field’s default: a cls view built with these arguments, one per view.

E.g. add: ButtonView = child(ButtonView, text=T("Add")). The arguments are copied for each view built, so a list among them is never shared.

Parameters:
  • cls (Callable[[~_P], _ViewT])

  • args (~_P)

  • kwargs (~_P)

Return type:

_ViewT

composeui.core.view.define_view(cls: _ClassT) → _ClassT[source]
composeui.core.view.define_view(cls: None = None, **kwargs: Any) → Callable[[_ClassT], _ClassT]

Define a view class: an attrs class whose field changes reach its renderer.

Use it as @define_view, or as @define_view(...) with keyword arguments for attrs.define. The fields are keyword-only. Hooks of its own (on_setattr) run after the validators, before the renderer hears the change.

Parameters:
  • cls (_ClassT | None)

  • kwargs (Any)

Return type:

_ClassT | Callable[[_ClassT], _ClassT]

composeui.core.view.find_in_lines(lines, query)[source]

Find query in a console’s lines, as its search does: plain text, any case.

Get each match’s line, start and end, in order; none for an empty query.

Parameters:
Return type:

list[tuple[int, int, int]]

composeui.core.view.format_date(value, date_format)[source]

Show value as date_format says, e.g. “18/10/2026” for “dd/MM/yyyy”.

A format lacking a part, e.g. a catalog’s mistake, shows the date as ISO 8601 does.

Parameters:
Return type:

str

composeui.core.view.notify_renderer(instance, attribute, value)[source]

Push the new value of a view’s field to its renderer, if the value changed.

The on_setattr hook of every view field (see define_view). Return value.

Parameters:
Return type:

Any

composeui.core.view.parse_date(text, date_format)[source]

Read a date typed as date_format says, or as ISO 8601 (2026-10-18) whatever it is.

The day and the month may have a single digit (“1/2/2026”), and a separator ending the format may be left out (“18.10.2026” for “dd.MM.yyyy.”). Raises ValueError for anything else, or a day the month doesn’t have.

Parameters:
  • text (str)

  • date_format (str)

Return type:

date

composeui.core.view.replace_cell(rows, row, column, text)[source]

Return rows with text in a cell, as new lists: a row short of it is filled with “”.

Parameters:
Return type:

list[list[str]]