From: Andy Spencer Date: Mon, 22 Oct 2012 00:35:19 +0000 (+0000) Subject: Add ical todos X-Git-Url: http://pileus.org/git/?p=lackey;a=commitdiff_plain;h=ba2658aef9fdf5965818bddaef06ce2e3945bd41 Add ical todos --- diff --git a/cals/ical.c b/cals/ical.c index 028385b..8506e25 100644 --- a/cals/ical.c +++ b/cals/ical.c @@ -45,55 +45,20 @@ static date_t to_date(struct icaltimetype time) { return (date_t){ .year = time.year, - .month = time.month-1, - .day = time.day-1, + .month = time.month ? time.month-1 : 0, + .day = time.day ? time.day -1 : 0, .hour = time.hour, .min = time.minute, }; } -static event_t *to_event(ical_inst *inst) -{ - icalproperty *prop = icalcomponent_get_first_property(inst->comp, ICAL_CATEGORIES_PROPERTY); - - event_t *event = calloc(1, sizeof(event_t)); - event->name = icalcomponent_get_summary(inst->comp); - event->desc = icalcomponent_get_description(inst->comp); - event->loc = icalcomponent_get_location(inst->comp); - event->cat = icalproperty_get_value_as_string(prop); - event->start = to_date(inst->start); - event->end = to_date(inst->end); - return event; -} - -static event_t *to_list(icalarray *array) -{ - event_t list = {}; - event_t *tail = &list; - for (int i = 0; i < array->num_elements; i++) { - ical_inst *inst = icalarray_element_at(array, i); - tail->next = to_event(inst); - tail = tail->next; - } - return list.next; -} - -static void print_list(event_t *start) -{ - for (event_t *cur = start; cur; cur = cur->next) - printf("%04d-%02d-%02d %02d:%02d - %s\n", - cur->start.year, cur->start.month, cur->start.day, - cur->start.hour, cur->start.min, - cur->name ?: cur->desc ?: "[no summary]"); -} - -static void add_events(icalarray *array, icalcomponent *comp, - icaltimetype start, icaltimetype end) +static void add_recur(icalarray *array, icalcomponent *comp, + icaltimetype start, icaltimetype end, + icalcomponent_kind which) { icalcomponent_kind kind = icalcomponent_isa(comp); - if (kind == ICAL_VEVENT_COMPONENT || - kind == ICAL_VTODO_COMPONENT) { + if (kind == which) { /* Get recurrence data */ struct icaltimetype cstart, cend; // Component times struct icaltimetype istart, iend; // Instance times @@ -112,15 +77,25 @@ static void add_events(icalarray *array, icalcomponent *comp, iter = icalrecur_iterator_new(recur, cstart); /* Add recurrences */ - while (1) { - istart = icalrecur_iterator_next(iter); + if (icaltime_is_null_time(cstart) || + which == ICAL_VTODO_COMPONENT) { + icalarray_append(array, &(ical_inst){ + .comp = comp, + .start = cstart, + .end = cend, + }); + } else while (1) { + istart = iend = icalrecur_iterator_next(iter); if (icaltime_is_null_time(istart)) break; // no more instances - iend = icaltime_add(istart, length); + if (!icaltime_is_null_time(cend)) + iend = icaltime_add(iend, length); + if (icaltime_compare(iend, start) <= 0) continue; // instance ends before start time if (icaltime_compare(istart, end) >= 0) break; // instance begins after stop time + icalarray_append(array, &(ical_inst){ .comp = comp, .start = istart, @@ -133,11 +108,85 @@ static void add_events(icalarray *array, icalcomponent *comp, icalcomponent_kind find = ICAL_ANY_COMPONENT; icalcomponent *child = icalcomponent_get_first_component(comp, find); while (child) { - add_events(array, child, start, end); + add_recur(array, child, start, end, which); child = icalcomponent_get_next_component(comp, find); } } +/* Event functions */ +static event_t *to_event(ical_inst *inst) +{ + icalproperty *prop = icalcomponent_get_first_property(inst->comp, ICAL_CATEGORIES_PROPERTY); + + event_t *event = calloc(1, sizeof(event_t)); + event->name = icalcomponent_get_summary(inst->comp); + event->desc = icalcomponent_get_description(inst->comp); + event->loc = icalcomponent_get_location(inst->comp); + event->cat = icalproperty_get_value_as_string(prop); + event->start = to_date(inst->start); + event->end = to_date(inst->end); + return event; +} + +static event_t *to_events(icalarray *array) +{ + event_t list = {}; + event_t *tail = &list; + for (int i = 0; i < array->num_elements; i++) { + ical_inst *inst = icalarray_element_at(array, i); + tail->next = to_event(inst); + tail = tail->next; + } + return list.next; +} + +static void print_events(event_t *start) +{ + for (event_t *cur = start; cur; cur = cur->next) + printf("%04d-%02d-%02d %02d:%02d - %s\n", + cur->start.year, cur->start.month, cur->start.day, + cur->start.hour, cur->start.min, + cur->name ?: cur->desc ?: "[no summary]"); +} + +/* Todo functions */ +static todo_t *to_todo(ical_inst *inst) +{ + icalproperty *cat = icalcomponent_get_first_property(inst->comp, ICAL_CATEGORIES_PROPERTY); + icalproperty *perc = icalcomponent_get_first_property(inst->comp, ICAL_PERCENTCOMPLETE_PROPERTY); + + todo_t *todo = calloc(1, sizeof(todo_t)); + todo->name = icalcomponent_get_summary(inst->comp); + todo->desc = icalcomponent_get_description(inst->comp); + todo->cat = icalproperty_get_value_as_string(cat); + todo->status = icalcomponent_get_status(inst->comp) == ICAL_STATUS_COMPLETED ? 100 : + perc ? icalproperty_get_percentcomplete(perc) : 0; + todo->start = to_date(inst->start); + todo->due = to_date(icalcomponent_get_due(inst->comp)); + return todo; +} + +static todo_t *to_todos(icalarray *array) +{ + todo_t list = {}; + todo_t *tail = &list; + for (int i = 0; i < array->num_elements; i++) { + ical_inst *inst = icalarray_element_at(array, i); + tail->next = to_todo(inst); + tail = tail->next; + } + return list.next; +} + +static void print_todos(todo_t *start) +{ + for (todo_t *cur = start; cur; cur = cur->next) + printf("%04d-%02d-%02d %02d:%02d - %d%% - %s\n", + cur->due.year, cur->due.month, cur->due.day, + cur->due.hour, cur->due.min, cur->status, + cur->name ?: cur->desc ?: "[no summary]"); +} + /* Event functions */ event_t *ical_events(cal_t *cal, year_t year, month_t month, day_t day, int days) { @@ -153,9 +202,9 @@ event_t *ical_events(cal_t *cal, year_t year, month_t month, day_t day, int days icalarray *array = icalarray_new(sizeof(ical_inst), 1); icaltimetype start = {.year = 2000}; icaltimetype end = {.year = 2020}; - add_events(array, ical, start, end); + add_recur(array, ical, start, end, ICAL_VEVENT_COMPONENT); icalarray_sort(array, ical_compare); - return to_list(array); + return to_events(array); /* Todo, memory management */ } @@ -163,7 +212,23 @@ event_t *ical_events(cal_t *cal, year_t year, month_t month, day_t day, int days /* Todo functions */ todo_t *ical_todos(cal_t *cal, year_t year, month_t month, day_t day, int days) { - return NULL; + /* Load ical */ + FILE *file = fopen("data/all.ics", "r"); + if (!file) + return NULL; + icalparser *parser = icalparser_new(); + icalparser_set_gen_data(parser, file); + icalcomponent *ical = icalparser_parse(parser, (void*)fgets); + + /* Add todos */ + icalarray *array = icalarray_new(sizeof(ical_inst), 1); + icaltimetype start = {.year = 2000}; + icaltimetype end = {.year = 2020}; + add_recur(array, ical, start, end, ICAL_VTODO_COMPONENT); + icalarray_sort(array, ical_compare); + return to_todos(array); + + /* Todo, memory management */ } /* Test functions */ @@ -195,17 +260,32 @@ void ical_test(void) icalparser_set_gen_data(parser, file); icalcomponent *ical = icalparser_parse(parser, (void*)fgets); - /* Test print */ - ical_printr(ical, 0); - - /* Test Add */ - icalarray *array = icalarray_new(sizeof(ical_inst), 1); + /* Misc */ + icalarray *array; icaltimetype start = {.year = 2000}; icaltimetype end = {.year = 2020}; - add_events(array, ical, start, end); + + /* Find events */ + array = icalarray_new(sizeof(ical_inst), 1); + add_recur(array, ical, start, end, ICAL_VEVENT_COMPONENT); + icalarray_sort(array, ical_compare); + event_t *events = to_events(array); + + /* Find Todos */ + array = icalarray_new(sizeof(ical_inst), 1); + add_recur(array, ical, start, end, ICAL_VTODO_COMPONENT); icalarray_sort(array, ical_compare); - event_t *events = to_list(array); - print_list(events); + todo_t *todos = to_todos(array); + + /* Print */ + //ical_printr(ical, 0); + //print_events(events); + print_todos(todos); + + (void)print_events; + (void)print_todos; + (void)events; + (void)todos; /* Cleanup */ icalparser_free(parser); diff --git a/src/main.c b/src/main.c index e02cda0..cc1444a 100644 --- a/src/main.c +++ b/src/main.c @@ -52,6 +52,10 @@ int main(int argc, char **argv) init_pair(COLOR_TITLE, COLOR_GREEN, -1); init_pair(COLOR_ERROR, COLOR_RED, -1); + init_pair(COLOR_NEW, COLOR_RED, -1); + init_pair(COLOR_WIP, COLOR_YELLOW, -1); + init_pair(COLOR_DONE, COLOR_GREEN, -1); + init_pair(COLOR_CLASS, COLOR_BLUE, -1); init_pair(COLOR_EC, COLOR_GREEN, -1); init_pair(COLOR_WORK, COLOR_MAGENTA, -1); diff --git a/src/util.c b/src/util.c index 24a8f37..929ec04 100644 --- a/src/util.c +++ b/src/util.c @@ -34,6 +34,14 @@ void util_init(void) debug_fd = fopen("/tmp/lackey.log", "w+"); } +/* String functions */ +void strsub(char *str, char find, char repl) +{ + for (char *cur = str; *cur; cur++) + if (*cur == find) + *cur = repl; +} + /* Debugging functions */ int debug(char *fmt, ...) { diff --git a/src/util.h b/src/util.h index b40f8b3..689ed62 100644 --- a/src/util.h +++ b/src/util.h @@ -25,6 +25,9 @@ /* Debug functions */ void util_init(void); +/* Stirng functions */ +void strsub(char *str, char find, char repl); + /* Debug functions */ #ifdef DEBUG int debug(char *fmt, ...); diff --git a/src/view.c b/src/view.c index ac33fc8..3f1adb1 100644 --- a/src/view.c +++ b/src/view.c @@ -129,20 +129,38 @@ void event_line(WINDOW *win, event_t *event, int y, int x, int w, int full) void todo_line(WINDOW *win, todo_t *todo, int y, int x, int w, int full) { char perc[16]; + char desc[LINES]; sprintf(perc, "%2d%%", todo->status); - int color = get_color(todo->cat); - if (color) wattron(win, COLOR_PAIR(color)); - mvwaddch(win, y, 2, ACS_BLOCK); - if (color) wattroff(win, COLOR_PAIR(color)); + int cat = get_color(todo->cat); + int status = todo->status == NEW ? COLOR_NEW : + todo->status == DONE ? COLOR_DONE : COLOR_WIP; + + sprintf(desc, "%s", todo->name ?: todo->desc ?: ""); + strsub(desc, '\n', ';'); + + /* Print category */ + if (cat) wattron(win, COLOR_PAIR(cat)); + mvwaddch(win, y, x, ACS_BLOCK); + if (cat) wattroff(win, COLOR_PAIR(cat)); + x += 2; - mvwprintw(win, y, 4, "%04d-%02d-%02d %2d:%02d", + /* Print time */ + mvwprintw(win, y, x, "%04d-%02d-%02d %2d:%02d", todo->due.year, todo->due.month+1, todo->due.day+1, todo->due.hour, todo->due.min); - mvwprintw(win, y, 22, "%s", - todo->status == NEW ? "new" : - todo->status == DONE ? "done" : perc); - mvwprintw(win, y, 30, "%s: %s", todo->name, todo->desc); + x += 18; + + /* Print status */ + if (status) wattron(win, COLOR_PAIR(status)); + mvwprintw(win, y, x, "%s", + todo->status == NEW ? "new" : + todo->status == DONE ? "done" : perc); + if (status) wattroff(win, COLOR_PAIR(status)); + x += 6; + + /* Print description */ + mvwprintw(win, y, x, "%s", desc); } /* View init */ diff --git a/src/view.h b/src/view.h index 033cae5..b72249b 100644 --- a/src/view.h +++ b/src/view.h @@ -19,10 +19,14 @@ #define COLOR_TITLE 1 #define COLOR_ERROR 2 -#define COLOR_CLASS 3 -#define COLOR_EC 4 -#define COLOR_WORK 5 -#define COLOR_OTHER 6 +#define COLOR_NEW 3 +#define COLOR_WIP 4 +#define COLOR_DONE 5 + +#define COLOR_CLASS 6 +#define COLOR_EC 7 +#define COLOR_WORK 8 +#define COLOR_OTHER 9 /* Helper functions */ void event_box(WINDOW *win, event_t *event, int y, int x, int h, int w); diff --git a/views/events.c b/views/events.c index 1a8f8b9..1b0d691 100644 --- a/views/events.c +++ b/views/events.c @@ -76,9 +76,9 @@ void events_draw(void) wattroff(win, A_UNDERLINE); row++; } - event_line(win, event, row++-line, 3, COLS-2, 1); + event_line(win, event, row++-line, 4, COLS-2, 1); if (event->name && event->desc) - mvwprintw(win, row++-line, 13, "%s", event->desc); + mvwprintw(win, row++-line, 14, "%s", event->desc); cur = next; count += 1; } diff --git a/views/todo.c b/views/todo.c index 27fdfcd..e452794 100644 --- a/views/todo.c +++ b/views/todo.c @@ -24,40 +24,42 @@ /* Static data */ static WINDOW *win; +static int line; +static int rows; static int show_new = 1; static int show_started = 1; static int show_finished = 1; /* Helper functions */ -static int print_todos(WINDOW *win, int y, todo_t *todos, status_t low, status_t high) +static int print_todos(WINDOW *win, int row, todo_t *todos, status_t low, status_t high) { int n = 0; for (todo_t *cur = todos; cur; cur = cur->next) if (low <= cur->status && cur->status <= high) - todo_line(win, cur, y+n++, 2, COLS-2, 1); + todo_line(win, cur, row+n++, 4, COLS-4, 1); return n; } -static int print_group(WINDOW *win, int y, todo_t *todos, +static int print_group(WINDOW *win, int row, todo_t *todos, int show, const char *label, status_t low, status_t high) { int n = 1; /* Label */ - mvwprintw(win, y, 0, "%s", label); + mvwprintw(win, row, 0, "%s", label); /* Todos */ if (show) - n = print_todos(win, y+1, todos, low, high); + n = print_todos(win, row+1, todos, low, high); /* Status */ if (!show) - mvwprintw(win, y+1, 4, "[hidden]"); + mvwprintw(win, row+1, 4, "[hidden]"); if (n == 0) - mvwprintw(win, y+1, 4, "[no tasks]"); + mvwprintw(win, row+1, 4, "[no tasks]"); - return y+1+MAX(n,1)+1; + return row+1+MAX(n,1)+1; } /* Todo init */ @@ -74,28 +76,35 @@ void todo_size(int rows, int cols) /* Todo draw */ void todo_draw(void) { - int y = 0; + int row = -line; - y = print_group(win, y, TODOS, + row = print_group(win, row, TODOS, show_new, "New Tasks", NEW, NEW); - y = print_group(win, y, TODOS, + row = print_group(win, row, TODOS, show_started, "Started Tasks", NEW+1, DONE-1); - y = print_group(win, y, TODOS, + row = print_group(win, row, TODOS, show_finished, "Finished Tasks", DONE, DONE); + + rows = row+line-1; } /* Todo run */ int todo_run(int key, mmask_t btn, int row, int col) { - int ref = 0; + int scroll = 0, ref = 0; switch (key) { + case 'g': ref = 1; scroll = -line; break; + case 'G': ref = 1; scroll = rows; break; + case 'j': ref = 1; scroll = 1; break; + case 'k': ref = 1; scroll = -1; break; case 'n': ref = 1; show_new ^= 1; break; case 's': ref = 1; show_started ^= 1; break; case 'f': ref = 1; show_finished ^= 1; break; } + line = CLAMP(line+scroll, 0, rows-1); if (ref) { werase(win); todo_draw();