2024-02-14 16:32:01 +01:00
// Use libraries
2024-02-20 16:11:38 +01:00
use std ::env ;
2024-02-14 16:32:01 +01:00
use adw ::prelude ::* ;
use adw ::* ;
2024-08-03 02:41:51 +02:00
use gtk ::glib ;
use gtk ::glib ::* ;
2024-02-16 22:21:09 +01:00
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk ::* ;
2024-02-14 16:32:01 +01:00
use std ::process ::Command ;
use std ::fs ;
use std ::path ::Path ;
2024-02-20 13:27:06 +01:00
use crate ::eula_page ::eula_page ;
use crate ::keyboard_page ::keyboard_page ;
use crate ::partitioning_page ::partitioning_page ;
use crate ::timezone_page ::timezone_page ;
2024-02-14 16:32:01 +01:00
2024-02-20 13:27:06 +01:00
pub fn language_page ( content_stack : & gtk ::Stack , window : & adw ::ApplicationWindow ) {
2024-02-14 16:32:01 +01:00
// 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 ( )
2024-02-20 16:11:38 +01:00
. label ( t! ( " back " ) )
2024-02-14 16:32:01 +01:00
. 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 ( )
2024-02-20 16:11:38 +01:00
. label ( t! ( " next " ) )
2024-02-14 16:32:01 +01:00
. 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 language page
let language_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// the header box for the language page
let language_header_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Horizontal )
. build ( ) ;
// the header text for the language page
let language_header_text = gtk ::Label ::builder ( )
2024-02-20 16:11:38 +01:00
. label ( t! ( " select_a_language " ) )
2024-02-14 16:32:01 +01:00
. halign ( gtk ::Align ::End )
. hexpand ( true )
. margin_top ( 15 )
. margin_bottom ( 15 )
. margin_start ( 15 )
. margin_end ( 5 )
. build ( ) ;
language_header_text . add_css_class ( " header_sized_text " ) ;
// the header icon for the language icon
let language_header_icon = gtk ::Image ::builder ( )
. icon_name ( " locale " )
. halign ( gtk ::Align ::Start )
. hexpand ( true )
. pixel_size ( 78 )
. margin_top ( 15 )
. margin_bottom ( 15 )
. margin_start ( 0 )
. margin_end ( 15 )
. build ( ) ;
// make language selection box for choosing installation or live media
let language_selection_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// / language_header_box appends
//// Add the language page header text and icon
language_header_box . append ( & language_header_text ) ;
language_header_box . append ( & language_header_icon ) ;
// / language_main_box appends
//// Add the language header to language main box
language_main_box . append ( & language_header_box ) ;
//// Add the language selection/page content box to language main box
language_main_box . append ( & language_selection_box ) ;
// text above language selection box
let language_selection_text = gtk ::Label ::builder ( )
2024-02-20 16:11:38 +01:00
. label ( t! ( " please_select_locale " ) )
2024-02-14 16:32:01 +01:00
. halign ( gtk ::Align ::Center )
. hexpand ( true )
. margin_top ( 15 )
. margin_bottom ( 15 )
. margin_start ( 15 )
. margin_end ( 15 )
. build ( ) ;
language_selection_text . add_css_class ( " medium_sized_text " ) ;
let language_selection_expander_row = adw ::ExpanderRow ::builder ( )
2024-02-20 16:11:38 +01:00
. title ( t! ( " no_locale_selected " ) )
2024-02-14 16:32:01 +01:00
. build ( ) ;
let null_checkbutton = gtk ::CheckButton ::builder ( )
2024-02-20 16:11:38 +01:00
. label ( t! ( " no_locale_selected " ) )
2024-02-14 16:32:01 +01:00
. build ( ) ;
2024-02-16 22:21:09 +01:00
let language_selection_expander_row_viewport =
2024-02-20 09:14:18 +01:00
gtk ::ScrolledWindow ::builder ( ) . height_request ( 420 ) . build ( ) ;
2024-02-14 16:32:01 +01:00
2024-02-20 10:32:31 +01:00
let language_selection_expander_row_viewport_box = gtk ::ListBox ::builder ( ) . build ( ) ;
2024-02-20 09:14:18 +01:00
language_selection_expander_row_viewport_box . add_css_class ( " boxed-list " ) ;
2024-02-14 16:32:01 +01:00
2024-02-16 22:21:09 +01:00
language_selection_expander_row_viewport
. set_child ( Some ( & language_selection_expander_row_viewport_box ) ) ;
2024-02-14 16:32:01 +01:00
let language_selection_expander_row_viewport_listbox = gtk ::ListBox ::builder ( )
. selection_mode ( SelectionMode ::None )
. margin_top ( 15 )
. margin_bottom ( 15 )
. margin_start ( 15 )
. margin_end ( 15 )
. build ( ) ;
language_selection_expander_row_viewport_listbox . add_css_class ( " boxed-list " ) ;
language_selection_expander_row_viewport_listbox . append ( & language_selection_expander_row ) ;
language_selection_expander_row . add_row ( & language_selection_expander_row_viewport ) ;
2024-02-20 09:14:18 +01:00
let language_search_bar = gtk ::SearchEntry ::builder ( )
. halign ( gtk ::Align ::Center )
. hexpand ( true )
. margin_top ( 15 )
. margin_bottom ( 15 )
. margin_start ( 15 )
. margin_end ( 15 )
. search_delay ( 500 )
. build ( ) ;
2024-02-14 16:32:01 +01:00
let current_locale = match env ::var_os ( " LANG " ) {
Some ( v ) = > v . into_string ( ) . unwrap ( ) ,
2024-02-16 22:21:09 +01:00
None = > panic! ( " $LANG is not set " ) ,
2024-02-14 16:32:01 +01:00
} ;
2024-02-27 18:40:38 +01:00
let locale_list = [ " ab_GE " ,
" aa_DJ " ,
" af_ZA " ,
" ak_GH " ,
" sq_AL " ,
" am_ET " ,
" ar_EG " ,
" an_ES " ,
" hy_AM " ,
" as_IN " ,
" ar_AE " ,
" az_AZ " ,
" bs_BA " ,
" eu_ES " ,
" be_BY " ,
" bn_BD " ,
" ar_BH " ,
" bi_VU " ,
" bs_BA " ,
" br_FR " ,
" bg_BG " ,
" my_MM " ,
" ca_ES " ,
" de_CH " ,
" ce_RU " ,
" zh_CN " ,
" cv_RU " ,
" kw_GB " ,
" es_CO " ,
" es_CR " ,
" hr_HR " ,
" cs_CZ " ,
" da_DK " ,
" dv_MV " ,
" nl_NL " ,
" dz_BT " ,
" en_US " ,
" en_GB " ,
" eo " ,
" et_EE " ,
" et_EE " ,
" fo_FO " ,
" hif_FJ " ,
" fi_FI " ,
" fr_FR " ,
" ff_SN " ,
" gl_ES " ,
" ka_GE " ,
" de_DE " ,
" el_GR " ,
" gu_IN " ,
" ht_HT " ,
" ha_NG " ,
" he_IL " ,
" hi_IN " ,
" hu_HU " ,
" ia_FR " ,
" id_ID " ,
" en_IE " ,
" ga_IE " ,
" ig_NG " ,
" ik_CA " ,
" is_IS " ,
" it_IT " ,
" iu_CA " ,
" ja_JP " ,
" kl_GL " ,
" kn_IN " ,
" ko_KR " ,
" kk_KZ " ,
" km_KH " ,
" rw_RW " ,
" ky_KG " ,
" ky_KG " ,
" ko_KR " ,
" ku_TR " ,
" lo_LA " ,
" lb_LU " ,
" lg_UG " ,
" li_NL " ,
" ln_CD " ,
" lo_LA " ,
" lt_LT " ,
" fr_LU " ,
" lv_LV " ,
" gv_GB " ,
" mk_MK " ,
" mg_MG " ,
" ms_MY " ,
" ml_IN " ,
" mt_MT " ,
" mi_NZ " ,
" mr_IN " ,
" mn_MN " ,
" ne_NP " ,
" en_NG " ,
" nb_NO " ,
" nn_NO " ,
" no_NO " ,
" nr_ZA " ,
" oc_FR " ,
" es_CU " ,
" om_ET " ,
" or_IN " ,
" os_RU " ,
" pa_IN " ,
" fa_IR " ,
" pl_PL " ,
" ps_AF " ,
" pt_BR " ,
" ro_RO " ,
" ru_RU " ,
" sa_IN " ,
" sc_IT " ,
" sd_IN " ,
" se_NO " ,
" sm_WS " ,
" en_SG " ,
" sr_RS " ,
" gd_GB " ,
" wo_SN " ,
" si_LK " ,
" sk_SK " ,
" sl_SI " ,
" so_SO " ,
" st_ZA " ,
" es_ES " ,
" sw_KE " ,
" ss_ZA " ,
" sv_SE " ,
" ta_IN " ,
" te_IN " ,
" tg_TJ " ,
" th_TH " ,
" ti_ER " ,
" bo_CN " ,
" tk_TM " ,
" tl_PH " ,
" tn_ZA " ,
" to_TO " ,
" tr_TR " ,
" ts_ZA " ,
" tt_RU " ,
" zh_TW " ,
" ug_CN " ,
" uk_UA " ,
" ur_PK " ,
" ve_ZA " ,
" vi_VN " ,
" wa_BE " ,
" cy_GB " ,
" wo_SN " ,
" fy_NL " ,
" xh_ZA " ,
" yi_US " ,
" yo_NG " ,
" zu_ZA " ,
" zu_ZA " ,
" pt_BR " ,
" pt_PT " , ] ;
2024-02-14 16:32:01 +01:00
2024-02-16 22:21:09 +01:00
let lang_data_buffer = gtk ::TextBuffer ::builder ( ) . build ( ) ;
2024-02-14 16:32:01 +01:00
2024-02-27 18:40:38 +01:00
for locale in locale_list . iter ( ) {
let locale = locale . to_string ( ) ;
2024-02-20 10:32:31 +01:00
let locale_name_cli =
Command ::new ( " /usr/lib/pika/pika-installer-gtk4/scripts/locale-name.py " )
. arg ( locale . clone ( ) )
. output ( )
. expect ( " failed to execute process " ) ;
2024-02-19 22:22:42 +01:00
let locale_name = String ::from_utf8 ( locale_name_cli . stdout ) . unwrap ( ) ;
2024-02-14 16:32:01 +01:00
let locale_clone = locale . clone ( ) ;
2024-02-19 22:22:42 +01:00
let locale_checkbutton = gtk ::CheckButton ::builder ( )
. valign ( Align ::Center )
. can_focus ( false )
. build ( ) ;
let locale_row = adw ::ActionRow ::builder ( )
. activatable_widget ( & locale_checkbutton )
. title ( locale_name )
. subtitle ( locale . clone ( ) )
. build ( ) ;
locale_row . add_prefix ( & locale_checkbutton ) ;
2024-02-14 16:32:01 +01:00
locale_checkbutton . set_group ( Some ( & null_checkbutton ) ) ;
2024-02-19 22:22:42 +01:00
language_selection_expander_row_viewport_box . append ( & locale_row ) ;
2024-02-14 16:32:01 +01:00
locale_checkbutton . connect_toggled ( clone! ( @ weak locale_checkbutton , @ weak language_selection_expander_row , @ weak bottom_next_button , @ weak lang_data_buffer = > move | _ | {
if locale_checkbutton . is_active ( ) = = true {
2024-02-19 22:22:42 +01:00
language_selection_expander_row . set_title ( & locale_row . title ( ) ) ;
2024-02-14 16:32:01 +01:00
bottom_next_button . set_sensitive ( true ) ;
lang_data_buffer . set_text ( & locale ) ;
}
} ) ) ;
2024-02-20 10:32:31 +01:00
if current_locale . contains ( & ( locale_clone ) )
& & current_locale ! = " C.UTF-8 "
& & current_locale ! = " C "
& & current_locale ! = " C.utf8 "
& & current_locale ! = " POSIX "
{
2024-02-14 16:32:01 +01:00
locale_checkbutton . set_active ( true ) ;
}
}
// / language_selection_box appends
//// add text and and entry to language page selections
language_selection_box . append ( & language_selection_text ) ;
2024-02-20 09:14:18 +01:00
language_selection_box . append ( & language_search_bar ) ;
2024-02-14 16:32:01 +01:00
language_selection_box . append ( & language_selection_expander_row_viewport_listbox ) ;
// / language_header_box appends
//// Add the language page header text and icon
language_header_box . append ( & language_header_text ) ;
language_header_box . append ( & language_header_icon ) ;
// / language_main_box appends
//// Add the language header to language main box
language_main_box . append ( & language_header_box ) ;
//// Add the language selection/page content box to language main box
language_main_box . append ( & language_selection_box ) ;
language_main_box . append ( & bottom_box ) ;
let lang_data_buffer_clone = lang_data_buffer . clone ( ) ;
2024-02-20 09:14:18 +01:00
language_search_bar . connect_search_changed ( clone! ( @ weak language_search_bar , @ weak language_selection_expander_row_viewport_box = > move | _ | {
let mut counter = language_selection_expander_row_viewport_box . first_child ( ) ;
while let Some ( row ) = counter {
if row . widget_name ( ) = = " AdwActionRow " {
if ! language_search_bar . text ( ) . is_empty ( ) {
if row . property ::< String > ( " subtitle " ) . to_lowercase ( ) . contains ( & language_search_bar . text ( ) . to_string ( ) . to_lowercase ( ) ) | | row . property ::< String > ( " title " ) . to_lowercase ( ) . contains ( & language_search_bar . text ( ) . to_string ( ) . to_lowercase ( ) ) {
language_selection_expander_row . set_expanded ( true ) ;
//row.grab_focus();
//row.add_css_class("highlight-widget");
row . set_property ( " visible " , true ) ;
language_search_bar . grab_focus ( ) ;
} else {
row . set_property ( " visible " , false ) ;
}
} else {
row . set_property ( " visible " , true ) ;
}
}
counter = row . next_sibling ( ) ;
}
} ) ) ;
2024-02-20 13:27:06 +01:00
// / Content stack appends
//// Add the language_main_box as page: language_page, Give it nice title
content_stack . add_titled (
& language_main_box ,
Some ( " language_page " ) ,
2024-02-20 16:11:38 +01:00
& t! ( " language " ) ,
2024-02-20 13:27:06 +01:00
) ;
// the header box for the eula page
let eula_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// / Content stack appends
//// Add the eula_main_box as page: eula_page, Give it nice title
2024-02-20 16:11:38 +01:00
content_stack . add_titled ( & eula_main_box , Some ( " eula_page " ) , & t! ( " eula " ) ) ;
2024-02-20 13:27:06 +01:00
// the header box for the timezone page
let timezone_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// / Content stack appends
//// Add the keyboard_main_box as page: keyboard_page, Give it nice title
content_stack . add_titled (
& timezone_main_box ,
Some ( " timezone_page " ) ,
2024-02-20 16:11:38 +01:00
& t! ( " timezone " ) ,
2024-02-20 13:27:06 +01:00
) ;
// the header box for the keyboard page
let keyboard_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// / 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 " ) ,
2024-02-20 16:11:38 +01:00
& t! ( " keyboard " ) ,
2024-02-20 13:27:06 +01:00
) ;
// Add install_page.rs as a page for content_stack
let install_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
let done_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// the header box for the partitioning page
let partitioning_main_box = gtk ::Box ::builder ( )
. orientation ( Orientation ::Vertical )
. build ( ) ;
// / Content stack appends
//// Add the partitioning_main_box as page: partitioning_page, Give it nice title
content_stack . add_titled (
& partitioning_main_box ,
Some ( " partitioning_page " ) ,
2024-02-20 16:11:38 +01:00
& t! ( " partitioning " ) ,
2024-02-20 13:27:06 +01:00
) ;
//// Add the install_main_box as page: install_page, Give it nice title
content_stack . add_titled (
& install_main_box ,
Some ( " install_page " ) ,
2024-02-20 16:11:38 +01:00
& t! ( " installation " ) ,
2024-02-20 13:27:06 +01:00
) ;
// Add done_page.rs as a page for content_stack
2024-02-20 16:11:38 +01:00
content_stack . add_titled ( & done_main_box , Some ( " done_page " ) , & t! ( " done " ) ) ;
2024-02-20 13:27:06 +01:00
bottom_next_button . connect_clicked ( clone! ( @ weak content_stack , @ weak window = > move | _ | {
2024-02-14 16:32:01 +01:00
if Path ::new ( " /tmp/pika-installer-gtk4-lang.txt " ) . exists ( ) {
fs ::remove_file ( " /tmp/pika-installer-gtk4-lang.txt " ) . expect ( " Bad permissions on /tmp/pika-installer-gtk4-lang.txt " ) ;
}
fs ::write ( " /tmp/pika-installer-gtk4-lang.txt " , lang_data_buffer_clone . text ( & lang_data_buffer_clone . bounds ( ) . 0 , & lang_data_buffer_clone . bounds ( ) . 1 , true ) . to_string ( ) ) . expect ( " Unable to write file " ) ;
Command ::new ( " sudo " )
. arg ( " localectl " )
. arg ( " set-locale " )
. arg ( " LANG= " . to_owned ( ) + & lang_data_buffer_clone . text ( & lang_data_buffer_clone . bounds ( ) . 0 , & lang_data_buffer_clone . bounds ( ) . 1 , true ) . to_string ( ) + " .UTF-8 " )
. spawn ( )
. expect ( " locale failed to start " ) ;
2024-02-20 16:11:38 +01:00
rust_i18n ::set_locale ( & lang_data_buffer_clone . text ( & lang_data_buffer_clone . bounds ( ) . 0 , & lang_data_buffer_clone . bounds ( ) . 1 , true ) . to_string ( ) ) ;
2024-02-20 13:27:06 +01:00
// Add eula_page.rs as a page for content_stack
while let Some ( widget ) = eula_main_box . last_child ( ) {
eula_main_box . remove ( & widget ) ;
}
eula_page ( & content_stack , & eula_main_box ) ;
// Add timezone_page.rs as a page for content_stack
while let Some ( widget ) = timezone_main_box . last_child ( ) {
timezone_main_box . remove ( & widget ) ;
}
timezone_page ( & content_stack , & timezone_main_box ) ;
// Add keyboard_page.rs as a page for content_stack
while let Some ( widget ) = keyboard_main_box . last_child ( ) {
keyboard_main_box . remove ( & widget ) ;
}
keyboard_page ( & content_stack , & keyboard_main_box ) ;
// Add partitioning_page.rs as a page for content_stack
while let Some ( widget ) = partitioning_main_box . last_child ( ) {
partitioning_main_box . remove ( & widget ) ;
}
partitioning_page ( & partitioning_main_box , & done_main_box , & install_main_box , & content_stack , & window ) ;
//
2024-02-14 16:32:01 +01:00
content_stack . set_visible_child_name ( " eula_page " )
} ) ) ;
bottom_back_button . connect_clicked ( clone! ( @ weak content_stack = > move | _ | {
content_stack . set_visible_child_name ( " welcome_page " )
} ) ) ;
}