filter based on app names or category
This commit is contained in:
parent
a66c017035
commit
d05f517366
4 changed files with 84 additions and 24 deletions
|
|
@ -2,6 +2,7 @@ use gtk::glib;
|
|||
use gtk::prelude::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk4 as gtk;
|
||||
use std::cell::Cell;
|
||||
|
||||
use gtk::CompositeTemplate;
|
||||
|
||||
|
|
@ -12,6 +13,7 @@ pub struct GridItem {
|
|||
pub name: TemplateChild<gtk::Label>,
|
||||
#[template_child]
|
||||
pub image: TemplateChild<gtk::Image>,
|
||||
pub index: Cell<u32>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ use gtk::subclass::prelude::*;
|
|||
use gtk::{gio, glib};
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct GridItem(ObjectSubclass<imp::GridItem>)
|
||||
@extends gtk::Widget, gtk::Box;
|
||||
pub struct GridItem(ObjectSubclass<imp::GridItem>)
|
||||
@extends gtk::Widget, gtk::Box,
|
||||
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
|
||||
}
|
||||
|
||||
impl Default for GridItem {
|
||||
|
|
@ -40,11 +41,15 @@ impl GridItem {
|
|||
);
|
||||
}
|
||||
if let Ok(icon) = app_group.property("icon") {
|
||||
&self_.image.set_from_icon_name(Some(
|
||||
self_.image.set_from_icon_name(Some(
|
||||
&icon
|
||||
.get::<String>()
|
||||
.expect("Property name needs to be a String."),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_index(&self, index: u32) {
|
||||
imp::GridItem::from_instance(self).index.set(index);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
mod imp;
|
||||
use crate::app_group::AppGroup;
|
||||
use crate::app_group::AppGroupData;
|
||||
use glib::FromVariant;
|
||||
use glib::Variant;
|
||||
use gtk4 as gtk;
|
||||
use gtk4::Button;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::grid_item::GridItem;
|
||||
|
|
@ -127,13 +130,21 @@ impl Window {
|
|||
app_names: Vec::new(),
|
||||
category: "Utility".to_string(),
|
||||
}),
|
||||
AppGroup::new(AppGroupData {
|
||||
id: 0,
|
||||
name: "Web".to_string(),
|
||||
icon: "folder".to_string(),
|
||||
mutable: true,
|
||||
app_names: vec!["Firefox Web Browser".to_string()],
|
||||
category: "".to_string(),
|
||||
}),
|
||||
]
|
||||
.iter()
|
||||
.for_each(|group| {
|
||||
group_model.append(group);
|
||||
});
|
||||
imp.group_grid_view
|
||||
.set_model(Some(>k4::SingleSelection::new(Some(&group_model))));
|
||||
let group_selection = gtk4::SingleSelection::new(Some(&group_model));
|
||||
imp.group_grid_view.set_model(Some(&group_selection));
|
||||
}
|
||||
|
||||
fn setup_callbacks(&self) {
|
||||
|
|
@ -187,7 +198,6 @@ impl Window {
|
|||
}
|
||||
});
|
||||
|
||||
// TODO connect to custom signal from app group grid item activation
|
||||
// on activation change the group filter model to use the app names, and category
|
||||
group_grid_view.connect_activate(glib::clone!(@weak app_filter_model => move |grid_view, position| {
|
||||
let model = grid_view.model().unwrap();
|
||||
|
|
@ -196,16 +206,27 @@ impl Window {
|
|||
.unwrap()
|
||||
.downcast::<AppGroup>()
|
||||
.unwrap();
|
||||
let category: String;
|
||||
let category =
|
||||
if let Ok(category_prop) = app_info.property("category") {
|
||||
category = category_prop.get::<String>().unwrap_or("".to_string()).to_lowercase();
|
||||
category_prop.get::<String>().unwrap_or("".to_string()).to_lowercase()
|
||||
} else {
|
||||
category = "".to_string();
|
||||
}
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let app_names =
|
||||
if let Ok(app_names_prop) = app_info.property("appnames") {
|
||||
<Vec<String>>::from_variant(&app_names_prop.get::<Variant>().expect("appnames nneds to be a variant.")).unwrap_or_default()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
dbg!(&app_names);
|
||||
let new_filter: gtk::CustomFilter = gtk::CustomFilter::new(move |obj| {
|
||||
let app = obj
|
||||
.downcast_ref::<gio::DesktopAppInfo>()
|
||||
.expect("The Object needs to be of type AppInfo");
|
||||
if app_names.len() > 0 {
|
||||
return app_names.contains(&String::from(app.name().as_str()));
|
||||
}
|
||||
match app.categories() {
|
||||
Some(categories) => categories.to_string().to_lowercase().contains(&category),
|
||||
None => false,
|
||||
|
|
@ -213,6 +234,35 @@ impl Window {
|
|||
});
|
||||
group_filter_model.set_filter(Some(new_filter).as_ref());
|
||||
}));
|
||||
// can't listen to select signal on grid view, but this a good to know example...
|
||||
// if group_grid_view.connect_local("select", true, glib::clone!(@weak group_filter_model => @default-return None, move |args| {
|
||||
// let grid_view = args[0].get::<gtk::GridView>().unwrap();
|
||||
// let position = args[1].get::<u32>().unwrap();
|
||||
// // on activation change the group filter model to use the app names, and category
|
||||
// let model = grid_view.model().unwrap();
|
||||
// let app_info = model
|
||||
// .item(position)
|
||||
// .unwrap()
|
||||
// .downcast::<AppGroup>()
|
||||
// .unwrap();
|
||||
// let category: String;
|
||||
// if let Ok(category_prop) = app_info.property("category") {
|
||||
// category = category_prop.get::<String>().unwrap_or("".to_string()).to_lowercase();
|
||||
// } else {
|
||||
// category = "".to_string();
|
||||
// }
|
||||
// let new_filter: gtk::CustomFilter = gtk::CustomFilter::new(move |obj| {
|
||||
// let app = obj
|
||||
// .downcast_ref::<gio::DesktopAppInfo>()
|
||||
// .expect("The Object needs to be of type AppInfo");
|
||||
// match app.categories() {
|
||||
// Some(categories) => categories.to_string().to_lowercase().contains(&category),
|
||||
// None => false,
|
||||
// }
|
||||
// });
|
||||
// group_filter_model.set_filter(Some(new_filter).as_ref());
|
||||
// None
|
||||
// })).is_err() { println!("Failed to connect to grid view select...") };
|
||||
|
||||
entry.connect_changed(
|
||||
glib::clone!(@weak app_filter_model, @weak sorted_model => move |search: >k::SearchEntry| {
|
||||
|
|
@ -289,20 +339,23 @@ impl Window {
|
|||
item.set_child(Some(&row));
|
||||
});
|
||||
|
||||
// the bind stage is used for "binding" the data to the created widgets on the "setup" stage
|
||||
app_factory.connect_bind(move |_factory, grid_item| {
|
||||
let app_info = grid_item
|
||||
.item()
|
||||
.unwrap()
|
||||
.downcast::<gio::DesktopAppInfo>()
|
||||
.unwrap();
|
||||
|
||||
let child = grid_item.child().unwrap().downcast::<GridItem>().unwrap();
|
||||
child.set_app_info(&app_info);
|
||||
});
|
||||
// Set the factory of the list view
|
||||
let imp = imp::Window::from_instance(self);
|
||||
imp.app_grid_view.set_factory(Some(&app_factory));
|
||||
// the bind stage is used for "binding" the data to the created widgets on the "setup" stage
|
||||
let app_grid_view = &imp.app_grid_view.get();
|
||||
app_factory.connect_bind(
|
||||
glib::clone!(@weak app_grid_view => move |_factory, grid_item| {
|
||||
let app_info = grid_item
|
||||
.item()
|
||||
.unwrap()
|
||||
.downcast::<gio::DesktopAppInfo>()
|
||||
.unwrap();
|
||||
|
||||
let child = grid_item.child().unwrap().downcast::<GridItem>().unwrap();
|
||||
child.set_app_info(&app_info);
|
||||
}),
|
||||
);
|
||||
// Set the factory of the list view
|
||||
app_grid_view.set_factory(Some(&app_factory));
|
||||
|
||||
let group_factory = SignalListItemFactory::new();
|
||||
group_factory.connect_setup(move |_factory, item| {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
<object class="GtkGridView" id="group_grid_view">
|
||||
<property name="min-columns">8</property>
|
||||
<property name="max-columns">8</property>
|
||||
<property name="single-click-activate">false</property>
|
||||
<property name="single-click-activate">true</property>
|
||||
<property name="enable-rubberband">false</property>
|
||||
</object>
|
||||
</child>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue