* 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"
static const char *get_edited_namepart(struct prefdata *f);
static void set_edited_namepart(struct prefdata *f, const char *value);
static void set_namepart(struct prefdata *f, const char *value);
-static void set_namepart_completed(void *v, const char *error);
+static void set_namepart_completed(void *v, const char *err);
static void kickoff_string(struct prefdata *f);
static void completed_string(struct prefdata *f);
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 *error, 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 prefdata_completed(void *v, const char *err, 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,
GtkWidget *widget;
};
-/* The type of a preference is the collection of callbacks needed to get,
- * display and set it */
+/** @brief Type of a track preference
+ *
+ * The type of a preference is the collection of callbacks needed to get,
+ * display and set it.
+ */
struct preftype {
+ /** @brief Kick off the request to fetch the pref from the server. */
void (*kickoff)(struct prefdata *f);
- /* Kick off the request to fetch the pref from the server. */
+ /** @brief Called when the value comes back in; creates the widget. */
void (*completed)(struct prefdata *f);
- /* Called when the value comes back in; creates the widget. */
+ /** @brief Get the edited value from the widget. */
const char *(*get_edited)(struct prefdata *f);
- /* Get the edited value from the widget. */
/** @brief Update the edited value */
void (*set_edited)(struct prefdata *f, const char *value);
+ /** @brief Set the new value and (if necessary) arrange for our display to update. */
void (*set)(struct prefdata *f, const char *value);
- /* Set the new value and (if necessary) arrange for our display to update. */
};
/* A namepart pref */
set_boolean
};
-/* @brief The known prefs for each track */
+/** @brief The known prefs for each track */
static const struct pref {
const char *label; /**< @brief user-level description */
const char *part; /**< @brief protocol-level tag */
/* 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,
},
};
}
}
-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;
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);
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 */
* 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_part(client, prefdata_completed,
+ f->track, "display", f->p->part, f);
}
static void completed_namepart(struct prefdata *f) {
/* 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) {
/* 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) {
/* 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);
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.