Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Adding a Passthrough Event Filter to a QWidget #16

Open
padraic-shafer opened this issue Sep 26, 2024 · 3 comments
Open

Docs: Adding a Passthrough Event Filter to a QWidget #16

padraic-shafer opened this issue Sep 26, 2024 · 3 comments
Labels
documentation Improvements or additions to documentation

Comments

@padraic-shafer
Copy link

In the major refactoring that is expected to happen during the early stages of our https://github.com/NSLS2/pymca/milestone/1 work, some code examples might get lost from the active branch.

Here, I'm documenting the idea of using a PassThroughEventFilter helper class to simplify adding non-consuming event filters from a view model to a view widget. This is extracted from commit f0b87e5 .

@padraic-shafer
Copy link
Author

Here the PassThroughEventFilter helper class is defined with an eventFilter() method that runs a matching event handler and then sends the event to the filter of the parent QObject.

class PassThroughEventFilter(QObject):
"""React to desired events then pass each event to the parent filter."""
def __init__(
self,
handlers: Mapping[QEvent.Type, Callable[[QEvent], None]],
parent: Optional[QObject] = None,
) -> None:
super().__init__(parent)
self.handle_event = defaultdict(self.do_nothing_factory)
self.handle_event.update(handlers)
@staticmethod
def do_nothing_factory():
"""Return a function that swallows its arguments and does nothing."""
def do_nothing(*args, **kwargs):
pass
return do_nothing
def eventFilter(
self,
obj: Optional[QObject],
event: Optional[QEvent],
) -> bool:
"""Respond to the event and then pass it to the parent filter."""
self.handle_event[event.type()](event)
return super().eventFilter(obj, event)

If a handler has been registeredduring PassThroughEventFilter initialization for the type of event being processed, then it will be called. Otherwise a 'no-op' handler is called.

@padraic-shafer
Copy link
Author

Here is an example of an event handler being registered by the connect_model_slots() method of the QTiledCatalogSelectorDialog widget.

def connect_model_slots(self) -> None:
"""Connect model slots to dialog signals."""
_logger.debug("QTiledCatalogSelectorDialog.connect_model_slots()...")
model = self.model
urlFocusInFilter = PassThroughEventFilter(
handlers={QEvent.Type.FocusIn: model.on_url_focus_in_event},
parent=self,
)
self.url_entry.installEventFilter(urlFocusInFilter)
self.url_entry.textEdited.connect(model.on_url_text_edited)
self.url_entry.editingFinished.connect(model.on_url_editing_finished)
self.connect_button.clicked.connect(model.on_connect_clicked)

  • It creates the urlFocusInFilter object -- an instance of the PassThroughEventFilter class -- by passing a dictionary with a single event handler (model.on_url_focus_in_event) as the value associated the QEvent.Type key (QEvent.Type.FocusIn).
  • This filter object is then installed on the dialog's QLineEdit widget named url_entry (self.url_entry.installEventFilter(urlFocusInFilter)).
  • Whenever the url_entry widget receives focus, the registered event handler from the model will now be called.

@padraic-shafer
Copy link
Author

Finally, here is an example of a simple event handler that responds to the FocusIn event, that is described above.

def on_url_focus_in_event(self, event: QEvent):
"""Handle the event when the URL widget gains focus."""
_logger.debug("TiledCatalogSelector.on_url_focus_in_event()...")
# TODO: Check whether this causes issues under the condition when
# the connection button is clicked before the user
# interacts with the URL text editor.
self.url_buffer = ""

@padraic-shafer padraic-shafer added the documentation Improvements or additions to documentation label Sep 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant