]> uap-core.de Git - note.git/commitdiff
add NotebookModel + async note loader
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 22 Feb 2025 16:44:59 +0000 (17:44 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 22 Feb 2025 16:44:59 +0000 (17:44 +0100)
13 files changed:
application/Makefile
application/application.h
application/menu.c [new file with mode: 0644]
application/menu.h [new file with mode: 0644]
application/notebook.c [new file with mode: 0644]
application/notebook.h [new file with mode: 0644]
application/store.c
application/store.h
application/store_sqlite.c
application/types.c
application/types.h
application/window.c
application/window.h

index bd8a5953e019ae5041c570e1944d61d7dd59d8fc..2df7deb86e9f6bef9d6167f07a1378b2ac35d8c5 100644 (file)
@@ -38,6 +38,7 @@ SRC += window.c
 SRC += types.c
 SRC += store.c
 SRC += store_sqlite.c
+SRC += notebook.c
 
 OBJ = $(SRC:%.c=../build/application/%.$(OBJ_EXT))
        
index 5c711c1ba57e8f58c0ebce642775f5523fd48e2c..e2889a8f994951d9010f80d44f5d1f31a5d59ef4 100644 (file)
@@ -30,6 +30,9 @@
 #define APPLICATION_H
 
 #include <ui/ui.h>
+#include "types.h"
+
+#include <cx/mempool.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -38,20 +41,67 @@ extern "C" {
 #define APP_STATE_NOTE_SELECTED 100
  
     
+typedef struct NotebookModel NotebookModel;
+    
 typedef struct MainWindow {
+    UiObject *obj;
+    
     UiList *notebooks;
     
+    NotebookModel *current_notebook;
+    
+    /*
+     * key: collection_id
+     * value: NotebookModel*
+     */
+    CxMap *notebook_cache;
     
     UiList *test1;
     UiList *test2;
 } MainWindow;
+
+struct NotebookModel {
+    /*
+     * Document context
+     */
+    UiContext *ctx;
+    
+    /*
+     * The window, this notebook model is attached to.
+     */
+    MainWindow *window;
+    
+    /*
+     * Pointer to NoteStore Collection
+     * 
+     * After a NoteStore refresh, this pointer is invalid and must be renewed.
+     */
+    Collection *collection;
+    
+    /*
+     * same as collection->collection_id, however Collection* may be an invalid
+     * pointer, therefore the collection_id is required separately.
+     */
+    int64_t collection_id;
+    
+    /*
+     * list of Note*
+     * 
+     * name: notes
+     */
+    UiList *notes;
+    
+    /*
+     * The mempool used to allocate the current list of notes
+     */
+    CxMempool *current_notes_pool;
+};
    
 
 void application_init();
 
 void application_startup(UiEvent *event, void *data);
 
-
 void action_note_new(UiEvent *event, void *data);
 
 
diff --git a/application/menu.c b/application/menu.c
new file mode 100644 (file)
index 0000000..760cdc8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "menu.h"
+
+void menu_init() {
+    
+}
+
+void toolbar_init() {
+    ui_toolbar_item("AddNote", .icon = UI_ICON_ADD, .onclick = action_note_new);
+    
+    
+    ui_toolbar_add_default("AddNote", UI_TOOLBAR_LEFT);
+}
diff --git a/application/menu.h b/application/menu.h
new file mode 100644 (file)
index 0000000..66b7e57
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MENU_H
+#define MENU_H
+
+#include <ui/ui.h>
+
+#include "application.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void menu_init();
+void toolbar_init();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MENU_H */
+
diff --git a/application/notebook.c b/application/notebook.c
new file mode 100644 (file)
index 0000000..8f3fa96
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "notebook.h"
+
+#include "store.h"
+
+NotebookModel* notebookmodel_create() {
+    NotebookModel *model = ui_document_new(sizeof(NotebookModel));
+    model->ctx = ui_document_context(model);
+    
+    model->notes = ui_list_new(model->ctx, "notes");
+    
+    
+    return model;
+}
+    
+void notebookmodel_attach(MainWindow *window, NotebookModel *model) {
+    if(window->current_notebook) {
+        notebookmodel_detach(window->current_notebook);
+    }
+    ui_attach_document(window->obj->ctx, model);
+    window->current_notebook = model;
+    model->window = window;
+}
+
+void notebookmodel_detach(NotebookModel *model) {
+    if(model->window) {
+        ui_detach_document2(model->window->obj->ctx, model);
+        model->window->current_notebook = NULL;
+    }
+}
+
+void notebookmodel_set_collection(NotebookModel *model, Collection *collection) {
+    model->collection = collection;
+    model->collection_id = collection->collection_id;
+}
+
+
+static void notebook_loaded(UiEvent *event, AsyncListResult *result, void *data) {
+    NotebookModel *model = data;
+    if(result->list) {
+        ui_list_clear(model->notes);
+        CxIterator i = cxListIterator(result->list);
+        cx_foreach(Note *, note, i) {
+            ui_list_append(model->notes, note);
+        }
+        ui_list_update(model->notes);
+    } else {
+        fprintf(stderr, "Error: get notes failed\n");
+    }
+}
+
+void notebookmodel_reload(UiObject *obj, NotebookModel *model) {
+    note_store_get_notes_async(obj, model->collection_id, notebook_loaded, model);
+}
diff --git a/application/notebook.h b/application/notebook.h
new file mode 100644 (file)
index 0000000..4d9a5d4
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NOTEBOOK_H
+#define NOTEBOOK_H
+
+#include "application.h"
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NotebookModel* notebookmodel_create();
+
+void notebookmodel_attach(MainWindow *window, NotebookModel *model);
+
+void notebookmodel_detach(NotebookModel *model);
+
+void notebookmodel_set_collection(NotebookModel *model, Collection *collection);
+
+void notebookmodel_reload(UiObject *obj, NotebookModel *model);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NOTEBOOK_H */
+
index 740548019a1b03acb55deb60b3199b9849f48a81..cc3f59a98e1517b2ac40d30ff1926f8943eeb706 100644 (file)
     "select * from cols\n" \
     "order by path;"
 
-
+#define SQL_NOTEBOOK_GET_NOTES "select note_id, parent_id, name, title, lastmodified, creationdate, contenttype, created_by from notes where parent_id = ? ;"
 
 static DBUConnection *connection;
 
+static UiThreadpool *queue;
+
 static char *settings_host;
 static char *settings_user;
 static char *settings_profile_name;
@@ -100,6 +102,8 @@ int init_note_store() {
         }
     }
     
