Add size groups
This commit is contained in:
parent
02e7cac3a9
commit
7028ce4682
20
data/config/community.json
Normal file
20
data/config/community.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"setup_steps": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"title": "update-pikaos-title",
|
||||||
|
"subtitle": "update-pikaos-subtitle",
|
||||||
|
"icon": "pika-system-software-update",
|
||||||
|
"button": "update-pikaos-button-label",
|
||||||
|
"command": "echo update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "install-media-codec-title",
|
||||||
|
"subtitle": "install-media-codec-subtitle",
|
||||||
|
"icon": "pika-media-tape",
|
||||||
|
"button": "install-media-codec-button-label",
|
||||||
|
"command": "echo codec"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
20
data/config/contribute.json
Normal file
20
data/config/contribute.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"setup_steps": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"title": "update-pikaos-title",
|
||||||
|
"subtitle": "update-pikaos-subtitle",
|
||||||
|
"icon": "pika-system-software-update",
|
||||||
|
"button": "update-pikaos-button-label",
|
||||||
|
"command": "echo update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "install-media-codec-title",
|
||||||
|
"subtitle": "install-media-codec-subtitle",
|
||||||
|
"icon": "pika-media-tape",
|
||||||
|
"button": "install-media-codec-button-label",
|
||||||
|
"command": "echo codec"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
22
data/config/look_and_feel.json
Normal file
22
data/config/look_and_feel.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"look_and_feel": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"title": "update-pikaos-title",
|
||||||
|
"subtitle": "update-pikaos-subtitle",
|
||||||
|
"icon": "pika-system-software-update",
|
||||||
|
"button": "update-pikaos-button-label",
|
||||||
|
"only-in": "",
|
||||||
|
"command": "echo update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "update-pikaos-title",
|
||||||
|
"subtitle": "update-pikaos-subtitle",
|
||||||
|
"icon": "pika-system-software-update",
|
||||||
|
"button": "update-pikaos-button-label",
|
||||||
|
"only-in": "gnome",
|
||||||
|
"command": "echo update"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
20
data/config/troubleshoot.json
Normal file
20
data/config/troubleshoot.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"setup_steps": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"title": "update-pikaos-title",
|
||||||
|
"subtitle": "update-pikaos-subtitle",
|
||||||
|
"icon": "pika-system-software-update",
|
||||||
|
"button": "update-pikaos-button-label",
|
||||||
|
"command": "echo update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "install-media-codec-title",
|
||||||
|
"subtitle": "install-media-codec-subtitle",
|
||||||
|
"icon": "pika-media-tape",
|
||||||
|
"button": "install-media-codec-button-label",
|
||||||
|
"command": "echo codec"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,7 +1,4 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use adw::prelude::*;
|
|
||||||
use adw::*;
|
|
||||||
use gtk::Orientation;
|
|
||||||
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
|
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
|
||||||
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
|
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
|
||||||
|
|
||||||
@ -10,6 +7,9 @@ use gtk::Orientation;
|
|||||||
use crate::config::*;
|
use crate::config::*;
|
||||||
use crate::save_window_size::save_window_size;
|
use crate::save_window_size::save_window_size;
|
||||||
use crate::welcome_content_page::welcome_content_page;
|
use crate::welcome_content_page::welcome_content_page;
|
||||||
|
use adw::prelude::*;
|
||||||
|
use adw::*;
|
||||||
|
use gtk::Orientation;
|
||||||
|
|
||||||
pub fn build_ui(app: &adw::Application) {
|
pub fn build_ui(app: &adw::Application) {
|
||||||
// setup glib
|
// setup glib
|
||||||
@ -52,4 +52,4 @@ pub fn build_ui(app: &adw::Application) {
|
|||||||
welcome_content_page(&window, &content_box);
|
welcome_content_page(&window, &content_box);
|
||||||
// show the window
|
// show the window
|
||||||
window.present()
|
window.present()
|
||||||
}
|
}
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -1,7 +1,6 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
mod config;
|
mod config;
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
use gdk::Display;
|
use gdk::Display;
|
||||||
@ -9,10 +8,11 @@ use gdk::Display;
|
|||||||
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
|
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
|
||||||
use gtk::*;
|
use gtk::*;
|
||||||
use single_instance::SingleInstance;
|
use single_instance::SingleInstance;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
use config::APP_ID;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use users::*;
|
use users::*;
|
||||||
use config::APP_ID;
|
|
||||||
|
|
||||||
// application crates
|
// application crates
|
||||||
mod build_ui;
|
mod build_ui;
|
||||||
@ -33,10 +33,7 @@ fn main() {
|
|||||||
None => panic!("$LANG is not set"),
|
None => panic!("$LANG is not set"),
|
||||||
};
|
};
|
||||||
rust_i18n::set_locale(current_locale.strip_suffix(".UTF-8").unwrap());
|
rust_i18n::set_locale(current_locale.strip_suffix(".UTF-8").unwrap());
|
||||||
let application = adw::Application::new(
|
let application = adw::Application::new(Some(APP_ID), Default::default());
|
||||||
Some(APP_ID),
|
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
application.connect_startup(|app| {
|
application.connect_startup(|app| {
|
||||||
// The CSS "magic" happens here.
|
// The CSS "magic" happens here.
|
||||||
let provider = CssProvider::new();
|
let provider = CssProvider::new();
|
||||||
@ -60,5 +57,4 @@ fn main() {
|
|||||||
println!("Error: This program can only be run via an installed system user");
|
println!("Error: This program can only be run via an installed system user");
|
||||||
std::process::exit(1)
|
std::process::exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use adw::{gio,};
|
use adw::gio;
|
||||||
use adw::prelude::SettingsExt;
|
use adw::prelude::SettingsExt;
|
||||||
use gtk::prelude::GtkWindowExt;
|
use gtk::prelude::GtkWindowExt;
|
||||||
pub fn save_window_size(window: &adw::ApplicationWindow, glib_settings: &gio::Settings) {
|
pub fn save_window_size(window: &adw::ApplicationWindow, glib_settings: &gio::Settings) {
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use duct::cmd;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{thread, time};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
|
use duct::cmd;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||||
struct setup_steps_entry {
|
struct community_entry {
|
||||||
id: i32,
|
id: i32,
|
||||||
title: String,
|
title: String,
|
||||||
subtitle: String,
|
subtitle: String,
|
||||||
icon: String,
|
icon: String,
|
||||||
button: String,
|
button: String,
|
||||||
command: String
|
command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_steps_page(
|
pub fn community_page(
|
||||||
setup_steps_content_page_stack: >k::Stack,
|
community_content_page_stack: >k::Stack,
|
||||||
window: &adw::ApplicationWindow,
|
window: &adw::ApplicationWindow,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -38,12 +38,9 @@ pub fn setup_steps_page(
|
|||||||
.expect("The channel needs to be open.");
|
.expect("The channel needs to be open.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let setup_steps_page_box = gtk::Box::builder()
|
let community_page_box = gtk::Box::builder().vexpand(true).hexpand(true).build();
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
let community_page_listbox = gtk::ListBox::builder()
|
||||||
.margin_top(20)
|
.margin_top(20)
|
||||||
.margin_bottom(20)
|
.margin_bottom(20)
|
||||||
.margin_start(20)
|
.margin_start(20)
|
||||||
@ -51,13 +48,13 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
community_page_listbox.add_css_class("boxed-list");
|
||||||
|
|
||||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
let community_page_scroll = gtk::ScrolledWindow::builder()
|
||||||
// that puts items vertically
|
// that puts items vertically
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.child(&setup_steps_page_box)
|
.child(&community_page_box)
|
||||||
.propagate_natural_width(true)
|
.propagate_natural_width(true)
|
||||||
.propagate_natural_height(true)
|
.propagate_natural_height(true)
|
||||||
.build();
|
.build();
|
||||||
@ -65,37 +62,43 @@ pub fn setup_steps_page(
|
|||||||
let internet_loop_context = MainContext::default();
|
let internet_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
internet_loop_context.spawn_local(
|
internet_loop_context.spawn_local(
|
||||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
clone!(@strong internet_connected_status, @weak community_page_box => async move {
|
||||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||||
if *internet_connected_status.borrow_mut() == true {
|
if *internet_connected_status.borrow_mut() == true {
|
||||||
setup_steps_page_box.set_sensitive(true);
|
community_page_box.set_sensitive(true);
|
||||||
} else {
|
} else {
|
||||||
setup_steps_page_box.set_sensitive(false);
|
community_page_box.set_sensitive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
let mut json_array: Vec<community_entry> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/community.json";
|
||||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
for setup_steps_entry in setup_steps {
|
if let serde_json::Value::Array(community) = &json_data["community"] {
|
||||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
for community_entry in community {
|
||||||
json_array.push(setup_steps_entry_struct);
|
let community_entry_struct: community_entry =
|
||||||
|
serde_json::from_value(community_entry.clone()).unwrap();
|
||||||
|
json_array.push(community_entry_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for setup_steps_entry in json_array {
|
let entry_buttons_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
||||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
|
||||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
|
||||||
|
|
||||||
let entry_title = setup_steps_entry.title;
|
for community_entry in json_array {
|
||||||
let entry_subtitle = setup_steps_entry.subtitle;
|
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) =
|
||||||
let entry_icon = setup_steps_entry.icon;
|
async_channel::unbounded();
|
||||||
let entry_button = setup_steps_entry.button;
|
let entry_command_status_loop_sender: async_channel::Sender<bool> =
|
||||||
let entry_command = setup_steps_entry.command;
|
entry_command_status_loop_sender.clone();
|
||||||
|
|
||||||
|
let entry_title = community_entry.title;
|
||||||
|
let entry_subtitle = community_entry.subtitle;
|
||||||
|
let entry_icon = community_entry.icon;
|
||||||
|
let entry_button = community_entry.button;
|
||||||
|
let entry_command = community_entry.command;
|
||||||
let entry_row = adw::ActionRow::builder()
|
let entry_row = adw::ActionRow::builder()
|
||||||
.title(t!(&entry_title))
|
.title(t!(&entry_title))
|
||||||
.subtitle(t!(&entry_subtitle))
|
.subtitle(t!(&entry_subtitle))
|
||||||
@ -113,6 +116,7 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.valign(gtk::Align::Center)
|
.valign(gtk::Align::Center)
|
||||||
.build();
|
.build();
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
entry_row.add_prefix(&entry_row_icon);
|
entry_row.add_prefix(&entry_row_icon);
|
||||||
entry_row.add_suffix(&entry_row_button);
|
entry_row.add_suffix(&entry_row_button);
|
||||||
|
|
||||||
@ -137,21 +141,30 @@ pub fn setup_steps_page(
|
|||||||
.heading(t!("cmd_err_dialog_heading"))
|
.heading(t!("cmd_err_dialog_heading"))
|
||||||
.transient_for(window)
|
.transient_for(window)
|
||||||
.build();
|
.build();
|
||||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
cmd_err_dialog.add_response(
|
||||||
|
"cmd_err_dialog_ok",
|
||||||
|
&t!("cmd_err_dialog_ok_label").to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
let entry_command_status_loop_context = MainContext::default();
|
let entry_command_status_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
entry_command_status_loop_context.spawn_local(
|
||||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||||
if state == false {
|
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||||
cmd_err_dialog.present();
|
if state == false {
|
||||||
|
cmd_err_dialog.present();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
}));
|
);
|
||||||
setup_steps_page_listbox.append(&entry_row)
|
community_page_listbox.append(&entry_row)
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
community_page_box.append(&community_page_listbox);
|
||||||
|
|
||||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
community_content_page_stack.add_titled(
|
||||||
}
|
&community_page_scroll,
|
||||||
|
Some("community_page"),
|
||||||
|
&t!("community_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use duct::cmd;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{thread, time};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
|
use duct::cmd;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||||
struct setup_steps_entry {
|
struct contribute_entry {
|
||||||
id: i32,
|
id: i32,
|
||||||
title: String,
|
title: String,
|
||||||
subtitle: String,
|
subtitle: String,
|
||||||
icon: String,
|
icon: String,
|
||||||
button: String,
|
button: String,
|
||||||
command: String
|
command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_steps_page(
|
pub fn contribute_page(
|
||||||
setup_steps_content_page_stack: >k::Stack,
|
contribute_content_page_stack: >k::Stack,
|
||||||
window: &adw::ApplicationWindow,
|
window: &adw::ApplicationWindow,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -38,12 +38,9 @@ pub fn setup_steps_page(
|
|||||||
.expect("The channel needs to be open.");
|
.expect("The channel needs to be open.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let setup_steps_page_box = gtk::Box::builder()
|
let contribute_page_box = gtk::Box::builder().vexpand(true).hexpand(true).build();
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
let contribute_page_listbox = gtk::ListBox::builder()
|
||||||
.margin_top(20)
|
.margin_top(20)
|
||||||
.margin_bottom(20)
|
.margin_bottom(20)
|
||||||
.margin_start(20)
|
.margin_start(20)
|
||||||
@ -51,13 +48,13 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
contribute_page_listbox.add_css_class("boxed-list");
|
||||||
|
|
||||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
let contribute_page_scroll = gtk::ScrolledWindow::builder()
|
||||||
// that puts items vertically
|
// that puts items vertically
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.child(&setup_steps_page_box)
|
.child(&contribute_page_box)
|
||||||
.propagate_natural_width(true)
|
.propagate_natural_width(true)
|
||||||
.propagate_natural_height(true)
|
.propagate_natural_height(true)
|
||||||
.build();
|
.build();
|
||||||
@ -65,37 +62,43 @@ pub fn setup_steps_page(
|
|||||||
let internet_loop_context = MainContext::default();
|
let internet_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
internet_loop_context.spawn_local(
|
internet_loop_context.spawn_local(
|
||||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
clone!(@strong internet_connected_status, @weak contribute_page_box => async move {
|
||||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||||
if *internet_connected_status.borrow_mut() == true {
|
if *internet_connected_status.borrow_mut() == true {
|
||||||
setup_steps_page_box.set_sensitive(true);
|
contribute_page_box.set_sensitive(true);
|
||||||
} else {
|
} else {
|
||||||
setup_steps_page_box.set_sensitive(false);
|
contribute_page_box.set_sensitive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
let mut json_array: Vec<contribute_entry> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/contribute.json";
|
||||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
for setup_steps_entry in setup_steps {
|
if let serde_json::Value::Array(contribute) = &json_data["contribute"] {
|
||||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
for contribute_entry in contribute {
|
||||||
json_array.push(setup_steps_entry_struct);
|
let contribute_entry_struct: contribute_entry =
|
||||||
|
serde_json::from_value(contribute_entry.clone()).unwrap();
|
||||||
|
json_array.push(contribute_entry_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for setup_steps_entry in json_array {
|
let entry_buttons_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
||||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
|
||||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
|
||||||
|
|
||||||
let entry_title = setup_steps_entry.title;
|
for contribute_entry in json_array {
|
||||||
let entry_subtitle = setup_steps_entry.subtitle;
|
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) =
|
||||||
let entry_icon = setup_steps_entry.icon;
|
async_channel::unbounded();
|
||||||
let entry_button = setup_steps_entry.button;
|
let entry_command_status_loop_sender: async_channel::Sender<bool> =
|
||||||
let entry_command = setup_steps_entry.command;
|
entry_command_status_loop_sender.clone();
|
||||||
|
|
||||||
|
let entry_title = contribute_entry.title;
|
||||||
|
let entry_subtitle = contribute_entry.subtitle;
|
||||||
|
let entry_icon = contribute_entry.icon;
|
||||||
|
let entry_button = contribute_entry.button;
|
||||||
|
let entry_command = contribute_entry.command;
|
||||||
let entry_row = adw::ActionRow::builder()
|
let entry_row = adw::ActionRow::builder()
|
||||||
.title(t!(&entry_title))
|
.title(t!(&entry_title))
|
||||||
.subtitle(t!(&entry_subtitle))
|
.subtitle(t!(&entry_subtitle))
|
||||||
@ -113,6 +116,7 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.valign(gtk::Align::Center)
|
.valign(gtk::Align::Center)
|
||||||
.build();
|
.build();
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
entry_row.add_prefix(&entry_row_icon);
|
entry_row.add_prefix(&entry_row_icon);
|
||||||
entry_row.add_suffix(&entry_row_button);
|
entry_row.add_suffix(&entry_row_button);
|
||||||
|
|
||||||
@ -137,21 +141,30 @@ pub fn setup_steps_page(
|
|||||||
.heading(t!("cmd_err_dialog_heading"))
|
.heading(t!("cmd_err_dialog_heading"))
|
||||||
.transient_for(window)
|
.transient_for(window)
|
||||||
.build();
|
.build();
|
||||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
cmd_err_dialog.add_response(
|
||||||
|
"cmd_err_dialog_ok",
|
||||||
|
&t!("cmd_err_dialog_ok_label").to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
let entry_command_status_loop_context = MainContext::default();
|
let entry_command_status_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
entry_command_status_loop_context.spawn_local(
|
||||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||||
if state == false {
|
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||||
cmd_err_dialog.present();
|
if state == false {
|
||||||
|
cmd_err_dialog.present();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
}));
|
);
|
||||||
setup_steps_page_listbox.append(&entry_row)
|
contribute_page_listbox.append(&entry_row)
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
contribute_page_box.append(&contribute_page_listbox);
|
||||||
|
|
||||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
contribute_content_page_stack.add_titled(
|
||||||
}
|
&contribute_page_scroll,
|
||||||
|
Some("contribute_page"),
|
||||||
|
&t!("contribute_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use duct::cmd;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{thread, time};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
|
use duct::cmd;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||||
struct setup_steps_entry {
|
struct look_and_feel_entry {
|
||||||
id: i32,
|
id: i32,
|
||||||
title: String,
|
title: String,
|
||||||
subtitle: String,
|
subtitle: String,
|
||||||
icon: String,
|
icon: String,
|
||||||
button: String,
|
button: String,
|
||||||
command: String
|
command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_steps_page(
|
pub fn look_and_feel_page(
|
||||||
setup_steps_content_page_stack: >k::Stack,
|
look_and_feel_content_page_stack: >k::Stack,
|
||||||
window: &adw::ApplicationWindow,
|
window: &adw::ApplicationWindow,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -38,12 +38,9 @@ pub fn setup_steps_page(
|
|||||||
.expect("The channel needs to be open.");
|
.expect("The channel needs to be open.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let setup_steps_page_box = gtk::Box::builder()
|
let look_and_feel_page_box = gtk::Box::builder().vexpand(true).hexpand(true).build();
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
let look_and_feel_page_listbox = gtk::ListBox::builder()
|
||||||
.margin_top(20)
|
.margin_top(20)
|
||||||
.margin_bottom(20)
|
.margin_bottom(20)
|
||||||
.margin_start(20)
|
.margin_start(20)
|
||||||
@ -51,13 +48,13 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
look_and_feel_page_listbox.add_css_class("boxed-list");
|
||||||
|
|
||||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
let look_and_feel_page_scroll = gtk::ScrolledWindow::builder()
|
||||||
// that puts items vertically
|
// that puts items vertically
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.child(&setup_steps_page_box)
|
.child(&look_and_feel_page_box)
|
||||||
.propagate_natural_width(true)
|
.propagate_natural_width(true)
|
||||||
.propagate_natural_height(true)
|
.propagate_natural_height(true)
|
||||||
.build();
|
.build();
|
||||||
@ -65,37 +62,43 @@ pub fn setup_steps_page(
|
|||||||
let internet_loop_context = MainContext::default();
|
let internet_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
internet_loop_context.spawn_local(
|
internet_loop_context.spawn_local(
|
||||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
clone!(@strong internet_connected_status, @weak look_and_feel_page_box => async move {
|
||||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||||
if *internet_connected_status.borrow_mut() == true {
|
if *internet_connected_status.borrow_mut() == true {
|
||||||
setup_steps_page_box.set_sensitive(true);
|
look_and_feel_page_box.set_sensitive(true);
|
||||||
} else {
|
} else {
|
||||||
setup_steps_page_box.set_sensitive(false);
|
look_and_feel_page_box.set_sensitive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
let mut json_array: Vec<look_and_feel_entry> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/look_and_feel.json";
|
||||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
for setup_steps_entry in setup_steps {
|
if let serde_json::Value::Array(look_and_feel) = &json_data["look_and_feel"] {
|
||||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
for look_and_feel_entry in look_and_feel {
|
||||||
json_array.push(setup_steps_entry_struct);
|
let look_and_feel_entry_struct: look_and_feel_entry =
|
||||||
|
serde_json::from_value(look_and_feel_entry.clone()).unwrap();
|
||||||
|
json_array.push(look_and_feel_entry_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for setup_steps_entry in json_array {
|
let entry_buttons_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
||||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
|
||||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
|
||||||
|
|
||||||
let entry_title = setup_steps_entry.title;
|
for look_and_feel_entry in json_array {
|
||||||
let entry_subtitle = setup_steps_entry.subtitle;
|
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) =
|
||||||
let entry_icon = setup_steps_entry.icon;
|
async_channel::unbounded();
|
||||||
let entry_button = setup_steps_entry.button;
|
let entry_command_status_loop_sender: async_channel::Sender<bool> =
|
||||||
let entry_command = setup_steps_entry.command;
|
entry_command_status_loop_sender.clone();
|
||||||
|
|
||||||
|
let entry_title = look_and_feel_entry.title;
|
||||||
|
let entry_subtitle = look_and_feel_entry.subtitle;
|
||||||
|
let entry_icon = look_and_feel_entry.icon;
|
||||||
|
let entry_button = look_and_feel_entry.button;
|
||||||
|
let entry_command = look_and_feel_entry.command;
|
||||||
let entry_row = adw::ActionRow::builder()
|
let entry_row = adw::ActionRow::builder()
|
||||||
.title(t!(&entry_title))
|
.title(t!(&entry_title))
|
||||||
.subtitle(t!(&entry_subtitle))
|
.subtitle(t!(&entry_subtitle))
|
||||||
@ -113,6 +116,8 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.valign(gtk::Align::Center)
|
.valign(gtk::Align::Center)
|
||||||
.build();
|
.build();
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
entry_row.add_prefix(&entry_row_icon);
|
entry_row.add_prefix(&entry_row_icon);
|
||||||
entry_row.add_suffix(&entry_row_button);
|
entry_row.add_suffix(&entry_row_button);
|
||||||
|
|
||||||
@ -137,21 +142,30 @@ pub fn setup_steps_page(
|
|||||||
.heading(t!("cmd_err_dialog_heading"))
|
.heading(t!("cmd_err_dialog_heading"))
|
||||||
.transient_for(window)
|
.transient_for(window)
|
||||||
.build();
|
.build();
|
||||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
cmd_err_dialog.add_response(
|
||||||
|
"cmd_err_dialog_ok",
|
||||||
|
&t!("cmd_err_dialog_ok_label").to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
let entry_command_status_loop_context = MainContext::default();
|
let entry_command_status_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
entry_command_status_loop_context.spawn_local(
|
||||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||||
if state == false {
|
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||||
cmd_err_dialog.present();
|
if state == false {
|
||||||
|
cmd_err_dialog.present();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
}));
|
);
|
||||||
setup_steps_page_listbox.append(&entry_row)
|
look_and_feel_page_listbox.append(&entry_row)
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
look_and_feel_page_box.append(&look_and_feel_page_listbox);
|
||||||
|
|
||||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
look_and_feel_content_page_stack.add_titled(
|
||||||
}
|
&look_and_feel_page_scroll,
|
||||||
|
Some("look_and_feel_page"),
|
||||||
|
&t!("look_and_feel_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -8,13 +8,21 @@ use std::process::Command;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// stack crates
|
// stack crates
|
||||||
mod welcome_page;
|
mod community_page;
|
||||||
mod setup_steps_page;
|
mod contribute_page;
|
||||||
|
mod look_and_feel_page;
|
||||||
mod recommended_addons_page;
|
mod recommended_addons_page;
|
||||||
|
mod setup_steps_page;
|
||||||
|
mod troubleshoot_page;
|
||||||
|
mod welcome_page;
|
||||||
|
|
||||||
use welcome_page::welcome_page;
|
use community_page::community_page;
|
||||||
use setup_steps_page::setup_steps_page;
|
use contribute_page::contribute_page;
|
||||||
|
use look_and_feel_page::look_and_feel_page;
|
||||||
use recommended_addons_page::recommended_addons_page;
|
use recommended_addons_page::recommended_addons_page;
|
||||||
|
use setup_steps_page::setup_steps_page;
|
||||||
|
use troubleshoot_page::troubleshoot_page;
|
||||||
|
use welcome_page::welcome_page;
|
||||||
|
|
||||||
use crate::config::{APP_GITHUB, APP_ICON, APP_ID, VERSION};
|
use crate::config::{APP_GITHUB, APP_ICON, APP_ID, VERSION};
|
||||||
|
|
||||||
@ -52,9 +60,7 @@ pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let window_banner = adw::Banner::builder()
|
let window_banner = adw::Banner::builder().revealed(false).build();
|
||||||
.revealed(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let window_title_bar = gtk::HeaderBar::builder().show_title_buttons(true).build();
|
let window_title_bar = gtk::HeaderBar::builder().show_title_buttons(true).build();
|
||||||
|
|
||||||
@ -65,7 +71,8 @@ pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::
|
|||||||
let mut json_array: Vec<GString> = Vec::new();
|
let mut json_array: Vec<GString> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/credits.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/credits.json";
|
||||||
let json_data = std::fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = std::fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
if let serde_json::Value::Array(developers) = &json_data["developers"] {
|
if let serde_json::Value::Array(developers) = &json_data["developers"] {
|
||||||
for developer in developers {
|
for developer in developers {
|
||||||
json_array.push(developer["dev"].as_str().to_owned().unwrap().into())
|
json_array.push(developer["dev"].as_str().to_owned().unwrap().into())
|
||||||
@ -130,10 +137,27 @@ pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::
|
|||||||
.bidirectional()
|
.bidirectional()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let welcome_content_page_split_view_breakpoint = adw::Breakpoint::new(BreakpointCondition::new_length(BreakpointConditionLengthType::MaxWidth, 600.0, LengthUnit::Px));
|
let welcome_content_page_split_view_breakpoint =
|
||||||
welcome_content_page_split_view_breakpoint.add_setter(&welcome_content_page_split_view, "collapsed", &true.to_value());
|
adw::Breakpoint::new(BreakpointCondition::new_length(
|
||||||
welcome_content_page_split_view_breakpoint.add_setter(&startup_switch, "visible", &false.to_value());
|
BreakpointConditionLengthType::MaxWidth,
|
||||||
welcome_content_page_split_view_breakpoint.add_setter(&sidebar_toggle_button, "visible", &true.to_value());
|
600.0,
|
||||||
|
LengthUnit::Px,
|
||||||
|
));
|
||||||
|
welcome_content_page_split_view_breakpoint.add_setter(
|
||||||
|
&welcome_content_page_split_view,
|
||||||
|
"collapsed",
|
||||||
|
&true.to_value(),
|
||||||
|
);
|
||||||
|
welcome_content_page_split_view_breakpoint.add_setter(
|
||||||
|
&startup_switch,
|
||||||
|
"visible",
|
||||||
|
&false.to_value(),
|
||||||
|
);
|
||||||
|
welcome_content_page_split_view_breakpoint.add_setter(
|
||||||
|
&sidebar_toggle_button,
|
||||||
|
"visible",
|
||||||
|
&true.to_value(),
|
||||||
|
);
|
||||||
|
|
||||||
window.add_breakpoint(welcome_content_page_split_view_breakpoint);
|
window.add_breakpoint(welcome_content_page_split_view_breakpoint);
|
||||||
|
|
||||||
@ -165,7 +189,15 @@ pub fn welcome_content_page(window: &adw::ApplicationWindow, content_box: >k::
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
welcome_page(&welcome_content_page_stack, &window_banner, &internet_connected);
|
welcome_page(
|
||||||
|
&welcome_content_page_stack,
|
||||||
|
&window_banner,
|
||||||
|
&internet_connected,
|
||||||
|
);
|
||||||
setup_steps_page(&welcome_content_page_stack, &window, &internet_connected);
|
setup_steps_page(&welcome_content_page_stack, &window, &internet_connected);
|
||||||
recommended_addons_page(&welcome_content_page_stack, &window, &internet_connected);
|
recommended_addons_page(&welcome_content_page_stack, &window, &internet_connected);
|
||||||
|
look_and_feel_page(&welcome_content_page_stack, &window, &internet_connected);
|
||||||
|
troubleshoot_page(&welcome_content_page_stack, &window, &internet_connected);
|
||||||
|
community_page(&welcome_content_page_stack, &window, &internet_connected);
|
||||||
|
contribute_page(&welcome_content_page_stack, &window, &internet_connected);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use std::io::BufReader;
|
|
||||||
use duct::cmd;
|
|
||||||
use std::io::BufRead;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{thread, time};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
|
use duct::cmd;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::fs;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||||
@ -22,7 +21,7 @@ struct recommended_addons_entry {
|
|||||||
subtitle: String,
|
subtitle: String,
|
||||||
icon: String,
|
icon: String,
|
||||||
checkpkg: String,
|
checkpkg: String,
|
||||||
packages: String
|
packages: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ADDON_COMMAND_PROG1: &str = r###"
|
const ADDON_COMMAND_PROG1: &str = r###"
|
||||||
@ -44,10 +43,21 @@ fn run_addon_command(
|
|||||||
entry_packages: &str,
|
entry_packages: &str,
|
||||||
) -> Result<(), std::boxed::Box<dyn Error + Send + Sync>> {
|
) -> Result<(), std::boxed::Box<dyn Error + Send + Sync>> {
|
||||||
let (pipe_reader, pipe_writer) = os_pipe::pipe()?;
|
let (pipe_reader, pipe_writer) = os_pipe::pipe()?;
|
||||||
let child = cmd!("pkexec", "bash", "-c", ADDON_COMMAND_PROG1.to_owned() + "apt " + operation + " " + &entry_packages + r###" -y -o Dpkg::Options::="--force-confnew""### + ADDON_COMMAND_PROG2)
|
let child = cmd!(
|
||||||
.stderr_to_stdout()
|
"pkexec",
|
||||||
.stdout_file(pipe_writer)
|
"bash",
|
||||||
.start()?;
|
"-c",
|
||||||
|
ADDON_COMMAND_PROG1.to_owned()
|
||||||
|
+ "apt "
|
||||||
|
+ operation
|
||||||
|
+ " "
|
||||||
|
+ &entry_packages
|
||||||
|
+ r###" -y -o Dpkg::Options::="--force-confnew""###
|
||||||
|
+ ADDON_COMMAND_PROG2
|
||||||
|
)
|
||||||
|
.stderr_to_stdout()
|
||||||
|
.stdout_file(pipe_writer)
|
||||||
|
.start()?;
|
||||||
for line in BufReader::new(pipe_reader).lines() {
|
for line in BufReader::new(pipe_reader).lines() {
|
||||||
log_loop_sender
|
log_loop_sender
|
||||||
.send_blocking(line?)
|
.send_blocking(line?)
|
||||||
@ -61,7 +71,7 @@ fn run_addon_command(
|
|||||||
pub fn recommended_addons_page(
|
pub fn recommended_addons_page(
|
||||||
recommended_addons_content_page_stack: >k::Stack,
|
recommended_addons_content_page_stack: >k::Stack,
|
||||||
window: &adw::ApplicationWindow,
|
window: &adw::ApplicationWindow,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -75,10 +85,7 @@ pub fn recommended_addons_page(
|
|||||||
.expect("The channel needs to be open.");
|
.expect("The channel needs to be open.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let recommended_addons_page_box = gtk::Box::builder()
|
let recommended_addons_page_box = gtk::Box::builder().vexpand(true).hexpand(true).build();
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let recommended_addons_page_listbox = gtk::ListBox::builder()
|
let recommended_addons_page_listbox = gtk::ListBox::builder()
|
||||||
.margin_top(20)
|
.margin_top(20)
|
||||||
@ -113,27 +120,32 @@ pub fn recommended_addons_page(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let entry_buttons_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
||||||
|
|
||||||
let mut json_array: Vec<recommended_addons_entry> = Vec::new();
|
let mut json_array: Vec<recommended_addons_entry> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/recommended_addons.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/recommended_addons.json";
|
||||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
if let serde_json::Value::Array(recommended_addons) = &json_data["recommended_addons"] {
|
if let serde_json::Value::Array(recommended_addons) = &json_data["recommended_addons"] {
|
||||||
for recommended_addons_entry in recommended_addons {
|
for recommended_addons_entry in recommended_addons {
|
||||||
let recommended_addons_entry_struct: recommended_addons_entry = serde_json::from_value(recommended_addons_entry.clone()).unwrap();
|
let recommended_addons_entry_struct: recommended_addons_entry =
|
||||||
|
serde_json::from_value(recommended_addons_entry.clone()).unwrap();
|
||||||
json_array.push(recommended_addons_entry_struct);
|
json_array.push(recommended_addons_entry_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for recommended_addons_entry in json_array {
|
for recommended_addons_entry in json_array {
|
||||||
let (checkpkg_status_loop_sender, checkpkg_status_loop_receiver) = async_channel::unbounded();
|
let (checkpkg_status_loop_sender, checkpkg_status_loop_receiver) =
|
||||||
let checkpkg_status_loop_sender: async_channel::Sender<bool> = checkpkg_status_loop_sender.clone();
|
async_channel::unbounded();
|
||||||
|
let checkpkg_status_loop_sender: async_channel::Sender<bool> =
|
||||||
|
checkpkg_status_loop_sender.clone();
|
||||||
|
|
||||||
let (log_loop_sender, log_loop_receiver) = async_channel::unbounded();
|
let (log_loop_sender, log_loop_receiver) = async_channel::unbounded();
|
||||||
let log_loop_sender: async_channel::Sender<String> = log_loop_sender.clone();
|
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, log_status_loop_receiver) = async_channel::unbounded();
|
||||||
let log_status_loop_sender: async_channel::Sender<bool> =
|
let log_status_loop_sender: async_channel::Sender<bool> = log_status_loop_sender.clone();
|
||||||
log_status_loop_sender.clone();
|
|
||||||
|
|
||||||
let entry_title = recommended_addons_entry.title;
|
let entry_title = recommended_addons_entry.title;
|
||||||
let entry_subtitle = recommended_addons_entry.subtitle;
|
let entry_subtitle = recommended_addons_entry.subtitle;
|
||||||
@ -141,18 +153,20 @@ pub fn recommended_addons_page(
|
|||||||
let entry_checkpkg = recommended_addons_entry.checkpkg;
|
let entry_checkpkg = recommended_addons_entry.checkpkg;
|
||||||
let entry_packages = recommended_addons_entry.packages;
|
let entry_packages = recommended_addons_entry.packages;
|
||||||
|
|
||||||
gio::spawn_blocking(clone!(@strong checkpkg_status_loop_sender, @strong entry_checkpkg => move || {
|
gio::spawn_blocking(
|
||||||
let checkpkg_command = Command::new("dpkg")
|
clone!(@strong checkpkg_status_loop_sender, @strong entry_checkpkg => move || {
|
||||||
.arg("-s")
|
let checkpkg_command = Command::new("dpkg")
|
||||||
.arg(entry_checkpkg)
|
.arg("-s")
|
||||||
.output()
|
.arg(entry_checkpkg)
|
||||||
.expect("failed to execute process");
|
.output()
|
||||||
if checkpkg_command.status.success() {
|
.expect("failed to execute process");
|
||||||
checkpkg_status_loop_sender.send_blocking(true).expect("The channel needs to be open.");
|
if checkpkg_command.status.success() {
|
||||||
} else {
|
checkpkg_status_loop_sender.send_blocking(true).expect("The channel needs to be open.");
|
||||||
checkpkg_status_loop_sender.send_blocking(false).expect("The channel needs to be open.");
|
} else {
|
||||||
}
|
checkpkg_status_loop_sender.send_blocking(false).expect("The channel needs to be open.");
|
||||||
}));
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
let entry_row = adw::ActionRow::builder()
|
let entry_row = adw::ActionRow::builder()
|
||||||
.title(t!(&entry_title))
|
.title(t!(&entry_title))
|
||||||
@ -170,6 +184,7 @@ pub fn recommended_addons_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.valign(gtk::Align::Center)
|
.valign(gtk::Align::Center)
|
||||||
.build();
|
.build();
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
entry_row.add_prefix(&entry_row_icon);
|
entry_row.add_prefix(&entry_row_icon);
|
||||||
entry_row.add_suffix(&entry_row_button);
|
entry_row.add_suffix(&entry_row_button);
|
||||||
|
|
||||||
@ -205,21 +220,23 @@ pub fn recommended_addons_page(
|
|||||||
|
|
||||||
let checkpkg_status_loop_context = MainContext::default();
|
let checkpkg_status_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
checkpkg_status_loop_context.spawn_local(clone!(@weak entry_row_button, @strong checkpkg_status_loop_receiver => async move {
|
checkpkg_status_loop_context.spawn_local(
|
||||||
while let Ok(state) = checkpkg_status_loop_receiver.recv().await {
|
clone!(@weak entry_row_button, @strong checkpkg_status_loop_receiver => async move {
|
||||||
if state == false {
|
while let Ok(state) = checkpkg_status_loop_receiver.recv().await {
|
||||||
entry_row_button.remove_css_class("destructive-action");
|
if state == false {
|
||||||
entry_row_button.set_label(&t!("entry_row_button_install").to_string());
|
entry_row_button.remove_css_class("destructive-action");
|
||||||
entry_row_button.add_css_class("suggested-action");
|
entry_row_button.set_label(&t!("entry_row_button_install").to_string());
|
||||||
entry_row_button.set_widget_name("false")
|
entry_row_button.add_css_class("suggested-action");
|
||||||
} else {
|
entry_row_button.set_widget_name("false")
|
||||||
entry_row_button.remove_css_class("suggested-action");
|
} else {
|
||||||
entry_row_button.set_label(&t!("entry_row_button_remove").to_string());
|
entry_row_button.remove_css_class("suggested-action");
|
||||||
entry_row_button.add_css_class("destructive-action");
|
entry_row_button.set_label(&t!("entry_row_button_remove").to_string());
|
||||||
entry_row_button.set_widget_name("true")
|
entry_row_button.add_css_class("destructive-action");
|
||||||
|
entry_row_button.set_widget_name("true")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
}));
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
let log_loop_context = MainContext::default();
|
let log_loop_context = MainContext::default();
|
||||||
@ -291,5 +308,9 @@ pub fn recommended_addons_page(
|
|||||||
|
|
||||||
recommended_addons_page_box.append(&recommended_addons_page_listbox);
|
recommended_addons_page_box.append(&recommended_addons_page_listbox);
|
||||||
|
|
||||||
recommended_addons_content_page_stack.add_titled(&recommended_addons_page_scroll, Some("recommended_addons_page"), &t!("recommended_addons_page_title").to_string());
|
recommended_addons_content_page_stack.add_titled(
|
||||||
}
|
&recommended_addons_page_scroll,
|
||||||
|
Some("recommended_addons_page"),
|
||||||
|
&t!("recommended_addons_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use duct::cmd;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{thread, time};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
|
use duct::cmd;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||||
@ -18,13 +18,13 @@ struct setup_steps_entry {
|
|||||||
subtitle: String,
|
subtitle: String,
|
||||||
icon: String,
|
icon: String,
|
||||||
button: String,
|
button: String,
|
||||||
command: String
|
command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_steps_page(
|
pub fn setup_steps_page(
|
||||||
setup_steps_content_page_stack: >k::Stack,
|
setup_steps_content_page_stack: >k::Stack,
|
||||||
window: &adw::ApplicationWindow,
|
window: &adw::ApplicationWindow,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -38,10 +38,7 @@ pub fn setup_steps_page(
|
|||||||
.expect("The channel needs to be open.");
|
.expect("The channel needs to be open.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let setup_steps_page_box = gtk::Box::builder()
|
let setup_steps_page_box = gtk::Box::builder().vexpand(true).hexpand(true).build();
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
let setup_steps_page_listbox = gtk::ListBox::builder()
|
||||||
.margin_top(20)
|
.margin_top(20)
|
||||||
@ -79,17 +76,23 @@ pub fn setup_steps_page(
|
|||||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
||||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
||||||
for setup_steps_entry in setup_steps {
|
for setup_steps_entry in setup_steps {
|
||||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
let setup_steps_entry_struct: setup_steps_entry =
|
||||||
|
serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
||||||
json_array.push(setup_steps_entry_struct);
|
json_array.push(setup_steps_entry_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let entry_buttons_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
||||||
|
|
||||||
for setup_steps_entry in json_array {
|
for setup_steps_entry in json_array {
|
||||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) =
|
||||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
async_channel::unbounded();
|
||||||
|
let entry_command_status_loop_sender: async_channel::Sender<bool> =
|
||||||
|
entry_command_status_loop_sender.clone();
|
||||||
|
|
||||||
let entry_title = setup_steps_entry.title;
|
let entry_title = setup_steps_entry.title;
|
||||||
let entry_subtitle = setup_steps_entry.subtitle;
|
let entry_subtitle = setup_steps_entry.subtitle;
|
||||||
@ -113,6 +116,7 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.valign(gtk::Align::Center)
|
.valign(gtk::Align::Center)
|
||||||
.build();
|
.build();
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
entry_row.add_prefix(&entry_row_icon);
|
entry_row.add_prefix(&entry_row_icon);
|
||||||
entry_row.add_suffix(&entry_row_button);
|
entry_row.add_suffix(&entry_row_button);
|
||||||
|
|
||||||
@ -137,21 +141,30 @@ pub fn setup_steps_page(
|
|||||||
.heading(t!("cmd_err_dialog_heading"))
|
.heading(t!("cmd_err_dialog_heading"))
|
||||||
.transient_for(window)
|
.transient_for(window)
|
||||||
.build();
|
.build();
|
||||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
cmd_err_dialog.add_response(
|
||||||
|
"cmd_err_dialog_ok",
|
||||||
|
&t!("cmd_err_dialog_ok_label").to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
let entry_command_status_loop_context = MainContext::default();
|
let entry_command_status_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
entry_command_status_loop_context.spawn_local(
|
||||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||||
if state == false {
|
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||||
cmd_err_dialog.present();
|
if state == false {
|
||||||
|
cmd_err_dialog.present();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
}));
|
);
|
||||||
setup_steps_page_listbox.append(&entry_row)
|
setup_steps_page_listbox.append(&entry_row)
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
setup_steps_page_box.append(&setup_steps_page_listbox);
|
||||||
|
|
||||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
setup_steps_content_page_stack.add_titled(
|
||||||
}
|
&setup_steps_page_scroll,
|
||||||
|
Some("setup_steps_page"),
|
||||||
|
&t!("setup_steps_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use duct::cmd;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::{thread, time};
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
|
use duct::cmd;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
#[derive(PartialEq, Debug, Eq, Hash, Clone, Ord, PartialOrd, Deserialize)]
|
||||||
struct setup_steps_entry {
|
struct troubleshoot_entry {
|
||||||
id: i32,
|
id: i32,
|
||||||
title: String,
|
title: String,
|
||||||
subtitle: String,
|
subtitle: String,
|
||||||
icon: String,
|
icon: String,
|
||||||
button: String,
|
button: String,
|
||||||
command: String
|
command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup_steps_page(
|
pub fn troubleshoot_page(
|
||||||
setup_steps_content_page_stack: >k::Stack,
|
troubleshoot_content_page_stack: >k::Stack,
|
||||||
window: &adw::ApplicationWindow,
|
window: &adw::ApplicationWindow,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -38,12 +38,9 @@ pub fn setup_steps_page(
|
|||||||
.expect("The channel needs to be open.");
|
.expect("The channel needs to be open.");
|
||||||
});
|
});
|
||||||
|
|
||||||
let setup_steps_page_box = gtk::Box::builder()
|
let troubleshoot_page_box = gtk::Box::builder().vexpand(true).hexpand(true).build();
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let setup_steps_page_listbox = gtk::ListBox::builder()
|
let troubleshoot_page_listbox = gtk::ListBox::builder()
|
||||||
.margin_top(20)
|
.margin_top(20)
|
||||||
.margin_bottom(20)
|
.margin_bottom(20)
|
||||||
.margin_start(20)
|
.margin_start(20)
|
||||||
@ -51,13 +48,13 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
setup_steps_page_listbox.add_css_class("boxed-list");
|
troubleshoot_page_listbox.add_css_class("boxed-list");
|
||||||
|
|
||||||
let setup_steps_page_scroll = gtk::ScrolledWindow::builder()
|
let troubleshoot_page_scroll = gtk::ScrolledWindow::builder()
|
||||||
// that puts items vertically
|
// that puts items vertically
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.child(&setup_steps_page_box)
|
.child(&troubleshoot_page_box)
|
||||||
.propagate_natural_width(true)
|
.propagate_natural_width(true)
|
||||||
.propagate_natural_height(true)
|
.propagate_natural_height(true)
|
||||||
.build();
|
.build();
|
||||||
@ -65,37 +62,43 @@ pub fn setup_steps_page(
|
|||||||
let internet_loop_context = MainContext::default();
|
let internet_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
internet_loop_context.spawn_local(
|
internet_loop_context.spawn_local(
|
||||||
clone!(@strong internet_connected_status, @weak setup_steps_page_box => async move {
|
clone!(@strong internet_connected_status, @weak troubleshoot_page_box => async move {
|
||||||
while let Ok(_state) = internet_loop_receiver.recv().await {
|
while let Ok(_state) = internet_loop_receiver.recv().await {
|
||||||
if *internet_connected_status.borrow_mut() == true {
|
if *internet_connected_status.borrow_mut() == true {
|
||||||
setup_steps_page_box.set_sensitive(true);
|
troubleshoot_page_box.set_sensitive(true);
|
||||||
} else {
|
} else {
|
||||||
setup_steps_page_box.set_sensitive(false);
|
troubleshoot_page_box.set_sensitive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut json_array: Vec<setup_steps_entry> = Vec::new();
|
let mut json_array: Vec<troubleshoot_entry> = Vec::new();
|
||||||
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/setup_steps.json";
|
let json_path = "/home/ward/builds/pkg-pika-welcome/data/config/troubleshoot.json";
|
||||||
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
let json_data = fs::read_to_string(json_path).expect("Unable to read json");
|
||||||
let json_data: serde_json::Value = serde_json::from_str(&json_data).expect("JSON format invalid");
|
let json_data: serde_json::Value =
|
||||||
if let serde_json::Value::Array(setup_steps) = &json_data["setup_steps"] {
|
serde_json::from_str(&json_data).expect("JSON format invalid");
|
||||||
for setup_steps_entry in setup_steps {
|
if let serde_json::Value::Array(troubleshoot) = &json_data["troubleshoot"] {
|
||||||
let setup_steps_entry_struct: setup_steps_entry = serde_json::from_value(setup_steps_entry.clone()).unwrap();
|
for troubleshoot_entry in troubleshoot {
|
||||||
json_array.push(setup_steps_entry_struct);
|
let troubleshoot_entry_struct: troubleshoot_entry =
|
||||||
|
serde_json::from_value(troubleshoot_entry.clone()).unwrap();
|
||||||
|
json_array.push(troubleshoot_entry_struct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for setup_steps_entry in json_array {
|
let entry_buttons_size_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Both);
|
||||||
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) = async_channel::unbounded();
|
|
||||||
let entry_command_status_loop_sender: async_channel::Sender<bool> = entry_command_status_loop_sender.clone();
|
|
||||||
|
|
||||||
let entry_title = setup_steps_entry.title;
|
for troubleshoot_entry in json_array {
|
||||||
let entry_subtitle = setup_steps_entry.subtitle;
|
let (entry_command_status_loop_sender, entry_command_status_loop_receiver) =
|
||||||
let entry_icon = setup_steps_entry.icon;
|
async_channel::unbounded();
|
||||||
let entry_button = setup_steps_entry.button;
|
let entry_command_status_loop_sender: async_channel::Sender<bool> =
|
||||||
let entry_command = setup_steps_entry.command;
|
entry_command_status_loop_sender.clone();
|
||||||
|
|
||||||
|
let entry_title = troubleshoot_entry.title;
|
||||||
|
let entry_subtitle = troubleshoot_entry.subtitle;
|
||||||
|
let entry_icon = troubleshoot_entry.icon;
|
||||||
|
let entry_button = troubleshoot_entry.button;
|
||||||
|
let entry_command = troubleshoot_entry.command;
|
||||||
let entry_row = adw::ActionRow::builder()
|
let entry_row = adw::ActionRow::builder()
|
||||||
.title(t!(&entry_title))
|
.title(t!(&entry_title))
|
||||||
.subtitle(t!(&entry_subtitle))
|
.subtitle(t!(&entry_subtitle))
|
||||||
@ -113,6 +116,7 @@ pub fn setup_steps_page(
|
|||||||
.vexpand(true)
|
.vexpand(true)
|
||||||
.valign(gtk::Align::Center)
|
.valign(gtk::Align::Center)
|
||||||
.build();
|
.build();
|
||||||
|
entry_buttons_size_group.add_widget(&entry_row_button);
|
||||||
entry_row.add_prefix(&entry_row_icon);
|
entry_row.add_prefix(&entry_row_icon);
|
||||||
entry_row.add_suffix(&entry_row_button);
|
entry_row.add_suffix(&entry_row_button);
|
||||||
|
|
||||||
@ -137,21 +141,30 @@ pub fn setup_steps_page(
|
|||||||
.heading(t!("cmd_err_dialog_heading"))
|
.heading(t!("cmd_err_dialog_heading"))
|
||||||
.transient_for(window)
|
.transient_for(window)
|
||||||
.build();
|
.build();
|
||||||
cmd_err_dialog.add_response("cmd_err_dialog_ok", &t!("cmd_err_dialog_ok_label").to_string());
|
cmd_err_dialog.add_response(
|
||||||
|
"cmd_err_dialog_ok",
|
||||||
|
&t!("cmd_err_dialog_ok_label").to_string(),
|
||||||
|
);
|
||||||
|
|
||||||
let entry_command_status_loop_context = MainContext::default();
|
let entry_command_status_loop_context = MainContext::default();
|
||||||
// The main loop executes the asynchronous block
|
// The main loop executes the asynchronous block
|
||||||
entry_command_status_loop_context.spawn_local(clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
entry_command_status_loop_context.spawn_local(
|
||||||
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
clone!(@weak cmd_err_dialog, @strong entry_command_status_loop_receiver => async move {
|
||||||
if state == false {
|
while let Ok(state) = entry_command_status_loop_receiver.recv().await {
|
||||||
cmd_err_dialog.present();
|
if state == false {
|
||||||
|
cmd_err_dialog.present();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
}));
|
);
|
||||||
setup_steps_page_listbox.append(&entry_row)
|
troubleshoot_page_listbox.append(&entry_row)
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_steps_page_box.append(&setup_steps_page_listbox);
|
troubleshoot_page_box.append(&troubleshoot_page_listbox);
|
||||||
|
|
||||||
setup_steps_content_page_stack.add_titled(&setup_steps_page_scroll, Some("setup_steps_page"), &t!("setup_steps_page_title").to_string());
|
troubleshoot_content_page_stack.add_titled(
|
||||||
}
|
&troubleshoot_page_scroll,
|
||||||
|
Some("troubleshoot_page"),
|
||||||
|
&t!("troubleshoot_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
// GTK crates
|
// GTK crates
|
||||||
use std::{thread, time};
|
use crate::config::DISTRO_ICON;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::*;
|
use adw::*;
|
||||||
use glib::*;
|
use glib::*;
|
||||||
use crate::config::DISTRO_ICON;
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
pub fn welcome_page(
|
pub fn welcome_page(
|
||||||
welcome_content_page_stack: >k::Stack,
|
welcome_content_page_stack: >k::Stack,
|
||||||
window_banner: &adw::Banner,
|
window_banner: &adw::Banner,
|
||||||
internet_connected: &Rc<RefCell<bool>>
|
internet_connected: &Rc<RefCell<bool>>,
|
||||||
) {
|
) {
|
||||||
let internet_connected_status = internet_connected.clone();
|
let internet_connected_status = internet_connected.clone();
|
||||||
|
|
||||||
@ -56,5 +56,9 @@ pub fn welcome_page(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
welcome_content_page_stack.add_titled(&welcome_page_scroll, Some("welcome_page"), &t!("welcome_page_title").to_string());
|
welcome_content_page_stack.add_titled(
|
||||||
}
|
&welcome_page_scroll,
|
||||||
|
Some("welcome_page"),
|
||||||
|
&t!("welcome_page_title").to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user