From 1a4bf2b0a2a54393c401522611f85c2637d1de88 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer <lfleischer@calcurse.org>
Date: Sun, 17 Jan 2016 20:04:25 +0100
Subject: Add a "hide completed" view to the todo panel

Add a second view to the todo panel that hides all completed items.

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
---
 src/calcurse.c |  6 ++++++
 src/calcurse.h | 13 +++++++++++--
 src/todo.c     | 17 +++++++++++++++--
 src/ui-todo.c  | 60 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 src/wins.c     |  1 +
 5 files changed, 83 insertions(+), 14 deletions(-)

(limited to 'src')

diff --git a/src/calcurse.c b/src/calcurse.c
index 889c68c..a4dc802 100644
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -423,6 +423,9 @@ static inline void key_generic_scroll_up(void)
 	if (wins_slctd() == CAL) {
 		ui_calendar_view_prev();
 		wins_update(FLAG_CAL | FLAG_APP);
+	} else if (wins_slctd() == TOD) {
+		ui_todo_view_prev();
+		wins_update(FLAG_TOD | FLAG_APP);
 	}
 }
 
@@ -431,6 +434,9 @@ static inline void key_generic_scroll_down(void)
 	if (wins_slctd() == CAL) {
 		ui_calendar_view_next();
 		wins_update(FLAG_CAL | FLAG_APP);
+	} else if (wins_slctd() == TOD) {
+		ui_todo_view_next();
+		wins_update(FLAG_TOD | FLAG_APP);
 	}
 }
 
diff --git a/src/calcurse.h b/src/calcurse.h
index 2b5b055..27fcc68 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -425,13 +425,20 @@ struct day_item {
 	union aptev_ptr item;
 };
 
-/* Available view for the calendar panel. */
+/* Available views for the calendar panel. */
 enum {
 	CAL_MONTH_VIEW,
 	CAL_WEEK_VIEW,
 	CAL_VIEWS
 };
 
+/* Available views for the todo panel. */
+enum {
+	TODO_SHOW_COMPLETED_VIEW,
+	TODO_HIDE_COMPLETED_VIEW,
+	TODO_VIEWS
+};
+
 struct notify_app {
 	long time;
 	int got_app;
@@ -1009,7 +1016,7 @@ int string_printf(struct string *, const char *, ...);
 
 /* todo.c */
 extern llist_t todolist;
-struct todo *todo_get_item(int);
+struct todo *todo_get_item(int, int);
 struct todo *todo_add(char *, int, char *);
 char *todo_tostr(struct todo *);
 char *todo_hash(struct todo *);
@@ -1062,6 +1069,8 @@ void ui_todo_popup_item(void);
 void ui_todo_flag(void);
 void ui_todo_view_note(void);
 void ui_todo_edit_note(void);
+void ui_todo_view_prev(void);
+void ui_todo_view_next(void);
 
 /* utf8.c */
 int utf8_width(char *);
diff --git a/src/todo.c b/src/todo.c
index 9869a1e..707628c 100644
--- a/src/todo.c
+++ b/src/todo.c
@@ -43,10 +43,23 @@
 
 llist_t todolist;
 
+static int todo_is_uncompleted(struct todo *todo, void *cbdata)
+{
+	return todo->id >= 0;
+}
+
 /* Returns a structure containing the selected item. */
-struct todo *todo_get_item(int item_number)
+struct todo *todo_get_item(int item_number, int skip_completed)
 {
-	return LLIST_GET_DATA(LLIST_NTH(&todolist, item_number));
+	llist_item_t *i;
+
+	if (skip_completed)
+		i = LLIST_FIND_NTH(&todolist, item_number, NULL,
+				   todo_is_uncompleted);
+	else
+		i = LLIST_NTH(&todolist, item_number);
+
+	return LLIST_GET_DATA(i);
 }
 
 static int todo_cmp_id(struct todo *a, struct todo *b)
diff --git a/src/ui-todo.c b/src/ui-todo.c
index 5a79ebd..86592c1 100644
--- a/src/ui-todo.c
+++ b/src/ui-todo.c
@@ -36,6 +36,14 @@
 
 #include "calcurse.h"
 
+static unsigned ui_todo_view = 0;
+
+static struct todo *ui_todo_selitem(void)
+{
+	return todo_get_item(listbox_get_sel(&lb_todo),
+			     ui_todo_view == TODO_HIDE_COMPLETED_VIEW);
+}
+
 /* Request user to enter a new todo item. */
 void ui_todo_add(void)
 {
@@ -77,7 +85,7 @@ void ui_todo_delete(void)
 		return;
 	}
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 
 	if (item->note)
 		answer = status_ask_choice(erase_warning, erase_choice,
@@ -107,7 +115,7 @@ void ui_todo_edit(void)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 	const char *mesg = _("Enter the new TODO description:");
 
 	status_mesg(mesg, "");
@@ -127,7 +135,7 @@ void ui_todo_pipe(void)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 
 	status_mesg(_("Pipe item to external command:"), "");
 	if (getstring(win[STA].p, cmd, BUFSIZ, 0, 1) != GETSTRING_VALID)
@@ -154,6 +162,14 @@ void ui_todo_draw(int n, WINDOW *win, int y, int hilt, void *cb_data)
 	char buf[width * UTF8_MAXLEN];
 	int j;
 
+	if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW) {
+		while (i && todo->id < 0) {
+			i = i->next;
+			if (i)
+				todo = LLIST_TS_GET_DATA(i);
+		}
+	}
+
 	mark[0] = todo->id > 0 ? '0' + todo->id : 'X';
 	mark[1] = todo->note ? '>' : '.';
 
@@ -199,8 +215,12 @@ void ui_todo_load_items(void)
 	llist_item_t *i;
 
 	/* TODO: Optimize this by keeping the list size in a variable. */
-	LLIST_FOREACH(&todolist, i)
+	LLIST_FOREACH(&todolist, i) {
+		struct todo *todo = LLIST_TS_GET_DATA(i);
+		if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW && todo->id < 0)
+			continue;
 		n++;
+	}
 
 	listbox_load_items(&lb_todo, n);
 }
