Use custom data types for keyboard and locale

This commit is contained in:
Ward from fusion-voyager-3 2024-08-22 00:06:34 +03:00
parent 785f820c50
commit e43de8ed74
4 changed files with 307 additions and 55 deletions

View File

@ -6,6 +6,19 @@ use crate::{
use gtk::{gio, glib, prelude::*}; use gtk::{gio, glib, prelude::*};
use std::{cell::RefCell, path::Path, rc::Rc}; use std::{cell::RefCell, path::Path, rc::Rc};
#[derive(Default, Clone, Debug)]
pub struct PikaLocale {
pub name: String,
pub pretty_name: String
}
#[derive(Default, Clone, Debug)]
pub struct PikaKeymap {
pub name: String,
pub variant: Option<String>,
pub pretty_name: String
}
pub fn build_ui(app: &adw::Application) { pub fn build_ui(app: &adw::Application) {
glib::set_prgname(Some("application_name")); glib::set_prgname(Some("application_name"));
glib::set_application_name(&t!("application_name")); glib::set_application_name(&t!("application_name"));
@ -53,9 +66,8 @@ pub fn build_ui(app: &adw::Application) {
_ => efi_error_page::efi_error_page(&window, &carousel), _ => efi_error_page::efi_error_page(&window, &carousel),
} }
let language_selection_text_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let language_selection_text_refcell: Rc<RefCell<PikaLocale>> = Rc::new(RefCell::default());
let keymap_base_selection_text_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let keymap_selection_text_refcell: Rc<RefCell<PikaKeymap>> = Rc::new(RefCell::default());
let keymap_varient_selection_text_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default());
let timezone_selection_text_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let timezone_selection_text_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default());
let partition_method_type_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let partition_method_type_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default());
let partition_method_automatic_target_refcell: Rc<RefCell<String>> = let partition_method_automatic_target_refcell: Rc<RefCell<String>> =
@ -87,8 +99,7 @@ pub fn build_ui(app: &adw::Application) {
keyboard_page::keyboard_page( keyboard_page::keyboard_page(
&carousel, &carousel,
&keymap_base_selection_text_refcell, &keymap_selection_text_refcell,
&keymap_varient_selection_text_refcell,
&language_changed_action, &language_changed_action,
); );

View File

@ -0,0 +1,239 @@
use crate::installer_stack_page;
use adw::prelude::*;
use glib::{clone, closure_local};
use gnome_desktop::XkbInfoExt;
use gtk::{gio, glib, prelude::*};
use std::{cell::RefCell, fs, path::Path, process::Command, rc::Rc};
struct PikaKeymap {
name: String,
pretty_name: String
}
pub fn keyboard_page(
main_carousel: &adw::Carousel,
keymap_base_data_refcell: &Rc<RefCell<String>>,
keymap_variant_data_refcell: &Rc<RefCell<String>>,
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);
keyboard_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 keyboard_selection_row_viewport_listbox = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None)
.build();
keyboard_selection_row_viewport_listbox.add_css_class("boxed-list");
keyboard_selection_row_viewport_listbox.add_css_class("round-border-only");
let keyboard_selection_row_viewport = gtk::ScrolledWindow::builder()
.vexpand(true)
.hexpand(true)
.has_frame(true)
.child(&keyboard_selection_row_viewport_listbox)
.build();
keyboard_selection_row_viewport.add_css_class("round-border-only-top-with-padding");
let keyboard_search_bar = gtk::SearchEntry::builder()
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.search_delay(500)
.build();
keyboard_search_bar.add_css_class("rounded-all-25");
let keyboard_test_entry_boxed_list = gtk::ListBox::builder()
.margin_top(5)
.margin_bottom(5)
.build();
keyboard_test_entry_boxed_list.add_css_class("boxed-list");
let keyboard_test_entry = adw::EntryRow::builder().build();
keyboard_test_entry_boxed_list.append(&keyboard_test_entry);
keyboard_test_entry_boxed_list.add_css_class("round-border-only-bottom");
let current_keymap = "us";
let xkbinfo = gnome_desktop::XkbInfo::new();
let keymap_list = gnome_desktop::XkbInfo::all_layouts(&xkbinfo);
let mut sorted_keymap_vec = Vec::new();
for keymap in keymap_list.iter() {
sorted_keymap_vec.push(PikaKeymap{
name: keymap.to_string(),
pretty_name: xkbinfo.layout_info(&keymap).unwrap().0.unwrap().to_string()
})
}
sorted_keymap_vec.sort_by_key(|k| k.pretty_name.clone());
for pika_keymap in sorted_keymap_vec {
let keymap = pika_keymap.name;
let keymap_name = pika_keymap.pretty_name;
let keymap_split: Vec<String> = keymap.split("+").map(|s| s.into()).collect();
let keymap_base = keymap_split.get(0).unwrap().clone();
let mut keymap_variant = String::new();
let mut split_index = 0;
for split in keymap_split {
split_index += 1;
if split_index == 1 {
continue;
}
keymap_variant.push_str(&split)
}
let keymap_clone = keymap.clone();
let keymap_checkbutton = gtk::CheckButton::builder()
.valign(gtk::Align::Center)
.can_focus(false)
.build();
let keymap_row = adw::ActionRow::builder()
.activatable_widget(&keymap_checkbutton)
.title(keymap_name)
.subtitle(keymap.clone())
.build();
keymap_row.add_prefix(&keymap_checkbutton);
keymap_checkbutton.set_group(Some(&null_checkbutton));
keyboard_selection_row_viewport_listbox.append(&keymap_row);
keymap_checkbutton.connect_toggled(clone!(
#[weak]
keymap_checkbutton,
#[strong]
keymap_base_data_refcell,
#[strong]
keymap_variant_data_refcell,
#[weak]
keyboard_page,
move |_| {
if keymap_checkbutton.is_active() == true {
keyboard_page.set_next_sensitive(true);
if keymap_variant.is_empty() {
*keymap_base_data_refcell.borrow_mut() = String::from(&keymap_base);
Command::new("setxkbmap")
.arg("-layout")
.arg(keymap_base.clone())
.spawn()
.expect("keyboard failed to start");
} else {
*keymap_base_data_refcell.borrow_mut() = String::from(&keymap_base);
*keymap_variant_data_refcell.borrow_mut() = String::from(&keymap_variant);
Command::new("setxkbmap")
.arg("-layout")
.arg(keymap_base.clone())
.arg("-variant")
.arg(keymap_variant.clone())
.spawn()
.expect("keyboard failed to start");
}
}
}
));
if current_keymap == keymap_clone {
keymap_checkbutton.set_active(true);
}
}
// / content_box appends
//// add text and and entry to keyboard page selections
content_box.append(&keyboard_search_bar);
content_box.append(&keyboard_selection_row_viewport);
content_box.append(&keyboard_test_entry_boxed_list);
keyboard_search_bar.connect_search_changed(clone!(
#[weak]
keyboard_search_bar,
#[weak]
keyboard_selection_row_viewport_listbox,
move |_| {
let mut counter = keyboard_selection_row_viewport_listbox.first_child();
while let Some(row) = counter {
if row.widget_name() == "AdwActionRow" {
if !keyboard_search_bar.text().is_empty() {
if row
.property::<String>("subtitle")
.to_lowercase()
.contains(&keyboard_search_bar.text().to_string().to_lowercase())
|| row
.property::<String>("title")
.to_lowercase()
.contains(&keyboard_search_bar.text().to_string().to_lowercase())
{
row.set_property("visible", true);
keyboard_search_bar.grab_focus();
} else {
row.set_property("visible", false);
}
} else {
row.set_property("visible", true);
}
}
counter = row.next_sibling();
}
}
));
keyboard_page.set_child_widget(&content_box);
//
language_changed_action.connect_activate(clone!(
#[weak]
keyboard_page,
#[weak]
keyboard_search_bar,
#[weak]
keyboard_test_entry,
move |_, _| {
keyboard_page.set_page_title(t!("keyboard_page_title"));
keyboard_page.set_page_subtitle(t!("keyboard_page_subtitle"));
keyboard_page.set_back_tooltip_label(t!("back"));
keyboard_page.set_next_tooltip_label(t!("next"));
//
keyboard_search_bar
.set_placeholder_text(Some(&t!("keyboard_search_bar_placeholder_text")));
//
keyboard_test_entry.set_title(&t!("keyboard_test_entry_title"))
}
));
//
keyboard_page.connect_closure(
"back-button-pressed",
false,
closure_local!(
#[weak]
main_carousel,
move |_keyboard_page: installer_stack_page::InstallerStackPage| {
main_carousel.scroll_to(&main_carousel.nth_page(2), true)
}
),
);
keyboard_page.connect_closure(
"next-button-pressed",
false,
closure_local!(
#[weak]
main_carousel,
move |_keyboard_page: installer_stack_page::InstallerStackPage| {
main_carousel.scroll_to(&main_carousel.nth_page(4), true)
}
),
);
main_carousel.append(&keyboard_page);
}

