Add mouse event and signal proxying support
parent
cebfe9dca3
commit
7fc7f72643
|
@ -21,8 +21,8 @@ Qt event proxying and processing using ``trio`` mem chans.
|
||||||
from contextlib import asynccontextmanager, AsyncExitStack
|
from contextlib import asynccontextmanager, AsyncExitStack
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore, QtGui
|
||||||
from PyQt5.QtCore import QEvent
|
from PyQt5.QtCore import QEvent, pyqtBoundSignal
|
||||||
from PyQt5.QtWidgets import QWidget
|
from PyQt5.QtWidgets import QWidget
|
||||||
import trio
|
import trio
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
@ -35,19 +35,30 @@ class KeyboardMsg(BaseModel):
|
||||||
'''Unpacked Qt keyboard event data.
|
'''Unpacked Qt keyboard event data.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
event: QEvent
|
event: QEvent
|
||||||
etype: int
|
etype: int
|
||||||
key: int
|
key: int
|
||||||
mods: int
|
mods: int
|
||||||
txt: str
|
txt: str
|
||||||
|
|
||||||
class Config:
|
|
||||||
arbitrary_types_allowed = True
|
|
||||||
|
|
||||||
def to_tuple(self) -> tuple:
|
def to_tuple(self) -> tuple:
|
||||||
return tuple(self.dict().values())
|
return tuple(self.dict().values())
|
||||||
|
|
||||||
|
|
||||||
|
class MouseMsg(BaseModel):
|
||||||
|
'''Unpacked Qt keyboard event data.
|
||||||
|
|
||||||
|
'''
|
||||||
|
class Config:
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
|
||||||
|
event: QEvent
|
||||||
|
etype: int
|
||||||
|
button: int
|
||||||
|
|
||||||
# TODO: maybe add some methods to detect key combos? Or is that gonna be
|
# TODO: maybe add some methods to detect key combos? Or is that gonna be
|
||||||
# better with pattern matching?
|
# better with pattern matching?
|
||||||
# # ctl + alt as combo
|
# # ctl + alt as combo
|
||||||
|
@ -79,7 +90,7 @@ class EventRelay(QtCore.QObject):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
etype = ev.type()
|
etype = ev.type()
|
||||||
# print(f'etype: {etype}')
|
# print(f'ev: {ev}')
|
||||||
|
|
||||||
if etype in self._event_types:
|
if etype in self._event_types:
|
||||||
# ev.accept()
|
# ev.accept()
|
||||||
|
@ -98,7 +109,7 @@ class EventRelay(QtCore.QObject):
|
||||||
|
|
||||||
msg = KeyboardMsg(
|
msg = KeyboardMsg(
|
||||||
event=ev,
|
event=ev,
|
||||||
etype=ev.type(),
|
etype=etype,
|
||||||
key=ev.key(),
|
key=ev.key(),
|
||||||
mods=ev.modifiers(),
|
mods=ev.modifiers(),
|
||||||
txt=ev.text(),
|
txt=ev.text(),
|
||||||
|
@ -114,12 +125,23 @@ class EventRelay(QtCore.QObject):
|
||||||
# processing **before** running a ``trio`` guest mode
|
# processing **before** running a ``trio`` guest mode
|
||||||
# tick, thus special handling or copying must be done.
|
# tick, thus special handling or copying must be done.
|
||||||
|
|
||||||
# send keyboard msg to async handler
|
elif etype in {
|
||||||
self._send_chan.send_nowait(msg)
|
QEvent.MouseButtonPress,
|
||||||
|
QEvent.MouseButtonRelease,
|
||||||
|
QtGui.QMouseEvent,
|
||||||
|
}:
|
||||||
|
print('mouse')
|
||||||
|
msg = MouseMsg(
|
||||||
|
event=ev,
|
||||||
|
etype=etype,
|
||||||
|
button=ev.button(),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# send event to async handler
|
msg = ev
|
||||||
self._send_chan.send_nowait(ev)
|
|
||||||
|
# send event-msg to async handler
|
||||||
|
self._send_chan.send_nowait(msg)
|
||||||
|
|
||||||
# **do not** filter out this event
|
# **do not** filter out this event
|
||||||
# and instead forward to the source widget
|
# and instead forward to the source widget
|
||||||
|
@ -156,6 +178,31 @@ async def open_event_stream(
|
||||||
source_widget.removeEventFilter(kc)
|
source_widget.removeEventFilter(kc)
|
||||||
|
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def open_signal_handler(
|
||||||
|
|
||||||
|
signal: pyqtBoundSignal,
|
||||||
|
async_handler: Callable,
|
||||||
|
|
||||||
|
) -> trio.abc.ReceiveChannel:
|
||||||
|
|
||||||
|
send, recv = trio.open_memory_channel(0)
|
||||||
|
|
||||||
|
def proxy_args_to_chan(*args):
|
||||||
|
send.send_nowait(args)
|
||||||
|
|
||||||
|
signal.connect(proxy_args_to_chan)
|
||||||
|
|
||||||
|
async def proxy_to_handler():
|
||||||
|
async for args in recv:
|
||||||
|
await async_handler(*args)
|
||||||
|
|
||||||
|
async with trio.open_nursery() as n:
|
||||||
|
n.start_soon(proxy_to_handler)
|
||||||
|
async with send:
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def open_handlers(
|
async def open_handlers(
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue