sysd-manager 2.19.4

Application to empower user to manage their <b>systemd units</b> via Graphical User Interface. Not only are you able to make changes to the enablement and running status of each of the units, but you will also be able to view and modify their unit files and check the journal logs.
use crate::widget::{
    unit_list::{column::SysdColumn, menus::create_col_menu},
    unit_properties_selector::{data_browser::PropertyBrowseItem, save::UnitColumn},
};
use adw::subclass::prelude::ObjectSubclassIsExt;
use gtk::glib::{self};
use std::collections::HashSet;
use tracing::info;

glib::wrapper! {
    pub struct UnitPropertySelection(ObjectSubclass<imp2::UnitPropertySelectionImpl>)    ;
}

impl UnitPropertySelection {
    pub fn from_browser(broswer_property: PropertyBrowseItem) -> Self {
        let interface = broswer_property.interface();
        let unit_property = broswer_property.unit_property();
        let sign = broswer_property.signature();

        println!("{interface} {unit_property} {sign:?}");
        let sysd_col = SysdColumn::new_from_props(&unit_property, &interface, sign);
        println!(" {sysd_col:?}");

        let col = if let Some(col) = broswer_property.column() {
            info!("COL {:?} {:?}", col.id(), col.title());
            col
        } else {
            let menu = create_col_menu(&sysd_col);

            let col = gtk::ColumnViewColumn::builder()
                .title(sysd_col.property())
                .id(sysd_col.id())
                .header_menu(&menu)
                .resizable(true)
                .build();
            info!("New COL {:?} {:?}", col.id(), col.title());
            col
        };

        let this_object = Self::from_column_view_column(col, sysd_col);
        let p_imp = this_object.imp();
        p_imp.access.replace(broswer_property.access());
        this_object
    }

    pub fn from_column_view_column(column: gtk::ColumnViewColumn, sysd_col: SysdColumn) -> Self {
        let this_object: Self = glib::Object::new();

        let p_imp = this_object.imp();

        p_imp.column.replace(column);
        p_imp.sysd_column.replace(Some(sysd_col));

        this_object
    }

    // fn fill_from_id(p_imp: &imp2::UnitPropertySelectionImpl, id: &str) {
    //     let custom_id: SysdColumn = (id, None).into();
    //     p_imp.unit_property.replace(custom_id.id().to_string());
    //     p_imp.sysd_column.replace(Some(custom_id));

    //     debug!("UNIT TYPE FROM ID {} ", id);
    // }

    pub fn from_column_config(unit_column_config: UnitColumn) -> Self {
        let col = match SysdColumn::verify(&unit_column_config) {
            Ok(sc) => sc,
            Err(e) => e.1,
        };
        Self::from_column_config2(unit_column_config, col)
    }

    pub fn from_column_config2(unit_column_config: UnitColumn, sysd_col: SysdColumn) -> Self {
        let title = unit_column_config
            .title
            .unwrap_or(sysd_col.property().to_owned());

        let column = gtk::ColumnViewColumn::builder()
            .id(sysd_col.id())
            .fixed_width(unit_column_config.fixed_width)
            .expand(unit_column_config.expands)
            .resizable(unit_column_config.resizable)
            .visible(unit_column_config.visible)
            .title(title)
            // .sorter(&unit_column_config.sort)
            .build();

        let column_menu = create_col_menu(&sysd_col);
        column.set_header_menu(Some(&column_menu));
        let this_object = Self::from_column_view_column(column, sysd_col);

        //TODO simplify
        this_object.set_sort(unit_column_config.sort.unwrap_or_default());

        this_object
    }

    // pub fn from_column(column_name: String) -> Self {
    //     let this_object: Self = glib::Object::new();

    //     let p_imp = this_object.imp();

    //     p_imp.unit_property.replace(column_name);

    //     this_object
    // }

    pub fn is_custom(&self) -> bool {
        self.imp().is_custom()
    }

    pub fn copy(&self) -> Self {
        let this_object: Self = glib::Object::new();
        self.copy_to(&this_object);

        this_object
    }

    pub fn copy_to(&self, to: &Self) {
        let p_imp = to.imp();

        // p_imp.unit_property.replace(self.unit_property());
        // p_imp.prop_type.replace(self.prop_type());
        p_imp.access.replace(self.access());
        // p_imp.unit_type.set(self.unit_type());

        p_imp.sysd_column.replace(self.sysd_column());
        {
            let col = self.column();
            let cur_col = p_imp.column.borrow();

            Self::copy_col_to_col(&col, &cur_col);
        }
    }

    pub fn copy_col_to_col(from: &gtk::ColumnViewColumn, to: &gtk::ColumnViewColumn) {
        to.set_expand(from.expands());
        to.set_factory(from.factory().as_ref());
        to.set_fixed_width(from.fixed_width());
        to.set_header_menu(from.header_menu().as_ref());
        to.set_id(from.id().as_deref());
        to.set_resizable(from.is_resizable());
        to.set_sorter(from.sorter().as_ref());
        to.set_title(from.title().as_deref());
        to.set_visible(from.is_visible());
    }

