diff --git a/Cargo.toml b/Cargo.toml index 12f4384..3bfd0e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -adw = { version = "0.5.3", package = "libadwaita" } +adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] } async-channel = "2.1.1" fragile = "2.0.0" glib = "0.18.5" -gtk = { version = "0.7.3", package = "gtk4" } +gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] } time = "0.3.31" diff --git a/src/build_ui.rs b/src/build_ui.rs index d29359b..2b1d63f 100644 --- a/src/build_ui.rs +++ b/src/build_ui.rs @@ -11,6 +11,7 @@ use gtk::subclass::layout_child; use crate::save_window_size; use crate::welcome_page; use crate::language_page; +use crate::keyboard_page; // build ui function linked to app startup above pub fn build_ui(app: &adw::Application) { @@ -23,9 +24,6 @@ pub fn build_ui(app: &adw::Application) { // Widget Bank - let gtk_loops = true; - - /// Create A box let _main_box = gtk::Box::builder() // that puts items vertically @@ -100,6 +98,9 @@ pub fn build_ui(app: &adw::Application) { // Add language_page.rs as a page for content_stack language_page(&content_stack); + // Add keyboard_page.rs as a page for content_stack + keyboard_page(&content_stack); + // glib maximization if glib_settings.boolean("is-maximized") == true { window.maximize() diff --git a/src/keyboard_page.rs b/src/keyboard_page.rs new file mode 100644 index 0000000..768a92c --- /dev/null +++ b/src/keyboard_page.rs @@ -0,0 +1,215 @@ +// Use libraries +/// Use all gtk4 libraries (gtk4 -> gtk because cargo) +/// Use all libadwaita libraries (libadwaita -> adw because cargo) +use gtk::prelude::*; +use gtk::*; +use adw::prelude::*; +use adw::*; +use glib::*; +use gdk::Display; +use gtk::subclass::layout_child; + +use std::io::BufRead; +use std::io::BufReader; +use std::process::Command; +use std::process::Stdio; +use std::time::Instant; + +pub fn keyboard_page(content_stack: >k::Stack) { + + // create the bottom box for next and back buttons + let bottom_box = gtk::Box::builder() + .orientation(Orientation::Horizontal) + .valign(gtk::Align::End) + .vexpand(true) + .build(); + + // Next and back button + let bottom_back_button = gtk::Button::builder() + .label("Back") + .margin_top(15) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .halign(gtk::Align::Start) + .hexpand(true) + .build(); + let bottom_next_button = gtk::Button::builder() + .label("Next") + .margin_top(15) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .halign(gtk::Align::End) + .hexpand(true) + .sensitive(false) + .build(); + + // Start Applying css classes + bottom_next_button.add_css_class("suggested-action"); + + // / bottom_box appends + //// Add the next and back buttons + bottom_box.append(&bottom_back_button); + bottom_box.append(&bottom_next_button); + + // the header box for the keyboard page + let keyboard_main_box = gtk::Box::builder() + .orientation(Orientation::Vertical) + .build(); + + // the header box for the keyboard page + let keyboard_header_box = gtk::Box::builder() + .orientation(Orientation::Horizontal) + .build(); + + // the header text for the keyboard page + let keyboard_header_text = gtk::Label::builder() + .label("Select a keyboard") + .halign(gtk::Align::End) + .hexpand(true) + .margin_top(15) + .margin_bottom(15) + .margin_start(15) + .margin_end(5) + .build(); + keyboard_header_text.add_css_class("header_sized_text"); + + // the header icon for the keyboard icon + let keyboard_header_icon = gtk::Image::builder() + .icon_name("keyboard") + .halign(gtk::Align::Start) + .hexpand(true) + .pixel_size(78) + .margin_top(15) + .margin_bottom(15) + .margin_start(0) + .margin_end(15) + .build(); + + // make keyboard selection box for choosing installation or live media + let keyboard_selection_box = gtk::Box::builder() + .orientation(Orientation::Vertical) + .build(); + + // / keyboard_header_box appends + //// Add the keyboard page header text and icon + keyboard_header_box.append(&keyboard_header_text); + keyboard_header_box.append(&keyboard_header_icon); + + // / keyboard_main_box appends + //// Add the keyboard header to keyboard main box + keyboard_main_box.append(&keyboard_header_box); + //// Add the keyboard selection/page content box to keyboard main box + keyboard_main_box.append(&keyboard_selection_box); + + // text above keyboard selection box + let keyboard_selection_text = gtk::Label::builder() + .label("Please select a Keyboard layout for the system to use") + .halign(gtk::Align::Center) + .hexpand(true) + .margin_top(15) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .build(); + keyboard_selection_text.add_css_class("medium_sized_text"); + + let keyboard_selection_expander_row = adw::ExpanderRow::builder() + .margin_top(15) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .title("No Keyboard Layout selected") + .build(); + + let null_checkbutton = gtk::CheckButton::builder() + .label("No Keyboard Layout selected") + .build(); + + let keyboard_selection_expander_row_viewport = gtk::ScrolledWindow::builder() + .height_request(200) + .build(); + + let keyboard_selection_expander_row_viewport_box = gtk::Box::builder() + .orientation(Orientation::Vertical) + .build(); + + keyboard_selection_expander_row_viewport.set_child(Some(&keyboard_selection_expander_row_viewport_box)); + + keyboard_selection_expander_row.add_row(&keyboard_selection_expander_row_viewport); + + keyboard_selection_expander_row_viewport_box.append(&null_checkbutton); + + let null_checkbutton_clone = null_checkbutton.clone(); + let keyboard_selection_expander_row_clone2 = keyboard_selection_expander_row.clone(); + let bottom_next_button_clone = bottom_next_button.clone(); + + + null_checkbutton.connect_toggled(move |_| { + if null_checkbutton_clone.is_active() == true { + keyboard_selection_expander_row_clone2.set_title("No Keyboard Layout selected"); + bottom_next_button_clone.set_sensitive(false); + } + }); + + let mut keyboard_layout_cli = Command::new("localectl") + .arg("list-x11-keymap-layouts") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .unwrap_or_else(|e| panic!("failed {}", e)); + + let keyboard_layout_stdout = keyboard_layout_cli.stdout.as_mut().expect("could not get stdout"); + let keyboard_layout_reader = BufReader::new(keyboard_layout_stdout); + + for keyboard_layout in keyboard_layout_reader.lines() { + let keyboard_layout = keyboard_layout.unwrap(); + let keyboard_layout_checkbutton = gtk::CheckButton::builder() + .label(keyboard_layout.clone()) + .build(); + keyboard_layout_checkbutton.set_group(Some(&null_checkbutton)); + keyboard_selection_expander_row_viewport_box.append(&keyboard_layout_checkbutton); + let keyboard_selection_expander_row_clone = keyboard_selection_expander_row.clone(); + let keyboard_layout_checkbutton_clone = keyboard_layout_checkbutton.clone(); + let bottom_next_button_clone2 = bottom_next_button.clone(); + keyboard_layout_checkbutton.connect_toggled(move |_| { + if keyboard_layout_checkbutton_clone.is_active() == true { + keyboard_selection_expander_row_clone.set_title(&keyboard_layout); + bottom_next_button_clone2.set_sensitive(true); + } + }); + } + + // / keyboard_selection_box appends + //// add text and and entry to keyboard page selections + keyboard_selection_box.append(&keyboard_selection_text); + keyboard_selection_box.append(&keyboard_selection_expander_row); + + // / keyboard_header_box appends + //// Add the keyboard page header text and icon + keyboard_header_box.append(&keyboard_header_text); + keyboard_header_box.append(&keyboard_header_icon); + + // / keyboard_main_box appends + //// Add the keyboard header to keyboard main box + keyboard_main_box.append(&keyboard_header_box); + //// Add the keyboard selection/page content box to keyboard main box + keyboard_main_box.append(&keyboard_selection_box); + + keyboard_main_box.append(&bottom_box); + + // / Content stack appends + //// Add the keyboard_main_box as page: keyboard_page, Give it nice title + content_stack.add_titled(&keyboard_main_box, Some("keyboard_page"), "Keyboard"); + + let content_stack_clone = content_stack.clone(); + let content_stack_clone2 = content_stack.clone(); + bottom_next_button.connect_clicked(move |_| { + content_stack_clone.set_visible_child_name("partitioning_page") + }); + bottom_back_button.connect_clicked(move |_| { + content_stack_clone2.set_visible_child_name("language_page") + }); + +} diff --git a/src/language_page.rs b/src/language_page.rs index e16de9e..00b8492 100644 --- a/src/language_page.rs +++ b/src/language_page.rs @@ -116,76 +116,104 @@ pub fn language_page(content_stack: >k::Stack) { .build(); language_selection_text.add_css_class("medium_sized_text"); - let language_selection_expander_row = adw::ExpanderRow::builder() + let language_selection_expander_row = gtk::Entry::builder() .margin_top(15) - .margin_bottom(15) .margin_start(15) .margin_end(15) - .title("Locale") .build(); let null_checkbutton = gtk::CheckButton::builder() - .label("No locale selected") + .valign(Align::Center) + .can_focus(false) .build(); let language_selection_expander_row_viewport = gtk::ScrolledWindow::builder() .height_request(200) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) .build(); - let language_selection_expander_row_viewport_box = gtk::Box::builder() - .orientation(Orientation::Vertical) + let language_selection_expander_row_viewport_box = gtk::ListBox::builder() + .selection_mode(SelectionMode::None) .build(); + language_selection_expander_row_viewport_box.add_css_class("boxed-list"); language_selection_expander_row_viewport.set_child(Some(&language_selection_expander_row_viewport_box)); - language_selection_expander_row.add_row(&language_selection_expander_row_viewport); + language_selection_expander_row.set_placeholder_text(Some("No locale selected")); - language_selection_expander_row_viewport_box.append(&null_checkbutton); + let null_action_row = adw::ActionRow::builder() + .title("No locale selected") + .activatable_widget(&null_checkbutton) + .build(); + null_action_row.add_prefix(&null_checkbutton); + + language_selection_expander_row_viewport_box.append(&null_action_row); let null_checkbutton_clone = null_checkbutton.clone(); let language_selection_expander_row_clone2 = language_selection_expander_row.clone(); let bottom_next_button_clone = bottom_next_button.clone(); - - null_checkbutton.connect_toggled(move |_| { - if null_checkbutton_clone.is_active() == true { - language_selection_expander_row_clone2.set_title("No locale selected"); - bottom_next_button_clone.set_sensitive(false); - } - }); - let mut locale_cli = Command::new("locale") .arg("-a") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() .unwrap_or_else(|e| panic!("failed {}", e)); - - let locale_stdout = locale_cli.stdout.as_mut().expect("could not get stdout"); - let locale_reader = BufReader::new(locale_stdout); - + let mut locale_cli_cut = Command::new("cut") + .arg("-d.") + .arg("-f1") + .stdin(Stdio::from(locale_cli.stdout.unwrap())) // Pipe through. + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + let mut locale_cli_sort = Command::new("sort") + .arg("-u") + .stdin(Stdio::from(locale_cli_cut.stdout.unwrap())) + .stdout(Stdio::piped()) + .spawn() + .unwrap(); + + let locale_reader = BufReader::new(locale_cli_sort.stdout.as_mut().expect("could not get stdout")); + for locale in locale_reader.lines() { let locale = locale.unwrap(); let locale_checkbutton = gtk::CheckButton::builder() - .label(locale.clone()) + .valign(Align::Center) + .can_focus(false) .build(); locale_checkbutton.set_group(Some(&null_checkbutton)); - language_selection_expander_row_viewport_box.append(&locale_checkbutton); + let locale_action_row = adw::ActionRow::builder() + .title(locale.clone()) + .activatable_widget(&locale_checkbutton) + .build(); + locale_action_row.add_prefix(&locale_checkbutton); + language_selection_expander_row_viewport_box.append(&locale_action_row); let language_selection_expander_row_clone = language_selection_expander_row.clone(); let locale_checkbutton_clone = locale_checkbutton.clone(); let bottom_next_button_clone2 = bottom_next_button.clone(); locale_checkbutton.connect_toggled(move |_| { if locale_checkbutton_clone.is_active() == true { - language_selection_expander_row_clone.set_title(&locale); + language_selection_expander_row_clone.set_text(&locale); bottom_next_button_clone2.set_sensitive(true); } }); } + + null_checkbutton.connect_toggled(move |_| { + if null_checkbutton_clone.is_active() == true { + language_selection_expander_row_clone2.set_text(" "); + bottom_next_button_clone.set_sensitive(false); + } + }); + // / language_selection_box appends //// add text and and entry to language page selections language_selection_box.append(&language_selection_text); language_selection_box.append(&language_selection_expander_row); + language_selection_box.append(&language_selection_expander_row_viewport); // / language_header_box appends //// Add the language page header text and icon diff --git a/src/main.rs b/src/main.rs index 4bbc50b..2413f52 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,9 +14,11 @@ use crate::build_ui::build_ui; mod save_window_size; mod welcome_page; mod language_page; +mod keyboard_page; use crate::save_window_size::save_window_size; use crate::welcome_page::welcome_page; use crate::language_page::language_page; +use crate::keyboard_page::keyboard_page; /// main function @@ -36,6 +38,5 @@ fn main() { app.connect_activate(build_ui); }); - application.run(); }