ocarina/gui/treeview.c

201 lines
4.6 KiB
C

/*
* Copyright 2016 (c) Anna Schumaker.
*/
#include <gui/filter.h>
#include <gui/model.h>
#include <gui/treeview.h>
#include <stdlib.h>
static const enum compare_t GUI_COL_MAP[GUI_MODEL_N_COLUMNS] = {
[GUI_MODEL_TRACK_NR] = COMPARE_TRACK,
[GUI_MODEL_TITLE] = COMPARE_TITLE,
[GUI_MODEL_LENGTH] = COMPARE_LENGTH,
[GUI_MODEL_ARTIST] = COMPARE_ARTIST,
[GUI_MODEL_ALBUM] = COMPARE_ALBUM,
[GUI_MODEL_YEAR] = COMPARE_YEAR,
[GUI_MODEL_GENRE] = COMPARE_GENRE,
[GUI_MODEL_COUNT] = COMPARE_COUNT,
[GUI_MODEL_LAST_PLAY] = COMPARE_PLAYED,
};
static unsigned int sort_count = 0;
static gchar *sort_text = NULL;
static bool can_scroll = true;
static int __gui_treeview_colum_match_sort(enum compare_t compare)
{
struct playlist *playlist = gui_model_get_playlist();
GSList *cur = playlist ? playlist->pl_queue.q_sort : NULL;
while (cur) {
int field = GPOINTER_TO_INT(cur->data);
if (abs(field) == compare)
return field;
cur = g_slist_next(cur);
}
return 0;
}
static void __gui_treeview_set_sort_indicators()
{
GtkTreeViewColumn *col;
unsigned int i, order;
int field;
for (i = 0; i < GUI_MODEL_N_COLUMNS; i++) {
col = gtk_tree_view_get_column(gui_treeview(), i);
if (!col)
continue;
field = __gui_treeview_colum_match_sort(GUI_COL_MAP[i]);
order = (field > 0) ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
gtk_tree_view_column_set_sort_indicator(col, field != 0);
gtk_tree_view_column_set_sort_order(col, order);
}
}
static void __gui_treeview_clear_sorting()
{
sort_count = 0;
if (sort_text) {
g_free(sort_text);
sort_text = NULL;
gtk_label_set_text(gui_sorting(), "");
}
}
static void __gui_treeview_set_sorting(gchar *text)
{
gchar *formatted;
__gui_treeview_clear_sorting();
if (!text)
return;
sort_text = g_strdup(text);
formatted = g_strdup_printf("Sorting: {%s}", text);
gtk_label_set_text(gui_sorting(), formatted);
g_free(formatted);
}
static int __gui_treeview_dec_sort(gpointer data)
{
if (sort_count > 0)
sort_count--;
if (sort_count == 0)
__gui_treeview_clear_sorting();
return FALSE;
}
static gchar *__gui_treeview_sort_text_append(GtkTreeViewColumn *col)
{
const gchar *title = gtk_tree_view_column_get_title(col);
gchar *text, **split;
unsigned int i;
if (!sort_text)
return g_strdup(title);
if (gtk_tree_view_column_get_sort_order(col) == GTK_SORT_ASCENDING)
return g_strdup_printf("%s, %s", sort_text, title);
/* Find the column and prefix it with a minus sign */
split = g_strsplit(sort_text, ", ", 0);
for (i = 0; split[i] != NULL; i++) {
if (g_strcmp0(split[i], title) == 0)
break;
}
g_free(split[i]);
split[i] = g_strdup_printf("-%s", title);
text = g_strjoinv(", ", split);
g_strfreev(split);
return text;
}
static void __gui_treeview_column_clicked(GtkTreeViewColumn *col,
gpointer data)
{
struct playlist *playlist = gui_model_get_playlist();
enum compare_t compare = GPOINTER_TO_UINT(data);
bool reset = (sort_count == 0);
gchar *text;
if (!playlist)
return;
playlist_sort(playlist->pl_type, playlist->pl_name, compare, reset);
if (!playlist->pl_queue.q_sort)
return;
__gui_treeview_set_sort_indicators();
text = __gui_treeview_sort_text_append(col);
__gui_treeview_set_sorting(text);
g_free(text);
sort_count++;
g_timeout_add_seconds(3, __gui_treeview_dec_sort, NULL);
}
void __gui_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path,
GtkTreeViewColumn *col, gpointer data)
{
can_scroll = false;
gui_filter_path_load_track(path);
can_scroll = true;
}
void gui_treeview_init()
{
GtkTreeViewColumn *col;
unsigned int i;
gtk_tree_view_set_model(gui_treeview(),
GTK_TREE_MODEL(gui_filter_get()));
for (i = 0; i < GUI_MODEL_N_COLUMNS; i++) {
col = gtk_tree_view_get_column(gui_treeview(), i);
if (col) {
g_signal_connect(col, "clicked",
G_CALLBACK(__gui_treeview_column_clicked),
GUINT_TO_POINTER(GUI_COL_MAP[i]));
}
}
}
void gui_treeview_deinit()
{
__gui_treeview_clear_sorting();
}
void gui_treeview_set_playlist(struct playlist *playlist)
{
gui_filter_set_playlist(playlist);
__gui_treeview_clear_sorting();
__gui_treeview_set_sort_indicators();
gui_treeview_scroll();
}
void gui_treeview_scroll()
{
struct playlist *playlist = gui_model_get_playlist();
GtkTreePath *path;
int pos;
pos = playlist ? playlist->pl_queue.q_cur.it_pos : -1;
if (!can_scroll || pos < 0)
return;
path = gui_filter_path_from_index(pos);
if (!path)
return;
gtk_tree_view_set_cursor(gui_treeview(), path, NULL, false);
gtk_tree_view_scroll_to_cell(gui_treeview(), path, NULL, true, 0.5, 0.5);
gtk_tree_path_free(path);
}