Architecture

This document describes the internal architecture of SlicerMouseMaster.

System Overview

┌─────────────────────────────────────────────────────────────────┐
│                         Qt Application                          │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │              MouseMasterEventHandler                       │  │
│  │  (Application-level Qt event filter)                       │  │
│  └───────────────────────────────────────────────────────────┘  │
│        │                    │                    │              │
│        ▼                    ▼                    ▼              │
│  ┌──────────┐        ┌──────────┐        ┌──────────────┐      │
│  │ Platform │        │  Preset  │        │    Action    │      │
│  │ Adapter  │        │ Manager  │        │   Registry   │      │
│  └──────────┘        └──────────┘        └──────────────┘      │
│        │                    │                    │              │
│        └────────────────────┼────────────────────┘              │
│                             ▼                                   │
│                    ┌──────────────┐                             │
│                    │ Mouse Profile│                             │
│                    │  (dataclass) │                             │
│                    └──────────────┘                             │
└─────────────────────────────────────────────────────────────────┘

Event Flow

When a user presses a mouse button:

User Button Press
    │
    ▼
Qt Application (eventFilter)
    │
    ▼
MouseMasterEventHandler.eventFilter()
    ├── Normalize button via PlatformAdapter
    ├── Get current Slicer module context
    ├── Look up binding: context-specific → default
    ├── Execute action via ActionRegistry
    └── Return True (consumed) or False (pass-through)

Key Classes

MouseMaster/MouseMaster.py

  • MouseMaster: Slicer module registration and metadata

  • MouseMasterWidget: Qt widget for UI setup and user interaction

  • MouseMasterLogic: Business logic coordinator

MouseMasterLib/EventHandler.py

The core of MouseMaster. Implements a Qt application-level event filter that intercepts mouse button events.

class MouseMasterEventHandler(QObject):
    def eventFilter(self, obj, event):
        if event.type() == QEvent.MouseButtonPress:
            button = event.button()
            # Normalize and execute mapped action
            return self.handleButton(button)
        return False

MouseMasterLib/MouseProfile.py

Data classes for mouse definitions:

  • MouseButton: Single button definition (id, name, Qt code, remappable)

  • MouseFeatures: Optional features (horizontal scroll, thumb wheel)

  • MouseProfile: Complete mouse definition with all buttons

MouseMasterLib/PresetManager.py

Handles preset loading, saving, and management:

  • Mapping: Single button-to-action mapping

  • Preset: Complete preset with mappings and context overrides

  • PresetManager: CRUD operations for presets

MouseMasterLib/ActionRegistry.py

Singleton registry of executable actions:

registry = ActionRegistry.get_instance()
registry.register("my_action", MyActionHandler(), category="custom")
registry.execute("my_action", parameters={})

MouseMasterLib/PlatformAdapter.py

Cross-platform button code normalization:

adapter = PlatformAdapter.get_instance()
normalized = adapter.normalize_button(qt_button_code)

MouseMasterLib/ButtonDetector.py

Interactive wizard for detecting button codes on unknown mice.

Data Formats

Mouse Definition JSON

Located in Resources/MouseDefinitions/:

{
  "id": "logitech_mx_master_3s",
  "name": "Logitech MX Master 3S",
  "vendor": "Logitech",
  "vendorId": "0x46D",
  "productIds": ["0x4082", "0xB023"],
  "buttons": [
    {
      "id": "left",
      "name": "Left Click",
      "qtButton": 1,
      "remappable": false
    },
    {
      "id": "back",
      "name": "Back",
      "qtButton": 8,
      "remappable": true,
      "defaultAction": "undo"
    }
  ],
  "features": {
    "horizontalScroll": true,
    "thumbWheel": true
  }
}

Preset JSON

Located in presets/:

{
  "id": "segmentation_workflow",
  "name": "Segmentation Workflow",
  "version": "1.0",
  "mouseId": "logitech_mx_master_3s",
  "mappings": {
    "back": {"action": "slicer_action", "actionId": "undo"},
    "forward": {"action": "slicer_action", "actionId": "redo"}
  },
  "contextMappings": {
    "SegmentEditor": {
      "back": {"action": "segment_previous"},
      "forward": {"action": "segment_next"}
    }
  }
}

Design Decisions

Key architectural decisions are documented in Architecture Decision Records (ADRs):

Important decisions:

  1. Qt event filter over VTK observers for broader coverage

  2. JSON presets for human-readable, shareable configurations

  3. Platform adapters to abstract OS differences

  4. Singleton registries for actions and adapters

Qt Button Codes

Reference for Qt mouse button constants:

Qt Button

Constant

Typical Mapping

1

Qt.LeftButton

Primary

2

Qt.RightButton

Context menu

4

Qt.MiddleButton

Pan/rotate

8

Qt.BackButton

Back/undo

16

Qt.ForwardButton

Forward/redo

32

Qt.ExtraButton1

Custom (thumb)

Modifier Keys

Qt Modifier

Constant

Shift

Qt.ShiftModifier

Ctrl

Qt.ControlModifier

Alt

Qt.AltModifier

Meta

Qt.MetaModifier