From 167b5c635a040cb52362ef3ca2142dca1aa8a881 Mon Sep 17 00:00:00 2001 From: Alexander Zhylin Date: Fri, 16 Jan 2026 16:34:40 +0200 Subject: [PATCH] ui: file list (not completed) --- src/deps.mk | 29 +++++++ src/query.c | 2 +- src/ui/modals/ask_server_addr.c | 2 +- src/ui/modals/login_credentials.c | 2 +- src/ui/modals/login_option.c | 2 +- src/ui/modals/notification.c | 2 +- src/ui/widget/dialogue.c | 19 +++++ src/ui/widget/fs_file_list.c | 126 ++++++++++++++++++------------ src/ui/widget/fs_file_list.h | 15 +++- 9 files changed, 142 insertions(+), 57 deletions(-) diff --git a/src/deps.mk b/src/deps.mk index e69de29..a154278 100644 --- a/src/deps.mk +++ b/src/deps.mk @@ -0,0 +1,29 @@ +client.o: src/client.c src/file_processor.h src/main.h src/types.h \ + src/ui/widget/file_list.h src/ui/widget/../widget.h \ + src/ui/widget/../../main.h src/client.h +connection.o: src/connection.c src/main.h src/types.h src/ui/app.h \ + src/ui/../common.h src/ui/widget.h src/ui/../main.h \ + src/ui/widget/dialogue.h src/ui/widget/../widget.h \ + src/ui/widget/../../common.h src/ui/widget/button.h \ + src/ui/widget/../../main.h src/ui/widget/group.h +file_processor.o: src/file_processor.c src/client.h src/main.h \ + src/types.h src/query.h src/ui/app.h src/ui/../common.h src/ui/widget.h \ + src/ui/../main.h src/ui/widget/dialogue.h src/ui/widget/../widget.h \ + src/ui/widget/../../common.h src/ui/widget/button.h \ + src/ui/widget/../../main.h src/ui/widget/group.h \ + src/ui/widget/dialogue.h src/ui/widget/file_list.h \ + src/ui/widget/progress_bar.h +fs.o: src/fs.c +main.o: src/main.c src/connection.h src/main.h src/types.h src/ui/app.h \ + src/ui/../common.h src/ui/widget.h src/ui/../main.h \ + src/ui/widget/dialogue.h src/ui/widget/../widget.h \ + src/ui/widget/../../common.h src/ui/widget/button.h \ + src/ui/widget/../../main.h src/ui/widget/group.h src/query.h \ + src/ui/widget.h src/ui/widget/file_list.h +query.o: src/query.c src/client.h src/main.h src/types.h src/connection.h \ + src/ui/app.h src/ui/../common.h src/ui/widget.h src/ui/../main.h \ + src/ui/widget/dialogue.h src/ui/widget/../widget.h \ + src/ui/widget/../../common.h src/ui/widget/button.h \ + src/ui/widget/../../main.h src/ui/widget/group.h src/file_processor.h \ + src/ui/widget/file_list.h src/server.h +server.o: src/server.c src/main.h src/types.h diff --git a/src/query.c b/src/query.c index b600d00..dcbcf74 100644 --- a/src/query.c +++ b/src/query.c @@ -36,7 +36,7 @@ void query_loop(app_t *app) { int sr; static file_args_t file_args; callback_args_t d_args = { - .app = app, .widget = NULL, .data = NULL, .resp_data = NULL}; + .app = app, .element = NULL, .data = NULL, .resp_data = NULL}; init_file_args(&file_args); query_args->sd = sd; diff --git a/src/ui/modals/ask_server_addr.c b/src/ui/modals/ask_server_addr.c index 6ac6f29..7600700 100644 --- a/src/ui/modals/ask_server_addr.c +++ b/src/ui/modals/ask_server_addr.c @@ -21,7 +21,7 @@ void asa_modal_dialogue_callback(callback_args_t *args) { memcpy(&d_args, args, sizeof(callback_args_t)); d_args.app = NULL; d_args.resp_data = &response; - d_args.widget = app->active_widget; + d_args.element = app->active_widget; input_t *in_ip = d->g_content->elements[0].element; input_t *in_port = d->g_content->elements[1].element; dialogue_default_callback(&d_args); diff --git a/src/ui/modals/login_credentials.c b/src/ui/modals/login_credentials.c index 32c8616..3e421ff 100644 --- a/src/ui/modals/login_credentials.c +++ b/src/ui/modals/login_credentials.c @@ -22,7 +22,7 @@ void init_login_credentials_modal_cb(callback_args_t *args) { memcpy(&d_args, args, sizeof(callback_args_t)); d_args.app = NULL; d_args.resp_data = &response; - d_args.widget = app->active_widget; + d_args.element = app->active_widget; input_t *in_name = d->g_content->elements[0].element; input_t *in_pass = d->g_content->elements[1].element; dialogue_default_callback(&d_args); diff --git a/src/ui/modals/login_option.c b/src/ui/modals/login_option.c index 7cfc548..6c56e52 100644 --- a/src/ui/modals/login_option.c +++ b/src/ui/modals/login_option.c @@ -19,7 +19,7 @@ void login_modal_option_cb(callback_args_t *args) { memcpy(&d_args, args, sizeof(callback_args_t)); d_args.app = NULL; d_args.resp_data = &response; - d_args.widget = app->active_widget; + d_args.element = app->active_widget; dialogue_default_callback(&d_args); if (response > -1) { switch (response) { diff --git a/src/ui/modals/notification.c b/src/ui/modals/notification.c index c9ddd6c..bf98ab6 100644 --- a/src/ui/modals/notification.c +++ b/src/ui/modals/notification.c @@ -20,7 +20,7 @@ void init_notification_modal_cb(callback_args_t *args) { memcpy(&d_args, args, sizeof(callback_args_t)); d_args.app = NULL; d_args.resp_data = &response; - d_args.widget = app->active_widget; + d_args.element = app->active_widget; dialogue_default_callback(&d_args); app->query_args->state = WAIT_CLIENT; diff --git a/src/ui/widget/dialogue.c b/src/ui/widget/dialogue.c index 56c4b4f..45c1d0e 100644 --- a/src/ui/widget/dialogue.c +++ b/src/ui/widget/dialogue.c @@ -42,6 +42,18 @@ } \ } +widget_t *get_active_widget(dialogue_t *d) { + group_t *g; + if (d->active.type == g_action) { + g = d->g_action; + } else { + g = d->g_content; + } + widget_t *w = (widget_t *) g->elements[d->active.id - g->first_id].element; + return w; +} + + void dialogue_default_callback(callback_args_t *args) { dialogue_t *d = (void *)args->element; int32_t key = *((int32_t *)args->data); @@ -54,6 +66,7 @@ void dialogue_default_callback(callback_args_t *args) { int32_t diff; d->needs_update = true; input_t *input; + widget_t *widget; switch (key) { case '\t': if (d->active.type == g_content) { @@ -98,6 +111,12 @@ void dialogue_default_callback(callback_args_t *args) { *resp_value = -1; break; case '\n': + widget = get_active_widget(d); + if (widget->callback != NULL) { /* Existing callback case */ + new_args.element = widget; + widget->callback(&new_args); + break; + } /* Default cases */ if (d->active.type == g_action) { new_args.element = new_args.element = d->g_action; group_default_callback(&new_args); diff --git a/src/ui/widget/fs_file_list.c b/src/ui/widget/fs_file_list.c index fe739c9..623dfd4 100644 --- a/src/ui/widget/fs_file_list.c +++ b/src/ui/widget/fs_file_list.c @@ -1,5 +1,4 @@ #include "fs_file_list.h" -#include "../../file_processor.h" #include "progress_bar.h" #include #include @@ -7,35 +6,60 @@ #include #include #include +#include #include +#include #include #include void reset_file_list(ui_fs_file_list_t *fl_ui); -static void fl_add(fl_item_t **f_start, fl_item_t **f_current, - struct dirent *dent) { - fl_item_t *c_item = malloc(sizeof(fl_item_t)); - c_item->name = dent->d_name; - c_item->description = NULL; - c_item->owner = NULL; - c_item->size = 0; +struct fl_args { + char *name; + u_char d_type; +}; + +static void fl_add(fs_fl_item_t **f_start, fs_fl_item_t **f_current, + struct fl_args *fargs) { + fs_fl_item_t *c_item = malloc(sizeof(fs_fl_item_t)); + c_item->name = malloc(strlen(fargs->name) + 1); + strcpy(c_item->name, fargs->name); c_item->next = NULL; + c_item->d_type = fargs->d_type; if (*f_start == NULL) { + c_item->prev = NULL; *f_start = c_item; *f_current = c_item; } else { + c_item->prev = *f_current; (*f_current)->next = c_item; *f_current = c_item; } } -fl_item_t *get_files_from_fs(char *path) { - /* TODO: separate files from directories, mark directories, filter empty fields */ +static void fl_clear(fs_fl_item_t **start, fs_fl_item_t **arg_current) { + if (*start == NULL) + return; + fs_fl_item_t *next, *current; + current = *start; + + do { + next = current->next; + free(current->name); + free(current); + } while ((current = next) != NULL); + *start = NULL; + *arg_current = NULL; +} + +fs_fl_item_t *get_files_from_fs(char *path) { DIR *dir; struct dirent *dent; + char name[64]; + struct fl_args f_args; - fl_item_t *l_start = NULL, *l_current = NULL; + fs_fl_item_t *d_start = NULL, *d_current = NULL; /* directories */ + fs_fl_item_t *f_start = NULL, *f_current = NULL; /* files */ dir = opendir(path); if (!dir) { @@ -43,39 +67,60 @@ fl_item_t *get_files_from_fs(char *path) { errno = 1; } while ((dent = readdir(dir)) != NULL) { - fl_add(&l_start, &l_current, dent); + if ((f_args.d_type = dent->d_type) == DT_DIR) { + if (!strcmp(dent->d_name, ".")) + continue; + sprintf(name, "/%s", dent->d_name); + f_args.name = name; + fl_add(&d_start, &d_current, &f_args); + } else { + f_args.name = dent->d_name; + sprintf(name, "%s", dent->d_name); + fl_add(&f_start, &f_current, &f_args); + } + } + if (d_current != NULL) d_current->next = f_start; + if (f_start != NULL) f_start->prev = d_current; + return d_start; +} + +void select_item(ui_fs_file_list_t *fui) { + char d_name[64] = "./"; + if (fui->current->d_type == DT_DIR) { + if (!strcmp("/..", fui->current->name)) { + /* TODO: slice the last "/abc" */ + } else { + strcat(d_name, fui->current->name + 1); /* skip "/" in the name */ + } + fui->start = get_files_from_fs(d_name); + fui->current = fui->start; + draw_fs_file_list(fui); } - return l_start; } void fs_file_list_cb(callback_args_t *args) { ui_fs_file_list_t *fui = args->element; int32_t key = *((int32_t *)args->data); int32_t q_len = 0; - fl_item_t *f_item; + fs_fl_item_t *f_item; ui_progress_bar_t *pb; switch (key) { case KEY_DOWN: - if (fui->current_idx < fui->current_count - 1) { + if (fui->current->next != NULL) { + fui->current = fui->current->next; fui->current_idx++; draw_fs_file_list(fui); - } else { - fl_clear(fui->start, fui->current); - reset_file_list(fui); } break; case KEY_UP: - if (fui->current_idx > 0) { + if (fui->current->prev != NULL) { + fui->current = fui->current->prev; fui->current_idx--; draw_fs_file_list(fui); - } else { - fl_clear(fui->start, fui->current); - reset_fs_file_list(fui); - fui->activate_last = true; } break; case '\n': - /* here goes file select */ + select_item(fui); break; } } @@ -85,22 +130,16 @@ ui_fs_file_list_t *init_fs_file_list(WINDOW **win, widget_t *w_parent) { WINDOW *win_par = *(w_parent->w_parent->parent_win); init_widget(&(fl_ui->w), w_parent, win, ""); fl_ui->current_idx = 0; - fl_ui->current_count = 0; - fl_ui->activate_last = false; fl_ui->info_win = NULL; - fl_ui->start = malloc(sizeof(fl_item_t *)); /* For compatibility reasons */ - *(fl_ui->start) = get_files_from_fs("./"); + fl_ui->start = get_files_from_fs("./"); + fl_ui->current = fl_ui->start; fl_ui->w.callback = fs_file_list_cb; fl_ui->w.x = getmaxx(win_par) / 10 * 8; fl_ui->w.y = getmaxy(win_par) / 10 * 8; return fl_ui; } -void reset_fs_file_list(ui_fs_file_list_t *fl_ui) { - fl_ui->current_idx = 0; - fl_ui->current_count = 0; - fl_ui->activate_last = false; -} +void reset_fs_file_list(ui_fs_file_list_t *fl_ui) { fl_ui->current_idx = 0; } void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { int32_t sz_y, sz_x; @@ -111,39 +150,31 @@ void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { int32_t sz_x_f = sz_x - 2; // actual size (without box) p_y = 1; p_x = 1; - fl_item_t *el = *(fl_ui->start); - fl_item_t *active_el = *(fl_ui->start); - int32_t cur_el_idx = 0; - - if (fl_ui->activate_last) { - fl_ui->current_idx = fl_ui->current_count - 1; - fl_ui->activate_last = false; - } + fs_fl_item_t *el = fl_ui->start; + fs_fl_item_t *active_el = fl_ui->start; if (fl_ui->current_idx + 1 >= sz_y_f) { p_y -= fl_ui->current_idx - sz_y_f + 2; } - wattrset(win, A_REVERSE); /* Match with window background */ + wattrset(win, A_REVERSE); /* Match with modal background */ do { if (p_y < 1) { p_y++; - cur_el_idx++; continue; } - if (cur_el_idx == fl_ui->current_idx) { + if (el == fl_ui->current) { wattrset(win, COLOR_PAIR(3) | A_BOLD | A_REVERSE); active_el = el; } p_x = 1; mvwprintw(win, p_y, p_x, "%s%n", el->name, &p_x); mvwprintw(win, p_y, p_x + 1, "%*s", sz_x_f - p_x, ""); - if (cur_el_idx == fl_ui->current_idx) { + if (el == fl_ui->current) { wattroff(win, COLOR_PAIR(3) | A_BOLD); } p_y++; - cur_el_idx++; } while ((el = el->next) != NULL && p_y < sz_y_f); p_x = 1; @@ -158,7 +189,6 @@ void draw_fs_file_list(ui_fs_file_list_t *fl_ui) { } void destroy_fs_file_list(ui_fs_file_list_t *fui) { - fl_clear(fui->start, fui->current); - free(fui->start); + fl_clear(&(fui->start), &(fui->current)); free(fui); } \ No newline at end of file diff --git a/src/ui/widget/fs_file_list.h b/src/ui/widget/fs_file_list.h index 0413116..b36f0d0 100644 --- a/src/ui/widget/fs_file_list.h +++ b/src/ui/widget/fs_file_list.h @@ -3,15 +3,22 @@ #include "../widget.h" #include #include +#include + +typedef struct fs_fl_item { + char *name; + struct fs_fl_item *next; + struct fs_fl_item *prev; + u_char d_type; +} fs_fl_item_t; typedef struct { widget_t w; - fl_item_t **current; - fl_item_t **start; + fs_fl_item_t *current; + fs_fl_item_t *start; int32_t current_idx; - uint32_t current_count; - uint32_t activate_last : 1; WINDOW *const* info_win; + char d_path[512]; } ui_fs_file_list_t; void draw_fs_file_list(ui_fs_file_list_t *fl_ui);