Skip to content

Commit

Permalink
Python: Add support for invoke_from_event_loop
Browse files Browse the repository at this point in the history
Fixes #420
  • Loading branch information
tronical committed Mar 5, 2024
1 parent 2f313f8 commit d2aac25
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
13 changes: 13 additions & 0 deletions api/python/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ fn quit_event_loop() -> Result<(), errors::PyEventLoopError> {
slint_interpreter::quit_event_loop().map_err(|e| e.into())
}

#[pyfunction]
fn invoke_from_event_loop(callable: PyObject) -> Result<(), errors::PyEventLoopError> {
slint_interpreter::invoke_from_event_loop(move || {
Python::with_gil(|py| {
if let Err(err) = callable.call0(py) {
eprintln!("Error invoking python callable from closure invoked via slint::invoke_from_event_loop: {}", err)
}
})
})
.map_err(|e| e.into())
}

use pyo3::prelude::*;

#[pymodule]
Expand All @@ -42,6 +54,7 @@ fn slint(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<models::PyModelBase>()?;
m.add_function(wrap_pyfunction!(run_event_loop, m)?)?;
m.add_function(wrap_pyfunction!(quit_event_loop, m)?)?;
m.add_function(wrap_pyfunction!(invoke_from_event_loop, m)?)?;

Ok(())
}
29 changes: 29 additions & 0 deletions api/python/tests/test_invoke_from_event_loop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright © SixtyFPS GmbH <[email protected]>
# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial

from slint import slint as native
import threading
from datetime import timedelta


def test_threads():
global was_here
was_here = False

def invoked_from_event_loop():
global was_here
was_here = True
native.quit_event_loop()

def quit():
native.invoke_from_event_loop(invoked_from_event_loop)

thr = threading.Thread(target=quit)
native.Timer.single_shot(timedelta(milliseconds=10), lambda: thr.start())
fallback_timer = native.Timer()
fallback_timer.start(native.TimerMode.Repeated, timedelta(
milliseconds=100), native.quit_event_loop)
native.run_event_loop()
thr.join()
fallback_timer.stop()
assert was_here == True

0 comments on commit d2aac25

Please sign in to comment.