+    queue = ui_threadpool_create(1);
+    
     return 0;
 }
 
@@ -337,3 +341,49 @@ void note_store_reload() {
 NoteStore* note_store_get() {
     return current_store;
 }
+
+
+CxList* note_store_get_notes(const CxAllocator *a, int64_t parent_collection_id) {
+    DBUQuery *q = connection->createQuery(connection, NULL);
+    dbuQuerySetSQL(q, SQL_NOTEBOOK_GET_NOTES);
+    dbuQuerySetParamInt64(q, 1, parent_collection_id);
+    DBUObjectBuilder *builder = dbuObjectBuilder(notes_class, q, a);
+    CxList *notes = dbuObjectBuilderGetList(builder);
+    dbuObjectBuilderDestroy(builder);
+    return notes;
+}
+
+typedef struct JobGetNotes {
+    int64_t collection_id;
+    listresult_func resultcb;
+    void *userdata;
+    AsyncListResult result;
+} JobGetNotes;
+
+static void uithr_get_notes_finished(UiEvent *event, JobGetNotes *job) {
+    if(job->resultcb) {
+        job->resultcb(event, &job->result, job->userdata);
+    } else {
+        cxMempoolFree(job->result.mp);
+    }
+    free(job);
+}
+
+static int qthr_get_notes(JobGetNotes *job) {
+    job->result.list = note_store_get_notes(job->result.mp->allocator, job->collection_id);
+    if(!job->result.list) {
+        cxMempoolFree(job->result.mp);
+        job->result.mp = NULL;
+    }
+    return 0;
+}
+
+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.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);
+}
index a556989e1bd570685bf60ef5481e8abe18af05cc..5974f0431c34bdf012226f4e62285d10a5826b8e 100644 (file)
@@ -45,6 +45,13 @@ typedef struct NoteStore {
     Collection *root;
 } NoteStore;
     
+typedef struct AsyncListResult {
+    CxMempool *mp;
+    CxList *list;
+} AsyncListResult;
+
+typedef void (*listresult_func)(UiEvent *event, AsyncListResult *result, void *userdata);
+
 int init_note_store();
 
 CxList* note_store_get_user_settings(const CxAllocator *a, const char *host, const char *user, const char *profile);
@@ -70,6 +77,9 @@ 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);
+
 
 #ifdef __cplusplus
 }
