From 877a6c442551501a529badde4d1462003ff0fc36 Mon Sep 17 00:00:00 2001 From: Marcus Behrendt Date: Fri, 11 Oct 2024 17:41:42 +0200 Subject: [PATCH 1/6] revert(container-row): Inherit from `AdwActionRow` This reverts commit 3dc7b2102651f62b5b36e6100ef431b9d7b41fdf. The reason is that we need to make the container rows selectable again, as we offer the option of switching between grid and list mode. --- src/view/container_row.rs | 164 ++++++++++++++++++++++++++++++++------ src/view/container_row.ui | 152 ++++++++++++++++++++++++++++------- 2 files changed, 265 insertions(+), 51 deletions(-) diff --git a/src/view/container_row.rs b/src/view/container_row.rs index 36d65c8a..15901e86 100644 --- a/src/view/container_row.rs +++ b/src/view/container_row.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; + use adw::prelude::*; use adw::subclass::prelude::*; use gettextrs::gettext; @@ -8,6 +10,7 @@ use gtk::glib; use gtk::CompositeTemplate; use crate::model; +use crate::model::prelude::*; use crate::utils; use crate::view; use crate::widget; @@ -19,30 +22,42 @@ mod imp { #[properties(wrapper_type = super::ContainerRow)] #[template(resource = "/com/github/marhkb/Pods/ui/view/container_row.ui")] pub(crate) struct ContainerRow { + pub(super) bindings: RefCell>, #[property(get, set, construct, nullable)] pub(super) container: glib::WeakRef, #[template_child] pub(super) spinner: TemplateChild, - // #[template_child] - // pub(super) name_label: TemplateChild, - // #[template_child] - // pub(super) repo_label: TemplateChild, + #[template_child] + pub(super) check_button_revealer: TemplateChild, + #[template_child] + pub(super) check_button: TemplateChild, + #[template_child] + pub(super) name_label: TemplateChild, + #[template_child] + pub(super) pod_image: TemplateChild, + #[template_child] + pub(super) repo_label: TemplateChild, + #[template_child] + pub(super) ports_flow_box: TemplateChild, #[template_child] pub(super) stats_box: TemplateChild, #[template_child] pub(super) cpu_bar: TemplateChild, #[template_child] pub(super) mem_bar: TemplateChild, + #[template_child] + pub(super) end_box_revealer: TemplateChild, } #[glib::object_subclass] impl ObjectSubclass for ContainerRow { const NAME: &'static str = "PdsContainerRow"; type Type = super::ContainerRow; - type ParentType = adw::ActionRow; + type ParentType = gtk::ListBoxRow; fn class_init(klass: &mut Self::Class) { klass.bind_template(); + klass.bind_template_callbacks(); klass.install_action("container-row.activate", None, |widget, _, _| { widget.activate(); @@ -76,9 +91,20 @@ mod imp { let container_list_expr = container_expr.chain_property::("container-list"); + let selection_mode_expr = + container_list_expr.chain_property::("selection-mode"); + + selection_mode_expr.bind(&*self.check_button_revealer, "reveal-child", Some(obj)); + selection_mode_expr + .chain_closure::(closure!(|_: Self::Type, is_selection_mode: bool| { + !is_selection_mode + })) + .bind(&*self.end_box_revealer, "reveal-child", Some(obj)); + let status_expr = container_expr.chain_property::("status"); let health_status_expr = container_expr.chain_property::("health-status"); + let pod_expr = container_expr.chain_property::("pod"); let stats_expr = container_expr.chain_property::("stats"); container_expr @@ -137,14 +163,33 @@ mod imp { } }), ) - .bind(obj, "title", Some(obj)); + .bind(&*self.name_label, "label", Some(obj)); + + pod_expr + .chain_closure::(closure!( + |_: Self::Type, pod: Option| pod.is_some() + )) + .bind(&*self.pod_image, "visible", Some(obj)); + + gtk::ClosureExpression::new::( + [ + &pod_expr, + &container_expr + .chain_property::("ports") + .chain_property::("len"), + ], + closure!(|_: Self::Type, pod: Option<&model::Pod>, len: u32| { + pod.is_none() && len > 0 + }), + ) + .bind(&*self.ports_flow_box, "visible", Some(obj)); container_expr .chain_property::("image-name") .chain_closure::(closure!(|_: Self::Type, name: Option| { utils::escape(&utils::format_option(name)) })) - .bind(obj, "subtitle", Some(obj)); + .bind(&*self.repo_label, "label", Some(obj)); status_expr .chain_closure::(closure!( @@ -194,13 +239,78 @@ mod imp { impl WidgetImpl for ContainerRow {} impl ListBoxRowImpl for ContainerRow {} - impl PreferencesRowImpl for ContainerRow {} - impl ActionRowImpl for ContainerRow {} + + #[gtk::template_callbacks] + impl ContainerRow { + #[template_callback] + fn on_notify_container(&self) { + let mut bindings = self.bindings.borrow_mut(); + while let Some(binding) = bindings.pop() { + binding.unbind(); + } + + let obj = &*self.obj(); + + if let Some(container) = obj.container() { + let binding = container + .bind_property("selected", &*self.check_button, "active") + .flags(glib::BindingFlags::SYNC_CREATE | glib::BindingFlags::BIDIRECTIONAL) + .build(); + + bindings.push(binding); + + if !container.has_pod() { + self.ports_flow_box.bind_model( + Some(&container.ports()), + clone!(@weak obj => @default-panic, move |item| { + let port_mapping = + item.downcast_ref::().unwrap(); + + let label = gtk::Label::builder() + .css_classes([ + "status-badge-small", + "numeric", + ]) + .halign(gtk::Align::Center) + .label(format!( + "{}/{}", + port_mapping.host_port(), + port_mapping.protocol() + )) + .build(); + + let css_classes = utils::css_classes(&label); + super::ContainerRow::this_expression("container") + .chain_property::("status") + .chain_closure::>(closure!( + |_: super::ContainerRow, status: model::ContainerStatus| { + css_classes + .iter() + .cloned() + .chain(Some(String::from( + super::super::container_status_css_class(status) + ))) + .collect::>() + } + )) + .bind(&label, "css-classes", Some(&obj)); + + gtk::FlowBoxChild::builder() + .halign(gtk::Align::Start) + .child(&label) + .build() + .upcast() + }), + ); + } + } + } + } } glib::wrapper! { pub(crate) struct ContainerRow(ObjectSubclass) - @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow, + @extends gtk::Widget, gtk::ListBoxRow, @implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget; } @@ -248,19 +358,27 @@ impl ContainerRow { fn activate(&self) { if let Some(container) = self.container().as_ref() { - let nav_page = adw::NavigationPage::builder() - .child(&view::ContainerDetailsPage::from(container)) - .build(); - - Self::this_expression("container") - .chain_property::("name") - .chain_closure::(closure!(|_: Self, name: &str| gettext!( - "Container {}", - name - ))) - .bind(&nav_page, "title", Some(self)); - - utils::navigation_view(self).push(&nav_page); + if container + .container_list() + .map(|list| list.is_selection_mode()) + .unwrap_or(false) + { + container.select(); + } else { + let nav_page = adw::NavigationPage::builder() + .child(&view::ContainerDetailsPage::from(container)) + .build(); + + Self::this_expression("container") + .chain_property::("name") + .chain_closure::(closure!(|_: Self, name: &str| gettext!( + "Container {}", + name + ))) + .bind(&nav_page, "title", Some(self)); + + utils::navigation_view(self).push(&nav_page); + } } } } diff --git a/src/view/container_row.ui b/src/view/container_row.ui index 15fe8715..5045e163 100644 --- a/src/view/container_row.ui +++ b/src/view/container_row.ui @@ -1,30 +1,28 @@ -