From 806f415178a69e152156cb6e5c3dc534dfb1d5cf Mon Sep 17 00:00:00 2001 From: Ward from fusion-voyager-3 Date: Wed, 7 Aug 2024 02:02:56 +0300 Subject: [PATCH] Add timezone Page --- locales/en_US.json | 3 +- src/build_ui.rs | 4 +- src/eula_page/mod.rs | 3 +- src/installer_stack_page/imp.rs | 4 +- src/keyboard_page/mod.rs | 10 +- src/language_page/mod.rs | 8 +- src/main.rs | 1 + src/timezone_page/mod.rs | 210 ++++++++++++++++++++++++++++++++ 8 files changed, 227 insertions(+), 16 deletions(-) create mode 100644 src/timezone_page/mod.rs diff --git a/locales/en_US.json b/locales/en_US.json index b531652..e69797e 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -96,5 +96,6 @@ "luks2_password_confirm": "Confirm LUKS Password", "luks_not_match": "The LUKS Passwords do not match!", "search_for_language": "Search for a Language", - "search_for_keyboard": "Search for a Keyboard Layout" + "search_for_keyboard": "Search for a Keyboard Layout", + "search_for_timezone": "Search for a Timezone" } diff --git a/src/build_ui.rs b/src/build_ui.rs index fd12758..c96ab9c 100644 --- a/src/build_ui.rs +++ b/src/build_ui.rs @@ -1,6 +1,6 @@ use std::path::Path; use gtk::{prelude::*, glib as glib, gio as gio}; -use crate::{efi_error_page, welcome_page, language_page, eula_page, keyboard_page}; +use crate::{efi_error_page, welcome_page, language_page, eula_page, keyboard_page, timezone_page}; pub fn build_ui(app: &adw::Application) { glib::set_prgname(Some("pikaos_installer")); @@ -57,5 +57,7 @@ pub fn build_ui(app: &adw::Application) { keyboard_page::keyboard_page(&carousel, &language_changed_action); + timezone_page::timezone_page(&carousel, &language_changed_action); + window.present() } \ No newline at end of file diff --git a/src/eula_page/mod.rs b/src/eula_page/mod.rs index 6c4a877..41fe50a 100644 --- a/src/eula_page/mod.rs +++ b/src/eula_page/mod.rs @@ -1,6 +1,5 @@ use adw::gio; use crate::installer_stack_page; -use crate::config; use gtk::{prelude::*, glib as glib}; use glib::{clone, closure_local}; @@ -9,6 +8,7 @@ pub fn eula_page( language_changed_action: &gio::SimpleAction ) { let eula_page = installer_stack_page::InstallerStackPage::new(); + eula_page.set_page_icon("error-correct-symbolic"); eula_page.set_back_visible(true); eula_page.set_next_visible(true); eula_page.set_back_sensitive(true); @@ -81,7 +81,6 @@ pub fn eula_page( move |_, _| { eula_page.set_page_title(t!("eula")); eula_page.set_page_subtitle(t!("pikaos_eula_agreement")); - eula_page.set_page_icon("error-correct-symbolic"); eula_page.set_back_tooltip_label(t!("back")); eula_page.set_next_tooltip_label(t!("next")); // diff --git a/src/installer_stack_page/imp.rs b/src/installer_stack_page/imp.rs index d662240..1e3a0b6 100644 --- a/src/installer_stack_page/imp.rs +++ b/src/installer_stack_page/imp.rs @@ -1,7 +1,7 @@ -use std::{cell::RefCell, env, rc::Rc, sync::OnceLock}; +use std::{cell::RefCell, rc::Rc, sync::OnceLock}; use gtk::{prelude::*, subclass::prelude::*, glib as glib, Justification}; use adw::{prelude::*, subclass::prelude::*}; -use glib::{clone, subclass::prelude::*, subclass::Signal}; +use glib::{clone, subclass::Signal}; // ANCHOR: custom_button // Object holding the state diff --git a/src/keyboard_page/mod.rs b/src/keyboard_page/mod.rs index 8642505..6243a21 100644 --- a/src/keyboard_page/mod.rs +++ b/src/keyboard_page/mod.rs @@ -1,17 +1,16 @@ use crate::installer_stack_page; -use crate::config; use gnome_desktop::XkbInfoExt; use gtk::{prelude::*, glib as glib, gio as gio}; use adw::{prelude::*}; use glib::{clone, closure_local}; -use std::{process::Command, env, fs, path::Path}; -use gtk::ResponseType::No; +use std::{process::Command, fs, path::Path}; pub fn keyboard_page( main_carousel: &adw::Carousel, language_changed_action: &gio::SimpleAction ) { let keyboard_page = installer_stack_page::InstallerStackPage::new(); + keyboard_page.set_page_icon("keyboard-symbolic"); keyboard_page.set_back_visible(true); keyboard_page.set_next_visible(true); keyboard_page.set_back_sensitive(true); @@ -145,7 +144,7 @@ pub fn keyboard_page( } } )); - if current_keymap.contains(&(keymap_clone)) { + if current_keymap == keymap_clone { keymap_checkbutton.set_active(true); } } @@ -196,7 +195,6 @@ pub fn keyboard_page( move |_, _| { keyboard_page.set_page_title(t!("keyboard")); keyboard_page.set_page_subtitle(t!("select_a_keyboard")); - keyboard_page.set_page_icon("keyboard-symbolic"); keyboard_page.set_back_tooltip_label(t!("back")); keyboard_page.set_next_tooltip_label(t!("next")); // @@ -244,7 +242,7 @@ pub fn keyboard_page( base_data_text ).expect("Unable to write file"); if Path::new("/tmp/pika-installer-gtk4-keyboard-variant.txt").exists() { - fs::remove_file("/tmp/pika-installer-gtk4-variant.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-keyboard-variant.txt"); + fs::remove_file("/tmp/pika-installer-gtk4-keyboard-variant.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-keyboard-variant.txt"); } let varient_data_text = keymap_variant_data_buffer_clone0 .text( diff --git a/src/language_page/mod.rs b/src/language_page/mod.rs index 7278391..af830be 100644 --- a/src/language_page/mod.rs +++ b/src/language_page/mod.rs @@ -1,10 +1,8 @@ use crate::installer_stack_page; -use crate::config; use gtk::{prelude::*, glib as glib, gio as gio}; use adw::{prelude::*}; use glib::{clone, closure_local}; use std::{process::Command, env, fs, path::Path}; -use gtk::ResponseType::No; pub fn language_page( main_carousel: &adw::Carousel, @@ -62,7 +60,9 @@ pub fn language_page( language_search_bar.add_css_class("rounded-all-25"); let current_locale = match env::var_os("LANG") { - Some(v) => v.into_string().unwrap(), + Some(v) => v.into_string().unwrap().chars() + .take_while(|&ch| ch != '.') + .collect::(), None => panic!("$LANG is not set"), }; @@ -262,7 +262,7 @@ pub fn language_page( } } )); - if current_locale.contains(&(locale_clone)) + if ¤t_locale == &locale_clone && current_locale != "C.UTF-8" && current_locale != "C" && current_locale != "C.utf8" diff --git a/src/main.rs b/src/main.rs index 169ef72..8f5e046 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ mod welcome_page; mod language_page; mod eula_page; mod keyboard_page; +mod timezone_page; #[macro_use] extern crate rust_i18n; diff --git a/src/timezone_page/mod.rs b/src/timezone_page/mod.rs new file mode 100644 index 0000000..17ae857 --- /dev/null +++ b/src/timezone_page/mod.rs @@ -0,0 +1,210 @@ +use crate::installer_stack_page; +use gtk::{prelude::*, glib as glib, gio as gio}; +use adw::{prelude::*}; +use glib::{clone, closure_local}; +use std::{process::Command, fs, path::Path}; +use std::io::BufRead; + +pub fn timezone_page( + main_carousel: &adw::Carousel, + language_changed_action: &gio::SimpleAction +) { + let timezone_page = installer_stack_page::InstallerStackPage::new(); + timezone_page.set_page_icon("alarm-symbolic"); + timezone_page.set_back_visible(true); + timezone_page.set_next_visible(true); + timezone_page.set_back_sensitive(true); + timezone_page.set_next_sensitive(false); + + let content_box = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .hexpand(true) + .vexpand(true) + .build(); + + let null_checkbutton = gtk::CheckButton::builder() + .build(); + + let timezone_selection_row_viewport = + gtk::ScrolledWindow::builder() + .vexpand(true) + .hexpand(true) + .build(); + + let timezone_selection_row_viewport_box = gtk::ListBox::builder().build(); + timezone_selection_row_viewport_box.add_css_class("boxed-list"); + + timezone_selection_row_viewport + .set_child(Some(&timezone_selection_row_viewport_box)); + + let timezone_selection_row_viewport_listbox = gtk::ListBox::builder() + .selection_mode(gtk::SelectionMode::None) + .margin_top(15) + .margin_bottom(15) + .margin_start(15) + .margin_end(15) + .build(); + timezone_selection_row_viewport_listbox.add_css_class("boxed-list"); + + let timezone_search_bar = gtk::SearchEntry::builder() + .hexpand(true) + .margin_top(15) + .margin_bottom(15) + .search_delay(500) + .build(); + + timezone_search_bar.add_css_class("rounded-all-25"); + + let current_timezone_cli = Command::new("timedatectl") + .arg("show") + .arg("--va") + .arg("-p") + .arg("Timezone") + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .unwrap_or_else(|e| panic!("failed {}", e)); + + let current_timezone_output = current_timezone_cli.wait_with_output().unwrap(); + let current_timezone = String::from_utf8_lossy(¤t_timezone_output.stdout).trim().to_owned(); + + let timezone_cli = Command::new("timedatectl") + .arg("list-timezones") + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .unwrap_or_else(|e| panic!("failed {}", e)); + + let timezone_stdout = timezone_cli.stdout.expect("could not get stdout"); + let timezone_reader = std::io::BufReader::new(timezone_stdout); + + let timezone_data_buffer = gtk::TextBuffer::builder().build(); + let timezone_data_buffer_clone0 = timezone_data_buffer.clone(); + + for timezone in timezone_reader.lines() { + let timezone = timezone.unwrap(); + let timezone_clone = timezone.clone(); + let timezone_checkbutton = gtk::CheckButton::builder() + .valign(gtk::Align::Center) + .can_focus(false) + .build(); + let timezone_row = adw::ActionRow::builder() + .activatable_widget(&timezone_checkbutton) + .title(timezone.clone()) + .build(); + timezone_row.add_prefix(&timezone_checkbutton); + timezone_checkbutton.set_group(Some(&null_checkbutton)); + timezone_selection_row_viewport_box.append(&timezone_row); + timezone_checkbutton.connect_toggled( + clone!( + #[weak] + timezone_checkbutton, + #[weak] + timezone_page, + #[weak] + timezone_data_buffer, + move |_| + { + if timezone_checkbutton.is_active() == true { + timezone_page.set_next_sensitive(true); + timezone_data_buffer.set_text(&timezone); + } + } + ) + ); + if ¤t_timezone == &timezone_clone { + timezone_checkbutton.set_active(true); + } + } + + // / content_box appends + //// add text and and entry to timezone page selections + content_box.append(&timezone_search_bar); + content_box.append(&timezone_selection_row_viewport); + + timezone_search_bar.connect_search_changed(clone!( + #[weak] + timezone_search_bar, + #[weak] + timezone_selection_row_viewport_box, + move |_| + { + let mut counter = timezone_selection_row_viewport_box.first_child(); + while let Some(row) = counter { + if row.widget_name() == "AdwActionRow" { + if !timezone_search_bar.text().is_empty() { + if row.property::("subtitle").to_lowercase().contains(&timezone_search_bar.text().to_string().to_lowercase()) || row.property::("title").to_lowercase().contains(&timezone_search_bar.text().to_string().to_lowercase()) { + row.set_property("visible", true); + timezone_search_bar.grab_focus(); + } else { + row.set_property("visible", false); + } + } else { + row.set_property("visible", true); + } + } + counter = row.next_sibling(); + } + } + )); + + timezone_page.set_child_widget(&content_box); + + // + language_changed_action.connect_activate( + clone!( + #[weak] + timezone_page, + #[weak] + timezone_search_bar, + move |_, _| { + timezone_page.set_page_title(t!("timezone")); + timezone_page.set_page_subtitle(t!("select_a_timezone")); + timezone_page.set_back_tooltip_label(t!("back")); + timezone_page.set_next_tooltip_label(t!("next")); + // + timezone_search_bar.set_placeholder_text(Some(&t!("search_for_timezone"))); + } + ) + ); + // + + timezone_page.connect_closure( + "back-button-pressed", + false, + closure_local!( + #[weak] + main_carousel, + move |_timezone_page: installer_stack_page::InstallerStackPage| + { + main_carousel.scroll_to(&main_carousel.nth_page(3), true) + } + ) + ); + + timezone_page.connect_closure( + "next-button-pressed", + false, + closure_local!( + #[weak] + main_carousel, + move |_timezone_page: installer_stack_page::InstallerStackPage| + { + let timezone_selection = timezone_data_buffer_clone0.text(&timezone_data_buffer_clone0.bounds().0, &timezone_data_buffer_clone0.bounds().1, true).to_string(); + if Path::new("/tmp/pika-installer-gtk4-timezone.txt").exists() { + fs::remove_file("/tmp/pika-installer-gtk4-timezone.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-timezone.txt"); + } + fs::write("/tmp/pika-installer-gtk4-timezone.txt", &timezone_selection).expect("Unable to write file"); + Command::new("sudo") + .arg("timedatectl") + .arg("set-timezone") + .arg(&timezone_selection) + .spawn() + .expect("timezone failed to start"); + main_carousel.scroll_to(&main_carousel.nth_page(5), true) + } + ) + ); + + main_carousel.append(&timezone_page); +} \ No newline at end of file