Macro

Macro data structures for recording and playing back user interactions.

This module defines the core event types (key, mouse, wheel) and the Macro container that serializes/deserializes recorded sessions.

Example usage:

from qgis_macros.macro import Macro

# Deserialize a macro from a dict (e.g. loaded from JSON)
macro = Macro.deserialize(data)

# Serialize back
data = macro.serialize()
class qgis_macros.macro.WidgetSpec(widget_class, text='')[source]

Bases: object

Identify a widget by its class name and display text.

Parameters:
  • widget_class (str)

  • text (str)

widget_class: str
text: str = ''
static create(widget)[source]

Create a WidgetSpec from an existing widget.

Parameters:

widget (_QWidgetStub)

Return type:

WidgetSpec

matches(widget)[source]

Return True if widget matches this spec’s class and text.

Parameters:

widget (_QWidgetStub)

Return type:

bool

get_suitable_widget(point, widget, level=1)[source]

Find the nearest child widget matching this spec.

Walk up the widget hierarchy (up to MAXIMUM_PARENT_DEPTH levels) searching for a visible child whose class and text match.

Raises:

WidgetNotFoundError – If no matching widget is found.

Parameters:
  • point (_Stub)

  • widget (_QWidgetStub)

  • level (int)

Return type:

_QWidgetStub

class qgis_macros.macro.WidgetPathNode(widget_class, sibling_index, text='')[source]

Bases: object

A single node in a widget path, identifying a widget within its parent.

Parameters:
  • widget_class (str)

  • sibling_index (int)

  • text (str)

widget_class: str
sibling_index: int
text: str = ''
matches(widget)[source]

Check if the given widget matches this node’s criteria.

Parameters:

widget (_QWidgetStub)

Return type:

bool

class qgis_macros.macro.WidgetPath(window_title, nodes, is_map_canvas=False)[source]

Bases: object

Path from a top-level window down to a target widget.

Each node identifies a widget by its class name, text, and index among same-class siblings. This allows reliable widget lookup even when widgets lack objectNames or shift position on screen.

Parameters:
  • window_title (str)

  • nodes (list[WidgetPathNode])

  • is_map_canvas (bool)

window_title: str
nodes: list[WidgetPathNode]
is_map_canvas: bool = False
static create(widget)[source]

Create a WidgetPath from a given widget.

by traversing its parent hierarchy.

Parameters:

widget (_QWidgetStub)

Return type:

WidgetPath

find_widget()[source]

Walk the path from the top-level window to find the target widget.

Return type:

_QWidgetStub | None

class qgis_macros.macro.MacroEvent(*args, **kwargs)[source]

Bases: Protocol

Single macro event for Macros.

ms_since_last_event: int
perform_event_action(schedule_next)[source]

Perform macro event action (e.g., moving mouse, clicking widget).

Parameters:

schedule_next (Callable[[], None])

Return type:

None

class qgis_macros.macro.Position(local_position, global_position)[source]

Bases: object

Screen position represented as local and global coordinate pairs.

Parameters:
  • local_position (tuple[int, int])

  • global_position (tuple[int, int])

local_position: tuple[int, int]
global_position: tuple[int, int]
static from_event(event)[source]

Create a Position from a Qt mouse or wheel event.

Parameters:

event (_Stub)

Return type:

Position

static from_points(local_point, global_point)[source]

Create a Position from local and global QPoint objects.

Parameters:
  • local_point (_Stub)

  • global_point (_Stub)

Return type:

Position

static interpolate(positions, number_of_positions)[source]

Reduce positions to number_of_positions by linear interpolation.

Parameters:
  • positions (list[Position])

  • number_of_positions (int)

Return type:

list[Position]

property local_point: _Stub

Return the local position as a QPoint.

property global_point: _Stub

Return the global position as a QPoint.

widget_corrected_position(widget)[source]

Return a new Position corrected for the widget’s current screen location.

Parameters:

widget (_QWidgetStub)

Return type:

Position

class qgis_macros.macro.BaseMacroEvent(widget_spec, ms_since_last_event=0, widget_path=None)[source]

Bases: ABC

Base class for all macro events.

Parameters:
widget_spec: WidgetSpec
ms_since_last_event: int = 0
widget_path: WidgetPath | None = None
static move_cursor(position)[source]

Move the mouse cursor to the given screen position.

Parameters:

position (tuple[int, int] | _Stub)

Return type:

None

get_widget(position)[source]

Resolve the target widget at position.

Fall back to a spec-based search if the widget at position does not match.

Parameters:

position (Position)

Return type:

_QWidgetStub

get_widget_and_corrected_position(position)[source]

Return the target widget and a screen-corrected position.

Parameters:

position (Position)

Return type:

tuple[_QWidgetStub, Position]

abstract perform_event_action(schedule_next)[source]

Execute the event action and call schedule_next when done.

Parameters:

schedule_next (Callable[[], None])

Return type:

