This commit is contained in:
Ward from fusion-voyager-3 2024-08-18 01:17:57 +03:00
parent 757f0c3f95
commit f7cde6bf14
9 changed files with 371 additions and 30 deletions

2
Cargo.lock generated
View File

@ -926,8 +926,6 @@ version = "1.0.2"
dependencies = [ dependencies = [
"async-channel", "async-channel",
"duct", "duct",
"glib 0.18.5",
"glib 0.20.0",
"glob", "glob",
"gnome-desktop", "gnome-desktop",
"gtk4", "gtk4",

View File

@ -6,11 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
glib_old = { version = "0.18", package = "glib"}
adw = { version = "0.7.0", package = "libadwaita", features = ["v1_5"] } adw = { version = "0.7.0", package = "libadwaita", features = ["v1_5"] }
async-channel = "2.3.1" async-channel = "2.3.1"
duct = "0.13.7" duct = "0.13.7"
glib = "0.20.0"
gtk = { version = "0.9.0", package = "gtk4", features = ["v4_14"] } gtk = { version = "0.9.0", package = "gtk4", features = ["v4_14"] }
pretty-bytes = "0.2.2" pretty-bytes = "0.2.2"
time = "0.3.31" time = "0.3.31"

View File

@ -1,6 +1,6 @@
use std::{path::Path, rc::Rc, cell::RefCell}; use std::{path::Path, rc::Rc, cell::RefCell};
use gtk::{prelude::*, glib as glib, gio as gio}; use gtk::{prelude::*, glib as glib, gio as gio};
use crate::{efi_error_page, welcome_page, language_page, eula_page, keyboard_page, timezone_page, partitioning_page}; use crate::{efi_error_page, eula_page, keyboard_page, language_page, partitioning_page::{self, CrypttabEntry, FstabEntry}, timezone_page, welcome_page};
pub fn build_ui(app: &adw::Application) { pub fn build_ui(app: &adw::Application) {
glib::set_prgname(Some("pikaos_installer")); glib::set_prgname(Some("pikaos_installer"));
@ -60,9 +60,9 @@ pub fn build_ui(app: &adw::Application) {
let partition_method_automatic_luks_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let partition_method_automatic_luks_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default());
let partition_method_automatic_ratio_refcell: Rc<RefCell<f64>> = Rc::new(RefCell::new(0.0)); let partition_method_automatic_ratio_refcell: Rc<RefCell<f64>> = Rc::new(RefCell::new(0.0));
let partition_method_automatic_seperation_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let partition_method_automatic_seperation_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default());
let partition_method_manual_fstab_json_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let partition_method_manual_fstab_entry_array_refcell: Rc<RefCell<Vec<FstabEntry>>> = Rc::new(RefCell::new(Vec::new()));
let partition_method_manual_luks_enabled_refcell: Rc<RefCell<bool>> = Rc::new(RefCell::new(false)); let partition_method_manual_luks_enabled_refcell: Rc<RefCell<bool>> = Rc::new(RefCell::new(false));
let partition_method_manual_crypttab_json_refcell: Rc<RefCell<String>> = Rc::new(RefCell::default()); let partition_method_manual_crypttab_entry_array_refcell: Rc<RefCell<Vec<CrypttabEntry>>> = Rc::new(RefCell::new(Vec::new()));
let language_changed_action = gio::SimpleAction::new("lang-changed", None); let language_changed_action = gio::SimpleAction::new("lang-changed", None);
@ -83,9 +83,9 @@ pub fn build_ui(app: &adw::Application) {
&partition_method_automatic_luks_refcell, &partition_method_automatic_luks_refcell,
&partition_method_automatic_ratio_refcell, &partition_method_automatic_ratio_refcell,
&partition_method_automatic_seperation_refcell, &partition_method_automatic_seperation_refcell,
&partition_method_manual_fstab_json_refcell, &partition_method_manual_fstab_entry_array_refcell,
&partition_method_manual_luks_enabled_refcell, &partition_method_manual_luks_enabled_refcell,
&partition_method_manual_crypttab_json_refcell, &partition_method_manual_crypttab_entry_array_refcell,
&language_changed_action); &language_changed_action);
window.present() window.present()

175
src/drive_mount_row/imp.rs Normal file
View File

@ -0,0 +1,175 @@
use std::{cell::RefCell, env, rc::Rc, sync::OnceLock};
use adw::{prelude::*, subclass::prelude::*, *};
use gtk::{glib as glib, Orientation::Horizontal};
use glib::{clone, subclass::Signal, Properties};
use crate::partitioning_page::FstabEntry;
// ANCHOR: custom_button
// Object holding the state
#[derive(Properties, Default)]
#[properties(wrapper_type = super::DriveMountRow)]
pub struct DriveMountRow {
#[property(get, set)]
fstabentry: RefCell<FstabEntry>,
#[property(get, set)]
deletable: RefCell<bool>,
#[property(get, set)]
partitionscroll: Rc<RefCell<gtk::ScrolledWindow>>,
}
// ANCHOR_END: custom_button
// The central trait for subclassing a GObject
#[glib::object_subclass]
impl ObjectSubclass for DriveMountRow {
const NAME: &'static str = "DriveMountRow";
type Type = super::DriveMountRow;
type ParentType = adw::ActionRow;
}
// ANCHOR: object_impl
// Trait shared by all GObjects
#[glib::derived_properties]
impl ObjectImpl for DriveMountRow {
fn signals() -> &'static [Signal] {
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
SIGNALS.get_or_init(|| vec![Signal::builder("row-deleted").build()])
}
fn constructed(&self) {
let current_locale = match env::var_os("LANG") {
Some(v) => v.into_string().unwrap(),
None => panic!("$LANG is not set"),
};
rust_i18n::set_locale(current_locale.strip_suffix(".UTF-8").unwrap());
self.parent_constructed();
// Bind label to number
// `SYNC_CREATE` ensures that the label will be immediately set
let obj = self.obj();
let action_row_content_box = gtk::Box::builder()
.orientation(Horizontal)
.spacing(0)
.vexpand(true)
.hexpand(true)
.build();
let partition_row_expander_adw_listbox = gtk::ListBox::builder()
.margin_end(5)
.margin_start(10)
.margin_top(5)
.margin_bottom(5)
.vexpand(true)
.hexpand(true)
.build();
partition_row_expander_adw_listbox.add_css_class("boxed-list");
let partition_row_expander = adw::ExpanderRow::builder()
.subtitle(t!("subtitle_partition"))
.vexpand(true)
.hexpand(true)
.width_request(300)
.build();
let mountpoint_entry_row = gtk::Entry::builder()
.placeholder_text(t!("title_mountpoint"))
.hexpand(true)
.vexpand(true)
.margin_bottom(5)
.margin_top(5)
.width_request(300)
.build();
let mountopt_entry_row = gtk::Entry::builder()
.placeholder_text(t!("title_mountopt"))
.hexpand(true)
.vexpand(true)
.margin_start(10)
.margin_bottom(5)
.margin_top(5)
.width_request(300)
.build();
let partition_row_delete_button = gtk::Button::builder()
.margin_end(5)
.margin_top(5)
.margin_bottom(5)
.vexpand(true)
.icon_name("user-trash")
.halign(gtk::Align::End)
.build();
obj.bind_property("deletable", &partition_row_delete_button, "visible")
.sync_create()
.bidirectional()
.build();
partition_row_delete_button.connect_clicked(clone!(
#[weak]
obj,
move |_|
{
obj.emit_by_name::<()>("row-deleted", &[]);
}
)
);
partition_row_expander_adw_listbox.append(&partition_row_expander);
action_row_content_box.append(&partition_row_expander_adw_listbox);
action_row_content_box.append(&mountpoint_entry_row);
action_row_content_box.append(&mountopt_entry_row);
obj.add_prefix(&action_row_content_box);
obj.add_suffix(&partition_row_delete_button);
// Bind label to number
// `SYNC_CREATE` ensures that the label will be immediately set
let obj = self.obj();
obj.bind_property("partition", &partition_row_expander, "title")
.sync_create()
.bidirectional()
.build();
obj.bind_property("mountpoint", &mountpoint_entry_row, "text")
.sync_create()
.bidirectional()
.build();
obj.bind_property("mountopt", &mountopt_entry_row, "text")
.sync_create()
.bidirectional()
.build();
obj.connect_partitionscroll_notify(clone!(
#[weak]
obj,
move |_|
{
partition_row_expander.add_row(&obj.property::<gtk::ScrolledWindow>("partitionscroll"));
}
)
);
}
}
// Trait shared by all widgets
impl WidgetImpl for DriveMountRow {}
// Trait shared by all buttons
// Trait shared by all buttons
impl ListBoxRowImpl for DriveMountRow {}
impl PreferencesRowImpl for DriveMountRow {}
impl ActionRowImpl for DriveMountRow {
//fn clicked(&self) {
// let incremented_number = self.obj().number() + 1;
// self.obj().set_number(incremented_number);
//}
}

View File

@ -0,0 +1,28 @@
mod imp;
use glib::Object;
use gtk::glib;
glib::wrapper! {
pub struct DriveMountRow(ObjectSubclass<imp::DriveMountRow>)
@extends adw::ActionRow, gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow,
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
impl DriveMountRow {
pub fn new() -> Self {
Object::builder().build()
}
pub fn new_with_scroll(partitions_scroll: &gtk::ScrolledWindow) -> Self {
Object::builder()
.property("partitionscroll", partitions_scroll)
.build()
}
}
// ANCHOR_END: mod
impl Default for DriveMountRow {
fn default() -> Self {
Self::new()
}
}

View File

@ -16,6 +16,8 @@ mod timezone_page;
mod partitioning_page; mod partitioning_page;
mod automatic_partitioning_page; mod automatic_partitioning_page;
mod manual_partitioning_page; mod manual_partitioning_page;
mod fstab_entry;
mod drive_mount_row;
#[macro_use] #[macro_use]
extern crate rust_i18n; extern crate rust_i18n;

View File

@ -14,9 +14,9 @@ const MINIMUM_ROOT_BYTE_SIZE: f64 = 39000000000.0;
pub fn manual_partitioning( pub fn manual_partitioning(
partition_carousel: &adw::Carousel, partition_carousel: &adw::Carousel,
partition_method_type_refcell: &Rc<RefCell<String>>, partition_method_type_refcell: &Rc<RefCell<String>>,
partition_method_manual_fstab_json_refcell: &Rc<RefCell<String>>, partition_method_manual_fstab_entry_array_refcell: &Rc<RefCell<String>>,
partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>, partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>,
partition_method_manual_crypttab_json_refcell: &Rc<RefCell<String>>, partition_method_manual_crypttab_entry_array_refcell: &Rc<RefCell<String>>,
language_changed_action: &gio::SimpleAction language_changed_action: &gio::SimpleAction
) { ) {
let manual_partitioning_page = installer_stack_page::InstallerStackPage::new(); let manual_partitioning_page = installer_stack_page::InstallerStackPage::new();
@ -58,19 +58,19 @@ pub fn manual_partitioning(
#[strong] #[strong]
partition_method_type_refcell, partition_method_type_refcell,
#[strong] #[strong]
partition_method_manual_fstab_json_refcell, partition_method_manual_fstab_entry_array_refcell,
#[strong] #[strong]
partition_method_manual_luks_enabled_refcell, partition_method_manual_luks_enabled_refcell,
#[strong] #[strong]
partition_method_manual_crypttab_json_refcell, partition_method_manual_crypttab_entry_array_refcell,
move |_automatic_partitioning_page: installer_stack_page::InstallerStackPage| move |_automatic_partitioning_page: installer_stack_page::InstallerStackPage|
{ {
*partition_method_type_refcell.borrow_mut() = String::from("automatic"); *partition_method_type_refcell.borrow_mut() = String::from("automatic");
//partition_carousel.scroll_to(&partition_carousel.nth_page(5), true) //partition_carousel.scroll_to(&partition_carousel.nth_page(5), true)
dbg!(partition_method_type_refcell.borrow()); dbg!(partition_method_type_refcell.borrow());
dbg!(partition_method_manual_fstab_json_refcell.borrow()); dbg!(partition_method_manual_fstab_entry_array_refcell.borrow());
dbg!(partition_method_manual_luks_enabled_refcell.borrow()); dbg!(partition_method_manual_luks_enabled_refcell.borrow());
dbg!(partition_method_manual_crypttab_json_refcell.borrow()); dbg!(partition_method_manual_crypttab_entry_array_refcell.borrow());
} }
) )
); );

View File

@ -1,7 +1,8 @@
use adw::gio; use adw::gio;
use crate::installer_stack_page; use crate::installer_stack_page;
use gtk::{prelude::*, glib as glib}; use gtk::{prelude::*, glib as glib};
use crate::partitioning_page::{get_block_devices}; use crate::partitioning_page::{get_partitions, CrypttabEntry, FstabEntry, Partition};
use crate::drive_mount_row::{DriveMountRow};
use adw::{prelude::*}; use adw::{prelude::*};
use glib::{clone, closure_local, ffi::gboolean}; use glib::{clone, closure_local, ffi::gboolean};
use std::{rc::Rc, cell::RefCell}; use std::{rc::Rc, cell::RefCell};
@ -10,13 +11,12 @@ const MINIMUM_EFI_BYTE_SIZE: f64 = 500000000.0;
const MINIMUM_BOOT_BYTE_SIZE: f64 = 1000000000.0; const MINIMUM_BOOT_BYTE_SIZE: f64 = 1000000000.0;
const MINIMUM_ROOT_BYTE_SIZE: f64 = 39000000000.0; const MINIMUM_ROOT_BYTE_SIZE: f64 = 39000000000.0;
pub fn manual_partitioning_page( pub fn manual_partitioning_page(
partition_carousel: &adw::Carousel, partition_carousel: &adw::Carousel,
partition_method_type_refcell: &Rc<RefCell<String>>, partition_method_type_refcell: &Rc<RefCell<String>>,
partition_method_manual_fstab_json_refcell: &Rc<RefCell<String>>, partition_method_manual_fstab_entry_array_refcell: &Rc<RefCell<Vec<FstabEntry>>>,
partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>, partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>,
partition_method_manual_crypttab_json_refcell: &Rc<RefCell<String>>, partition_method_manual_crypttab_entry_array_refcell: &Rc<RefCell<Vec<CrypttabEntry>>>,
language_changed_action: &gio::SimpleAction language_changed_action: &gio::SimpleAction
) { ) {
let manual_partitioning_page = installer_stack_page::InstallerStackPage::new(); let manual_partitioning_page = installer_stack_page::InstallerStackPage::new();
@ -26,6 +26,8 @@ pub fn manual_partitioning_page(
manual_partitioning_page.set_back_sensitive(true); manual_partitioning_page.set_back_sensitive(true);
manual_partitioning_page.set_next_sensitive(false); manual_partitioning_page.set_next_sensitive(false);
let partition_array_refcell = Rc::new(RefCell::new(get_partitions()));
// //
let content_box = gtk::Box::builder() let content_box = gtk::Box::builder()
@ -34,8 +36,44 @@ pub fn manual_partitioning_page(
.vexpand(true) .vexpand(true)
.build(); .build();
// let drive_mounts_adw_listbox = gtk::ListBox::builder().hexpand(true).vexpand(true).build();
drive_mounts_adw_listbox.add_css_class("boxed-list");
let drive_mounts_viewport = gtk::ScrolledWindow::builder()
.margin_top(30)
.margin_bottom(30)
.margin_start(30)
.margin_end(30)
.hexpand(true)
.vexpand(true)
.child(&drive_mounts_adw_listbox)
.build();
let drive_mount_add_button = gtk::Button::builder()
.icon_name("list-add")
.vexpand(true)
.hexpand(true)
.build();
drive_mounts_adw_listbox.append(&drive_mount_add_button);
content_box.append(&drive_mounts_viewport);
drive_mount_add_button.connect_clicked(clone!(
#[weak]
drive_mounts_adw_listbox,
#[strong]
partition_array_refcell,
#[strong]
partition_method_manual_fstab_entry_array_refcell,
move |_|
{
drive_mounts_adw_listbox.append(&create_mount_row(&drive_mounts_adw_listbox, &partition_array_refcell.borrow(), &partition_method_manual_fstab_entry_array_refcell))
}
)
);
//
manual_partitioning_page.connect_closure( manual_partitioning_page.connect_closure(
"back-button-pressed", "back-button-pressed",
false, false,
@ -58,19 +96,19 @@ pub fn manual_partitioning_page(
#[strong] #[strong]
partition_method_type_refcell, partition_method_type_refcell,
#[strong] #[strong]
partition_method_manual_fstab_json_refcell, partition_method_manual_fstab_entry_array_refcell,
#[strong] #[strong]
partition_method_manual_luks_enabled_refcell, partition_method_manual_luks_enabled_refcell,
#[strong] #[strong]
partition_method_manual_crypttab_json_refcell, partition_method_manual_crypttab_entry_array_refcell,
move |_automatic_partitioning_page: installer_stack_page::InstallerStackPage| move |_automatic_partitioning_page: installer_stack_page::InstallerStackPage|
{ {
*partition_method_type_refcell.borrow_mut() = String::from("manual"); *partition_method_type_refcell.borrow_mut() = String::from("manual");
//partition_carousel.scroll_to(&partition_carousel.nth_page(5), true) //partition_carousel.scroll_to(&partition_carousel.nth_page(5), true)
dbg!(partition_method_type_refcell.borrow()); dbg!(partition_method_type_refcell.borrow());
dbg!(partition_method_manual_fstab_json_refcell.borrow()); //dbg!(partition_method_manual_fstab_entry_array_refcell.borrow());
dbg!(partition_method_manual_luks_enabled_refcell.borrow()); dbg!(partition_method_manual_luks_enabled_refcell.borrow());
dbg!(partition_method_manual_crypttab_json_refcell.borrow()); //dbg!(partition_method_manual_crypttab_entry_array_refcell.borrow());
} }
) )
); );
@ -97,3 +135,91 @@ pub fn manual_partitioning_page(
); );
// //
} }
fn create_mount_row(
listbox: &gtk::ListBox,
partition_array: &Vec<Partition>,
fstab_refcell_array: &Rc<RefCell<Vec<FstabEntry>>>
) -> DriveMountRow {
let partition_scroll_child = gtk::ListBox::builder().build();
let partitions_scroll = gtk::ScrolledWindow::builder()
.hexpand(true)
.vexpand(true)
.child(&partition_scroll_child)
.build();
// Create row
let row = DriveMountRow::new_with_scroll(&partitions_scroll);
let null_checkbutton = gtk::CheckButton::builder().build();
for partition in partition_array {
let part_name = &partition.part_name.to_owned();
let partition_button = gtk::CheckButton::builder()
.valign(gtk::Align::Center)
.can_focus(false)
.build();
partition_button.set_group(Some(&null_checkbutton));
let partition_row: adw::ActionRow =
if partition.need_mapper {
let prow = adw::ActionRow::builder()
.activatable_widget(&partition_button)
.title(part_name)
.name(part_name)
.subtitle(t!("part_need_mapper"))
.build();
prow
} else {
let prow = adw::ActionRow::builder()
.activatable_widget(&partition_button)
.title(part_name)
.name(part_name)
.subtitle(String::from(&partition.part_fs) + &pretty_bytes::converter::convert(partition.part_size))
.build();
prow
};
partition_row.add_prefix(&partition_button);
partition_button.connect_toggled(clone!(
#[weak]
row,
#[weak]
listbox,
#[weak]
partition_button,
#[strong]
partition,
#[strong]
fstab_refcell_array,
move |_|
{
let mut fstab_refcell_array_ref = RefCell::borrow_mut(&fstab_refcell_array);
if partition_button.is_active() == true {
let part_name = &partition.part_name;
//row.set_partition(part_name.to_string());
} else {
}
}
)
);
partition_scroll_child.append(&partition_row);
}
let listbox_clone = listbox.clone();
row.connect_closure(
"row-deleted",
false,
closure_local!(
#[strong]
row,
move |row: DriveMountRow|
{
listbox_clone.remove(&row);
}
),
);
// Return row
row
}

View File

@ -1,6 +1,7 @@
use crate::drive_mount_row::DriveMountRow;
use crate::installer_stack_page; use crate::installer_stack_page;
use gtk::{prelude::*, glib as glib, gio as gio}; use gtk::{prelude::*, glib as glib, gio as gio};
use glib::{clone, closure_local}; use glib::{clone, closure_local, Properties};
use crate::{automatic_partitioning_page, manual_partitioning_page}; use crate::{automatic_partitioning_page, manual_partitioning_page};
use std::{rc::Rc, cell::RefCell}; use std::{rc::Rc, cell::RefCell};
use std::io::BufRead; use std::io::BufRead;
@ -14,9 +15,9 @@ pub fn partitioning_page(
partition_method_automatic_luks_refcell: &Rc<RefCell<String>>, partition_method_automatic_luks_refcell: &Rc<RefCell<String>>,
partition_method_automatic_ratio_refcell: &Rc<RefCell<f64>>, partition_method_automatic_ratio_refcell: &Rc<RefCell<f64>>,
partition_method_automatic_seperation_refcell: &Rc<RefCell<String>>, partition_method_automatic_seperation_refcell: &Rc<RefCell<String>>,
partition_method_manual_fstab_json_refcell: &Rc<RefCell<String>>, partition_method_manual_fstab_entry_array_refcell: &Rc<RefCell<Vec<FstabEntry>>>,
partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>, partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>,
partition_method_manual_crypttab_json_refcell: &Rc<RefCell<String>>, partition_method_manual_crypttab_entry_array_refcell: &Rc<RefCell<Vec<CrypttabEntry>>>,
language_changed_action: &gio::SimpleAction language_changed_action: &gio::SimpleAction
) { ) {
let partitioning_page = installer_stack_page::InstallerStackPage::new(); let partitioning_page = installer_stack_page::InstallerStackPage::new();
@ -109,9 +110,9 @@ pub fn partitioning_page(
manual_partitioning_page::manual_partitioning_page( manual_partitioning_page::manual_partitioning_page(
&partitioning_carousel, &partitioning_carousel,
&partition_method_type_refcell, &partition_method_type_refcell,
&partition_method_manual_fstab_json_refcell, &partition_method_manual_fstab_entry_array_refcell,
&partition_method_manual_luks_enabled_refcell, &partition_method_manual_luks_enabled_refcell,
&partition_method_manual_crypttab_json_refcell, &partition_method_manual_crypttab_entry_array_refcell,
&language_changed_action); &language_changed_action);
partitioning_page.connect_closure( partitioning_page.connect_closure(
@ -136,7 +137,7 @@ pub struct BlockDevice {
pub block_size_pretty: String pub block_size_pretty: String
} }
#[derive(Debug)] #[derive(Clone)]
pub struct Partition { pub struct Partition {
pub part_name: String, pub part_name: String,
pub part_fs: String, pub part_fs: String,
@ -146,6 +147,19 @@ pub struct Partition {
pub part_size_pretty: String pub part_size_pretty: String
} }
#[derive(Default)]
pub struct FstabEntry {
pub partition: String,
pub mountpoint: String,
pub mountopt: String,
}
pub struct CrypttabEntry {
pub map: String,
pub uuid: String,
pub password: Option<String>,
}
pub fn get_block_devices() -> Vec<BlockDevice> { pub fn get_block_devices() -> Vec<BlockDevice> {
let mut block_devices = Vec::new(); let mut block_devices = Vec::new();