commit 8429fa4b49ea6ce1a232dbb81f46d05ac5b3b4fd Author: phantomjinx <p.g.richard...@phantomjinx.co.uk> Date: Mon Oct 3 20:57:57 2011 +0100
Allow the multiple selection of playlists in the playlist view * Only the first selection is passed to libgtkpod and notified to other plugins. * On selection of extra playlists, a reduced context menu can be displayed, allowing for actions to be performed on the set of playlists, notably deletion. Fixes:3413192 - Not obvious how to delete a playlist without selecting from libgtkpod/context_menus.c | 24 --- libgtkpod/context_menus.h | 1 - plugins/playlist_display/display_playlists.c | 211 ++++++++++---------- plugins/playlist_display/display_playlists.h | 12 +- .../playlist_display/playlist_display_actions.c | 68 ++++--- .../playlist_display/playlist_display_actions.h | 14 +- .../playlist_display_context_menu.c | 134 ++++++++++--- plugins/playlist_display/plugin.c | 12 +- 8 files changed, 276 insertions(+), 200 deletions(-) --- diff --git a/libgtkpod/context_menus.c b/libgtkpod/context_menus.c index c781d44..1a56c90 100644 --- a/libgtkpod/context_menus.c +++ b/libgtkpod/context_menus.c @@ -110,11 +110,6 @@ GtkWidget *add_separator(GtkWidget *menu) { return sep; } -void context_menu_delete_track_head(GtkMenuItem *mi, gpointer data) { - DeleteAction deleteaction = GPOINTER_TO_INT (data); - delete_track_head(deleteaction); -} - GtkWidget *add_exec_commands(GtkWidget *menu) { GList *trkcmds = gtkpod_get_registered_track_commands(); GList *cmds = trkcmds; @@ -156,25 +151,6 @@ GtkWidget *add_update_tracks_from_file(GtkWidget *menu) { return hookup_menu_item(menu, _("Update Tracks from File"), GTK_STOCK_REFRESH, G_CALLBACK (update_tracks_from_file), NULL); } -/* - * sync_dirs_ entries - sync the directories of the selected playlist - * - * @mi - the menu item selected - * @data - Ignored, should be NULL - */ -static void sync_dirs(GtkMenuItem *mi, gpointer data) { - if (gtkpod_get_current_playlist()) { - sync_playlist(gtkpod_get_current_playlist(), NULL, KEY_SYNC_CONFIRM_DIRS, 0, KEY_SYNC_DELETE_TRACKS, 0, KEY_SYNC_CONFIRM_DELETE, 0, KEY_SYNC_SHOW_SUMMARY, 0); - } - else { - g_return_if_reached (); - } -} - -GtkWidget *add_sync_playlist_with_dirs(GtkWidget *menu) { - return hookup_menu_item(menu, _("Sync Playlist with Dir(s)"), GTK_STOCK_REFRESH, G_CALLBACK (sync_dirs), NULL); -} - static void copy_selected_tracks_to_target_itdb(GtkMenuItem *mi, gpointer *userdata) { iTunesDB *t_itdb = *userdata; g_return_if_fail (t_itdb); diff --git a/libgtkpod/context_menus.h b/libgtkpod/context_menus.h index 8024010..05a2de6 100644 --- a/libgtkpod/context_menus.h +++ b/libgtkpod/context_menus.h @@ -54,7 +54,6 @@ void context_menu_delete_track_head(GtkMenuItem *mi, gpointer data); GtkWidget *add_copy_track_to_filesystem (GtkWidget *menu); GtkWidget *add_create_playlist_file (GtkWidget *menu); GtkWidget *add_update_tracks_from_file (GtkWidget *menu); -GtkWidget *add_sync_playlist_with_dirs (GtkWidget *menu); GtkWidget *add_create_new_playlist (GtkWidget *menu); GtkWidget *add_edit_track_details (GtkWidget *menu); diff --git a/plugins/playlist_display/display_playlists.c b/plugins/playlist_display/display_playlists.c index 951b9da..208ad91 100644 --- a/plugins/playlist_display/display_playlists.c +++ b/plugins/playlist_display/display_playlists.c @@ -231,7 +231,7 @@ static gboolean pm_drag_motion(GtkWidget *widget, GdkDragContext *dc, gint x, gi return TRUE; case DND_GTKPOD_TRACKLIST: /* do not allow drop into currently selected playlist */ - if (pl_d == pm_get_selected_playlist()) { + if (pl_d == pm_get_first_selected_playlist()) { if ((pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE) || (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)) { gtk_tree_path_free(path); gdk_drag_status(dc, 0, time); @@ -1015,55 +1015,20 @@ void pm_add_child(Itdb_iTunesDB *itdb, PM_column_type type, gpointer item, gint gtk_tree_store_set(GTK_TREE_STORE (model), &iter, PM_COLUMN_ITDB, itdb, PM_COLUMN_TYPE, type, type, item, -1); } -/* Remove "playlist" from the display model. - "select": TRUE: a new playlist is selected - FALSE: no selection is taking place - (useful when quitting program) */ -void pm_remove_playlist(Playlist *playlist, gboolean select) { +/* Remove "playlist" from the display model */ +void pm_remove_playlist(Playlist *playlist) { GtkTreeModel *model; - gboolean have_iter = FALSE; - GtkTreeIter select_iter, delete_iter; - GtkTreeSelection *ts = NULL; + GtkTreeIter iter; g_return_if_fail (playlist); model = gtk_tree_view_get_model(playlist_treeview); g_return_if_fail (model); - ts = gtk_tree_view_get_selection(playlist_treeview); - - if (itdb_playlist_is_mpl(playlist) && (playlist->itdb == gtkpod_get_current_itdb())) { - /* We are about to remove the entire itdb (playlist is MPL) and - * a playlist of this itdb is selected --> clear display - * (pm_unselect_playlist probably works as well, but the - * unselect won't be done until later (callback)) */ - gtkpod_set_current_playlist(NULL); - } - - if (select && (gtkpod_get_current_playlist() == playlist)) { - /* We are about to delete the currently selected - * playlist. Try to select the next. */ - if (gtk_tree_selection_get_selected(ts, NULL, &select_iter)) { - GtkTreePath *path = gtk_tree_model_get_path(model, &select_iter); - if (gtk_tree_model_iter_next(model, &select_iter)) { - have_iter = TRUE; - } - else { /* no next iter -- try previous iter */ - if (gtk_tree_path_prev(path)) { /* OK -- make iter from it */ - gtk_tree_model_get_iter(model, &select_iter, path); - have_iter = TRUE; - } - } - gtk_tree_path_free(path); - } - } + gtkpod_set_current_playlist(NULL); - if (pm_get_iter_for_playlist(playlist, &delete_iter)) { - gtk_tree_store_remove(GTK_TREE_STORE (model), &delete_iter); + if (pm_get_iter_for_playlist(playlist, &iter)) { + gtk_tree_store_remove(GTK_TREE_STORE (model), &iter); } - - /* select our new iter !!! */ - if (have_iter && select) - gtk_tree_selection_select_iter(ts, &select_iter); } /* Remove all playlists from the display model */ @@ -1091,6 +1056,35 @@ void pm_remove_all_playlists(gboolean clear_sort) { } /* Select specified playlist */ +void pm_select_playlists(GList *playlists) { + GtkTreeIter iter; + GtkTreeSelection *ts; + + g_return_if_fail (playlist_treeview); + + if (!playlists) { + ts = gtk_tree_view_get_selection(playlist_treeview); + gtk_tree_selection_unselect_all(ts); + return; + } + + ts = gtk_tree_view_get_selection(playlist_treeview); + + for (gint i = 0; i < g_list_length(playlists); ++i) { + Playlist *pl = g_list_nth_data(playlists, i); + + if (pm_get_iter_for_playlist(pl, &iter)) { + gtk_tree_selection_select_iter(ts, &iter); + } + + /* Only properly select the first in the list */ + if (i == 0 && gtkpod_get_current_playlist() != pl) { + gtkpod_set_current_playlist(pl); + } + } +} + +/* Select specified playlist */ void pm_select_playlist(Playlist *playlist) { GtkTreeIter iter; GtkTreeSelection *ts; @@ -1128,10 +1122,13 @@ void pm_unselect_playlist(Playlist *playlist) { } static gboolean pm_selection_changed_cb(gpointer data) { - GtkTreeModel *model; GtkTreeIter iter; GtkTreeView *tree_view = GTK_TREE_VIEW (data); - GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); + + g_return_val_if_fail(tree_view, FALSE); + + GtkTreeModel *model = gtk_tree_view_get_model(tree_view); + g_return_val_if_fail(model, FALSE); #if DEBUG_TIMING GTimeVal time; @@ -1140,16 +1137,20 @@ static gboolean pm_selection_changed_cb(gpointer data) { time.tv_sec % 3600, time.tv_usec); #endif - if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE) { /* no selection -> reset sort tabs */ - // gphoto_change_to_photo_window (FALSE); + if (! pm_is_playlist_selected()) { + /* no selection */ gtkpod_set_current_playlist(NULL); } else { - Playlist *new_playlist = NULL; + Playlist *new_playlist = pm_get_first_selected_playlist(); + g_return_val_if_fail(new_playlist, FALSE); + Itdb_iTunesDB *itdb = NULL; Itdb_PhotoDB *photodb = NULL; PM_column_type type = 0; + /* handle new selection */ + pm_get_iter_for_playlist(new_playlist, &iter); gtk_tree_model_get(model, &iter, PM_COLUMN_TYPE, &type, PM_COLUMN_ITDB, &itdb, PM_COLUMN_PLAYLIST, &new_playlist, PM_COLUMN_PHOTOS, &photodb, -1); gtkpod_set_current_playlist(new_playlist); @@ -1159,8 +1160,6 @@ static gboolean pm_selection_changed_cb(gpointer data) { g_return_val_if_fail (new_playlist, FALSE); g_return_val_if_fail (itdb, FALSE); - // gphoto_change_to_photo_window (FALSE); - if (new_playlist->is_spl && new_playlist->splpref.liveupdate) itdb_spl_update(new_playlist); @@ -1169,7 +1168,6 @@ static gboolean pm_selection_changed_cb(gpointer data) { case PM_COLUMN_PHOTOS: g_return_val_if_fail (photodb, FALSE); g_return_val_if_fail (itdb, FALSE); - // gphoto_display_photo_window (itdb); break; case PM_COLUMN_ITDB: case PM_COLUMN_TYPE: @@ -1361,16 +1359,16 @@ static gint pm_get_position_for_playlist(Playlist *playlist) { /* "unsort" the playlist view without causing the sort tabs to be touched. */ static void pm_unsort() { - Playlist *cur_pl; + GList *cur_pls; pm_selection_blocked = TRUE; /* remember */ - cur_pl = pm_get_selected_playlist(); + cur_pls = pm_get_selected_playlists(); pm_remove_all_playlists(TRUE); - pm_set_selected_playlist(cur_pl); + pm_select_playlists(cur_pls); pm_selection_blocked = FALSE; /* reset sort counter */ @@ -1904,11 +1902,12 @@ static void pm_create_treeview(void) { model = gtk_tree_store_new(PM_NUM_COLUMNS, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_POINTER, G_TYPE_POINTER); /* set tree model */ gtk_tree_view_set_model(playlist_treeview, GTK_TREE_MODEL (model)); - /* gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (playlist_treeview), TRUE); */ - gtk_tree_selection_set_mode(gtk_tree_view_get_selection(playlist_treeview), GTK_SELECTION_SINGLE); + + /* set selection mode */ selection = gtk_tree_view_get_selection(playlist_treeview); - g_signal_connect (G_OBJECT (selection), "changed", - G_CALLBACK (pm_selection_changed), NULL); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (pm_selection_changed), NULL); + pm_add_columns(); pm_add_all_itdbs(); @@ -2005,51 +2004,63 @@ GtkWidget *pm_create_playlist_view(GtkActionGroup *action_group) { return GTK_WIDGET(vbox); } -Playlist* pm_get_selected_playlist(void) { - GtkTreeSelection *ts; - GtkTreeIter iter; - GtkTreeModel *model; - Playlist *result = NULL; +void pm_selected_playlists_foreach(PlaylistSelectionForeachFunc func, gpointer data) { + GList *playlists = pm_get_selected_playlists(); + while(playlists) { + Playlist *pl = playlists->data; + (* func) (pl ,data); + playlists = playlists->next; + } +} - g_return_val_if_fail (playlist_treeview, NULL); - ts = gtk_tree_view_get_selection(playlist_treeview); - g_return_val_if_fail (ts, NULL); +GList *pm_get_selected_playlists() { + g_return_val_if_fail(playlist_treeview, NULL); - if (gtk_tree_selection_get_selected(ts, &model, &iter)) { - gtk_tree_model_get(model, &iter, PM_COLUMN_PLAYLIST, &result, -1); + GtkTreeSelection *selection = gtk_tree_view_get_selection(playlist_treeview); + g_return_val_if_fail(selection, NULL); + + GtkTreeModel *model = gtk_tree_view_get_model(playlist_treeview); + GList *paths = gtk_tree_selection_get_selected_rows(selection, &model); + GList *playlists = NULL; + + while (paths) { + GtkTreePath *path = paths->data; + GtkTreeIter iter; + + if (gtk_tree_model_get_iter(model, &iter, path)) { + Playlist *pl; + gtk_tree_model_get(model, &iter, PM_COLUMN_PLAYLIST, &pl, -1); + if (pl) { + playlists = g_list_append(playlists, pl); + } + } + + paths = paths->next; } - /* playlist was just changed -- wait until current_playlist is - updated. */ - if (result != gtkpod_get_current_playlist()) - result = NULL; - return result; + g_list_free(paths); + + return playlists; } -Itdb_iTunesDB* pm_get_selected_itdb(void) { - GtkTreeSelection *ts; - GtkTreeIter iter; - GtkTreeModel *model; - Itdb_iTunesDB *result = NULL; +Playlist *pm_get_first_selected_playlist(void) { - g_return_val_if_fail (playlist_treeview, NULL); - ts = gtk_tree_view_get_selection(playlist_treeview); - g_return_val_if_fail (ts, NULL); + GList *playlists = pm_get_selected_playlists(); - if (gtk_tree_selection_get_selected(ts, &model, &iter)) { - gtk_tree_model_get(model, &iter, PM_COLUMN_ITDB, &result, -1); + if (!playlists) { + return NULL; } - /* playlist was just changed -- wait until current_playlist is - updated. */ - if (result != gtkpod_get_current_itdb()) - result = NULL; - return result; + return playlists->data; +} + +gint pm_get_selected_playlist_count() { + GtkTreeSelection *selection = gtk_tree_view_get_selection(playlist_treeview); + return gtk_tree_selection_count_selected_rows(selection); } -/* use with care!! */ -void pm_set_selected_playlist(Playlist *pl) { - gtkpod_set_current_playlist(pl); +gboolean pm_is_playlist_selected() { + return pm_get_selected_playlist_count() > 0; } void pm_show_all_playlists() { @@ -2082,7 +2093,7 @@ void playlist_display_update_itdb_cb(GtkPodApp *app, gpointer olditdb, gpointer /* remove @old_itdb (all playlists are removed if the MPL is removed and add @new_itdb at its place */ - pm_remove_playlist(itdb_playlist_mpl(old_itdb), FALSE); + pm_remove_playlist(itdb_playlist_mpl(old_itdb)); /* display replacement */ pm_add_itdb(new_itdb, pos); @@ -2103,21 +2114,7 @@ void playlist_display_itdb_removed_cb(GtkPodApp *app, gpointer itdb, gpointer da return; } - pm_remove_playlist(itdb_playlist_mpl(old_itdb), FALSE); -} - -void playlist_display_select_playlist_cb(GtkPodApp *app, gpointer pl, gpointer data) { - Playlist *new_playlist = pl; - Playlist *old_playlist = pm_get_selected_playlist(); - - if (old_playlist == new_playlist) { - return; - } - - if (old_playlist) - pm_unselect_playlist(old_playlist); - - pm_select_playlist(new_playlist); + pm_remove_playlist(itdb_playlist_mpl(old_itdb)); } void playlist_display_playlist_added_cb(GtkPodApp *app, gpointer pl, gint32 pos, gpointer data) { @@ -2129,7 +2126,7 @@ void playlist_display_playlist_added_cb(GtkPodApp *app, gpointer pl, gint32 pos, void playlist_display_playlist_removed_cb(GtkPodApp *app, gpointer pl, gpointer data) { Playlist *old_playlist = pl; - pm_remove_playlist(old_playlist, TRUE); + pm_remove_playlist(old_playlist); } void playlist_display_preference_changed_cb(GtkPodApp *app, gpointer pfname, gpointer value, gpointer data) { diff --git a/plugins/playlist_display/display_playlists.h b/plugins/playlist_display/display_playlists.h index e78f68f..8957a4b 100644 --- a/plugins/playlist_display/display_playlists.h +++ b/plugins/playlist_display/display_playlists.h @@ -49,16 +49,22 @@ typedef enum { GtkWidget *pm_create_playlist_view(GtkActionGroup *action_group); void pm_destroy_playlist_view(void); void pm_select_playlist(Playlist *playlist); -void pm_set_selected_playlist(Playlist *pl); + +GList *pm_get_selected_playlists(void); +Playlist *pm_get_first_selected_playlist(void); +gint pm_get_selected_playlist_count(void); +gboolean pm_is_playlist_selected(void); + +typedef gboolean (* PlaylistSelectionForeachFunc) (Playlist *playlist, gpointer data); +void pm_selected_playlists_foreach(PlaylistSelectionForeachFunc func, gpointer data); + void pm_remove_all_playlists (gboolean clear_sort); void pm_add_all_itdbs (void); -Playlist* pm_get_selected_playlist(void); void pm_stop_editing(gboolean cancel); void playlist_display_itdb_added_cb(GtkPodApp *app, gpointer itdb, gint32 pos, gpointer data); void playlist_display_itdb_removed_cb(GtkPodApp *app, gpointer itdb, gpointer data); void playlist_display_update_itdb_cb (GtkPodApp *app, gpointer olditdb, gpointer newitdb, gpointer data); -void playlist_display_select_playlist_cb (GtkPodApp *app, gpointer pl, gpointer data); void playlist_display_playlist_added_cb(GtkPodApp *app, gpointer pl, gint32 pos, gpointer data); void playlist_display_playlist_removed_cb(GtkPodApp *app, gpointer pl, gpointer data); void playlist_display_track_removed_cb(GtkPodApp *app, gpointer tk, gpointer data); diff --git a/plugins/playlist_display/playlist_display_actions.c b/plugins/playlist_display/playlist_display_actions.c index cd612d7..f8954b9 100644 --- a/plugins/playlist_display/playlist_display_actions.c +++ b/plugins/playlist_display/playlist_display_actions.c @@ -624,59 +624,77 @@ void on_pl_for_each_rating_activate(GtkAction *action, PlaylistDisplayPlugin* pl } } -static void delete_selected_playlist(DeleteAction deleteaction) { - Playlist *pl = pm_get_selected_playlist(); +static void delete_selected_playlists(DeleteAction deleteaction) { + GList *playlists = pm_get_selected_playlists(); + + while (playlists) { + Playlist *pl = playlists->data; + if (pl) { + gtkpod_set_current_playlist(pl); + delete_playlist_head(deleteaction); + } + else { + message_sb_no_playlist_selected(); + } - if (pl) { - delete_playlist_head(deleteaction); - } - else { - message_sb_no_playlist_selected(); + playlists = playlists->next; } } -void on_delete_selected_playlist (GtkAction *action, PlaylistDisplayPlugin* plugin) +void on_delete_selected_playlists (GtkAction *action, PlaylistDisplayPlugin* plugin) { - delete_selected_playlist (DELETE_ACTION_PLAYLIST); + delete_selected_playlists (DELETE_ACTION_PLAYLIST); } -void on_delete_selected_playlist_including_tracks_from_harddisk (GtkAction *action, PlaylistDisplayPlugin* plugin) +void on_delete_selected_playlists_including_tracks_from_harddisk (GtkAction *action, PlaylistDisplayPlugin* plugin) { - delete_selected_playlist (DELETE_ACTION_LOCAL); + delete_selected_playlists (DELETE_ACTION_LOCAL); } -void on_delete_selected_playlist_including_tracks_from_ipod (GtkAction *action, PlaylistDisplayPlugin* plugin) +void on_delete_selected_playlists_including_tracks_from_ipod (GtkAction *action, PlaylistDisplayPlugin* plugin) { - delete_selected_playlist (DELETE_ACTION_IPOD); + delete_selected_playlists (DELETE_ACTION_IPOD); } -void on_delete_selected_playlist_including_tracks_from_database (GtkAction *action, PlaylistDisplayPlugin* plugin) +void on_delete_selected_playlists_including_tracks_from_database (GtkAction *action, PlaylistDisplayPlugin* plugin) { - delete_selected_playlist (DELETE_ACTION_DATABASE); + delete_selected_playlists (DELETE_ACTION_DATABASE); } -void on_delete_selected_playlist_including_tracks_from_device(GtkAction *action, PlaylistDisplayPlugin* plugin) +void on_delete_selected_playlists_including_tracks_from_device(GtkAction *action, PlaylistDisplayPlugin* plugin) { iTunesDB *itdb = gtkpod_get_current_itdb(); if (!itdb) return; if (itdb->usertype & GP_ITDB_TYPE_IPOD) { - on_delete_selected_playlist_including_tracks_from_ipod(action, plugin); + on_delete_selected_playlists_including_tracks_from_ipod(action, plugin); } else if (itdb->usertype & GP_ITDB_TYPE_LOCAL) { - on_delete_selected_playlist_including_tracks_from_harddisk(action, plugin); + on_delete_selected_playlists_including_tracks_from_harddisk(action, plugin); } } -void on_update_selected_playlist (GtkAction *action, PlaylistDisplayPlugin* plugin) { - Playlist *pl = pm_get_selected_playlist(); - if (pl) { - update_tracks(pm_get_selected_playlist()->members); +void on_update_selected_playlists (GtkAction *action, PlaylistDisplayPlugin* plugin) { + + GList *playlists = pm_get_selected_playlists(); + + while (playlists) { + Playlist *pl = playlists->data; + if (pl) { + update_tracks(pl->members); + } + playlists = playlists->next; } } -void on_sync_playlist_with_dirs(GtkAction *action, PlaylistDisplayPlugin* plugin) { - if (gtkpod_get_current_playlist()) { - sync_playlist(gtkpod_get_current_playlist(), NULL, KEY_SYNC_CONFIRM_DIRS, 0, KEY_SYNC_DELETE_TRACKS, 0, KEY_SYNC_CONFIRM_DELETE, 0, KEY_SYNC_SHOW_SUMMARY, 0); +void on_sync_playlists_with_dirs(GtkAction *action, PlaylistDisplayPlugin* plugin) { + GList *playlists = pm_get_selected_playlists(); + + while (playlists) { + Playlist *pl = playlists->data; + if (pl) { + sync_playlist(pl, NULL, KEY_SYNC_CONFIRM_DIRS, 0, KEY_SYNC_DELETE_TRACKS, 0, KEY_SYNC_CONFIRM_DELETE, 0, KEY_SYNC_SHOW_SUMMARY, 0); + } + playlists = playlists->next; } } diff --git a/plugins/playlist_display/playlist_display_actions.h b/plugins/playlist_display/playlist_display_actions.h index 20ced8c..5d7b6d2 100644 --- a/plugins/playlist_display/playlist_display_actions.h +++ b/plugins/playlist_display/playlist_display_actions.h @@ -61,13 +61,13 @@ void on_pl_for_each_composer_activate(GtkAction *action, PlaylistDisplayPlugin* void on_pl_for_each_year_activate(GtkAction *action, PlaylistDisplayPlugin* plugin); void on_pl_for_each_rating_activate(GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_delete_selected_playlist (GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_delete_selected_playlist_including_tracks_from_harddisk (GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_delete_selected_playlist_including_tracks_from_ipod (GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_delete_selected_playlist_including_tracks_from_database (GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_delete_selected_playlist_including_tracks_from_device(GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_delete_selected_playlists (GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_delete_selected_playlists_including_tracks_from_harddisk (GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_delete_selected_playlists_including_tracks_from_ipod (GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_delete_selected_playlists_including_tracks_from_database (GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_delete_selected_playlists_including_tracks_from_device(GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_update_selected_playlist (GtkAction *action, PlaylistDisplayPlugin* plugin); -void on_sync_playlist_with_dirs(GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_update_selected_playlists (GtkAction *action, PlaylistDisplayPlugin* plugin); +void on_sync_playlists_with_dirs(GtkAction *action, PlaylistDisplayPlugin* plugin); #endif diff --git a/plugins/playlist_display/playlist_display_context_menu.c b/plugins/playlist_display/playlist_display_context_menu.c index b3246c6..2e8adda 100644 --- a/plugins/playlist_display/playlist_display_context_menu.c +++ b/plugins/playlist_display/playlist_display_context_menu.c @@ -40,13 +40,21 @@ #include "libgtkpod/gp_itdb.h" #include "libgtkpod/context_menus.h" #include "libgtkpod/misc_playlist.h" +#include "libgtkpod/misc_track.h" #include "libgtkpod/misc.h" +#include "libgtkpod/prefs.h" +#include "libgtkpod/syncdir.h" static void context_menu_delete_playlist_head(GtkMenuItem *mi, gpointer data) { DeleteAction deleteaction = GPOINTER_TO_INT (data); delete_playlist_head(deleteaction); } +void context_menu_delete_track_head(GtkMenuItem *mi, gpointer data) { + DeleteAction deleteaction = GPOINTER_TO_INT (data); + delete_track_head(deleteaction); +} + static GtkWidget *add_delete_all_tracks_from_ipod(GtkWidget *menu) { GtkWidget *mi; GtkWidget *sub; @@ -99,21 +107,33 @@ static GtkWidget *add_delete_playlist_but_keep_tracks(GtkWidget *menu) { return hookup_menu_item(menu, _("Delete But Keep Tracks"), GTK_STOCK_DELETE, G_CALLBACK (context_menu_delete_playlist_head), GINT_TO_POINTER (DELETE_ACTION_PLAYLIST)); } -static void copy_selected_playlist_to_target_itdb(GtkMenuItem *mi, gpointer *userdata) { +static void copy_selected_playlists_to_target_itdb(GtkMenuItem *mi, gpointer *userdata) { iTunesDB *t_itdb = *userdata; g_return_if_fail (t_itdb); - if (gtkpod_get_current_playlist()) - copy_playlist_to_target_itdb(gtkpod_get_current_playlist(), t_itdb); + + GList *playlists = pm_get_selected_playlists(); + while(playlists) { + Playlist *pl = playlists->data; + copy_playlist_to_target_itdb(pl, t_itdb); + playlists = playlists->next; + } } -static void copy_selected_playlist_to_target_playlist(GtkMenuItem *mi, gpointer *userdata) { + + +static void copy_selected_playlists_to_target_playlist(GtkMenuItem *mi, gpointer *userdata) { Playlist *t_pl = *userdata; g_return_if_fail (t_pl); - if (gtkpod_get_current_playlist()) - copy_playlist_to_target_playlist(gtkpod_get_current_playlist(), t_pl); + + GList *playlists = pm_get_selected_playlists(); + while(playlists) { + Playlist *pl = playlists->data; + copy_playlist_to_target_playlist(pl, t_pl); + playlists = playlists->next; + } } -static GtkWidget *add_copy_selected_playlist_to_target_itdb(GtkWidget *menu, const gchar *title) { +static GtkWidget *add_copy_selected_playlists_to_target_itdb(GtkWidget *menu, const gchar *title) { GtkWidget *mi; GtkWidget *sub; GtkWidget *pl_mi; @@ -150,7 +170,7 @@ static GtkWidget *add_copy_selected_playlist_to_target_itdb(GtkWidget *menu, con pl_sub = gtk_menu_new(); gtk_widget_show(pl_sub); gtk_menu_item_set_submenu(GTK_MENU_ITEM (pl_mi), pl_sub); - hookup_menu_item(pl_sub, _(itdb_playlist_mpl(itdb)->name), stock_id, G_CALLBACK(copy_selected_playlist_to_target_itdb), &itdbs->data); + hookup_menu_item(pl_sub, _(itdb_playlist_mpl(itdb)->name), stock_id, G_CALLBACK(copy_selected_playlists_to_target_itdb), &itdbs->data); add_separator(pl_sub); for (db = itdb->playlists; db; db = db->next) { pl = db->data; @@ -159,7 +179,7 @@ static GtkWidget *add_copy_selected_playlist_to_target_itdb(GtkWidget *menu, con stock_id = GTK_STOCK_PROPERTIES; else stock_id = GTK_STOCK_JUSTIFY_LEFT; - hookup_menu_item(pl_sub, _(pl->name), stock_id, G_CALLBACK(copy_selected_playlist_to_target_playlist), &db->data); + hookup_menu_item(pl_sub, _(pl->name), stock_id, G_CALLBACK(copy_selected_playlists_to_target_playlist), &db->data); } } } @@ -195,7 +215,13 @@ static void open_photo_editor(GtkMenuItem *mi, gpointer data) { /* Save Changes */ static void save_changes(GtkMenuItem *mi, gpointer data) { g_return_if_fail (gtkpod_get_current_playlist()); - gp_save_itdb(gtkpod_get_current_playlist()->itdb); + + GList *playlists = pm_get_selected_playlists(); + while (playlists) { + Playlist *pl = playlists->data; + gp_save_itdb(pl->itdb); + playlists = playlists->next; + } } /* Load an itdb */ @@ -268,21 +294,42 @@ static GtkWidget *add_eject_ipod(GtkWidget *menu) { return hookup_menu_item(menu, _("Eject iPod"), GTK_STOCK_DISCONNECT, G_CALLBACK (eject_ipod), NULL); } -void pm_context_menu_init(void) { - GtkWidget *menu = NULL; - Playlist *pl; +/* + * sync_dirs_ entries - sync the directories of the selected playlist + * + * @mi - the menu item selected + * @data - Ignored, should be NULL + */ +static void sync_dirs(GtkMenuItem *mi, gpointer data) { + GList *playlists = pm_get_selected_playlists(); + while (playlists) { + Playlist *pl = playlists->data; + sync_playlist(pl, NULL, KEY_SYNC_CONFIRM_DIRS, 0, KEY_SYNC_DELETE_TRACKS, 0, KEY_SYNC_CONFIRM_DELETE, 0, KEY_SYNC_SHOW_SUMMARY, 0); + playlists = playlists->next; + } +} - if (widgets_blocked) - return; +static GtkWidget *add_sync_playlist_with_dirs(GtkWidget *menu) { + return hookup_menu_item(menu, _("Sync Playlist with Dir(s)"), GTK_STOCK_REFRESH, G_CALLBACK (sync_dirs), NULL); +} - pm_stop_editing(TRUE); +static void update_multi_tracks_from_file(GtkMenuItem *mi, gpointer data) { + GList *playlists = pm_get_selected_playlists(); + while (playlists) { + Playlist *pl = playlists->data; + update_tracks(pl->members); + playlists = playlists->next; + } +} - if (!pm_get_selected_playlist()) - return; +GtkWidget *add_multi_update_tracks_from_file(GtkWidget *menu) { + return hookup_menu_item(menu, _("Update Tracks from File"), GTK_STOCK_REFRESH, G_CALLBACK (update_multi_tracks_from_file), NULL); +} - pl = pm_get_selected_playlist(); - if (!pl) - return; +static void _populate_single_playlist_menu(GtkWidget *menu) { + + Playlist *pl = pm_get_first_selected_playlist(); + g_return_if_fail(pl); // Ensure that all the tracks in the playlist are the current selected tracks gtkpod_set_selected_tracks(pl->members); @@ -293,8 +340,6 @@ void pm_context_menu_init(void) { eitdb = itdb->userdata; g_return_if_fail (eitdb); - menu = gtk_menu_new(); - if (itdb->usertype & GP_ITDB_TYPE_IPOD) { if (eitdb->itdb_imported) { add_exec_commands(menu); @@ -312,7 +357,7 @@ void pm_context_menu_init(void) { add_delete_playlist_but_keep_tracks(delete_menu); } add_separator(menu); - add_copy_selected_playlist_to_target_itdb(menu, _("Copy selected playlist to...")); + add_copy_selected_playlists_to_target_itdb(menu, _("Copy selected playlist to...")); add_separator(menu); add_update_tracks_from_file(menu); @@ -340,7 +385,7 @@ void pm_context_menu_init(void) { add_load_ipod(menu); } } - if (itdb->usertype & GP_ITDB_TYPE_LOCAL) { + else if (itdb->usertype & GP_ITDB_TYPE_LOCAL) { add_exec_commands(menu); add_separator(menu); @@ -353,7 +398,7 @@ void pm_context_menu_init(void) { add_delete_playlist_including_tracks_harddisk(delete_menu); add_delete_playlist_but_keep_tracks(delete_menu); } - add_copy_selected_playlist_to_target_itdb(menu, _("Copy selected playlist to...")); + add_copy_selected_playlists_to_target_itdb(menu, _("Copy selected playlist to...")); add_separator(menu); add_update_tracks_from_file(menu); if (!pl->is_spl) { @@ -376,6 +421,43 @@ void pm_context_menu_init(void) { if (eitdb->data_changed) { add_save_changes(menu); } +} + +static void _populate_multi_playlist_menu(GtkWidget *menu) { + + GtkWidget *delete_menu = add_sub_menu(menu, "Delete", GTK_STOCK_DELETE); + add_delete_playlist_including_tracks_ipod(delete_menu); + add_delete_playlist_but_keep_tracks(delete_menu); + + add_separator(menu); + add_copy_selected_playlists_to_target_itdb(menu, _("Copy selected playlist to...")); + + add_separator(menu); + add_multi_update_tracks_from_file(menu); + + add_sync_playlist_with_dirs(menu); + + add_save_changes(menu); +} + +void pm_context_menu_init(void) { + GtkWidget *menu = NULL; + + if (widgets_blocked) + return; + + pm_stop_editing(TRUE); + + if (!pm_is_playlist_selected()) + return; + + menu = gtk_menu_new(); + + if (pm_get_selected_playlist_count() == 1) { + _populate_single_playlist_menu(menu); + } else { + _populate_multi_playlist_menu(menu); + } /* * button should be button 0 as per the docs because we're calling diff --git a/plugins/playlist_display/plugin.c b/plugins/playlist_display/plugin.c index 2368e2c..407c55c 100644 --- a/plugins/playlist_display/plugin.c +++ b/plugins/playlist_display/plugin.c @@ -116,7 +116,7 @@ static GtkActionEntry playlist_actions[] = N_("Sync Playlist with Dir(s)"), NULL, NULL, - G_CALLBACK (on_sync_playlist_with_dirs) + G_CALLBACK (on_sync_playlists_with_dirs) }, { ACTION_NEW_PLAYLIST_MENU, @@ -268,7 +268,7 @@ static GtkActionEntry playlist_actions[] = N_("Selected Playlist"), NULL, NULL, - G_CALLBACK (on_delete_selected_playlist) + G_CALLBACK (on_delete_selected_playlists) }, { "ActionDeleteSelectedPlaylistIncDb", @@ -276,7 +276,7 @@ static GtkActionEntry playlist_actions[] = N_("Selected Playlist including Tracks from Database"), NULL, NULL, - G_CALLBACK (on_delete_selected_playlist_including_tracks_from_database) + G_CALLBACK (on_delete_selected_playlists_including_tracks_from_database) }, { "ActionDeleteSelectedPlaylistIncDev", @@ -284,7 +284,7 @@ static GtkActionEntry playlist_actions[] = N_("Selected Playlist including Tracks from Device"), NULL, NULL, - G_CALLBACK (on_delete_selected_playlist_including_tracks_from_device) + G_CALLBACK (on_delete_selected_playlists_including_tracks_from_device) }, { "ActionUpdatePlaylist", @@ -292,7 +292,7 @@ static GtkActionEntry playlist_actions[] = N_("Selected Playlist"), NULL, NULL, - G_CALLBACK (on_update_selected_playlist) + G_CALLBACK (on_update_selected_playlists) } }; @@ -349,7 +349,6 @@ static gboolean activate_plugin(AnjutaPlugin *plugin) { playlist_display_plugin->playlist_view = pm_create_playlist_view(action_group); - g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_SELECTED, G_CALLBACK (playlist_display_select_playlist_cb), NULL); g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_ADDED, G_CALLBACK (playlist_display_playlist_added_cb), NULL); g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_REMOVED, G_CALLBACK (playlist_display_playlist_removed_cb), NULL); g_signal_connect (gtkpod_app, SIGNAL_ITDB_ADDED, G_CALLBACK (playlist_display_itdb_added_cb), NULL); @@ -373,7 +372,6 @@ static gboolean deactivate_plugin(AnjutaPlugin *plugin) { playlist_display_plugin = (PlaylistDisplayPlugin*) plugin; ui = anjuta_shell_get_ui(plugin->shell, NULL); - g_signal_handlers_disconnect_by_func (plugin->shell, G_CALLBACK (playlist_display_select_playlist_cb), plugin); g_signal_handlers_disconnect_by_func (plugin->shell, G_CALLBACK (playlist_display_playlist_added_cb), plugin); g_signal_handlers_disconnect_by_func (plugin->shell, G_CALLBACK (playlist_display_playlist_removed_cb), plugin); g_signal_handlers_disconnect_by_func (plugin->shell, G_CALLBACK (playlist_display_itdb_added_cb), plugin); ------------------------------------------------------------------------------ All the data continuously generated in your IT infrastructure contains a definitive record of customers, application performance, security threats, fraudulent activity and more. Splunk takes this data and makes sense of it. Business sense. IT sense. Common sense. http://p.sf.net/sfu/splunk-d2dcopy1 _______________________________________________ gtkpod-cvs2 mailing list gtkpod-cvs2@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2