Compare commits
13 Commits
Author | SHA1 | Date |
---|---|---|
Anna Schumaker | 45d2422be3 | |
Anna Schumaker | 54138d8814 | |
Anna Schumaker | 6ab3cff28f | |
Anna Schumaker | 0972e027ed | |
Anna Schumaker | 77efa0c631 | |
Anna Schumaker | a9970c455f | |
Anna Schumaker | fc5e6eb043 | |
Anna Schumaker | a41652ab28 | |
Anna Schumaker | eca857cb3b | |
Anna Schumaker | d7fb67ed51 | |
Anna Schumaker | 7df129d533 | |
Anna Schumaker | a4cdac7f22 | |
Anna Schumaker | d5b0752497 |
|
@ -10,8 +10,8 @@ option(CONFIG_TESTING_ARTWORK "Enable album artwork fetching tests" ON)
|
|||
# Configure settings
|
||||
set(CONFIG_MAJOR 6)
|
||||
set(CONFIG_MINOR 5)
|
||||
set(CONFIG_MICRO 9)
|
||||
set(CONFIG_RC OFF)
|
||||
set(CONFIG_MICRO 10)
|
||||
set(CONFIG_RC ON)
|
||||
|
||||
set(CONFIG_VERSION "${CONFIG_MAJOR}.${CONFIG_MINOR}.${CONFIG_MICRO}")
|
||||
|
||||
|
|
|
@ -208,6 +208,20 @@ bool playlist_sort(struct playlist *playlist, enum compare_t sort)
|
|||
return g_slist_length(playlist->pl_sort) > 0;
|
||||
}
|
||||
|
||||
bool playlist_rearrange(struct playlist *playlist, unsigned int old_pos,
|
||||
unsigned int new_pos)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (!playlist || !playlist->pl_ops->pl_rearrange)
|
||||
return false;
|
||||
|
||||
ret = playlist->pl_ops->pl_rearrange(playlist, old_pos, new_pos);
|
||||
if (ret && playlist->pl_type < PL_MAX_TYPE)
|
||||
playlist_types[playlist->pl_type]->pl_save();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void playlist_set_search(struct playlist *playlist, const gchar *text)
|
||||
{
|
||||
gchar **tokens = NULL;
|
||||
|
|
|
@ -11,13 +11,15 @@ static struct playlist_ops pl_artist_ops = {
|
|||
.pl_can_select = playlist_generic_can_select,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
static struct playlist *__artist_pl_alloc(struct artist *artist)
|
||||
{
|
||||
return playlist_generic_alloc(artist->ar_name, PL_ARTIST,
|
||||
artist_index(artist), &pl_artist_ops);
|
||||
artist_index(artist), &pl_artist_ops,
|
||||
3, COMPARE_YEAR, COMPARE_ALBUM, COMPARE_TRACK);
|
||||
}
|
||||
|
||||
static bool __artist_pl_add(void *data)
|
||||
|
|
|
@ -38,26 +38,32 @@ void playlist_generic_set_callbacks(struct playlist_callbacks *cb)
|
|||
callbacks = cb;
|
||||
}
|
||||
|
||||
void playlist_generic_init(struct playlist *playlist)
|
||||
static void __playlist_generic_vinit(struct playlist *playlist,
|
||||
unsigned int nargs, va_list argp)
|
||||
{
|
||||
if (playlist) {
|
||||
g_queue_init(&playlist->pl_tracks);
|
||||
playlist->pl_length = 0;
|
||||
playlist->pl_random = false;
|
||||
playlist->pl_current = NULL;
|
||||
playlist->pl_sort = NULL;
|
||||
playlist->pl_search = NULL;
|
||||
}
|
||||
unsigned int i;
|
||||
|
||||
if (!playlist)
|
||||
return;
|
||||
|
||||
g_queue_init(&playlist->pl_tracks);
|
||||
playlist->pl_length = 0;
|
||||
playlist->pl_random = false;
|
||||
playlist->pl_current = NULL;
|
||||
playlist->pl_sort = NULL;
|
||||
playlist->pl_search = NULL;
|
||||
|
||||
for (i = 0; i < nargs; i++)
|
||||
playlist_generic_sort(playlist, va_arg(argp, unsigned int));
|
||||
}
|
||||
|
||||
void playlist_generic_init_sorted(struct playlist *playlist)
|
||||
void playlist_generic_init(struct playlist *playlist, unsigned int nargs, ...)
|
||||
{
|
||||
if (playlist) {
|
||||
playlist_generic_init(playlist);
|
||||
playlist_generic_sort(playlist, COMPARE_ARTIST);
|
||||
playlist_generic_sort(playlist, COMPARE_YEAR);
|
||||
playlist_generic_sort(playlist, COMPARE_TRACK);
|
||||
}
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, nargs);
|
||||
__playlist_generic_vinit(playlist, nargs, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void playlist_generic_deinit(struct playlist *playlist)
|
||||
|
@ -72,18 +78,23 @@ void playlist_generic_deinit(struct playlist *playlist)
|
|||
}
|
||||
|
||||
struct playlist *playlist_generic_alloc(gchar *name, enum playlist_type_t type,
|
||||
unsigned int id, struct playlist_ops *ops)
|
||||
unsigned int id, struct playlist_ops *ops,
|
||||
unsigned int nargs, ...)
|
||||
{
|
||||
struct playlist *playlist = g_malloc(sizeof(struct playlist));
|
||||
va_list argp;
|
||||
|
||||
playlist->pl_name = name;
|
||||
playlist->pl_type = type;
|
||||
playlist->pl_id = id;
|
||||
playlist->pl_ops = ops;
|
||||
|
||||
playlist_generic_init_sorted(playlist);
|
||||
va_start(argp, nargs);
|
||||
__playlist_generic_vinit(playlist, nargs, argp);
|
||||
if (callbacks)
|
||||
callbacks->pl_cb_alloc(playlist);
|
||||
va_end(argp);
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
||||
|
@ -269,6 +280,22 @@ void playlist_generic_resort(struct playlist *playlist)
|
|||
playlist_generic_update(playlist, NULL);
|
||||
}
|
||||
|
||||
bool playlist_generic_rearrange(struct playlist *playlist, unsigned int old_pos,
|
||||
unsigned int new_pos)
|
||||
{
|
||||
GList *nth;
|
||||
|
||||
if (old_pos == new_pos || old_pos >= playlist_size(playlist) ||
|
||||
new_pos > playlist_size(playlist))
|
||||
return false;
|
||||
|
||||
playlist_clear_sort(playlist);
|
||||
nth = g_queue_pop_nth_link(&playlist->pl_tracks, old_pos);
|
||||
g_queue_push_nth_link(&playlist->pl_tracks, new_pos, nth);
|
||||
playlist_generic_update(playlist, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct track *playlist_generic_next(struct playlist *playlist)
|
||||
{
|
||||
unsigned int pos, size = playlist_size(playlist);
|
||||
|
|
|
@ -22,7 +22,9 @@ static struct playlist_ops pl_library_ops;
|
|||
static struct playlist *__lib_pl_alloc(struct library *library)
|
||||
{
|
||||
return playlist_generic_alloc(library->li_path, PL_LIBRARY,
|
||||
library_index(library), &pl_library_ops);
|
||||
library_index(library), &pl_library_ops,
|
||||
4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||
COMPARE_ALBUM, COMPARE_TRACK);
|
||||
}
|
||||
|
||||
static bool __lib_pl_add(void *data)
|
||||
|
@ -179,6 +181,7 @@ static struct playlist_ops pl_library_ops = {
|
|||
.pl_delete = pl_library_delete,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ static struct playlist_ops favorites_ops = {
|
|||
.pl_remove = playlist_generic_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -132,6 +133,7 @@ static struct playlist_ops hidden_ops = {
|
|||
.pl_remove = sys_pl_hidden_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -183,6 +185,7 @@ static struct playlist_ops queued_ops = {
|
|||
.pl_remove = sys_pl_queued_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -207,6 +210,7 @@ static struct playlist_ops collection_ops = {
|
|||
.pl_remove = sys_pl_hidden_add,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -232,6 +236,7 @@ static struct playlist_ops dynamic_ops = {
|
|||
.pl_can_select = playlist_generic_can_select,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
@ -414,7 +419,7 @@ void pl_system_init(void)
|
|||
switch (i) {
|
||||
case SYS_PL_QUEUED:
|
||||
case SYS_PL_HISTORY:
|
||||
playlist_generic_init(playlist);
|
||||
playlist_generic_init(playlist, 0);
|
||||
break;
|
||||
case SYS_PL_COLLECTION:
|
||||
case SYS_PL_UNPLAYED:
|
||||
|
@ -423,7 +428,8 @@ void pl_system_init(void)
|
|||
sys_pl_update(playlist);
|
||||
case SYS_PL_FAVORITES:
|
||||
case SYS_PL_HIDDEN:
|
||||
playlist_generic_init_sorted(playlist);
|
||||
playlist_generic_init(playlist, 4, COMPARE_ARTIST,
|
||||
COMPARE_YEAR, COMPARE_ALBUM, COMPARE_TRACK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ static struct user_playlist *__user_db_alloc(gchar *name, unsigned int index)
|
|||
playlist->pl_playlist.pl_type = PL_USER;
|
||||
playlist->pl_playlist.pl_id = index;
|
||||
playlist->pl_playlist.pl_ops = &user_ops;
|
||||
playlist_generic_init_sorted(&playlist->pl_playlist);
|
||||
playlist_generic_init(&playlist->pl_playlist, 0);
|
||||
|
||||
return playlist;
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ static struct playlist_ops user_ops = {
|
|||
.pl_remove = playlist_generic_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -134,3 +134,9 @@ GtkTreePath *gui_filter_path_from_index(unsigned int index)
|
|||
gtk_tree_path_free(real);
|
||||
return path;
|
||||
}
|
||||
|
||||
void gui_filter_refilter(struct playlist *playlist)
|
||||
{
|
||||
if (!playlist || playlist == gui_model_get_playlist())
|
||||
gtk_tree_model_filter_refilter(gui_filter_get());
|
||||
}
|
||||
|
|
42
gui/model.c
42
gui/model.c
|
@ -28,6 +28,12 @@ static GType gui_model_columns[GUI_MODEL_N_COLUMNS] = {
|
|||
[GUI_MODEL_FONT] = G_TYPE_STRING,
|
||||
};
|
||||
|
||||
const GtkTargetEntry gui_model_drag_targets[] = {
|
||||
{ GUI_DRAG_DATA, GTK_TARGET_SAME_APP, 0 },
|
||||
};
|
||||
|
||||
const unsigned int gui_model_n_targets = G_N_ELEMENTS(gui_model_drag_targets);
|
||||
|
||||
static GtkTreeModelFlags __gui_model_get_flags(GtkTreeModel *model)
|
||||
{
|
||||
return GTK_TREE_MODEL_LIST_ONLY;
|
||||
|
@ -169,6 +175,27 @@ static gboolean __gui_model_iter_parent(GtkTreeModel *model, GtkTreeIter *iter,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean __gui_model_drag_data_get(GtkTreeDragSource *drag_source,
|
||||
GtkTreePath *path,
|
||||
GtkSelectionData *selection_data)
|
||||
{
|
||||
struct gui_model_drag_data *data = g_malloc(sizeof(*data));
|
||||
|
||||
data->drag_row = gtk_tree_path_get_indices(path)[0];
|
||||
data->drag_track = gui_model_path_get_track(path);
|
||||
|
||||
gtk_selection_data_set(selection_data, gdk_atom_intern(GUI_DRAG_DATA, false),
|
||||
8 /* bytes */, (void *)data, sizeof(*data));
|
||||
g_free(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
static gboolean __gui_model_drag_data_delete(GtkTreeDragSource *drag_source,
|
||||
GtkTreePath *path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __gui_model_init(GuiModel *model)
|
||||
{
|
||||
model->gm_stamp = g_random_int();
|
||||
|
@ -203,6 +230,12 @@ static void __gui_tree_model_init(GtkTreeModelIface *iface)
|
|||
iface->iter_parent = __gui_model_iter_parent;
|
||||
}
|
||||
|
||||
static void __gui_drag_source_init(GtkTreeDragSourceIface *iface)
|
||||
{
|
||||
iface->drag_data_get = __gui_model_drag_data_get;
|
||||
iface->drag_data_delete = __gui_model_drag_data_delete;
|
||||
}
|
||||
|
||||
static const GTypeInfo gui_model_type_info = {
|
||||
.class_size = sizeof(GuiModelClass),
|
||||
.base_init = NULL,
|
||||
|
@ -221,6 +254,12 @@ static const GInterfaceInfo gui_tree_model = {
|
|||
.interface_data = NULL,
|
||||
};
|
||||
|
||||
static const GInterfaceInfo gui_drag_source = {
|
||||
.interface_init = (GInterfaceInitFunc)__gui_drag_source_init,
|
||||
.interface_finalize = NULL,
|
||||
.interface_data = NULL,
|
||||
};
|
||||
|
||||
|
||||
void gui_model_init(void)
|
||||
{
|
||||
|
@ -229,6 +268,9 @@ void gui_model_init(void)
|
|||
(GTypeFlags)0);
|
||||
g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_MODEL,
|
||||
&gui_tree_model);
|
||||
g_type_add_interface_static(gui_model_type, GTK_TYPE_TREE_DRAG_SOURCE,
|
||||
&gui_drag_source);
|
||||
|
||||
|
||||
gui_model = g_object_new(gui_model_type, NULL);
|
||||
g_assert(gui_model != NULL);
|
||||
|
|
|
@ -37,6 +37,7 @@ static void __gui_playlist_alloc(struct playlist *playlist)
|
|||
static void __gui_playlist_added(struct playlist *playlist, struct track *track)
|
||||
{
|
||||
gui_model_add(playlist, track);
|
||||
gui_filter_refilter(playlist);
|
||||
__gui_playlist_update_size(playlist);
|
||||
}
|
||||
|
||||
|
@ -207,6 +208,31 @@ void __gui_playlist_row_expanded(GtkTreeView *treeview, GtkTreeIter *iter,
|
|||
gui_sidebar_filter_row_expanded(iter, true);
|
||||
}
|
||||
|
||||
void __gui_playlist_drag_data_received(GtkTreeView *treeview, GdkDragContext *context,
|
||||
gint x, gint y, GtkSelectionData *data,
|
||||
guint info, guint time, gpointer user_data)
|
||||
{
|
||||
struct playlist *playlist;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gui_sidebar_iter_from_xy(x, y, &iter))
|
||||
playlist = gui_sidebar_iter_playlist(&iter);
|
||||
if (!playlist)
|
||||
playlist = gui_pl_user_add_dialog();
|
||||
if (!playlist)
|
||||
goto out;
|
||||
|
||||
if (playlist == playlist_lookup(PL_SYSTEM, "Collection") &&
|
||||
gui_model_get_playlist() == playlist_lookup(PL_SYSTEM, "Hidden"))
|
||||
__gui_playlist_delete(NULL, NULL);
|
||||
else if (playlist != playlist_lookup(PL_SYSTEM, "History"))
|
||||
__gui_playlist_add_selected_to(playlist);
|
||||
|
||||
out:
|
||||
g_signal_stop_emission_by_name(treeview, "drag_data_received");
|
||||
gtk_drag_finish(context, true, true, time);
|
||||
}
|
||||
|
||||
bool __gui_playlist_init_idle()
|
||||
{
|
||||
struct playlist *playlist = playlist_current();
|
||||
|
|
|
@ -256,6 +256,10 @@ void gui_sidebar_init()
|
|||
GtkTreeSelection *selection;
|
||||
GtkTreeIter iter;
|
||||
|
||||
gtk_tree_view_enable_model_drag_dest(gui_sidebar_treeview(),
|
||||
gui_model_drag_targets, gui_model_n_targets,
|
||||
GDK_ACTION_MOVE);
|
||||
|
||||
if (!gui_sidebar_iter_first(&iter)) {
|
||||
__gui_sidebar_add_header(&iter, "Playlists", "emblem-documents");
|
||||
__gui_sidebar_add_header(&iter, "Dynamic", "emblem-generic");
|
||||
|
@ -486,3 +490,19 @@ gboolean gui_sidebar_iter_from_string(const gchar *path, GtkTreeIter *child)
|
|||
__gui_sidebar_filter_iter_convert(&iter, child);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean gui_sidebar_iter_from_xy(gint x, gint y, GtkTreeIter *child)
|
||||
{
|
||||
GtkTreeModel *model = GTK_TREE_MODEL(gui_sidebar_filter());
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!gtk_tree_view_get_path_at_pos(gui_sidebar_treeview(), x, y,
|
||||
&path, NULL, NULL, NULL))
|
||||
return false;
|
||||
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
__gui_sidebar_filter_iter_convert(&iter, child);
|
||||
gtk_tree_path_free(path);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,43 @@ void __gui_treeview_row_activated(GtkTreeView *treeview, GtkTreePath *path,
|
|||
can_scroll = true;
|
||||
}
|
||||
|
||||
void __gui_treeview_drag_data_received(GtkTreeView *treeview, GdkDragContext *context,
|
||||
gint x, gint y, GtkSelectionData *data,
|
||||
guint info, guint time, gpointer user_data)
|
||||
{
|
||||
struct gui_model_drag_data *drag_data;
|
||||
unsigned int to, from;
|
||||
GtkTreePath *path;
|
||||
|
||||
drag_data = (void *)gtk_selection_data_get_data(data);
|
||||
if (gtk_tree_view_get_path_at_pos(gui_treeview(), x, y,
|
||||
&path, NULL, NULL, NULL))
|
||||
gtk_tree_path_prev(path);
|
||||
else if (!gtk_tree_view_get_visible_range(gui_treeview(), NULL, &path))
|
||||
return;
|
||||
|
||||
from = drag_data->drag_row;
|
||||
to = gui_filter_path_get_index(path);
|
||||
|
||||
if (playlist_rearrange(gui_model_get_playlist(), from, to)) {
|
||||
gtk_tree_selection_unselect_all(gui_treeview_selection());
|
||||
gtk_tree_selection_select_path(gui_treeview_selection(), path);
|
||||
__gui_treeview_set_sort_indicators();
|
||||
}
|
||||
|
||||
g_signal_stop_emission_by_name(treeview, "drag_data_received");
|
||||
gtk_drag_finish(context, true, true, time);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
bool __gui_treeview_drag_drop(GtkTreeView *treeview, GdkDragContext *context,
|
||||
gint x, gint y, guint time, gpointer user_data)
|
||||
{
|
||||
gtk_drag_get_data(GTK_WIDGET(treeview), context,
|
||||
gdk_atom_intern(GUI_DRAG_DATA, false), time);
|
||||
return true;
|
||||
}
|
||||
|
||||
void gui_treeview_init()
|
||||
{
|
||||
GtkTreeViewColumn *col;
|
||||
|
@ -167,6 +204,12 @@ void gui_treeview_init()
|
|||
|
||||
gtk_tree_view_set_model(gui_treeview(),
|
||||
GTK_TREE_MODEL(gui_filter_get()));
|
||||
gtk_tree_view_enable_model_drag_source(gui_treeview(), GDK_BUTTON1_MASK,
|
||||
gui_model_drag_targets, gui_model_n_targets,
|
||||
GDK_ACTION_MOVE);
|
||||
gtk_tree_view_enable_model_drag_dest(gui_treeview(),
|
||||
gui_model_drag_targets, gui_model_n_targets,
|
||||
GDK_ACTION_MOVE);
|
||||
|
||||
for (i = 0; i < GUI_MODEL_N_COLUMNS; i++) {
|
||||
col = gtk_tree_view_get_column(gui_treeview(), i);
|
||||
|
@ -218,26 +261,22 @@ void gui_treeview_scroll()
|
|||
|
||||
void gui_treeview_select_path_at_pos(unsigned int x, unsigned int y)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreePath *path;
|
||||
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_selection_select_path(gui_treeview_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);
|
||||
GtkTreeSelection *selection = gui_treeview_selection();
|
||||
GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
|
||||
GList *cur = g_list_first(rows);
|
||||
GList *list = NULL;
|
||||
|
||||
while (cur) {
|
||||
list = g_list_append(list, gui_filter_path_get_track(cur->data));
|
||||
|
|
|
@ -71,6 +71,9 @@ void playlist_set_random(struct playlist *, bool);
|
|||
/* Called to change the sort order of the playlist. */
|
||||
bool playlist_sort(struct playlist *, enum compare_t);
|
||||
|
||||
/* Called to manually rearrange the order of the playlist. */
|
||||
bool playlist_rearrange(struct playlist *, unsigned int, unsigned int);
|
||||
|
||||
|
||||
/* Called to set the playlist's search text */
|
||||
void playlist_set_search(struct playlist *, const gchar *);
|
||||
|
|
|
@ -40,15 +40,15 @@ struct playlist_callbacks {
|
|||
void playlist_generic_set_callbacks(struct playlist_callbacks *);
|
||||
|
||||
/* Generic playlist init functions. */
|
||||
void playlist_generic_init(struct playlist *);
|
||||
void playlist_generic_init_sorted(struct playlist *);
|
||||
void playlist_generic_init(struct playlist *, unsigned int, ...);
|
||||
|
||||
/* Generic playlist deinit function. */
|
||||
void playlist_generic_deinit(struct playlist *);
|
||||
|
||||
/* Generic playlist alloc function. */
|
||||
struct playlist *playlist_generic_alloc(gchar *, enum playlist_type_t,
|
||||
unsigned int, struct playlist_ops *);
|
||||
unsigned int, struct playlist_ops *,
|
||||
unsigned int, ...);
|
||||
|
||||
/* Generic playlist free function. */
|
||||
void playlist_generic_free(struct playlist *);
|
||||
|
@ -82,6 +82,9 @@ void playlist_generic_set_random(struct playlist *, bool);
|
|||
void playlist_generic_sort(struct playlist *, enum compare_t);
|
||||
void playlist_generic_resort(struct playlist *);
|
||||
|
||||
/* Generic playlist rearranging operation. */
|
||||
bool playlist_generic_rearrange(struct playlist *, unsigned int, unsigned int);
|
||||
|
||||
/* Generic playlist next track operation. */
|
||||
struct track *playlist_generic_next(struct playlist *);
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ struct playlist_ops {
|
|||
|
||||
/* Called to sort the playlist. */
|
||||
void (*pl_sort)(struct playlist *, enum compare_t);
|
||||
|
||||
/* Called to rearrange the playlist. */
|
||||
bool (*pl_rearrange)(struct playlist *, unsigned int, unsigned int);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ unsigned int gui_filter_path_get_index(GtkTreePath *);
|
|||
/* Called to convert a playlist iterator index into a path. */
|
||||
GtkTreePath *gui_filter_path_from_index(unsigned int);
|
||||
|
||||
/* Called to refilter a playlist. Pass NULL to refilter the current playlist */
|
||||
void gui_filter_refilter(struct playlist *);
|
||||
|
||||
/* Called to access the filter search-entry. */
|
||||
static inline GtkSearchEntry *gui_filter_search(void)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,15 @@ struct gui_model_class {
|
|||
};
|
||||
typedef struct gui_model_class GuiModelClass;
|
||||
|
||||
struct gui_model_drag_data {
|
||||
unsigned int drag_row;
|
||||
struct track *drag_track;
|
||||
};
|
||||
|
||||
#define GUI_DRAG_DATA "GUI_DRAG_DATA"
|
||||
|
||||
extern const GtkTargetEntry gui_model_drag_targets[];
|
||||
extern const unsigned int gui_model_n_targets;
|
||||
|
||||
/* Called to initialize the GuiModel */
|
||||
void gui_model_init(void);
|
||||
|
|
|
@ -76,6 +76,9 @@ gboolean gui_sidebar_iter_find(GtkTreeIter *, const gchar *,
|
|||
/* Called to set the a GtkTreeIter to the row at path string */
|
||||
gboolean gui_sidebar_iter_from_string(const gchar *, GtkTreeIter *);
|
||||
|
||||
/* Called to set the GtkTreeIter to the row at (x, y) */
|
||||
gboolean gui_sidebar_iter_from_xy(gint, gint, GtkTreeIter *);
|
||||
|
||||
/* Called to get the sidebar widget. */
|
||||
static inline GtkPaned *gui_sidebar()
|
||||
{
|
||||
|
|
|
@ -32,6 +32,12 @@ static inline GtkTreeView *gui_treeview()
|
|||
return GTK_TREE_VIEW(gui_builder_widget("treeview"));
|
||||
}
|
||||
|
||||
/* Called to access the treview selection. */
|
||||
static inline GtkTreeSelection *gui_treeview_selection()
|
||||
{
|
||||
return gtk_tree_view_get_selection(gui_treeview());
|
||||
}
|
||||
|
||||
/* Called to access the sorting display widget. */
|
||||
static inline GtkLabel *gui_sorting()
|
||||
{
|
||||
|
|
|
@ -768,6 +768,8 @@ audio-volume-medium</property>
|
|||
<property name="search_column">1</property>
|
||||
<property name="enable_tree_lines">True</property>
|
||||
<signal name="button-press-event" handler="__gui_sidebar_button_press" swapped="no"/>
|
||||
<signal name="drag-data-received" handler="__gui_playlist_drag_data_received" swapped="no"/>
|
||||
<signal name="drag-drop" handler="__gui_treeview_drag_drop" swapped="no"/>
|
||||
<signal name="key-press-event" handler="__gui_sidebar_keypress" swapped="no"/>
|
||||
<signal name="row-activated" handler="__gui_playlist_row_activated" swapped="no"/>
|
||||
<signal name="row-collapsed" handler="__gui_playlist_row_collapsed" swapped="no"/>
|
||||
|
@ -912,6 +914,8 @@ audio-volume-medium</property>
|
|||
<property name="rubber_banding">True</property>
|
||||
<property name="tooltip_column">9</property>
|
||||
<signal name="button-press-event" handler="__gui_playlist_button_press" swapped="no"/>
|
||||
<signal name="drag-data-received" handler="__gui_treeview_drag_data_received" swapped="no"/>
|
||||
<signal name="drag-drop" handler="__gui_treeview_drag_drop" swapped="no"/>
|
||||
<signal name="key-press-event" handler="__gui_playlist_keypress" swapped="no"/>
|
||||
<signal name="row-activated" handler="__gui_treeview_row_activated" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
|
|
|
@ -34,6 +34,7 @@ static struct playlist_ops test_ops = {
|
|||
.pl_remove = playlist_generic_remove,
|
||||
.pl_set_random = playlist_generic_set_random,
|
||||
.pl_sort = playlist_generic_sort,
|
||||
.pl_rearrange = playlist_generic_rearrange,
|
||||
};
|
||||
static struct playlist_callbacks test_cb = {
|
||||
.pl_cb_alloc = test_pl_alloc,
|
||||
|
@ -49,8 +50,7 @@ static void test_null()
|
|||
g_assert_false(playlist_delete(NULL));
|
||||
playlist_generic_free(NULL);
|
||||
|
||||
playlist_generic_init(NULL);
|
||||
playlist_generic_init_sorted(NULL);
|
||||
playlist_generic_init(NULL, 0);
|
||||
playlist_generic_deinit(NULL);
|
||||
|
||||
g_assert_null(playlist_lookup(PL_MAX_TYPE, "NULL"));
|
||||
|
@ -77,6 +77,7 @@ static void test_null()
|
|||
g_assert_false(playlist_sort(NULL, COMPARE_TRACK));
|
||||
playlist_generic_resort(NULL);
|
||||
playlist_clear_sort(NULL);
|
||||
g_assert_false(playlist_rearrange(NULL, 0, 0));
|
||||
|
||||
playlist_set_search(NULL, NULL);
|
||||
|
||||
|
@ -110,9 +111,10 @@ static void test_playlist()
|
|||
int i;
|
||||
|
||||
g_assert_cmpuint(playlist_size(&p), ==, 0);
|
||||
playlist_generic_init(&p);
|
||||
playlist_generic_init(&p, 0);
|
||||
g_assert_cmpuint(playlist_size(&p), ==, 0);
|
||||
g_assert_cmpuint(p.pl_length, ==, 0);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||
|
||||
for (i = 0; i < 13; i++) {
|
||||
ex_length += track_get(i)->tr_length;
|
||||
|
@ -202,8 +204,9 @@ static void test_sorting()
|
|||
struct track *track;
|
||||
unsigned int i;
|
||||
|
||||
playlist_generic_init_sorted(&p);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 3);
|
||||
playlist_generic_init(&p, 4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||
COMPARE_ALBUM, COMPARE_TRACK);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||
playlist_clear_sort(&p);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||
|
||||
|
@ -279,6 +282,43 @@ static void test_sorting()
|
|||
g_assert_null(p.pl_sort);
|
||||
}
|
||||
|
||||
static void test_rearranging()
|
||||
{
|
||||
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
||||
struct track *track;
|
||||
unsigned int i;
|
||||
|
||||
playlist_generic_init(&p, 4, COMPARE_ARTIST, COMPARE_YEAR,
|
||||
COMPARE_ALBUM, COMPARE_TRACK);
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||
|
||||
for (i = 0; i < 13; i++)
|
||||
playlist_add(&p, track_get(i));
|
||||
|
||||
g_assert_false(playlist_rearrange(&p, 42, 4));
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||
g_assert_false(playlist_rearrange(&p, 4, 42));
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||
g_assert_false(playlist_rearrange(&p, 4, 4));
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 4);
|
||||
g_assert_true(playlist_rearrange(&p, 12, 0));
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||
g_assert_true(playlist_rearrange(&p, 1, 12));
|
||||
g_assert_cmpuint(g_slist_length(p.pl_sort), ==, 0);
|
||||
|
||||
for (i = 0; i < 13; i++) {
|
||||
track = playlist_at(&p, i);
|
||||
if (i == 0)
|
||||
g_assert_cmpuint(track->tr_track, ==, 13);
|
||||
else if (i == 12)
|
||||
g_assert_cmpuint(track->tr_track, ==, 1);
|
||||
else
|
||||
g_assert_cmpuint(track->tr_track, ==, i + 1);
|
||||
}
|
||||
|
||||
playlist_generic_deinit(&p);
|
||||
}
|
||||
|
||||
static void test_next()
|
||||
{
|
||||
struct playlist p = DEFINE_PLAYLIST(PL_MAX_TYPE, "Test", 0, &test_ops);
|
||||
|
@ -286,7 +326,7 @@ static void test_next()
|
|||
unsigned int i;
|
||||
|
||||
g_random_set_seed(0);
|
||||
playlist_generic_init(&p);
|
||||
playlist_generic_init(&p, 0);
|
||||
|
||||
for (i = 0; i < 13; i++)
|
||||
playlist_generic_add(&p, track_get(i));
|
||||
|
@ -403,6 +443,7 @@ int main(int argc, char **argv)
|
|||
g_test_add_func("/Core/Playlist/NULL", test_null);
|
||||
g_test_add_func("/Core/Playlists/General", test_playlist);
|
||||
g_test_add_func("/Core/Playlists/Sorting", test_sorting);
|
||||
g_test_add_func("/Core/Playlists/Rearranging", test_rearranging);
|
||||
g_test_add_func("/Core/Playlists/Next Track", test_next);
|
||||
g_test_add_func("/Core/Playlist/Save and Load", test_save_load);
|
||||
ret = g_test_run();
|
||||
|
|
|
@ -75,8 +75,8 @@ void test_library()
|
|||
playlist_set_random(playlist, false);
|
||||
g_assert_false(playlist->pl_random);
|
||||
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 3);
|
||||
playlist_clear_sort(playlist);
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 4);
|
||||
g_assert_true(playlist_rearrange(playlist, 15, 20));
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
||||
g_assert_true(playlist_sort(playlist, COMPARE_ARTIST));
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 1);
|
||||
|
|
|
@ -44,7 +44,7 @@ static void test_init()
|
|||
if (i == SYS_PL_QUEUED || i == SYS_PL_HISTORY) {
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 0);
|
||||
} else
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 3);
|
||||
g_assert_cmpuint(g_slist_length(playlist->pl_sort), ==, 4);
|
||||
}
|
||||
|
||||
/* Add tracks to the collection. */
|
||||
|
|
|
@ -65,7 +65,7 @@ void test_treeview_select()
|
|||
GList *list;
|
||||
unsigned int i;
|
||||
|
||||
selection = gtk_tree_view_get_selection(gui_treeview());
|
||||
selection = gui_treeview_selection();
|
||||
|
||||
gui_treeview_set_playlist(playlist_lookup(PL_SYSTEM, "Collection"));
|
||||
g_assert(gui_model_get_playlist() ==
|
||||
|
@ -112,6 +112,7 @@ void test_treeview_sort()
|
|||
break;
|
||||
case GUI_MODEL_ARTIST:
|
||||
case GUI_MODEL_YEAR:
|
||||
case GUI_MODEL_ALBUM:
|
||||
case GUI_MODEL_TRACK_NR:
|
||||
g_assert_true(
|
||||
gtk_tree_view_column_get_sort_indicator(col));
|
||||
|
|
Loading…
Reference in New Issue