show active apps
This commit is contained in:
parent
ad6f147546
commit
03300c788a
9 changed files with 113 additions and 339 deletions
|
|
@ -1,213 +0,0 @@
|
|||
use glib::{FromVariant, ParamFlags, ParamSpec, ToVariant, Value, Variant, VariantTy};
|
||||
use gtk4::glib;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::subclass::prelude::*;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::ApplicationData;
|
||||
|
||||
// Object holding the state
|
||||
#[derive(Default)]
|
||||
pub struct ApplicationObject {
|
||||
data: Rc<RefCell<ApplicationData>>,
|
||||
}
|
||||
|
||||
// The central trait for subclassing a GObject
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ApplicationObject {
|
||||
const NAME: &'static str = "ApplicationObject";
|
||||
type Type = super::ApplicationObject;
|
||||
type ParentType = glib::Object;
|
||||
}
|
||||
|
||||
// Trait shared by all GObjects
|
||||
impl ObjectImpl for ApplicationObject {
|
||||
fn properties() -> &'static [ParamSpec] {
|
||||
static PROPERTIES: Lazy<Vec<ParamSpec>> = Lazy::new(|| {
|
||||
vec![
|
||||
ParamSpec::new_uint(
|
||||
// Name
|
||||
"id",
|
||||
// Nickname
|
||||
"id",
|
||||
// Short description
|
||||
"ID of application in launcher search result",
|
||||
0,
|
||||
u32::MAX,
|
||||
// Default value
|
||||
0,
|
||||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
ParamSpec::new_string(
|
||||
// Name
|
||||
"name",
|
||||
// Nickname
|
||||
"name",
|
||||
// Short description
|
||||
"Name of application in launcher search result",
|
||||
// Default value
|
||||
Some(""),
|
||||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
ParamSpec::new_string(
|
||||
// Name
|
||||
"description",
|
||||
// Nickname
|
||||
"description",
|
||||
// Short description
|
||||
"Description of application in launcher search result",
|
||||
// Default value
|
||||
Some(""),
|
||||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
ParamSpec::new_variant(
|
||||
// Name
|
||||
"icon",
|
||||
// Nickname
|
||||
"icon",
|
||||
// Short description
|
||||
"Icon of application in launcher search result",
|
||||
VariantTy::new("(is)").expect("Oops invalid string for VariantTy tuple."),
|
||||
// Default value
|
||||
None,
|
||||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
ParamSpec::new_variant(
|
||||
// Name
|
||||
"categoryicon",
|
||||
// Nickname
|
||||
"categoryicon",
|
||||
// Short description
|
||||
"Category icon of application in launcher search result",
|
||||
VariantTy::new("(is)").expect("Oops invalid string for VariantTy tuple."),
|
||||
// Default value
|
||||
None,
|
||||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
ParamSpec::new_variant(
|
||||
// Name
|
||||
"window",
|
||||
// Nickname
|
||||
"window",
|
||||
// Short description
|
||||
"Window of application in launcher search result",
|
||||
// type (tuple of two uint32)
|
||||
VariantTy::new("(uu)").expect("Oops invalid string for VariantTy tuple."),
|
||||
// Default value
|
||||
None,
|
||||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
]
|
||||
});
|
||||
PROPERTIES.as_ref()
|
||||
}
|
||||
|
||||
fn set_property(&self, _obj: &Self::Type, _id: usize, value: &Value, pspec: &ParamSpec) {
|
||||
match pspec.name() {
|
||||
"id" => {
|
||||
let id = value.get().expect("The value needs to be of type `u32`.");
|
||||
self.data.borrow_mut().0.id = id;
|
||||
}
|
||||
"name" => {
|
||||
let name = value
|
||||
.get()
|
||||
.expect("The value needs to be of type `String`.");
|
||||
self.data.borrow_mut().0.name = name;
|
||||
}
|
||||
"description" => {
|
||||
let description = value
|
||||
.get()
|
||||
.expect("The description needs to be of type `String`");
|
||||
self.data.borrow_mut().0.description = description;
|
||||
}
|
||||
"icon" => {
|
||||
let icon = <(i32, String)>::from_variant(
|
||||
&value
|
||||
.get::<Variant>()
|
||||
.expect("The icon needs to be a Variant"),
|
||||
)
|
||||
.expect("The icon variant needs to be an (i32, String)");
|
||||
self.data.borrow_mut().0.icon = match icon {
|
||||
(i_type, name) if i_type == pop_launcher::IconSource::Name as i32 => {
|
||||
Some(pop_launcher::IconSource::Name(name.into()))
|
||||
}
|
||||
(i_type, name) if i_type == pop_launcher::IconSource::Mime as i32 => {
|
||||
Some(pop_launcher::IconSource::Mime(name.into()))
|
||||
}
|
||||
(i_type, name) => {
|
||||
println!("Failed to set icon. {} {}", i_type, name);
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
"categoryicon" => {
|
||||
let icon = <(i32, String)>::from_variant(
|
||||
&value
|
||||
.get::<Variant>()
|
||||
.expect("The icon needs to be a Variant"),
|
||||
)
|
||||
.expect("The icon variant needs to be an Option<(i32, String)>");
|
||||
self.data.borrow_mut().0.category_icon = match icon {
|
||||
(i_type, name) if i_type == pop_launcher::IconSource::Name as i32 => {
|
||||
Some(pop_launcher::IconSource::Name(name.into()))
|
||||
}
|
||||
(i_type, name) if i_type == pop_launcher::IconSource::Mime as i32 => {
|
||||
Some(pop_launcher::IconSource::Mime(name.into()))
|
||||
}
|
||||
(i_type, name) => {
|
||||
println!("Failed to set icon. {} {}", i_type, name);
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
"window" => {
|
||||
unimplemented!()
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &ParamSpec) -> Value {
|
||||
match pspec.name() {
|
||||
"id" => self.data.borrow().0.id.to_value(),
|
||||
"name" => self.data.borrow().0.name.to_value(),
|
||||
"description" => self.data.borrow().0.description.to_value(),
|
||||
"icon" => match &self.data.borrow().0.icon {
|
||||
Some(pop_launcher::IconSource::Name(icon_name)) => {
|
||||
(pop_launcher::IconSource::Name as i32, icon_name.to_string())
|
||||
.to_variant()
|
||||
.to_value()
|
||||
}
|
||||
Some(pop_launcher::IconSource::Mime(icon_name)) => {
|
||||
(pop_launcher::IconSource::Mime as i32, icon_name.to_string())
|
||||
.to_variant()
|
||||
.to_value()
|
||||
}
|
||||
_ => None::<Variant>.to_value(),
|
||||
},
|
||||
"categoryicon" => match &self.data.borrow().0.category_icon {
|
||||
Some(pop_launcher::IconSource::Name(icon_name)) => {
|
||||
(pop_launcher::IconSource::Name as i32, icon_name.to_string())
|
||||
.to_variant()
|
||||
.to_value()
|
||||
}
|
||||
Some(pop_launcher::IconSource::Mime(icon_name)) => {
|
||||
(pop_launcher::IconSource::Mime as i32, icon_name.to_string())
|
||||
.to_variant()
|
||||
.to_value()
|
||||
}
|
||||
_ => None::<Variant>.to_value(),
|
||||
},
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
mod imp;
|
||||
|
||||
use gdk4::glib::Object;
|
||||
use glib::ObjectExt;
|
||||
use glib::ToVariant;
|
||||
use gtk4::glib;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ApplicationObject(ObjectSubclass<imp::ApplicationObject>);
|
||||
}
|
||||
|
||||
impl ApplicationObject {
|
||||
pub fn new(application_search_result: &pop_launcher::SearchResult) -> Self {
|
||||
let self_: Self = Object::new(&[
|
||||
("id", &application_search_result.id),
|
||||
("name", &application_search_result.name),
|
||||
("description", &application_search_result.description),
|
||||
])
|
||||
.expect("Failed to create `ApplicationObject`.");
|
||||
if let Some(icon) = &application_search_result.icon {
|
||||
if let Err(e) = self_.set_property(
|
||||
"icon",
|
||||
match icon {
|
||||
pop_launcher::IconSource::Name(name) => {
|
||||
(pop_launcher::IconSource::Name as i32, name.to_string()).to_variant()
|
||||
}
|
||||
pop_launcher::IconSource::Mime(name) => {
|
||||
(pop_launcher::IconSource::Mime as i32, name.to_string()).to_variant()
|
||||
}
|
||||
},
|
||||
) {
|
||||
println!("failed to set icon property");
|
||||
dbg!(e);
|
||||
};
|
||||
}
|
||||
if let Some(icon) = &application_search_result.category_icon {
|
||||
if let Err(e) = self_.set_property(
|
||||
"categoryicon",
|
||||
match icon {
|
||||
pop_launcher::IconSource::Name(name) => {
|
||||
(pop_launcher::IconSource::Name as i32, name.to_string()).to_variant()
|
||||
}
|
||||
pop_launcher::IconSource::Mime(name) => {
|
||||
(pop_launcher::IconSource::Mime as i32, name.to_string()).to_variant()
|
||||
}
|
||||
},
|
||||
) {
|
||||
println!("failed to set category icon property");
|
||||
dbg!(e);
|
||||
};
|
||||
}
|
||||
|
||||
self_
|
||||
}
|
||||
}
|
||||
|
||||
// Object holding the state
|
||||
pub struct ApplicationData(pop_launcher::SearchResult);
|
||||
|
||||
impl Default for ApplicationData {
|
||||
fn default() -> Self {
|
||||
let default_application = pop_launcher::SearchResult {
|
||||
id: 0,
|
||||
name: String::default(),
|
||||
description: String::default(),
|
||||
icon: None,
|
||||
category_icon: None,
|
||||
window: None,
|
||||
};
|
||||
Self(default_application)
|
||||
}
|
||||
}
|
||||
|
|
@ -53,10 +53,15 @@ impl DockItem {
|
|||
pub fn set_app_info(&self, app_info: &DockObject, i: u32, saved_app_model: &ListStore) {
|
||||
if let Ok(app_info_value) = app_info.property("appinfo") {
|
||||
if let Ok(Some(app_info)) = app_info_value.get::<Option<DesktopAppInfo>>() {
|
||||
dbg!("setting app info");
|
||||
println!("setting app info {}", &app_info.name());
|
||||
let self_ = imp::DockItem::from_instance(self);
|
||||
self_.image.set_tooltip_text(Some(&app_info.name()));
|
||||
|
||||
let icon = app_info.icon().unwrap_or(
|
||||
Icon::for_string("image-missing").expect("Failed to set default icon"),
|
||||
);
|
||||
|
||||
self_.image.set_from_gicon(&icon);
|
||||
if let Some(drag_controller) = self_.drag_controller.get() {
|
||||
if let Some(file) = app_info.filename() {
|
||||
let provider =
|
||||
|
|
@ -108,39 +113,9 @@ impl DockItem {
|
|||
}),
|
||||
);
|
||||
}
|
||||
|
||||
let icon = app_info.icon().unwrap_or(
|
||||
Icon::for_string("image-missing").expect("Failed to set default icon"),
|
||||
);
|
||||
|
||||
self_.image.set_from_gicon(&icon);
|
||||
}
|
||||
} else {
|
||||
println!("initializing dock item failed...");
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn set_app_info(&self, app_obj: ApplicationObject) {
|
||||
// let self_ = imp::DockItem::from_instance(self);
|
||||
|
||||
// if let Ok(name) = app_obj.property("name") {
|
||||
// self_.image.set_tooltip_text(Some(
|
||||
// &name
|
||||
// .get::<String>()
|
||||
// .expect("Property name needs to be a String."),
|
||||
// ));
|
||||
// }
|
||||
// if let Ok(icon) = app_obj.property("icon") {
|
||||
// if let Ok(icon) = icon.get::<Variant>() {
|
||||
// let icon = match <(i32, String)>::from_variant(&icon) {
|
||||
// Some((i_type, name)) if i_type == pop_launcher::IconSource::Name as i32 => {
|
||||
// Some(pop_launcher::IconSource::Name(name.into()))
|
||||
// }
|
||||
// Some((i_type, name)) if i_type == pop_launcher::IconSource::Mime as i32 => {
|
||||
// Some(pop_launcher::IconSource::Mime(name.into()))
|
||||
// }
|
||||
// _ => None,
|
||||
// };
|
||||
// icon_source(&self_.image, &icon);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use gtk4::glib;
|
|||
use gtk4::prelude::*;
|
||||
use gtk4::subclass::prelude::*;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::cell::Cell;
|
||||
use std::cell::RefCell;
|
||||
|
||||
// Object holding the state
|
||||
|
|
@ -12,6 +13,7 @@ use std::cell::RefCell;
|
|||
pub struct DockObject {
|
||||
appinfo: RefCell<Option<DesktopAppInfo>>,
|
||||
active: RefCell<BoxedSearchResults>,
|
||||
saved: Cell<bool>,
|
||||
}
|
||||
|
||||
// The central trait for subclassing a GObject
|
||||
|
|
@ -49,6 +51,13 @@ impl ObjectImpl for DockObject {
|
|||
// The property can be read and written to
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
ParamSpec::new_boolean(
|
||||
"saved",
|
||||
"saved",
|
||||
"Indicates whether app is saved to the dock",
|
||||
false,
|
||||
ParamFlags::READWRITE,
|
||||
),
|
||||
]
|
||||
});
|
||||
PROPERTIES.as_ref()
|
||||
|
|
@ -66,6 +75,10 @@ impl ObjectImpl for DockObject {
|
|||
let active = value.get().expect("Value needs to be BoxedSearchResults");
|
||||
self.active.replace(active);
|
||||
}
|
||||
"saved" => {
|
||||
self.saved
|
||||
.replace(value.get().expect("Value needs to be a boolean"));
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -73,6 +86,8 @@ impl ObjectImpl for DockObject {
|
|||
fn property(&self, _obj: &Self::Type, _id: usize, pspec: &ParamSpec) -> Value {
|
||||
match pspec.name() {
|
||||
"appinfo" => self.appinfo.borrow().to_value(),
|
||||
"active" => self.active.borrow().to_value(),
|
||||
"saved" => self.saved.get().to_value(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ glib::wrapper! {
|
|||
|
||||
impl DockObject {
|
||||
pub fn new(appinfo: DesktopAppInfo) -> Self {
|
||||
Object::new(&[("appinfo", &Some(appinfo))]).expect("Failed to create `DockObject`.")
|
||||
Object::new(&[("appinfo", &Some(appinfo)), ("saved", &true)])
|
||||
.expect("Failed to create `DockObject`.")
|
||||
}
|
||||
|
||||
pub fn from_search_results(results: BoxedSearchResults) -> Self {
|
||||
|
|
@ -23,7 +24,6 @@ impl DockObject {
|
|||
.iter_mut()
|
||||
.filter_map(|xdg_data_path| {
|
||||
xdg_data_path.push("applications");
|
||||
dbg!(&xdg_data_path);
|
||||
std::fs::read_dir(xdg_data_path).ok()
|
||||
})
|
||||
.flatten()
|
||||
|
|
@ -35,7 +35,7 @@ impl DockObject {
|
|||
if app_info.should_show()
|
||||
&& first.description.as_str() == app_info.name().as_str()
|
||||
{
|
||||
return Some(DockObject::new(app_info));
|
||||
return Some(app_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,7 @@ impl DockObject {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
dbg!(&appinfo);
|
||||
Object::new(&[("appinfo", &appinfo), ("active", &results)])
|
||||
.expect("Failed to create `DockObject`.")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
mod application_object;
|
||||
mod dock_item;
|
||||
mod dock_object;
|
||||
mod utils;
|
||||
mod window;
|
||||
|
||||
use crate::utils::BoxedSearchResults;
|
||||
use async_io::Timer;
|
||||
use gdk4::Display;
|
||||
use gio::DesktopAppInfo;
|
||||
|
|
@ -18,9 +18,11 @@ use once_cell::sync::OnceCell;
|
|||
use pop_launcher_service::IpcClient;
|
||||
use postage::mpsc::Sender;
|
||||
use postage::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use x11rb::rust_connection::RustConnection;
|
||||
|
||||
use self::dock_object::DockObject;
|
||||
use self::window::Window;
|
||||
|
||||
const NUM_LAUNCHER_ITEMS: u8 = 10;
|
||||
|
|
@ -48,10 +50,10 @@ fn spawn_launcher(tx: Sender<Event>) -> IpcClient {
|
|||
|
||||
let mut sender = tx.clone();
|
||||
glib::MainContext::default().spawn_local(async move {
|
||||
loop {
|
||||
Timer::after(Duration::from_secs(1)).await;
|
||||
let _ = sender.send(Event::Search(String::new())).await;
|
||||
}
|
||||
// loop {
|
||||
let _ = sender.send(Event::Search(String::new())).await;
|
||||
Timer::after(Duration::from_secs(1)).await;
|
||||
// }
|
||||
});
|
||||
|
||||
launcher
|
||||
|
|
@ -120,8 +122,23 @@ fn main() {
|
|||
let _ = launcher.send(pop_launcher::Request::Activate(index)).await;
|
||||
}
|
||||
Event::Response(event) => {
|
||||
if let pop_launcher::Response::Update(_results) = event {
|
||||
println!("updating active apps")
|
||||
if let pop_launcher::Response::Update(results) = event {
|
||||
println!("updating active apps");
|
||||
let model = window.active_app_model();
|
||||
let model_len = model.n_items();
|
||||
let stack_active = results.iter().fold(HashMap::new(), |mut acc: HashMap<String, BoxedSearchResults>, elem| {
|
||||
if let Some(v) = acc.get_mut(&elem.description) {
|
||||
v.0.push(elem.clone());
|
||||
} else {
|
||||
acc.insert(elem.description.clone(), BoxedSearchResults(vec![elem.clone()]));
|
||||
}
|
||||
acc
|
||||
});
|
||||
let new_results: Vec<glib::Object> = stack_active
|
||||
.into_values()
|
||||
.map(|v| DockObject::from_search_results(v).upcast())
|
||||
.collect();
|
||||
model.splice(0, model_len, &new_results[..]);
|
||||
}
|
||||
else if let pop_launcher::Response::DesktopEntry {
|
||||
path,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub struct Window {
|
|||
#[template_child]
|
||||
pub saved_app_list_view: TemplateChild<ListView>,
|
||||
#[template_child]
|
||||
pub unsaved_open_app_list_view: TemplateChild<ListView>,
|
||||
pub active_app_list_view: TemplateChild<ListView>,
|
||||
#[template_child]
|
||||
pub revealer: TemplateChild<Revealer>,
|
||||
#[template_child]
|
||||
|
|
@ -26,7 +26,7 @@ pub struct Window {
|
|||
#[template_child]
|
||||
pub cursor_leave_handle: TemplateChild<Box>,
|
||||
pub saved_app_model: OnceCell<gio::ListStore>,
|
||||
pub unsaved_open_app_model: OnceCell<gio::ListStore>,
|
||||
pub active_app_model: OnceCell<gio::ListStore>,
|
||||
pub enter_event_controller: OnceCell<EventControllerMotion>,
|
||||
pub leave_event_controller: OnceCell<EventControllerMotion>,
|
||||
pub drop_controller: OnceCell<DropTarget>,
|
||||
|
|
|
|||
|
|
@ -46,13 +46,21 @@ impl Window {
|
|||
.expect("Could not get saved_app_model")
|
||||
}
|
||||
|
||||
pub fn active_app_model(&self) -> &gio::ListStore {
|
||||
// Get state
|
||||
let imp = imp::Window::from_instance(self);
|
||||
imp.active_app_model
|
||||
.get()
|
||||
.expect("Could not get active_app_model")
|
||||
}
|
||||
|
||||
fn setup_model(&self) {
|
||||
// Get state and set model
|
||||
|
||||
let imp = imp::Window::from_instance(self);
|
||||
let saved_app_model = gio::ListStore::new(DockObject::static_type());
|
||||
|
||||
let selection_model = gtk::SingleSelection::builder()
|
||||
let saved_selection_model = gtk::SingleSelection::builder()
|
||||
.autoselect(false)
|
||||
.can_unselect(true)
|
||||
.selected(gtk4::INVALID_LIST_POSITION)
|
||||
|
|
@ -93,7 +101,23 @@ impl Window {
|
|||
.set(saved_app_model)
|
||||
.expect("Could not set model");
|
||||
// Wrap model with selection and pass it to the list view
|
||||
imp.saved_app_list_view.set_model(Some(&selection_model));
|
||||
imp.saved_app_list_view
|
||||
.set_model(Some(&saved_selection_model));
|
||||
|
||||
let active_app_model = gio::ListStore::new(DockObject::static_type());
|
||||
let active_selection_model = gtk::SingleSelection::builder()
|
||||
.autoselect(false)
|
||||
.can_unselect(true)
|
||||
.selected(gtk4::INVALID_LIST_POSITION)
|
||||
.model(&active_app_model)
|
||||
.build();
|
||||
|
||||
imp.active_app_model
|
||||
.set(active_app_model)
|
||||
.expect("Could not set model");
|
||||
// Wrap model with selection and pass it to the list view
|
||||
imp.active_app_list_view
|
||||
.set_model(Some(&active_selection_model));
|
||||
}
|
||||
|
||||
fn setup_callbacks(&self) {
|
||||
|
|
@ -346,8 +370,8 @@ impl Window {
|
|||
}
|
||||
|
||||
fn setup_factory(&self) {
|
||||
let factory = SignalListItemFactory::new();
|
||||
factory.connect_setup(move |_, list_item| {
|
||||
let saved_app_factory = SignalListItemFactory::new();
|
||||
saved_app_factory.connect_setup(move |_, list_item| {
|
||||
let dock_item = DockItem::new();
|
||||
list_item.set_child(Some(&dock_item));
|
||||
});
|
||||
|
|
@ -356,7 +380,7 @@ impl Window {
|
|||
.saved_app_model
|
||||
.get()
|
||||
.expect("Failed to get saved app model.");
|
||||
factory.connect_bind(glib::clone!(@weak saved_app_model => move |_, list_item| {
|
||||
saved_app_factory.connect_bind(glib::clone!(@weak saved_app_model => move |_, list_item| {
|
||||
let application_object = list_item
|
||||
.item()
|
||||
.expect("The item has to exist.")
|
||||
|
|
@ -372,6 +396,35 @@ impl Window {
|
|||
dock_item.set_app_info(&application_object, i, &saved_app_model);
|
||||
}));
|
||||
// Set the factory of the list view
|
||||
imp.saved_app_list_view.set_factory(Some(&factory));
|
||||
imp.saved_app_list_view
|
||||
.set_factory(Some(&saved_app_factory));
|
||||
|
||||
let active_app_model = imp
|
||||
.active_app_model
|
||||
.get()
|
||||
.expect("Failed to get saved app model.");
|
||||
let active_factory = SignalListItemFactory::new();
|
||||
active_factory.connect_setup(move |_, list_item| {
|
||||
let dock_item = DockItem::new();
|
||||
list_item.set_child(Some(&dock_item));
|
||||
});
|
||||
active_factory.connect_bind(glib::clone!(@weak active_app_model => move |_, list_item| {
|
||||
let application_object = list_item
|
||||
.item()
|
||||
.expect("The item has to exist.")
|
||||
.downcast::<DockObject>()
|
||||
.expect("The item has to be a `DockObject`");
|
||||
let dock_item = list_item
|
||||
.child()
|
||||
.expect("The list item child needs to exist.")
|
||||
.downcast::<DockItem>()
|
||||
.expect("The list item type needs to be `DockItem`");
|
||||
|
||||
let i = list_item.position();
|
||||
println!("setting position {} of active app list.", i);
|
||||
dock_item.set_app_info(&application_object, i, &active_app_model);
|
||||
}));
|
||||
// Set the factory of the list view
|
||||
imp.active_app_list_view.set_factory(Some(&active_factory));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
<child>
|
||||
<object class="GtkListView" id="saved_app_list_view">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="hexpand">true</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
|
@ -44,9 +43,8 @@
|
|||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListView" id="unsaved_open_app_list_view">
|
||||
<object class="GtkListView" id="active_app_list_view">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="hexpand">true</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue