From dfe12252bba8cbfe427752ad9ed101002a76fe67 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sat, 1 Apr 2023 12:32:47 -0400 Subject: [Feature, Plugin] lastfm_scrobbler_viewer a plugin to view lastfm scrobbler logs uses print cell to give a spreadsheet view of scrobbler logs buffers the whole file if possible otherwise it reads entries from disk rudimentary text searching for columns include / exclude; all/any and case sensitive Change-Id: Id9616e5796658952fba4ea747f596cb77d6f34c0 --- apps/plugins/lib/printcell_helper.c | 297 +++++++++++++++++++++++++++--------- 1 file changed, 222 insertions(+), 75 deletions(-) (limited to 'apps/plugins/lib/printcell_helper.c') diff --git a/apps/plugins/lib/printcell_helper.c b/apps/plugins/lib/printcell_helper.c index 42de444c57..48b8b2c9d2 100644 --- a/apps/plugins/lib/printcell_helper.c +++ b/apps/plugins/lib/printcell_helper.c @@ -22,10 +22,6 @@ #include "plugin.h" #include "lib/printcell_helper.h" -#ifndef PRINTCELL_MAX_COLUMNS -#define PRINTCELL_MAX_COLUMNS 16 -#endif - #define COLUMN_ENDLEN 3 #define TITLE_FLAG 0xFF #define SELECTED_FLAG 0x1 @@ -37,48 +33,54 @@ #endif struct printcell_info_t { - int offw[NB_SCREENS]; - int iconw[NB_SCREENS]; - int selcol_offw[NB_SCREENS]; - int totalcolw[NB_SCREENS]; - int firstcolxw[NB_SCREENS]; - uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS]; - int ncols; - int selcol; - int selcol_index; - char title[PRINTCELL_MAXLINELEN]; - bool separator; + struct gui_synclist *gui_list; /* list to display */ + int offw[NB_SCREENS]; /* padding between column boundries and text */ + int iconw[NB_SCREENS]; /* width of an icon */ + int selcol_offw[NB_SCREENS]; /* offset width calculated for selected item */ + int totalcolw[NB_SCREENS]; /* total width of all columns */ + int firstcolxw[NB_SCREENS]; /* first column x + width, save recalculating */ + int ncols; /* number of columns */ + int selcol; /* selected column (-1 to ncols-1) */ + uint32_t hidecol_flags; /*bits 0-31 set bit to 1 to hide a column (1<= ncols || j >= (PRINTCELL_MAXLINELEN - 1)) + if (i >= ncols || j >= (bufsz - 1)) break; } ch = *dsp_text++; @@ -146,23 +148,39 @@ static inline void set_cell_width(struct viewport *vp, int max_w, int new_w) static inline int printcells(struct screen *display, char* buffer, uint16_t *sidx, struct line_desc *linedes, struct viewport *vp, int vp_w, int separator, - int x, int y, int offw, int selected_flag, bool scroll) + int x, int y, int offw, int selected_flag, int last_col, + bool scroll, bool is_title) { /* Internal function prints remaining cells */ int text_offset = offw + offw; - int ncols = printcell.ncols; int screen = display->screen_type; int height = linedes->height; int selsep = (selected_flag == 0) ? 0: separator; uint16_t *screencolwidth = printcell.colw[screen]; - for(int i = 1; i < ncols; i++) + for(int i = 1; i <= last_col; i++) { int ny = y; int nw = screencolwidth[i] + text_offset; + int offx = 0; + + if (i == last_col || x + nw >= vp_w - offw + 1) + { /* not enough space for next column use up excess */ + if (nw < (vp_w - x)) + { + if (is_title) + offx = ((vp_w - x) - nw) / 2; + nw = vp_w - x; + } + } + + if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i)) + nw = 0; + int nx = x + nw; char *buftext; - if (nx > 0 && x < vp_w) + + if (nx > 0 && nw > offw && x < vp_w) { set_cell_width(vp, vp_w, nx); @@ -173,11 +191,15 @@ static inline int printcells(struct screen *display, char* buffer, } else { + if (vp_w < x + text_offset) + { + scroll = false; + } linedes->scroll = scroll; linedes->separator_height = separator; } buftext = &buffer[sidx[i]]; - display->put_line(x + offw, ny, linedes, "$t", buftext); + display->put_line(x + offw + offx, ny, linedes, "$t", buftext); vp->width += COLUMN_ENDLEN + 1; draw_selector(display, linedes, selected_flag, i, separator, x, ny, nw, height); } @@ -200,6 +222,10 @@ static inline int calcvisible(int screen, int vp_w, int text_offset, int sbwidth for (int i = printcell.selcol - 1; i >= 0; i--) { int cw = screencolwidth[i] + text_offset; + + if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i)) + cw = 0; + if (i == 0) cw += screenicnwidth; if (offset > 0 || cw > maxw) @@ -257,15 +283,30 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info) separator = 1; int nx = x; + int last_col = printcell.ncols - 1; + int hidden_w = 0; int nw, colxw; - + char *buftext; printcell_buffer[0] = '\0'; - parse_dsptext(printcell.ncols, dsp_text, printcell_buffer, sidx); - char *buftext = &printcell_buffer[sidx[0]]; + uint16_t *screencolwidth = printcell.colw[screen]; + if (printcell.hidecol_flags > 0) + { + for (int i = 0; i < printcell.ncols; i++) + { + if (PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i)) + last_col = i; + else + hidden_w += (screencolwidth[i] + text_offset); + } + } if (is_title) { + parse_dsptext(printcell.titlesep, printcell.ncols, dsp_text, + printcell_buffer, sizeof(printcell_buffer), sidx); + + buftext = &printcell_buffer[sidx[0]]; /* set to first column text */ int sbwidth = 0; if (rb->global_settings->scrollbar == SCROLLBAR_LEFT) sbwidth = rb->global_settings->scrollbar_width; @@ -278,6 +319,9 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info) nx -= printcell.selcol_offw[screen]; nw = screencolwidth[0] + printcell.iconw[screen] + text_offset; + + if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, 0)) + nw = printcell.iconw[screen] - 1; nw += sbwidth; colxw = nx + nw; @@ -301,20 +345,21 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info) } else { + parse_dsptext(printcell.colsep, printcell.ncols, dsp_text, + printcell_buffer, sizeof(printcell_buffer), sidx); + + buftext = &printcell_buffer[sidx[0]]; /* set to first column text */ int cursor = Icon_NOICON; nx -= printcell.selcol_offw[screen]; if (selected_flag & SELECTED_FLAG) { - if (printcell.selcol >= 0) - printcell.selcol_index = sidx[printcell.selcol]; /* save the item offset*/ - else - printcell.selcol_index = -1; - cursor = Icon_Cursor; /* limit length of selection if columns don't reach end */ int maxw = nx + printcell.totalcolw[screen] + printcell.iconw[screen]; maxw += text_offset * printcell.ncols; + maxw -= hidden_w; + if (vp_w > maxw) vp->width = maxw; /* display a blank line first to draw selector across all cells */ @@ -364,7 +409,7 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info) nx += nw; /* display remaining cells */ printcells(display, printcell_buffer, sidx, linedes, vp, vp_w, separator, - nx, y, col_offset_width, selected_flag, scroll_items); + nx, y, col_offset_width, selected_flag, last_col, scroll_items, is_title); /* draw a line at the bottom of the list */ if (separator > 0 && line == list->nb_items - 1) @@ -377,14 +422,17 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info) vp->width = vp_w; } -void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator) +void printcell_enable(bool enable) { - printcell.separator = separator; + if (!printcell.gui_list) + return; + struct gui_synclist *gui_list = printcell.gui_list; #ifdef HAVE_LCD_COLOR static int list_sep_color = INT_MIN; if (enable) { - list_sep_color = rb->global_settings->list_separator_color; + if (list_sep_color == INT_MIN) + list_sep_color = rb->global_settings->list_separator_color; rb->global_settings->list_separator_color = rb->global_settings->fg_color; gui_list->callback_draw_item = printcell_listdraw_fn; } @@ -404,8 +452,11 @@ void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator } -int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap) +int printcell_increment_column(int increment, bool wrap) { + if (!printcell.gui_list) + return -1; + struct gui_synclist *gui_list = printcell.gui_list; int item = printcell.selcol + increment; int imin = -1; int imax = printcell.ncols - 1; @@ -425,36 +476,94 @@ int printcell_increment_column(struct gui_synclist *gui_list, int increment, boo FOR_NB_SCREENS(n) /* offset needs recalculated */ printcell.selcol_offw[n] = 0; printcell.selcol = item; - printcell.selcol_index = 0; + rb->gui_synclist_draw(gui_list); + rb->gui_synclist_speak_item(gui_list); } return item; } +int printcell_get_column_selected(void) +{ + if (!printcell.gui_list) + return -1; + return printcell.selcol; +} + +uint32_t printcell_get_column_visibility(int col) +{ + if (col >= 0) + return (PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, col) ? 0:1); + else /* return flag of all columns */ + return printcell.hidecol_flags; +} + +void printcell_set_column_visible(int col, bool visible) +{ + /* visible columns have 0 for the column bit hidden columns have the bit set */ + if (col >= 0) + { + if (visible) + printcell.hidecol_flags &= ~(PRINTCELL_COLUMN_FLAG(col)); + else + printcell.hidecol_flags |= PRINTCELL_COLUMN_FLAG(col); + } + else + { + if (visible) /* set to everything visible */ + printcell.hidecol_flags = 0; + else /* set to everything hidden */ + printcell.hidecol_flags = ((uint32_t)-1); + } +} + int printcell_set_columns(struct gui_synclist *gui_list, - char * title, enum themable_icons icon) + struct printcell_settings * pcs, + char * title, enum themable_icons icon) { + if (title == NULL) title = "$PRINTCELL NOT SETUP"; + + if (pcs == NULL) /* DEFAULTS */ + { +#if LCD_DEPTH > 1 + /* If line sep is set to automatic then outline cells */ + bool sep = (rb->global_settings->list_separator_height < 0); +#else + bool sep = (rb->global_settings->cursor_style == 0); +#endif + pcs = &(struct printcell_settings){ .cell_separator = sep, + .title_delimeter = '$', + .text_delimeter = '$', + .hidecol_flags = 0}; + } + uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /* starting position of column in title string */ int width, height, user_minwidth; int i = 0; - int j = 0; - int ch = '$'; /* first column $ is optional */ - + size_t j = 0; rb->memset(&printcell, 0, sizeof(struct printcell_info_t)); + printcell.gui_list = gui_list; + printcell.separator = pcs->cell_separator; + printcell.titlesep = pcs->title_delimeter; + printcell.colsep = pcs->text_delimeter; + printcell.hidecol_flags = pcs->hidecol_flags; + + int ch = printcell.titlesep; /* first column $ is optional */ + FOR_NB_SCREENS(n) { rb->screens[n]->getstringsize("W", &width, &height); printcell.offw[n] = width; /* set column text offset */ } - if (*title == '$') + if (*title == printcell.titlesep) title++; do { - if (ch == '$') + if (ch == printcell.titlesep) { printcell.title[j++] = ch; user_minwidth = 0; @@ -466,7 +575,7 @@ int printcell_set_columns(struct gui_synclist *gui_list, user_minwidth = 10*user_minwidth + *title - '0'; title++; } - if (*title != '$') /* user forgot $ or wants to display '*' */ + if (*title != printcell.titlesep) /* user forgot titlesep or wants to display '*' */ { title = dspst; user_minwidth = 0; @@ -476,17 +585,25 @@ int printcell_set_columns(struct gui_synclist *gui_list, } sidx[i] = j; - if (*title == '$') /* $$ escaped user must want to display $*/ - printcell.title[j++] = *title++; - while (*title != '\0' && *title != '$' && j < PRINTCELL_MAXLINELEN - 1) + while (*title != '\0' + && *title != printcell.titlesep + && j < PRINTCELL_MAXLINELEN - 1) + { printcell.title[j++] = *title++; + } FOR_NB_SCREENS(n) { - rb->screens[n]->getstringsize(&printcell.title[sidx[i]], &width, &height); + rb->screens[n]->getstringsize(&printcell.title[sidx[i]], + &width, &height); + if (width < user_minwidth) width = user_minwidth; + + if (width > LCD_WIDTH) + width = LCD_WIDTH; + printcell.colw[n][i] = width; printcell.totalcolw[n] += width; } @@ -498,37 +615,67 @@ int printcell_set_columns(struct gui_synclist *gui_list, printcell.ncols = i; printcell.title[j] = '\0'; printcell.selcol = -1; - printcell.selcol_index = 0; rb->gui_synclist_set_title(gui_list, printcell.title, icon); return printcell.ncols; } -char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz) +char *printcell_get_title_text(int selcol, char *buf, size_t bufsz) { - int selected = gui_list->selected_item; - int index = printcell.selcol_index - 1; + /* note offsets are calculated everytime this function is called + * shouldn't be used in hot code paths */ + int index = 0; + buf[0] = '\0'; + if (selcol < 0) /* return entire string incld col formatting '$'*/ + return printcell.title; + + if (selcol < printcell.ncols) + { + uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /*indexes zero terminated strings in buffer*/ + parse_dsptext(printcell.titlesep, selcol + 1, printcell.title, buf, bufsz, sidx); + index = sidx[selcol]; + } + return &buf[index]; +} - if (index < 0) - index = 0; +char *printcell_get_column_text(int selcol, char *buf, size_t bufsz) +{ + int index = 0; char *bpos; + struct gui_synclist *gui_list = printcell.gui_list; - if (gui_list->callback_get_item_name(selected, gui_list->data, buf, bufsz) == buf) + if (gui_list && gui_list->callback_draw_item == printcell_listdraw_fn) { - bpos = &buf[index]; - if (printcell.selcol < 0) /* return entire string incld col formatting '$'*/ - return bpos; - while(bpos < &buf[bufsz - 1]) + int col = selcol; + int item = gui_list->selected_item; + void *data = gui_list->data; + + if (col < printcell.ncols + && gui_list->callback_get_item_name(item, data, buf, bufsz) == buf) { - if (*bpos == '$' || *bpos == '\0') - goto success; - bpos++; + bpos = buf; + if (col < 0) /* return entire string incld col formatting '$'*/ + { + return bpos; + } + bpos++; /* Skip sep/NULL */ + + while(bpos < &buf[bufsz - 1]) + { + if (*bpos == printcell.colsep || *bpos == '\0') + { + if (col-- == 0) + goto success; + index = bpos - buf + 1; /* Skip sep/NULL */ + } + bpos++; + } } } /*failure*/ - bpos = buf; - index = 0; + bpos = buf; + index = 0; success: - *bpos = '\0'; - return &buf[index]; + *bpos = '\0'; + return &buf[index]; } -- cgit v1.2.3