Updated installer for new GTK API

This commit is contained in:
Bruce Leidl 2021-10-04 05:57:20 -04:00
parent 6c1f0e7221
commit 2e6542e9f7
5 changed files with 170 additions and 196 deletions

View File

@ -10,8 +10,10 @@ homepage = "https://subgraph.com"
libcitadel = { path = "../libcitadel" } libcitadel = { path = "../libcitadel" }
failure = "0.1.8" failure = "0.1.8"
dbus = "0.8.4" dbus = "0.8.4"
gtk = { version = "0.9.0", features = ["v3_16"] } gtk = { version = "0.14.0", features = ["v3_24"] }
gio = "0.9.1" gio = "0.14.0"
glib = "0.10.2" glib = "0.14.0"
gdk = "0.13.2" glib-macros = "0.14.0"
gdk = "0.14.0"
pango = "0.9.1" pango = "0.9.1"
once_cell = "1.0"

View File

@ -17,32 +17,32 @@ impl Builder {
} }
pub fn get_entry(&self, name: &str) -> Result<gtk::Entry> { pub fn get_entry(&self, name: &str) -> Result<gtk::Entry> {
Self::ok_or_err("GtkEntry", name, self.builder.get_object(name)) Self::ok_or_err("GtkEntry", name, self.builder.object(name))
} }
pub fn get_box(&self, name: &str) -> Result<gtk::Box> { pub fn get_box(&self, name: &str) -> Result<gtk::Box> {
Self::ok_or_err("GtkBox", name, self.builder.get_object(name)) Self::ok_or_err("GtkBox", name, self.builder.object(name))
} }
pub fn get_label(&self, name: &str) -> Result<gtk::Label> { pub fn get_label(&self, name: &str) -> Result<gtk::Label> {
Self::ok_or_err("GtkLabel", name, self.builder.get_object(name)) Self::ok_or_err("GtkLabel", name, self.builder.object(name))
} }
pub fn get_listbox(&self, name: &str) -> Result<gtk::ListBox> { pub fn get_listbox(&self, name: &str) -> Result<gtk::ListBox> {
Self::ok_or_err("GtkListBox", name, self.builder.get_object(name)) Self::ok_or_err("GtkListBox", name, self.builder.object(name))
} }
pub fn get_progress_bar(&self, name: &str) -> Result<gtk::ProgressBar> { pub fn get_progress_bar(&self, name: &str) -> Result<gtk::ProgressBar> {
Self::ok_or_err("GtkProgressBar", name, self.builder.get_object(name)) Self::ok_or_err("GtkProgressBar", name, self.builder.object(name))
} }
pub fn get_textview(&self, name: &str) -> Result<gtk::TextView> { pub fn get_textview(&self, name: &str) -> Result<gtk::TextView> {
Self::ok_or_err("GtkTextView", name, self.builder.get_object(name)) Self::ok_or_err("GtkTextView", name, self.builder.object(name))
} }
pub fn get_scrolled_window(&self, name: &str) -> Result<gtk::ScrolledWindow> { pub fn get_scrolled_window(&self, name: &str) -> Result<gtk::ScrolledWindow> {
Self::ok_or_err("GtkScrolledWindow", name, self.builder.get_object(name)) Self::ok_or_err("GtkScrolledWindow", name, self.builder.object(name))
} }
} }

View File

@ -1,13 +1,11 @@
#![allow(deprecated)] #![allow(deprecated)]
#[macro_use] extern crate glib;
use gtk::prelude::*; use gtk::prelude::*;
use gio::prelude::*;
use std::env::args;
mod ui; mod ui;
mod builder; mod builder;
mod error; mod error;
mod rowdata; mod rowdata;
mod dbus_client; mod dbus_client;
use libcitadel::CommandLine; use libcitadel::CommandLine;
use ui::Ui; use ui::Ui;
@ -15,8 +13,7 @@ pub use error::{Result,Error};
fn main() { fn main() {
let application = let application =
gtk::Application::new(Some("com.subgraph.citadel-installer"), Default::default()) gtk::Application::new(Some("com.subgraph.citadel-installer"), Default::default());
.expect("Initialization failed...");
application.connect_activate(|app| { application.connect_activate(|app| {
if !(CommandLine::live_mode() || CommandLine::install_mode()) { if !(CommandLine::live_mode() || CommandLine::install_mode()) {
@ -39,5 +36,5 @@ fn main() {
} }
} }
}); });
application.run(&args().collect::<Vec<_>>()); application.run();
} }

