/* * gpe-conf * * Copyright (C) 2002 Pierre TARDY * 2003, 2005, 2006 Florian Boor * * 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 (at your option) any later version. * * GPE keybindings software setup utility (here: keylaunch) * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "applets.h" #include "keyctl.h" #include "device.h" static gchar *keylaunchrc = NULL; static gchar *bg_image = NULL; static gint bg_x = 0, bg_y = 0; static gboolean menuselect = FALSE; static gint NUM_COMMANDS = 0; static gint NUM_BUTTONS = 0; #define KEYLAUNCH_BIN PREFIX "/bin/keylaunch" #define FILE_COMMANDS "/etc/gpe/key-commands" #define FILE_LAYOUT "/etc/gpe/key-layout" #define ICON_PATH PREFIX "/share/pixmaps" void FileSelected (gchar *file, gpointer data); /* local types */ typedef struct { gchar *symbol; gchar *key; gchar *modificator; gchar *command; gchar *title; gint type; gint x, y; } t_buttondef; typedef struct { gchar *title; gchar *command; } t_scommand; /* local variables */ static struct { gboolean active; GtkWidget **buttons; GdkPixbuf *p; GtkWidget *edit; GtkWidget *icon; GtkWidget *select; } self; t_scommand *commands = NULL; t_buttondef *buttondefs = NULL; static gint active_button = 0; static gboolean commands_load(void) { GKeyFile *cmdfile; GError *err = NULL; gchar **keys; guint i; gsize cmdcnt; gchar *filename; cmdfile = g_key_file_new(); filename = device_get_specific_file (FILE_COMMANDS); if (!filename) filename = g_strdup (FILE_COMMANDS); if (!g_key_file_load_from_file (cmdfile, filename, G_KEY_FILE_KEEP_COMMENTS, &err)) { g_printerr ("%s\n", err->message); g_error_free(err); g_free (filename); return FALSE; } g_free (filename); keys = g_key_file_get_keys (cmdfile, "Commands", &cmdcnt, &err); if (keys) { for (i=0; i < cmdcnt; i++) { gsize cnt = 0; gchar **vals; commands = realloc(commands, (NUM_COMMANDS+1) * sizeof(t_scommand)); vals = g_key_file_get_string_list (cmdfile, "Commands", keys[i], &cnt, &err); if (cnt == 2) { commands[NUM_COMMANDS].title = vals[0]; commands[NUM_COMMANDS].command = vals[1]; NUM_COMMANDS++; } else if (cnt == 1) { commands[NUM_COMMANDS].title = vals[0]; commands[NUM_COMMANDS].command = ""; NUM_COMMANDS++; } else { if (vals) g_strfreev(vals); } } g_strfreev(keys); } return TRUE; } static gboolean layout_load(void) { GKeyFile *layoutfile; GError *err = NULL; gchar **btndefs; guint i; gsize btncnt; gchar *filename; layoutfile = g_key_file_new(); filename = device_get_specific_file (FILE_LAYOUT); if (!filename) filename = g_strdup (FILE_LAYOUT); if (!g_key_file_load_from_file (layoutfile, filename, G_KEY_FILE_KEEP_COMMENTS, &err)) { g_printerr ("%s\n", err->message); g_error_free(err); g_free (filename); err = NULL; return FALSE; } g_free (filename); if (g_key_file_has_group(layoutfile, "Global")) { bg_image = g_key_file_get_string(layoutfile, "Global", "image", &err); if (err) { g_error_free(err); err = NULL; } bg_x = g_key_file_get_integer(layoutfile, "Global", "offset_x", &err); if (err) { g_error_free(err); err = NULL; } bg_y = g_key_file_get_integer(layoutfile, "Global", "offset_y", &err); if (err) { g_error_free(err); err = NULL; } } else { gpe_error_box(_("Button layout file is missing a global section.")); return FALSE; } btndefs = g_key_file_get_groups(layoutfile, &btncnt); if (btndefs) { for (i=0; i < btncnt; i++) { if (!strcmp(btndefs[i], "Global")) /* Ignore global section */ continue; buttondefs = realloc(buttondefs, (NUM_BUTTONS+1) * sizeof(t_buttondef)); buttondefs[NUM_BUTTONS].title = g_key_file_get_string(layoutfile, btndefs[i], "title", &err); if (err) { g_error_free(err); err = NULL; continue; } buttondefs[NUM_BUTTONS].symbol = g_key_file_get_string(layoutfile, btndefs[i], "symbol", &err); if (err) { g_error_free(err); err = NULL; continue; } buttondefs[NUM_BUTTONS].key = g_key_file_get_string(layoutfile, btndefs[i], "key", &err); if (err) { g_error_free(err); err = NULL; continue; } buttondefs[NUM_BUTTONS].modificator = g_key_file_get_string(layoutfile, btndefs[i], "modificator", &err); if (err) { g_error_free(err); err = NULL; continue; } buttondefs[NUM_BUTTONS].command = g_key_file_get_string(layoutfile, btndefs[i], "command", &err); if (err) { g_error_free(err); err = NULL; continue; } buttondefs[NUM_BUTTONS].x = g_key_file_get_integer(layoutfile, btndefs[i], "xpos", &err); if (err) { g_error_free(err); err = NULL; continue; } buttondefs[NUM_BUTTONS].y = g_key_file_get_integer(layoutfile, btndefs[i], "ypos", &err); if (err) { g_error_free(err); err = NULL; continue; } NUM_BUTTONS++; } g_strfreev(btndefs); } return TRUE; } void init_buttons (void) { FILE *fd; gchar *buffer = NULL; gchar *slash; gint i; size_t len; #warning todo correlate read settings with defined buttons, support combinations active_button = 0; /* default keylaunchrc in homedir */ keylaunchrc = g_strdup_printf ("%s/.keylaunchrc", getenv ("HOME")); /* if root or no keylaunchrc, we choose another */ if (!getuid() || access(keylaunchrc,R_OK)) { g_free(keylaunchrc); keylaunchrc = g_strdup ("/etc/keylaunchrc"); } /* read from configfile and set buttons */ fd = fopen (keylaunchrc, "r"); if (fd != NULL) { /* load from configfile */ while (getline(&buffer, &len, fd) > 0) { for (i = 0; i < NUM_BUTTONS; i++) if (strlen(buffer) && (buffer[0] !='#') && strstr(buffer, buttondefs[i].key) && !strstr(buffer, "???Held") && !strstr(buffer, "???Combine")) { slash = strrchr (buffer, ':'); if (slash && ((slash - buffer) > 0)) { slash++; if (slash[strlen(slash)-1] == '\n') slash[strlen(slash)-1] = 0; g_free(buttondefs[i].command); buttondefs[i].command = g_strdup(slash); } } } fclose (fd); } } void on_button_clicked (GtkButton * button, gpointer user_data) { ask_user_a_file ("/usr/bin", NULL, FileSelected, NULL, button); } void on_button_select (GtkButton * button, gpointer user_data) { gint nr = (gint)user_data; gint i; gchar *bname; if ((nr == active_button) || ((active_button < 0) && (active_button >= NUM_BUTTONS))) return; g_free(buttondefs[active_button].command); buttondefs[active_button].command = g_strdup(gtk_entry_get_text(GTK_ENTRY(self.edit))); gtk_entry_set_text(GTK_ENTRY(self.edit), buttondefs[nr].command); active_button = nr; bname = g_strdup_printf(PREFIX "/share/pixmaps/%s", buttondefs[nr].symbol); gtk_image_set_from_file(GTK_IMAGE(self.icon), bname); g_free(bname); for (i = 1; i < NUM_COMMANDS; i++) if (!strcmp(buttondefs[nr].command, commands[i].command)) { gtk_option_menu_set_history(GTK_OPTION_MENU(self.select), i); return; } gtk_option_menu_set_history(GTK_OPTION_MENU(self.select), 0); } void on_edit_changed (GtkWidget * edit, gpointer user_data) { gint i; if (menuselect) return; for (i = 1; i < NUM_COMMANDS; i++) if (!strcmp(buttondefs[active_button].command, commands[i].command)) { gtk_option_menu_set_history(GTK_OPTION_MENU(self.select), i); return; } gtk_option_menu_set_history(GTK_OPTION_MENU(self.select), 0); } void on_menu_select (GtkOptionMenu *menu, gpointer user_data) { gint pos = gtk_option_menu_get_history(menu); menuselect = TRUE; if ((pos > 0) && (commands[pos].command)) gtk_entry_set_text(GTK_ENTRY(self.edit), commands[pos].command); else gtk_entry_set_text(GTK_ENTRY(self.edit), ""); menuselect = FALSE; } GtkWidget * Keyctl_Build_Objects (void) { GtkWidget *vbox = gtk_vbox_new(FALSE, 0); GtkWidget *layout1 = gtk_layout_new(NULL, NULL); GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL); GtkWidget *bFile = gtk_button_new_from_stock(GTK_STOCK_OPEN); GtkWidget *table = gtk_table_new(3, 2, FALSE); GtkWidget *cmenu = gtk_menu_new(); gint i; self.buttons = NULL; commands_load(); if (!layout_load()) /* configuration available for current device? */ { GtkWidget *label; label = gtk_label_new (_("No button configuration available for this device.")); gtk_label_set_line_wrap (GTK_LABEL(label), TRUE); gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_CENTER); self.active = FALSE; return label; } self.active = TRUE; gtk_menu_set_screen(GTK_MENU(cmenu), NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_table_set_col_spacings(GTK_TABLE(table), 2); gtk_container_set_border_width (GTK_CONTAINER(table), 2); self.edit = gtk_entry_new(); if (gdk_screen_width() < 280) gtk_widget_set_size_request(self.edit, 110, -1); self.select = gtk_option_menu_new(); self.icon = gtk_image_new(); for (i = 0; i < NUM_COMMANDS; i++) gtk_menu_shell_append(GTK_MENU_SHELL(cmenu), gtk_menu_item_new_with_label(commands[i].title)); gtk_option_menu_set_menu(GTK_OPTION_MENU(self.select), cmenu); gtk_option_menu_set_history(GTK_OPTION_MENU(self.select), 0); gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, TRUE, 0); gtk_table_attach(GTK_TABLE(table),self.icon, 0, 1, 0, 2, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(table),self.edit, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(table),self.select, 1, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach(GTK_TABLE(table),bFile, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0); if (NUM_BUTTONS) { self.buttons = g_malloc(NUM_BUTTONS * sizeof(GtkWidget*)); self.buttons[0] = gtk_radio_button_new(NULL); for (i=1; i