RR: Codec page + Gameutils Page + Update Page fixes + change default window size

This commit is contained in:
Ward from fusion-voyager-3 2024-02-09 16:57:56 +03:00
parent f41136a754
commit 15c59118a3
7 changed files with 604 additions and 4 deletions

View File

@ -2,11 +2,11 @@
<schemalist>
<schema id="com.github.pikaos-linux.pikafirstsetup" path="/com/github/pikaos-linux/pikafirstsetup/">
<key name="window-width" type="i">
<default>1200</default>
<default>700</default>
<summary>Default window width</summary>
</key>
<key name="window-height" type="i">
<default>600</default>
<default>500</default>
<summary>Default window height</summary>
</key>
<key name="is-maximized" type="b">

View File

@ -0,0 +1,230 @@
use std::cell::RefCell;
use std::rc::Rc;
// GTK crates
use adw::ffi::ADW_TOOLBAR_FLAT;
use adw::prelude::*;
use adw::*;
use gdk::Display;
use glib::*;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use vte::prelude::*;
use vte::*;
use std::{thread, time};
use std::{
error::Error,
io::Error as ErrorIO,
io::{ErrorKind, Read, Write},
process::{Command, Stdio},
};
use duct::cmd;
use os_pipe::*;
use std::io::prelude::*;
use std::io::BufReader;
const CODEC_INSTALL_PROG: &str = "
#! /bin/bash
set -e
sudo apt update -y && sudo apt install pika-codecs-meta -y
";
fn codec_install(
log_loop_sender: async_channel::Sender<String>,
) -> Result<(), std::boxed::Box<dyn Error + Send + Sync>> {
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<RefCell<bool>>,
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<String> = log_loop_sender.clone();
let (log_status_loop_sender, log_status_loop_receiver) = async_channel::unbounded();
let log_status_loop_sender: async_channel::Sender<bool> = 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("Multi-media Codecs")
.description("Would you like to install additional video playback and encoding/decoding packages?\n(strongly recommended)")
.build();
first_setup_codec_box_text.add_css_class("compact");
let first_setup_codec_button = gtk::Button::builder()
.label("Install Codecs")
.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("Skip Codec Installation")
.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("Codec installation Log")
.build();
codec_install_dialog.add_response("codec_install_dialog_ok", "Ok");
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("Install Codecs");
} else {
first_setup_codec_button.set_sensitive(false);
first_setup_codec_button.set_label("Disabled.. Network setup was skipped");
}
}
}),
);
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("Codec installation Completed Successfully!");
first_setup_codec_button.remove_css_class("suggested-action");
first_setup_codec_skip_button.set_label("Next");
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("Skip Codec Installation");
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("Codec installation Failed!\nPlease try again.");
}
}
}));
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);
}));
}

View File

@ -0,0 +1,126 @@
use std::cell::RefCell;
use std::rc::Rc;
// GTK crates
use adw::ffi::ADW_TOOLBAR_FLAT;
use adw::prelude::*;
use adw::*;
use gdk::Display;
use glib::*;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use vte::prelude::*;
use vte::*;
use std::{thread, time};
use std::{
error::Error,
io::Error as ErrorIO,
io::{ErrorKind, Read, Write},
process::{Command, Stdio},
};
use duct::cmd;
use os_pipe::*;
use std::io::prelude::*;
use std::io::BufReader;
pub fn driver_carousel(
first_setup_carousel: &adw::Carousel,
internet_connected: &Rc<RefCell<bool>>,
) {
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("Hardware Drivers")
.description("You can install drivers such as the NVIDIA proprietary drivers and CPU microcode.")
.build();
first_setup_driver_box_text.add_css_class("compact");
let first_setup_driver_button = gtk::Button::builder()
.label("Open Driver manager")
.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("Skip Driver installation")
.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("Open Driver manager");
} else {
first_setup_driver_button.set_sensitive(false);
first_setup_driver_button.set_label("Disabled.. Network setup was skipped");
}
}
}),
);
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("Next");
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);
}));
}

View File

