Source code for spacr.qt.widgets.cursor_zoom

"""Explicit cursor anchoring for image views, independent of Qt mouse history."""
from __future__ import annotations

import math

from PySide6.QtCore import QPointF
from PySide6.QtWidgets import QGraphicsView


[docs] def zoom_at_pointer(view, factor, position=None): """Scale an image while retaining the scene point beneath a viewport point. :param view: QGraphicsView whose owner suppresses peer updates while zooming. :param factor: positive, finite magnification multiplier. :param position: viewport coordinates; None uses its center for buttons. :returns: whether a zoom was applied. Extra scene margins allow anchoring even when the image is smaller than the viewport. The scene itself remains unchanged so fit-to-image still uses the actual image bounds. """ factor = float(factor) if not math.isfinite(factor) or factor <= 0 or view.scene() is None: return False position = QPointF(position if position is not None else view.viewport().rect().center()) inverse, valid = view.viewportTransform().inverted() if not valid: return False target = inverse.map(position) anchor = view.transformationAnchor() view.setTransformationAnchor(QGraphicsView.NoAnchor) try: view.scale(factor, factor) scale = abs(view.transform().m11()) if scale == 0: return False margin_x = view.viewport().width() / scale margin_y = view.viewport().height() / scale bounds = view.scene().sceneRect().united( view.scene().sceneRect().translated(target - view.scene().sceneRect().center())) view.setSceneRect(bounds.adjusted(-margin_x, -margin_y, margin_x, margin_y)) inverse, _ = view.viewportTransform().inverted() center = inverse.map(QPointF(view.viewport().rect().center())) view.centerOn(target + center - inverse.map(position)) finally: view.setTransformationAnchor(anchor) return True