More work on keyboard stage, now compiling.

This commit is contained in:
2026-05-06 23:21:12 +02:00
parent 8b3f22909e
commit 9081e301d4
2 changed files with 97 additions and 78 deletions
+5 -2
View File
@@ -22,6 +22,9 @@
"timezone.select_timezone": "Please select preffered time zone", "timezone.select_timezone": "Please select preffered time zone",
"timezone.init_error": "Error getting time zones data from system!", "timezone.init_error": "Error getting time zones data from system!",
"locale.select_language_locale": "The system language will be set to", "locale.select_language_locale": "The system language will be set to",
"locale.select_formats_locale": "The numbers and dates locale will be set to" "locale.select_formats_locale": "The numbers and dates locale will be set to",
"keyboard.select_model": "Select keyboard model",
"keyboard.select_layout": "Select keyboard layout",
"keyboard.select_variant": "Select keyboard variant",
"keyboard.init_error": "Error getting keyboard layouts information from the system!"
} }
+86 -70
View File
@@ -29,7 +29,11 @@ pub struct Layout {
layout: String, layout: String,
description: String, description: String,
} }
impl std::fmt::Display for Layout {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ({})", &self.layout, &self.description)
}
}
impl Layout { impl Layout {
pub fn from_str_touple(v: &(&str, &str)) -> Self { pub fn from_str_touple(v: &(&str, &str)) -> Self {
Self { Self {
@@ -39,12 +43,17 @@ impl Layout {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Variant { pub struct Variant {
variant: String, variant: String,
description: String, description: String,
} }
impl std::fmt::Display for Variant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ({})", &self.variant, &self.description)
}
}
impl Variant { impl Variant {
pub fn from_str_touple(v: &(&str, &str)) -> Self { pub fn from_str_touple(v: &(&str, &str)) -> Self {
Self { Self {
@@ -60,11 +69,24 @@ pub struct KeyboarLayout {
variant: Variant, variant: Variant,
} }
impl KeyboarLayout {
pub fn to_result(&self) -> String {
format!("{}||{}", self.layout.layout, self.variant.variant)
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyboarModel { pub struct KeyboarModel {
model: String, model: String,
description: String, description: String,
} }
impl std::fmt::Display for KeyboarModel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ({})", &self.model, &self.description)
}
}
impl KeyboarModel { impl KeyboarModel {
pub fn from_str_touple(v: &(&str, &str)) -> Self { pub fn from_str_touple(v: &(&str, &str)) -> Self {
Self { Self {
@@ -74,7 +96,6 @@ impl KeyboarModel {
} }
} }
impl std::fmt::Display for KeyboarLayout { impl std::fmt::Display for KeyboarLayout {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}/{}", &self.layout.layout, &self.variant.variant) write!(f, "{}/{}", &self.layout.layout, &self.variant.variant)
@@ -88,15 +109,15 @@ pub struct KeyboardStage {
variants_map: HashMap<String, Vec<Variant>>, variants_map: HashMap<String, Vec<Variant>>,
variants: Vec<Variant>, variants: Vec<Variant>,
model: Option<KeyboarModel>, model: Option<KeyboarModel>,
layout: Option<Layout>, layout: Option<usize>,
variant: Option<Variant>, variant: Option<usize>,
keyboard_layouts: Vec<KeyboarLayout>, keyboard_layouts: Vec<KeyboarLayout>,
selected_kbd_layout_id: Option<usize>, selected_kbd_layout_id: Option<usize>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Message { pub enum Message {
SelectKeyboardModel(kira_scroll_list::ListViewMessage), SelectKeyboardModel(KeyboarModel),
SelectLayout(kira_scroll_list::ListViewMessage), SelectLayout(kira_scroll_list::ListViewMessage),
SelectVariant(kira_scroll_list::ListViewMessage), SelectVariant(kira_scroll_list::ListViewMessage),
@@ -111,7 +132,11 @@ pub enum Message {
const XKB_RULES_FILE_NAME: &str = "/usr/share/X11/xkb/rules/evdev.lst"; const XKB_RULES_FILE_NAME: &str = "/usr/share/X11/xkb/rules/evdev.lst";
/// Getting list of awailable keyboard layouts from from xkb/rules/evdev.lst file. /// Getting list of awailable keyboard layouts from from xkb/rules/evdev.lst file.
fn get_layouts_blocking() -> std::io::Result<(Vec<KeyboarModel>, Vec<Layout>, HashMap<String, Vec<Variant>>)> { fn get_layouts_blocking() -> std::io::Result<(
Vec<KeyboarModel>,
Vec<Layout>,
HashMap<String, Vec<Variant>>,
)> {
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
@@ -124,7 +149,6 @@ fn get_layouts_blocking() -> std::io::Result<(Vec<KeyboarModel>, Vec<Layout>, Ha
let raw_sections: Vec<String> = file_content.split("! ").map(str::to_string).collect(); let raw_sections: Vec<String> = file_content.split("! ").map(str::to_string).collect();
// Parsing models data // Parsing models data
let models: Vec<KeyboarModel> = raw_sections let models: Vec<KeyboarModel> = raw_sections
.iter() .iter()
@@ -177,9 +201,9 @@ fn get_layouts_blocking() -> std::io::Result<(Vec<KeyboarModel>, Vec<Layout>, Ha
.for_each(|v| { .for_each(|v| {
let maybe_key = variants let maybe_key = variants
.get_mut(v.0) .get_mut(v.0)
.and_then(|vrn_vec| Some(vrn_vec.push(v.1))); .and_then(|vrn_vec| Some(vrn_vec.push(v.1.clone())));
if maybe_key.is_none() { if maybe_key.is_none() {
variants.insert(v.0.to_string(), vec![v.1]); variants.insert(v.0.to_string(), vec![v.1.clone()]);
} }
}), }),
) )
@@ -191,23 +215,30 @@ fn get_layouts_blocking() -> std::io::Result<(Vec<KeyboarModel>, Vec<Layout>, Ha
impl KeyboardStage { impl KeyboardStage {
pub fn new() -> Result<Self, String> { pub fn new() -> Result<Self, String> {
match get_layouts_blocking() { match get_layouts_blocking() {
Ok((models, layouts, variants)) => { Ok((models, layouts, variants_map)) => Ok({
let def_layout = layouts
.iter()
.enumerate()
.find_map(|(idx, l)| (l.layout == "us").then_some(idx));
let variants = variants_map
.get("us")
.cloned()
.unwrap_or_else(|| Vec::new());
let def_model = models[0].clone();
Ok(Self { Self {
layouts: layouts, layouts: layouts,
variants_map: variants, variants_map: variants_map,
variants: Vec::new(), variants: variants,
model: Some(models[0].clone()), model: Some(def_model),
models: models, models: models,
layout: None, layout: def_layout,
variant: None, variant: Some(0),
keyboard_layouts: Vec::new(), keyboard_layouts: Vec::new(),
selected_kbd_layout_id: None, selected_kbd_layout_id: None,
} }
) }),
}
Err(ex) => { Err(ex) => {
let err = format!( let err = format!(
"Exception while trying to get kayboard layouts data from system {}", "Exception while trying to get kayboard layouts data from system {}",
@@ -219,95 +250,80 @@ impl KeyboardStage {
} }
fn gen_result(&self) -> StageResult { fn gen_result(&self) -> StageResult {
if let Some(time_zone) = &self.selected_zone { if let Some(model) = &self.model && self.keyboard_layouts.len() > 0 {
StageResult { StageResult {
name: "time_zone".to_string(), name: "keyboard".to_string(),
config: Some(HashMap::from([ config: Some(HashMap::from([
( (
"name".to_string(), "model".to_string(),
ConfigValue::String(time_zone.to_string()), ConfigValue::String(model.model.clone()),
), ),
( (
"region".to_string(), "layouts".to_string(),
ConfigValue::String(time_zone.region.clone()), ConfigValue::Vector(self.keyboard_layouts.iter().map(|kl| ConfigValue::String(kl.to_result())).collect()),
),
(
"zone".to_string(),
ConfigValue::String(time_zone.zone.clone()),
), ),
])), ])),
resuts: None, resuts: None,
error: None, error: None,
} }
} else { }
else {
StageResult { StageResult {
name: "time_zone".to_string(), name: "keyboard".to_string(),
config: None, config: None,
resuts: None, resuts: None,
error: None, error: Some("Something go terrible wrong, there is no keyboard layouts.".into()),
} }
} }
} }
pub fn update(&mut self, message: Message) -> StageAction { pub fn update(&mut self, message: Message) -> StageAction {
match message { match message {
Message::SelectRegion(scroll_list::ListViewMessage::Select(region_id)) => {
let region = self.regions.get(region_id).unwrap();
self.zones = self
.time_zones
.as_ref()
.unwrap()
.get(region)
.unwrap()
.clone();
self.region_id = Some(region_id);
self.zone_id = None;
//self.selected_zone_text.clear();
StageAction::None
}
Message::SelectZone(scroll_list::ListViewMessage::Select(zone_id)) => {
let zone = TimeZoneData {
region: self.regions[self.region_id.unwrap()].clone(),
zone: self.zones[zone_id].clone(),
};
self.selected_zone_text =
format!("{} {}", t!("timezone.selected_timezone"), zone.to_string());
self.zone_id = Some(zone_id);
self.selected_zone = Some(zone);
StageAction::None
}
Message::Next => StageAction::Next(self.gen_result()), Message::Next => StageAction::Next(self.gen_result()),
Message::Back => StageAction::Back, Message::Back => StageAction::Back,
_ => StageAction::None,
} }
} }
pub fn view(&self) -> iced::Element<'_, Message> { pub fn view(&self) -> iced::Element<'_, Message> {
let next_button = if self.zone_id.is_some() {
let next_button = if self.model.is_some() && self.keyboard_layouts.len() > 0 {
widget::button(widget::text(t!("button.next"))).on_press(Message::Next) widget::button(widget::text(t!("button.next"))).on_press(Message::Next)
} else { } else {
widget::button(widget::text(t!("button.next"))) widget::button(widget::text(t!("button.next")))
}; };
let main_content = match &self.time_zones {
Ok(_) => widget::container( let main_content = if self.layouts.len() > 0 {
widget::container(
widget::column![ widget::column![
widget::text(t!("timezone.select_timezone")), widget::text(t!("keyboard.select_model")),
widget::pick_list(
self.models.clone(),
self.model.clone(),
Message::SelectKeyboardModel,
),
widget::row![ widget::row![
scroll_list::list_view(&self.regions, self.region_id, Length::Shrink) widget::column![
.map(Message::SelectRegion), widget::text(t!("keyboard.select_layout")),
scroll_list::list_view(&self.zones, self.zone_id, Length::FillPortion(1)) crate::kira_scroll_list::list_view(&self.layouts, self.layout, Length::Shrink)
.map(Message::SelectZone), .map(Message::SelectLayout)],
widget::column![
widget::text(t!("keyboard.select_variant")),
crate::kira_scroll_list::list_view(&self.variants, self.variant, Length::FillPortion(1))
.map(Message::SelectVariant)],
] ]
.padding(20) .padding(20)
.spacing(10) .spacing(10)
.height(Length::Shrink), .height(Length::Shrink),
widget::text(self.selected_zone_text.clone())
] ]
.spacing(10) .spacing(10)
.align_x(Alignment::Center), .align_x(Alignment::Center),
), )}
else {
Err(_) => widget::container(widget::text(t!("timezone.init_error"))), widget::container(widget::text(t!("keyboard.init_error")))
}; };
let back_button = widget::button(widget::text(t!("button.back"))).on_press(Message::Back); let back_button = widget::button(widget::text(t!("button.back"))).on_press(Message::Back);
widget::column![ widget::column![