diff --git a/CMakeLists.txt b/CMakeLists.txt index 40278f0..bcadb00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ set(SOURCES src/ncurses/ui_call_flow.c src/ncurses/call_list.c src/ncurses/ui_call_raw.c - src/ncurses/ui_column_select.c + src/ncurses/column_select.c src/ncurses/ui_filter.c src/ncurses/ui_msg_diff.c src/ncurses/ui_save.c diff --git a/src/filter.c b/src/filter.c index a159a65..1916244 100644 --- a/src/filter.c +++ b/src/filter.c @@ -120,7 +120,7 @@ filter_check_call(gconstpointer item, G_GNUC_UNUSED gconstpointer user_data) break; case FILTER_CALL_LIST: // FIXME Maybe call should know hot to calculate this line - call_list_line_text(ui_find_by_type(WINDOW_CALL_LIST), call, data); + call_list_line_text(ncurses_find_by_type(WINDOW_CALL_LIST), call, data); break; default: // Unknown filter id diff --git a/src/glib-utils.c b/src/glib-utils.c index f84c501..17ccec0 100644 --- a/src/glib-utils.c +++ b/src/glib-utils.c @@ -210,6 +210,14 @@ g_ptr_array_remove_array(GPtrArray *array, GPtrArray *items) g_ptr_array_foreach(items, (GFunc) g_ptr_array_remove_cb, array); } +void +g_ptr_array_remove_all(GPtrArray *array) +{ + if (g_ptr_array_len(array) != 0) { + g_ptr_array_remove_range(array, 0, g_ptr_array_len(array)); + } +} + #if !GLIB_CHECK_VERSION(2, 54, 0) gboolean g_ptr_array_find(GPtrArray *haystack, gconstpointer needle, guint *index_) diff --git a/src/glib-utils.h b/src/glib-utils.h index 96cc1a1..decf25d 100644 --- a/src/glib-utils.h +++ b/src/glib-utils.h @@ -84,6 +84,9 @@ g_ptr_array_add_array(GPtrArray *array, GPtrArray *items); void g_ptr_array_remove_array(GPtrArray *array, GPtrArray *items); +void +g_ptr_array_remove_all(GPtrArray *array); + #if !GLIB_CHECK_VERSION(2,54,0) gboolean g_ptr_array_find(GPtrArray *haystack, gconstpointer needle, guint *index); diff --git a/src/ncurses/call_list.c b/src/ncurses/call_list.c index becd7e0..998a188 100644 --- a/src/ncurses/call_list.c +++ b/src/ncurses/call_list.c @@ -47,6 +47,7 @@ #include "ncurses/ui_filter.h" #include "ncurses/ui_save.h" #include "storage.h" +#include "column_select.h" /** * @brief Get custom information of given panel @@ -57,7 +58,7 @@ * @param window UI structure pointer * @return a pointer to info structure of given panel */ -CallListInfo * +static CallListInfo * call_list_info(Window *window) { return (CallListInfo*) panel_userptr(window->panel); @@ -214,8 +215,8 @@ call_list_resize(Window *window) static void call_list_draw_header(Window *window) { - const char *infile, *coldesc; - int colpos, collen; + const char *infile; + int colpos; const char *countlb; const char *device, *filterbpf; @@ -297,26 +298,25 @@ call_list_draw_header(Window *window) colpos = 6; } - for (guint i = 0; i < info->columncnt; i++) { - // Get current column width - collen = info->columns[i].width; + for (guint i = 0; i < g_ptr_array_len(info->columns); i++) { + CallListColumn *column = g_ptr_array_index(info->columns, i); // Get current column title - coldesc = sip_attr_get_title(info->columns[i].id); + const gchar *coldesc = sip_attr_get_title(column->id); // Check if the column will fit in the remaining space of the screen if (colpos + strlen(coldesc) >= (guint) window->width) break; // Print sort column indicator - if (info->columns[i].id == sort.by) { + if (column->id == sort.by) { wattron(window->win, A_BOLD | COLOR_PAIR(CP_YELLOW_ON_CYAN)); gchar sortind = (gchar) ((sort.asc) ? '^' : 'v'); - mvwprintw(window->win, 4, colpos, "%c%.*s", sortind, collen, coldesc); + mvwprintw(window->win, 4, colpos, "%c%.*s", sortind, column->width, coldesc); wattron(window->win, A_BOLD | COLOR_PAIR(CP_DEF_ON_CYAN)); } else { - mvwprintw(window->win, 4, colpos, "%.*s", collen, coldesc); + mvwprintw(window->win, 4, colpos, "%.*s", column->width, coldesc); } - colpos += collen + 1; + colpos += column->width + 1; } // Print Autoscroll indicator @@ -339,7 +339,6 @@ call_list_draw_header(Window *window) } else { mvwprintw(window->win, 1, 45, "%s: %d", countlb, stats.total); } - } /** @@ -381,12 +380,9 @@ call_list_draw_footer(Window *window) static void call_list_draw_list(Window *window) { - WINDOW *list_win; int listh, listw, cline = 0; SipCall *call = NULL; - int collen; char coltext[SIP_ATTR_MAXLEN]; - int colid; int colpos; int color; @@ -395,7 +391,7 @@ call_list_draw_list(Window *window) g_return_if_fail(info != NULL); // Get window of call list panel - list_win = info->list_win; + WINDOW *list_win = info->list_win; getmaxyx(list_win, listh, listw); // Get the list of calls that are goint to be displayed @@ -443,36 +439,33 @@ call_list_draw_list(Window *window) // Print requested columns colpos = 6; - for (guint j = 0; j < info->columncnt; j++) { - // Get current column id - colid = info->columns[j].id; - // Get current column width - collen = info->columns[j].width; + for (guint j = 0; j < g_ptr_array_len(info->columns); j++) { + CallListColumn *column = g_ptr_array_index(info->columns, j); // Check if next column fits on window width - if (colpos + collen >= listw) + if (colpos + column->width >= (guint) listw) break; // Initialize column text memset(coltext, 0, sizeof(coltext)); // Get call attribute for current column - if (!call_get_attribute(call, colid, coltext)) { - colpos += collen + 1; + if (!call_get_attribute(call, column->id, coltext)) { + colpos += column->width + 1; continue; } // Enable attribute color (if not current one) color = 0; if (info->cur_idx != i) { - if ((color = sip_attr_get_color(colid, coltext)) > 0) { + if ((color = sip_attr_get_color(column->id, coltext)) > 0) { wattron(list_win, color); } } // Add the column text to the existing columns - mvwprintw(list_win, cline, colpos, "%.*s", collen, coltext); - colpos += collen + 1; + mvwprintw(list_win, cline, colpos, "%.*s", column->width, coltext); + colpos += column->width + 1; // Disable attribute color if (color > 0) @@ -583,13 +576,11 @@ call_list_line_text(Window *window, SipCall *call, char *text) g_return_val_if_fail(info != NULL, text); // Print requested columns - for (guint i = 0; i < info->columncnt; i++) { - - // Get current column id - enum sip_attr_id colid = info->columns[i].id; + for (guint i = 0; i < g_ptr_array_len(info->columns); i++) { + CallListColumn *column = g_ptr_array_index(info->columns, i); // Get current column width - gint collen = info->columns[i].width; + gint collen = column->width; // Check if next column fits on window width if ((gint)(strlen(text) + collen) >= window->width) @@ -604,7 +595,7 @@ call_list_line_text(Window *window, SipCall *call, char *text) memset(call_attr, 0, sizeof(call_attr)); // Get call attribute for current column - if (call_get_attribute(call, colid, call_attr)) { + if (call_get_attribute(call, column->id, call_attr)) { sprintf(coltext, "%.*s", collen, call_attr); } // Add the column text to the existing columns @@ -635,11 +626,12 @@ call_list_select_sort_attribute(Window *window) mvderwin(info->list_win, 5, 12); // Create menu entries - for (guint i = 0; i < info->columncnt; i++) { - info->items[i] = new_item(sip_attr_get_name(info->columns[i].id), 0); + for (guint i = 0; i < g_ptr_array_len(info->columns); i++) { + CallListColumn *column = g_ptr_array_index(info->columns, i); + info->items[i] = new_item(sip_attr_get_name(column->id), 0); } - info->items[info->columncnt] = NULL; + info->items[g_ptr_array_len(info->columns)] = NULL; // Create the columns menu and post it info->menu = new_menu(info->items); @@ -845,7 +837,7 @@ static int call_list_handle_key(Window *window, int key) { guint rnpag_steps = (guint) setting_get_intvalue(SETTING_CL_SCROLLSTEP); - Window *next_ui; + Window *next_window; SipCallGroup *group; int action = -1; SipCall *call; @@ -931,7 +923,8 @@ call_list_handle_key(Window *window, int key) ncurses_create_window(PANEL_FILTER); break; case ACTION_SHOW_COLUMNS: - ncurses_create_window(PANEL_COLUMN_SELECT); + next_window = ncurses_create_window(WINDOW_COLUMN_SELECT); + column_select_set_columns(next_window, info->columns); break; case ACTION_SHOW_STATS: ncurses_create_window(PANEL_STATS); @@ -941,8 +934,8 @@ call_list_handle_key(Window *window, int key) dialog_run("Saving is not possible when multiple input sources are specified."); break; } - next_ui = ncurses_create_window(PANEL_SAVE); - save_set_group(next_ui, info->group); + next_window = ncurses_create_window(PANEL_SAVE); + save_set_group(next_window, info->group); break; case ACTION_CLEAR: // Clear group calls @@ -1108,18 +1101,19 @@ call_list_help(G_GNUC_UNUSED Window *window) * @param width Column Width * @return 0 if column has been successufly added to the list, -1 otherwise */ -void +static void call_list_add_column(Window *window, enum sip_attr_id id, const char* attr, const char *title, int width) { CallListInfo *info = call_list_info(window); g_return_if_fail(info != NULL); - info->columns[info->columncnt].id = id; - info->columns[info->columncnt].attr = attr; - info->columns[info->columncnt].title = title; - info->columns[info->columncnt].width = (guint) width; - info->columncnt++; + CallListColumn *column = g_malloc0(sizeof(CallListColumn)); + column->id = id; + column->attr = attr; + column->title = title; + column->width = (guint) width; + g_ptr_array_add(info->columns, column); } void @@ -1159,6 +1153,7 @@ call_list_free(Window *window) // Deallocate window private data call_group_free(info->group); + g_ptr_array_free(info->columns, TRUE); g_ptr_array_free(info->dcalls, FALSE); delwin(info->list_win); g_free(info); @@ -1188,6 +1183,7 @@ call_list_new() set_panel_userptr(window->panel, (void*) info); // Add configured columns + info->columns = g_ptr_array_new_with_free_func(g_free); for (guint i = 0; i < SIP_ATTR_COUNT; i++) { // Get column attribute name from options gchar *option = g_strdup_printf("cl.column%d", i); diff --git a/src/ncurses/call_list.h b/src/ncurses/call_list.h index f06265f..6abf411 100644 --- a/src/ncurses/call_list.h +++ b/src/ncurses/call_list.h @@ -84,9 +84,7 @@ struct _CallListInfo { //! Selected calls with space SipCallGroup *group; //! Displayed column list, make it configurable in the future - CallListColumn columns[SIP_ATTR_COUNT]; - //! Displayed column count. - guint columncnt; + GPtrArray *columns; //! List subwindow WINDOW *list_win; //! Form that contains the display filter @@ -121,18 +119,6 @@ struct _CallListInfo { Window * call_list_new(); -/** - * @brief Get custom information of given panel - * - * Return ncurses users pointer of the given panel into panel's - * information structure pointer. - * - * @param window UI structure pointer - * @return a pointer to info structure of given panel - */ -CallListInfo * -call_list_info(Window *window); - /** * @brief Get List line from the given call * @@ -147,22 +133,6 @@ call_list_info(Window *window); const char* call_list_line_text(Window *window, SipCall *call, char *text); -/** - * @brief Add a column the Call List - * - * This function will add a new column to the Call List panel - * @todo Columns are not configurable yet. - * - * @param window UI structure pointer - * @param id SIP call attribute id - * @param attr SIP call attribute name - * @param title SIP call attribute description - * @param width Column Width - */ -void -call_list_add_column(Window *window, enum sip_attr_id id, const char* attr, - const char *title, int width); - /** * @brief Remove all calls from the list and calls storage * diff --git a/src/ncurses/ui_column_select.c b/src/ncurses/column_select.c similarity index 61% rename from src/ncurses/ui_column_select.c rename to src/ncurses/column_select.c index aff80a7..26c378e 100644 --- a/src/ncurses/ui_column_select.c +++ b/src/ncurses/column_select.c @@ -29,331 +29,139 @@ */ #include "config.h" #include -#include #include #include #include #include +#include +#include "glib-utils.h" #include "ncurses/ui_manager.h" #include "ncurses/call_list.h" -#include "ncurses/ui_column_select.h" +#include "ncurses/column_select.h" /** - * Ui Structure definition for Message Diff panel + * @brief Get custom information of given panel + * + * Return ncurses users pointer of the given panel into panel's + * information structure pointer. + * + * @param ui UI structure pointer + * @return a pointer to info structure of given panel */ -Window ui_column_select = { - .type = PANEL_COLUMN_SELECT, - .panel = NULL, - .create = column_select_create, - .handle_key = column_select_handle_key, - .destroy = column_select_destroy -}; - -void -column_select_create(Window *ui) -{ - int attr_id; - MENU *menu; - column_select_info_t *info; - - // Cerate a new indow for the panel and form - window_init(ui, 20, 60); - - // Initialize Filter panel specific data - info = g_malloc0(sizeof(column_select_info_t)); - - // Store it into panel userptr - set_panel_userptr(ui->panel, (void*) info); - - // Initialize the fields - info->fields[FLD_COLUMNS_ACCEPT] = new_field(1, 10, ui->height - 2, 13, 0, 0); - info->fields[FLD_COLUMNS_SAVE] = new_field(1, 10, ui->height - 2, 25, 0, 0); - info->fields[FLD_COLUMNS_CANCEL] = new_field(1, 10, ui->height - 2, 37, 0, 0); - info->fields[FLD_COLUMNS_COUNT] = NULL; - - // Field Labels - set_field_buffer(info->fields[FLD_COLUMNS_ACCEPT], 0, "[ Accept ]"); - set_field_buffer(info->fields[FLD_COLUMNS_SAVE], 0, "[ Save ]"); - set_field_buffer(info->fields[FLD_COLUMNS_CANCEL], 0, "[ Cancel ]"); - - // Create the form and post it - info->form = new_form(info->fields); - set_form_sub(info->form, ui->win); - post_form(info->form); - - // Create a subwin for the menu area - info->menu_win = derwin(ui->win, 10, ui->width - 2, 7, 0); - - // Initialize one field for each attribute - for (attr_id = 0; attr_id < SIP_ATTR_COUNT; attr_id++) { - // Create a new field for this column - info->items[attr_id] = new_item("[ ]", sip_attr_get_description(attr_id)); - set_item_userptr(info->items[attr_id], (void*) sip_attr_get_name(attr_id)); - } - info->items[SIP_ATTR_COUNT] = NULL; - - // Create the columns menu and post it - info->menu = menu = new_menu(info->items); - - // Set current enabled fields - // FIXME Stealing Call list columns :/ - CallListInfo *list_info = call_list_info(ui_find_by_type(WINDOW_CALL_LIST)); - - // Enable current enabled fields and move them to the top - for (guint column = 0; column < list_info->columncnt; column++) { - const char *attr = list_info->columns[column].attr; - for (attr_id = 0; attr_id < item_count(menu); attr_id++) { - if (!strcmp(item_userptr(info->items[attr_id]), attr)) { - column_select_toggle_item(ui, info->items[attr_id]); - column_select_move_item(ui, info->items[attr_id], column); - break; - } - } - } - - // Set main window and sub window - set_menu_win(menu, ui->win); - set_menu_sub(menu, derwin(ui->win, 10, ui->width - 5, 7, 2)); - set_menu_format(menu, 10, 1); - set_menu_mark(menu, ""); - set_menu_fore(menu, COLOR_PAIR(CP_DEF_ON_BLUE)); - menu_opts_off(menu, O_ONEVALUE); - post_menu(menu); - - // Draw a scrollbar to the right - info->scroll = ui_set_scrollbar(info->menu_win, SB_VERTICAL, SB_RIGHT); - info->scroll.max = item_count(menu) - 1; - ui_scrollbar_draw(info->scroll); - - // Set the window title and boxes - mvwprintw(ui->win, 1, ui->width / 2 - 14, "Call List columns selection"); - wattron(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); - title_foot_box(ui->panel); - mvwhline(ui->win, 6, 1, ACS_HLINE, ui->width - 1); - mvwaddch(ui->win, 6, 0, ACS_LTEE); - mvwaddch(ui->win, 6, ui->width - 1, ACS_RTEE); - wattroff(ui->win, COLOR_PAIR(CP_BLUE_ON_DEF)); - - // Some brief explanation abotu what window shows - wattron(ui->win, COLOR_PAIR(CP_CYAN_ON_DEF)); - mvwprintw(ui->win, 3, 2, "This windows show the list of columns displayed on Call"); - mvwprintw(ui->win, 4, 2, "List. You can enable/disable using Space Bar and reorder"); - mvwprintw(ui->win, 5, 2, "them using + and - keys."); - wattroff(ui->win, COLOR_PAIR(CP_CYAN_ON_DEF)); - - info->form_active = 0; -} - -void -column_select_destroy(Window *ui) -{ - int i; - column_select_info_t *info = column_select_info(ui); - - // Remove menu and items - unpost_menu(info->menu); - free_menu(info->menu); - for (i = 0; i < SIP_ATTR_COUNT; i++) - free_item(info->items[i]); - - // Remove form and fields - unpost_form(info->form); - free_form(info->form); - for (i = 0; i < FLD_COLUMNS_COUNT; i++) - free_field(info->fields[i]); - - g_free(info); - - // Remove panel window and custom info - window_deinit(ui); -} - - -column_select_info_t * +static ColumnSelectInfo * column_select_info(Window *ui) { - return (column_select_info_t*) panel_userptr(ui->panel); + return (ColumnSelectInfo*) panel_userptr(ui->panel); } -int -column_select_handle_key(Window *ui, int key) +/** + * @brief Move a item to a new position + * + * This function can be used to reorder the column list + * + * @param ui UI structure pointer + * @param item Menu item to be moved + * @param post New position in the menu + */ +static void +column_select_move_item(Window *ui, ITEM *item, int pos) { // Get panel information - column_select_info_t *info = column_select_info(ui); + ColumnSelectInfo *info = column_select_info(ui); - if (info->form_active) { - return column_select_handle_key_form(ui, key); + // Check we have a valid position + if (pos == item_count(info->menu) || pos < 0) + return; + + // Swap position with destination + int item_pos = item_index(item); + info->items[item_pos] = info->items[pos]; + info->items[pos] = item; + set_menu_items(info->menu, info->items); +} + +/** + * @brief Select/Deselect a menu item + * + * This function can be used to toggle selection status of + * the menu item + * + * @param ui UI structure pointer + * @param item Menu item to be (de)selected + */ +static void +column_select_toggle_item(Window *ui, ITEM *item) +{ + // Get panel information + ColumnSelectInfo *info = column_select_info(ui); + + int pos = item_index(item); + + // Change item name + if (!strncmp(item_name(item), "[ ]", 3)) { + info->items[pos] = new_item("[*]", item_description(item)); } else { - return column_select_handle_key_menu(ui, key); + info->items[pos] = new_item("[ ]", item_description(item)); } - return 0; + + // Restore menu item + set_item_userptr(info->items[pos], item_userptr(item)); + set_menu_items(info->menu, info->items); + + // Destroy old item + free_item(item); } -int -column_select_handle_key_menu(Window *ui, int key) +/** + * @brief Update menu after a change + * + * After moving an item or updating its selectioactivn status + * menu must be redrawn. + * + * @param ui UI structure pointer + */ +static void +column_select_update_menu(Window *ui) { - MENU *menu; - ITEM *current; - int current_idx; - int action = -1; - // Get panel information - column_select_info_t *info = column_select_info(ui); + ColumnSelectInfo *info = column_select_info(ui); + ITEM *current = current_item(info->menu); + int top_idx = top_row(info->menu); - menu = info->menu; - current = current_item(menu); - current_idx = item_index(current); + // Remove the menu from the subwindow + unpost_menu(info->menu); + // Set menu items + set_menu_items(info->menu, info->items); + // Put the menu agin into its subwindow + post_menu(info->menu); - // Check actions for this key - while ((action = key_find_action(key, action)) != ERR) { - // Check if we handle this action - switch (action) { - case ACTION_DOWN: - menu_driver(menu, REQ_DOWN_ITEM); - break; - case ACTION_UP: - menu_driver(menu, REQ_UP_ITEM); - break; - case ACTION_NPAGE: - menu_driver(menu, REQ_SCR_DPAGE); - break; - case ACTION_PPAGE: - menu_driver(menu, REQ_SCR_UPAGE); - break; - case ACTION_SELECT: - column_select_toggle_item(ui, current); - column_select_update_menu(ui); - break; - case ACTION_COLUMN_MOVE_DOWN: - column_select_move_item(ui, current, current_idx + 1); - column_select_update_menu(ui); - break; - case ACTION_COLUMN_MOVE_UP: - column_select_move_item(ui, current, current_idx - 1); - column_select_update_menu(ui); - break; - case ACTION_NEXT_FIELD: - info->form_active = 1; - set_menu_fore(menu, COLOR_PAIR(CP_DEFAULT)); - set_field_back(info->fields[FLD_COLUMNS_ACCEPT], A_REVERSE); - form_driver(info->form, REQ_VALIDATION); - break; - case ACTION_CONFIRM: - column_select_update_columns(ui); - ui_destroy(ui); - return KEY_HANDLED; - default: - // Parse next action - continue; - } + // Move until the current position is set + set_top_row(info->menu, top_idx); + set_current_item(info->menu, current); - // This panel has handled the key successfully - break; - } - - // Draw a scrollbar to the right - info->scroll.pos = top_row(menu); - ui_scrollbar_draw(info->scroll); - wnoutrefresh(info->menu_win); - - // Return if this panel has handled or not the key - return (action == ERR) ? KEY_NOT_HANDLED : KEY_HANDLED; + // Force menu redraw + menu_driver(info->menu, REQ_DOWN_ITEM); + menu_driver(info->menu, REQ_UP_ITEM); } -int -column_select_handle_key_form(Window *ui, int key) -{ - int field_idx, new_field_idx; - char field_value[48]; - int action = -1; - - // Get panel information - column_select_info_t *info = column_select_info(ui); - - // Get current field id - field_idx = field_index(current_field(info->form)); - - // Get current field value. - memset(field_value, 0, sizeof(field_value)); - strcpy(field_value, field_buffer(current_field(info->form), 0)); - g_strstrip(field_value); - - // Check actions for this key - while ((action = key_find_action(key, action)) != ERR) { - // Check if we handle this action - switch (action) { - case ACTION_RIGHT: - case ACTION_NEXT_FIELD: - form_driver(info->form, REQ_NEXT_FIELD); - break; - case ACTION_LEFT: - case ACTION_PREV_FIELD: - form_driver(info->form, REQ_PREV_FIELD); - break; - case ACTION_SELECT: - case ACTION_CONFIRM: - switch(field_idx) { - case FLD_COLUMNS_ACCEPT: - column_select_update_columns(ui); - ui_destroy(ui); - return KEY_HANDLED; - case FLD_COLUMNS_CANCEL: - ui_destroy(ui); - return KEY_HANDLED; - case FLD_COLUMNS_SAVE: - column_select_update_columns(ui); - column_select_save_columns(ui); - ui_destroy(ui); - return KEY_HANDLED; - } - break; - default: - // Parse next action - continue; - } - - // This panel has handled the key successfully - break; - } - - // Validate all input data - form_driver(info->form, REQ_VALIDATION); - - // Change background and cursor of "button fields" - set_field_back(info->fields[FLD_COLUMNS_ACCEPT], A_NORMAL); - set_field_back(info->fields[FLD_COLUMNS_SAVE], A_NORMAL); - set_field_back(info->fields[FLD_COLUMNS_CANCEL], A_NORMAL); - - // Get current selected field - new_field_idx = field_index(current_field(info->form)); - - // Swap between menu and form - if (field_idx == FLD_COLUMNS_CANCEL && new_field_idx == FLD_COLUMNS_ACCEPT) { - set_menu_fore(info->menu, COLOR_PAIR(CP_DEF_ON_BLUE)); - info->form_active = 0; - } else { - // Change current field background - set_field_back(info->fields[new_field_idx], A_REVERSE); - } - - // Return if this panel has handled or not the key - return (action == ERR) ? KEY_NOT_HANDLED : KEY_HANDLED; -} - -void +/** + * @brief Update Call List columns + * + * This function will update the columns of Call List + * + * @param ui UI structure pointer + */ +static void column_select_update_columns(Window *ui) { int column, attr_id; // Get panel information - column_select_info_t *info = column_select_info(ui); - - // Set enabled fields - Window *ui_list = ui_find_by_type(WINDOW_CALL_LIST); - CallListInfo *list_info = call_list_info(ui_list); + ColumnSelectInfo *info = column_select_info(ui); + g_return_if_fail(info != NULL); // Reset column count - list_info->columncnt = 0; + g_ptr_array_remove_all(info->selected); // Add all selected columns for (column = 0; column < item_count(info->menu); column++) { @@ -363,13 +171,26 @@ column_select_update_columns(Window *ui) // Get column attribute attr_id = sip_attr_from_name(item_userptr(info->items[column])); + // Add a new column to the list - call_list_add_column(ui_list, attr_id, sip_attr_get_name(attr_id), - sip_attr_get_title(attr_id), sip_attr_get_width(attr_id)); + CallListColumn *column = g_malloc0(sizeof(CallListColumn)); + column->id = attr_id; + column->attr = sip_attr_get_name(attr_id); + column->title = sip_attr_get_title(attr_id); + column->width = (guint) sip_attr_get_width(attr_id); + g_ptr_array_add(info->selected, column); } } -void +/** + * @brief Save selected columns to user config file + * + * Remove previously configurated columns from user's + * $SNGREPRC or $HOME/.sngreprc and add new ones + * + * @param ui UI structure pointer + */ +static void column_select_save_columns(Window *ui) { g_autoptr(GString) userconf = g_string_new(NULL); @@ -429,7 +250,7 @@ column_select_save_columns(Window *ui) } // Get panel information - column_select_info_t *info = column_select_info(ui); + ColumnSelectInfo *info = column_select_info(ui); // Add all selected columns for (gint i = 0; i < item_count(info->menu); i++) { @@ -447,67 +268,338 @@ column_select_save_columns(Window *ui) dialog_run("Column layout successfully saved to %s", userconf->str); } - -void -column_select_move_item(Window *ui, ITEM *item, int pos) +/** + * @brief Manage pressed keys for column selection panel + * + * This function will handle keys when menu is active. + * You can switch between menu and rest of the components + * using TAB + * + * @param ui UI structure pointer + * @param key key code + * @return enum @key_handler_ret + */ +static int +column_select_handle_key_menu(Window *ui, int key) { + ITEM *current; + int current_idx; + int action = -1; + // Get panel information - column_select_info_t *info = column_select_info(ui); + ColumnSelectInfo *info = column_select_info(ui); + g_return_val_if_fail(info != NULL, KEY_DESTROY); - // Check we have a valid position - if (pos == item_count(info->menu) || pos < 0) - return; + current = current_item(info->menu); + current_idx = item_index(current); - // Swap position with destination - int item_pos = item_index(item); - info->items[item_pos] = info->items[pos]; - info->items[pos] = item; - set_menu_items(info->menu, info->items); -} + // Check actions for this key + while ((action = key_find_action(key, action)) != ERR) { + // Check if we handle this action + switch (action) { + case ACTION_DOWN: + menu_driver(info->menu, REQ_DOWN_ITEM); + break; + case ACTION_UP: + menu_driver(info->menu, REQ_UP_ITEM); + break; + case ACTION_NPAGE: + menu_driver(info->menu, REQ_SCR_DPAGE); + break; + case ACTION_PPAGE: + menu_driver(info->menu, REQ_SCR_UPAGE); + break; + case ACTION_SELECT: + column_select_toggle_item(ui, current); + column_select_update_menu(ui); + break; + case ACTION_COLUMN_MOVE_DOWN: + column_select_move_item(ui, current, current_idx + 1); + column_select_update_menu(ui); + break; + case ACTION_COLUMN_MOVE_UP: + column_select_move_item(ui, current, current_idx - 1); + column_select_update_menu(ui); + break; + case ACTION_NEXT_FIELD: + info->form_active = 1; + set_menu_fore(info->menu, COLOR_PAIR(CP_DEFAULT)); + set_field_back(info->fields[FLD_COLUMNS_ACCEPT], A_REVERSE); + form_driver(info->form, REQ_VALIDATION); + break; + case ACTION_CONFIRM: + column_select_update_columns(ui); + return KEY_DESTROY; + default: + // Parse next action + continue; + } -void -column_select_toggle_item(Window *ui, ITEM *item) -{ - // Get panel information - column_select_info_t *info = column_select_info(ui); - - int pos = item_index(item); - - // Change item name - if (!strncmp(item_name(item), "[ ]", 3)) { - info->items[pos] = new_item("[*]", item_description(item)); - } else { - info->items[pos] = new_item("[ ]", item_description(item)); + // This panel has handled the key successfully + break; } - // Restore menu item - set_item_userptr(info->items[pos], item_userptr(item)); - set_menu_items(info->menu, info->items); + // Draw a scrollbar to the right + info->scroll.pos = (guint) top_row(info->menu); + ui_scrollbar_draw(info->scroll); + wnoutrefresh(info->menu_win); - // Destroy old item - free_item(item); + // Return if this panel has handled or not the key + return (action == ERR) ? KEY_NOT_HANDLED : KEY_HANDLED; +} + + +/** + * @brief Manage pressed keys for column selection panel + * + * This function will handle keys when form is active. + * You can switch between menu and rest of the components + * using TAB + * + * @param ui UI structure pointer + * @param key key code + * @return enum @key_handler_ret + */ +static int +column_select_handle_key_form(Window *ui, int key) +{ + int field_idx, new_field_idx; + char field_value[48]; + int action = -1; + + // Get panel information + ColumnSelectInfo *info = column_select_info(ui); + g_return_val_if_fail(info != NULL, KEY_DESTROY); + + // Get current field id + field_idx = field_index(current_field(info->form)); + + // Get current field value. + memset(field_value, 0, sizeof(field_value)); + strcpy(field_value, field_buffer(current_field(info->form), 0)); + g_strstrip(field_value); + + // Check actions for this key + while ((action = key_find_action(key, action)) != ERR) { + // Check if we handle this action + switch (action) { + case ACTION_RIGHT: + case ACTION_NEXT_FIELD: + form_driver(info->form, REQ_NEXT_FIELD); + break; + case ACTION_LEFT: + case ACTION_PREV_FIELD: + form_driver(info->form, REQ_PREV_FIELD); + break; + case ACTION_SELECT: + case ACTION_CONFIRM: + switch(field_idx) { + case FLD_COLUMNS_ACCEPT: + column_select_update_columns(ui); + return KEY_DESTROY; + case FLD_COLUMNS_CANCEL: + return KEY_DESTROY; + case FLD_COLUMNS_SAVE: + column_select_update_columns(ui); + column_select_save_columns(ui); + return KEY_DESTROY; + default:break; + } + break; + default: + // Parse next action + continue; + } + + // This panel has handled the key successfully + break; + } + + // Validate all input data + form_driver(info->form, REQ_VALIDATION); + + // Change background and cursor of "button fields" + set_field_back(info->fields[FLD_COLUMNS_ACCEPT], A_NORMAL); + set_field_back(info->fields[FLD_COLUMNS_SAVE], A_NORMAL); + set_field_back(info->fields[FLD_COLUMNS_CANCEL], A_NORMAL); + + // Get current selected field + new_field_idx = field_index(current_field(info->form)); + + // Swap between menu and form + if (field_idx == FLD_COLUMNS_CANCEL && new_field_idx == FLD_COLUMNS_ACCEPT) { + set_menu_fore(info->menu, COLOR_PAIR(CP_DEF_ON_BLUE)); + info->form_active = 0; + } else { + // Change current field background + set_field_back(info->fields[new_field_idx], A_REVERSE); + } + + // Return if this panel has handled or not the key + return (action == ERR) ? KEY_NOT_HANDLED : KEY_HANDLED; +} + +/** + * @brief Manage pressed keys for column selection panel + * + * This function is called by UI manager every time a + * key is pressed. This allow the filter panel to manage + * its own keys. + * + * @param window UI structure pointer + * @param key key code + * @return enum @key_handler_ret + */ +static int +column_select_handle_key(Window *window, int key) +{ + // Get panel information + ColumnSelectInfo *info = column_select_info(window); + g_return_val_if_fail(info != NULL, KEY_DESTROY); + + if (info->form_active) { + return column_select_handle_key_form(window, key); + } else { + return column_select_handle_key_menu(window, key); + } } void -column_select_update_menu(Window *ui) +column_select_set_columns(Window *window, GPtrArray *columns) { // Get panel information - column_select_info_t *info = column_select_info(ui); - ITEM *current = current_item(info->menu); - int top_idx = top_row(info->menu); + ColumnSelectInfo *info = column_select_info(window); + g_return_if_fail(info != NULL); - // Remove the menu from the subwindow + // Set selected column array + info->selected = columns; + + // Toggle current enabled fields and move them to the top + for (guint i = 0; i < g_ptr_array_len(info->selected); i++) { + CallListColumn *column = g_ptr_array_index(info->selected, i); + + for (guint attr_id = 0; attr_id < (guint) item_count(info->menu); attr_id++) { + if (!strcmp(item_userptr(info->items[attr_id]), column->attr)) { + column_select_toggle_item(window, info->items[attr_id]); + column_select_update_menu(window); + column_select_move_item(window, info->items[attr_id], i); + column_select_update_menu(window); + break; + } + } + } + + +} + +/** + * @brief Destroy column selection panel + * + * This function do the final cleanups for this panel + * + * @param ui UI structure pointer + */ +void +column_select_free(Window *ui) +{ + int i; + ColumnSelectInfo *info = column_select_info(ui); + + // Remove menu and items unpost_menu(info->menu); - // Set menu items - set_menu_items(info->menu, info->items); - // Put the menu agin into its subwindow + free_menu(info->menu); + for (i = 0; i < SIP_ATTR_COUNT; i++) + free_item(info->items[i]); + + // Remove form and fields + unpost_form(info->form); + free_form(info->form); + for (i = 0; i < FLD_COLUMNS_COUNT; i++) + free_field(info->fields[i]); + + g_free(info); + + // Remove panel window and custom info + window_deinit(ui); +} + +Window * +column_select_new() +{ + Window *window = g_malloc0(sizeof(Window)); + window->type = WINDOW_COLUMN_SELECT; + window->handle_key = column_select_handle_key; + window->destroy = column_select_free; + + // Cerate a new indow for the panel and form + window_init(window, 20, 60); + + // Initialize Filter panel specific data + ColumnSelectInfo *info = g_malloc0(sizeof(ColumnSelectInfo)); + set_panel_userptr(window->panel, (void*) info); + + // Initialize attributes + info->form_active = FALSE; + + // Initialize the fields + info->fields[FLD_COLUMNS_ACCEPT] = new_field(1, 10, window->height - 2, 13, 0, 0); + info->fields[FLD_COLUMNS_SAVE] = new_field(1, 10, window->height - 2, 25, 0, 0); + info->fields[FLD_COLUMNS_CANCEL] = new_field(1, 10, window->height - 2, 37, 0, 0); + info->fields[FLD_COLUMNS_COUNT] = NULL; + + // Field Labels + set_field_buffer(info->fields[FLD_COLUMNS_ACCEPT], 0, "[ Accept ]"); + set_field_buffer(info->fields[FLD_COLUMNS_SAVE], 0, "[ Save ]"); + set_field_buffer(info->fields[FLD_COLUMNS_CANCEL], 0, "[ Cancel ]"); + + // Create the form and post it + info->form = new_form(info->fields); + set_form_sub(info->form, window->win); + post_form(info->form); + + // Create a subwin for the menu area + info->menu_win = derwin(window->win, 10, window->width - 2, 7, 0); + + // Initialize one field for each attribute + for (guint attr_id = 0; attr_id < SIP_ATTR_COUNT; attr_id++) { + // Create a new field for this column + info->items[attr_id] = new_item("[ ]", sip_attr_get_description(attr_id)); + set_item_userptr(info->items[attr_id], (void*) sip_attr_get_name(attr_id)); + } + info->items[SIP_ATTR_COUNT] = NULL; + + // Create the columns menu and post it + info->menu = new_menu(info->items); + + // Set main window and sub window + set_menu_win(info->menu, window->win); + set_menu_sub(info->menu, derwin(window->win, 10, window->width - 5, 7, 2)); + set_menu_format(info->menu, 10, 1); + set_menu_mark(info->menu, ""); + set_menu_fore(info->menu, COLOR_PAIR(CP_DEF_ON_BLUE)); + menu_opts_off(info->menu, O_ONEVALUE); post_menu(info->menu); - // Move until the current position is set - set_top_row(info->menu, top_idx); - set_current_item(info->menu, current); + // Draw a scrollbar to the right + info->scroll = ui_set_scrollbar(info->menu_win, SB_VERTICAL, SB_RIGHT); + info->scroll.max = (guint) (item_count(info->menu) - 1); + ui_scrollbar_draw(info->scroll); - // Force menu redraw - menu_driver(info->menu, REQ_UP_ITEM); - menu_driver(info->menu, REQ_DOWN_ITEM); + // Set the window title and boxes + mvwprintw(window->win, 1, window->width / 2 - 14, "Call List columns selection"); + wattron(window->win, COLOR_PAIR(CP_BLUE_ON_DEF)); + title_foot_box(window->panel); + mvwhline(window->win, 6, 1, ACS_HLINE, window->width - 1); + mvwaddch(window->win, 6, 0, ACS_LTEE); + mvwaddch(window->win, 6, window->width - 1, ACS_RTEE); + wattroff(window->win, COLOR_PAIR(CP_BLUE_ON_DEF)); + + // Some brief explanation abotu what window shows + wattron(window->win, COLOR_PAIR(CP_CYAN_ON_DEF)); + mvwprintw(window->win, 3, 2, "This windows show the list of columns displayed on Call"); + mvwprintw(window->win, 4, 2, "List. You can enable/disable using Space Bar and reorder"); + mvwprintw(window->win, 5, 2, "them using + and - keys."); + wattroff(window->win, COLOR_PAIR(CP_CYAN_ON_DEF)); + + return window; } diff --git a/src/ncurses/column_select.h b/src/ncurses/column_select.h new file mode 100644 index 0000000..a15881b --- /dev/null +++ b/src/ncurses/column_select.h @@ -0,0 +1,98 @@ +/************************************************************************** + ** + ** sngrep - SIP Messages flow viewer + ** + ** Copyright (C) 2013-2018 Ivan Alonso (Kaian) + ** Copyright (C) 2013-2018 Irontec SL. All rights reserved. + ** + ** This program is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** This program is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with this program. If not, see . + ** + ****************************************************************************/ +/** + * @file ui_column_select.h + * @author Ivan Alonso [aka Kaian] + * + * @brief Functions to manage columns select panel + */ + +#ifndef __UI_COLUMN_SELECT_H +#define __UI_COLUMN_SELECT_H + +#include "config.h" +#include +#include +#include "ncurses/ui_manager.h" +#include "ncurses/scrollbar.h" +#include "sip_attr.h" + +/** + * @brief Enum of available fields + */ +enum ColumnSelectFields { + FLD_COLUMNS_ACCEPT = 0, + FLD_COLUMNS_SAVE, + FLD_COLUMNS_CANCEL, + //! Never remove this field id + FLD_COLUMNS_COUNT +}; + + +//! Sorter declaration of struct columns_select_info +typedef struct _ColumnSelectInfo ColumnSelectInfo; + +/** + * @brief Column selector panel private information + * + * This structure contains the durable data of column selection panel. + */ +struct _ColumnSelectInfo { + //! Section of panel where menu is being displayed + WINDOW *menu_win; + //! Columns menu + MENU *menu; + // Columns Items + ITEM *items[SIP_ATTR_COUNT + 1]; + //! Current selected columns + GPtrArray *selected; + //! Form that contains the save fields + FORM *form; + //! An array of window form fields + FIELD *fields[FLD_COLUMNS_COUNT + 1]; + //! Flag to handle key inputs + gboolean form_active; + //! Scrollbar for the menu window + scrollbar_t scroll; +}; + +/** + * @brief Creates a new column selection window + * + * This function allocates all required memory for + * displaying the column selection window. It also draws all the + * static information of the panel that will never be + * redrawn. + * + * @return Window UI structure pointer + */ +Window * +column_select_new(); + +/** + * @brief Set Column array to be updated + * @param columns Array of currect active columns + */ +void +column_select_set_columns(Window *window, GPtrArray *columns); + +#endif /* __UI_COLUMN_SELECT_H */ diff --git a/src/ncurses/ui_call_flow.c b/src/ncurses/ui_call_flow.c index 279866d..008bfd9 100644 --- a/src/ncurses/ui_call_flow.c +++ b/src/ncurses/ui_call_flow.c @@ -1299,7 +1299,7 @@ call_flow_set_group(SipCallGroup *group) Window *ui; call_flow_info_t *info; - if (!(ui = ui_find_by_type(PANEL_CALL_FLOW))) + if (!(ui = ncurses_find_by_type(PANEL_CALL_FLOW))) return -1; if (!(info = call_flow_info(ui))) diff --git a/src/ncurses/ui_call_raw.c b/src/ncurses/ui_call_raw.c index 42eef56..992a05d 100644 --- a/src/ncurses/ui_call_raw.c +++ b/src/ncurses/ui_call_raw.c @@ -270,7 +270,7 @@ call_raw_handle_key(Window *ui, int key) case ACTION_TOGGLE_SYNTAX: case ACTION_CYCLE_COLOR: // Handle colors using default handler - ui_default_handle_key(ui, key); + ncurses_default_keyhandler(ui, key); // Create a new pad (forces messages draw) delwin(info->pad); info->pad = newpad(500, COLS); @@ -315,7 +315,7 @@ call_raw_set_group(SipCallGroup *group) if (!group) return -1; - if (!(ui = ui_find_by_type(PANEL_CALL_RAW))) + if (!(ui = ncurses_find_by_type(PANEL_CALL_RAW))) return -1; if (!(info = call_raw_info(ui))) @@ -341,7 +341,7 @@ call_raw_set_msg(SipMsg *msg) if (!msg) return -1; - if (!(ui = ui_find_by_type(PANEL_CALL_RAW))) + if (!(ui = ncurses_find_by_type(PANEL_CALL_RAW))) return -1; if (!(info = call_raw_info(ui))) diff --git a/src/ncurses/ui_column_select.h b/src/ncurses/ui_column_select.h deleted file mode 100644 index 8049475..0000000 --- a/src/ncurses/ui_column_select.h +++ /dev/null @@ -1,209 +0,0 @@ -/************************************************************************** - ** - ** sngrep - SIP Messages flow viewer - ** - ** Copyright (C) 2013-2018 Ivan Alonso (Kaian) - ** Copyright (C) 2013-2018 Irontec SL. All rights reserved. - ** - ** This program is free software: you can redistribute it and/or modify - ** it under the terms of the GNU General Public License as published by - ** the Free Software Foundation, either version 3 of the License, or - ** (at your option) any later version. - ** - ** This program is distributed in the hope that it will be useful, - ** but WITHOUT ANY WARRANTY; without even the implied warranty of - ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - ** GNU General Public License for more details. - ** - ** You should have received a copy of the GNU General Public License - ** along with this program. If not, see . - ** - ****************************************************************************/ -/** - * @file ui_column_select.h - * @author Ivan Alonso [aka Kaian] - * - * @brief Functions to manage columns select panel - */ - -#ifndef __UI_COLUMN_SELECT_H -#define __UI_COLUMN_SELECT_H - -#include "config.h" -#include -#include -#include "ncurses/ui_manager.h" -#include "ncurses/scrollbar.h" -#include "sip_attr.h" - -/** - * @brief Enum of available fields - */ -enum column_select_field_list { - FLD_COLUMNS_ACCEPT = 0, - FLD_COLUMNS_SAVE, - FLD_COLUMNS_CANCEL, - //! Never remove this field id - FLD_COLUMNS_COUNT -}; - - -//! Sorter declaration of struct columns_select_info -typedef struct column_select_info column_select_info_t; - -/** - * @brief Column selector panel private information - * - * This structure contains the durable data of column selection panel. - */ -struct column_select_info { - // Section of panel where menu is being displayed - WINDOW *menu_win; - // Columns menu - MENU *menu; - // Columns Items - ITEM *items[SIP_ATTR_COUNT + 1]; - //! Form that contains the save fields - FORM *form; - //! An array of window form fields - FIELD *fields[FLD_COLUMNS_COUNT + 1]; - //! Flag to handle key inputs - int form_active; - //! Scrollbar for the menu window - scrollbar_t scroll; -}; - -/** - * @brief Creates a new column selection panel - * - * This function allocates all required memory for - * displaying the column selection panel. It also draws all the - * static information of the panel that will never be - * redrawn. - * - * @param ui UI structure pointer - */ -void -column_select_create(Window *ui); - -/** - * @brief Destroy column selection panel - * - * This function do the final cleanups for this panel - * - * @param ui UI structure pointer - */ -void -column_select_destroy(Window *ui); - -/** - * @brief Get custom information of given panel - * - * Return ncurses users pointer of the given panel into panel's - * information structure pointer. - * - * @param ui UI structure pointer - * @return a pointer to info structure of given panel - */ -column_select_info_t * -column_select_info(Window *ui); - -/** - * @brief Manage pressed keys for column selection panel - * - * This function is called by UI manager every time a - * key is pressed. This allow the filter panel to manage - * its own keys. - * - * @param ui UI structure pointer - * @param key key code - * @return enum @key_handler_ret - */ -int -column_select_handle_key(Window *ui, int key); - -/** - * @brief Manage pressed keys for column selection panel - * - * This function will handle keys when menu is active. - * You can switch between menu and rest of the components - * using TAB - * - * @param ui UI structure pointer - * @param key key code - * @return enum @key_handler_ret - */ -int -column_select_handle_key_menu(Window *ui, int key); - -/** - * @brief Manage pressed keys for column selection panel - * - * This function will handle keys when form is active. - * You can switch between menu and rest of the components - * using TAB - * - * @param ui UI structure pointer - * @param key key code - * @return enum @key_handler_ret - */ -int -column_select_handle_key_form(Window *ui, int key); - -/** - * @brief Update Call List columns - * - * This function will update the columns of Call List - * - * @param ui UI structure pointer - */ -void -column_select_update_columns(Window *ui); - -/** - * @brief Save selected columns to user config file - * - * Remove previously configurated columns from user's - * $SNGREPRC or $HOME/.sngreprc and add new ones - * - * @param ui UI structure pointer - */ -void -column_select_save_columns(Window *ui); - -/** - * @brief Move a item to a new position - * - * This function can be used to reorder the column list - * - * @param ui UI structure pointer - * @param item Menu item to be moved - * @param post New position in the menu - */ -void -column_select_move_item(Window *ui, ITEM *item, int pos); - -/** - * @brief Select/Deselect a menu item - * - * This function can be used to toggle selection status of - * the menu item - * - * @param ui UI structure pointer - * @param item Menu item to be (de)selected - */ -void -column_select_toggle_item(Window *ui, ITEM *item); - -/** - * @brief Update menu after a change - * - * After moving an item or updating its selectioactivn status - * menu must be redrawn. - * - * @param ui UI structure pointer - */ -void -column_select_update_menu(Window *ui); - -#endif /* __UI_COLUMN_SELECT_H */ diff --git a/src/ncurses/ui_filter.c b/src/ncurses/ui_filter.c index ac764ce..4f54032 100644 --- a/src/ncurses/ui_filter.c +++ b/src/ncurses/ui_filter.c @@ -394,7 +394,7 @@ filter_save_options(Window *ui) // Force filter evaluation filter_reset_calls(); // TODO FIXME Refresh call list FIXME - call_list_clear(ui_find_by_type(WINDOW_CALL_LIST)); + call_list_clear(ncurses_find_by_type(WINDOW_CALL_LIST)); } diff --git a/src/ncurses/ui_manager.c b/src/ncurses/ui_manager.c index 4089d9c..328e9e8 100644 --- a/src/ncurses/ui_manager.c +++ b/src/ncurses/ui_manager.c @@ -41,7 +41,7 @@ #include "ncurses/ui_call_raw.h" #include "ncurses/ui_filter.h" #include "ncurses/ui_msg_diff.h" -#include "ncurses/ui_column_select.h" +#include "ncurses/column_select.h" #include "ncurses/ui_save.h" #include "ncurses/ui_settings.h" @@ -58,7 +58,6 @@ static Window *panel_pool[] = { &ui_filter, &ui_save, &ui_msg_diff, - &ui_column_select, &ui_settings, &ui_stats }; @@ -160,7 +159,16 @@ Window * ncurses_create_window(enum WindowTypes type) { // Find the panel of given type and create it - return ui_create(ui_find_by_type(type)); + return ui_create(ncurses_find_by_type(type)); +} + +void +ncurses_destroy_window(Window *window) +{ + // Remove from the window list + g_ptr_array_remove(windows, window); + // Deallocate window memory + ui_destroy(window); } static gboolean @@ -176,7 +184,7 @@ ncurses_window_type_cmp(Window *window, gpointer type) } Window * -ui_find_by_panel(PANEL *panel) +ncurses_find_by_panel(PANEL *panel) { guint index; if (g_ptr_array_find_with_equal_func(windows, panel, @@ -195,7 +203,7 @@ ui_find_by_panel(PANEL *panel) } Window * -ui_find_by_type(enum WindowTypes type) +ncurses_find_by_type(enum WindowTypes type) { int i; @@ -212,6 +220,13 @@ ui_find_by_type(enum WindowTypes type) return window; } + if (type == WINDOW_COLUMN_SELECT) { + Window *window = column_select_new(); + g_ptr_array_add(windows, window); + return window; + } + + // Return ui pointer if found for (i = 0; i < PANEL_COUNT; i++) { if (panel_pool[i]->type == type) @@ -231,7 +246,7 @@ ui_wait_for_input() while ((panel = panel_below(NULL))) { // Get panel interface structure - ui = ui_find_by_panel(panel); + ui = ncurses_find_by_panel(panel); // Set character input timeout 200 ms halfdelay(REFRESHTHSECS); @@ -278,12 +293,15 @@ ui_wait_for_input() continue; } else if (hld == KEY_PROPAGATED) { // Destroy current panel - ui_destroy(ui); + ncurses_destroy_window(ui); // Try to handle this key with the previus panel - ui = ui_find_by_panel(panel_below(NULL)); + ui = ncurses_find_by_panel(panel_below(NULL)); + } else if (hld == KEY_DESTROY) { + ncurses_destroy_window(ui); + break; } else { // Key not handled by UI nor propagated. Use default handler - hld = ui_default_handle_key(ui, c); + hld = ncurses_default_keyhandler(ui, c); } } capture_unlock(capture_manager()); @@ -293,7 +311,7 @@ ui_wait_for_input() } int -ui_default_handle_key(Window *ui, int key) +ncurses_default_keyhandler(Window *window, int key) { int action = -1; @@ -324,10 +342,10 @@ ui_default_handle_key(Window *ui, int key) capture_manager()->paused = !capture_manager()->paused; break; case ACTION_SHOW_HELP: - ui_help(ui); + ui_help(window); break; case ACTION_PREV_SCREEN: - ui_destroy(ui); + ncurses_destroy_window(window); break; default: // Parse next action @@ -349,7 +367,7 @@ ui_resize_panels() // While there are still panels while ((panel = panel_below(panel))) { // Invoke resize for this panel - ui_resize_panel(ui_find_by_panel(panel)); + ui_resize_panel(ncurses_find_by_panel(panel)); } } diff --git a/src/ncurses/ui_manager.h b/src/ncurses/ui_manager.h index 1473741..955a7ac 100644 --- a/src/ncurses/ui_manager.h +++ b/src/ncurses/ui_manager.h @@ -57,7 +57,6 @@ extern Window ui_call_raw; extern Window ui_filter; extern Window ui_save; extern Window ui_msg_diff; -extern Window ui_column_select; extern Window ui_settings; extern Window ui_stats; @@ -98,13 +97,13 @@ ncurses_create_window(enum WindowTypes type); * @brief Find a ui from its pannel pointer */ Window * -ui_find_by_panel(PANEL *panel); +ncurses_find_by_panel(PANEL *panel); /** * @brief Find a ui form its panel id */ Window * -ui_find_by_type(enum WindowTypes type); +ncurses_find_by_type(enum WindowTypes type); /** * @brief Wait for user input in topmost panel @@ -122,11 +121,11 @@ ui_wait_for_input(); * If ui doesn't handle the given key (ui_handle_key returns the key value) * then the default handler will be invoked * - * @param ui Current displayed UI structure + * @param window Current displayed UI structure * @param key key pressed by user */ int -ui_default_handle_key(Window *ui, int key); +ncurses_default_keyhandler(Window *window, int key); /** * @brief Call Resize function in all panels in the stack diff --git a/src/ncurses/ui_panel.h b/src/ncurses/ui_panel.h index 39e21df..67965da 100644 --- a/src/ncurses/ui_panel.h +++ b/src/ncurses/ui_panel.h @@ -43,7 +43,9 @@ enum key_handler_ret { //! Panel has not handled the key, try defualt key handler KEY_NOT_HANDLED = -1, //! Panel destroys and requests previous panel to handle key - KEY_PROPAGATED = -2 + KEY_PROPAGATED = -2, + //! Panel request destroy + KEY_DESTROY = -3 }; /** @@ -65,7 +67,7 @@ enum WindowTypes { //! Message comprare PANEL_MSG_DIFF, //! Column selector panel - PANEL_COLUMN_SELECT, + WINDOW_COLUMN_SELECT, //! Settings panel PANEL_SETTINGS, //! Stats panel