View File

@ -1,156 +1,130 @@
use gio::prelude::*; use gio::prelude::*;
use std::fmt; use std::fmt;
pub mod row_data { use glib::subclass::prelude::*;
use glib::ParamSpec;
use gtk::glib;
use super::*; use std::cell::RefCell;
use glib::subclass; #[derive(Default)]
use glib::subclass::prelude::*; pub struct RowDataImpl {
use glib::translate::*; model: RefCell<Option<String>>,
path: RefCell<Option<String>>,
size: RefCell<Option<String>>,
removable: RefCell<bool>,
}
mod imp { #[glib::object_subclass]
use super::*; impl ObjectSubclass for RowDataImpl {
use std::cell::RefCell; const NAME: &'static str = "RowData";
type Type = RowData;
type ParentType = glib::Object;
}
pub struct RowData { impl ObjectImpl for RowDataImpl {
model: RefCell<Option<String>>, fn properties() -> &'static [ParamSpec] {
path: RefCell<Option<String>>, use once_cell::sync::Lazy;
size: RefCell<Option<String>>, static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
removable: RefCell<bool>, vec![
} glib::ParamSpec::new_string(
"model",
static PROPERTIES: [subclass::Property; 4] = [
subclass::Property("model", |name| {
glib::ParamSpec::string(
name,
"Model", "Model",
"Model", "Model",
None, // Default value None,
glib::ParamFlags::READWRITE, glib::ParamFlags::READWRITE,
) ),
}), glib::ParamSpec::new_string(
subclass::Property("path", |name| { "path",
glib::ParamSpec::string(
name,
"Path", "Path",
"Path", "Path",
None, // Default value None,
glib::ParamFlags::READWRITE, glib::ParamFlags::READWRITE,
) ),
}), glib::ParamSpec::new_string(
subclass::Property("size", |name| { "size",
glib::ParamSpec::string(
name,
"Size", "Size",
"Size", "Size",
None, // Default value None,
glib::ParamFlags::READWRITE, glib::ParamFlags::READWRITE,
) ),
}), glib::ParamSpec::new_boolean(
subclass::Property("removable", |name| { "removable",
glib::ParamSpec::boolean(
name,
"Removable", "Removable",
"Removable", "Removable",
false, // Default value false,
glib::ParamFlags::READWRITE, glib::ParamFlags::READWRITE,
) ),
}), ]
]; });
PROPERTIES.as_ref()
}
impl ObjectSubclass for RowData { fn set_property(
const NAME: &'static str = "RowData"; &self,
type ParentType = glib::Object; _obj: &Self::Type,
type Instance = subclass::simple::InstanceStruct<Self>; _id: usize,
type Class = subclass::simple::ClassStruct<Self>; value: &glib::Value,
pspec: &glib::ParamSpec,
glib_object_subclass!(); ) {
match pspec.name() {
fn class_init(klass: &mut Self::Class) { "model" => {
klass.install_properties(&PROPERTIES); let model = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.model.replace(model);
} }
"path" => {
fn new() -> Self { let path = value
Self { .get()
model: RefCell::new(None), .expect("type conformity checked by `Object::set_property`");
path: RefCell::new(None), self.path.replace(path);
size: RefCell::new(None),
removable: RefCell::new(false),
}
} }
} "size" => {
let size = value
impl ObjectImpl for RowData { .get()
glib_object_impl!(); .expect("type conformity checked by `Object::set_property`");
self.size.replace(size);
fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
let prop = &PROPERTIES[id];
match *prop {
subclass::Property("model", ..) => {
let model = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.model.replace(model);
}
subclass::Property("path", ..) => {
let path = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.path.replace(path);
}
subclass::Property("size", ..) => {
let size = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.size.replace(size);
}
subclass::Property("removable", ..) => {
let removable = value
.get_some()
.expect("type conformity checked by `Object::set_property`");
self.removable.replace(removable);
}
_ => unimplemented!(),
}
} }
"removable" => {
fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> { let removable = value
let prop = &PROPERTIES[id]; .get()
.expect("type conformity checked by `Object::set_property`");
match *prop { self.removable.replace(removable);
subclass::Property("model", ..) => Ok(self.model.borrow().to_value()),
subclass::Property("path", ..) => Ok(self.path.borrow().to_value()),
subclass::Property("size", ..) => Ok(self.size.borrow().to_value()),
subclass::Property("removable", ..) => Ok(self.removable.borrow().to_value()),
_ => unimplemented!(),
}
} }
_ => unimplemented!(),
} }
} }
glib_wrapper! { fn property(&self, _obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
pub struct RowData(Object<subclass::simple::InstanceStruct<imp::RowData>, subclass::simple::ClassStruct<imp::RowData>, RowDataClass>); match pspec.name() {
"model" => self.model.borrow().to_value(),
match fn { "path" => self.path.borrow().to_value(),
get_type => || imp::RowData::get_type().to_glib(), "size" => self.size.borrow().to_value(),
} "removable" => self.removable.borrow().to_value(),
} _ => unimplemented!(),
impl RowData {
pub fn new(model: &str, path: &str, size: &str, removable: bool) -> RowData {
glib::Object::new(Self::static_type(), &[("model", &model), ("path", &path), ("size", &size), ("removable", &removable)])
.expect("Failed to create row data")
.downcast()
.expect("Created row data is of wrong type")
}
}
impl fmt::Display for RowData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.1)
} }
} }
} }
glib::wrapper! {
pub struct RowData(ObjectSubclass<RowDataImpl>);
}
impl RowData {
pub fn new(model: &str, path: &str, size: &str, removable: bool) -> RowData {
glib::Object::new(&[
("model", &model),
("path", &path),
("size", &size),
("removable", &removable),
])
.expect("Failed to create row data")
}
}
impl fmt::Display for RowData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}

