diff --git a/src/main/include/models.h b/src/main/include/models.h index 6072be3..2e402e0 100644 --- a/src/main/include/models.h +++ b/src/main/include/models.h @@ -22,26 +22,11 @@ void klist_user_delete(klist *, klist_user *); void klist_user_deinit(klist_user *); -struct klist_stage { - ssize_t id; - unsigned char *name; - unsigned char *desc; - ssize_t list_id; -}; -typedef struct klist_stage klist_stage; - -klist_stage *klist_stage_init(); -klist_stage *klist_stage_init_from_sql(sqlite3_stmt *); -klist_stage *klist_stage_get_by_id(klist *, u_int); -void klist_stage_save(klist *, klist_stage *); -void klist_stage_delete(klist *, klist_stage *); -void klist_stage_deinit(klist_stage *); - - struct klist_list { ssize_t id; unsigned char *name; unsigned char *desc; + bool is_preset; }; typedef struct klist_list klist_list; @@ -55,6 +40,23 @@ void klist_list_delete(klist *, klist_list *); void klist_list_deinit(klist_list *); +struct klist_stage { + ssize_t id; + unsigned char *name; + unsigned char *desc; + ssize_t list_id; +}; +typedef struct klist_stage klist_stage; + +klist_stage *klist_stage_init(); +klist_stage *klist_stage_init_from_sql(sqlite3_stmt *); +klist_stage *klist_stage_get_by_id(klist *, u_int); +klist_stage **klist_stage_get_all_for_list(klist *, u_int, size_t *); +void klist_stage_save(klist *, klist_stage *); +void klist_stage_delete(klist *, klist_stage *); +void klist_stage_deinit(klist_stage *); + + struct klist_task { ssize_t id; unsigned char *name; @@ -69,7 +71,8 @@ typedef struct klist_task klist_task; klist_task *klist_task_init(); klist_task *klist_task_init_from_sql(sqlite3_stmt *); klist_task *klist_task_get_by_id(klist *, u_int); -klist_task **klist_task_get_for_list(klist *, u_int, u_int *); +klist_task **klist_task_get_for_list(klist *, u_int, size_t *); +klist_task *klist_task_get_for_list_by_name(klist *, u_int, const char *); void klist_task_save(klist *, klist_task *); void klist_task_delete(klist *, klist_task *); void klist_task_deinit(klist_task *); diff --git a/src/main/include/sql.h b/src/main/include/sql.h index d9b678b..a60688e 100644 --- a/src/main/include/sql.h +++ b/src/main/include/sql.h @@ -25,6 +25,7 @@ enum KLIST_SQL { GET_TASK, GET_TASKS, GET_TASKS_FOR_LIST, + GET_TASKS_FOR_LIST_BY_NAME, MOD_TASK_NAME, MOD_TASK_DESCRIPTION, DEL_TASK, diff --git a/src/main/include/util.h b/src/main/include/util.h index e4524e4..d539acf 100644 --- a/src/main/include/util.h +++ b/src/main/include/util.h @@ -52,6 +52,7 @@ struct klist_list_context { char *desc; char **stages; size_t stages_len; + char *preset; }; typedef struct klist_list_context klist_list_context; @@ -70,6 +71,7 @@ struct klist_task_context { enum klist_task_command cmd; char *list; char *name; + char *desc; char *stage; }; typedef struct klist_task_context klist_task_context; diff --git a/src/main/main.c b/src/main/main.c index 4d5d737..af33bee 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -20,10 +20,12 @@ int main(int argc, char **argv) { if (!ctx->error) { setup(ctx, argc, argv); klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = NULL; int i = 0; switch (ctx->cmd) { case USER: - switch (((klist_user_context *)ctx->cmd_ctx)->cmd) { + klist_user_context *user_ctx = ctx->cmd_ctx; + switch (user_ctx->cmd) { case USER_GET: if (user) { fprintf( @@ -51,9 +53,10 @@ int main(int argc, char **argv) { } else fprintf(stderr, "User not found, no changes done.\n"); break; } + klist_user_context_deinit(user_ctx); + break; case LIST: klist_list_context *list_ctx = ctx->cmd_ctx; - klist_list *list = NULL; if (!list_ctx->name) { fprintf(stderr, "Missing name.\n"); break; } switch (list_ctx->cmd) { case LIST_ADD: @@ -61,6 +64,7 @@ int main(int argc, char **argv) { list = klist_list_init(); list->name = (unsigned char*)list_ctx->name; list->desc = (unsigned char*)list_ctx->desc; + list->is_preset = false; klist_list_save(ctx, list); i = 0; for (; i < list_ctx->stages_len; i++) { @@ -79,9 +83,9 @@ int main(int argc, char **argv) { user = klist_user_get_by_local(ctx, getuid()); list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); if (list) { - u_int tasks_len = 0; + size_t tasks_len = 0; klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); - fprintf(stderr, "Name: %s\nDescription: %s\nTasks: %d\n", list->name, list->desc, tasks_len); + fprintf(stderr, "Name: %s\nDescription: %s\nTasks: %ld\n", (char *)list->name, (char *)list->desc, tasks_len); int i = 0; for(; i < tasks_len; i++) klist_task_deinit(tasks[i]); free(tasks); @@ -91,7 +95,7 @@ int main(int argc, char **argv) { case LIST_DELETE: list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); if (list) { - u_int tasks_len = 0; + size_t tasks_len = 0; klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); int i = 0; for (; i < tasks_len; i++) { @@ -101,18 +105,106 @@ int main(int argc, char **argv) { free(tasks); } } - if (!list) klist_list_deinit(list); + if (list_ctx) klist_list_context_deinit(list_ctx); + break; case TASK: + klist_task_context *task_ctx = ctx->cmd_ctx; switch (((klist_task_context *)ctx->cmd_ctx)->cmd) { - case TASK_ADD: + case TASK_ADD: // basically the same things happen and edit can create if nescessary case TASK_EDIT: + klist_assure_user(ctx, getuid(), getlogin()); + user = klist_user_get_by_local(ctx, getuid()); + list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); + if (list) { + size_t stages_len = 0; + klist_stage **stages = klist_stage_get_all_for_list(ctx, list->id, &stages_len); + if (!task_ctx->stage) { + fprintf(stderr, "Stage missing/wrong, please pass one of: "); + i = 0; + for (; i < stages_len; i++) + fprintf(stderr, "%s ", (char *)stages[i]->name); + fprintf(stderr, "\n"); + break; + } + i = 0; + ssize_t stage_id = -1; + for (; i < stages_len; i++) + if (strcmp((char *)stages[i]->name, (char *)task_ctx->stage) == 0) + stage_id = stages[i]->id; + + if (stage_id == -1) { + fprintf(stderr, "Stage %s not found. Use one of: ", (char *)task_ctx->stage); + i = 0; + for (; i < stages_len; i++) + fprintf(stderr, "%s ", (char *)stages[i]->name); + fprintf(stderr, "\n"); + } + i = 0; + for (; i < stages_len; i++) + klist_stage_deinit(stages[i]); + free(stages); + if (ctx->error) break; + + klist_task *task = klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); + if (!task) task = klist_task_init(); + task->name = (unsigned char*)task_ctx->name; + if (task_ctx->desc) task->desc = (unsigned char*)task_ctx->desc; + task->stage_id = stage_id; + klist_task_save(ctx, task); + klist_task_deinit(task); + } else fprintf(stderr, "List not found.\n"); + break; case TASK_GET: + klist_assure_user(ctx, getuid(), getlogin()); + user = klist_user_get_by_local(ctx, getuid()); + list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); + if (list) { + if (task_ctx->name) { + klist_task *task = klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); + if (task) { + fprintf(stderr, "Name: %s\n", (char *)task->name); + fprintf(stderr, "Description: %s\n", (char *)task->desc); + klist_stage *stage = klist_stage_get_by_id(ctx, task->stage_id); + fprintf(stderr, "Stage: %s\n", (char*)stage->name); + klist_stage_deinit(stage); + klist_task_deinit(task); + } else fprintf(stderr, "Task not found.\n"); + } else { + size_t tasks_len = 0; + klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); + i = 0; + for (; i < tasks_len; i++) { + fprintf(stderr, "Name: %s\n", (char *)tasks[i]->name); + fprintf(stderr, "Description: %s\n", (char *)tasks[i]->desc); + klist_stage *stage = klist_stage_get_by_id(ctx, tasks[i]->stage_id); + fprintf(stderr, "Stage: %s\n", (char*)stage->name); + klist_stage_deinit(stage); + klist_task_deinit(tasks[i]); + if ((i+1) < tasks_len) fprintf(stderr, "\n"); + } + } + } else fprintf(stderr, "List not found"); case TASK_DELETE: + klist_assure_user(ctx, getuid(), getlogin()); + user = klist_user_get_by_local(ctx, getuid()); + list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); + if (list) { + if (task_ctx) { + klist_task *task = klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); + if (task) { + fprintf(stderr, "Deleting task '%s'.\n", (char *)task->name); + klist_task_delete(ctx, task); + klist_task_deinit(task); + } else fprintf(stderr, "Task not found.\n"); + } else fprintf(stderr, "Task not found, only deletion by name is currently supoprted.\n"); + + } fprintf(stderr, "Not implemented\n"); - ; } + klist_task_context_deinit(task_ctx); default: ; } + if (list) klist_list_deinit(list); if (user) klist_user_deinit(user); } @@ -163,7 +255,7 @@ void setup(klist *ctx, int argc, char **argv) { klist_list_context *list_ctx = malloc(sizeof(struct klist_list_context)); optind = 3; - while ((opt = getopt(argc, argv, "aeds:")) != -1) + while ((opt = getopt(argc, argv, "adep:s:")) != -1) switch (opt) { case 'a': list_ctx->cmd = LIST_ADD; @@ -174,14 +266,19 @@ void setup(klist *ctx, int argc, char **argv) { case 'd': list_ctx->cmd = LIST_DELETE; break; + case 'p': + list_ctx->preset = malloc((strlen(optarg) + 1) * sizeof(char)); + strcpy(list_ctx->preset, optarg); + break; default: print_help(argv); fprintf(stderr, "" - "list options:" - "-a\tadd a list" - "-e\tedit a list" - "-d\tdelete a list" - "Not providing a parameter prints all lists."); + "list options:\n" + "-a\t\tadd a list\n" + "-e\t\tedit a list\n" + "-d\t\tdelete a list\n" + "-p \tdefine as preset or use existing one with name " + "Not providing a parameter prints all lists and existing presets."); } ctx->cmd_ctx = list_ctx; break; @@ -190,7 +287,7 @@ void setup(klist *ctx, int argc, char **argv) { fprintf(stderr, "Prints all lists.\n"); break; } - klist_list_context *task_ctx = malloc(sizeof(struct klist_task_context)); + klist_task_context *task_ctx = malloc(sizeof(struct klist_task_context)); optind = 3; diff --git a/src/main/models.c b/src/main/models.c index 9f987db..4625b1d 100644 --- a/src/main/models.c +++ b/src/main/models.c @@ -60,7 +60,7 @@ void klist_user_save(klist *ctx, klist_user *user) { int result = 0; sqlite3_bind_int(stmt, 1, user->id); sqlite3_bind_int(stmt, 2, user->local_id); - if ((result = sqlite3_step(stmt)) == SQLITE_ROW) + if ((result = sqlite3_step(stmt)) != SQLITE_ROW) fprintf(stderr, "failed to save logins for user: %s - %d\n", sqlite3_errmsg(ctx->db), result); sqlite3_clear_bindings(stmt); } @@ -113,6 +113,23 @@ klist_stage *klist_stage_get_by_id(klist *ctx, u_int id) { return NULL; } +klist_stage **klist_stage_get_all_for_list(klist *ctx, u_int id, size_t *count) { + sqlite3_stmt *stmt = ctx->stmts[GET_STAGES_FOR_LIST]; + sqlite3_bind_int(stmt, 1, id); + klist_stage **stages = NULL; + size_t stages_len = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + stages_len++; + klist_stage **_stages = realloc(stages, stages_len * sizeof(klist_stage *)); + if (_stages) { + stages = _stages; + stages[stages_len - 1] = klist_stage_init(stmt); + } + } + if (count != NULL) *count = stages_len; + return stages; +} + void klist_stage_save(klist *ctx, klist_stage *stage) { sqlite3_stmt *stmt = ctx->stmts[ADD_STAGE]; int result = 0; @@ -136,6 +153,7 @@ klist_list *klist_list_init() { list->id = -1; list->name = NULL; list->desc = NULL; + list->is_preset = false; return list; } @@ -151,6 +169,7 @@ klist_list *klist_list_init_from_sql(sqlite3_stmt *stmt) { list->desc = malloc(bytes); memcpy(list->desc, sqlite3_column_text(stmt, 2), bytes); } + list->is_preset = sqlite3_column_int(stmt, 3) ? true : false; return list; } @@ -186,7 +205,7 @@ klist_list *klist_list_get_by_user_and_name(klist *ctx, u_int user_id, const cha sqlite3_bind_int(stmt, 1, user_id); sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC); - while (sqlite3_step(stmt) == SQLITE_ROW) { + if (sqlite3_step(stmt) == SQLITE_ROW) { sqlite3_clear_bindings(stmt); return klist_list_init(stmt); } @@ -244,7 +263,7 @@ klist_task *klist_task_get_by_id(klist *ctx, u_int id) { return NULL; } -klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, u_int *count) { +klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, size_t *count) { sqlite3_stmt *stmt = ctx->stmts[GET_TASKS_FOR_LIST]; sqlite3_bind_int(stmt, 1, list_id); klist_task **tasks = NULL; @@ -259,6 +278,18 @@ klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, u_int *count) { return tasks; } +klist_task *klist_task_get_for_list_by_name(klist *ctx, u_int list_id, const char *name) { + sqlite3_stmt *stmt = ctx->stmts[GET_TASKS_FOR_LIST_BY_NAME]; + sqlite3_bind_int(stmt, 1, list_id); + sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC); + + if (sqlite3_step(stmt) == SQLITE_ROW) { + sqlite3_clear_bindings(stmt); + return klist_task_init(stmt); + } + return NULL; +} + void klist_task_save(klist *ctx, klist_task *task) { sqlite3_stmt *stmt = ctx->stmts[ADD_TASK]; int result = 0; diff --git a/src/main/sql.c b/src/main/sql.c index db3e111..e50d9ac 100644 --- a/src/main/sql.c +++ b/src/main/sql.c @@ -24,7 +24,8 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { "create table if not exists lists (\n" " id integer primary key,\n" " name text not null,\n" - " desc text\n" + " desc text,\n" + " is_preset int not null\n" ");\n" "create table if not exists task_stages (\n" " id integer primary key,\n" @@ -51,7 +52,7 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { case GET_USERS: return "select * from users"; case MOD_USER_NAME: return "update users set name = ?1 where id = ?2"; case DEL_USER: return "delete from users where id = ?1"; - case ADD_LIST: return "insert into lists (name, desc) values (?1, ?2)"; + case ADD_LIST: return "insert into lists (name, desc, is_preset) values (?1, ?2, ?3)"; case GET_LIST: return "select * from lists where id = ?1"; case GET_LISTS: return "select * from lists"; case GET_LISTS_BY_USER: return "select * from lists inner join user_lists on user_lists.list_id = lists.id where user_lists.user_id = ?1"; @@ -60,12 +61,13 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { case DEL_LIST: return "delete from lists where id = ?1"; case ADD_STAGE: return "insert into task_stages (name, desc, list_id) values (?1, ?2, ?3)"; case GET_STAGE: return "select * from task_stages where id = ?1"; - case GET_STAGES_FOR_LIST: return "select * from task_stages"; + case GET_STAGES_FOR_LIST: return "select * from task_stages where list_id = ?1"; case DEL_STAGE: return "delete from task_stages where id = ?1"; case ADD_TASK: return "insert into tasks (name, desc, stage, due, target_stage) values (?1, ?2, ?3, ?4, ?5);"; case GET_TASK: return "select * from tasks where id = ?1"; case GET_TASKS: return "select * from tasks;"; case GET_TASKS_FOR_LIST: return "select tasks.* from tasks join task_stages on task_stages.id = tasks.stage where task_stages.list_id = ?1"; + case GET_TASKS_FOR_LIST_BY_NAME: return "select tasks.* from tasks join task_stages on task_stages.id = tasks.stage where task_stages.list_id = ?1 and tasks.name like ?2"; case MOD_TASK_NAME: return "update tasks set name = ?1 where id = ?2"; case MOD_TASK_DESCRIPTION: return "update tasks set desc = ?1 where id = ?2"; case DEL_TASK: return "delete from tasks where id = ?1"; diff --git a/src/main/util.c b/src/main/util.c index b98c453..53208d1 100644 --- a/src/main/util.c +++ b/src/main/util.c @@ -27,7 +27,7 @@ void klist_deinit(klist *ctx) { for (; i < _KLIST_SQL_COUNT; i++) sqlite3_finalize(ctx->stmts[i]); sqlite3_close(ctx->db); - if (ctx->cmd_ctx) free(ctx->cmd_ctx); + //if (ctx->cmd_ctx) free(ctx->cmd_ctx); free(ctx->stmts); free(ctx); } @@ -48,12 +48,18 @@ klist_list_context *klist_list_context_init(klist *list) { ctx->desc = NULL; ctx->stages = NULL; ctx->stages_len = 0; + ctx->preset = NULL; return ctx; } void klist_list_context_deinit(klist_list_context *ctx) { - int i = 0; - for (; i < ctx->stages_len; i++) free(ctx->stages[i]); - free(ctx->stages); + if (ctx->name) free(ctx->name); + if (ctx->desc) free(ctx->desc); + if (ctx->preset) free(ctx->preset); + if (ctx->stages) { + int i = 0; + for (; i < ctx->stages_len; i++) free(ctx->stages[i]); + free(ctx->stages); + } free(ctx); } @@ -61,12 +67,14 @@ klist_task_context *klist_task_context_init(klist *list) { klist_task_context *ctx = malloc(sizeof(klist_task_context)); ctx->cmd = -1; ctx->name = NULL; + ctx->list = NULL; ctx->stage = NULL; return ctx; } void klist_task_context_deinit(klist_task_context *ctx) { - free(ctx->name); - free(ctx->stage); + if (ctx->name) free(ctx->name); + if (ctx->list) free(ctx->list); + if (ctx->stage) free(ctx->stage); free(ctx); } @@ -91,6 +99,10 @@ void klist_sql_prepare(klist *ctx, char *db) { fprintf(stderr, "sqlite3_prepare: %s\n", sqlite3_errmsg(ctx->db)); } +void klist_sql_seed(klist *ctx) { + +} + /* * assuring things */