index 9676c912c25db1942c46c6398a05e8c484bf4461..0557bc47216cfc4bee73f5735660ff279536fcdd 100644 (file)
     "foreign key (default_collection_id) references collections(collection_id), " \
     "unique (host, user, profile_name)" \
     ");"
-#define SQL_CREATE_TABLE_RESOURCE "create table resources( " \
-    "resource_id             integer primary key, " \
+#define SQL_CREATE_TABLE_NOTES "create table notes( " \
+    "note_id                 integer primary key, " \
     "parent_id               integer, " \
     "name                    text, " \
     "title                   text, " \
     "lastmodified            text, " \
     "creationdate            text, " \
-    "contentlength           integer, " \
+    "contenttype             text, " \
     "content                 text, " \
     "bin_content             blob, " \
-    "note_item               integer, " \
     "created_by              text, " \
     "foreign key (parent_id) references collections(collection_id), " \
     "unique (parent_id, name) " \
@@ -89,7 +88,7 @@ int store_sqlite_init_db(DBUConnection *connection) {
         SQL_CREATE_TABLE_REPOSITORIES,
         SQL_CREATE_TABLE_COLLECTIONS,
         SQL_CREATE_TABLE_USER_SETTINGS,
-        SQL_CREATE_TABLE_RESOURCE
+        SQL_CREATE_TABLE_NOTES
     };
     int nsql = sizeof(sql) / sizeof(char*);
     
index 2fc3a846ecac52272dba052c35d920c6dd763767..3d3cd8698b2905948e9334d6f254cc421d404a7c 100644 (file)
@@ -33,7 +33,7 @@ static DBUContext *ctx;
 DBUClass *usersettings_class;
 DBUClass *repository_class;
 DBUClass *collection_class;
