251 lines
6.1 KiB
C
251 lines
6.1 KiB
C
/*
|
|
* Copyright 2016 (c) Anna Schumaker.
|
|
*/
|
|
#include <core/settings.h>
|
|
#include <gui/filter.h>
|
|
#include <gui/model.h>
|
|
#include <gui/treeview.h>
|
|
#include <stdlib.h>
|
|
|
|
struct col_map_entry {
|
|
enum compare_t compare;
|
|
const gchar *setting;
|
|
};
|
|
|
|
static const struct col_map_entry GUI_COL_MAP[GUI_MODEL_N_COLUMNS] = {
|
|
[GUI_MODEL_TRACK_NR] = { COMPARE_TRACK, "gui.queue.track" },
|
|
[GUI_MODEL_TITLE] = { COMPARE_TITLE, "gui.queue.title" },
|
|
[GUI_MODEL_LENGTH] = { COMPARE_LENGTH, "gui.queue.length" },
|
|
[GUI_MODEL_ARTIST] = { COMPARE_ARTIST, "gui.queue.artist" },
|
|
[GUI_MODEL_ALBUM] = { COMPARE_ALBUM, "gui.queue.album" },
|
|
[GUI_MODEL_YEAR] = { COMPARE_YEAR, "gui.queue.year" },
|
|
[GUI_MODEL_GENRE] = { COMPARE_GENRE, "gui.queue.genre" },
|
|
[GUI_MODEL_COUNT] = { COMPARE_COUNT, "gui.queue.count" },
|
|
[GUI_MODEL_LAST_PLAY] = { COMPARE_PLAYED, NULL },
|
|
};
|
|
|
|
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_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].compare);
|
|
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);
|
|
gchar *text;
|
|
|
|
if (!playlist)
|
|
return;
|
|
|
|
if (sort_count == 0)
|
|
playlist_clear_sort(playlist);
|
|
if (!playlist_sort(playlist, compare))
|
|
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_column_resized(GtkTreeViewColumn *col, GParamSpec *pspec,
|
|
gpointer data)
|
|
{
|
|
settings_set(GUI_COL_MAP[GPOINTER_TO_UINT(data)].setting,
|
|
gtk_tree_view_column_get_width(col));
|
|
}
|
|
|
|
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;
|
|
int i, pos;
|
|
|
|
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].compare));
|
|
g_signal_connect(col, "notify::width",
|
|
G_CALLBACK(__gui_treeview_column_resized),
|
|
GUINT_TO_POINTER(i));
|
|
pos = settings_get(GUI_COL_MAP[i].setting);
|
|
if (pos > 0)
|
|
gtk_tree_view_column_set_fixed_width(col, pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
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()
|
|
{
|
|
int pos = playlist_current_index(gui_model_get_playlist());
|
|
GtkTreePath *path;
|
|
|
|
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);
|
|
}
|
|
|
|
void gui_treeview_select_path_at_pos(unsigned int x, unsigned int y)
|
|
{
|
|
GtkTreeSelection *selection;
|
|
GtkTreePath *path;
|
|
|
|
selection = gtk_tree_view_get_selection(gui_treeview());
|
|
if (gtk_tree_view_get_path_at_pos(gui_treeview(), x, y,
|
|
&path, NULL, NULL, NULL))
|
|
{
|
|
gtk_tree_selection_select_path(selection, path);
|
|
gtk_tree_path_free(path);
|
|
}
|
|
}
|
|
|
|
GList *gui_treeview_list_selected_tracks(void)
|
|
{
|
|
GList *rows, *cur, *list = NULL;
|
|
GtkTreeSelection *selection;
|
|
|
|
selection = gtk_tree_view_get_selection(gui_treeview());
|
|
rows = gtk_tree_selection_get_selected_rows(selection, NULL);
|
|
cur = g_list_first(rows);
|
|
|
|
while (cur) {
|
|
list = g_list_append(list, gui_filter_path_get_track(cur->data));
|
|
cur = g_list_next(cur);
|
|
}
|
|
|
|
g_list_free_full(rows, (GDestroyNotify) gtk_tree_path_free);
|
|
gtk_tree_selection_unselect_all(selection);
|
|
return list;
|
|
}
|