Database: Restore selection in lower menu levels

The database only remembered what you'd selected when
ascending the menu hierarchy again from a lower level.

Now it restores a previous selection going in the other
direction as well, when you enter a new menu, as long
as the selection at the current level hasn't changed.

Change-Id: I5068287ff758a7cfebf1428e9b0ffd30e6ef541e
This commit is contained in:
Christian Soffke 2022-11-11 01:27:15 +01:00
parent e6ab74d4ac
commit c088a9453d
3 changed files with 59 additions and 20 deletions

View file

@ -191,6 +191,7 @@ static int current_entry_count;
static struct tree_context *tc; static struct tree_context *tc;
static int max_history_level; /* depth of menu levels with applicable history */
static int selected_item_history[MAX_DIR_LEVELS]; static int selected_item_history[MAX_DIR_LEVELS];
static int table_history[MAX_DIR_LEVELS]; static int table_history[MAX_DIR_LEVELS];
static int extra_history[MAX_DIR_LEVELS]; static int extra_history[MAX_DIR_LEVELS];
@ -1248,6 +1249,7 @@ static void tagtree_unload(struct tree_context *c)
void tagtree_init(void) void tagtree_init(void)
{ {
max_history_level = 0;
format_count = 0; format_count = 0;
menu_count = 0; menu_count = 0;
menu = NULL; menu = NULL;
@ -1818,7 +1820,16 @@ int tagtree_load(struct tree_context* c)
return count; return count;
} }
int tagtree_enter(struct tree_context* c) /* Enters menu or table for selected item in the database.
*
* Call this with the is_visible parameter set to false to
* prevent selected_item_history from being updated or applied, in
* case the menus aren't displayed to the user.
* Before calling tagtree_enter again with the parameter set to
* true, make sure that you are back at the previous dirlevel, by
* calling tagtree_exit as needed, with is_visible set to false.
*/
int tagtree_enter(struct tree_context* c, bool is_visible)
{ {
int rc = 0; int rc = 0;
struct tagentry *dptr; struct tagentry *dptr;
@ -1826,14 +1837,17 @@ int tagtree_enter(struct tree_context* c)
int newextra; int newextra;
int seek; int seek;
int source; int source;
bool is_random_item = false;
bool adjust_selection = true;
dptr = tagtree_get_entry(c, c->selected_item); dptr = tagtree_get_entry(c, c->selected_item);
c->dirfull = false; c->dirfull = false;
seek = dptr->extraseek; seek = dptr->extraseek;
if (seek == -1) if (seek == -1) /* <Random> menu item was selected */
{ {
if(c->filesindir<=2) is_random_item = true;
if(c->filesindir<=2) /* Menu contains only <All> and <Random> menu items */
return 0; return 0;
srand(current_tick); srand(current_tick);
dptr = (tagtree_get_entry(c, 2+(rand() % (c->filesindir-2)))); dptr = (tagtree_get_entry(c, 2+(rand() % (c->filesindir-2))));
@ -1844,7 +1858,21 @@ int tagtree_enter(struct tree_context* c)
if (c->dirlevel >= MAX_DIR_LEVELS) if (c->dirlevel >= MAX_DIR_LEVELS)
return 0; return 0;
if (is_visible) /* update selection history only for user-selected items */
{
/* We need to discard selected item history for levels
descending from current one if selection has changed */
if (max_history_level < c->dirlevel + 1
|| (max_history_level > c->dirlevel
&& selected_item_history[c->dirlevel] != c->selected_item)
|| is_random_item)
{
max_history_level = c->dirlevel + 1;
selected_item_history[c->dirlevel + 1] = 0;
}
selected_item_history[c->dirlevel]=c->selected_item; selected_item_history[c->dirlevel]=c->selected_item;
}
table_history[c->dirlevel] = c->currtable; table_history[c->dirlevel] = c->currtable;
extra_history[c->dirlevel] = c->currextra; extra_history[c->dirlevel] = c->currextra;
c->dirlevel++; c->dirlevel++;
@ -1853,8 +1881,6 @@ int tagtree_enter(struct tree_context* c)
tree_lock_cache(c); tree_lock_cache(c);
core_pin(tagtree_handle); core_pin(tagtree_handle);
bool reset_selection = true;
switch (c->currtable) { switch (c->currtable) {
case ROOT: case ROOT:
c->currextra = newextra; c->currextra = newextra;
@ -1890,6 +1916,10 @@ int tagtree_enter(struct tree_context* c)
if (source == source_constant) if (source == source_constant)
continue; continue;
/* discard history for lower levels when doing runtime searches */
if (is_visible)
max_history_level = c->dirlevel - 1;
searchstring=csi->clause[i][j]->str; searchstring=csi->clause[i][j]->str;
*searchstring = '\0'; *searchstring = '\0';
@ -1919,7 +1949,7 @@ int tagtree_enter(struct tree_context* c)
rc = kbd_input(searchstring, SEARCHSTR_SIZE, NULL); rc = kbd_input(searchstring, SEARCHSTR_SIZE, NULL);
if (rc < 0 || !searchstring[0]) if (rc < 0 || !searchstring[0])
{ {
tagtree_exit(c); tagtree_exit(c, is_visible);
tree_unlock_cache(c); tree_unlock_cache(c);
core_unpin(tagtree_handle); core_unpin(tagtree_handle);
return 0; return 0;
@ -1940,7 +1970,7 @@ int tagtree_enter(struct tree_context* c)
case ALLSUBENTRIES: case ALLSUBENTRIES:
if (newextra == PLAYTRACK) if (newextra == PLAYTRACK)
{ {
reset_selection = false; adjust_selection = false;
if (global_settings.party_mode && audio_status()) { if (global_settings.party_mode && audio_status()) {
splash(HZ, ID2P(LANG_PARTY_MODE)); splash(HZ, ID2P(LANG_PARTY_MODE));
@ -1973,8 +2003,11 @@ int tagtree_enter(struct tree_context* c)
break; break;
} }
if (reset_selection) if (adjust_selection)
{ {
if (is_visible && c->dirlevel <= max_history_level)
c->selected_item = selected_item_history[c->dirlevel];
else
c->selected_item = 0; c->selected_item = 0;
} }
@ -1984,11 +2017,15 @@ int tagtree_enter(struct tree_context* c)
return rc; return rc;
} }
void tagtree_exit(struct tree_context* c) /* Exits current database menu or table */
void tagtree_exit(struct tree_context* c, bool is_visible)
{ {
if (is_visible) /* update selection history only for user-selected items */
selected_item_history[c->dirlevel] = c->selected_item;
c->dirfull = false; c->dirfull = false;
if (c->dirlevel > 0) if (c->dirlevel > 0)
c->dirlevel--; c->dirlevel--;
if (is_visible)
c->selected_item=selected_item_history[c->dirlevel]; c->selected_item=selected_item_history[c->dirlevel];
c->currtable = table_history[c->dirlevel]; c->currtable = table_history[c->dirlevel];
c->currextra = extra_history[c->dirlevel]; c->currextra = extra_history[c->dirlevel];
@ -2083,6 +2120,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
{ {
char buf[MAX_PATH]; char buf[MAX_PATH];
int dirlevel = tc->dirlevel; int dirlevel = tc->dirlevel;
int selected_item = tc->selected_item;
int newtable; int newtable;
show_search_progress( show_search_progress(
@ -2112,7 +2150,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
if (newtable == NAVIBROWSE) if (newtable == NAVIBROWSE)
{ {
tagtree_enter(tc); tagtree_enter(tc, false);
tagtree_load(tc); tagtree_load(tc);
newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
} }
@ -2125,7 +2163,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
/* Now the current table should be allsubentries. */ /* Now the current table should be allsubentries. */
if (newtable != PLAYTRACK) if (newtable != PLAYTRACK)
{ {
tagtree_enter(tc); tagtree_enter(tc, false);
tagtree_load(tc); tagtree_load(tc);
newtable = tagtree_get_entry(tc, tc->selected_item)->newtable; newtable = tagtree_get_entry(tc, tc->selected_item)->newtable;
@ -2134,7 +2172,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
{ {
logf("newtable: %d !!", newtable); logf("newtable: %d !!", newtable);
while (tc->dirlevel > dirlevel) while (tc->dirlevel > dirlevel)
tagtree_exit(tc); tagtree_exit(tc, false);
tagtree_load(tc); tagtree_load(tc);
return false; return false;
} }
@ -2151,7 +2189,8 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
/* Finally return the dirlevel to its original value. */ /* Finally return the dirlevel to its original value. */
while (tc->dirlevel > dirlevel) while (tc->dirlevel > dirlevel)
tagtree_exit(tc); tagtree_exit(tc, false);
tc->selected_item = selected_item;
tagtree_load(tc); tagtree_load(tc);
return true; return true;

View file

@ -34,8 +34,8 @@
int tagtree_export(void); int tagtree_export(void);
int tagtree_import(void); int tagtree_import(void);
void tagtree_init(void) INIT_ATTR; void tagtree_init(void) INIT_ATTR;
int tagtree_enter(struct tree_context* c); int tagtree_enter(struct tree_context* c, bool is_visible);
void tagtree_exit(struct tree_context* c); void tagtree_exit(struct tree_context* c, bool is_visible);
int tagtree_load(struct tree_context* c); int tagtree_load(struct tree_context* c);
char* tagtree_get_entry_name(struct tree_context *c, int id, char* tagtree_get_entry_name(struct tree_context *c, int id,
char* buf, size_t bufsize); char* buf, size_t bufsize);

View file

@ -683,7 +683,7 @@ static int dirbrowse(void)
} }
} }
#ifdef HAVE_TAGCACHE #ifdef HAVE_TAGCACHE
switch (id3db?tagtree_enter(&tc):ft_enter(&tc)) switch (id3db ? tagtree_enter(&tc, true) : ft_enter(&tc))
#else #else
switch (ft_enter(&tc)) switch (ft_enter(&tc))
#endif #endif
@ -723,7 +723,7 @@ static int dirbrowse(void)
#ifdef HAVE_TAGCACHE #ifdef HAVE_TAGCACHE
if (id3db) if (id3db)
tagtree_exit(&tc); tagtree_exit(&tc, true);
else else
#endif #endif
if (ft_exit(&tc) == 3) if (ft_exit(&tc) == 3)