-DBUClass *resource_class;
+DBUClass *notes_class;
 
 DBUContext* get_dbu_context() {
     return ctx;
@@ -57,16 +57,15 @@ void register_types() {
     dbuClassAdd(collection_class, Collection, display_name);
     dbuClassAdd(collection_class, Collection, type);
     
-    resource_class = dbuRegisterClass(ctx, "resources", Resource, resource_id);
-    dbuClassAdd(resource_class, Resource, resource_id);
-    dbuClassAdd(resource_class, Resource, parent_id);
-    dbuClassAdd(resource_class, Resource, name);
-    dbuClassAdd(resource_class, Resource, title);
-    dbuClassAdd(resource_class, Resource, lastmodified);
-    dbuClassAdd(resource_class, Resource, creationdate);
-    dbuClassAdd(resource_class, Resource, contentlength);
-    dbuClassAdd(resource_class, Resource, content);
-    dbuClassAdd(resource_class, Resource, bin_content);
-    dbuClassAdd(resource_class, Resource, note_item);
-    dbuClassAdd(resource_class, Resource, created_by);
+    notes_class = dbuRegisterClass(ctx, "notes", Note, note_id);
+    dbuClassAdd(notes_class, Note, parent_id);
+    dbuClassAdd(notes_class, Note, name);
+    dbuClassAdd(notes_class, Note, title);
+    dbuClassAdd(notes_class, Note, lastmodified);
+    dbuClassAdd(notes_class, Note, creationdate);
+    dbuClassAdd(notes_class, Note, contenttype);
+    dbuClassAdd(notes_class, Note, contentlength);
+    dbuClassAdd(notes_class, Note, content);
+    dbuClassAdd(notes_class, Note, bin_content);
+    dbuClassAdd(notes_class, Note, created_by);
 }
\ No newline at end of file
index 41d08e2e647ac15378442a0e5c3d19137cfaae23..48e064a13bc07be11e681ebf6c54a1ad5d48bd3f 100644 (file)
@@ -39,7 +39,7 @@ extern "C" {
 typedef struct UserSettings UserSettings;
 typedef struct Repository   Repository;
 typedef struct Collection   Collection;
-typedef struct Resource     Resource;
+typedef struct Note         Note;
     
 struct UserSettings {
     char    *host;
@@ -72,24 +72,24 @@ struct Collection {
     CxList     *children;
 };
 
-struct Resource {
-    int64_t    resource_id;
+struct Note {
+    int64_t    note_id;
     int64_t    parent_id;
     char       *name;
     char       *title;
     char       *lastmodified;
     char       *creationdate;
+    char       *contenttype;
     uint64_t   contentlength;
     cxmutstr   content;
     cxmutstr   bin_content;
-    bool       note_item;
     char       *created_by;
 };
 
 extern DBUClass *usersettings_class;
 extern DBUClass *repository_class;
 extern DBUClass *collection_class;
-extern DBUClass *resource_class;
+extern DBUClass *notes_class;
 
 void register_types();
 
index 9df9370c1760c4bf443e6c8acc25ab805e81aaf0..8b1bdc57b5718768753b9217006e0bffc5bd8c4f 100644 (file)
 #include "window.h"
 #include "application.h"
 #include "store.h"
+#include "notebook.h"
 
 #include <cx/array_list.h>
+#include <cx/hash_map.h>
 
 
 void window_create() {
@@ -44,7 +46,7 @@ void window_create() {
     };
     */
     ui_sidebar(obj) {
-        ui_sourcelist(obj, .dynamic_sublist = wdata->notebooks, .getvalue = window_sidebar_getvalue, .fill = UI_ON);
+        ui_sourcelist(obj, .dynamic_sublist = wdata->notebooks, .getvalue = window_sidebar_getvalue, .onactivate = action_notebook_selected, .fill = UI_ON);
         ui_hbox(obj, .spacing = 2, .fill = UI_OFF) {
             ui_button(obj, .icon = "folder-new-symbolic", .style_class = "flat");
         }
@@ -54,7 +56,8 @@ void window_create() {
         // splitpane left: table
         UiModel* model = ui_model(obj->ctx, UI_STRING, "Name", UI_STRING_FREE, "Last Modified", -1);
         model->columnsize[0] = -1;
-        ui_table(obj, .model = model, .varname = "notes");
+        model->getvalue = window_notelist_getvalue;
+        ui_table(obj, .model = model, .varname = "notes",);
         
         // splitpane right: content
         ui_grid(obj, .columnspacing = 10, .rowspacing = 10, .def_vfill = TRUE) {
@@ -72,10 +75,13 @@ void window_create() {
 MainWindow* window_init_data(UiObject *obj) {
     MainWindow *wdata = ui_calloc(obj->ctx, 1, sizeof(MainWindow));
     obj->window = wdata;
+    wdata->obj = obj;
     
     wdata->notebooks = ui_list_new(obj->ctx, NULL);
     update_sublists(obj->ctx, wdata->notebooks);
     
+    wdata->notebook_cache = cxHashMapCreateSimple(CX_STORE_POINTERS);
+    
     return wdata;
 }
 
@@ -145,3 +151,42 @@ void update_sublists(UiContext *ctx, UiList *sublists) {
     delete_list->collection.destructor_data = ctx;
     cxListFree(delete_list);
 }
+
+void* window_notelist_getvalue(void *data, int col) {
+    Note *note = data;
+    switch(col) {
+        case 0: {
+            return note->title ? note->title : note->name;
+        }
+        case 1: {
+            return note->lastmodified ? strdup(note->lastmodified) : NULL;
+        }
+    }
+    
+    return NULL;
+}
+
+void action_notebook_selected(UiEvent *event, void *userdata) {
+    UiSubListEventData *data = event->eventdata;
+    MainWindow *window = event->window;
+    Collection *collection = data->row_data;
+    
+    printf("notebook selected: %s\n", collection->name);
+    
+    if(window->current_notebook && window->current_notebook->collection == collection) {
+        return; // notebook already selected
+    }
+    
+    CxHashKey key = cx_hash_key(&collection->collection_id, sizeof(collection->collection_id));
+    NotebookModel *notebook = cxMapGet(window->notebook_cache, key);
+    if(!notebook) {
+        printf("notebook not in cache\n");
+        notebook = notebookmodel_create();
+        notebookmodel_set_collection(notebook, collection);
+        notebookmodel_reload(event->obj, notebook);
+        cxMapPut(window->notebook_cache, key, notebook);
+    } else {
+        printf("notebook in cache\n");
+    }
+    notebookmodel_attach(window, notebook);
+}
index 9373298bb90e79f23fde15bf869cc8d188e8f9eb..cd6ae982394d86ceb7a859534585ddd81120c230 100644 (file)
@@ -44,6 +44,10 @@ void window_sidebar_getvalue(void *sublist_userdata, void *rowdata, int index, U
 
 void update_sublists(UiContext *ctx, UiList *sublists);
 
+void* window_notelist_getvalue(void *data, int col);
+
+void action_notebook_selected(UiEvent *event, void *userdata);
+
 
 #ifdef __cplusplus
 }