chiark / gitweb /
Correct sense of pause/resume tooltips
[disorder] / disobedience / playlists.c
index a7c9cc60a8736dd1084534d3693923d96528f0ad..4d4194ea76a0e3c5361ed03f2d794ac52920d384 100644 (file)
@@ -123,6 +123,14 @@ static gboolean playlist_picker_find(GtkTreeIter *parent,
 static void playlist_picker_delete_obsolete(GtkTreeIter parent[1],
                                             char **exists,
                                             int nexists);
+static gboolean playlist_picker_button(GtkWidget *widget,
+                                       GdkEventButton *event,
+                                       gpointer user_data);
+static gboolean playlist_editor_keypress(GtkWidget *widget,
+                                         GdkEventKey *event,
+                                         gpointer user_data);
+static void playlist_editor_ok(GtkButton *button, gpointer userdata);
+static void playlist_editor_help(GtkButton *button, gpointer userdata);
 
 /** @brief Playlist editing window */
 static GtkWidget *playlist_window;
@@ -143,12 +151,12 @@ static const struct queue_column playlist_columns[] = {
  * - select/deselect all work
  */
 static struct menuitem playlist_menuitems[] = {
-  { "Track properties", ql_properties_activate, ql_properties_sensitive, 0, 0 },
-  { "Play track", ql_play_activate, ql_play_sensitive, 0, 0 },
-  { "Play playlist", playlist_playall_activate, playlist_playall_sensitive, 0, 0 },
-  { "Remove track from queue", playlist_remove_activate, playlist_remove_sensitive, 0, 0 },
-  { "Select all tracks", ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
-  { "Deselect all tracks", ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
+  { "Track properties", GTK_STOCK_PROPERTIES, ql_properties_activate, ql_properties_sensitive, 0, 0 },
+  { "Play track", GTK_STOCK_MEDIA_PLAY, ql_play_activate, ql_play_sensitive, 0, 0 },
+  { "Play playlist", NULL, playlist_playall_activate, playlist_playall_sensitive, 0, 0 },
+  { "Remove track from playlist", GTK_STOCK_DELETE, playlist_remove_activate, playlist_remove_sensitive, 0, 0 },
+  { "Select all tracks", GTK_STOCK_SELECT_ALL, ql_selectall_activate, ql_selectall_sensitive, 0, 0 },
+  { "Deselect all tracks", NULL, ql_selectnone_activate, ql_selectnone_sensitive, 0, 0 },
 };
 
 static const GtkTargetEntry playlist_targets[] = {
@@ -872,13 +880,15 @@ static struct button playlist_picker_buttons[] = {
     GTK_STOCK_ADD,
     playlist_picker_add,
     "Create a new playlist",
-    0
+    0,
+    NULL,
   },
   {
     GTK_STOCK_REMOVE,
     playlist_picker_delete,
     "Delete a playlist",
-    0
+    0,
+    NULL,
   },
 };
 #define NPLAYLIST_PICKER_BUTTONS (sizeof playlist_picker_buttons / sizeof *playlist_picker_buttons)
@@ -919,6 +929,8 @@ static GtkWidget *playlist_picker_create(void) {
 
   g_signal_connect(tree, "key-press-event",
                    G_CALLBACK(playlist_picker_keypress), 0);
+  g_signal_connect(tree, "button-press-event",
+                   G_CALLBACK(playlist_picker_button), 0);
 
   return vbox;
 }
@@ -938,6 +950,96 @@ static gboolean playlist_picker_keypress(GtkWidget attribute((unused)) *widget,
   }
 }
 
+static void playlist_picker_select_activate(GtkMenuItem attribute((unused)) *item,
+                                            gpointer attribute((unused)) userdata) {
+  /* nothing */
+}
+
+static int playlist_picker_select_sensitive(void *extra) {
+  GtkTreeIter *iter = extra;
+  return gtk_tree_store_iter_depth(playlist_picker_list, iter) > 0;
+}
+
+static void playlist_picker_play_activate(GtkMenuItem attribute((unused)) *item,
+                                          gpointer attribute((unused)) userdata) {
+  /* Re-use the menu-based activation callback */
+  disorder_eclient_playlist_get(client, playlist_menu_received_content,
+                                playlist_picker_selected, NULL);
+}
+
+static int playlist_picker_play_sensitive(void *extra) {
+  GtkTreeIter *iter = extra;
+  return gtk_tree_store_iter_depth(playlist_picker_list, iter) > 0;
+}
+
+static void playlist_picker_remove_activate(GtkMenuItem attribute((unused)) *item,
+                                            gpointer attribute((unused)) userdata) {
+  /* Re-use the 'Remove' button' */
+  playlist_picker_delete(NULL, NULL);
+}
+
+static int playlist_picker_remove_sensitive(void *extra) {
+  GtkTreeIter *iter = extra;
+  if(gtk_tree_store_iter_depth(playlist_picker_list, iter) > 0) {
+    if(strchr(playlist_picker_selected, '.')) {
+      if(!strncmp(playlist_picker_selected, config->username,
+                  strlen(config->username)))
+        return TRUE;
+    } else
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/** @brief Pop-up menu for picker */
+static struct menuitem playlist_picker_menuitems[] = {
+  {
+    "Select playlist",
+    NULL,
+    playlist_picker_select_activate,
+    playlist_picker_select_sensitive,
+    0,
+    0
+  },
+  {
+    "Play playlist",
+    GTK_STOCK_MEDIA_PLAY, 
+    playlist_picker_play_activate,
+    playlist_picker_play_sensitive,
+    0,
+    0
+  },
+  {
+    "Remove playlist",
+    GTK_STOCK_DELETE,
+    playlist_picker_remove_activate,
+    playlist_picker_remove_sensitive,
+    0,
+    0
+  },
+};
+
+static gboolean playlist_picker_button(GtkWidget *widget,
+                                       GdkEventButton *event,
+                                       gpointer attribute((unused)) user_data) {
+  if(event->type == GDK_BUTTON_PRESS && event->button == 3) {
+    static GtkWidget *playlist_picker_menu;
+
+    /* Right click press pops up a menu */
+    ensure_selected(GTK_TREE_VIEW(widget), event);
+    /* Find the selected row */
+    GtkTreeIter iter[1];
+    if(!gtk_tree_selection_get_selected(playlist_picker_selection, 0, iter))
+      return TRUE;
+    popup(&playlist_picker_menu, event,
+          playlist_picker_menuitems,
+          sizeof playlist_picker_menuitems / sizeof *playlist_picker_menuitems,
+          iter);
+    return TRUE;
+  }
+  return FALSE;
+}
+
 static void playlist_picker_destroy(void) {
   playlist_picker_delete_button = NULL;
   g_object_unref(playlist_picker_list);
@@ -953,6 +1055,26 @@ static GtkWidget *playlist_editor_public;
 static GtkWidget *playlist_editor_private;
 static int playlist_editor_setting_buttons;
 
+/** @brief Buttons for the playlist window */
+static struct button playlist_editor_buttons[] = {
+  {
+    GTK_STOCK_OK,
+    playlist_editor_ok,
+    "Close window",
+    0,
+    gtk_box_pack_end,
+  },
+  {
+    GTK_STOCK_HELP,
+    playlist_editor_help,
+    "Go to manual",
+    0,
+    gtk_box_pack_end,
+  },
+};
+
+#define NPLAYLIST_EDITOR_BUTTONS (int)(sizeof playlist_editor_buttons / sizeof *playlist_editor_buttons)
+
 static GtkWidget *playlists_editor_create(void) {
   assert(ql_playlist.view == NULL);     /* better not be set up already */
 
@@ -977,15 +1099,36 @@ static GtkWidget *playlists_editor_create(void) {
   gtk_box_pack_start(GTK_BOX(hbox), playlist_editor_private,
                      FALSE/*expand*/, FALSE/*fill*/, 0);
   playlist_editor_set_buttons(0,0,0);
+  create_buttons_box(playlist_editor_buttons,
+                     NPLAYLIST_EDITOR_BUTTONS,
+                     hbox);
 
   GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(vbox), init_queuelike(&ql_playlist),
+  GtkWidget *view = init_queuelike(&ql_playlist);
+  gtk_box_pack_start(GTK_BOX(vbox), view,
                      TRUE/*expand*/, TRUE/*fill*/, 0);
   gtk_box_pack_start(GTK_BOX(vbox), hbox,
                      FALSE/*expand*/, FALSE/*fill*/, 0);
+  g_signal_connect(view, "key-press-event",
+                   G_CALLBACK(playlist_editor_keypress), 0);
   return vbox;
 }
 
+static gboolean playlist_editor_keypress(GtkWidget attribute((unused)) *widget,
+                                         GdkEventKey *event,
+                                         gpointer attribute((unused)) user_data) {
+  if(event->state)
+    return FALSE;
+  switch(event->keyval) {
+  case GDK_BackSpace:
+  case GDK_Delete:
+    playlist_remove_activate(NULL, NULL);
+    return TRUE;
+  default:
+    return FALSE;
+  }
+}
+
 /** @brief Called when the public/private buttons are set */
 static void playlist_editor_button_toggled(GtkToggleButton *tb,
                                            gpointer userdata) {
@@ -1109,6 +1252,16 @@ static void playlists_editor_received_tracks(void *v,
   ql_new_queue(&ql_playlist, newq);
 }
 
+static void playlist_editor_ok(GtkButton attribute((unused)) *button, 
+                               gpointer attribute((unused)) userdata) {
+  gtk_widget_destroy(playlist_window);
+}
+
+static void playlist_editor_help(GtkButton attribute((unused)) *button, 
+                                 gpointer attribute((unused)) userdata) {
+  popup_help("playlists.html");
+}
+
 /* Playlist mutation -------------------------------------------------------- */
 
 /** @brief State structure for guarded playlist modification