util.actionDialog module

A general-purpose popup dialog (ActionDialog) that renders a small, dependency-free subset of HTML – bold/italic/underline, line breaks, and <a id="..."> action links – inside a tk.Text widget, and invokes a caller-supplied callback when an action link is clicked. Motivating use case: a validation-error popup (eg: for decorators.py’s error tag) that lists an object’s errors, one per line, each with inline “Fix” / “Delete” / “Ignore” links – without needing a full HTML rendering dependency (eg: tkinterweb) or a hand-rolled tag/click-binding scheme every time such a popup is needed.

Created on Sep 18, 2026

Code author: Rob Kremer <robkremer@me.com>

util.actionDialog.ActionCallback

A zero-argument callback invoked when an action link is clicked.

alias of Callable[[], None]

util.actionDialog._STYLE_TAGS = {'b': 'bold', 'em': 'italic', 'i': 'italic', 'strong': 'bold', 'u': 'underline'}

Maps the small subset of supported inline HTML tags to the tk.Text tag name that renders them.

class util.actionDialog._RichTextParser

Bases: HTMLParser

Parses the small HTML subset ActionDialog understands – <b>/ <strong>, <i>/<em>, <u>, <br>, <ol>/<ul>/ <li>, plain text, and <a id="...">label</a> action links – into a flat list of (text, styleTags, actionId) runs.

Anything outside that subset (unknown tags, attributes other than id on <a>) is silently ignored rather than raising: this is meant for small, hand-written strings composed by the caller, not for rendering arbitrary or untrusted HTML documents.

__init__() → None

Initialize and reset this instance.

If convert_charrefs is True (the default), all character references are automatically converted to the corresponding Unicode characters.

runs: list[tuple[str, tuple[str, ...], str | None]]

Accumulated (text, styleTags, actionId) runs, in document order.

_styleStack: list[str]
_linkId: str | None
_listStack: list[dict[str, int | str]]

One entry per currently-open <ol>/<ul>, innermost last: {“kind”: “ol”|”ul”, “index”: int}.

_atLineStart: bool

Whether the run most recently emitted ended with a newline (or nothing has been emitted yet).

_emit(text: str, actionId: str | None = None) → None
Parameters:
  • text (str)

  • actionId (Optional[str])

handle_starttag(tag: str, attrs: list[tuple[str, str | None]]) → None
Parameters:
  • tag (str)

  • attrs (list[tuple[str, Optional[str]]])

handle_endtag(tag: str) → None
Parameters:

tag (str)

handle_data(data: str) → None
Parameters:

data (str)

class util.actionDialog.ActionDialog(parent: Wm, title: str, html: str, actions: dict[str, Callable[[], None]] | None = None, *, closeOnAction: bool = True, width: int = 80, maxHeight: int = 40)

Bases: Toplevel

A general-purpose popup dialog that renders a small subset of HTML (bold, italic, underline, line breaks, ordered/unordered lists, and <a id="..."> action links) and invokes a caller-supplied callback when an action link is clicked.

Typical use – eg: from decorators.py’s error-tag popup – is to build one html string per object with an <li> per validation error and a Fix/Ignore/Delete action link at the end of each item, and a matching actions dict mapping each link’s id to the handler that should run when it’s clicked. <li> items need no <br> between them – each one starts its own line automatically, numbered if inside an <ol> or bulleted otherwise:

ActionDialog(parent, "Validation errors",
  "<b>2 errors on 'Foo':</b>"
  "<ol>"
  "<li>Missing type &#8212; <a id='fix0'>Fix</a> <a id='ignore0'>Ignore</a></li>"
  "<li>Broken link &#8212; <a id='fix1'>Fix</a> <a id='delete1'>Delete</a></li>"
  "</ol>",
  actions={
    "fix0": lambda: fixMissingType(obj),
    "ignore0": lambda: ignoreError(obj, 0),
    "fix1": lambda: fixBrokenLink(obj),
    "delete1": lambda: deleteError(obj, 1),
  },
  closeOnAction=False)  # stay open so the remaining errors can still be acted on
Parameters:
  • parent (tk.Misc) – The parent widget this dialog is transient for.

  • title (str) – The dialog’s window title.

  • html (str) – The content, in the small HTML subset _RichTextParser understands (<b>, <strong>, <i>, <em>, <u>, <br>, <ol>, <ul>, <li>, and <a id="...">).

  • actions (Optional[dict[str, ActionCallback]]) – [default: None] Maps each <a id="..."> link’s id to the zero-argument callback to invoke when it’s clicked. A link whose id has no entry here is still rendered (as a link) but is inert when clicked.

  • closeOnAction (bool) – [default: True] If True, clicking any action link closes the dialog immediately after running its callback. Pass False for a dialog meant to stay open across several actions – eg: fixing one error in a list and leaving the rest visible to act on next.

  • width (int) – [default: 60] The text area’s width, in characters.

  • maxHeight (int) – [default: 25] The text area’s height is sized to fit its content up to this many lines, then scrolls.

Return type:

None

__init__(parent: Wm, title: str, html: str, actions: dict[str, Callable[[], None]] | None = None, *, closeOnAction: bool = True, width: int = 80, maxHeight: int = 40) → None
Parameters:
  • parent (tk.Wm)

  • title (str)

  • html (str)

  • actions (Optional[dict[str, ActionCallback]])

  • closeOnAction (bool)

  • width (int)

  • maxHeight (int)

_actions: dict[str, Callable[[], None]]
_closeOnAction: bool
_linkTagCount: int
_render(html: str) → None

Parse html and insert its runs into self.text, giving each distinct action link its own uniquely-named tag (so each link can be bound to, and later look up, its own callback independent of any other link that happens to share the same visible label).

Parameters:

html (str) – The markup to render – see the class docstring for the supported subset.

Return type:

None

_bindAction(tagName: str, actionId: str) → None

Wire up one action link’s click and hover behaviour: clicking it runs the caller’s callback for actionId (if any was supplied) and then closes the dialog iff self._closeOnAction; hovering it swaps the cursor to a hand to signal it’s clickable.

Parameters:
  • tagName (str) – This specific link occurrence’s unique tk.Text tag.

  • actionId (str) – The id from the <a id="..."> markup, used to look up the callback in self._actions.

Return type:

None