From 5e00e676e9050c58d5a661a20827120a05e62afc Mon Sep 17 00:00:00 2001 From: Ward from fusion-voyager-3 Date: Thu, 19 Sep 2024 21:13:08 +0300 Subject: [PATCH] add apt repo tools integration --- .../apt_manage_page/apt_sourcelist_row/imp.rs | 597 ------------------ .../apt_manage_page/apt_sourcelist_row/mod.rs | 45 -- src/bin/gui/apt_manage_page/mod.rs | 162 +++-- 3 files changed, 125 insertions(+), 679 deletions(-) delete mode 100644 src/bin/gui/apt_manage_page/apt_sourcelist_row/imp.rs delete mode 100644 src/bin/gui/apt_manage_page/apt_sourcelist_row/mod.rs diff --git a/src/bin/gui/apt_manage_page/apt_sourcelist_row/imp.rs b/src/bin/gui/apt_manage_page/apt_sourcelist_row/imp.rs deleted file mode 100644 index 5cd11de..0000000 --- a/src/bin/gui/apt_manage_page/apt_sourcelist_row/imp.rs +++ /dev/null @@ -1,597 +0,0 @@ -use std::{cell::RefCell, sync::OnceLock}; - -use adw::*; -use adw::{prelude::*, subclass::prelude::*}; -use glib::{clone, subclass::Signal, Properties}; -use gtk::*; -use pretty_bytes::converter::convert; -use std::env; - -// ANCHOR: custom_button -// Object holding the state -#[derive(Properties, Default)] -#[properties(wrapper_type = super::AptSourceListRow)] -pub struct AptSourceListRow { - #[property(get, set)] - package_name: RefCell, - #[property(get, set)] - package_arch: RefCell, - #[property(get, set)] - package_installed_version: RefCell, - #[property(get, set)] - package_candidate_version: RefCell, - #[property(get, set)] - package_description: RefCell, - #[property(get, set)] - package_source_uri: RefCell, - #[property(get, set)] - package_maintainer: RefCell, - #[property(get, set)] - package_size: RefCell, - #[property(get, set)] - package_installed_size: RefCell, - #[property(get, set)] - package_marked: RefCell, -} -// ANCHOR_END: custom_button - -// The central trait for subclassing a GObject -#[glib::object_subclass] -impl ObjectSubclass for AptSourceListRow { - const NAME: &'static str = "AptSourceListRow"; - type Type = super::AptSourceListRow; - type ParentType = ExpanderRow; -} - -// ANCHOR: object_impl -// Trait shared by all GObjects -#[glib::derived_properties] -impl ObjectImpl for AptSourceListRow { - fn signals() -> &'static [Signal] { - static SIGNALS: OnceLock> = OnceLock::new(); - SIGNALS.get_or_init(|| { - vec![ - Signal::builder("checkbutton-toggled").build(), - Signal::builder("checkbutton-untoggled").build(), - ] - }) - } - fn constructed(&self) { - let current_locale = match env::var_os("LANG") { - Some(v) => v - .into_string() - .unwrap() - .chars() - .take_while(|&ch| ch != '.') - .collect::(), - None => panic!("$LANG is not set"), - }; - rust_i18n::set_locale(¤t_locale); - - self.parent_constructed(); - - // Bind label to number - // `SYNC_CREATE` ensures that the label will be immediately set - let obj = self.obj(); - - let prefix_box = Box::new(Orientation::Vertical, 0); - - let expandable_box = Box::new(Orientation::Vertical, 0); - - obj.connect_package_name_notify(clone!( - #[weak] - prefix_box, - #[weak] - expandable_box, - #[strong] - obj, - move |_| { - remove_all_children_from_box(&prefix_box); - remove_all_children_from_box(&expandable_box); - // - let package_name = obj.package_name(); - let package_arch = obj.package_arch(); - let package_installed_version = obj.package_installed_version(); - let package_candidate_version = obj.package_candidate_version(); - let package_description = obj.package_description(); - let package_source_uri = obj.package_source_uri(); - let package_maintainer = obj.package_maintainer(); - let package_size = obj.package_size(); - let package_installed_size = obj.package_installed_size(); - // - create_prefix_content( - &prefix_box, - &package_name, - &package_arch, - &package_installed_version, - &package_candidate_version, - ); - // - 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_row(&expandable_box); - - let suffix_toggle = CheckButton::builder() - .tooltip_text(t!("mark_for_update")) - .halign(Align::Center) - .valign(Align::Center) - .hexpand(false) - .vexpand(false) - .build(); - - suffix_toggle.connect_toggled(clone!( - #[weak] - obj, - #[weak] - suffix_toggle, - move |_| { - if suffix_toggle.is_active() { - obj.emit_by_name::<()>("checkbutton-toggled", &[]); - } else { - obj.emit_by_name::<()>("checkbutton-untoggled", &[]); - } - } - )); - - obj.add_suffix(&suffix_toggle); - - let obj = self.obj(); - obj.bind_property("package-marked", &suffix_toggle, "active") - .sync_create() - .bidirectional() - .build(); - - // turn on by default - obj.set_property("package-marked", true) - } -} -// Trait shared by all widgets -impl WidgetImpl for AptSourceListRow {} - -// Trait shared by all buttons -// Trait shared by all buttons - -impl ListBoxRowImpl for AptSourceListRow {} -impl PreferencesRowImpl for AptSourceListRow {} -impl ExpanderRowImpl for AptSourceListRow {} - -fn create_version_badge(installed_version: &str, candidate_version: &str) -> ListBox { - let (base_version, installed_diff, candidate_diff) = - get_diff_by_prefix(installed_version, candidate_version); - - let badge_box = Box::builder() - .halign(Align::Start) - .hexpand(false) - .orientation(Orientation::Horizontal) - .margin_start(5) - .margin_end(5) - .margin_bottom(5) - .margin_top(5) - .build(); - - let installed_version_box = Box::builder() - .halign(Align::Start) - .hexpand(false) - .orientation(Orientation::Horizontal) - .tooltip_text(t!("installed_version_badge_text")) - .build(); - - let installed_version_base_version_label = Label::builder() - .label(format!( - "{}: {}", - t!("installed_version_badge_text"), - &base_version - )) - .valign(Align::Center) - .halign(Align::Start) - .hexpand(false) - .vexpand(true) - .build(); - - let installed_diff_label = Label::builder() - .label(installed_diff) - .valign(Align::Center) - .halign(Align::Start) - .hexpand(false) - .vexpand(true) - .build(); - installed_diff_label.add_css_class("destructive-color-text"); - - installed_version_box.append(&installed_version_base_version_label.clone()); - installed_version_box.append(&installed_diff_label); - - let label_separator = Separator::builder().margin_start(5).margin_end(5).build(); - - let candidate_version_box = Box::builder() - .halign(Align::Start) - .hexpand(false) - .orientation(Orientation::Horizontal) - .tooltip_text(t!("candidate_version_badge_text")) - .build(); - - let candidate_version_base_version_label = Label::builder() - .label(format!( - "{}: {}", - t!("candidate_version_badge_text"), - &base_version - )) - .valign(Align::Center) - .halign(Align::Start) - .hexpand(false) - .vexpand(true) - .build(); - - let candidate_diff_label = Label::builder() - .label(candidate_diff) - .valign(Align::Center) - .halign(Align::Start) - .hexpand(false) - .vexpand(true) - .build(); - candidate_diff_label.add_css_class("success-color-text"); - - candidate_version_box.append(&candidate_version_base_version_label); - candidate_version_box.append(&candidate_diff_label); - - badge_box.append(&installed_version_box); - badge_box.append(&label_separator); - badge_box.append(&candidate_version_box); - - let boxedlist = ListBox::builder() - .selection_mode(SelectionMode::None) - .halign(Align::Start) - .valign(Align::End) - .margin_start(5) - .margin_end(5) - .margin_bottom(10) - .build(); - - boxedlist.add_css_class("boxed-list"); - boxedlist.append(&badge_box); - boxedlist -} - -fn create_arch_badge(arch: &str) -> ListBox { - let arch_label = Label::builder() - .halign(Align::Start) - .hexpand(false) - .label(format!("{}: {}", t!("arch_label_label"), arch)) - .margin_start(5) - .margin_end(5) - .margin_bottom(5) - .margin_top(5) - .build(); - - let boxedlist = ListBox::builder() - .selection_mode(SelectionMode::None) - .halign(Align::Start) - .valign(Align::End) - .margin_start(5) - .margin_end(5) - .margin_bottom(10) - .build(); - - boxedlist.add_css_class("boxed-list"); - boxedlist.append(&arch_label); - boxedlist -} - -fn remove_all_children_from_box(parent: >k::Box) { - while let Some(child) = parent.last_child() { - parent.remove(&child); - } -} - -fn create_prefix_content( - prefix_box: >k::Box, - package_name: &str, - package_arch: &str, - package_installed_version: &str, - package_candidate_version: &str, -) { - let package_label = Label::builder() - .halign(Align::Start) - .margin_start(5) - .margin_end(5) - .margin_bottom(5) - .margin_top(5) - .label(package_name) - .build(); - package_label.add_css_class("size-20-bold-text"); - let version_box = Box::new(Orientation::Horizontal, 0); - version_box.append(&create_version_badge( - package_installed_version, - package_candidate_version, - )); - version_box.append(&create_arch_badge(package_arch)); - prefix_box.append(&package_label); - prefix_box.append(&version_box); -} - -fn create_expandable_content( - apt_package_row: &impl IsA, - expandable_box: >k::Box, - package_description: String, - package_source_uri: String, - package_maintainer: String, - package_size: u64, - package_installed_size: u64, -) { - let expandable_page_selection_box = Box::builder() - .orientation(Orientation::Horizontal) - .hexpand(false) - .vexpand(false) - .halign(Align::Start) - .valign(Align::Start) - .margin_bottom(10) - .margin_top(10) - .margin_start(10) - .margin_end(10) - .build(); - expandable_page_selection_box.add_css_class("linked"); - // - let description_page_button = ToggleButton::builder() - .label(t!("description_button_label")) - .active(true) - .build(); - let extra_info_page_button = ToggleButton::builder() - .label(t!("extra_info_page_button_label")) - .group(&description_page_button) - .build(); - let uris_page_button = ToggleButton::builder() - .label(t!("uris_page_button_label")) - .group(&description_page_button) - .build(); - let changelog_page_button = ToggleButton::builder() - .label(t!("changelog_page_button_label")) - // till we find a way to implement - .sensitive(false) - .group(&description_page_button) - .build(); - expandable_page_selection_box.append(&description_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_box.append(&expandable_page_selection_box); - // - let expandable_bin = Bin::builder().hexpand(true).vexpand(true).build(); - // - description_page_button.connect_clicked(clone!( - #[strong] - expandable_bin, - #[strong] - description_page_button, - move |_| { - if description_page_button.is_active() { - expandable_bin.set_child(Some(&description_stack_page(&package_description))); - } - } - )); - - extra_info_page_button.connect_clicked(clone!( - #[strong] - expandable_bin, - #[strong] - extra_info_page_button, - move |_| { - if extra_info_page_button.is_active() { - expandable_bin.set_child(Some(&extra_info_stack_page( - &package_maintainer, - package_size, - package_installed_size, - ))); - } - } - )); - - uris_page_button.connect_clicked(clone!( - #[strong] - expandable_bin, - #[strong] - uris_page_button, - move |_| { - if uris_page_button.is_active() { - expandable_bin.set_child(Some(&uris_stack_page(&package_source_uri))); - } - } - )); - - apt_package_row.connect_expanded_notify(clone!( - #[strong] - expandable_bin, - #[strong] - expandable_box, - #[strong] - apt_package_row, - #[strong] - description_page_button, - move |_| { - if apt_package_row.property("expanded") { - description_page_button.set_active(true); - description_page_button.emit_by_name::<()>("clicked", &[]); - 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 uris_stack_page(package_source_uri: &str) -> gtk::Box { - let uris_content_box = Box::builder() - .hexpand(true) - .vexpand(true) - .orientation(Orientation::Vertical) - .build(); - let uris_text_buffer = TextBuffer::builder() - .text(package_source_uri.to_owned() + "\n") - .build(); - let uris_text_view = TextView::builder() - .buffer(&uris_text_buffer) - .hexpand(true) - .vexpand(true) - .margin_top(15) - .margin_bottom(15) - .margin_start(15) - .margin_end(15) - .editable(false) - .buffer(&uris_text_buffer) - .build(); - uris_content_box.append(&uris_text_view); - uris_content_box -} - -fn description_stack_page(package_description: &str) -> gtk::Box { - let description_content_box = Box::builder() - .hexpand(true) - .vexpand(true) - .orientation(Orientation::Vertical) - .build(); - let description_text_buffer = TextBuffer::builder() - .text(package_description.to_owned() + "\n") - .build(); - let description_text_view = TextView::builder() - .buffer(&description_text_buffer) - .hexpand(true) - .vexpand(true) - .margin_top(0) - .margin_bottom(10) - .margin_start(15) - .margin_end(15) - .editable(false) - .build(); - description_content_box.append(&description_text_view); - description_content_box -} - -fn extra_info_stack_page( - package_maintainer: &str, - package_size: u64, - package_installed_size: u64, -) -> gtk::Box { - let extra_info_badges_content_box = Box::builder() - .hexpand(true) - .vexpand(true) - .orientation(Orientation::Vertical) - .build(); - let extra_info_badges_size_group = SizeGroup::new(SizeGroupMode::Both); - let extra_info_badges_size_group0 = SizeGroup::new(SizeGroupMode::Both); - let extra_info_badges_size_group1 = 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( - label0_text: &str, - label1_text: &str, - css_style: &str, - group_size: &SizeGroup, - group_size0: &SizeGroup, - group_size1: &SizeGroup, -) -> ListBox { - let badge_box = Box::builder().build(); - - let label0 = Label::builder() - .label(label0_text) - .margin_start(5) - .margin_end(5) - .margin_bottom(1) - .margin_top(1) - .valign(Align::Center) - .halign(Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - group_size0.add_widget(&label0); - - let label_separator = Separator::builder().build(); - - let label1 = Label::builder() - .label(label1_text) - .margin_start(3) - .margin_end(0) - .margin_bottom(1) - .margin_top(1) - .valign(Align::Center) - .halign(Align::Center) - .hexpand(true) - .vexpand(true) - .build(); - group_size1.add_widget(&label1); - - label1.add_css_class(css_style); - - badge_box.append(&label0); - badge_box.append(&label_separator); - badge_box.append(&label1); - - let boxedlist = ListBox::builder() - .selection_mode(SelectionMode::None) - .halign(Align::Start) - .valign(Align::Start) - .margin_start(10) - .margin_end(10) - .margin_bottom(10) - .margin_top(10) - .build(); - - boxedlist.add_css_class("boxed-list"); - boxedlist.append(&badge_box); - group_size.add_widget(&boxedlist); - boxedlist -} - -pub fn get_diff_by_prefix(xs: &str, ys: &str) -> (String, String, String) { - let mut count = String::new(); - for (x, y) in xs.chars().zip(ys.chars()) { - if x == y { - count.push(x) - } else { - break; - } - } - let count_clone0 = count.clone(); - return ( - count_clone0, - xs.trim_start_matches(&count.as_str()).to_string(), - ys.trim_start_matches(&count.as_str()).to_string(), - ); -} diff --git a/src/bin/gui/apt_manage_page/apt_sourcelist_row/mod.rs b/src/bin/gui/apt_manage_page/apt_sourcelist_row/mod.rs deleted file mode 100644 index e04e3f0..0000000 --- a/src/bin/gui/apt_manage_page/apt_sourcelist_row/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -mod imp; - -use crate::apt_update_page::AptPackageSocket; -use glib::Object; -use gtk::glib; - -glib::wrapper! { - pub struct AptPackageRow(ObjectSubclass) - @extends adw::ExpanderRow, gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, - @implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget; -} - -impl AptPackageRow { - pub fn new(package: AptPackageSocket) -> Self { - Object::builder() - .property("package-name", package.name) - .property("package-arch", package.arch) - .property("package-installed-version", package.installed_version) - .property("package-candidate-version", package.candidate_version) - .property("package-description", package.description) - .property("package-source-uri", package.source_uri) - .property("package-maintainer", package.maintainer) - .property("package-size", package.size) - .property("package-installed-size", package.installed_size) - .build() - } -} -// ANCHOR_END: mod - -impl Default for AptPackageRow { - fn default() -> Self { - Self::new(AptPackageSocket { - name: "name".to_string(), - arch: "arch".to_string(), - installed_version: "0.0".to_string(), - candidate_version: "0.0".to_string(), - description: "??".to_string(), - source_uri: "??".to_string(), - maintainer: "??".to_string(), - size: 0, - installed_size: 0, - is_last: false, - }) - } -} diff --git a/src/bin/gui/apt_manage_page/mod.rs b/src/bin/gui/apt_manage_page/mod.rs index 497aaad..bbcb556 100644 --- a/src/bin/gui/apt_manage_page/mod.rs +++ b/src/bin/gui/apt_manage_page/mod.rs @@ -5,6 +5,7 @@ use apt_deb822_tools::Deb822Repository; use gtk::glib::*; use gtk::*; use std::cell::Ref; +use std::ops::Deref; use pika_unixsocket_tools::pika_unixsocket_tools::*; use property::PropertyGet; use rust_apt::cache::*; @@ -23,18 +24,27 @@ pub fn apt_manage_page( let deb822_sources = Deb822Repository::get_deb822_sources().unwrap(); + let mut unofficial_deb822_sources = deb822_sources.clone(); + let system_source = deb822_sources.iter().filter(|x| { match &x.repolib_id { Some(t) => { - if t == "system" { - true - } else { - false - } + t == "system" } None => false } }).next().unwrap(); + + unofficial_deb822_sources.retain(|x| { + match &x.repolib_id { + Some(t) => { + !(t == "system") + } + None => true + } + }); + + let legacy_apt_repos = apt_legacy_tools::LegacyAptSource::get_legacy_sources(); let main_box = Box::builder() .hexpand(true) @@ -100,17 +110,23 @@ pub fn apt_manage_page( let unofficial_sources_list_store = gio::ListStore::new::(); - struct Row2 { - col1: String, - col2: String, + enum AptSourceConfig { + Legacy(apt_legacy_tools::LegacyAptSource), + DEB822(apt_deb822_tools::Deb822Repository) } - (0..10000).for_each(|i| { - unofficial_sources_list_store.append(&BoxedAnyObject::new(Row2 { - col1: format!("col1 {i}"), - col2: format!("col2 {i}"), - })) - }); + for deb822_source in unofficial_deb822_sources { + unofficial_sources_list_store.append(&BoxedAnyObject::new(AptSourceConfig::DEB822(deb822_source))); + }; + + match legacy_apt_repos { + Ok(vec) => { + for legacy_repo in vec { + unofficial_sources_list_store.append(&BoxedAnyObject::new(AptSourceConfig::Legacy(legacy_repo))); + }; + } + Err(_) => {} + } let unofficial_sources_selection_model = SingleSelection::new(Some(unofficial_sources_list_store)); @@ -143,45 +159,117 @@ pub fn apt_manage_page( .model(&unofficial_sources_selection_model) .build(); - let col1factory = gtk::SignalListItemFactory::new(); - let col2factory = gtk::SignalListItemFactory::new(); - col1factory.connect_setup(move |_factory, item| { + // + + let unofficial_sources_columnview_factory0 = gtk::SignalListItemFactory::new(); + + unofficial_sources_columnview_factory0.connect_setup(move |_factory, item| { let item = item.downcast_ref::().unwrap(); - let row = Label::default(); + let row = Label::builder() + .halign(Align::Start) + .build(); item.set_child(Some(&row)); }); - col1factory.connect_bind(move |_factory, item| { - let item = item.downcast_ref::().unwrap(); + unofficial_sources_columnview_factory0.connect_bind(move |_factory, item| { + let item: &ListItem = item.downcast_ref::().unwrap(); let child = item.child().and_downcast::