View File

@ -1,13 +1,13 @@
use gtk::prelude::*; use gtk::prelude::*;
use gtk::glib;
use gio::prelude::*;
use dbus::Message; use dbus::Message;
use std::time::Duration; use std::time::Duration;
use std::thread; use std::thread;
use std::collections::HashMap; use std::collections::HashMap;
use dbus::blocking::{Connection, Proxy}; use dbus::blocking::{Connection, Proxy};
use crate::builder::*; use crate::builder::*;
use crate::rowdata::row_data::RowData; use crate::rowdata::RowData;
use crate::{Result, Error}; use crate::{Result, Error};
use crate::dbus_client::*; use crate::dbus_client::*;
@ -41,6 +41,7 @@ pub struct Ui {
pub luks_password_status_label: gtk::Label, pub luks_password_status_label: gtk::Label,
pub disks_listbox: gtk::ListBox, pub disks_listbox: gtk::ListBox,
pub disks_model: gio::ListStore, pub disks_model: gio::ListStore,
pub disk_rows: Vec<RowData>,
pub confirm_install_label: gtk::Label, pub confirm_install_label: gtk::Label,
pub install_page: gtk::Box, pub install_page: gtk::Box,
pub install_progress: gtk::ProgressBar, pub install_progress: gtk::ProgressBar,
@ -57,11 +58,11 @@ impl Ui {
assistant.set_position(gtk::WindowPosition::CenterAlways); assistant.set_position(gtk::WindowPosition::CenterAlways);
assistant.set_application(Some(application)); assistant.set_application(Some(application));
assistant.connect_delete_event(clone!(@strong application => move |_, _| { assistant.connect_delete_event(glib::clone!(@strong application => move |_, _| {
application.quit(); application.quit();
gtk::Inhibit(false) gtk::Inhibit(false)
})); }));
assistant.connect_cancel(clone!(@strong application => move |_| { assistant.connect_cancel(glib::clone!(@strong application => move |_| {
application.quit(); application.quit();
})); }));
let welcome_builder = Builder::new(WELCOME_UI); let welcome_builder = Builder::new(WELCOME_UI);
@ -91,7 +92,7 @@ impl Ui {
let item = item.downcast_ref::<RowData>().expect("Row data is of wrong type"); let item = item.downcast_ref::<RowData>().expect("Row data is of wrong type");
let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5); let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5);
hbox.set_homogeneous(true); hbox.set_homogeneous(true);
let removable = item.get_property("removable").unwrap().get().unwrap().unwrap(); let removable= item.property("removable").unwrap().get::<bool>().unwrap();
let icon_name = Self::get_disk_icon(removable); let icon_name = Self::get_disk_icon(removable);
let disk_icon = gtk::Image::from_icon_name(Some(&icon_name), gtk::IconSize::LargeToolbar); let disk_icon = gtk::Image::from_icon_name(Some(&icon_name), gtk::IconSize::LargeToolbar);
disk_icon.set_halign(gtk::Align::Start); disk_icon.set_halign(gtk::Align::Start);
@ -121,7 +122,7 @@ impl Ui {
row.show_all(); row.show_all();
row.upcast::<gtk::Widget>() row.upcast::<gtk::Widget>()
}); });
disks_listbox.connect_row_selected(clone!(@strong assistant, @strong install_destination_page => move |_, listbox_row | { disks_listbox.connect_row_selected(glib::clone!(@strong assistant, @strong install_destination_page => move |_, listbox_row | {
if let Some(_) = listbox_row { if let Some(_) = listbox_row {
assistant.set_page_complete(&install_destination_page, true); assistant.set_page_complete(&install_destination_page, true);
} }
@ -156,6 +157,7 @@ impl Ui {
luks_password_status_label, luks_password_status_label,
disks_listbox, disks_listbox,
disks_model, disks_model,
disk_rows: disks.clone(),
confirm_install_label, confirm_install_label,
install_page, install_page,
install_progress, install_progress,
@ -163,12 +165,12 @@ impl Ui {
install_textview, install_textview,
sender, sender,
}; };
receiver.attach(None,clone!(@strong ui, @strong application => move |msg| { receiver.attach(None,glib::clone!(@strong ui, @strong application => move |msg| {
match msg { match msg {
Msg::InstallStarted => { Msg::InstallStarted => {
ui.install_progress.set_fraction(0.1428); ui.install_progress.set_fraction(0.1428);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
let text = format!( let text = format!(
"+ Installing Citadel to {}. \nFor a full log, consult the systemd journal by running the following command:\n <i>sudo journalctl -u citadel-installer-backend.service</i>\n", "+ Installing Citadel to {}. \nFor a full log, consult the systemd journal by running the following command:\n <i>sudo journalctl -u citadel-installer-backend.service</i>\n",
ui.get_install_destination()); ui.get_install_destination());
@ -177,41 +179,41 @@ impl Ui {
}, },
Msg::LuksSetup(text) => { Msg::LuksSetup(text) => {
ui.install_progress.set_fraction(0.1428 * 2.0); ui.install_progress.set_fraction(0.1428 * 2.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
buffer.insert(&mut iter, &text); buffer.insert(&mut iter, &text);
}, },
Msg::LvmSetup(text) => { Msg::LvmSetup(text) => {
ui.install_progress.set_fraction(0.1428 * 3.0); ui.install_progress.set_fraction(0.1428 * 3.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
buffer.insert(&mut iter, &text); buffer.insert(&mut iter, &text);
}, },
Msg::BootSetup(text) => { Msg::BootSetup(text) => {
ui.install_progress.set_fraction(0.1428 * 4.0); ui.install_progress.set_fraction(0.1428 * 4.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
buffer.insert(&mut iter, &text); buffer.insert(&mut iter, &text);
}, },
Msg::StorageCreated(text) => { Msg::StorageCreated(text) => {
ui.install_progress.set_fraction(0.1428 * 5.0); ui.install_progress.set_fraction(0.1428 * 5.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
buffer.insert(&mut iter, &text); buffer.insert(&mut iter, &text);
}, },
Msg::RootfsInstalled(text) => { Msg::RootfsInstalled(text) => {
ui.install_progress.set_fraction(0.1428 * 6.0); ui.install_progress.set_fraction(0.1428 * 6.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
buffer.insert(&mut iter, &text); buffer.insert(&mut iter, &text);
}, },
Msg::InstallCompleted => { Msg::InstallCompleted => {
ui.install_progress.set_fraction(1.0); ui.install_progress.set_fraction(1.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
buffer.insert(&mut iter, "+ Completed the installation successfully\n"); buffer.insert(&mut iter, "+ Completed the installation successfully\n");
let quit_button = gtk::Button::with_label("Quit"); let quit_button = gtk::Button::with_label("Quit");
quit_button.connect_clicked(clone!(@strong application => move |_| { quit_button.connect_clicked(glib::clone!(@strong application => move |_| {
application.quit(); application.quit();
})); }));
quit_button.set_sensitive(true); quit_button.set_sensitive(true);
@ -220,12 +222,12 @@ impl Ui {
}, },
Msg::InstallFailed(error) => { Msg::InstallFailed(error) => {
ui.install_progress.set_fraction(100.0); ui.install_progress.set_fraction(100.0);
let buffer = ui.install_textview.get_buffer().unwrap(); let buffer = ui.install_textview.buffer().unwrap();
let mut iter = buffer.get_end_iter(); let mut iter = buffer.end_iter();
let text = format!("+ Install failed with error:\n<i>{}</i>\n", error); let text = format!("+ Install failed with error:\n<i>{}</i>\n", error);
buffer.insert_markup(&mut iter, &text); buffer.insert_markup(&mut iter, &text);
let quit_button = gtk::Button::with_label("Quit"); let quit_button = gtk::Button::with_label("Quit");
quit_button.connect_clicked(clone!(@strong application => move |_| { quit_button.connect_clicked(glib::clone!(@strong application => move |_| {
application.quit(); application.quit();
})); }));
quit_button.set_sensitive(true); quit_button.set_sensitive(true);
@ -270,9 +272,9 @@ impl Ui {
pub fn setup_entry_signals(&self, page: &gtk::Box, first_entry: &gtk::Entry, second_entry: &gtk::Entry, status_label: &gtk::Label) { pub fn setup_entry_signals(&self, page: &gtk::Box, first_entry: &gtk::Entry, second_entry: &gtk::Entry, status_label: &gtk::Label) {
let ui = self.clone(); let ui = self.clone();
let assistant = ui.assistant.clone(); let assistant = ui.assistant.clone();
first_entry.connect_changed(clone!(@weak assistant, @weak page, @weak second_entry, @weak status_label => move |entry| { first_entry.connect_changed(glib::clone!(@weak assistant, @weak page, @weak second_entry, @weak status_label => move |entry| {
let password = entry.get_text(); let password = entry.text();
let confirm = second_entry.get_text(); let confirm = second_entry.text();
if password != "" && confirm != "" { if password != "" && confirm != "" {
let matches = password == confirm; let matches = password == confirm;
if !matches { if !matches {
@ -283,15 +285,15 @@ impl Ui {
assistant.set_page_complete(&page, matches); assistant.set_page_complete(&page, matches);
} }
})); }));
first_entry.connect_activate(clone!(@weak second_entry => move |_| { first_entry.connect_activate(glib::clone!(@weak second_entry => move |_| {
second_entry.grab_focus(); second_entry.grab_focus();
})); }));
} }
pub fn setup_prepare_signal(&self) { pub fn setup_prepare_signal(&self) {
let ui = self.clone(); let ui = self.clone();
ui.assistant.connect_prepare(clone!(@strong ui => move |assistant, page| { ui.assistant.connect_prepare(glib::clone!(@strong ui => move |assistant, page| {
let page_type = assistant.get_page_type(page); let page_type = assistant.page_type(page);
if page_type == gtk::AssistantPageType::Confirm { if page_type == gtk::AssistantPageType::Confirm {
let path = ui.get_install_destination(); let path = ui.get_install_destination();
let text = format!("<i>{}</i>", path); let text = format!("<i>{}</i>", path);
@ -302,7 +304,7 @@ impl Ui {
pub fn setup_apply_signal(&self) { pub fn setup_apply_signal(&self) {
let ui = self.clone(); let ui = self.clone();
ui.assistant.connect_apply(clone!(@strong ui => move |_| { ui.assistant.connect_apply(glib::clone!(@strong ui => move |_| {
let citadel_password = ui.get_citadel_password(); let citadel_password = ui.get_citadel_password();
let luks_password = ui.get_luks_password(); let luks_password = ui.get_luks_password();
let destination = ui.get_install_destination(); let destination = ui.get_install_destination();
@ -318,9 +320,9 @@ impl Ui {
pub fn setup_autoscroll_signal(&self) { pub fn setup_autoscroll_signal(&self) {
let ui = self.clone(); let ui = self.clone();
let scrolled_window = ui.install_scrolled_window; let scrolled_window = ui.install_scrolled_window;
ui.install_textview.connect_size_allocate(clone!(@weak scrolled_window => move |_, _| { ui.install_textview.connect_size_allocate(glib::clone!(@weak scrolled_window => move |_, _| {
let adjustment = scrolled_window.get_vadjustment().unwrap(); let adjustment = scrolled_window.vadjustment();
adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); adjustment.set_value(adjustment.upper() - adjustment.page_size());
})); }));
} }
@ -346,63 +348,62 @@ impl Ui {
println!("Error parsing CSS style: {}", err); println!("Error parsing CSS style: {}", err);
return; return;
} }
if let Some(screen) = gdk::Screen::get_default() { if let Some(screen) = gdk::Screen::default() {
gtk::StyleContext::add_provider_for_screen(&screen, &css, gtk::STYLE_PROVIDER_PRIORITY_USER); gtk::StyleContext::add_provider_for_screen(&screen, &css, gtk::STYLE_PROVIDER_PRIORITY_USER);
} }
} }
pub fn get_citadel_password(&self) -> String { pub fn get_citadel_password(&self) -> String {
let ui = self.clone(); let ui = self.clone();
let password = ui.citadel_password_entry.get_text(); let password = ui.citadel_password_entry.text();
password.to_string() password.to_string()
} }
pub fn get_luks_password(&self) -> String { pub fn get_luks_password(&self) -> String {
let ui = self.clone(); let ui = self.clone();
let password = ui.luks_password_entry.get_text(); let password = ui.luks_password_entry.text();
password.to_string() password.to_string()
} }
pub fn get_install_destination(&self) -> String { pub fn get_install_destination(&self) -> String {
let ui = self.clone(); let ui = self.clone();
let model = ui.disks_model; if let Some(row) = ui.disks_listbox.selected_row() {
if let Some(row) = ui.disks_listbox.get_selected_row() { let index = row.index() as usize;
let index = row.get_index() as u32; if ui.disk_rows.len() > index {
let data = model.get_object(index).unwrap(); let data = &ui.disk_rows[index];
let data = data.downcast_ref::<RowData>().expect("Row data is of wrong type"); let path: String = data.property("path").unwrap().get::<String>().unwrap();
// TODO: Fix unwrap return path.to_string();
let path: String = data.get_property("path").unwrap().get().unwrap().unwrap(); }
return path.to_string();
} }
"".to_string() "".to_string()
} }
fn setup_signal_matchers(&self, proxy: Proxy<&Connection>) { fn setup_signal_matchers(&self, proxy: Proxy<&Connection>) {
let sender = self.sender.clone(); let sender = self.sender.clone();
let _ = proxy.match_signal(clone!(@strong sender => move |_: ComSubgraphInstallerManagerInstallCompleted, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |_: ComSubgraphInstallerManagerInstallCompleted, _: &Connection, _: &Message| {
let _ = sender.send(Msg::InstallCompleted); let _ = sender.send(Msg::InstallCompleted);
true true
})); }));
let _ = proxy.match_signal(clone!(@strong sender => move |h: ComSubgraphInstallerManagerLvmSetup, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |h: ComSubgraphInstallerManagerLvmSetup, _: &Connection, _: &Message| {
let _ = sender.send(Msg::LvmSetup(h.text)); let _ = sender.send(Msg::LvmSetup(h.text));
true true
})); }));
let _ = proxy.match_signal(clone!(@strong sender => move |h: ComSubgraphInstallerManagerLuksSetup, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |h: ComSubgraphInstallerManagerLuksSetup, _: &Connection, _: &Message| {
let _ = sender.send(Msg::LuksSetup(h.text)); let _ = sender.send(Msg::LuksSetup(h.text));
true true
})); }));
let _ = proxy.match_signal(clone!(@strong sender => move |h: ComSubgraphInstallerManagerBootSetup, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |h: ComSubgraphInstallerManagerBootSetup, _: &Connection, _: &Message| {
let _ = sender.send(Msg::BootSetup(h.text)); let _ = sender.send(Msg::BootSetup(h.text));
true true
})); }));
let _ = proxy.match_signal(clone!(@strong sender => move |h: ComSubgraphInstallerManagerStorageCreated, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |h: ComSubgraphInstallerManagerStorageCreated, _: &Connection, _: &Message| {
let _ = sender.send(Msg::StorageCreated(h.text)); let _ = sender.send(Msg::StorageCreated(h.text));
true true
})); }));
let _ = proxy.match_signal(clone!(@strong sender => move |h: ComSubgraphInstallerManagerRootfsInstalled, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |h: ComSubgraphInstallerManagerRootfsInstalled, _: &Connection, _: &Message| {
let _ = sender.send(Msg::RootfsInstalled(h.text)); let _ = sender.send(Msg::RootfsInstalled(h.text));
true true
})); }));
let _ = proxy.match_signal(clone!(@strong sender => move |h: ComSubgraphInstallerManagerInstallFailed, _: &Connection, _: &Message| { let _ = proxy.match_signal(glib::clone!(@strong sender => move |h: ComSubgraphInstallerManagerInstallFailed, _: &Connection, _: &Message| {
let _ = sender.send(Msg::InstallFailed(h.text)); let _ = sender.send(Msg::InstallFailed(h.text));
true true
})); }));