From 0f37f7be3756a071efb45b34e5e7b776839bbec4 Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Sun, 23 Feb 2025 16:29:30 +0100 Subject: [PATCH] add note content loader --- application/application.h | 1 + application/note.c | 19 +++++++++- application/note.h | 5 ++- application/notebook.c | 5 +-- application/store.c | 75 ++++++++++++++++++++++++++++++++++++++- application/store.h | 6 +++- application/window.c | 2 +- ui/gtk/list.c | 20 +++++++---- 8 files changed, 119 insertions(+), 14 deletions(-) diff --git a/application/application.h b/application/application.h index 895b786..e46198c 100644 --- a/application/application.h +++ b/application/application.h @@ -103,6 +103,7 @@ struct NotebookModel { struct NoteModel { UiContext *ctx; + const CxAllocator *note_allocator; UiInteger *type; UiString *title; diff --git a/application/note.c b/application/note.c index 7ac8e4f..4f3c913 100644 --- a/application/note.c +++ b/application/note.c @@ -28,9 +28,12 @@ #include "note.h" -NoteModel* notemodel_create() { +#include "store.h" + +NoteModel* notemodel_create(const CxAllocator *note_allocator) { NoteModel *model = ui_document_new(sizeof(NoteModel)); model->ctx = ui_document_context(model); + model->note_allocator = note_allocator; model->type = ui_int_new(model->ctx, "note_type"); model->title = ui_string_new(model->ctx, "note_title"); @@ -56,3 +59,17 @@ void notemodel_set_note(NoteModel *model, Note *note) { } } } + + +static void note_content_loaded(UiEvent *event, cxmutstr result, void *userdata) { + Note *note = userdata; + note->content = result; + printf("note content: %s\n", result.ptr); + if(note->model) { + ui_set(note->model->text, result.ptr); + } +} + +void note_load_content(UiObject *obj, NotebookModel *notebook, Note *note) { + note_store_get_note_content_async(obj, notebook->current_notes_pool->allocator, note->note_id, note_content_loaded, note); +} diff --git a/application/note.h b/application/note.h index a5beafb..e1242b4 100644 --- a/application/note.h +++ b/application/note.h @@ -35,9 +35,12 @@ extern "C" { #endif -NoteModel* notemodel_create(); +NoteModel* notemodel_create(const CxAllocator *note_allocator); void notemodel_set_note(NoteModel *model, Note *note); +// TODO: the interface is weird, but we need the NotebookModel for the allocator +void note_load_content(UiObject *obj, NotebookModel *notebook, Note *note); + #ifdef __cplusplus } diff --git a/application/notebook.c b/application/notebook.c index 50d3a9d..734c3ba 100644 --- a/application/notebook.c +++ b/application/notebook.c @@ -73,6 +73,7 @@ static void notebook_loaded(UiEvent *event, AsyncListResult *result, void *data) ui_list_append(model->notes, note); } ui_list_update(model->notes); + model->current_notes_pool = result->mp; } else { fprintf(stderr, "Error: get notes failed\n"); } @@ -89,7 +90,7 @@ void notebookmodel_attach_note(NotebookModel *model, Note *note) { } if(note && !note->model) { - NoteModel *notemodel = notemodel_create(); + NoteModel *notemodel = notemodel_create(model->current_notes_pool->allocator); notemodel_set_note(notemodel, note); } @@ -101,7 +102,7 @@ void notebookmodel_attach_note(NotebookModel *model, Note *note) { model->current_note = note; if(!note->content_loaded) { - // TODO: load content + note_load_content(model->window->obj, model, note); } } diff --git a/application/store.c b/application/store.c index cc3f59a..3ddcd62 100644 --- a/application/store.c +++ b/application/store.c @@ -57,6 +57,8 @@ #define SQL_NOTEBOOK_GET_NOTES "select note_id, parent_id, name, title, lastmodified, creationdate, contenttype, created_by from notes where parent_id = ? ;" +#define SQL_NOTE_GET_CONTENT "select content, bin_content from notes where note_id = ? ;" + static DBUConnection *connection; static UiThreadpool *queue; @@ -380,10 +382,81 @@ static int qthr_get_notes(JobGetNotes *job) { void note_store_get_notes_async(UiObject* obj, int64_t parent_collection_id, listresult_func resultcb, void *userdata) { JobGetNotes *job = malloc(sizeof(JobGetNotes)); - job->result.mp = cxMempoolCreate(128, NULL); + job->result.mp = cxMempoolCreateSimple(128); job->result.list = NULL; job->collection_id = parent_collection_id; job->resultcb = resultcb; job->userdata = userdata; ui_threadpool_job(queue, obj, (ui_threadfunc)qthr_get_notes, job, (ui_callback)uithr_get_notes_finished, job); } + + + +typedef struct GetNoteContentJob { + int64_t note_id; + stringresult_func resultcb; + void *userdata; + cxmutstr result; + const CxAllocator *a; +} GetNoteContentJob; + + + +cxmutstr note_store_get_note_content(const CxAllocator *a, int64_t note_id) { + cxmutstr content = (cxmutstr){NULL, 0}; + + DBUQuery *q = connection->createQuery(connection, NULL); + dbuQuerySetSQL(q, SQL_NOTE_GET_CONTENT); + dbuQuerySetParamInt64(q, 1, note_id); + + if(dbuQueryExec(q)) { + dbuQueryFree(q); + return content; + } + + DBUResult *result = dbuQueryGetResult(q); + dbuQueryFree(q); + if(!result) { + return content; + } + + if(result->hasData(result)) { + if(!result->isNull(result, 0)) { + cxstring s = result->getText(result, 0); + content = cx_strdup_a(a, s); + } else if(!result->isNull(result, 1)) { + if(result->optional_getBinary) { + DBUBytes b = result->optional_getBinary(result, 1); + content = cx_strdup_a(a, cx_strn((char*)b.bytes, b.length)); + } else { + cxstring s = result->getText(result, 1); + content = cx_strdup_a(a, s); + } + } + } + result->free(result); + + return content; +} + +static void uithr_get_note_content_finished(UiEvent *event, GetNoteContentJob *job) { + if(job->resultcb) { + job->resultcb(event, job->result, job->userdata); + } + free(job); +} + +static int qthr_get_note_content(GetNoteContentJob *job) { + job->result = note_store_get_note_content(job->a, job->note_id); + return 0; +} + +void note_store_get_note_content_async(UiObject *obj, const CxAllocator *a, int64_t note_id, stringresult_func resultcb, void *userdata) { + GetNoteContentJob *job = malloc(sizeof(GetNoteContentJob)); + job->result = (cxmutstr){NULL, 0}; + job->a = a; + job->note_id = note_id; + job->resultcb = resultcb; + job->userdata = userdata; + ui_threadpool_job(queue, obj, (ui_threadfunc)qthr_get_note_content, job, (ui_callback)uithr_get_note_content_finished, job); +} diff --git a/application/store.h b/application/store.h index 5974f04..9a49f35 100644 --- a/application/store.h +++ b/application/store.h @@ -51,6 +51,7 @@ typedef struct AsyncListResult { } AsyncListResult; typedef void (*listresult_func)(UiEvent *event, AsyncListResult *result, void *userdata); +typedef void (*stringresult_func)(UiEvent *event, cxmutstr result, void *userdata); int init_note_store(); @@ -78,7 +79,10 @@ void note_store_reload(); NoteStore* note_store_get(); CxList* note_store_get_notes(const CxAllocator *a, int64_t parent_collection_id); -void note_store_get_notes_async(UiObject* obj, int64_t parent_collection_id, listresult_func resultcb, void *userdata); +void note_store_get_notes_async(UiObject *obj, int64_t parent_collection_id, listresult_func resultcb, void *userdata); + +cxmutstr note_store_get_note_content(const CxAllocator *a, int64_t note_id); +void note_store_get_note_content_async(UiObject *obj, const CxAllocator *a, int64_t note_id, stringresult_func resultcb, void *userdata); #ifdef __cplusplus diff --git a/application/window.c b/application/window.c index c187074..323bad5 100644 --- a/application/window.c +++ b/application/window.c @@ -71,7 +71,7 @@ void window_create() { ui_textfield(obj, .varname = "note_title", .hexpand = TRUE, .groups = UI_GROUPS(APP_STATE_NOTE_SELECTED)); ui_newline(obj); } - ui_textarea(obj, .varname = "note_content", .vfill = TRUE, .hfill = TRUE, .hexpand = TRUE, .vexpand = TRUE, .colspan = 2, .groups = UI_GROUPS(APP_STATE_NOTE_SELECTED), .fill = UI_ON); + ui_textarea(obj, .varname = "note_text", .vfill = TRUE, .hfill = TRUE, .hexpand = TRUE, .vexpand = TRUE, .colspan = 2, .groups = UI_GROUPS(APP_STATE_NOTE_SELECTED), .fill = UI_ON); } } } diff --git a/ui/gtk/list.c b/ui/gtk/list.c index aac751f..dc0c479 100644 --- a/ui/gtk/list.c +++ b/ui/gtk/list.c @@ -454,13 +454,7 @@ static void listview_event(ui_callback cb, void *cbdata, UiListView *view) { } } -void ui_columnview_activate(void *ignore, guint position, gpointer userdata) { - UiListView *view = userdata; - listview_event(view->onactivate, view->onactivatedata, view); -} - -void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) { - UiListView *view = userdata; +static void listview_update_selection(UiListView *view) { free(view->selection.rows); view->selection.count = 0; view->selection.rows = NULL; @@ -483,7 +477,19 @@ void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guin } else { free(newselection); } +} +void ui_columnview_activate(void *ignore, guint position, gpointer userdata) { + UiListView *view = userdata; + if(view->selection.count == 0) { + listview_update_selection(view); + } + listview_event(view->onactivate, view->onactivatedata, view); +} + +void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) { + UiListView *view = userdata; + listview_update_selection(view); listview_event(view->onselection, view->onselectiondata, view); } -- 2.43.5