summaryrefslogtreecommitdiff
path: root/capplets/file-types/file-types-capplet-dialogs.c
diff options
context:
space:
mode:
Diffstat (limited to 'capplets/file-types/file-types-capplet-dialogs.c')
-rw-r--r--capplets/file-types/file-types-capplet-dialogs.c690
1 files changed, 381 insertions, 309 deletions
diff --git a/capplets/file-types/file-types-capplet-dialogs.c b/capplets/file-types/file-types-capplet-dialogs.c
index 8af403ea7..c554c72b1 100644
--- a/capplets/file-types/file-types-capplet-dialogs.c
+++ b/capplets/file-types/file-types-capplet-dialogs.c
@@ -35,7 +35,9 @@
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-application-registry.h>
#include <libgnomevfs/gnome-vfs-mime-info.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+#include "libuuid/uuid.h"
#include "nautilus-mime-type-capplet.h"
#include "nautilus-mime-type-capplet-dialogs.h"
@@ -67,7 +69,8 @@ static edit_dialog_details *edit_component_details = NULL;
static void show_new_application_window (GtkWidget *button, GtkWidget *list);
static void show_edit_application_window (GtkWidget *button, GtkWidget *list);
static void delete_selected_application (GtkWidget *button, GtkWidget *list);
-static void add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, int position);
+static void add_item_to_application_list (GtkWidget *list, const char *id, const char *name, const char *mime_type,
+ gboolean user_owned, int position);
static void find_message_label_callback (GtkWidget *widget, gpointer callback_data);
static void find_message_label (GtkWidget *widget, const char *message);
@@ -139,12 +142,73 @@ application_button_toggled_callback (GtkToggleButton *button, gpointer user_data
}
static void
+insert_item (GtkList *list_widget, GtkListItem *item, int position)
+{
+ GList *singleton_list;
+
+ g_assert (GTK_IS_LIST (list_widget));
+ g_assert (GTK_IS_LIST_ITEM (item));
+
+ /* Due to GTK inheritance stupidity, the "Add" signal, which we
+ * rely on for widget sensitivity updates, is not sent if you
+ * use the GtkList API to add items. So when we add new items,
+ * which always go at the end, we must use the GtkContainer API.
+ */
+ if (position < 0) {
+ gtk_container_add (GTK_CONTAINER (list_widget), GTK_WIDGET (item));
+ } else {
+ singleton_list = g_list_prepend (NULL, item);
+ gtk_list_insert_items (list_widget, singleton_list, position);
+ /* This looks like a leak of a singleton_list, but believe it or not
+ * gtk_list takes ownership of the list of items.
+ */
+ }
+}
+
+static GtkListItem *
+create_application_list_item (const char *id, const char *name, const char *mime_type,
+ gboolean user_owned, GList *short_list)
+{
+ GtkWidget *list_item;
+ GtkWidget *hbox, *check_button, *label;
+
+ list_item = gtk_list_item_new ();
+
+ hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
+ gtk_container_add (GTK_CONTAINER (list_item), hbox);
+
+ check_button = gtk_check_button_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
+
+ label = gtk_label_new (name);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (list_item);
+
+ /* Save ID and mime type*/
+ gtk_object_set_data_full (GTK_OBJECT (check_button), "application_id", g_strdup (id), g_free);
+ gtk_object_set_data_full (GTK_OBJECT (check_button), "mime_type", g_strdup (mime_type), g_free);
+ gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (id), g_free);
+ gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
+ gtk_object_set_data (GTK_OBJECT (list_item), "user_owned", GINT_TO_POINTER(user_owned));
+
+ /* Check and see if component is in preferred list */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
+ application_is_in_list (id, short_list));
+
+ /* Connect to toggled signal */
+ gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
+ GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
+
+ return GTK_LIST_ITEM (list_item);
+}
+
+static void
populate_default_applications_list (GtkWidget *list, const char *mime_type)
{
GList *short_list, *app_list, *list_element;
GnomeVFSMimeApplication *application;
- GtkWidget *button, *list_item;
- GtkWidget *hbox, *label;
+ GtkListItem *list_item;
/* Get the application short list */
short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
@@ -156,43 +220,20 @@ populate_default_applications_list (GtkWidget *list, const char *mime_type)
application = list_element->data;
/* Create list item */
- list_item = gtk_list_item_new ();
-
- /* Create check button */
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (list_item), hbox);
-
- button = gtk_check_button_new ();
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
-
- label = gtk_label_new (application->name);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- /* Add list item to list */
- gtk_container_add (GTK_CONTAINER (list), list_item);
+ list_item = create_application_list_item (application->id, application->name,
+ mime_type,
+ gnome_vfs_application_is_user_owned_application (application),
+ short_list);
- /* Save ID and mime type*/
- gtk_object_set_data_full (GTK_OBJECT (button), "application_id", g_strdup (application->id), g_free);
- gtk_object_set_data_full (GTK_OBJECT (button), "mime_type", g_strdup (mime_type), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (application->id), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
+ insert_item (GTK_LIST (list), list_item, -1);
- /* Check and see if component is in preferred list */
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
- application_is_in_list (application->id, short_list));
-
- /* Connect to toggled signal */
- gtk_signal_connect (GTK_OBJECT (button), "toggled",
- GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
- }
+ }
gnome_vfs_mime_application_list_free (app_list);
}
- if (short_list != NULL) {
- gnome_vfs_mime_application_list_free (short_list);
- }
+ gnome_vfs_mime_application_list_free (short_list);
}
@@ -314,11 +355,17 @@ check_button_status (GtkList *list, GtkWidget *widget, ButtonHolder *button_hold
gtk_widget_set_sensitive (button_holder->delete_button, FALSE);
gtk_widget_set_sensitive (button_holder->edit_button, FALSE);
} else {
- gtk_widget_set_sensitive (button_holder->delete_button, TRUE);
gtk_widget_set_sensitive (button_holder->edit_button, TRUE);
}
}
+static void
+update_delete_button (GtkList *list, GtkWidget *widget, ButtonHolder *button_holder)
+{
+ gtk_widget_set_sensitive (button_holder->delete_button,
+ GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (widget), "user_owned")));
+}
+
/*
* initialize_edit_applications_dialog
@@ -342,6 +389,8 @@ initialize_edit_applications_dialog (const char *mime_type)
NULL,
NULL);
+ /* FIXME: dialog should be parented on Control Center window */
+
gtk_container_set_border_width (GTK_CONTAINER (edit_application_details->window), GNOME_PAD);
gtk_window_set_policy (GTK_WINDOW (edit_application_details->window), FALSE, TRUE, FALSE);
gtk_window_set_default_size (GTK_WINDOW (edit_application_details->window),
@@ -357,7 +406,7 @@ initialize_edit_applications_dialog (const char *mime_type)
main_vbox = GNOME_DIALOG (edit_application_details->window)->vbox;
/* Add label */
- label_text = g_strdup_printf (_("Select applications to appear in menu for mime type \"%s\""), mime_type);
+ label_text = g_strdup_printf (_("Select applications to appear in menu for MIME type \"%s\""), mime_type);
label = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -403,11 +452,12 @@ initialize_edit_applications_dialog (const char *mime_type)
/* Watch container so we can update buttons */
gtk_signal_connect (GTK_OBJECT (list), "add", check_button_status, button_holder);
gtk_signal_connect_full (GTK_OBJECT (list), "remove", check_button_status, NULL, button_holder,
- g_free, FALSE, FALSE);
+ g_free, FALSE, FALSE);
+ gtk_signal_connect (GTK_OBJECT (list), "select_child", update_delete_button, button_holder);
- populate_default_applications_list (list, mime_type);
-
gtk_widget_show_all (main_vbox);
+
+ populate_default_applications_list (list, mime_type);
}
@@ -447,7 +497,7 @@ initialize_edit_components_dialog (const char *mime_type)
main_vbox = GNOME_DIALOG (edit_component_details->window)->vbox;
/* Add label */
- label_text = g_strdup_printf (_("Select views to appear in menu for mime type \"%s\""), mime_type);
+ label_text = g_strdup_printf (_("Select views to appear in menu for MIME type \"%s\""), mime_type);
label = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -482,19 +532,13 @@ show_edit_applications_dialog (const char *mime_type)
if (edit_application_details == NULL) {
initialize_edit_applications_dialog (mime_type);
}
-
- switch(gnome_dialog_run (GNOME_DIALOG (edit_application_details->window))) {
- case 0:
- nautilus_mime_type_capplet_update_application_info (mime_type);
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_application_details->window);
- break;
-
- case 1:
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_application_details->window);
- break;
- }
+
+ /* FIXME: This is a modal dialog with no Cancel button, so the close box
+ * has to do the same thing as the OK button, which is pretty darn confusing.
+ * It would be better to make it modeless someday.
+ */
+ gnome_dialog_run_and_close (GNOME_DIALOG (edit_application_details->window));
+ nautilus_mime_type_capplet_update_application_info (mime_type);
}
@@ -511,18 +555,13 @@ show_edit_components_dialog (const char *mime_type)
initialize_edit_components_dialog (mime_type);
}
- switch(gnome_dialog_run (GNOME_DIALOG (edit_component_details->window))) {
- case 0:
- nautilus_mime_type_capplet_update_viewer_info (mime_type);
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_component_details->window);
- break;
-
- case 1:
- /* Delete the dialog so the lists are repopulated on next lauch */
- gtk_widget_destroy (edit_component_details->window);
- break;
- }
+ /* FIXME: This is a modal dialog with no Cancel button, so the close box
+ * has to do the same thing as the OK button, which is pretty darn confusing.
+ * It would be better to make it modeless someday.
+ */
+ gnome_dialog_run_and_close (GNOME_DIALOG (edit_component_details->window));
+
+ nautilus_mime_type_capplet_update_viewer_info (mime_type);
}
@@ -688,6 +727,30 @@ display_upper_case_dialog (void)
gnome_dialog_run_and_close (dialog);
}
+/* Do some basic validation of the text entry and enable the OK button if the text is
+ * determined to be a valid string.
+ */
+static void
+validate_text_and_update_button (GtkEntry *entry, gpointer data)
+{
+ char *text, *token;
+ gboolean sensitize;
+
+ sensitize = TRUE;
+
+ text = gtk_entry_get_text (entry);
+ if (text == NULL) {
+ sensitize = FALSE;
+ } else {
+ token = strtok (text, " ");
+ if (token == NULL || strlen (token) <= 0) {
+ /* Entered text is invalid as best as we can detect. */
+ sensitize = FALSE;
+ }
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (data), sensitize);
+}
char *
nautilus_mime_type_capplet_show_new_mime_window (void)
@@ -696,8 +759,6 @@ nautilus_mime_type_capplet_show_new_mime_window (void)
GtkWidget *mime_entry;
GtkWidget *label;
GtkWidget *desc_entry;
- GtkWidget *hbox;
- GtkWidget *vbox;
const char *description;
char *mime_type, *tmp_str, c;
gboolean upper_case_alert;
@@ -705,70 +766,62 @@ nautilus_mime_type_capplet_show_new_mime_window (void)
mime_type = NULL;
upper_case_alert = FALSE;
- dialog = gnome_dialog_new (_("Add Mime Type"), GNOME_STOCK_BUTTON_OK,
+ dialog = gnome_dialog_new (_("Add MIME Type"), GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL, NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 1);
- label = gtk_label_new (_("Add a new Mime Type\n"
- "For example: image/tiff; text/x-scheme"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new (_("Mime Type:"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ label = gtk_label_new (_("New MIME type (e.g. image/x-thumper):"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
+
mime_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), mime_entry, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), mime_entry, TRUE, TRUE, 0);
-
- vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), vbox, FALSE, FALSE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD_SMALL);
- label = gtk_label_new (_("Type in a description for this mime-type."));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Description:")), FALSE, FALSE, 0);
+ label = gtk_label_new (_("Description (e.g. Thumper image):"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), label, TRUE, TRUE, 0);
+
desc_entry = gtk_entry_new ();
- gtk_box_pack_start (GTK_BOX (hbox), desc_entry, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), desc_entry, TRUE, TRUE, 0);
+ /* Set up text entry validation signal */
+ gtk_signal_connect (GTK_OBJECT (mime_entry), "changed",
+ GTK_SIGNAL_FUNC (validate_text_and_update_button), GNOME_DIALOG (dialog)->buttons->data);
- gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
+ /* Set initial OK button state to desensitized */
+ gtk_widget_set_sensitive (GTK_WIDGET (GNOME_DIALOG (dialog)->buttons->data), FALSE);
+
+ /* Set focus to text entry widget */
+ gtk_widget_grab_focus (mime_entry);
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- mime_type = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
- g_assert (mime_type != NULL);
-
- /* Handle illegal mime types as best we can */
- for (tmp_str = mime_type; (c = *tmp_str) != '\0'; tmp_str++) {
- if (isascii (c) && isupper (c)) {
- *tmp_str = tolower (c);
- upper_case_alert = TRUE;
- }
- }
-
- description = gtk_entry_get_text (GTK_ENTRY (desc_entry));
-
- /* Add new mime type here */
- if (strlen (mime_type) > 3) {
- gnome_vfs_mime_set_value (mime_type,
- "description",
- description);
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
+ mime_type = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
+ g_assert (mime_type != NULL);
+
+ /* Handle illegal mime types as best we can */
+ for (tmp_str = mime_type; (c = *tmp_str) != '\0'; tmp_str++) {
+ if (isascii ((guchar) c) && isupper ((guchar) c)) {
+ *tmp_str = tolower (c);
+ upper_case_alert = TRUE;
}
- /* Fall through to close dialog */
- break;
-
- case 1:
- default:
- break;
+ }
+
+ description = gtk_entry_get_text (GTK_ENTRY (desc_entry));
+
+ /* Add new mime type here */
+ if (strlen (mime_type) > 3) {
+ /* This call creates the key */
+ gnome_vfs_mime_set_registered_type_key (mime_type,
+ "description",
+ description);
+
+ /* Ths call sets the user information */
+ gnome_vfs_mime_set_value (mime_type,
+ "description",
+ description);
+ }
}
gnome_dialog_close (GNOME_DIALOG (dialog));
@@ -793,6 +846,13 @@ add_extension_clicked (GtkWidget *widget, gpointer data)
extension_list = GTK_LIST (data);
new_extension = nautilus_mime_type_capplet_show_new_extension_window ();
+
+ /* Filter out bogus extensions */
+ if (new_extension == NULL || strlen (new_extension) <= 0 || new_extension[0] == ' ') {
+ g_free (new_extension);
+ return;
+ }
+
new_list_item = gtk_list_item_new_with_label (new_extension);
gtk_widget_show (new_list_item);
@@ -874,14 +934,16 @@ get_extensions_from_gtk_list (GtkList *list)
}
char *
-nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
+nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type, gboolean *new_list)
{
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *list;
- char *extensions_list;
+ char *extensions_list_str;
+ *new_list = FALSE;
+
dialog = gnome_dialog_new (_("File Extensions "),
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
@@ -933,7 +995,6 @@ nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
extensions_list = gnome_vfs_mime_get_extensions_list (mime_type);
-
if (extensions_list != NULL) {
widget_list = NULL;
for (temp = extensions_list; temp != NULL; temp = temp->next) {
@@ -950,22 +1011,21 @@ nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- extensions_list = get_extensions_from_gtk_list (GTK_LIST (list));
- if (extensions_list == NULL) {
- extensions_list = g_strdup ("");
- }
- break;
- case 1:
- default:
- extensions_list = g_strdup ("");
- break;
- }
+ extensions_list_str = NULL;
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
+ *new_list = TRUE;
+ extensions_list_str = get_extensions_from_gtk_list (GTK_LIST (list));
+ if (extensions_list_str == NULL) {
+ extensions_list_str = g_strdup ("");
+ }
+ }
+ if (extensions_list_str == NULL) {
+ extensions_list_str = g_strdup ("");
+ }
gnome_dialog_close (GNOME_DIALOG (dialog));
- return extensions_list;
+ return extensions_list_str;
}
@@ -982,7 +1042,9 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
GNOME_STOCK_BUTTON_CANCEL, NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);
gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
- label = gtk_label_new (_("Type in the extensions for this mime-type.\nFor example: .html, .htm"));
+ label = gtk_label_new (_("Type in the extensions for this mime-type (without dot).\n"
+ "You can enter several extensions seperated by a space,\n"
+ "for example: html htm"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
@@ -998,17 +1060,13 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
- gtk_window_set_focus (GTK_WINDOW (dialog), mime_entry);
+ gtk_widget_grab_focus (mime_entry);
- new_extension = g_strdup ("");
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- new_extension = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
- case 1:
- break;
- default:
- break;
- }
+ if (gnome_dialog_run (GNOME_DIALOG (dialog)) == GNOME_OK) {
+ new_extension = g_strdup (gtk_entry_get_text (GTK_ENTRY (mime_entry)));
+ } else {
+ new_extension = g_strdup ("");
+ }
gnome_dialog_close (GNOME_DIALOG (dialog));
@@ -1020,17 +1078,19 @@ nautilus_mime_type_capplet_show_new_extension_window (void)
* Create or update a GnomeVFSMimeApplication and register
* it with the mime database.
*/
-static void
+static char *
add_or_update_application (GtkWidget *list, const char *name, const char *command,
gboolean multiple, gboolean expects_uris,
gboolean update)
{
GnomeVFSMimeApplication app, *original;
const char *mime_type;
-
+ uuid_t app_uuid;
+ char app_uuid_string[100];
+
/* Check for empty strings. Command can be empty. */
if (name[0] == '\0') {
- return;
+ return NULL;
}
mime_type = nautilus_mime_type_capplet_get_selected_item_mime_type ();
@@ -1039,7 +1099,11 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
/* It's ok to cast, we don't modify the application
* structure and thus the name/command, this should really
* use the application registry explicitly */
- app.id = (char *)name;
+
+ /* Generate unique application id */
+ uuid_generate(app_uuid);
+ uuid_unparse(app_uuid, app_uuid_string);
+ app.id = app_uuid_string;
app.name = (char *)name;
app.command = (char *)command;
app.can_open_multiple_files = multiple;
@@ -1049,7 +1113,7 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
app.requires_terminal = FALSE;
if (update) {
- original = gnome_vfs_mime_application_new_from_id (name);
+ original = gnome_vfs_mime_application_new_from_id (app.id);
if (original == NULL) {
const char *original_id;
GList *selection;
@@ -1059,20 +1123,20 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
/* If there isn't a selection we cannot allow an edit */
selection = GTK_LIST (list)->selection;
if (selection == NULL || g_list_length (selection) <= 0) {
- return;
+ return NULL;
}
/* Get application id and info */
item = GTK_LIST_ITEM (selection->data);
if (item == NULL) {
- return;
+ return NULL;
}
original_id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
if (original_id == NULL) {
- return;
+ return NULL;
}
-
+
/* Remove original application data */
gnome_vfs_application_registry_remove_mime_type (original_id, mime_type);
gnome_vfs_application_registry_sync ();
@@ -1083,77 +1147,122 @@ add_or_update_application (GtkWidget *list, const char *name, const char *comman
gtk_container_remove (GTK_CONTAINER (list), GTK_WIDGET (item));
/* Add new widget and restore position */
- add_item_to_application_list (list, name, mime_type, position);
+ add_item_to_application_list (list, original_id, name, mime_type,
+ gnome_vfs_application_is_user_owned_application (original),
+ position);
}
}
gnome_vfs_application_registry_save_mime_application (&app);
- gnome_vfs_application_registry_add_mime_type (name, mime_type);
+ gnome_vfs_application_registry_add_mime_type (app.id, mime_type);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_add_application_to_short_list (mime_type, app.id);
+
+ return g_strdup (app.id);
}
static void
-add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, int position)
+add_item_to_application_list (GtkWidget *list, const char *id, const char *name, const char *mime_type,
+ gboolean user_owned, int position)
{
- GtkWidget *check_button, *list_item, *hbox, *label;
-
- /* Create list item */
- list_item = gtk_list_item_new ();
-
- /* Create check button */
- hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (list_item), hbox);
-
- check_button = gtk_check_button_new ();
- gtk_box_pack_start (GTK_BOX (hbox), check_button, FALSE, FALSE, 0);
+ GtkListItem *list_item;
+ GList *short_list;
- label = gtk_label_new (name);
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
- /* Add list item to list */
- if (position == -1) {
- gtk_container_add (GTK_CONTAINER (list), list_item);
- } else {
- GList *items;
- items = g_list_alloc ();
- items->data = list_item;
- gtk_list_insert_items (GTK_LIST (list), items, position);
- gtk_list_select_child (GTK_LIST (list), list_item);
+ short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
+ list_item = create_application_list_item (id, name, mime_type, user_owned, short_list);
+ gnome_vfs_mime_application_list_free (short_list);
+
+ insert_item (GTK_LIST (list), list_item, position);
+ gtk_list_select_child (GTK_LIST (list), GTK_WIDGET (list_item));
+}
+
+static gboolean
+handle_invalid_application_input (GtkWindow *parent_window, const char *name, const char *command)
+{
+ char *message;
+ char *stripped_name;
+ GnomeDialog *error_dialog;
+ gboolean error_in_name;
+
+ message = NULL;
+ error_in_name = FALSE;
+
+ stripped_name = g_strstrip (g_strdup (name));
+
+ if (strlen (stripped_name) == 0) {
+ message = g_strdup (_("You must enter a name."));
+ error_in_name = TRUE;
+ } else if (strlen (command) == 0) {
+ message = g_strdup (_("You must enter a command."));
+ } else if (!gnome_vfs_is_executable_command_string (command)) {
+ if (command[0] == '/') {
+ /* FIXME: Should strip parameters off before using in this message. */
+ /* FIXME: Should use separate messages for doesn't exist/isn't executable. */
+ /* Both of these FIXMEs would need to handle quoting to work correctly,
+ * since otherwise a space might be part of path or separator before parameters.
+ */
+ /* FIXME: Should use some line-wrapping technology a la nautilus-stock-dialogs.c */
+ message = g_strdup_printf
+ (_("\"%s\" does not exist or is not executable.\n"
+ "Check your spelling and make sure you have\n"
+ "the right permissions to execute this file."), command);
+ } else {
+ /* FIXME: Should strip parameters off before using in this message */
+ message = g_strdup_printf
+ (_("The command \"%s\" cannot be found.\n"
+ "You must use a command that can work from any command line."), command);
+ }
}
-
- gtk_widget_show_all (list);
-
- /* Save ID and mime type*/
- gtk_object_set_data_full (GTK_OBJECT (check_button), "application_id", g_strdup (name), g_free);
- gtk_object_set_data_full (GTK_OBJECT (check_button), "mime_type", g_strdup (mime_type), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "application_id", g_strdup (name), g_free);
- gtk_object_set_data_full (GTK_OBJECT (list_item), "mime_type", g_strdup (mime_type), g_free);
- /* Check and see if component is in preferred list */
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
+ g_free (stripped_name);
+
+ if (message != NULL) {
+ error_dialog = GNOME_DIALOG (gnome_error_dialog_parented (message,
+ parent_window));
+ gtk_window_set_title (GTK_WINDOW (error_dialog),
+ error_in_name
+ ? _("Bad Application Name")
+ : _("Bad Application Command"));
+
+ gnome_dialog_run (error_dialog);
+ g_free (message);
+
+ return TRUE;
+ }
- /* Connect to toggled signal */
- gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
- GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
+ return FALSE;
}
+
static void
-show_new_application_window (GtkWidget *button, GtkWidget *list)
+run_edit_or_new_application_dialog (const char *mime_type, GtkWidget *list, GnomeVFSMimeApplication *application)
{
- GtkWidget *app_entry, *command_entry;
GtkWidget *dialog;
+ GtkWidget *app_entry, *command_entry;
GtkWidget *label;
GtkWidget *behavior_frame, *frame_vbox;
GtkWidget *multiple_check_box, *uri_check_box;
GtkWidget *table;
- char *name, *command, *mime_type;
- gboolean multiple, uri;
-
- dialog = gnome_dialog_new (_("New Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
-
+ gboolean initial_toggle_state;
+ const char *name;
+ const char *command;
+ int dialog_result;
+ gboolean entry_validated;
+ char *invalid_entry_message, *app_id;
+
+ g_assert (mime_type != NULL || application != NULL);
+ g_assert (GTK_IS_WIDGET (list));
+
+ dialog = gnome_dialog_new (
+ application == NULL
+ ? _("Add Application")
+ : _("Edit Application"),
+ GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
+
+ /* FIXME: Dialog should be parented on Edit Applications dialog */
+
/* Create table */
- table = gtk_table_new (3, 2, FALSE);
+ table = gtk_table_new (4, 2, FALSE);
gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog)->vbox), table);
gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
@@ -1161,21 +1270,26 @@ show_new_application_window (GtkWidget *button, GtkWidget *list)
/* Application Name label and entry */
label = gtk_label_new (_("Application Name:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults ( GTK_TABLE (table), label, 0, 1, 0, 1);
+ gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
app_entry = gtk_entry_new ();
gtk_table_attach_defaults ( GTK_TABLE (table), app_entry, 1, 2, 0, 1);
+ if (application != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (app_entry), application->name);
+ }
/* Application Command label and entry */
label = gtk_label_new (_("Application Command:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults ( GTK_TABLE (table), label, 0, 1, 1, 2);
+ gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
command_entry = gtk_entry_new ();
- gtk_table_attach_defaults ( GTK_TABLE (table), command_entry, 1, 2, 1, 2);
-
+ gtk_table_attach_defaults (GTK_TABLE (table), command_entry, 1, 2, 1, 2);
+ if (application != NULL) {
+ gtk_entry_set_text (GTK_ENTRY (command_entry), application->command);
+ }
+
/* Open Behavior frame */
- /* FIXME bugzilla.eazel.com 6066: Need to add expected uri schemes */
behavior_frame = gtk_frame_new (_("Open Behavior"));
gtk_table_attach_defaults ( GTK_TABLE (table), behavior_frame, 0, 2, 2, 3);
@@ -1184,52 +1298,70 @@ show_new_application_window (GtkWidget *button, GtkWidget *list)
multiple_check_box = gtk_check_button_new_with_label (_("Can open multiple files"));
gtk_box_pack_start (GTK_BOX (frame_vbox), multiple_check_box, FALSE, FALSE, 0);
+ initial_toggle_state = application == NULL
+ ? FALSE
+ : application->can_open_multiple_files;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (multiple_check_box), initial_toggle_state);
- uri_check_box = gtk_check_button_new_with_label (_("Expects URIs as arguments"));
+ /* FIXME bugzilla.eazel.com 6066: This needs to be three options now: "yes", "no", and "use uris for non-file locations" */
+ uri_check_box = gtk_check_button_new_with_label (_("Can open from URI"));
gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
-
-
+ initial_toggle_state = application == NULL
+ ? FALSE
+ : application->expects_uris;
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uri_check_box), initial_toggle_state);
+
+
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
- gtk_window_set_focus (GTK_WINDOW (dialog), app_entry);
+ gtk_widget_grab_focus (app_entry);
+
+ do {
+ dialog_result = gnome_dialog_run (GNOME_DIALOG (dialog));
+ entry_validated = FALSE;
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
+ if (dialog_result == GNOME_OK) {
name = gtk_entry_get_text (GTK_ENTRY (app_entry));
command = gtk_entry_get_text (GTK_ENTRY (command_entry));
- multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box));
- uri = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box));
-
- if (strlen (name) > 0 && strlen (command) > 0) {
- mime_type = gtk_object_get_data (GTK_OBJECT (button), "mime_type");
- add_or_update_application (list,
- gtk_entry_get_text (GTK_ENTRY (app_entry)),
- gtk_entry_get_text (GTK_ENTRY (command_entry)),
-
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
- FALSE);
- add_item_to_application_list (list, name, mime_type, -1);
+
+ invalid_entry_message = NULL;
+
+ if (!handle_invalid_application_input (GTK_WINDOW (dialog), name, command)) {
+ entry_validated = TRUE;
+ app_id = add_or_update_application (list,
+ name,
+ command,
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
+ application != NULL);
+ if (application == NULL && app_id != NULL) {
+ add_item_to_application_list (list, app_id, name, mime_type, TRUE, -1);
+ }
+ g_free (app_id);
}
- case 1:
- gtk_widget_destroy (dialog);
- break;
-
- default:
- break;
- }
+ }
+ } while (dialog_result == GNOME_OK && !entry_validated);
+
+ /* FIXME: Close box is treated like Cancel, which loses user changes silently.
+ * Would be better to either do nothing at all (force use of OK or Cancel) or
+ * even put up a little dialog telling them they have to use OK or Cancel.
+ * Too bad we can't prevent the close box from appearing. Window Managers suck.
+ */
+ if (dialog_result >= 0) {
+ gnome_dialog_close (GNOME_DIALOG (dialog));
+ }
}
static void
+show_new_application_window (GtkWidget *button, GtkWidget *list)
+{
+ run_edit_or_new_application_dialog (gtk_object_get_data (GTK_OBJECT (button), "mime_type"), list, NULL);
+}
+
+static void
show_edit_application_window (GtkWidget *button, GtkWidget *list)
{
- GtkWidget *app_entry, *command_entry;
- GtkWidget *dialog;
- GtkWidget *label;
- GtkWidget *behavior_frame, *frame_vbox;
- GtkWidget *multiple_check_box, *uri_check_box;
- GtkWidget *table;
GList *selection;
const char *id;
GnomeVFSMimeApplication *application;
@@ -1257,78 +1389,16 @@ show_edit_application_window (GtkWidget *button, GtkWidget *list)
return;
}
- dialog = gnome_dialog_new (_("Edit Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
-
- /* Create table */
- table = gtk_table_new (4, 2, FALSE);
- gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (dialog)->vbox), table);
- gtk_table_set_row_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
- gtk_table_set_col_spacings (GTK_TABLE (table), GNOME_PAD_SMALL);
-
- /* Application Name label and entry */
- label = gtk_label_new (_("Application Name:"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
-
- app_entry = gtk_entry_new ();
- gtk_table_attach_defaults ( GTK_TABLE (table), app_entry, 1, 2, 0, 1);
- gtk_entry_set_text (GTK_ENTRY (app_entry), application->name);
+ run_edit_or_new_application_dialog (NULL, list, application);
- /* Application Command label and entry */
- label = gtk_label_new (_("Application Command:"));
- gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
- gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
-
- command_entry = gtk_entry_new ();
- gtk_entry_set_text (GTK_ENTRY (command_entry), application->command);
- gtk_table_attach_defaults (GTK_TABLE (table), command_entry, 1, 2, 1, 2);
-
- /* Open Behavior frame */
- behavior_frame = gtk_frame_new (_("Open Behavior"));
- gtk_table_attach_defaults ( GTK_TABLE (table), behavior_frame, 0, 2, 2, 3);
-
- frame_vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
- gtk_container_add (GTK_CONTAINER (behavior_frame), frame_vbox);
-
- multiple_check_box = gtk_check_button_new_with_label (_("Can open multiple files"));
- gtk_box_pack_start (GTK_BOX (frame_vbox), multiple_check_box, FALSE, FALSE, 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (multiple_check_box), application->can_open_multiple_files);
-
- /* FIXME bugzilla.eazel.com 6066: This needs to be three options now: "yes", "no", and "use uris for non-file locations" */
- uri_check_box = gtk_check_button_new_with_label (_("Can open from URI"));
- gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (uri_check_box), application->expects_uris);
-
-
- gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
-
- /* Set focus to text entry widget */
- gtk_window_set_focus (GTK_WINDOW (dialog), app_entry);
-
- switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
- case 0:
- add_or_update_application (list,
- gtk_entry_get_text (GTK_ENTRY (app_entry)),
- gtk_entry_get_text (GTK_ENTRY (command_entry)),
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (multiple_check_box)),
- gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (uri_check_box)),
- TRUE);
-
- case 1:
- gnome_vfs_mime_application_free (application);
- gtk_widget_destroy (dialog);
- break;
-
- default:
- break;
- }
+ gnome_vfs_mime_application_free (application);
}
static void
delete_selected_application (GtkWidget *button, GtkWidget *list)
{
GtkListItem *item;
- const char *mime_type, *name;
+ const char *mime_type, *id;
GList *selection;
/* Get selected list item */
@@ -1342,14 +1412,16 @@ delete_selected_application (GtkWidget *button, GtkWidget *list)
return;
}
- name = gtk_object_get_data (GTK_OBJECT (item), "application_id");
+ g_return_if_fail (GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (item), "user_owned")));
+
+ id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
mime_type = gtk_object_get_data (GTK_OBJECT (item), "mime_type");
- /* Remove mime data */
- if (name != NULL && mime_type != NULL) {
- gnome_vfs_application_registry_remove_mime_type (name, mime_type);
+ /* Remove application if it is user owned */
+ if (id != NULL && mime_type != NULL) {
+ gnome_vfs_application_registry_remove_mime_type (id, mime_type);
gnome_vfs_application_registry_sync ();
- gnome_vfs_mime_remove_application_from_short_list (mime_type, name);
+ gnome_vfs_mime_remove_application_from_short_list (mime_type, id);
}
/* Remove widget from list */