select all, deselect all button

This commit is contained in:
Ward from fusion-voyager-3 2024-07-07 03:08:14 +03:00
parent a84bf4efdc
commit 8ec3ea1855
3 changed files with 119 additions and 26 deletions

View File

@ -9,6 +9,7 @@
<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$/.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_update_page/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/apt_update_page/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" />
@ -107,7 +108,8 @@
<workItem from="1719847278228" duration="8841000" /> <workItem from="1719847278228" duration="8841000" />
<workItem from="1719872581190" duration="4000" /> <workItem from="1719872581190" duration="4000" />
<workItem from="1720090281244" duration="5582000" /> <workItem from="1720090281244" duration="5582000" />
<workItem from="1720289925469" duration="5474000" /> <workItem from="1720289925469" duration="7265000" />
<workItem from="1720301553869" duration="6532000" />
</task> </task>
<servers /> <servers />
</component> </component>

View File

@ -33,6 +33,8 @@ pub struct AptPackageRow {
package_size: RefCell<u64>, package_size: RefCell<u64>,
#[property(get, set)] #[property(get, set)]
package_installed_size: RefCell<u64>, package_installed_size: RefCell<u64>,
#[property(get, set)]
package_marked: RefCell<bool>,
} }
// ANCHOR_END: custom_button // ANCHOR_END: custom_button
@ -50,7 +52,7 @@ impl ObjectSubclass for AptPackageRow {
impl ObjectImpl for AptPackageRow { impl ObjectImpl for AptPackageRow {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new(); static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
SIGNALS.get_or_init(|| vec![Signal::builder("row-deleted").build()]) SIGNALS.get_or_init(|| vec![Signal::builder("checkbutton-toggled").build(), Signal::builder("checkbutton-untoggled").build()])
} }
fn constructed(&self) { fn constructed(&self) {
let current_locale = match env::var_os("LANG") { let current_locale = match env::var_os("LANG") {
@ -96,11 +98,32 @@ impl ObjectImpl for AptPackageRow {
obj.add_prefix(&prefix_box); obj.add_prefix(&prefix_box);
obj.add_row(&expandable_box); obj.add_row(&expandable_box);
//let obj = self.obj(); let suffix_toggle = gtk::CheckButton::builder()
//obj.bind_property("package-name", &package_label, "label") .tooltip_text(t!("mark_for_update"))
// .sync_create() .halign(Align::Center)
// .bidirectional() .valign(Align::Center)
// .build(); .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 // Trait shared by all widgets

View File

@ -124,6 +124,35 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
.width_request(500) .width_request(500)
.build(); .build();
let bottom_bar = gtk::Box::builder()
.valign(Align::End)
.build();
let select_button = gtk::Button::builder()
.halign(Align::End)
.valign(Align::Center)
.hexpand(true)
.margin_start(10)
.margin_end(30)
.margin_top(2)
.margin_bottom(15)
.label(t!("select_button_deselect_all"))
.build();
select_button.connect_clicked(clone!(@weak select_button, @weak packages_boxedlist => move |_| {
let select_button_label = select_button.label().unwrap();
let value_to_mark = if select_button_label == t!("select_button_select_all").to_string() {
true
} else if select_button_label == t!("select_button_deselect_all").to_string() {
false
} else {
panic!("Unexpected label on selection button")
};
set_all_apt_row_marks_to(&packages_boxedlist, value_to_mark)
}));
bottom_bar.append(&select_button);
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 => async move {
@ -192,7 +221,7 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
get_upgradable_server_context.spawn_local( get_upgradable_server_context.spawn_local(
clone!(@weak packages_boxedlist => async move { clone!(@weak packages_boxedlist => 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 { let apt_row = AptPackageRow::new(AptPackageSocket {
name: state.name, name: state.name,
arch: state.arch, arch: state.arch,
installed_version: state.installed_version, installed_version: state.installed_version,
@ -203,15 +232,28 @@ 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,
is_last: state.is_last is_last: state.is_last
})); });
apt_row.connect_closure(
"checkbutton-toggled",
false,
closure_local!(@strong apt_row, @strong select_button, @strong packages_boxedlist => move |apt_row: AptPackageRow| {
if is_widget_select_all_ready(&packages_boxedlist) {
select_button.set_label(&t!("select_button_select_all").to_string())
} else {
select_button.set_label(&t!("select_button_deselect_all").to_string())
}
}),
);
apt_row.connect_closure(
"checkbutton-untoggled",
false,
closure_local!(@strong apt_row, @strong select_button, @strong packages_boxedlist => move |apt_row: AptPackageRow| {
select_button.set_label(&t!("select_button_select_all").to_string())
}),
);
packages_boxedlist.append(&apt_row);
if state.is_last { if state.is_last {
packages_boxedlist.set_sensitive(true); packages_boxedlist.set_sensitive(true);
let mut counter = packages_boxedlist.first_child();
while let Some(row) = counter {
let row_next_sibling = row.next_sibling();
row.downcast::<AptPackageRow>().unwrap().add_suffix(&gtk::Button::builder().label("gg").build());
counter = row_next_sibling;
}
} }
} }
}), }),
@ -238,11 +280,37 @@ pub fn apt_update_page(window: adw::ApplicationWindow) -> gtk::Box {
main_box.append(&searchbar); main_box.append(&searchbar);
main_box.append(&packages_viewport); main_box.append(&packages_viewport);
main_box.append(&bottom_bar);
apt_update_dialog.present(); apt_update_dialog.present();
main_box main_box
} }
fn is_widget_select_all_ready(parent_listbox: &impl IsA<ListBox>) -> bool {
let mut is_ready = false;
let mut child_counter = parent_listbox.borrow().first_child();
while let Some(child) = child_counter {
let next_child = child.next_sibling();
let downcast = child.downcast::<AptPackageRow>().unwrap();
if !downcast.package_marked() {
is_ready = true;
break
}
child_counter = next_child
}
is_ready
}
fn set_all_apt_row_marks_to(parent_listbox: &impl IsA<ListBox>, value: bool) {
let mut child_counter = parent_listbox.borrow().first_child();
while let Some(child) = child_counter {
let next_child = child.next_sibling();
let downcast = child.downcast::<AptPackageRow>().unwrap();
downcast.set_package_marked(value);
child_counter = next_child
}
}
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";