@@ -219,7 +239,7 @@ void ui_todo_sel_move(int delta)
 void ui_todo_update_panel(int which_pan)
 {
 	/*
-	 * This is used and modified by display_todo_item() to avoid quadratic
+	 * This is used and modified by ui_todo_draw() to avoid quadratic
 	 * running time.
 	 */
 	llist_item_t *p = LLIST_FIRST(&todolist);
@@ -234,7 +254,7 @@ void ui_todo_chg_priority(int diff)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 	int id = item->id + diff;
 	struct todo *item_new;
 
@@ -254,7 +274,7 @@ void ui_todo_popup_item(void)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 	item_in_popup(NULL, NULL, item->mesg, _("TODO:"));
 }
 
@@ -263,8 +283,10 @@ void ui_todo_flag(void)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 	todo_flag(item);
+	if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW)
+		ui_todo_load_items();
 	io_set_modified();
 }
 
@@ -273,7 +295,7 @@ void ui_todo_view_note(void)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 	todo_view_note(item, conf.pager);
 }
 
@@ -282,7 +304,25 @@ void ui_todo_edit_note(void)
 	if (!LLIST_FIRST(&todolist))
 		return;
 
-	struct todo *item = todo_get_item(listbox_get_sel(&lb_todo));
+	struct todo *item = ui_todo_selitem();
 	todo_edit_note(item, conf.editor);
 	io_set_modified();
 }
+
+/* Switch to next todo view. */
+void ui_todo_view_next(void)
+{
+	ui_todo_view++;
+	if (ui_todo_view == TODO_VIEWS)
+		ui_todo_view = 0;
+	ui_todo_load_items();
+}
+
+/* Switch to previous todo view. */
+void ui_todo_view_prev(void)
+{
+	if (ui_todo_view == 0)
+		ui_todo_view = TODO_VIEWS;
+	ui_todo_view--;
+	ui_todo_load_items();
+}
diff --git a/src/wins.c b/src/wins.c
index 5e390f5..8eb6bca 100644
--- a/src/wins.c
+++ b/src/wins.c
@@ -665,6 +665,7 @@ void wins_update_bindings(void)
 	static int bindings_todo[] = {
 		KEY_GENERIC_HELP, KEY_GENERIC_QUIT, KEY_GENERIC_SAVE,
 		KEY_GENERIC_RELOAD, KEY_GENERIC_CHANGE_VIEW,
+		KEY_GENERIC_SCROLL_DOWN, KEY_GENERIC_SCROLL_UP,
 		KEY_GENERIC_IMPORT, KEY_GENERIC_EXPORT, KEY_ADD_ITEM,
 		KEY_DEL_ITEM, KEY_EDIT_ITEM, KEY_VIEW_ITEM, KEY_PIPE_ITEM,
 		KEY_FLAG_ITEM, KEY_RAISE_PRIORITY, KEY_LOWER_PRIORITY,
-- 
cgit v1.2.3-70-g09d2