summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Murphy <hello@itsjamie.dev>2023-02-16 07:54:42 -0800
committerJamie Murphy <hello@itsjamie.dev>2023-02-16 07:54:42 -0800
commit76c2a1b540989e41756ccfc7fac2623ded3de92f (patch)
tree61cb7bfcd30ca790adbdc5e89d4601c92f4d858c
parent46493030e00e266f05893059009eab6dcef3b6b9 (diff)
downloadgnome-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.rs1
-rw-r--r--src/engine/task_list.rs151
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]);
+ }
+ }
+}