* status bar.
*/
static void gtkclient_protocol_error(void attribute((unused)) *u,
- void *v,
+ void attribute((unused)) *v,
int code,
const char *msg) {
- struct callbackdata *cbd = v;
-
D(("gtkclient_protocol_error %s", msg));
- if(cbd && cbd->onerror)
- cbd->onerror(cbd, code, msg);
- else
- gtk_label_set_text(GTK_LABEL(report_label), msg);
+ gtk_label_set_text(GTK_LABEL(report_label), msg);
}
/** @brief Report callback from eclient */
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk/gdkkeysyms.h>
/* Types ------------------------------------------------------------------- */
struct choosenode;
struct progress_window;
-/** @brief Callback data structure
- *
- * This program is extremely heavily callback-driven. Rather than have
- * numerous different callback structures we have a single one which can be
- * interpreted adequately both by success and error handlers.
- */
-struct callbackdata {
- void (*onerror)(struct callbackdata *cbd,
- int code,
- const char *msg); /* called on error */
- union {
- const char *key; /* gtkqueue.c op_part_lookup */
- struct choosenode *choosenode; /* gtkchoose.c got_files/got_dirs */
- struct queuelike *ql; /* gtkqueue.c queuelike_completed */
- struct prefdata *f; /* properties.c */
- const char *user; /* users.c */
- struct {
- const char *user, *email; /* users.c */
- } edituser;
- } u;
-};
-
/** @brief Per-tab callbacks
*
* Some of the options in the main menu depend on which tab is displayed, so we
* It you hit Cancel then the window disappears without saving anything.
*
* TODO
- * - escape and return should work
* - cancel/close should be consistent with properties
*/
gtk_widget_destroy(login_window);
}
+/** @brief Keypress handler */
+static gboolean login_keypress(GtkWidget attribute((unused)) *widget,
+ GdkEventKey *event,
+ gpointer attribute((unused)) user_data) {
+ if(event->state)
+ return FALSE;
+ switch(event->keyval) {
+ case GDK_Return:
+ login_ok(0, 0);
+ return TRUE;
+ case GDK_Escape:
+ login_cancel(0, 0);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
/* Buttons that appear at the bottom of the window */
static struct button buttons[] = {
{
G_CALLBACK(gtk_widget_destroyed), &login_window);
gtk_window_set_title(GTK_WINDOW(login_window), "Login Details");
/* Construct the form */
- table = gtk_table_new(NLWIS + 1/*rows*/, 2/*columns*/, FALSE/*homogenous*/);
+ table = gtk_table_new(NLWIS/*rows*/, 2/*columns*/, FALSE/*homogenous*/);
gtk_widget_set_style(table, tool_style);
for(n = 0; n < NLWIS; ++n) {
label = gtk_label_new(lwis[n].description);
}
buttonbox = create_buttons(buttons, NBUTTONS);
vbox = gtk_vbox_new(FALSE, 1);
+ gtk_box_pack_start(GTK_BOX(vbox),
+ gtk_image_new_from_pixbuf(find_image("logo256.png")),
+ TRUE/*expand*/,
+ TRUE/*fill*/,
+ 4/*padding*/);
gtk_box_pack_start(GTK_BOX(vbox), table,
TRUE/*expand*/, TRUE/*fill*/, 1/*padding*/);
gtk_box_pack_start(GTK_BOX(vbox), buttonbox,
gtk_container_add(GTK_CONTAINER(login_window), frame_widget(vbox, NULL));
gtk_window_set_transient_for(GTK_WINDOW(login_window),
GTK_WINDOW(toplevel));
+ /* Keyboard shortcuts */
+ g_signal_connect(login_window, "key-press-event",
+ G_CALLBACK(login_keypress), 0);
gtk_widget_show_all(login_window);
}
*/
/** @file disobedience/properties.c
* @brief Track properties editor
- *
- * TODO:
- * - return and escape keys should work
*/
#include "disobedience.h"
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);
}
}
+/** @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) {
int n, m;
struct prefdata *f;
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);
* 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) {
/* 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);
*
* TODO:
* - enter new username in the GtkTreeView
- * - escape and enter keys should work
* - should have a cancel or close button, consistent with properties and login
*/
};
#define NUSERS_BUTTONS (sizeof users_buttons / sizeof *users_buttons)
+/** @brief Keypress handler */
+static gboolean users_keypress(GtkWidget attribute((unused)) *widget,
+ GdkEventKey *event,
+ gpointer attribute((unused)) user_data) {
+ if(event->state)
+ return FALSE;
+ switch(event->keyval) {
+ case GDK_Escape:
+ gtk_widget_destroy(users_window);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
/** @brief Pop up the user management window */
void manage_users(void) {
GtkWidget *tree, *buttons, *hbox, *hbox2, *vbox, *vbox2;
g_signal_connect(users_window, "destroy",
G_CALLBACK(gtk_widget_destroyed), &users_window);
gtk_window_set_title(GTK_WINDOW(users_window), "User Management");
+ /* Keyboard shortcuts */
+ g_signal_connect(users_window, "key-press-event",
+ G_CALLBACK(users_keypress), 0);
/* default size is too small */
gtk_window_set_default_size(GTK_WINDOW(users_window), 240, 240);
nodown.png nodowndown.png noup.png noupup.png tick.png up.png upup.png \
notes.png play.png pause.png random.png randomcross.png notescross.png \
propagate.png speaker.png speakercross.png directory.png logo.png \
-logosmall.png
+logosmall.png logo256.png
EXTRA_DIST=$(pkghttp_DATA) duck.png disobedience16x16.xpm disobedience32x32.xpm