From 15d2569956d7dd4c820e4b8064c9e8d1b527c65f Mon Sep 17 00:00:00 2001
From: bilelmoussaoui CSS
fn load_css() {
// Load the CSS file and add it to the provider
let provider = CssProvider::new();
- provider.load_from_data(include_str!("style.css"));
+ provider.load_from_string(include_str!("style.css"));
// Add the provider to the default screen
gtk::style_context_add_provider_for_display(
@@ -300,7 +300,7 @@ fn load_css() {
// Load the CSS file and add it to the provider
let provider = CssProvider::new();
- provider.load_from_data(include_str!("style.css"));
+ provider.load_from_string(include_str!("style.css"));
// Add the provider to the default screen
gtk::style_context_add_provider_for_display(
@@ -372,7 +372,7 @@
fn load_css() {
// Load the CSS file and add it to the provider
let provider = CssProvider::new();
- provider.load_from_data(include_str!("style.css"));
+ provider.load_from_string(include_str!("style.css"));
// Add the provider to the default screen
gtk::style_context_add_provider_for_display(
diff --git a/stable/latest/book/print.html b/stable/latest/book/print.html
index 7c4ed9b3d76b..0fba23cbf749 100644
--- a/stable/latest/book/print.html
+++ b/stable/latest/book/print.html
@@ -398,8 +398,8 @@ gtk4 crate to your dependencies in
Cargo.toml
.
-At the time of this writing the newest version is 4.8
.
cargo add gtk4 --rename gtk --features v4_8
+At the time of this writing the newest version is 4.12
.
+cargo add gtk4 --rename gtk --features v4_12
By specifying this feature you opt-in to API that was added with minor releases of GTK 4.
Now, you can run your application by executing:
@@ -10792,7 +10792,7 @@ fn load_css() {
// Load the CSS file and add it to the provider
let provider = CssProvider::new();
- provider.load_from_data(include_str!("style.css"));
+ provider.load_from_string(include_str!("style.css"));
// Add the provider to the default screen
gtk::style_context_add_provider_for_display(
@@ -10947,7 +10947,7 @@ fn load_css() {
// Load the CSS file and add it to the provider
let provider = CssProvider::new();
- provider.load_from_data(include_str!("style.css"));
+ provider.load_from_string(include_str!("style.css"));
// Add the provider to the default screen
gtk::style_context_add_provider_for_display(
diff --git a/stable/latest/book/project_setup.html b/stable/latest/book/project_setup.html
index 9c1e11e8922e..d00702e642f2 100644
--- a/stable/latest/book/project_setup.html
+++ b/stable/latest/book/project_setup.html
@@ -189,8 +189,8 @@ Project Setup
pkg-config --modversion gtk4
Use this information to add the gtk4 crate to your dependencies in Cargo.toml
.
-At the time of this writing the newest version is 4.8
.
-cargo add gtk4 --rename gtk --features v4_8
+At the time of this writing the newest version is 4.12
.
+cargo add gtk4 --rename gtk --features v4_12
By specifying this feature you opt-in to API that was added with minor releases of GTK 4.
Now, you can run your application by executing:
diff --git a/stable/latest/book/searchindex.js b/stable/latest/book/searchindex.js
index b3dd0d2d6c12..d023d2de384f 100644
--- a/stable/latest/book/searchindex.js
+++ b/stable/latest/book/searchindex.js
@@ -1 +1 @@
-Object.assign(window.search, {"doc_urls":["introduction.html#gui-development-with-rust-and-gtk-4","introduction.html#who-this-book-is-for","introduction.html#how-to-use-this-book","introduction.html#license","installation.html#installation","installation_linux.html#linux","installation_macos.html#macos","installation_windows.html#windows","installation_windows.html#install-rustup","installation_windows.html#install-gtk-4","installation_windows.html#set-rust-toolchain-to-msvc","installation_windows.html#build-gtk-4","installation_windows.html#update-path-environment-variable","installation_windows.html#set-rust-toolchain-to-msvc-1","installation_windows.html#visual-studio","installation_windows.html#git","installation_windows.html#cmake","installation_windows.html#python","installation_windows.html#meson","installation_windows.html#gettext-021","installation_windows.html#pkg-config","installation_windows.html#update-environment-variables","installation_windows.html#compile-and-install-gtk-4","installation_windows.html#install-rustup-1","installation_windows.html#remove-residues-from-the-msvc-toolchain","installation_windows.html#msys2","installation_windows.html#install-gtk-4-1","installation_windows.html#update-path-environment-variable-1","installation_windows.html#setup-the-gnu-toolchain-for-rust","project_setup.html#project-setup","hello_world.html#hello-world","widgets.html#widgets","g_object_concepts.html#gobject-concepts","g_object_memory_management.html#memory-management","g_object_subclassing.html#subclassing","g_object_subclassing.html#adding-functionality","g_object_values.html#generic-values","g_object_values.html#value","g_object_values.html#variant","g_object_properties.html#properties","g_object_properties.html#adding-properties-to-custom-gobjects","g_object_signals.html#signals","g_object_signals.html#adding-signals-to-custom-gobjects","main_event_loop.html#the-main-event-loop","main_event_loop.html#how-to-avoid-blocking-the-main-loop","main_event_loop.html#channels","main_event_loop.html#embed-blocking-calls-in-an-async-context","main_event_loop.html#run-async-functions-from-external-crates","main_event_loop.html#tokio","main_event_loop.html#conclusion","settings.html#settings","saving_window_state.html#saving-window-state","list_widgets.html#list-widgets","list_widgets.html#views","list_widgets.html#expressions","list_widgets.html#string-list","list_widgets.html#conclusion","composite_templates.html#composite-templates","composite_templates.html#resources","composite_templates.html#custom-widgets","composite_templates.html#template-callbacks","composite_templates.html#registering-types","composite_templates.html#conclusion","todo_1.html#building-a-simple-to-do-app","todo_1.html#window","todo_1.html#task-object","todo_1.html#task-row","actions.html#actions","actions.html#parameter-and-state","actions.html#actionable","actions.html#menus","actions.html#settings","todo_2.html#manipulating-state-of-to-do-app","todo_2.html#filtering-tasks","todo_2.html#saving-and-restoring-tasks","css.html#css","css.html#style-classes-applied-by-gtk","css.html#adding-your-own-style-class","css.html#specifying-name-of-a-widget","css.html#css-rules-provided-by-gtk","css.html#interface-builder","css.html#pseudo-classes","css.html#nodes","css.html#set-css-name-and-use-exported-colors","css.html#adapt-todo-app","css.html#conclusion","libadwaita.html#libadwaita","libadwaita.html#linux","libadwaita.html#macos","libadwaita.html#windows","libadwaita.html#if-using-gvsbuild","libadwaita.html#if-building-manually-with-msvc","libadwaita.html#work-around-missing-icons","libadwaita.html#gvsbuild","libadwaita.html#manually-with-msvc","todo_3.html#let-to-do-app-use-libadwaita","todo_3.html#boxed-lists","todo_4.html#adding-collections","todo_4.html#sidebar","todo_4.html#placeholder-page","todo_4.html#collections","todo_4.html#window","todo_4.html#message-dialog"],"index":{"documentStore":{"docInfo":{"0":{"body":83,"breadcrumbs":6,"title":5},"1":{"body":43,"breadcrumbs":2,"title":1},"10":{"body":9,"breadcrumbs":6,"title":4},"100":{"body":281,"breadcrumbs":4,"title":1},"101":{"body":5381,"breadcrumbs":4,"title":1},"102":{"body":2384,"breadcrumbs":5,"title":2},"11":{"body":17,"breadcrumbs":5,"title":3},"12":{"body":63,"breadcrumbs":6,"title":4},"13":{"body":9,"breadcrumbs":6,"title":4},"14":{"body":15,"breadcrumbs":4,"title":2},"15":{"body":3,"breadcrumbs":3,"title":1},"16":{"body":3,"breadcrumbs":3,"title":1},"17":{"body":12,"breadcrumbs":3,"title":1},"18":{"body":7,"breadcrumbs":3,"title":1},"19":{"body":9,"breadcrumbs":4,"title":2},"2":{"body":78,"breadcrumbs":3,"title":2},"20":{"body":14,"breadcrumbs":4,"title":2},"21":{"body":39,"breadcrumbs":5,"title":3},"22":{"body":124,"breadcrumbs":6,"title":4},"23":{"body":5,"breadcrumbs":4,"title":2},"24":{"body":14,"breadcrumbs":6,"title":4},"25":{"body":3,"breadcrumbs":3,"title":1},"26":{"body":49,"breadcrumbs":5,"title":3},"27":{"body":21,"breadcrumbs":6,"title":4},"28":{"body":36,"breadcrumbs":6,"title":4},"29":{"body":78,"breadcrumbs":4,"title":2},"3":{"body":17,"breadcrumbs":2,"title":1},"30":{"body":269,"breadcrumbs":4,"title":2},"31":{"body":194,"breadcrumbs":2,"title":1},"32":{"body":46,"breadcrumbs":4,"title":2},"33":{"body":1343,"breadcrumbs":6,"title":2},"34":{"body":309,"breadcrumbs":4,"title":1},"35":{"body":215,"breadcrumbs":5,"title":2},"36":{"body":24,"breadcrumbs":6,"title":2},"37":{"body":333,"breadcrumbs":5,"title":1},"38":{"body":184,"breadcrumbs":5,"title":1},"39":{"body":310,"breadcrumbs":4,"title":1},"4":{"body":26,"breadcrumbs":2,"title":1},"40":{"body":833,"breadcrumbs":7,"title":4},"41":{"body":227,"breadcrumbs":4,"title":1},"42":{"body":457,"breadcrumbs":7,"title":4},"43":{"body":171,"breadcrumbs":6,"title":3},"44":{"body":140,"breadcrumbs":7,"title":4},"45":{"body":593,"breadcrumbs":4,"title":1},"46":{"body":170,"breadcrumbs":8,"title":5},"47":{"body":203,"breadcrumbs":8,"title":5},"48":{"body":533,"breadcrumbs":4,"title":1},"49":{"body":101,"breadcrumbs":4,"title":1},"5":{"body":44,"breadcrumbs":3,"title":1},"50":{"body":682,"breadcrumbs":2,"title":1},"51":{"body":356,"breadcrumbs":6,"title":3},"52":{"body":195,"breadcrumbs":4,"title":2},"53":{"body":1359,"breadcrumbs":3,"title":1},"54":{"body":911,"breadcrumbs":3,"title":1},"55":{"body":294,"breadcrumbs":4,"title":2},"56":{"body":35,"breadcrumbs":3,"title":1},"57":{"body":215,"breadcrumbs":4,"title":2},"58":{"body":598,"breadcrumbs":3,"title":1},"59":{"body":282,"breadcrumbs":4,"title":2},"6":{"body":20,"breadcrumbs":3,"title":1},"60":{"body":581,"breadcrumbs":4,"title":2},"61":{"body":268,"breadcrumbs":4,"title":2},"62":{"body":73,"breadcrumbs":3,"title":1},"63":{"body":24,"breadcrumbs":6,"title":3},"64":{"body":534,"breadcrumbs":4,"title":1},"65":{"body":221,"breadcrumbs":5,"title":2},"66":{"body":1675,"breadcrumbs":5,"title":2},"67":{"body":540,"breadcrumbs":2,"title":1},"68":{"body":205,"breadcrumbs":3,"title":2},"69":{"body":483,"breadcrumbs":2,"title":1},"7":{"body":24,"breadcrumbs":3,"title":1},"70":{"body":659,"breadcrumbs":2,"title":1},"71":{"body":997,"breadcrumbs":2,"title":1},"72":{"body":0,"breadcrumbs":6,"title":3},"73":{"body":2999,"breadcrumbs":5,"title":2},"74":{"body":1055,"breadcrumbs":6,"title":3},"75":{"body":208,"breadcrumbs":2,"title":1},"76":{"body":47,"breadcrumbs":5,"title":4},"77":{"body":153,"breadcrumbs":4,"title":3},"78":{"body":154,"breadcrumbs":4,"title":3},"79":{"body":103,"breadcrumbs":5,"title":4},"8":{"body":5,"breadcrumbs":4,"title":2},"80":{"body":80,"breadcrumbs":3,"title":2},"81":{"body":122,"breadcrumbs":3,"title":2},"82":{"body":107,"breadcrumbs":2,"title":1},"83":{"body":428,"breadcrumbs":7,"title":6},"84":{"body":36,"breadcrumbs":4,"title":3},"85":{"body":52,"breadcrumbs":2,"title":1},"86":{"body":100,"breadcrumbs":2,"title":1},"87":{"body":21,"breadcrumbs":2,"title":1},"88":{"body":3,"breadcrumbs":2,"title":1},"89":{"body":0,"breadcrumbs":2,"title":1},"9":{"body":6,"breadcrumbs":5,"title":3},"90":{"body":9,"breadcrumbs":3,"title":2},"91":{"body":43,"breadcrumbs":4,"title":3},"92":{"body":6,"breadcrumbs":5,"title":4},"93":{"body":16,"breadcrumbs":2,"title":1},"94":{"body":11,"breadcrumbs":3,"title":2},"95":{"body":527,"breadcrumbs":7,"title":3},"96":{"body":2004,"breadcrumbs":6,"title":2},"97":{"body":0,"breadcrumbs":5,"title":2},"98":{"body":1174,"breadcrumbs":4,"title":1},"99":{"body":238,"breadcrumbs":5,"title":2}},"docs":{"0":{"body":"by Julian Hofer, with contributions from the community GTK 4 is the newest version of a popular cross-platform widget toolkit written in C. Thanks to GObject-Introspection, GTK's API can be easily targeted by various programming languages. The API even describes the ownership of its parameters! Managing ownership without giving up speed is one of Rust's greatest strengths, which makes it an excellent choice to develop GTK apps with. With this combination you don't have to worry about hitting bottlenecks mid-project anymore. Additionally, with Rust you will have nice things such as thread safety, memory safety, sensible dependency management as well as excellent third party libraries. The gtk-rs project provides bindings to many GTK-related libraries which we will be using throughout this book.","breadcrumbs":"Introduction » GUI development with Rust and GTK 4","id":"0","title":"GUI development with Rust and GTK 4"},"1":{"body":"This book assumes that you know your way around Rust code. If this is not already the case, reading The Rust Programming Language is an enjoyable way to get you to that stage. If you have experience with another low-level language such as C or C++ you might find that reading A half hour to learn Rust gives you sufficient information as well. Luckily, this — together with the wish to develop graphical applications — is all that is necessary to benefit from this book.","breadcrumbs":"Introduction » Who this book is for","id":"1","title":"Who this book is for"},"10":{"body":"Set the Rust toolchain to MSVC by executing: rustup default stable-msvc","breadcrumbs":"Installation » Windows » Set Rust toolchain to MSVC","id":"10","title":"Set Rust toolchain to MSVC"},"100":{"body":"We still need a way to store our collections. Just like we have already created TaskObject, we will now introduce CollectionObject. It will have the members title and tasks, both of which will be exposed as properties. As usual, the full implementation can be seen by clicking at the eye symbol at the top right of the snippet. Filename: listings/todo/8/collection_object/imp.rs # use std::cell::RefCell;\n# # use adw::prelude::*;\n# use adw::subclass::prelude::*;\n# use glib::Properties;\n# use gtk::{gio, glib};\n# use std::cell::OnceCell;\n# // Object holding the state\n#[derive(Properties, Default)]\n#[properties(wrapper_type = super::CollectionObject)]\npub struct CollectionObject { #[property(get, set)] pub title: RefCell, #[property(get, set)] pub tasks: OnceCell,\n} // The central trait for subclassing a GObject\n#[glib::object_subclass]\nimpl ObjectSubclass for CollectionObject { const NAME: &'static str = \"TodoCollectionObject\"; type Type = super::CollectionObject;\n}\n# # // Trait shared by all GObjects\n# #[glib::derived_properties]\n# impl ObjectImpl for CollectionObject {} We also add the struct CollectionData to aid in serialization and deserialization. Filename: listings/todo/8/collection_object/mod.rs # mod imp;\n# # use adw::prelude::*;\n# use adw::subclass::prelude::*;\n# use glib::Object;\n# use gtk::{gio, glib};\n# use serde::{Deserialize, Serialize};\n# # use crate::task_object::{TaskData, TaskObject};\n# # glib::wrapper! {\n# pub struct CollectionObject(ObjectSubclass);\n# }\n# # impl CollectionObject {\n# pub fn new(title: &str, tasks: gio::ListStore) -> Self {\n# Object::builder()\n# .property(\"title\", title)\n# .property(\"tasks\", tasks)\n# .build()\n# }\n# # pub fn to_collection_data(&self) -> CollectionData {\n# let title = self.imp().title.borrow().clone();\n# let tasks_data = self\n# .tasks()\n# .iter::()\n# .filter_map(Result::ok)\n# .map(|task_object| task_object.task_data())\n# .collect();\n# CollectionData { title, tasks_data }\n# }\n# # pub fn from_collection_data(collection_data: CollectionData) -> Self {\n# let title = collection_data.title;\n# let tasks_to_extend: Vec = collection_data\n# .tasks_data\n# .into_iter()\n# .map(TaskObject::from_task_data)\n# .collect();\n# # let tasks = gio::ListStore::new::();\n# tasks.extend_from_slice(&tasks_to_extend);\n# # Self::new(&title, tasks)\n# }\n# }\n# #[derive(Default, Clone, Serialize, Deserialize)]\npub struct CollectionData { pub title: String, pub tasks_data: Vec,\n} Finally, we add methods to CollectionObject in order to construct it with new, easily access the tasks ListStore with tasks and convert to and from CollectionData with to_collection_data and from_collection_data. Filename: listings/todo/8/collection_object/mod.rs # mod imp;\n# # use adw::prelude::*;\n# use adw::subclass::prelude::*;\n# use glib::Object;\n# use gtk::{gio, glib};\n# use serde::{Deserialize, Serialize};\n# # use crate::task_object::{TaskData, TaskObject};\n# # glib::wrapper! {\n# pub struct CollectionObject(ObjectSubclass);\n# }\n# impl CollectionObject { pub fn new(title: &str, tasks: gio::ListStore) -> Self { Object::builder() .property(\"title\", title) .property(\"tasks\", tasks) .build() } pub fn to_collection_data(&self) -> CollectionData { let title = self.imp().title.borrow().clone(); let tasks_data = self .tasks() .iter::() .filter_map(Result::ok) .map(|task_object| task_object.task_data()) .collect(); CollectionData { title, tasks_data } } pub fn from_collection_data(collection_data: CollectionData) -> Self { let title = collection_data.title; let tasks_to_extend: Vec = collection_data .tasks_data .into_iter() .map(TaskObject::from_task_data) .collect(); let tasks = gio::ListStore::new::(); tasks.extend_from_slice(&tasks_to_extend); Self::new(&title, tasks) }\n}\n# # #[derive(Default, Clone, Serialize, Deserialize)]\n# pub struct CollectionData {\n# pub title: String,\n# pub tasks_data: Vec,\n# }","breadcrumbs":"Libadwaita » Adding Collections » Collections","id":"100","title":"Collections"},"101":{"body":"In order to hook up the new logic, we have to add more state to imp::Window. There are additional widgets that we access via the template_child macro. Additionally, we reference the collections list store, the current_collection as well as the current_filter_model. We also store tasks_changed_handler_id. Its purpose will become clear in later snippets. Filename: listings/todo/8/window/imp.rs # use std::cell::RefCell;\n# use std::fs::File;\n# # use adw::subclass::prelude::*;\n# use adw::{prelude::*, NavigationSplitView};\n# use gio::Settings;\n# use glib::subclass::InitializingObject;\n# use gtk::glib::SignalHandlerId;\n# use gtk::{gio, glib, CompositeTemplate, Entry, FilterListModel, ListBox, Stack};\n# use std::cell::OnceCell;\n# # use crate::collection_object::{CollectionData, CollectionObject};\n# use crate::utils::data_path;\n# // Object holding the state\n#[derive(CompositeTemplate, Default)]\n#[template(resource = \"/org/gtk_rs/Todo8/window.ui\")]\npub struct Window { pub settings: OnceCell, #[template_child] pub entry: TemplateChild, #[template_child] pub tasks_list: TemplateChild, // 👇 all members below are new #[template_child] pub collections_list: TemplateChild, #[template_child] pub split_view: TemplateChild, #[template_child] pub stack: TemplateChild, pub collections: OnceCell, pub current_collection: RefCell