From a8d62bdb0d30950dd2c7559efb83789a1df599ff Mon Sep 17 00:00:00 2001 From: Ward from fusion-voyager-3 Date: Sat, 24 Feb 2024 15:34:58 +0300 Subject: [PATCH] Adaptive Layout --- ...ithub.pikaos-linux.pikawelcome.gschema.xml | 9 +- debian/control | 2 +- src/build_ui.rs | 43 ++- src/first_setup/codec_carousel/mod.rs | 223 ------------ src/first_setup/driver_carousel/mod.rs | 115 ------- src/first_setup/final_carousel/mod.rs | 51 --- src/first_setup/gameutils_carousel/mod.rs | 223 ------------ src/first_setup/initial_carousel/mod.rs | 45 --- src/first_setup/internet_carousel/mod.rs | 196 ----------- src/first_setup/mod.rs | 83 ----- src/first_setup/user_carousel/mod.rs | 324 ------------------ src/main.rs | 5 +- src/save_window_size/mod.rs | 14 + src/welcome_content_page/mod.rs | 131 +++++++ .../update_carousel/mod.rs | 0 15 files changed, 187 insertions(+), 1277 deletions(-) delete mode 100644 src/first_setup/codec_carousel/mod.rs delete mode 100644 src/first_setup/driver_carousel/mod.rs delete mode 100644 src/first_setup/final_carousel/mod.rs delete mode 100644 src/first_setup/gameutils_carousel/mod.rs delete mode 100644 src/first_setup/initial_carousel/mod.rs delete mode 100644 src/first_setup/internet_carousel/mod.rs delete mode 100644 src/first_setup/mod.rs delete mode 100644 src/first_setup/user_carousel/mod.rs create mode 100644 src/save_window_size/mod.rs create mode 100644 src/welcome_content_page/mod.rs rename src/{first_setup => welcome_content_page}/update_carousel/mod.rs (100%) diff --git a/data/com.github.pikaos-linux.pikawelcome.gschema.xml b/data/com.github.pikaos-linux.pikawelcome.gschema.xml index 31a6f38..ae07e9d 100644 --- a/data/com.github.pikaos-linux.pikawelcome.gschema.xml +++ b/data/com.github.pikaos-linux.pikawelcome.gschema.xml @@ -1,6 +1,6 @@ - + 700 Default window width @@ -13,5 +13,12 @@ false Default window maximized behaviour + + true + Show PikaOS Welcome on startup. + + Show PikaOS Welcome on startup. + + diff --git a/debian/control b/debian/control index e45b29b..8272318 100644 --- a/debian/control +++ b/debian/control @@ -15,4 +15,4 @@ Rules-Requires-Root: no Package: pika-welcome Architecture: any Depends: ${shlibs:Depends} -Description: A frontend in GTK 4 and Libadwaita for initial user setup in pika. +Description: A frontend in GTK 4 and Libadwaita for Post install PikaOS setup. diff --git a/src/build_ui.rs b/src/build_ui.rs index 9e65f98..e27a5f4 100644 --- a/src/build_ui.rs +++ b/src/build_ui.rs @@ -1,41 +1,56 @@ // GTK crates use adw::prelude::*; use adw::*; +use glib::*; +use gtk::Orientation; /// Use all gtk4 libraries (gtk4 -> gtk because cargo) /// Use all libadwaita libraries (libadwaita -> adw because cargo) // application crates /// first setup crates use crate::config::*; -use crate::first_setup::*; +use crate::save_window_size::save_window_size; +use crate::welcome_content_page::welcome_content_page; pub fn build_ui(app: &adw::Application) { // setup glib gtk::glib::set_prgname(Some(t!("app_name").to_string())); glib::set_application_name(&t!("app_name").to_string()); + let glib_settings = gio::Settings::new(APP_ID); + + let content_box = gtk::Box::builder() + .vexpand(true) + .hexpand(true) + .orientation(Orientation::Vertical) + .build(); // create the main Application window let window = adw::ApplicationWindow::builder() - // The text on the titlebar .title(t!("app_name")) - // link it to the application "app" .application(app) - // Add the box called "window_box" to it - // Application icon + .content(&content_box) .icon_name(APP_ICON) - // Minimum Size/Default - .width_request(700) + .default_width(glib_settings.int("window-width")) + .default_height(glib_settings.int("window-height")) + .width_request(300) .height_request(500) - // Hide window instead of destroy - .hide_on_close(true) - .deletable(false) - // Startup .startup_id(APP_ID) - // build the window .build(); - first_setup(&window); + if glib_settings.boolean("is-maximized") == true { + window.maximize() + } + window.connect_close_request(move |window| { + if let Some(application) = window.application() { + save_window_size(&window, &glib_settings); + application.remove_window(window); + } + glib::Propagation::Proceed + }); + + // + welcome_content_page(&window, &content_box); // show the window window.present() -} +} \ No newline at end of file diff --git a/src/first_setup/codec_carousel/mod.rs b/src/first_setup/codec_carousel/mod.rs deleted file mode 100644 index 8d9c25f..0000000 --- a/src/first_setup/codec_carousel/mod.rs +++ /dev/null @@ -1,223 +0,0 @@ -use std::cell::RefCell; -use std::rc::Rc; -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - - - -use std::{thread, time}; - -use std::{ - error::Error, -}; - -use duct::cmd; -use std::io::prelude::*; -use std::io::BufReader; - -const CODEC_INSTALL_PROG: &str = " -#! /bin/bash -set -e -/usr/lib/pika/pika-welcome/scripts/pika-sudo.sh apt update -y && /usr/lib/pika/pika-welcome/scripts/pika-sudo.sh apt install pika-codecs-meta -y -"; - -fn codec_install( - log_loop_sender: async_channel::Sender, -) -> Result<(), std::boxed::Box> { - let (pipe_reader, pipe_writer) = os_pipe::pipe()?; - let child = cmd!("bash", "-c", CODEC_INSTALL_PROG) - .stderr_to_stdout() - .stdout_file(pipe_writer) - .start()?; - for line in BufReader::new(pipe_reader).lines() { - log_loop_sender - .send_blocking(line?) - .expect("Channel needs to be opened.") - } - child.wait()?; - - Ok(()) -} - -pub fn codec_carousel( - first_setup_carousel: &adw::Carousel, - internet_connected: &Rc>, - window: &adw::ApplicationWindow, -) { - let internet_connected_status = internet_connected.clone(); - - let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded(); - let internet_loop_sender = internet_loop_sender.clone(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(move || loop { - thread::sleep(time::Duration::from_secs(1)); - internet_loop_sender - .send_blocking(true) - .expect("The channel needs to be open."); - }); - - let (log_loop_sender, log_loop_receiver) = async_channel::unbounded(); - let log_loop_sender: async_channel::Sender = log_loop_sender.clone(); - - let (log_status_loop_sender, log_status_loop_receiver) = async_channel::unbounded(); - let log_status_loop_sender: async_channel::Sender = log_status_loop_sender.clone(); - - let first_setup_codec_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .valign(gtk::Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - - let first_setup_codec_box_text = adw::StatusPage::builder() - .icon_name("media-tape") - .title(t!("first_setup_codec_box_text_title")) - .description(t!("first_setup_codec_box_text_description")) - .build(); - first_setup_codec_box_text.add_css_class("compact"); - - let first_setup_codec_button = gtk::Button::builder() - .label(t!("first_setup_codec_button_label")) - .sensitive(false) - .build(); - - first_setup_codec_button.add_css_class("suggested-action"); - first_setup_codec_button.add_css_class("pill"); - - let first_setup_codec_skip_button = gtk::Button::builder() - .label(t!("first_setup_codec_skip_button_label")) - .sensitive(true) - .width_request(25) - .build(); - - let first_setup_codec_buttons_box = gtk::Box::builder() - .orientation(Orientation::Horizontal) - .halign(gtk::Align::Center) - .valign(gtk::Align::End) - .vexpand(true) - .hexpand(true) - .margin_end(15) - .margin_start(15) - .margin_bottom(15) - .margin_top(15) - .spacing(80) - .build(); - - first_setup_codec_skip_button.add_css_class("pill"); - - let codec_install_log_terminal_buffer = gtk::TextBuffer::builder().build(); - - let codec_install_log_terminal = gtk::TextView::builder() - .vexpand(true) - .hexpand(true) - .editable(false) - .buffer(&codec_install_log_terminal_buffer) - .build(); - - let codec_install_log_terminal_scroll = gtk::ScrolledWindow::builder() - .width_request(400) - .height_request(200) - .vexpand(true) - .hexpand(true) - .child(&codec_install_log_terminal) - .build(); - - let codec_install_dialog = adw::MessageDialog::builder() - .transient_for(window) - .hide_on_close(true) - .extra_child(&codec_install_log_terminal_scroll) - .width_request(400) - .height_request(200) - .heading(t!("codec_install_dialog_heading")) - .build(); - codec_install_dialog.add_response("codec_install_dialog_ok", &t!("system_update_dialog_ok_label")); - - first_setup_codec_buttons_box.append(&first_setup_codec_button); - first_setup_codec_buttons_box.append(&first_setup_codec_skip_button); - - first_setup_codec_box.append(&first_setup_codec_box_text); - first_setup_codec_box.append(&first_setup_codec_buttons_box); - - first_setup_carousel.append(&first_setup_codec_box); - - let internet_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - internet_loop_context.spawn_local( - clone!(@strong internet_connected_status, @weak first_setup_codec_button => async move { - while let Ok(_state) = internet_loop_receiver.recv().await { - if *internet_connected_status.borrow_mut() == true { - first_setup_codec_button.set_sensitive(true); - first_setup_codec_button.set_label(&t!("first_setup_codec_button_label")); - } else { - first_setup_codec_button.set_sensitive(false); - first_setup_codec_button.set_label(&t!("internet_network_disabled")); - } - } - }), - ); - - let log_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - log_loop_context.spawn_local(clone!(@weak codec_install_log_terminal_buffer, @weak codec_install_dialog => async move { - while let Ok(state) = log_loop_receiver.recv().await { - codec_install_log_terminal_buffer.insert(&mut codec_install_log_terminal_buffer.end_iter(), &("\n".to_string() + &state)) - } - })); - - let log_status_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - log_status_loop_context.spawn_local(clone!(@weak codec_install_dialog, @weak first_setup_codec_button, @weak first_setup_codec_skip_button => async move { - while let Ok(state) = log_status_loop_receiver.recv().await { - if state == true { - codec_install_dialog.set_response_enabled("codec_install_dialog_ok", true); - codec_install_dialog.set_body(&t!("codec_install_dialog_success_true")); - first_setup_codec_button.remove_css_class("suggested-action"); - first_setup_codec_skip_button.set_label(&t!("internet_next_button_label")); - first_setup_codec_skip_button.add_css_class("suggested-action"); - } else { - first_setup_codec_skip_button.remove_css_class("suggested-action"); - first_setup_codec_skip_button.set_label(&t!("first_setup_codec_skip_button_label")); - first_setup_codec_button.add_css_class("suggested-action"); - codec_install_dialog.set_response_enabled("codec_install_dialog_ok", true); - codec_install_dialog.set_body(&t!("codec_install_dialog_success_false")); - } - } - })); - - codec_install_log_terminal_buffer.connect_changed(clone!(@weak codec_install_log_terminal, @weak codec_install_log_terminal_buffer,@weak codec_install_log_terminal_scroll => move |_|{ - if codec_install_log_terminal_scroll.vadjustment().upper() - codec_install_log_terminal_scroll.vadjustment().value() > 100.0 { - codec_install_log_terminal_scroll.vadjustment().set_value(codec_install_log_terminal_scroll.vadjustment().upper()) - } - })); - - first_setup_codec_button.connect_clicked(clone!(@strong internet_connected_status, @weak codec_install_log_terminal,@weak codec_install_log_terminal_buffer, @weak codec_install_dialog,@weak first_setup_carousel => move |_| { - codec_install_log_terminal_buffer.delete(&mut codec_install_log_terminal_buffer.bounds().0, &mut codec_install_log_terminal_buffer.bounds().1); - codec_install_dialog.set_response_enabled("codec_install_dialog_ok", false); - codec_install_dialog.set_body(""); - codec_install_dialog.present(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(clone!(@strong log_loop_sender, @strong log_status_loop_sender => move || { - let command = codec_install(log_loop_sender); - match command { - Ok(_) => { - println!("Status: Codec install Successful"); - log_status_loop_sender.send_blocking(true).expect("The channel needs to be open."); - } - Err(_) => { - println!("Status: Codec install Failed"); - log_status_loop_sender.send_blocking(false).expect("The channel needs to be open."); - } - } - })); - })); - - first_setup_codec_skip_button.connect_clicked(clone!(@weak first_setup_carousel => move |_|{ - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(6), true); - })); -} diff --git a/src/first_setup/driver_carousel/mod.rs b/src/first_setup/driver_carousel/mod.rs deleted file mode 100644 index c515ca5..0000000 --- a/src/first_setup/driver_carousel/mod.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::cell::RefCell; -use std::rc::Rc; -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - - - -use std::{thread, time}; - -use std::{ - process::{Command}, -}; - -pub fn driver_carousel( - first_setup_carousel: &adw::Carousel, - internet_connected: &Rc>, -) { - let internet_connected_status = internet_connected.clone(); - - let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded(); - let internet_loop_sender = internet_loop_sender.clone(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(move || loop { - thread::sleep(time::Duration::from_secs(1)); - internet_loop_sender - .send_blocking(true) - .expect("The channel needs to be open."); - }); - - let first_setup_driver_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .valign(gtk::Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - - let first_setup_driver_box_text = adw::StatusPage::builder() - .icon_name("audio-card") - .title(t!("first_setup_driver_box_text_title")) - .description(t!("first_setup_driver_box_text_description")) - .build(); - first_setup_driver_box_text.add_css_class("compact"); - - let first_setup_driver_button = gtk::Button::builder() - .label(t!("first_setup_driver_button_label")) - .sensitive(false) - .build(); - - first_setup_driver_button.add_css_class("suggested-action"); - first_setup_driver_button.add_css_class("pill"); - - let first_setup_driver_skip_button = gtk::Button::builder() - .label(t!("first_setup_driver_skip_button_label")) - .sensitive(true) - .width_request(25) - .build(); - - let first_setup_driver_buttons_box = gtk::Box::builder() - .orientation(Orientation::Horizontal) - .halign(gtk::Align::Center) - .valign(gtk::Align::End) - .vexpand(true) - .hexpand(true) - .margin_end(15) - .margin_start(15) - .margin_bottom(15) - .margin_top(15) - .spacing(80) - .build(); - - first_setup_driver_skip_button.add_css_class("pill"); - - first_setup_driver_buttons_box.append(&first_setup_driver_button); - first_setup_driver_buttons_box.append(&first_setup_driver_skip_button); - - first_setup_driver_box.append(&first_setup_driver_box_text); - first_setup_driver_box.append(&first_setup_driver_buttons_box); - - first_setup_carousel.append(&first_setup_driver_box); - - let internet_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - internet_loop_context.spawn_local( - clone!(@strong internet_connected_status, @weak first_setup_driver_button => async move { - while let Ok(_state) = internet_loop_receiver.recv().await { - if *internet_connected_status.borrow_mut() == true { - first_setup_driver_button.set_sensitive(true); - first_setup_driver_button.set_label(&t!("first_setup_driver_button_label")); - } else { - first_setup_driver_button.set_sensitive(false); - first_setup_driver_button.set_label(&t!("internet_network_disabled")); - } - } - }), - ); - - first_setup_driver_button.connect_clicked(clone!(@weak first_setup_carousel, @weak first_setup_driver_button, @weak first_setup_driver_skip_button => move |_| { - Command::new("pika-drivers") - .spawn() - .expect("pika-drivers failed to start"); - first_setup_driver_button.remove_css_class("suggested-action"); - first_setup_driver_skip_button.set_label(&t!("internet_next_button_label")); - first_setup_driver_skip_button.add_css_class("suggested-action"); - })); - - first_setup_driver_skip_button.connect_clicked(clone!(@weak first_setup_carousel => move |_|{ - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(5), true); - })); -} diff --git a/src/first_setup/final_carousel/mod.rs b/src/first_setup/final_carousel/mod.rs deleted file mode 100644 index 21f0ab9..0000000 --- a/src/first_setup/final_carousel/mod.rs +++ /dev/null @@ -1,51 +0,0 @@ -// GTK crates -use adw::prelude::*; -use adw::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - - - -use duct::cmd; - -const REBOOT_PROG: &str = r###" -#! /bin/bash -userdel -r -f pikaos -reboot -"###; - -pub fn final_carousel(first_setup_carousel: &adw::Carousel) { - let first_setup_final_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .vexpand(true) - .valign(Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - - let first_setup_final_box_text = adw::StatusPage::builder() - .icon_name("emblem-favorite") - .title(t!("first_setup_final_box_text_title")) - .description(t!("first_setup_final_box_text_description")) - .build(); - first_setup_final_box_text.add_css_class("compact"); - - let first_setup_start_button = gtk::Button::builder() - .label(t!("first_setup_reboot_button_label")) - .halign(Align::Center) - .build(); - - first_setup_start_button.add_css_class("suggested-action"); - first_setup_start_button.add_css_class("pill"); - - first_setup_final_box.append(&first_setup_final_box_text); - first_setup_final_box.append(&first_setup_start_button); - - first_setup_carousel.append(&first_setup_final_box); - - first_setup_start_button.connect_clicked( move |_| { - let _ = cmd!("/usr/lib/pika/pika-welcome/scripts/pika-sudo.sh", "bash", "-c", REBOOT_PROG).read(); - }); -} diff --git a/src/first_setup/gameutils_carousel/mod.rs b/src/first_setup/gameutils_carousel/mod.rs deleted file mode 100644 index d43ef9c..0000000 --- a/src/first_setup/gameutils_carousel/mod.rs +++ /dev/null @@ -1,223 +0,0 @@ -use std::cell::RefCell; -use std::rc::Rc; -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - - - -use std::{thread, time}; - -use std::{ - error::Error, -}; - -use duct::cmd; -use std::io::prelude::*; -use std::io::BufReader; - -const GAMEUTILS_INSTALL_PROG: &str = " -#! /bin/bash -set -e -/usr/lib/pika/pika-welcome/scripts/pika-sudo.sh apt update -y && /usr/lib/pika/pika-welcome/scripts/pika-sudo.sh apt install pika-gameutils-meta -y -"; - -fn gameutils_install( - log_loop_sender: async_channel::Sender, -) -> Result<(), std::boxed::Box> { - let (pipe_reader, pipe_writer) = os_pipe::pipe()?; - let child = cmd!("bash", "-c", GAMEUTILS_INSTALL_PROG) - .stderr_to_stdout() - .stdout_file(pipe_writer) - .start()?; - for line in BufReader::new(pipe_reader).lines() { - log_loop_sender - .send_blocking(line?) - .expect("Channel needs to be opened.") - } - child.wait()?; - - Ok(()) -} - -pub fn gameutils_carousel( - first_setup_carousel: &adw::Carousel, - internet_connected: &Rc>, - window: &adw::ApplicationWindow, -) { - let internet_connected_status = internet_connected.clone(); - - let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded(); - let internet_loop_sender = internet_loop_sender.clone(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(move || loop { - thread::sleep(time::Duration::from_secs(1)); - internet_loop_sender - .send_blocking(true) - .expect("The channel needs to be open."); - }); - - let (log_loop_sender, log_loop_receiver) = async_channel::unbounded(); - let log_loop_sender: async_channel::Sender = log_loop_sender.clone(); - - let (log_status_loop_sender, log_status_loop_receiver) = async_channel::unbounded(); - let log_status_loop_sender: async_channel::Sender = log_status_loop_sender.clone(); - - let first_setup_gameutils_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .valign(gtk::Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - - let first_setup_gameutils_box_text = adw::StatusPage::builder() - .icon_name("input-gaming") - .title(t!("first_setup_gameutils_box_text_title")) - .description(t!("first_setup_gameutils_box_text_description")) - .build(); - first_setup_gameutils_box_text.add_css_class("compact"); - - let first_setup_gameutils_button = gtk::Button::builder() - .label(t!("first_setup_gameutils_button_label")) - .sensitive(false) - .build(); - - first_setup_gameutils_button.add_css_class("suggested-action"); - first_setup_gameutils_button.add_css_class("pill"); - - let first_setup_gameutils_skip_button = gtk::Button::builder() - .label(t!("first_setup_gameutils_skip_button_label")) - .sensitive(true) - .width_request(25) - .build(); - - let first_setup_gameutils_buttons_box = gtk::Box::builder() - .orientation(Orientation::Horizontal) - .halign(gtk::Align::Center) - .valign(gtk::Align::End) - .vexpand(true) - .hexpand(true) - .margin_end(15) - .margin_start(15) - .margin_bottom(15) - .margin_top(15) - .spacing(80) - .build(); - - first_setup_gameutils_skip_button.add_css_class("pill"); - - let gameutils_install_log_terminal_buffer = gtk::TextBuffer::builder().build(); - - let gameutils_install_log_terminal = gtk::TextView::builder() - .vexpand(true) - .hexpand(true) - .editable(false) - .buffer(&gameutils_install_log_terminal_buffer) - .build(); - - let gameutils_install_log_terminal_scroll = gtk::ScrolledWindow::builder() - .width_request(400) - .height_request(200) - .vexpand(true) - .hexpand(true) - .child(&gameutils_install_log_terminal) - .build(); - - let gameutils_install_dialog = adw::MessageDialog::builder() - .transient_for(window) - .hide_on_close(true) - .extra_child(&gameutils_install_log_terminal_scroll) - .width_request(400) - .height_request(200) - .heading(t!("gameutils_install_dialog_heading")) - .build(); - gameutils_install_dialog.add_response("gameutils_install_dialog_ok", &t!("system_update_dialog_ok_label")); - - first_setup_gameutils_buttons_box.append(&first_setup_gameutils_button); - first_setup_gameutils_buttons_box.append(&first_setup_gameutils_skip_button); - - first_setup_gameutils_box.append(&first_setup_gameutils_box_text); - first_setup_gameutils_box.append(&first_setup_gameutils_buttons_box); - - first_setup_carousel.append(&first_setup_gameutils_box); - - let internet_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - internet_loop_context.spawn_local( - clone!(@strong internet_connected_status, @weak first_setup_gameutils_button => async move { - while let Ok(_state) = internet_loop_receiver.recv().await { - if *internet_connected_status.borrow_mut() == true { - first_setup_gameutils_button.set_sensitive(true); - first_setup_gameutils_button.set_label(&t!("first_setup_gameutils_button_label")); - } else { - first_setup_gameutils_button.set_sensitive(false); - first_setup_gameutils_button.set_label(&t!("internet_network_disabled")); - } - } - }), - ); - - let log_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - log_loop_context.spawn_local(clone!(@weak gameutils_install_log_terminal_buffer, @weak gameutils_install_dialog => async move { - while let Ok(state) = log_loop_receiver.recv().await { - gameutils_install_log_terminal_buffer.insert(&mut gameutils_install_log_terminal_buffer.end_iter(), &("\n".to_string() + &state)) - } - })); - - let log_status_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - log_status_loop_context.spawn_local(clone!(@weak gameutils_install_dialog, @weak first_setup_gameutils_button, @weak first_setup_gameutils_skip_button => async move { - while let Ok(state) = log_status_loop_receiver.recv().await { - if state == true { - gameutils_install_dialog.set_response_enabled("gameutils_install_dialog_ok", true); - gameutils_install_dialog.set_body(&t!("gameutils_install_dialog_success_true")); - first_setup_gameutils_button.remove_css_class("suggested-action"); - first_setup_gameutils_skip_button.set_label("Next"); - first_setup_gameutils_skip_button.add_css_class("suggested-action"); - } else { - first_setup_gameutils_skip_button.remove_css_class("suggested-action"); - first_setup_gameutils_skip_button.set_label("Skip Meta Package Installation"); - first_setup_gameutils_button.add_css_class("suggested-action"); - gameutils_install_dialog.set_response_enabled("gameutils_install_dialog_ok", true); - gameutils_install_dialog.set_body(&t!("gameutils_install_dialog_success_false")); - } - } - })); - - gameutils_install_log_terminal_buffer.connect_changed(clone!(@weak gameutils_install_log_terminal, @weak gameutils_install_log_terminal_buffer,@weak gameutils_install_log_terminal_scroll => move |_|{ - if gameutils_install_log_terminal_scroll.vadjustment().upper() - gameutils_install_log_terminal_scroll.vadjustment().value() > 100.0 { - gameutils_install_log_terminal_scroll.vadjustment().set_value(gameutils_install_log_terminal_scroll.vadjustment().upper()) - } - })); - - first_setup_gameutils_button.connect_clicked(clone!(@strong internet_connected_status, @weak gameutils_install_log_terminal,@weak gameutils_install_log_terminal_buffer, @weak gameutils_install_dialog,@weak first_setup_carousel => move |_| { - gameutils_install_log_terminal_buffer.delete(&mut gameutils_install_log_terminal_buffer.bounds().0, &mut gameutils_install_log_terminal_buffer.bounds().1); - gameutils_install_dialog.set_response_enabled("gameutils_install_dialog_ok", false); - gameutils_install_dialog.set_body(""); - gameutils_install_dialog.present(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(clone!(@strong log_loop_sender, @strong log_status_loop_sender => move || { - let command = gameutils_install(log_loop_sender); - match command { - Ok(_) => { - println!("Status: gameutils install Successful"); - log_status_loop_sender.send_blocking(true).expect("The channel needs to be open."); - } - Err(_) => { - println!("Status: gameutils install Failed"); - log_status_loop_sender.send_blocking(false).expect("The channel needs to be open."); - } - } - })); - })); - - first_setup_gameutils_skip_button.connect_clicked(clone!(@weak first_setup_carousel => move |_|{ - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(7), true); - })); -} diff --git a/src/first_setup/initial_carousel/mod.rs b/src/first_setup/initial_carousel/mod.rs deleted file mode 100644 index 44f7cdd..0000000 --- a/src/first_setup/initial_carousel/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - - -use crate::config::{DISTRO_ICON}; - -pub fn initial_carousel(first_setup_carousel: &adw::Carousel) { - let first_setup_initial_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .vexpand(true) - .valign(Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - - let first_setup_initial_box_text = adw::StatusPage::builder() - .icon_name(DISTRO_ICON) - .title(t!("first_setup_initial_box_text_title")) - .description(t!("first_setup_initial_box_text_description")) - .build(); - first_setup_initial_box_text.add_css_class("compact"); - - let first_setup_start_button = gtk::Button::builder() - .label(t!("first_setup_start_button_label")) - .halign(Align::Center) - .build(); - - first_setup_start_button.add_css_class("suggested-action"); - first_setup_start_button.add_css_class("pill"); - - first_setup_initial_box.append(&first_setup_initial_box_text); - first_setup_initial_box.append(&first_setup_start_button); - - first_setup_carousel.append(&first_setup_initial_box); - - first_setup_start_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(1), true) - })); -} diff --git a/src/first_setup/internet_carousel/mod.rs b/src/first_setup/internet_carousel/mod.rs deleted file mode 100644 index 6c0e1be..0000000 --- a/src/first_setup/internet_carousel/mod.rs +++ /dev/null @@ -1,196 +0,0 @@ -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - - - -//use crate::check_internet_connection; -use std::cell::RefCell; -use std::env; -use std::process::Command; -use std::rc::Rc; - -pub fn internet_carousel( - first_setup_carousel: &adw::Carousel, - internet_connected: &Rc>, - window: &adw::ApplicationWindow, -) { - let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded(); - let internet_loop_sender = internet_loop_sender.clone(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(move || { - loop { - //match check_internet_connection() { - // Ok(_) => { - // internet_loop_sender.send_blocking(true).expect("The channel needs to be open."); - // } - // Err(_) => { - // internet_loop_sender.send_blocking(false).expect("The channel needs to be open."); - // } - //} - let check_internet_connection_cli = Command::new("ping") - .arg("ppa.pika-os.com") - .arg("-c 1") - .output() - .expect("failed to execute process"); - if check_internet_connection_cli.status.success() { - internet_loop_sender - .send_blocking(true) - .expect("The channel needs to be open."); - } else { - internet_loop_sender - .send_blocking(false) - .expect("The channel needs to be open."); - } - } - }); - - let first_setup_internet_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .hexpand(true) - .vexpand(true) - .margin_end(15) - .margin_start(15) - .margin_bottom(15) - .margin_top(15) - .build(); - - let first_setup_internet_box_text = adw::StatusPage::builder() - .icon_name("network-cellular-acquiring") - .title(t!("first_setup_internet_box_text_title")) - .description(t!("first_setup_internet_box_text_description")) - .hexpand(true) - .vexpand(true) - .valign(Align::Start) - .build(); - first_setup_internet_box_text.add_css_class("compact"); - - let internet_skip_button = gtk::Button::builder() - .label(t!("internet_skip_button_label")) - .halign(Align::Center) - .sensitive(false) - .build(); - - internet_skip_button.add_css_class("destructive-action"); - internet_skip_button.add_css_class("pill"); - - let internet_next_button = gtk::Button::builder() - .label(t!("internet_next_button_label")) - .halign(Align::Center) - .sensitive(false) - .build(); - - internet_next_button.add_css_class("suggested-action"); - internet_next_button.add_css_class("pill"); - - let internet_buttons_box = gtk::Box::builder() - .orientation(Orientation::Horizontal) - .halign(Align::Center) - .valign(Align::End) - .vexpand(true) - .hexpand(true) - .margin_end(15) - .margin_start(15) - .margin_bottom(15) - .margin_top(15) - .spacing(80) - .build(); - - let first_setup_internet_button_content_box = gtk::Box::builder() - .orientation(Orientation::Vertical) - .build(); - - let first_setup_internet_button_content_text = gtk::Label::builder() - .label(t!("first_setup_internet_button_content_text_label")) - .build(); - - let first_setup_internet_button_content = adw::ButtonContent::builder() - .label(t!("first_setup_internet_button_content_label")) - .icon_name("network-wired") - .build(); - - let first_setup_internet_button = gtk::Button::builder() - .child(&first_setup_internet_button_content_box) - .halign(Align::Center) - .valign(Align::Center) - .build(); - - internet_buttons_box.append(&internet_skip_button); - internet_buttons_box.append(&internet_next_button); - - first_setup_internet_button_content_box.append(&first_setup_internet_button_content); - first_setup_internet_button_content_box.append(&first_setup_internet_button_content_text); - - first_setup_carousel.append(&first_setup_internet_box); - - first_setup_internet_box.append(&first_setup_internet_box_text); - first_setup_internet_box.append(&first_setup_internet_button); - first_setup_internet_box.append(&internet_buttons_box); - - let first_setup_internet_skip_dialog = adw::MessageDialog::builder() - .heading(t!("first_setup_internet_skip_dialog_heading")) - .body(t!("first_setup_internet_skip_dialog_body")) - .transient_for(window) - .hide_on_close(true) - .build(); - - first_setup_internet_skip_dialog.add_response("skip_cancel", &t!("first_setup_internet_skip_dialog_skip_cancel_label")); - first_setup_internet_skip_dialog.add_response("skip_confirm", &t!("first_setup_internet_skip_dialog_skip_confirm_label")); - first_setup_internet_skip_dialog - .set_response_appearance("skip_confirm", adw::ResponseAppearance::Destructive); - - let internet_connected_status = internet_connected.clone(); - - let internet_loop_context = MainContext::default(); - // The main loop executes the asynchronous block - internet_loop_context.spawn_local(clone!(@weak internet_skip_button, @weak internet_next_button, @weak first_setup_internet_box_text => async move { - while let Ok(state) = internet_loop_receiver.recv().await { - if state == true { - internet_skip_button.set_sensitive(false); - internet_next_button.set_sensitive(true); - first_setup_internet_box_text.set_description(Some(&t!("first_setup_internet_box_text_description_true"))); - first_setup_internet_box_text.set_icon_name(Some("network-cellular-signal-excellent")); - *internet_connected_status.borrow_mut()=true; - } else { - internet_next_button.set_sensitive(false); - internet_skip_button.set_sensitive(true); - first_setup_internet_box_text.set_description(Some(&t!("first_setup_internet_box_text_description_false"))); - first_setup_internet_box_text.set_icon_name(Some("network-cellular-offline")); - *internet_connected_status.borrow_mut()=false; - } - } - })); - - first_setup_internet_button.connect_clicked(move |_| { - let env_xdg_session_desktop = env::var("XDG_SESSION_DESKTOP").unwrap(); - if env_xdg_session_desktop.contains("gnome") || env_xdg_session_desktop.contains("ubuntu") { - Command::new("gnome-control-center") - .arg("network") - .spawn() - .expect("gnome-control-center failed to start"); - } else { - Command::new("nm-connection-editor") - .spawn() - .expect("nm-connection-editor failed to start"); - } - }); - - internet_next_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(2), true); - })); - - internet_skip_button.connect_clicked( - clone!(@weak first_setup_carousel, @weak first_setup_internet_skip_dialog => move |_| { - first_setup_internet_skip_dialog.choose(None::<&gio::Cancellable>, move |choice| { - if choice == "skip_confirm" { - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(2), true); - } - }); - }), - ); -} diff --git a/src/first_setup/mod.rs b/src/first_setup/mod.rs deleted file mode 100644 index 1925732..0000000 --- a/src/first_setup/mod.rs +++ /dev/null @@ -1,83 +0,0 @@ -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) - - - -// -use std::cell::RefCell; -use std::rc::Rc; - -// carousel crates -mod initial_carousel; -mod internet_carousel; -mod user_carousel; -mod update_carousel; -mod driver_carousel; -mod codec_carousel; -mod gameutils_carousel; -mod final_carousel; - -use initial_carousel::*; -use internet_carousel::*; -use user_carousel::*; -use update_carousel::*; -use driver_carousel::*; -use codec_carousel::*; -use gameutils_carousel::*; -use final_carousel::*; - -pub fn first_setup(window: &adw::ApplicationWindow) { - let first_setup_carousel = adw::Carousel::builder() - .allow_long_swipes(false) - .allow_mouse_drag(false) - .allow_scroll_wheel(false) - .interactive(false) - .vexpand(true) - .hexpand(true) - .build(); - - let first_setup_carousel_indicator = adw::CarouselIndicatorDots::builder() - .carousel(&first_setup_carousel) - .build(); - - let first_setup_window_headerbar_back_button = gtk::Button::builder().label(t!("first_setup_window_headerbar_back_button_label")).build(); - - let first_setup_window_headerbar = adw::HeaderBar::builder() - .show_start_title_buttons(true) - .title_widget(&first_setup_carousel_indicator) - .build(); - - let first_setup_window_toolbarview = adw::ToolbarView::builder() - .top_bar_style(ToolbarStyle::Flat) - .content(&first_setup_carousel) - .build(); - - let internet_connected = Rc::new(RefCell::new(false)); - - first_setup_window_headerbar.pack_start(&first_setup_window_headerbar_back_button); - first_setup_window_toolbarview.add_top_bar(&first_setup_window_headerbar); - - first_setup_window_headerbar_back_button.connect_clicked(clone!(@weak first_setup_carousel => move |_| { - let first_setup_prev_page = first_setup_carousel.position() - 1.0; - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(first_setup_prev_page as u32), true) - })); - - // CAROUSELS - - // Initial Carousel - initial_carousel(&first_setup_carousel); - internet_carousel(&first_setup_carousel, &internet_connected, &window); - user_carousel(&first_setup_carousel); - update_carousel(&first_setup_carousel, &internet_connected, &window); - driver_carousel(&first_setup_carousel, &internet_connected); - codec_carousel(&first_setup_carousel, &internet_connected, &window); - gameutils_carousel(&first_setup_carousel, &internet_connected, &window); - final_carousel(&first_setup_carousel); - - // Add file to window - window.set_content(Some(&first_setup_window_toolbarview)) -} diff --git a/src/first_setup/user_carousel/mod.rs b/src/first_setup/user_carousel/mod.rs deleted file mode 100644 index 12be2db..0000000 --- a/src/first_setup/user_carousel/mod.rs +++ /dev/null @@ -1,324 +0,0 @@ -// GTK crates -use adw::prelude::*; -use adw::*; -use glib::*; -/// Use all gtk4 libraries (gtk4 -> gtk because cargo) -/// Use all libadwaita libraries (libadwaita -> adw because cargo) -use gtk::*; - -// -use regex::Regex; -use std::cell::RefCell; -use std::rc::Rc; -use std::{thread, time}; -use duct::cmd; - -const USER_CREATE_PROG: &str = r###" -#! /bin/bash -USERNAME="$0" -PASSWORD="$1" -FULLNAME="$2" -HOSTNAME="$3" -adduser --quiet --disabled-password --shell /bin/bash --gecos "${FULLNAME}" "${USERNAME}" -echo "${USERNAME}":"${PASSWORD}" | chpasswd -usermod -a -G sudo "${USERNAME}" -mkdir -p /home/"${USERNAME}" -cp -rvf /etc/skel/.* /home/"${USERNAME}"/ || true -chown -R "${USERNAME}":"${USERNAME}" /home/"${USERNAME}" -usermod -a -G adm,cdrom,sudo,render,dip,video,plugdev,input,render,lpadmin "${USERNAME}" -rm -rf /etc/sddm.conf.d/zautologin.conf || true -hostnamectl set-hostname "${HOSTNAME}" -echo "127.0.0.1 ${HOSTNAME}" >> /etc/hosts -"###; - -fn only_alphanumeric(input: &str) -> bool { - return input.chars().all(|c| c.is_alphanumeric()); -} - -fn uppercase_first_letter(s: &str) -> String { - let mut c = s.chars(); - match c.next() { - None => String::new(), - Some(f) => f.to_uppercase().chain(c).collect(), - } -} - -pub fn user_carousel(first_setup_carousel: &adw::Carousel) { - let user_info_username_valid = Rc::new(RefCell::new(false)); - let user_info_full_name_valid = Rc::new(RefCell::new(false)); - let user_info_hostname_valid = Rc::new(RefCell::new(false)); - let user_info_passwords_valid = Rc::new(RefCell::new(false)); - - let (user_loop_sender, user_loop_receiver) = async_channel::unbounded(); - let user_loop_sender = user_loop_sender.clone(); - // The long running operation runs now in a separate thread - gio::spawn_blocking(move || loop { - thread::sleep(time::Duration::from_secs(1)); - user_loop_sender - .send_blocking(true) - .expect("The channel needs to be open."); - }); - - let first_setup_user_box = gtk::Box::builder() - // that puts items vertically - .orientation(Orientation::Vertical) - .hexpand(true) - .vexpand(true) - .margin_end(15) - .margin_start(15) - .margin_bottom(15) - .margin_top(15) - .build(); - - let first_setup_user_box_text = adw::StatusPage::builder() - .title(t!("first_setup_user_box_text_title")) - .description(t!("first_setup_user_box_text_description")) - .hexpand(true) - .valign(Align::Start) - .build(); - first_setup_user_box_text.add_css_class("compact"); - - let user_info_box = gtk::Box::builder() - .orientation(Orientation::Vertical) - .valign(Align::Center) - .vexpand(true) - .hexpand(true) - .build(); - - let user_info_box_clamp = adw::Clamp::builder() - .child(&user_info_box) - .maximum_size(500) - .build(); - - let user_info_username = adw::EntryRow::builder() - .hexpand(true) - .title(t!("user_info_username_title")) - .input_purpose(InputPurpose::Alpha) - .input_hints(InputHints::LOWERCASE) - .build(); - - let user_info_full_name = adw::EntryRow::builder() - .hexpand(true) - .title(t!("user_info_full_name_title")) - .input_purpose(InputPurpose::Name) - .build(); - - let user_info_password = adw::PasswordEntryRow::builder() - .hexpand(true) - .title(t!("user_info_password_title")) - .build(); - - let user_info_hostname = adw::EntryRow::builder() - .hexpand(true) - .title(t!("user_info_hostname_title")) - .build(); - - let user_info_password_verify = adw::PasswordEntryRow::builder() - .hexpand(true) - .title(t!("user_info_password_verify_title")) - .build(); - - let user_info_password_verify_revealer = gtk::Revealer::builder() - .child(&user_info_password_verify) - .reveal_child(false) - .transition_type(RevealerTransitionType::SwingDown) - .build(); - - let user_info_avatar = adw::Avatar::builder() - .show_initials(true) - .size(128) - .margin_top(15) - .margin_bottom(15) - .margin_start(15) - .margin_end(15) - .build(); - - let _user_info_avatar_full_name_binding = user_info_full_name - .bind_property("text", &user_info_avatar, "text") - .sync_create() - .build(); - - let user_info_listbox = gtk::ListBox::builder() - .margin_top(15) - .margin_bottom(15) - .margin_start(15) - .margin_end(15) - .build(); - user_info_listbox.add_css_class("boxed-list"); - - let error_label = gtk::Label::builder() - .margin_top(15) - .margin_bottom(15) - .margin_start(15) - .margin_end(15) - .visible(false) - .build(); - - error_label.add_css_class("red-text"); - - let user_next_button = gtk::Button::builder() - .label(t!("internet_next_button_label")) - .sensitive(false) - .halign(Align::Center) - .valign(Align::End) - .vexpand(true) - .hexpand(true) - .build(); - - user_next_button.add_css_class("suggested-action"); - user_next_button.add_css_class("pill"); - - first_setup_carousel.append(&first_setup_user_box); - - user_info_listbox.append(&user_info_username); - user_info_listbox.append(&user_info_full_name); - user_info_listbox.append(&user_info_hostname); - user_info_listbox.append(&user_info_password); - user_info_listbox.append(&user_info_password_verify_revealer); - - user_info_box.append(&user_info_avatar); - user_info_box.append(&user_info_listbox); - - first_setup_user_box.append(&first_setup_user_box_text); - first_setup_user_box.append(&user_info_box_clamp); - first_setup_user_box.append(&error_label); - first_setup_user_box.append(&user_next_button); - - // The main loop executes the asynchronous block - let user_loop_context = MainContext::default(); - user_loop_context.spawn_local(clone!(@strong user_info_username_valid, @strong user_info_full_name_valid,@strong user_info_hostname_valid, @strong user_info_passwords_valid, @weak user_next_button => async move { - while let Ok(_state) = user_loop_receiver.recv().await { - if *user_info_username_valid.borrow_mut() == true && *user_info_full_name_valid.borrow_mut() == true && *user_info_hostname_valid.borrow_mut() && *user_info_passwords_valid.borrow_mut() == true { - user_next_button.set_sensitive(true); - } else { - user_next_button.set_sensitive(false); - } - } - })); - - user_info_username.connect_changed(clone!(@strong user_info_username_valid, @weak user_info_username, @weak user_info_full_name, @weak error_label => move |_| { - let user_info_username_string = user_info_username.text().to_string(); - - user_info_full_name.set_text(&uppercase_first_letter(&user_info_username_string)); - - if user_info_username_string.len() > 32 { - user_info_username.set_text(&user_info_username_string[..32]); - user_info_username.set_position(-1); - } - - if Regex::new(r"[A-Z]").unwrap().is_match(&user_info_username_string) { - user_info_username.set_text(&user_info_username_string.to_lowercase()); - user_info_username.set_position(-1); - } - - let mut _username_is_root = false; - let mut _username_is_pikaos = false; - let mut _username_is_special = false; - - if user_info_username_string != "root" { - _username_is_root=false; - } else { - error_label.set_label(&t!("error_label_is_root_label")); - _username_is_root=true; - } - - if user_info_username_string != "pikaos" { - _username_is_pikaos=false; - } else { - error_label.set_label(&t!("error_label_is_pikaos_label")); - _username_is_pikaos=true; - } - - if only_alphanumeric(&user_info_username_string) { - _username_is_special=false; - } else { - error_label.set_label(&t!("error_label_username_is_special_label")); - _username_is_special=true; - } - - if _username_is_root == false && _username_is_pikaos == false && _username_is_special == false { - error_label.set_visible(false); - if !user_info_username.text().is_empty() { - *user_info_username_valid.borrow_mut()=true; - } - } else { - *user_info_username_valid.borrow_mut()=false; - error_label.set_visible(true); - } - })); - - user_info_full_name.connect_changed(clone!(@strong user_info_full_name_valid, @weak user_info_full_name, @weak error_label => move |_| { - let user_info_full_name_string = user_info_full_name.text().to_string(); - - if user_info_full_name_string.len() > 32 { - user_info_full_name.set_text(&user_info_full_name_string[..32]); - user_info_full_name.set_position(-1); - } - - if user_info_full_name.text().is_empty() { - *user_info_full_name_valid.borrow_mut()=false; - } else { - *user_info_full_name_valid.borrow_mut()=true; - } - })); - - user_info_hostname.connect_changed(clone!(@strong user_info_hostname_valid, @weak user_info_hostname, @weak user_info_full_name, @weak error_label => move |_| { - let user_info_hostname_string = user_info_hostname.text().to_string(); - - if user_info_hostname_string.len() > 32 { - user_info_hostname.set_text(&user_info_hostname_string[..32]); - user_info_hostname.set_position(-1); - } - - let mut _hostname_is_special = false; - - if Regex::new(r"^[A-Za-z0-9\.]*$").unwrap().is_match(&user_info_hostname_string) { - _hostname_is_special=false; - } else { - error_label.set_label(&t!("error_label_hostname_is_special_label")); - _hostname_is_special=true; - } - - if _hostname_is_special == false { - error_label.set_visible(false); - if !user_info_hostname.text().is_empty() { - *user_info_hostname_valid.borrow_mut()=true; - } - } else { - *user_info_hostname_valid.borrow_mut()=false; - error_label.set_visible(true); - } - })); - - user_info_password.connect_changed(clone!(@strong user_info_passwords_valid,@weak user_info_password_verify_revealer, @weak user_info_password, @weak user_info_password_verify, @weak error_label => move |_| { - if user_info_password.text().is_empty() { - user_info_password_verify_revealer.set_reveal_child(false) - } else { - user_info_password_verify_revealer.set_reveal_child(true) - } - - if user_info_password.text() == user_info_password_verify.text() { - error_label.set_visible(false); - *user_info_passwords_valid.borrow_mut()=true; - } else { - *user_info_passwords_valid.borrow_mut()=false; - } - })); - - user_info_password_verify.connect_changed(clone!(@strong user_info_passwords_valid, @weak user_info_password, @weak user_info_password_verify, @weak error_label => move |_| { - if user_info_password.text() == user_info_password_verify.text() { - error_label.set_visible(false); - *user_info_passwords_valid.borrow_mut()=true; - } else { - error_label.set_visible(true); - error_label.set_label(&t!("error_label_password_mismatch_label")); - *user_info_passwords_valid.borrow_mut()=false; - } - })); - - user_next_button.connect_clicked(clone!(@weak first_setup_carousel, @weak user_info_username, @weak user_info_hostname, @weak user_info_password, @weak user_info_full_name, @weak user_info_hostname_valid => move |_| { - let result = cmd!("/usr/lib/pika/pika-welcome/scripts/pika-sudo.sh", "bash", "-c", USER_CREATE_PROG, &user_info_username.text(), &user_info_password.text(), &user_info_full_name.text(), &user_info_hostname.text()).read(); - assert!(result.is_ok()); - first_setup_carousel.scroll_to(&first_setup_carousel.nth_page(3), true); - })); -} diff --git a/src/main.rs b/src/main.rs index b4ec14f..3365aa0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,8 @@ use gdk::Display; /// Use all libadwaita libraries (libadwaita -> adw because cargo) use gtk::*; use single_instance::SingleInstance; +use glib::*; +use glib::prelude::*; use std::boxed::Box; use users::*; @@ -17,8 +19,9 @@ use config::{APP_ID}; // application crates mod build_ui; use crate::build_ui::build_ui; +mod save_window_size; /// first setup crates -mod first_setup; +mod welcome_content_page; // Init translations for current crate. #[macro_use] diff --git a/src/save_window_size/mod.rs b/src/save_window_size/mod.rs new file mode 100644 index 0000000..d125a86 --- /dev/null +++ b/src/save_window_size/mod.rs @@ -0,0 +1,14 @@ +use adw::ffi::AdwApplicationWindow; +use adw::{gio, glib}; +use adw::prelude::SettingsExt; +use adw::subclass::window; +use gtk::prelude::GtkWindowExt; +use glib::*; +use glib::prelude::*; +pub fn save_window_size(window: &adw::ApplicationWindow, glib_settings: &gio::Settings) { + let size = window.default_size(); + + let _ = glib_settings.set_int("window-width", size.0); + let _ = glib_settings.set_int("window-height", size.1); + let _ = glib_settings.set_boolean("is-maximized", window.is_maximized()); +} diff --git a/src/welcome_content_page/mod.rs b/src/welcome_content_page/mod.rs new file mode 100644 index 0000000..c8bf4a3 --- /dev/null +++ b/src/welcome_content_page/mod.rs @@ -0,0 +1,131 @@ +// GTK crates +use adw::prelude::*; +use adw::*; +use glib::*; +/// Use all gtk4 libraries (gtk4 -> gtk because cargo) +/// Use all libadwaita libraries (libadwaita -> adw because cargo) + + + +// +use std::cell::RefCell; +use std::process::Command; +use std::rc::Rc; +use adw::glib::gobject_ffi::GValue; +use gtk::Orientation::Horizontal; + +// carousel crates +mod update_carousel; + +use update_carousel::*; +use crate::config::{APP_GITHUB, APP_ICON, VERSION}; + +pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::Box) { + let internet_connected = Rc::new(RefCell::new(false)); + + let (internet_loop_sender, internet_loop_receiver) = async_channel::unbounded(); + let internet_loop_sender = internet_loop_sender.clone(); + // The long running operation runs now in a separate thread + gio::spawn_blocking(move || { + loop { + //match check_internet_connection() { + // Ok(_) => { + // internet_loop_sender.send_blocking(true).expect("The channel needs to be open."); + // } + // Err(_) => { + // internet_loop_sender.send_blocking(false).expect("The channel needs to be open."); + // } + //} + let check_internet_connection_cli = Command::new("ping") + .arg("ppa.pika-os.com") + .arg("-c 1") + .output() + .expect("failed to execute process"); + if check_internet_connection_cli.status.success() { + internet_loop_sender + .send_blocking(true) + .expect("The channel needs to be open."); + } else { + internet_loop_sender + .send_blocking(false) + .expect("The channel needs to be open."); + } + } + }); + + let window_title_bar = gtk::HeaderBar::builder().show_title_buttons(true).build(); + + let credits_button = gtk::Button::builder() + .icon_name("dialog-information-symbolic") + .build(); + + let credits_window = adw::AboutWindow::builder() + .application_icon(APP_ICON) + .application_name(t!("app_name")) + .transient_for(window) + .version(VERSION) + .hide_on_close(true) + .developer_name(t!("app_dev")) + .issue_url(APP_GITHUB.to_owned() + "/issues") + .build(); + + content_box.append(&window_title_bar); + + let welcome_content_page_stack = gtk::Stack::builder() + .vexpand(true) + .hexpand(true) + .build(); + + let welcome_content_page_stack_sidebar = gtk::StackSidebar::builder() + .vexpand(true) + .hexpand(true) + .stack(&welcome_content_page_stack) + .build(); + + let welcome_content_page_split_view = adw::OverlaySplitView::builder() + .vexpand(true) + .hexpand(true) + .content(&welcome_content_page_stack) + .sidebar(&welcome_content_page_stack_sidebar) + .max_sidebar_width(300.0) + .min_sidebar_width(300.0) + .enable_hide_gesture(true) + .enable_show_gesture(true) + .build(); + + let sidebar_toggle_button = gtk::ToggleButton::builder() + .icon_name("view-right-pane-symbolic") + .build(); + + let _sidebar_toggle_button_binding = welcome_content_page_split_view + .bind_property("show_sidebar", &sidebar_toggle_button, "active") + .sync_create() + .bidirectional() + .build(); + + let welcome_content_page_split_view_breakpoint = adw::Breakpoint::new(BreakpointCondition::new_length(BreakpointConditionLengthType::MaxWidth, 400.0, LengthUnit::Px)); + welcome_content_page_split_view_breakpoint.add_setter(&welcome_content_page_split_view, "show_sidebar", &false.to_value()); + + window.add_breakpoint(welcome_content_page_split_view_breakpoint); + + window_title_bar.pack_end(&credits_button); + window_title_bar.pack_start(&sidebar_toggle_button); + content_box.append(&welcome_content_page_split_view); + + credits_button + .connect_clicked(clone!(@weak credits_button => move |_| credits_window.present())); + + let internet_connected_status = internet_connected.clone(); + + let internet_loop_context = MainContext::default(); + // The main loop executes the asynchronous block + internet_loop_context.spawn_local(clone!(@weak window => async move { + while let Ok(state) = internet_loop_receiver.recv().await { + if state == true { + *internet_connected_status.borrow_mut()=true; + } else { + *internet_connected_status.borrow_mut()=false; + } + } + })); +} diff --git a/src/first_setup/update_carousel/mod.rs b/src/welcome_content_page/update_carousel/mod.rs similarity index 100% rename from src/first_setup/update_carousel/mod.rs rename to src/welcome_content_page/update_carousel/mod.rs