expander rows

This commit is contained in:
Ward from fusion-voyager-3 2024-07-01 00:23:36 +03:00
parent fa0e0359cd
commit 669f169a79
11 changed files with 225 additions and 91 deletions

View File

@ -8,10 +8,7 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="df2ca9e1-e07d-43f4-bc68-0a6113fc1fa2" name="Changes" comment=""> <list default="true" id="df2ca9e1-e07d-43f4-bc68-0a6113fc1fa2" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/apt_package_row/imp.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_package_row/imp.rs" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/apt_package_row/imp.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_package_row/imp.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/apt_package_row/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_package_row/mod.rs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/apt_update_page/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_update_page/mod.rs" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -103,6 +100,7 @@
<workItem from="1719504952240" duration="1363000" /> <workItem from="1719504952240" duration="1363000" />
<workItem from="1719510804090" duration="7000" /> <workItem from="1719510804090" duration="7000" />
<workItem from="1719609702948" duration="9756000" /> <workItem from="1719609702948" duration="9756000" />
<workItem from="1719635307639" duration="18000" />
</task> </task>
<servers /> <servers />
</component> </component>

42
Cargo.lock generated
View File

@ -61,6 +61,17 @@ dependencies = [
"syn 2.0.68", "syn 2.0.68",
] ]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.3.0" version = "1.3.0"
@ -509,6 +520,15 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.29.0" version = "0.29.0"
@ -767,6 +787,15 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.3.9" version = "0.3.9"
@ -1033,7 +1062,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi 0.3.9",
"libc", "libc",
] ]
@ -1147,6 +1176,7 @@ dependencies = [
"futures 0.3.30", "futures 0.3.30",
"gtk4", "gtk4",
"libadwaita", "libadwaita",
"pretty-bytes",
"rust-apt", "rust-apt",
"rust-i18n", "rust-i18n",
"serde", "serde",
@ -1173,6 +1203,16 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "pretty-bytes"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "009d6edd2c1dbf2e1c0cd48a2f7766e03498d49ada7109a01c6911815c685316"
dependencies = [
"atty",
"getopts",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.3.1" version = "1.3.1"

View File

@ -24,3 +24,4 @@ serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.118" serde_json = "1.0.118"
async-trait = "0.1.80" async-trait = "0.1.80"
futures = "0.3.30" futures = "0.3.30"
pretty-bytes = "0.2.2"

View File

@ -6,6 +6,7 @@ use glib::{subclass::Signal, Properties, clone};
use gtk::{*}; use gtk::{*};
use gtk::Orientation::Horizontal; use gtk::Orientation::Horizontal;
use crate::apt_update_page::AptPackageSocket; use crate::apt_update_page::AptPackageSocket;
use pretty_bytes::converter::convert;
use std::env; use std::env;
// ANCHOR: custom_button // ANCHOR: custom_button
@ -85,7 +86,7 @@ impl ObjectImpl for AptPackageRow {
// //
create_prefix_content(&prefix_box, &package_name, &package_arch, &package_installed_version, &package_candidate_version); create_prefix_content(&prefix_box, &package_name, &package_arch, &package_installed_version, &package_candidate_version);
// //
create_expandable_content(&expandable_box); create_expandable_content(obj, &expandable_box, package_description, package_source_uri, package_maintainer, package_size, package_installed_size);
})); }));
obj.add_prefix(&prefix_box); obj.add_prefix(&prefix_box);
@ -246,7 +247,7 @@ fn create_prefix_content(prefix_box: &gtk::Box, package_name: &str ,package_arch
prefix_box.append(&version_box); prefix_box.append(&version_box);
} }
fn create_expandable_content(expandable_box: &gtk::Box) { fn create_expandable_content(apt_package_row: &impl IsA<ExpanderRow>, expandable_box: &gtk::Box, package_description: String, package_source_uri: String, package_maintainer: String, package_size: u64, package_installed_size: u64) {
let expandable_page_selection_box = gtk::Box::builder() let expandable_page_selection_box = gtk::Box::builder()
.orientation(Orientation::Horizontal) .orientation(Orientation::Horizontal)
.hexpand(false) .hexpand(false)
@ -261,13 +262,17 @@ fn create_expandable_content(expandable_box: &gtk::Box) {
expandable_page_selection_box.add_css_class("linked"); expandable_page_selection_box.add_css_class("linked");
// //
let description_page_button = gtk::ToggleButton::builder() let description_page_button = gtk::ToggleButton::builder()
.label(t!("changelog_page_button_label")) .label(t!("description_page_button_label"))
.active(true) .active(true)
.build(); .build();
let extra_info_page_button = gtk::ToggleButton::builder() let extra_info_page_button = gtk::ToggleButton::builder()
.label(t!("extra_info_page_button_label")) .label(t!("extra_info_page_button_label"))
.group(&description_page_button) .group(&description_page_button)
.build(); .build();
let uris_page_button = gtk::ToggleButton::builder()
.label(t!("uris_page_button_label"))
.group(&description_page_button)
.build();
let changelog_page_button = gtk::ToggleButton::builder() let changelog_page_button = gtk::ToggleButton::builder()
.label(t!("changelog_page_button_label")) .label(t!("changelog_page_button_label"))
// till we find a way to implement // till we find a way to implement
@ -276,24 +281,45 @@ fn create_expandable_content(expandable_box: &gtk::Box) {
.build(); .build();
expandable_page_selection_box.append(&description_page_button); expandable_page_selection_box.append(&description_page_button);
expandable_page_selection_box.append(&extra_info_page_button); expandable_page_selection_box.append(&extra_info_page_button);
expandable_page_selection_box.append(&uris_page_button);
expandable_page_selection_box.append(&changelog_page_button); expandable_page_selection_box.append(&changelog_page_button);
// //
expandable_box.append(&expandable_page_selection_box); expandable_box.append(&expandable_page_selection_box);
// //
let expandable_stack = gtk::Stack::builder() let expandable_bin = adw::Bin::builder()
.hexpand(true) .hexpand(true)
.vexpand(true) .vexpand(true)
.vhomogeneous(true)
.hhomogeneous(true)
.transition_type(StackTransitionType::SlideLeftRight)
.build(); .build();
// //
expandable_box.append(&expandable_stack) apt_package_row.connect_expanded_notify(clone!(@strong expandable_bin, @strong expandable_box, @strong apt_package_row, @strong description_page_button => move |apt_package_row| {
if apt_package_row.property("expanded") {
expandable_bin.set_child(Some(&extra_info_stack_page(&package_maintainer, package_size, package_installed_size)));
description_page_button.set_active(true);
expandable_box.append(&expandable_bin)
} else {
expandable_box.remove(&expandable_bin)
}
}));
//expandable_bin.add_named(&extra_info_stack_page(package_maintainer, package_size, package_installed_size), Some("extra_info_page"));
//
} }
fn extra_info_stack_page() { fn extra_info_stack_page(package_maintainer: &str, package_size: u64, package_installed_size: u64) -> gtk::Box {
//create_color_badge(t!("")) let extra_info_badges_content_box = gtk::Box::builder()
//background-accent-bg .hexpand(true)
.vexpand(true)
.orientation(Orientation::Vertical)
.sensitive(false)
.build();
let extra_info_badges_size_group = gtk::SizeGroup::new(SizeGroupMode::Both);
let extra_info_badges_size_group0 = gtk::SizeGroup::new(SizeGroupMode::Both);
let extra_info_badges_size_group1 = gtk::SizeGroup::new(SizeGroupMode::Both);
let package_size = package_size as f64;
let package_installed_size = package_installed_size as f64;
extra_info_badges_content_box.append(&create_color_badge(&t!("extra_info_maintainer").to_string(), package_maintainer, "background-accent-bg", &extra_info_badges_size_group, &extra_info_badges_size_group0, &extra_info_badges_size_group1));
extra_info_badges_content_box.append(&create_color_badge(&t!("extra_info_download_size").to_string(), &convert(package_size), "background-accent-bg", &extra_info_badges_size_group, &extra_info_badges_size_group0, &extra_info_badges_size_group1));
extra_info_badges_content_box.append(&create_color_badge(&t!("extra_info_installed_size").to_string(), &convert(package_installed_size), "background-accent-bg", &extra_info_badges_size_group, &extra_info_badges_size_group0, &extra_info_badges_size_group1));
extra_info_badges_content_box
} }
fn create_color_badge( fn create_color_badge(
label0_text: &str, label0_text: &str,

View File

@ -1,8 +1,8 @@
mod imp; mod imp;
use crate::apt_update_page::AptPackageSocket;
use glib::Object; use glib::Object;
use gtk::glib; use gtk::glib;
use crate::apt_update_page::AptPackageSocket;
glib::wrapper! { glib::wrapper! {
pub struct AptPackageRow(ObjectSubclass<imp::AptPackageRow>) pub struct AptPackageRow(ObjectSubclass<imp::AptPackageRow>)
@ -29,7 +29,7 @@ impl AptPackageRow {
impl Default for AptPackageRow { impl Default for AptPackageRow {
fn default() -> Self { fn default() -> Self {
Self::new(AptPackageSocket{ Self::new(AptPackageSocket {
name: "name".to_string(), name: "name".to_string(),
arch: "arch".to_string(), arch: "arch".to_string(),
installed_version: "0.0".to_string(), installed_version: "0.0".to_string(),
@ -38,7 +38,7 @@ impl Default for AptPackageRow {
source_uri: "??".to_string(), source_uri: "??".to_string(),
maintainer: "??".to_string(), maintainer: "??".to_string(),
size: 0, size: 0,
installed_size: 0 installed_size: 0,
}) })
} }
} }

View File

@ -1,10 +1,10 @@
use pika_unixsocket_tools::*;
use rust_apt::new_cache; use rust_apt::new_cache;
use tokio::net::{UnixStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use rust_apt::progress::{AcquireProgress, DynAcquireProgress}; use rust_apt::progress::{AcquireProgress, DynAcquireProgress};
use rust_apt::raw::{AcqTextStatus, ItemDesc, PkgAcquire}; use rust_apt::raw::{AcqTextStatus, ItemDesc, PkgAcquire};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::UnixStream;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use pika_unixsocket_tools::*;
pub struct AptUpdateProgressSocket<'a> { pub struct AptUpdateProgressSocket<'a> {
pulse_interval: usize, pulse_interval: usize,
@ -22,7 +22,7 @@ impl<'a> AptUpdateProgressSocket<'a> {
max: 0, max: 0,
progress: 0.0, progress: 0.0,
percent_socket_path: percent_socket_path, percent_socket_path: percent_socket_path,
status_socket_path: status_socket_path status_socket_path: status_socket_path,
}; };
progress progress
} }
@ -40,7 +40,9 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> {
/// The higher the number, the less frequent pulse updates will be. /// The higher the number, the less frequent pulse updates will be.
/// ///
/// Pulse Interval set to 0 assumes the apt defaults. /// Pulse Interval set to 0 assumes the apt defaults.
fn pulse_interval(&self) -> usize { self.pulse_interval } fn pulse_interval(&self) -> usize {
self.pulse_interval
}
/// Called when an item is confirmed to be up-to-date. /// Called when an item is confirmed to be up-to-date.
/// ///
@ -48,7 +50,9 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> {
fn hit(&mut self, item: &ItemDesc) { fn hit(&mut self, item: &ItemDesc) {
let message = format!("Up-to-date: {} {}", item.description(), item.short_desc()); let message = format!("Up-to-date: {} {}", item.description(), item.short_desc());
println!("{}", message); println!("{}", message);
Runtime::new().unwrap().block_on(send_progress_status(message, self.status_socket_path)); Runtime::new()
.unwrap()
.block_on(send_progress_status(message, self.status_socket_path));
} }
/// Called when an Item has started to download /// Called when an Item has started to download
@ -57,7 +61,9 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> {
fn fetch(&mut self, item: &ItemDesc) { fn fetch(&mut self, item: &ItemDesc) {
let message = format!("Fetching: {} {}", item.description(), item.short_desc()); let message = format!("Fetching: {} {}", item.description(), item.short_desc());
println!("{}", message); println!("{}", message);
Runtime::new().unwrap().block_on(send_progress_status(message, self.status_socket_path)); Runtime::new()
.unwrap()
.block_on(send_progress_status(message, self.status_socket_path));
} }
/// Called when an item is successfully and completely fetched. /// Called when an item is successfully and completely fetched.
@ -66,7 +72,9 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> {
fn done(&mut self, item: &ItemDesc) { fn done(&mut self, item: &ItemDesc) {
let message = format!("Downloading: {} {}", item.description(), item.short_desc()); let message = format!("Downloading: {} {}", item.description(), item.short_desc());
println!("{}", message); println!("{}", message);
Runtime::new().unwrap().block_on(send_progress_status(message, self.status_socket_path)); Runtime::new()
.unwrap()
.block_on(send_progress_status(message, self.status_socket_path));
} }
/// Called when progress has started. /// Called when progress has started.
@ -87,9 +95,15 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> {
/// ///
/// Print out the ErrorText for the Item. /// Print out the ErrorText for the Item.
fn fail(&mut self, item: &ItemDesc) { fn fail(&mut self, item: &ItemDesc) {
let message = format!("Download Failed!: {} {}", item.description(), item.short_desc()); let message = format!(
"Download Failed!: {} {}",
item.description(),
item.short_desc()
);
eprintln!("{}", message); eprintln!("{}", message);
Runtime::new().unwrap().block_on(send_progress_status(message, self.status_socket_path)); Runtime::new()
.unwrap()
.block_on(send_progress_status(message, self.status_socket_path));
} }
/// Called periodically to provide the overall progress information /// Called periodically to provide the overall progress information
@ -98,8 +112,12 @@ impl<'a> DynAcquireProgress for AptUpdateProgressSocket<'a> {
/// Each line has an overall percent meter and a per active item status /// Each line has an overall percent meter and a per active item status
/// meter along with an overall bandwidth and ETA indicator. /// meter along with an overall bandwidth and ETA indicator.
fn pulse(&mut self, status: &AcqTextStatus, owner: &PkgAcquire) { fn pulse(&mut self, status: &AcqTextStatus, owner: &PkgAcquire) {
let progress_percent: f32 = (status.current_bytes() as f32 * 100.0) / status.total_bytes() as f32; let progress_percent: f32 =
Runtime::new().unwrap().block_on(send_progress_percent(progress_percent, self.percent_socket_path)); (status.current_bytes() as f32 * 100.0) / status.total_bytes() as f32;
Runtime::new().unwrap().block_on(send_progress_percent(
progress_percent,
self.percent_socket_path,
));
} }
} }
@ -107,14 +125,25 @@ fn main() {
let update_cache = new_cache!().unwrap(); let update_cache = new_cache!().unwrap();
let percent_socket_path = "/tmp/pika_apt_update_percent.sock"; let percent_socket_path = "/tmp/pika_apt_update_percent.sock";
let status_socket_path = "/tmp/pika_apt_update_status.sock"; let status_socket_path = "/tmp/pika_apt_update_status.sock";
match update_cache.update(&mut AcquireProgress::new(AptUpdateProgressSocket::new(percent_socket_path, status_socket_path))) { match update_cache.update(&mut AcquireProgress::new(AptUpdateProgressSocket::new(
percent_socket_path,
status_socket_path,
))) {
Ok(_) => { Ok(_) => {
Runtime::new().unwrap().block_on(send_successful_to_socket(percent_socket_path)); Runtime::new()
Runtime::new().unwrap().block_on(send_successful_to_socket(status_socket_path)); .unwrap()
.block_on(send_successful_to_socket(percent_socket_path));
Runtime::new()
.unwrap()
.block_on(send_successful_to_socket(status_socket_path));
} }
Err(e) => { Err(e) => {
Runtime::new().unwrap().block_on(send_failed_to_socket(percent_socket_path)); Runtime::new()
Runtime::new().unwrap().block_on(send_failed_to_socket(status_socket_path)); .unwrap()
.block_on(send_failed_to_socket(percent_socket_path));
Runtime::new()
.unwrap()
.block_on(send_failed_to_socket(status_socket_path));
panic!("{}", e.to_string()) panic!("{}", e.to_string())
} }
}; };
@ -122,17 +151,27 @@ fn main() {
async fn send_progress_percent(progress_f32: f32, socket_path: &str) { async fn send_progress_percent(progress_f32: f32, socket_path: &str) {
// Connect to the Unix socket // Connect to the Unix socket
let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); let mut stream = UnixStream::connect(socket_path)
.await
.expect("Could not connect to server");
let message = progress_f32.to_string(); let message = progress_f32.to_string();
// Send the message to the server // Send the message to the server
stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); stream
.write_all(message.as_bytes())
.await
.expect("Failed to write to stream");
} }
async fn send_progress_status(message: String, socket_path: &str) { async fn send_progress_status(message: String, socket_path: &str) {
// Connect to the Unix socket // Connect to the Unix socket
let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); let mut stream = UnixStream::connect(socket_path)
.await
.expect("Could not connect to server");
// Send the message to the server // Send the message to the server
stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); stream
.write_all(message.as_bytes())
.await
.expect("Failed to write to stream");
} }

View File

@ -1,19 +1,22 @@
use std::{fs, thread}; use crate::apt_package_row::AptPackageRow;
use std::path::Path; use adw::prelude::*;
use rust_apt::*; use gtk::glib::*;
use gtk::*;
use pika_unixsocket_tools::*;
use rust_apt::cache::*; use rust_apt::cache::*;
use rust_apt::new_cache; use rust_apt::new_cache;
use rust_apt::records::RecordField; use rust_apt::records::RecordField;
use rust_apt::*;
use std::borrow::BorrowMut;
use std::path::Path;
use std::process::Command; use std::process::Command;
use gtk::glib::*; use std::sync::atomic::AtomicBool;
use adw::prelude::*; use std::sync::Arc;
use gtk::*; use std::{fs, thread};
use tokio::net::{UnixListener, UnixStream};
use tokio::io::AsyncReadExt; use tokio::io::AsyncReadExt;
use tokio::net::{UnixListener, UnixStream};
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use tokio::task; use tokio::task;
use pika_unixsocket_tools::*;
use crate::apt_package_row::AptPackageRow;
pub struct AptPackageSocket { pub struct AptPackageSocket {
pub name: String, pub name: String,
@ -24,7 +27,7 @@ pub struct AptPackageSocket {
pub source_uri: String, pub source_uri: String,
pub maintainer: String, pub maintainer: String,
pub size: u64, pub size: u64,
pub installed_size: u64 pub installed_size: u64,
} }
pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box { pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
@ -36,11 +39,15 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
let get_upgradable_sender = get_upgradable_sender.clone(); let get_upgradable_sender = get_upgradable_sender.clone();
thread::spawn(move || { thread::spawn(move || {
Runtime::new().unwrap().block_on(update_percent_socket_server(update_percent_sender)); Runtime::new()
.unwrap()
.block_on(update_percent_socket_server(update_percent_sender));
}); });
thread::spawn(move || { thread::spawn(move || {
Runtime::new().unwrap().block_on(update_status_socket_server(update_status_sender)); Runtime::new()
.unwrap()
.block_on(update_status_socket_server(update_status_sender));
}); });
Command::new("pkexec") Command::new("pkexec")
@ -68,6 +75,7 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
.margin_start(15) .margin_start(15)
.margin_end(15) .margin_end(15)
.margin_start(15) .margin_start(15)
.sensitive(false)
.build(); .build();
packages_boxedlist.add_css_class("boxed-list"); packages_boxedlist.add_css_class("boxed-list");
let rows_size_group = gtk::SizeGroup::new(SizeGroupMode::Both); let rows_size_group = gtk::SizeGroup::new(SizeGroupMode::Both);
@ -113,17 +121,21 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
.width_request(500) .width_request(500)
.build(); .build();
let mut updates_parsed = Arc::new(AtomicBool::new(false));
let update_parsed_clone0 = Arc::clone(&updates_parsed);
let update_percent_server_context = MainContext::default(); let update_percent_server_context = MainContext::default();
// The main loop executes the asynchronous block // The main loop executes the asynchronous block
update_percent_server_context.spawn_local(clone!(@weak apt_update_dialog_progress_bar, @weak apt_update_dialog, @strong get_upgradable_sender => async move { update_percent_server_context.spawn_local(clone!(@weak apt_update_dialog_progress_bar, @weak apt_update_dialog, @strong get_upgradable_sender, @strong update_parsed_clone0 => async move {
while let Ok(state) = update_percent_receiver.recv().await { while let Ok(state) = update_percent_receiver.recv().await {
match state.as_ref() { match state.as_ref() {
"FN_OVERRIDE_SUCCESSFUL" => { "FN_OVERRIDE_SUCCESSFUL" => {
let get_upgradable_sender = get_upgradable_sender.clone(); let get_upgradable_sender = get_upgradable_sender.clone();
thread::spawn( move || { let update_parsed_clone = Arc::clone(&update_parsed_clone0);
thread::spawn(move || {
// Create upgradable list cache // Create upgradable list cache
let upgradable_cache = new_cache!().unwrap(); let upgradable_cache = new_cache!().unwrap();
// Create pack sort from upgradable_cache // Create pack sort from upgradable_cache
let upgradable_sort = PackageSort::default().upgradable().names(); let upgradable_sort = PackageSort::default().upgradable().names();
@ -148,6 +160,7 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
}; };
get_upgradable_sender.send_blocking(package_struct).unwrap() get_upgradable_sender.send_blocking(package_struct).unwrap()
} }
update_parsed_clone.store(true, std::sync::atomic::Ordering::Relaxed)
}); });
apt_update_dialog.close(); apt_update_dialog.close();
} }
@ -160,7 +173,8 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
let update_status_server_context = MainContext::default(); let update_status_server_context = MainContext::default();
// The main loop executes the asynchronous block // The main loop executes the asynchronous block
update_status_server_context.spawn_local(clone!(@weak apt_update_dialog, @weak apt_update_dialog_spinner => async move { update_status_server_context.spawn_local(
clone!(@weak apt_update_dialog, @weak apt_update_dialog_spinner => async move {
while let Ok(state) = update_status_receiver.recv().await { while let Ok(state) = update_status_receiver.recv().await {
match state.as_ref() { match state.as_ref() {
"FN_OVERRIDE_SUCCESSFUL" => {} "FN_OVERRIDE_SUCCESSFUL" => {}
@ -171,11 +185,14 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
_ => apt_update_dialog.set_body(&state) _ => apt_update_dialog.set_body(&state)
} }
} }
})); }),
);
let update_parsed_clone1 = Arc::clone(&updates_parsed);
let get_upgradable_server_context = MainContext::default(); let get_upgradable_server_context = MainContext::default();
// The main loop executes the asynchronous block // The main loop executes the asynchronous block
get_upgradable_server_context.spawn_local(clone!(@weak packages_boxedlist => async move { get_upgradable_server_context.spawn_local(
clone!(@weak packages_boxedlist, @strong update_parsed_clone1 => async move {
while let Ok(state) = get_upgradable_receiver.recv().await { while let Ok(state) = get_upgradable_receiver.recv().await {
packages_boxedlist.append(&AptPackageRow::new(AptPackageSocket { packages_boxedlist.append(&AptPackageRow::new(AptPackageSocket {
name: state.name, name: state.name,
@ -188,9 +205,12 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
size: state.size, size: state.size,
installed_size: state.installed_size installed_size: state.installed_size
})); }));
if update_parsed_clone1.load(std::sync::atomic::Ordering::Relaxed) {
packages_boxedlist.set_sensitive(true)
}
} }
})); }),
);
main_box.append(&searchbar); main_box.append(&searchbar);
main_box.append(&packages_viewport); main_box.append(&packages_viewport);
@ -199,7 +219,6 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
main_box main_box
} }
async fn update_percent_socket_server(buffer_sender: async_channel::Sender<String>) { async fn update_percent_socket_server(buffer_sender: async_channel::Sender<String>) {
// Path to the Unix socket file // Path to the Unix socket file
let socket_path = "/tmp/pika_apt_update_percent.sock"; let socket_path = "/tmp/pika_apt_update_percent.sock";

View File

@ -1,14 +1,14 @@
use adw::prelude::*;
use adw::*;
use gtk::{Orientation, License};
use crate::apt_update_page; use crate::apt_update_page;
use crate::apt_update_page::apt_update_page; use crate::apt_update_page::apt_update_page;
use crate::config::{APP_ICON, APP_ID, APP_GITHUB, VERSION}; use crate::config::{APP_GITHUB, APP_ICON, APP_ID, VERSION};
use adw::prelude::*;
use adw::*;
use gtk::glib::{clone, MainContext}; use gtk::glib::{clone, MainContext};
use std::thread; use gtk::{License, Orientation};
use std::process::Command;
use std::cell::RefCell; use std::cell::RefCell;
use std::process::Command;
use std::rc::Rc; use std::rc::Rc;
use std::thread;
pub fn build_ui(app: &adw::Application) { pub fn build_ui(app: &adw::Application) {
// setup glib // setup glib

View File

@ -1,17 +1,16 @@
mod config;
mod build_ui;
mod apt_update_page;
mod apt_package_row; mod apt_package_row;
mod apt_update_page;
mod build_ui;
mod config;
use std::env; use crate::config::APP_ID;
use adw::prelude::*; use adw::prelude::*;
use adw::*; use adw::*;
use build_ui::build_ui;
use gdk::Display; use gdk::Display;
use gtk::*; use gtk::*;
use std::boxed::Box; use std::boxed::Box;
use build_ui::build_ui; use std::env;
use crate::config::{APP_ID};
// Init translations for current crate. // Init translations for current crate.
#[macro_use] #[macro_use]
@ -21,16 +20,16 @@ i18n!("locales", fallback = "en_US");
/// main function /// main function
fn main() { fn main() {
let current_locale = match env::var_os("LANG") { let current_locale = match env::var_os("LANG") {
Some(v) => v.into_string().unwrap().chars() Some(v) => v
.into_string()
.unwrap()
.chars()
.take_while(|&ch| ch != '.') .take_while(|&ch| ch != '.')
.collect::<String>(), .collect::<String>(),
None => panic!("$LANG is not set"), None => panic!("$LANG is not set"),
}; };
rust_i18n::set_locale(&current_locale); rust_i18n::set_locale(&current_locale);
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();

View File

@ -1,24 +1,34 @@
use tokio::net::{UnixStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::UnixStream;
pub async fn send_successful_to_socket(socket_path: &str) { pub async fn send_successful_to_socket(socket_path: &str) {
// Connect to the Unix socket // Connect to the Unix socket
let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); let mut stream = UnixStream::connect(socket_path)
.await
.expect("Could not connect to server");
let message = "FN_OVERRIDE_SUCCESSFUL"; let message = "FN_OVERRIDE_SUCCESSFUL";
// Send the message to the server // Send the message to the server
stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); stream
.write_all(message.as_bytes())
.await
.expect("Failed to write to stream");
} }
pub async fn send_failed_to_socket(socket_path: &str) { pub async fn send_failed_to_socket(socket_path: &str) {
// Connect to the Unix socket // Connect to the Unix socket
let mut stream = UnixStream::connect(socket_path).await.expect("Could not connect to server"); let mut stream = UnixStream::connect(socket_path)
.await
.expect("Could not connect to server");
let message = "FN_OVERRIDE_FAILED"; let message = "FN_OVERRIDE_FAILED";
// Send the message to the server // Send the message to the server
stream.write_all(message.as_bytes()).await.expect("Failed to write to stream"); stream
.write_all(message.as_bytes())
.await
.expect("Failed to write to stream");
} }
// Function to handle a single client connection // Function to handle a single client connection
@ -30,7 +40,9 @@ pub async fn handle_client(mut stream: UnixStream, buffer_sender: async_channel:
match stream.read(&mut buffer).await { match stream.read(&mut buffer).await {
Ok(size) => { Ok(size) => {
// Print the received message // Print the received message
buffer_sender.send_blocking(String::from_utf8_lossy(&buffer[..size]).to_string()).expect("Buffer channel closed") buffer_sender
.send_blocking(String::from_utf8_lossy(&buffer[..size]).to_string())
.expect("Buffer channel closed")
} }
Err(e) => { Err(e) => {
// Print error message if reading fails // Print error message if reading fails