All right, so by inverting one of AkiR’s other snippets that he posted here, I managed to make a function that clicks roughly at the intended document coordinates, regardless of zoom etc.
from krita import Krita
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
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_q_canvas(q_view):
scroll_area = q_view.findChild(QAbstractScrollArea)
viewport = scroll_area.viewport()
for child in viewport.children():
cls_name = child.metaObject().className()
if cls_name.startswith('Kis') and ('Canvas' in cls_name):
return child
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
def get_global_from_document_coords(doc_x, doc_y):
app = Krita.instance()
view = app.activeWindow().activeView()
document = view.document()
if document:
q_view = get_q_view(view)
q_canvas = get_q_canvas(q_view)
transform = get_transform(view)
# Calculate the center of the document
centerCanvas = QPointF(0.5 * document.width(), 0.5 * document.height())
#Convert document coordinates to coordinates relative to the center
local_pos = QPointF(doc_x, doc_y) - centerCanvas
# Apply the transformation to convert to canvas coordinates
transformed_pos = transform.map(local_pos)
# Find the center of the canvas
center = q_canvas.rect().center()
# Convert canvas coordinates to local widget coordinates
widget_local_pos = transformed_pos + QPointF(center)
return QPoint(int(widget_local_pos.x()), int(widget_local_pos.y()))
def click_canvas(x0, y0):
pos0 = get_global_from_document_coords(x0, y0)
app = Krita.instance()
view = app.activeWindow().activeView()
document = view.document()
if document is None:
return
q_view = get_q_view(view)
canvas = get_q_canvas(q_view)
global_pos = QPointF(canvas.mapToGlobal(pos0))
device = QTabletEvent.Stylus
pointer_type = QTabletEvent.Pen
pressure = 1
x_tilt = 0
y_tilt = 0
tangential_pressure = 0.0
rotation = 0.0
z_pos = 0
key_state = Qt.NoModifier
unique_id = 1234 # ???
button = Qt.LeftButton
buttons = Qt.LeftButton
canvas.activateWindow()
table_press = QTabletEvent(
QEvent.TabletPress,
pos0,
global_pos,
device,
pointer_type,
pressure,
x_tilt,
y_tilt,
tangential_pressure,
rotation,
z_pos,
key_state,
unique_id,
button,
buttons)
table_release = QTabletEvent(
QEvent.TabletRelease,
pos0,
global_pos,
device,
pointer_type,
pressure,
x_tilt,
y_tilt,
tangential_pressure,
rotation,
z_pos,
key_state,
unique_id,
button,
buttons)
QApplication.sendEvent(canvas, table_press)
QApplication.sendEvent(canvas, table_release)
app = Krita.instance()
view = app.activeWindow().activeView()
document = view.document()
click_canvas(100,100)
Krita.instance().activeDocument().refreshProjection()
However, just clicking is unfortunately not good enough. I’ve got the Enclose-and-Fill tool in Rectangle mode, so I’d like to drag it from 0,0 (pos0) to the max width and height of the document (pos1).
Setting the release coordinates to pos1 doesn’t work, even with throwing in a few hacky sleep
statements that I stole from somewhere:
def sleep(value):
loop = QEventLoop()
QTimer.singleShot(value, loop.quit)
loop.exec()
Similarly, clicking down in the four corners in lasso mode before releasing doesn’t work either.
Does anyone have an idea how I could make it properly drag accross the area?
If no, I guess I could switch the tool to brush mode, and just click across the entire canvas, but that’s a much more unreliable solution than dragging accross the entire canvas, and I’d have to figure out a way to set the pen size.