-
-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
book: Extend main loop chapter with async section (#1511)
* book: Extend main loop chapter with async section * Update book/listings/main_event_loop/7/main.rs Co-authored-by: Bilal Elmoussaoui <[email protected]> * book: Fix typo * book: Add tokio and reqwest listing * book: Fix app ids * book: Add filenames * Explain spawn_blocking in async context and ashpd * book: Add example that reqwest fails without tokio * book: Start with conclusion * book: Move to async-channel for reqwest demo * book: Add section about tokio * book: Add main_event_loop_1 video * book: Extend chapter * book: Address Sabrina's comments * Apply suggestions from @felinira's code review Co-authored-by: Fina <[email protected]> * Update book/src/main_event_loop.md Co-authored-by: Fina <[email protected]> --------- Co-authored-by: Bilal Elmoussaoui <[email protected]> Co-authored-by: Fina <[email protected]>
- Loading branch information
1 parent
fb3ef4d
commit 776fa54
Showing
9 changed files
with
2,170 additions
and
207 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use glib::{clone, MainContext}; | ||
use gtk::prelude::*; | ||
use gtk::{gio, glib}; | ||
use gtk::{Application, ApplicationWindow, Button}; | ||
use std::thread; | ||
use std::time::Duration; | ||
|
||
const APP_ID: &str = "org.gtk_rs.MainEventLoop6"; | ||
|
||
fn main() -> glib::ExitCode { | ||
// Create a new application | ||
let app = Application::builder().application_id(APP_ID).build(); | ||
|
||
// Connect to "activate" signal of `app` | ||
app.connect_activate(build_ui); | ||
|
||
// Run the application | ||
app.run() | ||
} | ||
|
||
fn build_ui(app: &Application) { | ||
// Create a button | ||
let button = Button::builder() | ||
.label("Press me!") | ||
.margin_top(12) | ||
.margin_bottom(12) | ||
.margin_start(12) | ||
.margin_end(12) | ||
.build(); | ||
|
||
// ANCHOR: callback | ||
// Connect to "clicked" signal of `button` | ||
button.connect_clicked(move |button| { | ||
let main_context = MainContext::default(); | ||
// The main loop executes the asynchronous block | ||
main_context.spawn_local(clone!(@weak button => async move { | ||
// Deactivate the button until the operation is done | ||
button.set_sensitive(false); | ||
let enable_button = gio::spawn_blocking(move || { | ||
let ten_seconds = Duration::from_secs(10); | ||
thread::sleep(ten_seconds); | ||
true | ||
}) | ||
.await | ||
.expect("Task needs to finish successfully."); | ||
// Set sensitivity of button to `enable_button` | ||
button.set_sensitive(enable_button); | ||
})); | ||
}); | ||
// ANCHOR_END: callback | ||
|
||
// Create a window | ||
let window = ApplicationWindow::builder() | ||
.application(app) | ||
.title("My GTK App") | ||
.child(&button) | ||
.build(); | ||
|
||
// Present window | ||
window.present(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
use ashpd::desktop::account::UserInformation; | ||
use ashpd::WindowIdentifier; | ||
use glib::{clone, MainContext}; | ||
use gtk::prelude::*; | ||
use gtk::{glib, Application, ApplicationWindow, Button}; | ||
|
||
const APP_ID: &str = "org.gtk_rs.MainEventLoop7"; | ||
|
||
fn main() -> glib::ExitCode { | ||
// Create a new application | ||
let app = Application::builder().application_id(APP_ID).build(); | ||
|
||
// Connect to "activate" signal of `app` | ||
app.connect_activate(build_ui); | ||
|
||
// Run the application | ||
app.run() | ||
} | ||
|
||
fn build_ui(app: &Application) { | ||
// Create a button | ||
let button = Button::builder() | ||
.label("Press me!") | ||
.margin_top(12) | ||
.margin_bottom(12) | ||
.margin_start(12) | ||
.margin_end(12) | ||
.build(); | ||
|
||
// ANCHOR: callback | ||
// Connect to "clicked" signal of `button` | ||
button.connect_clicked(move |button| { | ||
let main_context = MainContext::default(); | ||
// The main loop executes the asynchronous block | ||
main_context.spawn_local(clone!(@weak button => async move { | ||
// Get native of button for window identifier | ||
let native = button.native().expect("Need to be able to get native."); | ||
// Get window identifier so that the dialog will be modal to the main window | ||
let identifier = WindowIdentifier::from_native(&native).await; | ||
let request = UserInformation::request() | ||
.reason("App would like to access user information.") | ||
.identifier(identifier) | ||
.send() | ||
.await; | ||
|
||
if let Ok(response) = request.and_then(|r| r.response()) { | ||
println!("User name: {}", response.name()); | ||
} else { | ||
println!("Could not access user information.") | ||
} | ||
})); | ||
}); | ||
// ANCHOR_END: callback | ||
|
||
// Create a window | ||
let window = ApplicationWindow::builder() | ||
.application(app) | ||
.title("My GTK App") | ||
.child(&button) | ||
.build(); | ||
|
||
// Present window | ||
window.present(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use glib::{clone, MainContext}; | ||
use gtk::glib; | ||
use gtk::prelude::*; | ||
use gtk::{Application, ApplicationWindow, Button}; | ||
|
||
const APP_ID: &str = "org.gtk_rs.MainEventLoop8"; | ||
|
||
fn main() -> glib::ExitCode { | ||
// Create a new application | ||
let app = Application::builder().application_id(APP_ID).build(); | ||
|
||
// Connect to "activate" signal of `app` | ||
app.connect_activate(build_ui); | ||
|
||
// Run the application | ||
app.run() | ||
} | ||
|
||
fn build_ui(app: &Application) { | ||
// Create a button | ||
let button = Button::builder() | ||
.label("Press me!") | ||
.margin_top(12) | ||
.margin_bottom(12) | ||
.margin_start(12) | ||
.margin_end(12) | ||
.build(); | ||
|
||
// ANCHOR: callback | ||
let (sender, receiver) = async_channel::bounded(1); | ||
// Connect to "clicked" signal of `button` | ||
button.connect_clicked(move |_| { | ||
let main_context = MainContext::default(); | ||
// The main loop executes the asynchronous block | ||
main_context.spawn_local(clone!(@strong sender => async move { | ||
let response = reqwest::get("https://www.gtk-rs.org").await; | ||
sender.send(response).await.expect("The channel needs to be open."); | ||
})); | ||
}); | ||
|
||
let main_context = MainContext::default(); | ||
// The main loop executes the asynchronous block | ||
main_context.spawn_local(clone!(@weak button => async move { | ||
while let Ok(response) = receiver.recv().await { | ||
if let Ok(response) = response { | ||
println!("Status: {}", response.status()); | ||
} else { | ||
println!("Could not make a `GET` request."); | ||
} | ||
} | ||
})); | ||
// ANCHOR_END: callback | ||
|
||
// Create a window | ||
let window = ApplicationWindow::builder() | ||
.application(app) | ||
.title("My GTK App") | ||
.child(&button) | ||
.build(); | ||
|
||
// Present window | ||
window.present(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use glib::{clone, MainContext}; | ||
use gtk::glib; | ||
use gtk::prelude::*; | ||
use gtk::{Application, ApplicationWindow, Button}; | ||
use once_cell::sync::Lazy; | ||
use tokio::runtime::Runtime; | ||
|
||
// ANCHOR: tokio_runtime | ||
const APP_ID: &str = "org.gtk_rs.MainEventLoop9"; | ||
static RUNTIME: Lazy<Runtime> = | ||
Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); | ||
|
||
fn main() -> glib::ExitCode { | ||
// Create a new application | ||
let app = Application::builder().application_id(APP_ID).build(); | ||
|
||
// Connect to "activate" signal of `app` | ||
app.connect_activate(build_ui); | ||
|
||
// Run the application | ||
app.run() | ||
} | ||
// ANCHOR_END: tokio_runtime | ||
|
||
fn build_ui(app: &Application) { | ||
// Create a button | ||
let button = Button::builder() | ||
.label("Press me!") | ||
.margin_top(12) | ||
.margin_bottom(12) | ||
.margin_start(12) | ||
.margin_end(12) | ||
.build(); | ||
|
||
// ANCHOR: callback | ||
let (sender, receiver) = async_channel::bounded(1); | ||
// Connect to "clicked" signal of `button` | ||
button.connect_clicked(move |_| { | ||
RUNTIME.spawn(clone!(@strong sender => async move { | ||
let response = reqwest::get("https://www.gtk-rs.org").await; | ||
sender.send(response).await.expect("The channel needs to be open."); | ||
})); | ||
}); | ||
|
||
let main_context = MainContext::default(); | ||
// The main loop executes the asynchronous block | ||
main_context.spawn_local(clone!(@weak button => async move { | ||
while let Ok(response) = receiver.recv().await { | ||
if let Ok(response) = response { | ||
println!("Status: {}", response.status()); | ||
} else { | ||
println!("Could not make a `GET` request."); | ||
} | ||
} | ||
})); | ||
// ANCHOR_END: callback | ||
|
||
// Create a window | ||
let window = ApplicationWindow::builder() | ||
.application(app) | ||
.title("My GTK App") | ||
.child(&button) | ||
.build(); | ||
|
||
// Present window | ||
window.present(); | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.