None

class qgis_macros.macro.MacroKeyEvent(widget_spec, ms_since_last_event=0, widget_path=None, key=0, is_release=False, modifiers=0)[source]

Bases: BaseMacroEvent

Keyboard press or release event.

Parameters:
  • widget_spec (WidgetSpec)

  • ms_since_last_event (int)

  • widget_path (WidgetPath | None)

  • key (int)

  • is_release (bool)

  • modifiers (int)

key: int = 0
is_release: bool = False
modifiers: int = 0
perform_event_action(schedule_next)[source]

Replay the key press or release on the currently focused widget.

Parameters:

schedule_next (Callable[[], None])

Return type:

None

class qgis_macros.macro.MacroMouseMoveEvent(widget_spec, ms_since_last_event=0, widget_path=None, positions=<factory>, buttons=0, modifiers=0)[source]

Bases: BaseMacroEvent

Mouse movement event containing a sequence of positions.

Parameters:
  • widget_spec (WidgetSpec)

  • ms_since_last_event (int)

  • widget_path (WidgetPath | None)

  • positions (list[Position])

  • buttons (int)

  • modifiers (int)

positions: list[Position]
buttons: int = 0
modifiers: int = 0
add_position(position)[source]

Append a position, ignoring duplicates of the last position.

Parameters:

position (Position)

Return type:

None

perform_event_action(schedule_next)[source]

Replay the mouse movement along the recorded positions.

Parameters:

schedule_next (Callable[[], None])

Return type:

None

perform_event_action_with_event()[source]

Replay movement by posting QMouseEvent objects (when buttons are held).

Return type:

None

interpolate_positions(number_of_positions)[source]

Interpolate the positions to a given number of positions.

Parameters:

number_of_positions (int)

Return type:

None

class qgis_macros.macro.MacroMouseEvent(widget_spec, ms_since_last_event=0, widget_path=None, position=Position(local_position=(0, 0), global_position=(0, 0)), is_release=False, button=0, modifiers=0)[source]

Bases: BaseMacroEvent

Mouse button press or release event.

Parameters:
  • widget_spec (WidgetSpec)

  • ms_since_last_event (int)

  • widget_path (WidgetPath | None)

  • position (Position)

  • is_release (bool)

  • button (int)

  • modifiers (int)

position: Position = Position(local_position=(0, 0), global_position=(0, 0))
is_release: bool = False
button: int = 0
modifiers: int = 0
perform_event_action(schedule_next)[source]

Replay the mouse press or release at the recorded position.

Parameters:

schedule_next (Callable[[], None])

Return type:

None

class qgis_macros.macro.MacroWheelEvent(widget_spec, ms_since_last_event=0, widget_path=None, position=Position(local_position=(0, 0), global_position=(0, 0)), delta=0, phase=0, inverted=False, source=0)[source]

Bases: BaseMacroEvent

Mouse wheel scroll event.

Parameters:
  • widget_spec (WidgetSpec)

  • ms_since_last_event (int)

  • widget_path (WidgetPath | None)

  • position (Position)

  • delta (int)

  • phase (int)

  • inverted (bool)

  • source (int)

position: Position = Position(local_position=(0, 0), global_position=(0, 0))
delta: int = 0
phase: int = 0
inverted: bool = False
source: int = 0
perform_event_action(schedule_next)[source]

Replay the wheel scroll at the recorded position.

Parameters:

schedule_next (Callable[[], None])

Return type:

None

class qgis_macros.macro.MacroMouseDoubleClickEvent(widget_spec, ms_since_last_event=0, widget_path=None, position=Position(local_position=(0, 0), global_position=(0, 0)), button=0, modifiers=0)[source]

Bases: BaseMacroEvent

Mouse double-click event.

Parameters:
position: Position = Position(local_position=(0, 0), global_position=(0, 0))
button: int = 0
modifiers: int = 0
perform_event_action(schedule_next)[source]

Replay the double-click at the recorded position.

Parameters:

schedule_next (Callable[[], None])

Return type:

None

class qgis_macros.macro.Macro(events, name=None, speed=1.0, qgis_version=0)[source]

Bases: object

A recorded sequence of user interaction events.

Example:

import json
from pathlib import Path

from qgis_macros.macro import Macro

# Load macros from a JSON file
with Path("macros.json").open() as f:
    data = json.load(f)
macros = [Macro.deserialize(d) for d in data]

# Serialize macros back to JSON
serialized = [m.serialize() for m in macros]
Parameters:
  • events (list[MacroEvent])

  • name (str | None)

  • speed (float)

  • qgis_version (int)

events: list[MacroEvent]
name: str | None = None
speed: float = 1.0
qgis_version: int = 0
serialize()[source]

Serialize the macro to a JSON-compatible dict.

Return type:

dict

classmethod deserialize(data)[source]

Construct a Macro from a dict previously produced by serialize().

Parameters:

data (dict)

Return type:

Macro