@ -19,6 +19,9 @@ use crate::first_setup::initial_carousel::initial_carousel;
use crate::first_setup::internet_carousel::internet_carousel;
use crate::first_setup::update_carousel::update_carousel;
use crate::first_setup::user_carousel::user_carousel;
use crate::first_setup::driver_carousel::driver_carousel;
use crate::first_setup::codec_carousel::codec_carousel;
use crate::first_setup::gameutils_carousel::gameutils_carousel;
pub fn first_setup(window: &adw::ApplicationWindow) {
let first_setup_carousel = adw::Carousel::builder()
@ -63,6 +66,9 @@ pub fn first_setup(window: &adw::ApplicationWindow) {
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);
// Add file to window
window.set_content(Some(&first_setup_window_toolbarview))

View File

@ -0,0 +1,230 @@
use std::cell::RefCell;
use std::rc::Rc;
// GTK crates
use adw::ffi::ADW_TOOLBAR_FLAT;
use adw::prelude::*;
use adw::*;
use gdk::Display;
use glib::*;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use vte::prelude::*;
use vte::*;
use std::{thread, time};
use std::{
error::Error,
io::Error as ErrorIO,
io::{ErrorKind, Read, Write},
process::{Command, Stdio},
};
use duct::cmd;
use os_pipe::*;
use std::io::prelude::*;
use std::io::BufReader;
const GAMEUTILS_INSTALL_PROG: &str = "
#! /bin/bash
set -e
sudo apt update -y && sudo apt install pika-gameutils-meta -y
";
fn gameutils_install(
log_loop_sender: async_channel::Sender<String>,
) -> Result<(), std::boxed::Box<dyn Error + Send + Sync>> {
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<RefCell<bool>>,
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<String> = log_loop_sender.clone();
let (log_status_loop_sender, log_status_loop_receiver) = async_channel::unbounded();
let log_status_loop_sender: async_channel::Sender<bool> = 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("PikaOS Gaming Meta Package")
.description("Would you like the PikaOS Gaming Meta Package?\n(essential for gaming thus strongly recommended)")
.build();
first_setup_gameutils_box_text.add_css_class("compact");
let first_setup_gameutils_button = gtk::Button::builder()
.label("Install Meta Package")
.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("Skip Meta Package Installation")
.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("Meta Package installation Log")
.build();
gameutils_install_dialog.add_response("gameutils_install_dialog_ok", "Ok");
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("Install Meta Package");
} else {
first_setup_gameutils_button.set_sensitive(false);
first_setup_gameutils_button.set_label("Disabled.. Network setup was skipped");
}
}
}),
);
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("Meta Package installation Completed Successfully!");
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("Meta Package installation Failed!\nPlease try again.");
}
}
}));
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);
}));
}

View File

@ -3,3 +3,6 @@ pub mod initial_carousel;
pub mod internet_carousel;
pub mod update_carousel;
pub mod user_carousel;
pub mod driver_carousel;
pub mod codec_carousel;
pub mod gameutils_carousel;

View File

@ -77,7 +77,6 @@ pub fn update_carousel(
let first_setup_update_box = gtk::Box::builder()
// that puts items vertically
.orientation(Orientation::Vertical)
.vexpand(true)
.valign(gtk::Align::Center)
.hexpand(true)
.vexpand(true)
@ -180,12 +179,18 @@ pub fn update_carousel(
let log_status_loop_context = MainContext::default();
// The main loop executes the asynchronous block
log_status_loop_context.spawn_local(clone!(@weak system_update_dialog => async move {
log_status_loop_context.spawn_local(clone!(@weak system_update_dialog, @weak first_setup_update_button, @weak first_setup_update_skip_button => async move {
while let Ok(state) = log_status_loop_receiver.recv().await {
if state == true {
system_update_dialog.set_response_enabled("system_update_dialog_ok", true);
system_update_dialog.set_body("Update Completed Successfully!");
first_setup_update_button.remove_css_class("suggested-action");
first_setup_update_skip_button.set_label("Next");
first_setup_update_skip_button.add_css_class("suggested-action");
} else {
first_setup_update_skip_button.remove_css_class("suggested-action");
first_setup_update_skip_button.set_label("Skip");
first_setup_update_button.add_css_class("suggested-action");
system_update_dialog.set_response_enabled("system_update_dialog_ok", true);
system_update_dialog.set_body("Update Failed!\nPlease try again.");
}