kee

Offline IOU signer with QR as transport
git clone https://holbrook.no/src/kee
Info | Log | Files | Refs | README | LICENSE

commit 8946223e127136fe0e1a58ac40e54ea72a7ac88d
parent 3eb4440343e35da66825a16b1d73885dd5286400
Author: lash <dev@holbrook.no>
Date:   Tue, 19 Mar 2024 04:50:27 +0000

Add toggle buttons for imports

Diffstat:
Msrc/Makefile | 1+
Msrc/gtk/Makefile | 3++-
Msrc/gtk/kee-uicontext.c | 43++++++++++++++++++++++++++++++++++++++-----
Msrc/gtk/kee-uicontext.h | 26+++++++++++---------------
Msrc/gtk/main.c | 24++++++++----------------
Msrc/gtk/menu.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/gtk/menu.h | 5++++-
Msrc/gtk/ui.c | 32++++++++++++++++++++++++++++++--
Msrc/gtk/ui.h | 22+---------------------
Msrc/gtk/view.c | 6++++++
Msrc/state.h | 13+++++++++++++
11 files changed, 183 insertions(+), 78 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -21,6 +21,7 @@ dev: $(CC) $(CFLAGS) -c settings.c -o settings.o $(LDFLAGS) $(CC) $(CFLAGS) -c context.c -o context.o $(LDFLAGS) $(CC) $(CFLAGS) -c camera.c -o camera.o $(LDFLAGS) + $(CC) $(CFLAGS) -c state.c -o state.o make -C gtk dev .PHONY: clean aux diff --git a/src/gtk/Makefile b/src/gtk/Makefile @@ -16,6 +16,7 @@ debug: all clean: rm -vf *.o rm -vf a.out + rm -vf a_dev.out rm -vf resources.c resource: @@ -29,4 +30,4 @@ dev: $(CC) $(CFLAGS) -c ui.c -o ui.o $(CC) $(CFLAGS) -c menu.c -o menu.o $(CC) $(CFLAGS) -c kee-uicontext.c -o kee-uicontext.o - $(CC) $(CFLAGS) main.c -o a_dev.out ../settings.o ../camera.o ../context.o ./kee-uicontext.o ./debug.o ./menu.o ./scan.o ./ui.o ./view.o ./nav.o $(LDFLAGS) + $(CC) $(CFLAGS) main.c -o a_dev.out ../settings.o ../camera.o ../context.o ../state.o ./kee-uicontext.o ./debug.o ./menu.o ./scan.o ./ui.o ./view.o ./nav.o $(LDFLAGS) diff --git a/src/gtk/kee-uicontext.c b/src/gtk/kee-uicontext.c @@ -20,6 +20,7 @@ struct _KeeUicontext { struct kee_context *ctx; GListModel *camera_list; GtkApplication *gapp; + kee_state_t state; }; G_DEFINE_TYPE(KeeUicontext, kee_uicontext, G_TYPE_OBJECT) @@ -110,7 +111,21 @@ static void kee_uicontext_get_property(GObject *oo, guint property_id, GValue *v static void kee_uicontext_class_init(KeeUicontextClass *kls) { GObjectClass *o = G_OBJECT_CLASS(kls); - kee_sigs[SCAN_WANT] = g_signal_newv("scan_want", + kee_sigs[KEE_S_STATE_CHANGE] = g_signal_new("state", + G_TYPE_FROM_CLASS(o), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 3, + G_TYPE_CHAR, + G_TYPE_POINTER, + G_TYPE_POINTER + ); + + kee_sigs[KEE_S_SCAN_CHANGE] = g_signal_newv("scan", G_TYPE_FROM_CLASS(o), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, NULL, @@ -122,10 +137,10 @@ static void kee_uicontext_class_init(KeeUicontextClass *kls) { NULL ); - kee_sigs[SCAN_CHANGE] = g_signal_newv("scan_change", + kee_sigs[KEE_S_KEY_UNLOCKED] = g_signal_new("unlock", G_TYPE_FROM_CLASS(o), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, - NULL, + 0, NULL, NULL, NULL, @@ -230,13 +245,31 @@ void kee_uicontext_scaninit(KeeUicontext *o) { void kee_uicontext_scanchange(KeeUicontext *o, const char *device) { settings_set(o->ctx->settings, SETTINGS_VIDEO, (unsigned char*)device); //ui_state_change(o->ui, KEE_ST_SCAN_SEARCH, 0); - g_signal_emit(o, kee_sigs[SCAN_WANT], 0); + g_signal_emit(o, kee_sigs[KEE_S_SCAN_CHANGE], 0); } void kee_uicontext_scanadd(KeeUicontext *o, GtkLabel *label) { g_list_store_append(G_LIST_STORE(o->camera_list), label); } +void kee_uicontext_unlock(KeeUicontext *o) { + g_signal_emit(o, kee_sigs[KEE_S_KEY_UNLOCKED], 0); +} + +void kee_uicontext_state_change(KeeUicontext *o, kee_state_t *add, kee_state_t *sub) { + kee_state_t old_state; + char hint; + + hint = 0; + if (add) { + hint = kee_state_add(&o->state, add); + } + + memcpy(&old_state, &o->state, sizeof(kee_state_t)); + + g_signal_emit(o, kee_sigs[KEE_S_STATE_CHANGE], 0, hint, &o->state, &old_state); +} + void kee_uicontext_scanstart(KeeUicontext *o) { // if (KEE_IS_SCANNING(o->ui)) { // g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "already in scanning state"); @@ -244,7 +277,7 @@ void kee_uicontext_scanstart(KeeUicontext *o) { // } // // ui_state_change(o->ui, KEE_ST_SCAN_SEARCH, 0); - g_signal_emit(o, kee_sigs[SCAN_WANT], 0); + g_signal_emit(o, kee_sigs[KEE_S_SCAN_CHANGE], 0); } // //KeeState kee_uicontext_state(KeeUicontext *o) { diff --git a/src/gtk/kee-uicontext.h b/src/gtk/kee-uicontext.h @@ -2,37 +2,31 @@ #define _GTK_KEE_UICONTEXT_H #include <glib-object.h> + #include "context.h" +#include "state.h" #define KEE_W_FRONTLIST "frontlist" #define KEE_W_CAMERA_VIEWFINDER "camera_view" #define KEE_W_WINDOW "win" #define KEE_W_HEADER "header" +#define KEE_W_PASSPHRASE "passphrase" + +#define KEE_ST_UI_HEAD_ADD 0x1 G_BEGIN_DECLS -typedef struct { - int ui; - int ctx; -} KeeState; enum KEE_SIGS { - SCAN_WANT, - SCAN_CHANGE, + KEE_S_STATE_CHANGE, + KEE_S_SCAN_CHANGE, + KEE_S_KEY_UNLOCKED, KEE_N_SIGS, }; enum KEE_PROPS { CORE_CONTEXT = 1, -// UI_CONTAINER, -// UI_HEADER, -// UI_LIST, -// UI_WINDOW, -// UI_PUSH, CAMERA_LIST, -// CAMERA_SCAN, -// CAMERA_DEVICE, -// CAMERA_VIEW, GAPP, KEE_N_PROPS, }; @@ -45,7 +39,9 @@ void kee_uicontext_scaninit(KeeUicontext *o); void kee_uicontext_scanstart(KeeUicontext *o); void kee_uicontext_scanadd(KeeUicontext *o, GtkLabel *label); void kee_uicontext_scanchange(KeeUicontext *o, const char *devices); -KeeState kee_uicontext_state(KeeUicontext *o); +kee_state_t kee_uicontext_state(KeeUicontext *o); +void kee_uicontext_unlock(KeeUicontext *o); +void kee_uicontext_state_change(KeeUicontext *o, kee_state_t *add, kee_state_t *sub); G_END_DECLS diff --git a/src/gtk/main.c b/src/gtk/main.c @@ -10,10 +10,13 @@ //#include "camera.h" +static void state_log(KeeUicontext *uctx, char state_hint, kee_state_t *new_state, kee_state_t *old_state) { + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "new state hint: %d", state_hint); +} + static void startup(GtkApplication *app, KeeUicontext *uctx) { kee_uicontext_scaninit(uctx); - header_setup(app, uctx); - //ui_setup(uctx); + menu_setup(app, uctx); } @@ -23,7 +26,6 @@ static void activate(GtkApplication *app, KeeUicontext *uctx) { static void deactivate(GtkApplication *app, gpointer user_data) { g_object_unref(user_data); - //ui_free(user_data); } int main(int argc, char **argv) { @@ -32,32 +34,22 @@ int main(int argc, char **argv) { struct kee_settings settings; struct kee_context ctx; GtkApplication *gapp; - //struct ui_container ui; - - //r = ui_init(&ui); - //if (r) { - // return r; - //} gapp = gtk_application_new ("org.defalsify.Kee", G_APPLICATION_DEFAULT_FLAGS); - //settings_new_from_xdg(&ctx.settings); settings_new_from_xdg(&settings); - //settings_init(&ctx.settings); settings_init(&settings); - //kee_context_new(&ctx, &ui, &settings); - //uctx = g_object_new(KEE_TYPE_UICONTEXT, "ui_container", &ui, "core_context", &ctx, NULL); uctx = g_object_new(KEE_TYPE_UICONTEXT, "gtk_application", gapp, "core_context", &ctx, NULL); //db_connect(&ctx.db, "./testdata_mdb"); g_signal_connect (gapp, "startup", G_CALLBACK (startup), uctx); g_signal_connect (gapp, "activate", G_CALLBACK (activate), uctx); g_signal_connect (gapp, "shutdown", G_CALLBACK (deactivate), uctx); -// //g_signal_connect (uctx, "scan_want", G_CALLBACK( ui_handle_scan) , &ctx); -// g_signal_connect (uctx, "scan_want", G_CALLBACK( ui_handle_scan) , uctx); + g_signal_connect (uctx, "scan", G_CALLBACK( ui_handle_scan) , uctx); + g_signal_connect (uctx, "unlock", G_CALLBACK(ui_handle_unlock), uctx); + g_signal_connect (uctx, "state", G_CALLBACK(state_log), NULL); -// r = g_application_run (G_APPLICATION (ui.gapp), argc, argv); r = g_application_run (G_APPLICATION (gapp), argc, argv); g_object_unref(gapp); diff --git a/src/gtk/menu.c b/src/gtk/menu.c @@ -4,6 +4,8 @@ //#include "ui.h" #include "scan.h" #include "context.h" +#include "state.h" +#include "menu.h" static void act_quit(GSimpleAction *act, GVariant *param, KeeUicontext *uctx) { @@ -13,15 +15,37 @@ static void act_quit(GSimpleAction *act, GVariant *param, KeeUicontext *uctx) { g_application_quit(gapp); } +static void act_import(GSimpleAction *act, GVariant *param, KeeUicontext *uctx) { + scan_act(act, param, uctx); +} + +static void menu_handle_state(KeeUicontext *uctx, char state_hint, kee_state_t *new_state, kee_state_t *old_state, GObject *head) { + GtkApplication *gapp; + GtkWidget *widget; + GAction *act; + + if (!(state_hint & KEE_ST_HINT_UI_MENU)) { + return; + } + + if (new_state->ui_menu & KEE_ST_UI_HEAD_ADD) { + widget = g_object_get_data(head, KEE_W_UI_MENU_QUICK_ADD); + gtk_widget_set_sensitive(widget, true); + g_object_get(uctx, "gtk_application", &gapp, NULL); + act = g_action_map_lookup_action(G_ACTION_MAP(gapp), "import"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(act), true); + } +} + -static GtkWidget* menu_setup(GtkApplication *gapp, KeeUicontext *uctx) { +static GtkWidget* menu_button_setup(GObject *head, GtkApplication *gapp, KeeUicontext *uctx) { GMenu *menu; GMenuItem *menu_item; GtkWidget *butt; GSimpleAction *act; menu = g_menu_new(); - menu_item = g_menu_item_new("Scan", "app.scan"); + menu_item = g_menu_item_new("Import", "app.import"); g_menu_append_item(menu, menu_item); g_object_unref(menu_item); @@ -33,10 +57,10 @@ static GtkWidget* menu_setup(GtkApplication *gapp, KeeUicontext *uctx) { g_action_map_add_action(G_ACTION_MAP(gapp), G_ACTION(act)); g_signal_connect(act, "activate", G_CALLBACK(act_quit), uctx); - act = g_simple_action_new("scan", NULL); + act = g_simple_action_new("import", NULL); g_simple_action_set_enabled(act, false); g_action_map_add_action(G_ACTION_MAP(gapp), G_ACTION(act)); - g_signal_connect(act, "activate", G_CALLBACK(scan_act), uctx); + g_signal_connect(act, "activate", G_CALLBACK(act_import), uctx); butt = gtk_menu_button_new(); gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(butt), G_MENU_MODEL(menu)); @@ -50,22 +74,50 @@ static GtkWidget* menu_setup(GtkApplication *gapp, KeeUicontext *uctx) { void header_setup(GtkApplication *gapp, KeeUicontext *uctx) { GtkWidget *head; - GtkWidget *butt_back; - GtkWidget *butt_add; - GtkWidget *butt_menu; + GtkWidget *butt; + GtkToggleButton *butt_prev; head = gtk_header_bar_new(); - butt_back = gtk_button_new_from_icon_name("go-previous"); - gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt_back); - gtk_widget_set_visible(butt_back, false); + butt = menu_button_setup(G_OBJECT(head), gapp, uctx); + gtk_header_bar_pack_end(GTK_HEADER_BAR(head), butt); + + butt = gtk_button_new_from_icon_name("go-previous"); + gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt); + gtk_widget_set_visible(butt, false); + + butt = gtk_button_new_from_icon_name("insert-object"); + gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt); + gtk_widget_set_sensitive(butt, false); + g_object_set_data(G_OBJECT(head), KEE_W_UI_MENU_QUICK_ADD, butt); - butt_add = gtk_button_new_from_icon_name("insert-object"); - gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt_add); - gtk_widget_set_sensitive(butt_add, false); + butt = gtk_toggle_button_new(); + gtk_button_set_icon_name(GTK_BUTTON(butt), "insert-image"); + gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(butt), true); + gtk_widget_set_visible(butt, false); + + butt_prev = GTK_TOGGLE_BUTTON(butt); + butt = gtk_toggle_button_new(); + gtk_toggle_button_set_group(GTK_TOGGLE_BUTTON(butt), butt_prev); + gtk_button_set_icon_name(GTK_BUTTON(butt), "document-new"); + gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt); + gtk_widget_set_visible(butt, false); + + butt_prev = GTK_TOGGLE_BUTTON(butt); + butt = gtk_toggle_button_new(); + gtk_toggle_button_set_group(GTK_TOGGLE_BUTTON(butt), butt_prev); + gtk_button_set_icon_name(GTK_BUTTON(butt), "document-save"); + gtk_header_bar_pack_start(GTK_HEADER_BAR(head), butt); + gtk_widget_set_visible(butt, false); + + g_object_set_data(G_OBJECT(uctx), KEE_W_HEADER, GTK_HEADER_BAR(head)); + + g_signal_connect (uctx, "state", G_CALLBACK(menu_handle_state), head); + + +} - butt_menu = menu_setup(gapp, uctx); - gtk_header_bar_pack_end(GTK_HEADER_BAR(head), butt_menu); - //g_object_set(uctx, "ui_header", GTK_HEADER_BAR(head), NULL); - g_object_set_data(G_OBJECT(uctx), KEE_W_HEADER, head); +void menu_setup(GtkApplication *gapp, KeeUicontext *uctx) { + header_setup(gapp, uctx); } diff --git a/src/gtk/menu.h b/src/gtk/menu.h @@ -3,6 +3,9 @@ #include "kee-uicontext.h" -void header_setup(GtkApplication *gapp, KeeUicontext *uctx); +#define KEE_W_UI_MENU_QUICK_ADD "quick_add" +#define KEE_W_UI_MENU_ACT_IMPORT "act_import" + +void menu_setup(GtkApplication *gapp, KeeUicontext *uctx); #endif // _KEE_GTK_MENU_H diff --git a/src/gtk/ui.c b/src/gtk/ui.c @@ -33,11 +33,34 @@ static void new_item(GtkListItemFactory *factory, GtkListItem *item, gpointer us //} -static void ui_handle_unlock_click(GtkWidget *button, gpointer user_data) { - g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "click"); +void ui_handle_unlock(KeeUicontext *uctx, gpointer user_data) { + kee_state_t state_delta; + + kee_state_zero(&state_delta); + + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "key is unlocked"); + kee_view_prev(); + + state_delta.ui_menu |= KEE_ST_UI_HEAD_ADD; + kee_uicontext_state_change(uctx, &state_delta, NULL); +} + + +//static void ui_handle_unlock_click(GtkWidget *button, gpointer user_data) { +static void ui_handle_unlock_click(GtkWidget *button, KeeUicontext *uctx) { + GtkEntryBuffer *buf; + const char *passphrase; //ui = (struct ui_container*)user_data; //gtk_stack_set_visible_child(ui->stack, GTK_WIDGET(ui->front_view)); + + buf = g_object_get_data(G_OBJECT(uctx), "passphrase"); + passphrase = gtk_entry_buffer_get_text(buf); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "click"); + + kee_uicontext_unlock(uctx); + + gtk_entry_buffer_delete_text(buf, 0, gtk_entry_buffer_get_length(buf)); } //static void ui_handle_camera_change(GtkDropDown *chooser, GParamSpec *spec, struct kee_context *ctx) { @@ -63,11 +86,16 @@ GtkWidget* ui_build_unlock(KeeUicontext *uctx) { GtkWidget *box; GtkWidget *entry; GtkWidget *button; + GtkEntryBuffer *buf; box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10); entry = gtk_entry_new(); gtk_box_append(GTK_BOX(box), entry); + buf = gtk_entry_get_buffer(GTK_ENTRY(entry)); + gtk_entry_set_input_purpose(GTK_ENTRY(entry), GTK_INPUT_PURPOSE_PASSWORD); + gtk_entry_set_visibility(GTK_ENTRY(entry), false); + g_object_set_data(G_OBJECT(uctx), "passphrase", buf); button = gtk_button_new_with_label("create"); gtk_box_append(GTK_BOX(box), button); diff --git a/src/gtk/ui.h b/src/gtk/ui.h @@ -3,31 +3,11 @@ #include <gtk/gtk.h> -#include "scan.h" -#include "settings.h" #include "kee-uicontext.h" -//struct ui_container { -// GtkApplication *gapp; -// GtkApplicationWindow *win; -// //GtkStack *stack; -// GListModel *front_list; -// GListModel *camera_list; -// GtkBox *front_scan; -// GtkHeaderBar *head; -// //struct kee_scanner scan; -// struct kee_context *ctx; -// int state; -//}; - -//int ui_init(struct ui_container *ui); -//int ui_setup(KeeUicontext *ctx); void ui_build(GtkApplication *app, KeeUicontext *uctx); -//int ui_state_change(struct ui_container *ui, int set, int reset); -//void ui_free(struct ui_container *ui); -//void ui_handle_scan(GtkApplication *app, struct kee_context *ctx); -//void ui_handle_scan(GtkApplication *app, KeeUicontext *uctx); void ui_handle_scan(KeeUicontext *uctx); +void ui_handle_unlock(KeeUicontext *uctx, gpointer user_data); #endif // _UI_H diff --git a/src/gtk/view.c b/src/gtk/view.c @@ -26,3 +26,9 @@ int kee_view_next(const char *label) { gtk_stack_set_visible_child(view.stack, widget); return ERR_OK; } + +int kee_view_prev() { + kee_nav_pop(&view.nav); + gtk_stack_set_visible_child(view.stack, view.nav.now); + return ERR_OK; +} diff --git a/src/state.h b/src/state.h @@ -10,5 +10,18 @@ #define KEE_ST_SCAN_INIT 0x0201 #define KEE_ST_SCAN_SEARCH 0x0202 +#define KEE_ST_HINT_KEY 0x01 +#define KEE_ST_HINT_UI_MENU 0x10 + #define KEE_IS_SCANNING(c) c->state & KEE_ST_SCAN_SEARCH + +typedef struct { + long ui_menu; + long key; +} kee_state_t; + +void kee_state_zero(kee_state_t *state); +char kee_state_add(kee_state_t *target, kee_state_t *delta); +char kee_state_sub(kee_state_t *target, kee_state_t *delta); + #endif // _KEE_STATE_H