filter based on app names or category
This commit is contained in:
parent
9d3be77538
commit
3779b7ec5e
4 changed files with 84 additions and 24 deletions
|
|
@ -2,6 +2,7 @@ use gtk::glib;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use gtk4 as gtk;
|
use gtk4 as gtk;
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
use gtk::CompositeTemplate;
|
use gtk::CompositeTemplate;
|
||||||
|
|
||||||
|
|
@ -12,6 +13,7 @@ pub struct GridItem {
|
||||||
pub name: TemplateChild<gtk::Label>,
|
pub name: TemplateChild<gtk::Label>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub image: TemplateChild<gtk::Image>,
|
pub image: TemplateChild<gtk::Image>,
|
||||||
|
pub index: Cell<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ use gtk::subclass::prelude::*;
|
||||||
use gtk::{gio, glib};
|
use gtk::{gio, glib};
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct GridItem(ObjectSubclass<imp::GridItem>)
|
pub struct GridItem(ObjectSubclass<imp::GridItem>)
|
||||||
@extends gtk::Widget, gtk::Box;
|
@extends gtk::Widget, gtk::Box,
|
||||||
|
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GridItem {
|
impl Default for GridItem {
|
||||||
|
|
@ -40,11 +41,15 @@ impl GridItem {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Ok(icon) = app_group.property("icon") {
|
if let Ok(icon) = app_group.property("icon") {
|
||||||
&self_.image.set_from_icon_name(Some(
|
self_.image.set_from_icon_name(Some(
|
||||||
&icon
|
&icon
|
||||||
.get::<String>()
|
.get::<String>()
|
||||||
.expect("Property name needs to be a 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;
|
mod imp;
|
||||||
use crate::app_group::AppGroup;
|
use crate::app_group::AppGroup;
|
||||||
use crate::app_group::AppGroupData;
|
use crate::app_group::AppGroupData;
|
||||||
|
use glib::FromVariant;
|
||||||
|
use glib::Variant;
|
||||||
use gtk4 as gtk;
|
use gtk4 as gtk;
|
||||||
|
use gtk4::Button;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::grid_item::GridItem;
|
use crate::grid_item::GridItem;
|
||||||
|
|
@ -127,13 +130,21 @@ impl Window {
|
||||||
app_names: Vec::new(),
|
app_names: Vec::new(),
|
||||||
category: "Utility".to_string(),
|
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()
|
.iter()
|
||||||
.for_each(|group| {
|
.for_each(|group| {
|
||||||
group_model.append(group);
|
group_model.append(group);
|
||||||
});
|
});
|
||||||
imp.group_grid_view
|
let group_selection = gtk4::SingleSelection::new(Some(&group_model));
|
||||||
.set_model(Some(>k4::SingleSelection::new(Some(&group_model))));
|
imp.group_grid_view.set_model(Some(&group_selection));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_callbacks(&self) {
|
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
|
// 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| {
|
group_grid_view.connect_activate(glib::clone!(@weak app_filter_model => move |grid_view, position| {
|
||||||
let model = grid_view.model().unwrap();
|
let model = grid_view.model().unwrap();
|
||||||
|
|
@ -196,16 +206,27 @@ impl Window {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.downcast::<AppGroup>()
|
.downcast::<AppGroup>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let category: String;
|
let category =
|
||||||
if let Ok(category_prop) = app_info.property("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 {
|
} 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 new_filter: gtk::CustomFilter = gtk::CustomFilter::new(move |obj| {
|
||||||
let app = obj
|
let app = obj
|
||||||
.downcast_ref::<gio::DesktopAppInfo>()
|
.downcast_ref::<gio::DesktopAppInfo>()
|
||||||
.expect("The Object needs to be of type AppInfo");
|
.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() {
|
match app.categories() {
|
||||||
Some(categories) => categories.to_string().to_lowercase().contains(&category),
|
Some(categories) => categories.to_string().to_lowercase().contains(&category),
|
||||||
None => false,
|
None => false,
|
||||||
|
|
@ -213,6 +234,35 @@ impl Window {
|
||||||
});
|
});
|
||||||
group_filter_model.set_filter(Some(new_filter).as_ref());
|
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(
|
entry.connect_changed(
|
||||||
glib::clone!(@weak app_filter_model, @weak sorted_model => move |search: >k::SearchEntry| {
|
glib::clone!(@weak app_filter_model, @weak sorted_model => move |search: >k::SearchEntry| {
|
||||||
|
|
@ -289,20 +339,23 @@ impl Window {
|
||||||
item.set_child(Some(&row));
|
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);
|
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();
|
let group_factory = SignalListItemFactory::new();
|
||||||
group_factory.connect_setup(move |_factory, item| {
|
group_factory.connect_setup(move |_factory, item| {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
<object class="GtkGridView" id="group_grid_view">
|
<object class="GtkGridView" id="group_grid_view">
|
||||||
<property name="min-columns">8</property>
|
<property name="min-columns">8</property>
|
||||||
<property name="max-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>
|
<property name="enable-rubberband">false</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue