add apt repo tools integration
This commit is contained in:
parent
4e28e295ae
commit
5e00e676e9
@ -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<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_arch: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_installed_version: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_candidate_version: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_description: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_source_uri: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_maintainer: RefCell<String>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_size: RefCell<u64>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_installed_size: RefCell<u64>,
|
|
||||||
#[property(get, set)]
|
|
||||||
package_marked: RefCell<bool>,
|
|
||||||
}
|
|
||||||
// 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<Vec<Signal>> = 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::<String>(),
|
|
||||||
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<ExpanderRow>,
|
|
||||||
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(),
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
mod imp;
|
|
||||||
|
|
||||||
use crate::apt_update_page::AptPackageSocket;
|
|
||||||
use glib::Object;
|
|
||||||
use gtk::glib;
|
|
||||||
|
|
||||||
glib::wrapper! {
|
|
||||||
pub struct AptPackageRow(ObjectSubclass<imp::AptPackageRow>)
|
|
||||||
@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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,6 +5,7 @@ use apt_deb822_tools::Deb822Repository;
|
|||||||
use gtk::glib::*;
|
use gtk::glib::*;
|
||||||
use gtk::*;
|
use gtk::*;
|
||||||
use std::cell::Ref;
|
use std::cell::Ref;
|
||||||
|
use std::ops::Deref;
|
||||||
use pika_unixsocket_tools::pika_unixsocket_tools::*;
|
use pika_unixsocket_tools::pika_unixsocket_tools::*;
|
||||||
use property::PropertyGet;
|
use property::PropertyGet;
|
||||||
use rust_apt::cache::*;
|
use rust_apt::cache::*;
|
||||||
@ -23,18 +24,27 @@ pub fn apt_manage_page(
|
|||||||
|
|
||||||
let deb822_sources = Deb822Repository::get_deb822_sources().unwrap();
|
let deb822_sources = Deb822Repository::get_deb822_sources().unwrap();
|
||||||
|
|
||||||
|
let mut unofficial_deb822_sources = deb822_sources.clone();
|
||||||
|
|
||||||
let system_source = deb822_sources.iter().filter(|x| {
|
let system_source = deb822_sources.iter().filter(|x| {
|
||||||
match &x.repolib_id {
|
match &x.repolib_id {
|
||||||
Some(t) => {
|
Some(t) => {
|
||||||
if t == "system" {
|
t == "system"
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => false
|
None => false
|
||||||
}
|
}
|
||||||
}).next().unwrap();
|
}).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()
|
let main_box = Box::builder()
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
@ -100,17 +110,23 @@ pub fn apt_manage_page(
|
|||||||
|
|
||||||
let unofficial_sources_list_store = gio::ListStore::new::<BoxedAnyObject>();
|
let unofficial_sources_list_store = gio::ListStore::new::<BoxedAnyObject>();
|
||||||
|
|
||||||
struct Row2 {
|
enum AptSourceConfig {
|
||||||
col1: String,
|
Legacy(apt_legacy_tools::LegacyAptSource),
|
||||||
col2: String,
|
DEB822(apt_deb822_tools::Deb822Repository)
|
||||||
}
|
}
|
||||||
|
|
||||||
(0..10000).for_each(|i| {
|
for deb822_source in unofficial_deb822_sources {
|
||||||
unofficial_sources_list_store.append(&BoxedAnyObject::new(Row2 {
|
unofficial_sources_list_store.append(&BoxedAnyObject::new(AptSourceConfig::DEB822(deb822_source)));
|
||||||
col1: format!("col1 {i}"),
|
};
|
||||||
col2: format!("col2 {i}"),
|
|
||||||
}))
|
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));
|
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)
|
.model(&unofficial_sources_selection_model)
|
||||||
.build();
|
.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::<gtk::ListItem>().unwrap();
|
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||||
let row = Label::default();
|
let row = Label::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.build();
|
||||||
item.set_child(Some(&row));
|
item.set_child(Some(&row));
|
||||||
});
|
});
|
||||||
|
|
||||||
col1factory.connect_bind(move |_factory, item| {
|
unofficial_sources_columnview_factory0.connect_bind(move |_factory, item| {
|
||||||
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
let item: &ListItem = item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||||
let child = item.child().and_downcast::<Label>().unwrap();
|
let child = item.child().and_downcast::<Label>().unwrap();
|
||||||
let entry = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
let entry: BoxedAnyObject = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
||||||
let r: Ref<Row2> = entry.borrow();
|
let entry_borrow = entry.borrow::<AptSourceConfig>();
|
||||||
child.set_label(&r.col1.to_string());
|
let repo_name = match entry_borrow.deref() {
|
||||||
|
AptSourceConfig::DEB822(src) => {
|
||||||
|
match &src.repolib_name {
|
||||||
|
Some(name) => name,
|
||||||
|
None => match(&src.uris, &src.suites, &src.components) {
|
||||||
|
(Some(uris),Some(suites),Some(components)) => {
|
||||||
|
&format!("{} {} {}", uris, suites, components)
|
||||||
|
}
|
||||||
|
(_,_,_) => {
|
||||||
|
&t!("apt_source_parse_error").to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AptSourceConfig::Legacy(src) => {
|
||||||
|
&format!("{} {} {} {}",
|
||||||
|
if src.is_source {
|
||||||
|
"(Legacy Src)"
|
||||||
|
} else {
|
||||||
|
"(Legacy)"
|
||||||
|
},
|
||||||
|
&src.url,
|
||||||
|
&src.suite,
|
||||||
|
&src.components
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
child.set_label(&repo_name);
|
||||||
});
|
});
|
||||||
col2factory.connect_setup(move |_factory, item| {
|
|
||||||
|
let unofficial_sources_columnview_col0 = gtk::ColumnViewColumn::builder()
|
||||||
|
.title(t!("unofficial_sources_columnview_col0_title"))
|
||||||
|
.factory(&unofficial_sources_columnview_factory0)
|
||||||
|
.expand(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
let unofficial_sources_columnview_factory1 = gtk::SignalListItemFactory::new();
|
||||||
|
|
||||||
|
unofficial_sources_columnview_factory1.connect_setup(move |_factory, item| {
|
||||||
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||||
let row = Label::default();
|
let row = Label::builder()
|
||||||
|
.halign(Align::Start)
|
||||||
|
.build();
|
||||||
item.set_child(Some(&row));
|
item.set_child(Some(&row));
|
||||||
});
|
});
|
||||||
|
|
||||||
col2factory.connect_bind(move |_factory, item| {
|
unofficial_sources_columnview_factory1.connect_bind(move |_factory, item| {
|
||||||
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
let item: &ListItem = item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||||
let child = item.child().and_downcast::<Label>().unwrap();
|
let child = item.child().and_downcast::<Label>().unwrap();
|
||||||
let entry = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
let entry: BoxedAnyObject = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
||||||
let r: Ref<Row2> = entry.borrow();
|
let entry_borrow = entry.borrow::<AptSourceConfig>();
|
||||||
child.set_label(&r.col2.to_string());
|
let repo_enabled = match entry_borrow.deref() {
|
||||||
|
AptSourceConfig::DEB822(src) => {
|
||||||
|
match &src.enabled {
|
||||||
|
Some(t) => match t.to_lowercase().as_str() {
|
||||||
|
"yes" => true,
|
||||||
|
"true" => true,
|
||||||
|
"no" => false,
|
||||||
|
"false" => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AptSourceConfig::Legacy(src) => {
|
||||||
|
src.enabled
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if repo_enabled {
|
||||||
|
child.set_label(&t!("apt_repo_enabled"));
|
||||||
|
} else {
|
||||||
|
child.set_label(&t!("apt_repo_disabled"));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
let col1: ColumnViewColumn = gtk::ColumnViewColumn::new(Some("Column 1"), Some(col1factory));
|
|
||||||
let col2 = gtk::ColumnViewColumn::new(Some("Column 2"), Some(col2factory));
|
let unofficial_sources_columnview_col1 = gtk::ColumnViewColumn::builder()
|
||||||
col1.set_expand(true);
|
.title(t!("unofficial_sources_columnview_col1_title"))
|
||||||
|
.factory(&unofficial_sources_columnview_factory1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
unofficial_sources_selection_model.connect_selected_item_notify(|selection| {
|
unofficial_sources_selection_model.connect_selected_item_notify(|selection| {
|
||||||
let selection = selection.selected_item().unwrap();
|
let selection = selection.selected_item().unwrap();
|
||||||
let entry = selection.downcast_ref::<BoxedAnyObject>().unwrap();
|
let entry = selection.downcast_ref::<BoxedAnyObject>().unwrap();
|
||||||
let r: Ref<Row2> = entry.borrow();
|
//let r: Ref<AptSourceConfig> = entry.borrow();
|
||||||
println!("{}", r.col2.to_string())
|
//println!("{}", r.col2.to_string())
|
||||||
});
|
});
|
||||||
unofficial_sources_columnview.append_column(&col1);
|
unofficial_sources_columnview.append_column(&unofficial_sources_columnview_col0);
|
||||||
unofficial_sources_columnview.append_column(&col2);
|
unofficial_sources_columnview.append_column(&unofficial_sources_columnview_col1);
|
||||||
|
|
||||||
let unofficial_sources_boxedlist = ListBox::builder()
|
let unofficial_sources_boxedlist = ListBox::builder()
|
||||||
.selection_mode(SelectionMode::None)
|
.selection_mode(SelectionMode::None)
|
||||||
|
Loading…
Reference in New Issue
Block a user