Not perfect, but can give some Ideas.
"""
tested in Krita 4.4.8 Win 10
Notes:
create new document before running.
coordinates are little bit wrong. (integer vs float pixels...)
"""
from PyQt5.QtCore import (
Qt,
QEvent,
QPointF,
QRect)
from PyQt5.QtGui import (
QTransform,
QPainter,
QBrush,
QColor,
QPolygonF,
QInputEvent)
from PyQt5.QtWidgets import (
QWidget,
QMdiArea,
QAbstractScrollArea)
def get_q_view(view):
window = view.window()
q_window = window.qwindow()
q_stacked_widget = q_window.centralWidget()
q_mdi_area = q_stacked_widget.findChild(QMdiArea)
for v, q_mdi_view in zip(window.views(), q_mdi_area.subWindowList()):
if v == view:
return q_mdi_view.widget()
def get_transform(view):
def _offset(scroller):
mid = (scroller.minimum() + scroller.maximum()) / 2.0
return -(scroller.value() - mid)
canvas = view.canvas()
document = view.document()
q_view = get_q_view(view)
area = q_view.findChild(QAbstractScrollArea)
zoom = (canvas.zoomLevel() * 72.0) / document.resolution()
transform = QTransform()
transform.translate(
_offset(area.horizontalScrollBar()),
_offset(area.verticalScrollBar()))
transform.rotate(canvas.rotation())
transform.scale(zoom, zoom)
return transform
class MyOverlay(QWidget):
_degree = 6
_colors = [
QBrush(QColor(0, 0, 255)),
QBrush(QColor(0, 255, 0)),
QBrush(QColor(255, 0, 0)),
QBrush(QColor(255, 0, 255)),
QBrush(QColor(0, 255, 255)),
QBrush(QColor(255, 255, 0))]
def __init__(self, view):
parent = get_q_view(view)
super().__init__(parent)
# ToDo: is there better way to ignore events?
self.setAttribute(Qt.WA_TransparentForMouseEvents)
self.setFocusPolicy(Qt.NoFocus)
self._view = view
q_canvas = parent.findChild(QAbstractScrollArea).viewport()
size = q_canvas.size()
self.setGeometry(QRect(0, 0, size.width(), size.height()))
parent.installEventFilter(self)
def paintEvent(self, e):
document = self._view.document()
width = float(document.width())
height = float(document.height())
half_width = 0.5 * width
half_height = 0.5 * height
triangle = (
QPointF(-half_width, half_height),
QPointF(0.0, -half_height),
QPointF(half_width, half_height))
# Turtles all the way down
painter = QPainter(self)
try:
painter.setRenderHint(QPainter.Antialiasing, True)
painter.translate(self.rect().center())
painter.setTransform(get_transform(self._view), combine=True)
painter.setPen(Qt.NoPen)
self.draw_sierpinski(painter, triangle, self._degree)
finally:
painter.end()
def draw_sierpinski(self, painter, triangle, degree):
painter.setBrush(self._colors[degree % len(self._colors)])
polygon = QPolygonF()
polygon.append(triangle[0])
polygon.append(triangle[1])
polygon.append(triangle[2])
painter.drawConvexPolygon(polygon)
if degree > 0:
next_degree = degree - 1
mid_1 = 0.5 * (triangle[0] + triangle[1])
mid_2 = 0.5 * (triangle[0] + triangle[2])
mid_3 = 0.5 * (triangle[1] + triangle[2])
self.draw_sierpinski(painter, (triangle[0], mid_1, mid_2), next_degree)
self.draw_sierpinski(painter, (triangle[1], mid_1, mid_3), next_degree)
self.draw_sierpinski(painter, (triangle[2], mid_3, mid_2), next_degree)
def eventFilter(self, obj, e):
if e.type() == QEvent.Resize:
q_canvas = self.parent().findChild(QAbstractScrollArea).viewport()
size = q_canvas.size()
self.setGeometry(QRect(0, 0, size.width(), size.height()))
return super().eventFilter(obj, e)
active_window = Application.activeWindow()
active_view = active_window.activeView()
if active_view.document() is None:
raise RuntimeError('Document of active view is None!')
my_overlay = MyOverlay(active_view)
my_overlay.show()
/AkiR