    pub fn fill_property_fetcher(&self, property_list_send: &mut HashSet<SysdColumn>) {
        if let Some(col) = self.sysd_column()
            && !matches!(col, SysdColumn::FullName | SysdColumn::Active)
        {
            property_list_send.insert(col);
        }
    }

    pub fn sysd_column(&self) -> Option<SysdColumn> {
        self.imp().sysd_column()
    }

    pub fn prop_type(&self) -> Option<String> {
        self.imp().prop_type()
    }

    pub fn unit_property(&self) -> String {
        self.imp().unit_property()
    }
}

mod imp2 {
    use std::cell::{Cell, RefCell};

    use glib::GString;
    use gtk::{glib, prelude::*, subclass::prelude::*};

    use crate::{
        systemd::enums::UnitType,
        widget::{
            unit_list::{column::SysdColumn, get_clean_col_title},
            unit_properties_selector::save::SortType,
        },
    };

    #[derive(Debug, glib::Properties, Default)]
    #[properties(wrapper_type = super::UnitPropertySelection)]
    pub struct UnitPropertySelectionImpl {
        /*         #[property(get)]
        pub(super) interface: RefCell<String>, */
        // #[property(get)]
        // pub(super) unit_property: RefCell<String>,
        // #[property(get)]
        // pub(super) prop_type: RefCell<Option<String>>,
        #[property(get)]
        pub(super) access: RefCell<Option<String>>,
        #[property(name = "visible", get= Self::visible, set= Self::set_visible, type = bool)]
        #[property(name = "id", get= Self::id, set= Self::set_id, type = Option<GString>)]
        #[property(name = "title", get=Self::title, set=Self::set_title, type = Option<String>)]
        #[property(name = "fixed-width", get= Self::fixed_width, set= Self::set_fixed_width, type = i32)]
        #[property(name = "resizable", get= Self::resizable, set= Self::set_resizable, type = bool)]
        #[property(name = "expands", get= Self::expands, set= Self::set_expand, type = bool)]
        #[property(get, set)]
        pub(super) column: RefCell<gtk::ColumnViewColumn>,

        #[property(name = "interface", get= Self::interface, type = String)]
        // #[property(get, default)]
        // pub(super) unit_type: Cell<UnitType>,
        #[property(get, set, default)]
        pub(super) sort: Cell<SortType>,

        pub(super) sysd_column: RefCell<Option<SysdColumn>>,
    }

    impl UnitPropertySelectionImpl {
        pub fn is_custom(&self) -> bool {
            self.sysd_column
                .borrow()
                .as_ref()
                .map(|s| s.is_custom())
                .unwrap_or(true)
        }

        fn interface(&self) -> String {
            self.unit_type().interface().to_string()
        }

        fn visible(&self) -> bool {
            self.column.borrow().is_visible()
        }

        fn set_visible(&self, visible: bool) {
            self.column.borrow().set_visible(visible)
        }

        fn id(&self) -> Option<GString> {
            self.column.borrow().id()
        }

        fn set_id(&self, id: Option<&str>) {
            self.column.borrow().set_id(id)
        }

        fn title(&self) -> Option<String> {
            self.column
                .borrow()
                .title()
                .map(|t| get_clean_col_title(t.as_str()))
        }

        fn set_title(&self, title: Option<&str>) {
            self.column.borrow().set_title(title)
        }

        fn fixed_width(&self) -> i32 {
            self.column.borrow().fixed_width()
        }

        fn set_fixed_width(&self, fixed_width: i32) {
            self.column.borrow().set_fixed_width(fixed_width);
        }

        fn resizable(&self) -> bool {
            self.column.borrow().is_resizable()
        }

        fn set_resizable(&self, resizable: bool) {
            self.column.borrow().set_resizable(resizable)
        }

        fn expands(&self) -> bool {
            self.column.borrow().expands()
        }

        fn set_expand(&self, expand: bool) {
            self.column.borrow().set_expand(expand)
        }

        pub fn sysd_column(&self) -> Option<SysdColumn> {
            self.sysd_column.borrow().as_ref().cloned()
        }

        fn unit_type(&self) -> UnitType {
            self.sysd_column
                .borrow()
                .as_ref()
                .map(|s| s.utype())
                .unwrap_or(UnitType::Unknown)
        }

        pub(crate) fn prop_type(&self) -> Option<String> {
            self.sysd_column
                .borrow()
                .as_ref()
                .and_then(|s| s.property_type().clone())
        }

        pub(crate) fn unit_property(&self) -> String {
            self.sysd_column
                .borrow()
                .as_ref()
                .map(|s| s.property().to_owned())
                .unwrap_or_default()
        }
    }

    #[glib::object_subclass]
    impl ObjectSubclass for UnitPropertySelectionImpl {
        const NAME: &'static str = "UnitPropertySelection";
        type Type = super::UnitPropertySelection;
    }

    #[glib::derived_properties]
    impl ObjectImpl for UnitPropertySelectionImpl {}
    impl UnitPropertySelectionImpl {}
}