View File

@ -1,19 +1,13 @@
use crate::installer_stack_page; use crate::{build_ui::PikaKeymap, installer_stack_page};
use adw::prelude::*; use adw::prelude::*;
use glib::{clone, closure_local}; use glib::{clone, closure_local};
use gnome_desktop::XkbInfoExt; use gnome_desktop::XkbInfoExt;
use gtk::{gio, glib, prelude::*}; use gtk::{gio, glib, prelude::*};
use std::{cell::RefCell, fs, path::Path, process::Command, rc::Rc}; use std::{cell::RefCell, fs, path::Path, process::Command, rc::Rc};
struct PikaKeymap {
name: String,
pretty_name: String
}
pub fn keyboard_page( pub fn keyboard_page(
main_carousel: &adw::Carousel, main_carousel: &adw::Carousel,
keymap_base_data_refcell: &Rc<RefCell<String>>, keymap_data_refcell: &Rc<RefCell<PikaKeymap>>,
keymap_variant_data_refcell: &Rc<RefCell<String>>,
language_changed_action: &gio::SimpleAction, language_changed_action: &gio::SimpleAction,
) { ) {
let keyboard_page = installer_stack_page::InstallerStackPage::new(); let keyboard_page = installer_stack_page::InstallerStackPage::new();
@ -78,14 +72,8 @@ pub fn keyboard_page(
for keymap in keymap_list.iter() { for keymap in keymap_list.iter() {
sorted_keymap_vec.push(PikaKeymap{ sorted_keymap_vec.push(PikaKeymap{
name: keymap.to_string(), name: keymap.to_string(),
pretty_name: xkbinfo.layout_info(&keymap).unwrap().0.unwrap().to_string() pretty_name: xkbinfo.layout_info(&keymap).unwrap().0.unwrap().to_string(),
}) variant: {
}
sorted_keymap_vec.sort_by_key(|k| k.pretty_name.clone());
for pika_keymap in sorted_keymap_vec {
let keymap = pika_keymap.name;
let keymap_name = pika_keymap.pretty_name;
let keymap_split: Vec<String> = keymap.split("+").map(|s| s.into()).collect(); let keymap_split: Vec<String> = keymap.split("+").map(|s| s.into()).collect();
let keymap_base = keymap_split.get(0).unwrap().clone(); let keymap_base = keymap_split.get(0).unwrap().clone();
let mut keymap_variant = String::new(); let mut keymap_variant = String::new();
@ -97,7 +85,22 @@ pub fn keyboard_page(
} }
keymap_variant.push_str(&split) keymap_variant.push_str(&split)
} }
let keymap_clone = keymap.clone(); if keymap_variant.is_empty() {
None
} else {
Some(keymap_variant)
}
}
})
}
sorted_keymap_vec.sort_by_key(|k| k.pretty_name.clone());
for pika_keymap in sorted_keymap_vec {
let keymap_clone0 = pika_keymap.clone();
let keymap_clone1 = pika_keymap.clone();
let keymap = pika_keymap.name;
let keymap_name = pika_keymap.pretty_name;
let keymap_variant = pika_keymap.variant;
let keymap_checkbutton = gtk::CheckButton::builder() let keymap_checkbutton = gtk::CheckButton::builder()
.valign(gtk::Align::Center) .valign(gtk::Align::Center)
.can_focus(false) .can_focus(false)
@ -114,36 +117,37 @@ pub fn keyboard_page(
#[weak] #[weak]
keymap_checkbutton, keymap_checkbutton,
#[strong] #[strong]
keymap_base_data_refcell, keymap_data_refcell,
#[strong] #[strong]
keymap_variant_data_refcell, keymap_clone0,
#[weak] #[weak]
keyboard_page, keyboard_page,
move |_| { move |_| {
if keymap_checkbutton.is_active() == true { if keymap_checkbutton.is_active() == true {
*keymap_data_refcell.borrow_mut() = keymap_clone0.clone();
keyboard_page.set_next_sensitive(true); keyboard_page.set_next_sensitive(true);
if keymap_variant.is_empty() { match keymap_variant.clone() {
*keymap_base_data_refcell.borrow_mut() = String::from(&keymap_base); Some(t) => {
Command::new("setxkbmap") Command::new("setxkbmap")
.arg("-layout") .arg("-layout")
.arg(keymap_base.clone()) .arg(&keymap_clone0.name)
.spawn()
.expect("keyboard failed to start");
} else {
*keymap_base_data_refcell.borrow_mut() = String::from(&keymap_base);
*keymap_variant_data_refcell.borrow_mut() = String::from(&keymap_variant);
Command::new("setxkbmap")
.arg("-layout")
.arg(keymap_base.clone())
.arg("-variant") .arg("-variant")
.arg(keymap_variant.clone()) .arg(t)
.spawn() .spawn()
.expect("keyboard failed to start"); .expect("keyboard failed to start");
} }
None => {
Command::new("setxkbmap")
.arg("-layout")
.arg(&keymap_clone0.name)
.spawn()
.expect("keyboard failed to start");
}
}
} }
} }
)); ));
if current_keymap == keymap_clone { if current_keymap == keymap_clone1.name {
keymap_checkbutton.set_active(true); keymap_checkbutton.set_active(true);
} }
} }

