Add mouse event and signal proxying support

fsp_feeds
Tyler Goodlet 2021-08-12 14:48:31 -04:00
parent cebfe9dca3
commit 7fc7f72643
1 changed files with 58 additions and 11 deletions

View File

@ -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(