about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoan Lledó <jlledom@member.fsf.org>2023-09-30 13:06:01 +0200
committerJoan Lledó <jlledom@member.fsf.org>2023-09-30 13:14:53 +0200
commit14ae87d469555af8301356f99a11c2254edee1a4 (patch)
tree2ec472aeebd7d12d9c9ceb43c73122e8a61f5aca
parentc6d5440c44ac7b94a9d7db38c36e638097872852 (diff)
downloadFurtherance-14ae87d469555af8301356f99a11c2254edee1a4.tar.zst
Implement search by tag list
-rw-r--r--src/database.rs24
-rw-r--r--src/ui/window.rs12
2 files changed, 21 insertions, 15 deletions
diff --git a/src/database.rs b/src/database.rs
index 8a7c6c9..2f97d2d 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -349,13 +349,23 @@ pub fn get_list_by_id(id_list: Vec<i32>) -> Result<Vec<Task>, rusqlite::Error> {
     Ok(tasks_vec)
 }
 
-pub fn get_list_by_name(task_name: String) -> Result<Vec<Task>, rusqlite::Error> {
+pub fn get_list_by_name_and_tags(task_name: String, tag_list: Vec<String>) -> Result<Vec<Task>, rusqlite::Error> {
     let conn = Connection::open(get_directory())?;
-    let mut tasks_vec: Vec<Task> = Vec::new();
+
     let name_param = format!("%{}%", task_name);
+    let tag_list_params: Vec<String> = tag_list.iter().map(|tag| format!("%{}%", tag)).collect();
+
+    let mut sql_query = String::from("SELECT * FROM tasks WHERE lower(task_name) LIKE lower(?)");
+    tag_list_params.iter().for_each(|_| sql_query.push_str(" AND lower(tags) LIKE lower(?)"));
+    sql_query.push_str(" ORDER BY task_name");
+
+    let mut query = conn.prepare(sql_query.as_str())?;
+    query.raw_bind_parameter(1, name_param)?;
+    for (i, tag) in tag_list_params.iter().enumerate() {
+        query.raw_bind_parameter(i + 2, tag)?;
+    }
 
-    let mut query = conn.prepare("SELECT * FROM tasks WHERE lower(task_name) LIKE lower(:task_name) ORDER BY task_name")?;
-    let task_iter = query.query_map(&[(":task_name", &name_param)], |row| {
+    let tasks_vec = query.raw_query().mapped(|row| {
         Ok(Task {
             id: row.get(0)?,
             task_name: row.get(1)?,
@@ -363,11 +373,7 @@ pub fn get_list_by_name(task_name: String) -> Result<Vec<Task>, rusqlite::Error>
             stop_time: row.get(3)?,
             tags: row.get(4)?,
         })
-    })?;
-
-    for task_item in task_iter {
-        tasks_vec.push(task_item.unwrap());
-    }
+    }).map(|task_item| task_item.unwrap()).collect();
 
     Ok(tasks_vec)
 }
diff --git a/src/ui/window.rs b/src/ui/window.rs
index ccf2364..8972ed9 100644
--- a/src/ui/window.rs
+++ b/src/ui/window.rs
@@ -208,9 +208,9 @@ impl FurtheranceWindow {
             .connect_changed(clone!(@weak self as this => move |task_input| {
                 let imp2 = imp::FurtheranceWindow::from_obj(&this);
                 let task_input_text = task_input.text();
-                let split_tags: Vec<&str> = task_input_text.trim().split('#').collect();
-                let task_name = split_tags[0];
-                if task_name.trim().is_empty() {
+                let mut split_tags: Vec<String> = task_input_text.split('#').map(|tag| String::from(tag.trim())).collect();
+                let task_name = split_tags.remove(0);
+                if task_name.is_empty() {
                     imp2.start_button.set_sensitive(false);
                 } else {
                     imp2.start_button.set_sensitive(true);
@@ -218,7 +218,7 @@ impl FurtheranceWindow {
 
                 if task_input.text().len() >= FurtheranceWindow::MIN_PREFIX_LENGTH.try_into().unwrap() {
                     let task_autocomplete = task_input.completion().unwrap();
-                    let model = Self::update_list_model(task_name.to_string()).unwrap();
+                    let model = Self::update_list_model(task_name.to_string(), split_tags).unwrap();
                     task_autocomplete.set_model(Some(&model));
                 }
             }));
@@ -544,9 +544,9 @@ impl FurtheranceWindow {
         imp.task_input.set_activates_default(true);
     }
 
-    fn update_list_model(task_name: String) -> Result<gtk::ListStore, anyhow::Error> {
+    fn update_list_model(task_name: String, tag_list: Vec<String>) -> Result<gtk::ListStore, anyhow::Error> {
         let col_types: [glib::Type; 1] = [glib::Type::STRING];
-        let mut task_list = database::get_list_by_name(task_name)?;
+        let mut task_list = database::get_list_by_name_and_tags(task_name, tag_list)?;
         task_list.dedup_by(|a, b| a.task_name == b.task_name && a.tags == b.tags);
         let store = gtk::ListStore::new(&col_types);