chiark / gitweb /
A bit of work towards a mini-Disobedience mode (issue #30). Nowhere
[disorder] / disobedience / properties.c
index 16ee97cbaaf59d352ac599757666f273bbc50dcd..6600cf947ed88b0b7f0ed1caccd7e7cf212cf15d 100644 (file)
@@ -2,26 +2,21 @@
  * This file is part of DisOrder.
  * Copyright (C) 2006-2008 Richard Kettlewell
  *
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 /** @file disobedience/properties.c
  * @brief Track properties editor
- *
- * TODO:
- * - return and escape keys should work 
  */
 #include "disobedience.h"
 
@@ -47,16 +42,11 @@ static void set_edited_boolean(struct prefdata *f, const char *value);
 static void set_boolean(struct prefdata *f, const char *value);
 
 static void prefdata_completed(void *v, const char *err, const char *value);
-static void prefdata_onerror(struct callbackdata *cbd,
-                             int code,
-                             const char *msg);
-static struct callbackdata *make_callbackdata(struct prefdata *f);
-static void prefdata_completed_common(struct prefdata *f,
-                                      const char *value);
 
 static void properties_ok(GtkButton *button, gpointer userdata);
 static void properties_apply(GtkButton *button, gpointer userdata);
 static void properties_cancel(GtkButton *button, gpointer userdata);
+static void properties_help(GtkButton *button, gpointer userdata);
 
 static void properties_logged_in(const char *event,
                                  void *eventdata,
@@ -136,23 +126,33 @@ static const struct pref {
 
 /* Buttons that appear at the bottom of the window */
 static struct button buttons[] = {
+  {
+    GTK_STOCK_HELP,
+    properties_help,
+    "Go to manual",
+    0,
+    gtk_box_pack_start,
+  },
   {
     GTK_STOCK_OK,
     properties_ok,
     "Apply all changes and close window",
-    0
-  },
-  {
-    GTK_STOCK_APPLY,
-    properties_apply,
-    "Apply all changes and keep window open",
-    0
+    0,
+    gtk_box_pack_end,
   },
   {
     GTK_STOCK_CANCEL,
     properties_cancel,
     "Discard all changes and close window",
-    0
+    0,
+    gtk_box_pack_end
+  },
+  {
+    GTK_STOCK_APPLY,
+    properties_apply,
+    "Apply all changes and keep window open",
+    0,
+    gtk_box_pack_end,
   },
 };
 
@@ -179,7 +179,26 @@ static void propagate_clicked(GtkButton attribute((unused)) *button,
   }
 }
 
-void properties(int ntracks, const char **tracks) {
+/** @brief Keypress handler */
+static gboolean properties_keypress(GtkWidget attribute((unused)) *widget,
+                                    GdkEventKey *event,
+                                    gpointer attribute((unused)) user_data) {
+  if(event->state)
+    return FALSE;
+  switch(event->keyval) {
+  case GDK_Return:
+    properties_ok(0, 0);
+    return TRUE;
+  case GDK_Escape:
+    properties_cancel(0, 0);
+    return TRUE;
+  default:
+    return FALSE;
+  }
+}
+
+void properties(int ntracks, const char **tracks,
+                GtkWidget *parent) {
   int n, m;
   struct prefdata *f;
   GtkWidget *buttonbox, *vbox, *label, *entry, *propagate;
@@ -205,6 +224,9 @@ void properties(int ntracks, const char **tracks) {
   gtk_widget_set_style(properties_window, tool_style);
   g_signal_connect(properties_window, "destroy",
                   G_CALLBACK(gtk_widget_destroyed), &properties_window);
+  /* Keyboard shortcuts */
+  g_signal_connect(properties_window, "key-press-event",
+                   G_CALLBACK(properties_keypress), 0);
   /* Most of the action is the table of preferences */
   properties_table = gtk_table_new((NPREFS + 1) * ntracks, 2 + ntracks > 1,
                                    FALSE);
@@ -289,7 +311,9 @@ void properties(int ntracks, const char **tracks) {
   if(pw)
     progress_window_progress(pw, 0, 0);
   /* Pop up a progress bar while we're waiting */
-  pw = progress_window_new("Fetching Track Properties");
+  while(parent->parent)
+    parent = parent->parent;
+  pw = progress_window_new("Fetching Track Properties", parent);
 }
 
 /* Everything is filled in now */
@@ -311,8 +335,8 @@ static void kickoff_namepart(struct prefdata *f) {
    * wanted was the underlying preference, but in fact it should always match
    * and will supply a sane default without having to know how to parse tracks
    * names (which implies knowing collection roots). */
-  disorder_eclient_namepart(client, prefdata_completed, f->track, "display", f->p->part,
-                            make_callbackdata(f));
+  disorder_eclient_namepart(client, prefdata_completed,
+                            f->track, "display", f->p->part, f);
 }
 
 static void completed_namepart(struct prefdata *f) {
@@ -357,8 +381,7 @@ static void set_namepart_completed(void *v, const char *err) {
 /* String preferences ------------------------------------------------------ */
 
 static void kickoff_string(struct prefdata *f) {
-  disorder_eclient_get(client, prefdata_completed, f->track, f->p->part, 
-                      make_callbackdata(f));
+  disorder_eclient_get(client, prefdata_completed, f->track, f->p->part, f);
 }
 
 static void completed_string(struct prefdata *f) {
@@ -390,8 +413,7 @@ static void set_string(struct prefdata *f, const char *value) {
 /* Boolean preferences ----------------------------------------------------- */
 
 static void kickoff_boolean(struct prefdata *f) {
-  disorder_eclient_get(client, prefdata_completed, f->track, f->p->part, 
-                      make_callbackdata(f));
+  disorder_eclient_get(client, prefdata_completed, f->track, f->p->part, f);
 }
 
 static void completed_boolean(struct prefdata *f) {
@@ -424,34 +446,11 @@ static void set_boolean(struct prefdata *f, const char *value) {
 
 /* Querying preferences ---------------------------------------------------- */
 
-/* Make a suitable callbackdata */
-static struct callbackdata *make_callbackdata(struct prefdata *f) {
-  struct callbackdata *cbd = xmalloc(sizeof *cbd);
-
-  cbd->onerror = prefdata_onerror;
-  cbd->u.f = f;
-  return cbd;
-}
-
-/* No pref was set */
-static void prefdata_onerror(struct callbackdata *cbd,
-                             int attribute((unused)) code,
-                             const char attribute((unused)) *msg) {
-  prefdata_completed_common(cbd->u.f, 0);
-}
-
-/* Got the value of a pref */
 static void prefdata_completed(void *v, const char *err, const char *value) {
-  if(err) {
-  } else {
-    struct callbackdata *cbd = v;
-    
-    prefdata_completed_common(cbd->u.f, value);
-  }
-}
+  struct prefdata *const f = v;
 
-static void prefdata_completed_common(struct prefdata *f,
-                                      const char *value) {
+  if(err)
+    popup_protocol_error(0, err);
   f->value = value;
   f->p->type->completed(f);
   f->p->type->set_edited(f, f->value);
@@ -502,6 +501,11 @@ static void properties_cancel(GtkButton attribute((unused)) *button,
   properties_event = 0;
 }
 
+static void properties_help(GtkButton attribute((unused)) *button,
+                            gpointer attribute((unused)) userdata) {
+  popup_help("properties.html");
+}
+
 /** @brief Called when we've just logged in
  *
  * Destroys the current properties window.