diff options
author | Jamie Murphy <hello@itsjamie.dev> | 2023-02-16 07:54:42 -0800 |
---|---|---|
committer | Jamie Murphy <hello@itsjamie.dev> | 2023-02-16 07:54:42 -0800 |
commit | 76c2a1b540989e41756ccfc7fac2623ded3de92f (patch) | |
tree | 61cb7bfcd30ca790adbdc5e89d4601c92f4d858c | |
parent | 46493030e00e266f05893059009eab6dcef3b6b9 (diff) | |
download | gnome-todo-refactor.tar.gz |
task_list: Implement basic task listrefactor
Currently, only adding and removing tasks from the list is supported
-rw-r--r-- | src/engine/lib.rs | 1 | ||||
-rw-r--r-- | src/engine/task_list.rs | 151 |
2 files changed, 152 insertions, 0 deletions
diff --git a/src/engine/lib.rs b/src/engine/lib.rs index f8400b74..8ee729f4 100644 --- a/src/engine/lib.rs +++ b/src/engine/lib.rs @@ -4,4 +4,5 @@ pub mod provider; pub mod providers; pub mod schema; pub mod task; +pub mod task_list; pub mod utils; diff --git a/src/engine/task_list.rs b/src/engine/task_list.rs new file mode 100644 index 00000000..2d17870d --- /dev/null +++ b/src/engine/task_list.rs @@ -0,0 +1,151 @@ +use gtk::{ + gio::ListModel, + glib::{self, Object}, + prelude::*, + subclass::prelude::*, +}; +use indexmap::IndexMap; + +use crate::task::Task; + +mod imp { + use std::cell::{Cell, RefCell}; + + use gtk::glib::{subclass::Signal, ParamSpec, Properties, Value}; + use once_cell::sync::Lazy; + + use super::*; + + #[derive(Properties, Default)] + #[properties(wrapper_type = super::TaskList)] + pub struct TaskList { + #[property(get, set)] + pub name: RefCell<String>, + #[property(get, set)] + pub archived: Cell<bool>, + // Can a TaskList be deleted or removed in any way? + // This should normally be True, except for global lists + // (like All Tasks or Inbox) + #[property(get, set, construct_only)] + pub removable: Cell<bool>, + + // INTERNAL PROPERTIES + pub tasks: RefCell<IndexMap<String, Task>>, + } + + #[glib::object_subclass] + impl ObjectSubclass for TaskList { + const NAME: &'static str = "GtdTaskList"; + type Type = super::TaskList; + type ParentType = glib::Object; + } + + impl ObjectImpl for TaskList { + fn properties() -> &'static [ParamSpec] { + Self::derived_properties() + } + + fn signals() -> &'static [Signal] { + static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { + vec![ + Signal::builder("task-added") + .param_types([Task::static_type()]) + .build(), + Signal::builder("task-removed") + .param_types([Task::static_type()]) + .build(), + ] + }); + SIGNALS.as_ref() + } + + fn set_property(&self, id: usize, value: &Value, pspec: &ParamSpec) { + Self::derived_set_property(self, id, value, pspec) + } + + fn property(&self, id: usize, pspec: &ParamSpec) -> Value { + Self::derived_property(self, id, pspec) + } + } + + impl ListModelImpl for TaskList { + fn item_type(&self) -> glib::Type { + Task::static_type() + } + + fn n_items(&self) -> u32 { + self.tasks + .borrow() + .len() + .try_into() + .expect("Expected a u32") + } + + fn item(&self, position: u32) -> Option<glib::Object> { + self.tasks + .borrow() + .get_index(position.try_into().expect("Expected a u32")) + .map(|(_, v)| v.clone().upcast::<Object>()) + } + } +} + +glib::wrapper! { + pub struct TaskList(ObjectSubclass<imp::TaskList>) + @implements ListModel; +} + +impl Default for TaskList { + /// Create a new TaskList + fn default() -> Self { + Object::new() + } +} + +impl TaskList { + /// Create a new TaskList with values from a database + pub fn new(name: String, archived: bool, removable: bool) -> Self { + Object::builder() + .property("name", name) + .property("archived", archived) + .property("removable", removable) + .build() + } + + /// Add a GtdTask into this TaskList. + pub fn add_task(&self, task: &Task) { + let _self = self.clone(); + let mut list = _self.imp().tasks.borrow_mut(); + + if !list.contains_key(&task.id()) { + let (index, _) = list.insert_full(task.id(), task.clone()); + + self.clone().upcast::<ListModel>().items_changed( + index.try_into().expect("Expected a u32"), + 0, + 1, + ); + + self.emit_by_name::<()>("task-added", &[task]); + } + } + + // Removes a GtdTask from this TaskList + pub fn remove_task(&self, task: &Task) { + let _self = self.clone(); + let mut list = _self.imp().tasks.borrow_mut(); + + if list.contains_key(&task.id()) { + let index = list.get_index_of(&task.id()).unwrap_or_default(); + list.remove(&task.id()); + + self.clone().upcast::<ListModel>().items_changed( + index.try_into().expect("Expected a u32"), + 1, + 0, + ); + + self.emit_by_name::<()>("task-removed", &[task]); + } + } +} |