View File

@ -1,17 +1,12 @@
use crate::installer_stack_page; use crate::{build_ui::PikaLocale, installer_stack_page};
use adw::prelude::*; use adw::prelude::*;
use glib::{clone, closure_local}; use glib::{clone, closure_local};
use gtk::{gio, glib, prelude::*}; use gtk::{gio, glib, prelude::*};
use std::{cell::RefCell, env, fs, path::Path, process::Command, rc::Rc}; use std::{cell::RefCell, env, fs, path::Path, process::Command, rc::Rc};
struct PikaLocale {
name: String,
pretty_name: String
}
pub fn language_page( pub fn language_page(
main_carousel: &adw::Carousel, main_carousel: &adw::Carousel,
lang_data_refcell: &Rc<RefCell<String>>, lang_data_refcell: &Rc<RefCell<PikaLocale>>,
language_changed_action: &gio::SimpleAction, language_changed_action: &gio::SimpleAction,
) { ) {
let language_page = installer_stack_page::InstallerStackPage::new(); let language_page = installer_stack_page::InstallerStackPage::new();
@ -99,6 +94,7 @@ pub fn language_page(
sorted_locale_vec.sort_by_key(|k| k.pretty_name.clone()); sorted_locale_vec.sort_by_key(|k| k.pretty_name.clone());
for pika_locale in sorted_locale_vec { for pika_locale in sorted_locale_vec {
let pika_locale_clone0 = pika_locale.clone();
let locale = pika_locale.name; let locale = pika_locale.name;
let locale_clone0 = locale.clone(); let locale_clone0 = locale.clone();
let locale_name = pika_locale.pretty_name; let locale_name = pika_locale.pretty_name;
@ -119,12 +115,14 @@ pub fn language_page(
locale_checkbutton, locale_checkbutton,
#[strong] #[strong]
lang_data_refcell, lang_data_refcell,
#[strong]
pika_locale_clone0,
#[weak] #[weak]
language_page, language_page,
move |_| { move |_| {
if locale_checkbutton.is_active() == true { if locale_checkbutton.is_active() == true {
language_page.set_next_sensitive(true); language_page.set_next_sensitive(true);
*lang_data_refcell.borrow_mut() = String::from(&locale); *lang_data_refcell.borrow_mut() = pika_locale_clone0.clone();
} }
} }
)); ));
@ -208,7 +206,7 @@ pub fn language_page(
// .arg("LANG=".to_owned() + &locale + ".UTF-8") // .arg("LANG=".to_owned() + &locale + ".UTF-8")
// .spawn() // .spawn()
// .expect("locale failed to start"); // .expect("locale failed to start");
rust_i18n::set_locale(&locale); rust_i18n::set_locale(&locale.name);
language_changed_action.activate(None); language_changed_action.activate(None);
main_carousel.scroll_to(&main_carousel.nth_page(2), true) main_carousel.scroll_to(&main_carousel.nth_page(2), true)
} }