Use a separate field for the completed status
Add a new field that indicates whether a todo item is completed or not instead of encoding completed todo items by negative priorities. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
1a4bf2b0a2
commit
beea88e5fe
@ -323,6 +323,7 @@ struct event {
|
|||||||
struct todo {
|
struct todo {
|
||||||
char *mesg;
|
char *mesg;
|
||||||
int id;
|
int id;
|
||||||
|
int completed;
|
||||||
char *note;
|
char *note;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1017,7 +1018,7 @@ int string_printf(struct string *, const char *, ...);
|
|||||||
/* todo.c */
|
/* todo.c */
|
||||||
extern llist_t todolist;
|
extern llist_t todolist;
|
||||||
struct todo *todo_get_item(int, int);
|
struct todo *todo_get_item(int, int);
|
||||||
struct todo *todo_add(char *, int, char *);
|
struct todo *todo_add(char *, int, int, char *);
|
||||||
char *todo_tostr(struct todo *);
|
char *todo_tostr(struct todo *);
|
||||||
char *todo_hash(struct todo *);
|
char *todo_hash(struct todo *);
|
||||||
void todo_write(struct todo *, FILE *);
|
void todo_write(struct todo *, FILE *);
|
||||||
|
18
src/ical.c
18
src/ical.c
@ -266,14 +266,11 @@ static void ical_export_todo(FILE * stream, int export_uid)
|
|||||||
|
|
||||||
LLIST_FOREACH(&todolist, i) {
|
LLIST_FOREACH(&todolist, i) {
|
||||||
struct todo *todo = LLIST_TS_GET_DATA(i);
|
struct todo *todo = LLIST_TS_GET_DATA(i);
|
||||||
int priority = todo->id;
|
|
||||||
|
|
||||||
fputs("BEGIN:VTODO\n", stream);
|
fputs("BEGIN:VTODO\n", stream);
|
||||||
if (todo->id < 0) {
|
if (todo->completed)
|
||||||
fprintf(stream, "STATUS:COMPLETED\n");
|
fprintf(stream, "STATUS:COMPLETED\n");
|
||||||
priority = -priority;
|
fprintf(stream, "PRIORITY:%d\n", todo->id);
|
||||||
}
|
|
||||||
fprintf(stream, "PRIORITY:%d\n", priority);
|
|
||||||
fprintf(stream, "SUMMARY:%s\n", todo->mesg);
|
fprintf(stream, "SUMMARY:%s\n", todo->mesg);
|
||||||
|
|
||||||
if (export_uid) {
|
if (export_uid) {
|
||||||
@ -327,9 +324,10 @@ static void ical_log(FILE * log, ical_types_e type, unsigned lineno,
|
|||||||
fprintf(log, "%s [%d]: %s\n", typestr[type], lineno, msg);
|
fprintf(log, "%s [%d]: %s\n", typestr[type], lineno, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ical_store_todo(int priority, char *mesg, char *note, int list)
|
static void ical_store_todo(int priority, int completed, char *mesg,
|
||||||
|
char *note, int list)
|
||||||
{
|
{
|
||||||
struct todo *todo = todo_add(mesg, priority, note);
|
struct todo *todo = todo_add(mesg, priority, completed, note);
|
||||||
if (list) {
|
if (list) {
|
||||||
char *hash = todo_hash(todo);
|
char *hash = todo_hash(todo);
|
||||||
printf("%s\n", hash);
|
printf("%s\n", hash);
|
||||||
@ -1081,16 +1079,14 @@ ical_read_todo(FILE * fdi, FILE * log, int list, unsigned *notodos,
|
|||||||
if (starts_with_ci(buf, "END:VTODO")) {
|
if (starts_with_ci(buf, "END:VTODO")) {
|
||||||
if (!vtodo.has_priority)
|
if (!vtodo.has_priority)
|
||||||
vtodo.priority = LOWEST;
|
vtodo.priority = LOWEST;
|
||||||
if (vtodo.completed)
|
|
||||||
vtodo.priority = -vtodo.priority;
|
|
||||||
if (!vtodo.mesg) {
|
if (!vtodo.mesg) {
|
||||||
ical_log(log, ICAL_VTODO, ITEMLINE,
|
ical_log(log, ICAL_VTODO, ITEMLINE,
|
||||||
_("could not retrieve item summary."));
|
_("could not retrieve item summary."));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ical_store_todo(vtodo.priority, vtodo.mesg,
|
ical_store_todo(vtodo.priority, vtodo.completed,
|
||||||
vtodo.note, list);
|
vtodo.mesg, vtodo.note, list);
|
||||||
(*notodos)++;
|
(*notodos)++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
19
src/io.c
19
src/io.c
@ -630,7 +630,7 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
FILE *data_file;
|
FILE *data_file;
|
||||||
char *newline;
|
char *newline;
|
||||||
int nb_tod = 0;
|
int nb_tod = 0;
|
||||||
int c, id;
|
int c, id, completed;
|
||||||
char buf[BUFSIZ], e_todo[BUFSIZ], note[MAX_NOTESIZ + 1];
|
char buf[BUFSIZ], e_todo[BUFSIZ], note[MAX_NOTESIZ + 1];
|
||||||
unsigned line = 0;
|
unsigned line = 0;
|
||||||
|
|
||||||
@ -642,7 +642,15 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
c = getc(data_file);
|
c = getc(data_file);
|
||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
break;
|
break;
|
||||||
} else if (c == '[') { /* new style with id */
|
} else if (c == '[') {
|
||||||
|
/* new style with id */
|
||||||
|
c = getc(data_file);
|
||||||
|
if (c == '-') {
|
||||||
|
completed = 1;
|
||||||
|
} else {
|
||||||
|
completed = 0;
|
||||||
|
ungetc(c, data_file);
|
||||||
|
}
|
||||||
if (fscanf(data_file, " %d ", &id) != 1
|
if (fscanf(data_file, " %d ", &id) != 1
|
||||||
|| getc(data_file) != ']')
|
|| getc(data_file) != ']')
|
||||||
io_load_error(path_todo, line,
|
io_load_error(path_todo, line,
|
||||||
@ -651,6 +659,7 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
ungetc(c, data_file);
|
ungetc(c, data_file);
|
||||||
} else {
|
} else {
|
||||||
id = 9;
|
id = 9;
|
||||||
|
completed = 0;
|
||||||
ungetc(c, data_file);
|
ungetc(c, data_file);
|
||||||
}
|
}
|
||||||
/* Now read the attached note, if any. */
|
/* Now read the attached note, if any. */
|
||||||
@ -678,13 +687,13 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
continue;
|
continue;
|
||||||
if (filter->priority && id != filter->priority)
|
if (filter->priority && id != filter->priority)
|
||||||
continue;
|
continue;
|
||||||
if (filter->completed && id > 0)
|
if (filter->completed && !completed)
|
||||||
continue;
|
continue;
|
||||||
if (filter->uncompleted && id < 0)
|
if (filter->uncompleted && completed)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct todo *todo = todo_add(e_todo, id, note);
|
struct todo *todo = todo_add(e_todo, id, completed, note);
|
||||||
|
|
||||||
/* Filter by hash. */
|
/* Filter by hash. */
|
||||||
if (filter && filter->hash) {
|
if (filter && filter->hash) {
|
||||||
|
@ -311,7 +311,7 @@ static void pcal_export_todo(FILE * stream)
|
|||||||
fputs("#\n# Todos\n#\n", stream);
|
fputs("#\n# Todos\n#\n", stream);
|
||||||
LLIST_FOREACH(&todolist, i) {
|
LLIST_FOREACH(&todolist, i) {
|
||||||
struct todo *todo = LLIST_TS_GET_DATA(i);
|
struct todo *todo = LLIST_TS_GET_DATA(i);
|
||||||
if (todo->id < 0) /* completed items */
|
if (todo->completed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fputs("note all ", stream);
|
fputs("note all ", stream);
|
||||||
|
30
src/todo.c
30
src/todo.c
@ -45,7 +45,7 @@ llist_t todolist;
|
|||||||
|
|
||||||
static int todo_is_uncompleted(struct todo *todo, void *cbdata)
|
static int todo_is_uncompleted(struct todo *todo, void *cbdata)
|
||||||
{
|
{
|
||||||
return todo->id >= 0;
|
return !todo->completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a structure containing the selected item. */
|
/* Returns a structure containing the selected item. */
|
||||||
@ -64,27 +64,20 @@ struct todo *todo_get_item(int item_number, int skip_completed)
|
|||||||
|
|
||||||
static int todo_cmp_id(struct todo *a, struct todo *b)
|
static int todo_cmp_id(struct todo *a, struct todo *b)
|
||||||
{
|
{
|
||||||
/*
|
return a->id - b->id;
|
||||||
* As of version 2.6, todo items can have a negative id, which means they
|
|
||||||
* were completed. To keep them sorted, we need to consider the absolute id
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
int abs_a = abs(a->id);
|
|
||||||
int abs_b = abs(b->id);
|
|
||||||
|
|
||||||
return abs_a < abs_b ? -1 : (abs_a == abs_b ? 0 : 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add an item in the todo linked list.
|
* Add an item in the todo linked list.
|
||||||
*/
|
*/
|
||||||
struct todo *todo_add(char *mesg, int id, char *note)
|
struct todo *todo_add(char *mesg, int id, int completed, char *note)
|
||||||
{
|
{
|
||||||
struct todo *todo;
|
struct todo *todo;
|
||||||
|
|
||||||
todo = mem_malloc(sizeof(struct todo));
|
todo = mem_malloc(sizeof(struct todo));
|
||||||
todo->mesg = mem_strdup(mesg);
|
todo->mesg = mem_strdup(mesg);
|
||||||
todo->id = id;
|
todo->id = id;
|
||||||
|
todo->completed = completed;
|
||||||
todo->note = (note != NULL
|
todo->note = (note != NULL
|
||||||
&& note[0] != '\0') ? mem_strdup(note) : NULL;
|
&& note[0] != '\0') ? mem_strdup(note) : NULL;
|
||||||
|
|
||||||
@ -96,11 +89,13 @@ struct todo *todo_add(char *mesg, int id, char *note)
|
|||||||
char *todo_tostr(struct todo *todo)
|
char *todo_tostr(struct todo *todo)
|
||||||
{
|
{
|
||||||
char *res;
|
char *res;
|
||||||
|
const char *cstr = todo->completed ? "-" : "";
|
||||||
|
|
||||||
if (todo->note)
|
if (todo->note)
|
||||||
asprintf(&res, "[%d]>%s %s", todo->id, todo->note, todo->mesg);
|
asprintf(&res, "[%s%d]>%s %s", cstr, todo->id, todo->note,
|
||||||
|
todo->mesg);
|
||||||
else
|
else
|
||||||
asprintf(&res, "[%d] %s", todo->id, todo->mesg);
|
asprintf(&res, "[%s%d] %s", cstr, todo->id, todo->mesg);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -144,15 +139,10 @@ void todo_delete(struct todo *todo)
|
|||||||
mem_free(todo);
|
mem_free(todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Flag a todo item. */
|
||||||
* Flag a todo item (for now on, only the 'completed' state is available).
|
|
||||||
* Internally, a completed item keeps its priority, but it becomes negative.
|
|
||||||
* This way, it is easy to retrive its original priority if the user decides
|
|
||||||
* that in fact it was not completed.
|
|
||||||
*/
|
|
||||||
void todo_flag(struct todo *t)
|
void todo_flag(struct todo *t)
|
||||||
{
|
{
|
||||||
t->id = -t->id;
|
t->completed = !t->completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -60,7 +60,7 @@ void ui_todo_add(void)
|
|||||||
status_mesg(mesg_id, "");
|
status_mesg(mesg_id, "");
|
||||||
ch = wgetch(win[KEY].p);
|
ch = wgetch(win[KEY].p);
|
||||||
}
|
}
|
||||||
todo_add(todo_input, ch - '0', NULL);
|
todo_add(todo_input, ch - '0', 0, NULL);
|
||||||
ui_todo_load_items();
|
ui_todo_load_items();
|
||||||
io_set_modified();
|
io_set_modified();
|
||||||
}
|
}
|
||||||
@ -163,14 +163,14 @@ void ui_todo_draw(int n, WINDOW *win, int y, int hilt, void *cb_data)
|
|||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW) {
|
if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW) {
|
||||||
while (i && todo->id < 0) {
|
while (i && todo->completed) {
|
||||||
i = i->next;
|
i = i->next;
|
||||||
if (i)
|
if (i)
|
||||||
todo = LLIST_TS_GET_DATA(i);
|
todo = LLIST_TS_GET_DATA(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mark[0] = todo->id > 0 ? '0' + todo->id : 'X';
|
mark[0] = todo->completed ? 'X' : '0' + todo->id;
|
||||||
mark[1] = todo->note ? '>' : '.';
|
mark[1] = todo->note ? '>' : '.';
|
||||||
|
|
||||||
hilt = hilt && (wins_slctd() == TOD);
|
hilt = hilt && (wins_slctd() == TOD);
|
||||||
@ -217,7 +217,8 @@ void ui_todo_load_items(void)
|
|||||||
/* TODO: Optimize this by keeping the list size in a variable. */
|
/* 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);
|
struct todo *todo = LLIST_TS_GET_DATA(i);
|
||||||
if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW && todo->id < 0)
|
if (ui_todo_view == TODO_HIDE_COMPLETED_VIEW &&
|
||||||
|
todo->completed)
|
||||||
continue;
|
continue;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
@ -263,7 +264,7 @@ void ui_todo_chg_priority(int diff)
|
|||||||
else if (id > 9)
|
else if (id > 9)
|
||||||
id = 9;
|
id = 9;
|
||||||
|
|
||||||
item_new = todo_add(item->mesg, id, item->note);
|
item_new = todo_add(item->mesg, id, item->completed, item->note);
|
||||||
todo_delete(item);
|
todo_delete(item);
|
||||||
io_set_modified();
|
io_set_modified();
|
||||||
listbox_set_sel(&lb_todo, todo_get_position(item_new));
|
listbox_set_sel(&lb_todo, todo_get_position(item_new));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user