#include "store.h"
#include "menu.h"
#include "notebook.h"
+#include "note.h"
#include "editor.h"
#include <unistd.h>
#include <limits.h>
#include <cx/mempool.h>
+#include <cx/printf.h>
void application_init() {
menu_init();
NotebookModel *notebook = event->document;
notebookmodel_new_note(notebook);
}
+
+
+static void delete_result(UiEvent *event, void *data) {
+ NotebookModel *notebook = event->document;
+ if(event->intval) {
+ notebookmodel_delete_note(notebook);
+ }
+}
+
+void action_note_delete(UiEvent *event, void *data) {
+ NotebookModel *notebook = event->document;
+ Note *note = notebook->current_note;
+ cxmutstr msg = cx_asprintf("Delete note %s?", note_get_title(note));
+ ui_dialog(
+ event->obj,
+ .title = "Delete Note",
+ .content = msg.ptr,
+ .button1_label = "Delete",
+ .closebutton_label = "Cancel",
+ .result = delete_result);
+ free(msg.ptr);
+}
\ No newline at end of file
void action_go_forward(UiEvent *event, void *data);
void action_note_new(UiEvent *event, void *data);
-
+void action_note_delete(UiEvent *event, void *data);
#ifdef __cplusplus
}
#include "menu.h"
+static UiMenuBuilder* notelist_context_menu;
+
void menu_init() {
-
+ ui_contextmenu(¬elist_context_menu) {
+ ui_menuitem(.label = "New Note", .onclick = action_note_new);
+ ui_menuitem(.label = "Delete", .onclick = action_note_delete);
+ }
+}
+
+void menu_cleanup() {
+ ui_menubuilder_free(notelist_context_menu);
}
void toolbar_init() {
ui_toolbar_add_default("GoForward", UI_TOOLBAR_LEFT);
ui_toolbar_add_default("AddNote", UI_TOOLBAR_LEFT);
}
+
+
+UiMenuBuilder* get_notelist_context_menu() {
+ return notelist_context_menu;
+}
#endif
void menu_init();
+void menu_cleanup();
void toolbar_init();
+UiMenuBuilder* get_notelist_context_menu();
+
#ifdef __cplusplus
}
ui_set(note->textnote_code, !enabled);
}
}
+
+
+const char* note_get_title(Note *note) {
+ return note->title ? note->title : note->name;
+}
+
+void note_destroy(const CxAllocator *a, Note *note) {
+ cxFree(a, note->name);
+ cxFree(a, note->title);
+ cxFree(a, note->lastmodified);
+ cxFree(a, note->creationdate);
+ cxFree(a, note->contenttype);
+ cxFree(a, note->created_by);
+ cxFree(a, note->content.ptr);
+ cxFree(a, note->bin_content.ptr);
+
+ if(note->model) {
+ // TODO: destroy model->context
+ }
+}
} TextNoteParagraphStyles;
NoteModel *notemodel_current(UiObject *obj);
-
+
NoteModel* notemodel_create(const CxAllocator *note_allocator);
void notemodel_set_note(NoteModel *model, Note *note);
void note_text_style_set_code(NoteModel *note, UiBool enabled);
+const char* note_get_title(Note *note);
+void note_destroy(const CxAllocator *a, Note *note);
+
#ifdef __cplusplus
}
#endif
#include "note.h"
#include "editor.h"
+#include <cx/printf.h>
+
NotebookModel* notebookmodel_create() {
NotebookModel *model = ui_document_new(sizeof(NotebookModel));
model->ctx = ui_document_context(model);
editor_load_markdown(new_note->model->text, cx_mutstrn("", 0));
}
+typedef struct NoteDeleteOp {
+ NotebookModel *notebook;
+ Note *note;
+} NoteDeleteOp;
+
+static void note_deleted(UiEvent *event, int error, void *userdata) {
+ NotebookModel *notebook = event->document;
+ NoteDeleteOp *op = userdata;
+
+ CxList *notes = op->notebook->notes->data;
+ size_t index = cxListFind(notes, op->note);
+ if(cxListIndexValid(notes, index)) {
+ cxListRemove(notes, index);
+ ui_list_update(op->notebook->notes);
+ note_destroy(op->notebook->current_notes_pool->allocator, op->note);
+ } else {
+ fprintf(stderr, "Error: cannot remove deleted note from list\n");
+ }
+}
+
+void notebookmodel_delete_note(NotebookModel *model) {
+ NoteDeleteOp *op = malloc(sizeof(NoteDeleteOp));
+ op->notebook = model;
+ op->note = model->current_note;
+ note_store_delete_async(model->window->obj, op->note, TRUE, note_deleted, op);
+}
+
+
/*
* Add the current state (notebook + note + ui options) to the navstack.
* If the user navigated through the navstack and the current pos is not the
Note* notebookmodel_get_note_by_id(NotebookModel *model, int64_t note_id, size_t *index);
void notebookmodel_new_note(NotebookModel *model);
+void notebookmodel_delete_note(NotebookModel *model);
void notebookmodel_add2navstack(NotebookModel *model);
"content = ? " \
"where note_id = ? ;"
+#define SQL_NOTE_MOVE_TO_TRASH "update notes set parent_id = ? where note_id = ? ;"
+
+#define SQL_NOTE_DELETE "delete from notes where note_id = ? ;"
+
static DBUConnection *connection;
static UiThreadpool *queue;
NoteStore *store = cxMalloc(a, sizeof(NoteStore));
store->mp = mp;
store->root = NULL;
+ store->trash = NULL;
// key: collection_id value: Collection*
CxMap *collection_map = cxHashMapCreate(NULL, CX_STORE_POINTERS, cxListSize(collections) + 16);
job->error = 0;
ui_threadpool_job(queue, obj, (ui_threadfunc)qthr_save_note, job, (ui_callback)uithr_save_note_finished, job);
}
+
+
+typedef struct DeleteNoteJob {
+ int64_t note_id;
+ UiBool move_to_trash;
+ execresult_func resultcb;
+ void *userdata;
+ int error;
+} DeleteNoteJob;
+
+static int qthr_delete_note(DeleteNoteJob *job) {
+ DBUQuery *q = connection->createQuery(connection, NULL);
+ if(job->move_to_trash && current_store->trash) {
+ dbuQuerySetSQL(q, SQL_NOTE_MOVE_TO_TRASH);
+ dbuQuerySetParamInt64(q, 1, current_store->trash->collection_id);
+ dbuQuerySetParamInt64(q, 2, job->note_id);
+ } else {
+ dbuQuerySetSQL(q, SQL_NOTE_DELETE);
+ dbuQuerySetParamInt64(q, 1, job->note_id);
+ }
+ if(dbuQueryExec(q)) {
+ job->error = 1;
+ }
+ dbuQueryFree(q);
+ return 0;
+}
+
+static void uithr_save_delete_finished(UiEvent *event, DeleteNoteJob *job) {
+ if(job->resultcb) {
+ job->resultcb(event, job->error, job->userdata);
+ }
+ free(job);
+}
+
+void note_store_delete_async(UiObject *obj, Note *note, UiBool move_to_trash, execresult_func resultcb, void *userdata) {
+ DeleteNoteJob *job = malloc(sizeof(DeleteNoteJob));
+ job->note_id = note->note_id;
+ job->move_to_trash = move_to_trash;
+ job->resultcb = resultcb;
+ job->userdata = userdata;
+ job->error = 0;
+ ui_threadpool_job(queue, obj, (ui_threadfunc)qthr_delete_note, job, (ui_callback)uithr_save_delete_finished, job);
+}
typedef struct NoteStore {
CxMempool *mp;
Collection *root;
+ Collection *trash;
} NoteStore;
typedef struct AsyncListResult {
void note_store_new_note_async(UiObject *obj, Note *note, execresult_func resultcb, void *userdata);
void note_store_save_note_async(UiObject *obj, Note *note, execresult_func resultcb, void *userdata);
+void note_store_delete_async(UiObject *obj, Note *note, UiBool move_to_trash, execresult_func resultcb, void *userdata);
+
#ifdef __cplusplus
}
#endif
#include "notebook.h"
#include "editor.h"
#include "note.h"
+#include "menu.h"
#include <cx/array_list.h>
#include <cx/hash_map.h>
UiModel* model = ui_model(obj->ctx, UI_STRING, "Name", UI_STRING_FREE, "Last Modified", -1);
model->columnsize[0] = -1;
model->getvalue = window_notelist_getvalue;
- ui_table(obj, .model = model, .varname = "notes", .multiselection = TRUE, .onselection = action_note_selected, .onactivate = action_note_activated);
+
+ ui_table(obj, .model = model, .varname = "notes", .contextmenu = get_notelist_context_menu(), .multiselection = TRUE, .onselection = action_note_selected, .onactivate = action_note_activated);
// splitpane right: content
ui_tabview_w(obj, wdata->document_tabview, .tabview = UI_TABVIEW_INVISIBLE, .varname = "note_type") {