gnome-control-center/capplets/file-types/mime-edit-dialog.c
Jody Goldberg b4995826e8 http://bugzilla.gnome.org/show_bug.cgi?id=85397
2002-06-15  Jody Goldberg <jody@gnome.org>

	http://bugzilla.gnome.org/show_bug.cgi?id=85397
	http://bugzilla.gnome.org/show_bug.cgi?id=84545
	* mime-types-model.c (mime_types_model_get_value) :
	  gtk_tree_view_search_equal_func does not like NULL.
	(IS_CATEGORY) : check for NULL.
	* file-types-capplet.c (create_dialog) : search the description not
	  the mime type.

2002-06-08  Jody Goldberg <jody@gnome.org>

	* mime-types-model.c (IS_CATEGORY) : test for null in case we are
	  stupid.

2002-06-07  Jody Goldberg <jody@gnome.org>

	* file-types-capplet.c (dialog_done_cb) : no need to save things
	  again.  The only caller had already done that.

	* mime-type-info.c (mime_type_info_save) : Don't mess with the
	  application here, it should already be setup.  However, be really
	  really anal about verifying it because I do not trust the
	  surrounding code or know it well enough to trust it.  Make sure that
	  the assigned app is on the short list of associated apps.

	* mime-category-edit-dialog.c (store_data) : Use
	  mime_edit_dialog_get_app.
	* mime-edit-dialog.c (store_data) : Use it here too.
	(mime_edit_dialog_get_app) : new.  split some duplicated code out of
	  the type and category dialogs and move it here.  Then make it
	  readable and less stupid about creating copies of existing
	  applications.  While we're at it have it handle the creation of new
	  applications, merging commands with existing applications and other
	  useful stuff.

2002-06-07  Jody Goldberg <jody@gnome.org>

	* mime-category-edit-dialog.c (store_data) : clarify and remove the
	  custom flag.

	* mime-type-info.c (mime_category_info_using_custom_app) : delete.
	(mime_type_info_using_custom_app) : delete.

	* mime-edit-dialog.c (validate_data) : correct the warning about
	  invalid type, we would _not_ create one for the user :-(
	  Allow a user to optionally overwrite an existing mime type.
	  This is useful when editing.
	* mime-edit-dialog.c (store_data) : clarify and remove the custom flag.


2002-06-10  Jody Goldberg <jody@gnome.org>

	* accessibility-keyboard.c : tweak the layout as requested and adjust
	  the max slowkey delay to 500 to avoid losing the keyboard due to some
	  sort of an X problem.

2002-06-13  Jody Goldberg <jody@gnome.org>

	* gnome-keyboard-properties.c (accessibility_button_clicked) : produce
	  a better warning for failure to launch the keyboard accessibility
	  capplet.
2002-06-18 18:55:14 +00:00

953 lines
29 KiB
C

/* -*- mode: c; style: linux -*- */
/* mime-edit-dialog.c
* Copyright (C) 2001 Ximian, Inc.
*
* Written by Bradford Hovinen <hovinen@ximian.com>
*
* 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, 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.
*
* 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.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include <glade/glade.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-application-registry.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include "mime-edit-dialog.h"
#include "mime-types-model.h"
#include "libuuid/uuid.h"
#define WID(x) (glade_xml_get_widget (dialog->p->dialog_xml, x))
enum {
DONE,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_MODEL,
PROP_INFO,
PROP_IS_ADD
};
struct _MimeEditDialogPrivate
{
MimeTypeInfo *info;
GladeXML *dialog_xml;
GtkWidget *dialog_win;
GtkTreeStore *ext_store;
gboolean is_add;
GtkTreeModel *model;
gboolean component_active : 1;
gboolean default_action_active : 1;
gboolean custom_action : 1;
gboolean use_cat_dfl : 1;
};
static guint dialog_signals[LAST_SIGNAL];
static GObjectClass *parent_class;
static void mime_edit_dialog_init (MimeEditDialog *mime_edit_dialog,
MimeEditDialogClass *class);
static void mime_edit_dialog_class_init (MimeEditDialogClass *class);
static void mime_edit_dialog_set_prop (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void mime_edit_dialog_get_prop (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void mime_edit_dialog_dispose (GObject *object);
static void mime_edit_dialog_finalize (GObject *object);
static void fill_dialog (MimeEditDialog *dialog);
static void setup_add_dialog (MimeEditDialog *dialog);
static void populate_component_list (MimeEditDialog *dialog);
static void populate_application_list (MimeEditDialog *dialog);
static void populate_extensions_list (MimeEditDialog *dialog);
static void add_ext_cb (MimeEditDialog *dialog);
static void remove_ext_cb (MimeEditDialog *dialog);
static void choose_cat_cb (MimeEditDialog *dialog);
static void default_action_changed_cb (MimeEditDialog *dialog);
static void use_category_defaults_toggled_cb (MimeEditDialog *dialog,
GtkToggleButton *tb);
static void response_cb (MimeEditDialog *dialog,
gint response_id);
static void update_sensitivity (MimeEditDialog *dialog);
GType
mime_edit_dialog_get_type (void)
{
static GType mime_edit_dialog_type = 0;
if (!mime_edit_dialog_type) {
GTypeInfo mime_edit_dialog_info = {
sizeof (MimeEditDialogClass),
(GBaseInitFunc) NULL,
NULL, /* GBaseFinalizeFunc */
(GClassInitFunc) mime_edit_dialog_class_init,
NULL, /* GClassFinalizeFunc */
NULL, /* user-supplied data */
sizeof (MimeEditDialog),
0, /* n_preallocs */
(GInstanceInitFunc) mime_edit_dialog_init,
NULL
};
mime_edit_dialog_type =
g_type_register_static (G_TYPE_OBJECT,
"MimeEditDialog",
&mime_edit_dialog_info, 0);
}
return mime_edit_dialog_type;
}
/**
* mime_edit_editable_enters: Make the "activate" signal of an editable click
* the default dialog button.
* @dialog: dialog to affect.
* @editable: Editable to affect.
*
* This is a literal copy of gnome_dialog_editable_enters, but not restricted
* to GnomeDialogs.
*
* Normally if there's an editable widget (such as #GtkEntry) in your
* dialog, pressing Enter will activate the editable rather than the
* default dialog button. However, in most cases, the user expects to
* type something in and then press enter to close the dialog. This
* function enables that behavior.
*
**/
static void
mime_edit_editable_enters (MimeEditDialog *dialog, GtkEditable *editable)
{
g_signal_connect_swapped (G_OBJECT (editable),
"activate",
G_CALLBACK (gtk_window_activate_default),
GTK_WINDOW (dialog->p->dialog_win));
}
static void
mime_edit_dialog_init (MimeEditDialog *dialog, MimeEditDialogClass *class)
{
GtkSizeGroup *size_group;
GtkTreeView *view;
GtkCellRenderer *renderer;
dialog->p = g_new0 (MimeEditDialogPrivate, 1);
dialog->p->dialog_xml = glade_xml_new
(GNOMECC_DATA_DIR "/interfaces/file-types-properties.glade", "edit_widget", NULL);
size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget (size_group, WID ("description_label"));
gtk_size_group_add_widget (size_group, WID ("mime_type_label"));
gtk_size_group_add_widget (size_group, WID ("category_label"));
size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget (size_group, WID ("component_label"));
gtk_size_group_add_widget (size_group, WID ("default_action_label"));
gtk_size_group_add_widget (size_group, WID ("program_label"));
dialog->p->ext_store = gtk_tree_store_new (1, G_TYPE_STRING);
view = GTK_TREE_VIEW (WID ("ext_list"));
gtk_tree_view_set_model (view, GTK_TREE_MODEL (dialog->p->ext_store));
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes (view, -1, _("Extension"), renderer, "text", 0, NULL);
dialog->p->dialog_win = gtk_dialog_new_with_buttons
(_("Edit file type"), NULL, -1,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog->p->dialog_win),
GTK_RESPONSE_OK);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->p->dialog_win)->vbox), WID ("edit_widget"), TRUE, TRUE, 0);
g_signal_connect_swapped (G_OBJECT (WID ("add_ext_button")), "clicked", (GCallback) add_ext_cb, dialog);
g_signal_connect_swapped (G_OBJECT (WID ("remove_ext_button")), "clicked", (GCallback) remove_ext_cb, dialog);
g_signal_connect_swapped (G_OBJECT (WID ("choose_button")), "clicked", (GCallback) choose_cat_cb, dialog);
g_signal_connect_swapped (G_OBJECT (WID ("default_action_select")), "changed", (GCallback) default_action_changed_cb, dialog);
g_signal_connect_swapped (G_OBJECT (WID ("use_category_defaults_toggle")), "toggled",
(GCallback) use_category_defaults_toggled_cb, dialog);
g_signal_connect_swapped (G_OBJECT (dialog->p->dialog_win), "response", (GCallback) response_cb, dialog);
mime_edit_editable_enters (dialog, GTK_EDITABLE (WID ("description_entry")));
mime_edit_editable_enters (dialog, GTK_EDITABLE (WID ("mime_type_entry")));
mime_edit_editable_enters (dialog, GTK_EDITABLE (WID ("category_entry")));
}
static void
mime_edit_dialog_class_init (MimeEditDialogClass *class)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (class);
object_class->dispose = mime_edit_dialog_dispose;
object_class->finalize = mime_edit_dialog_finalize;
object_class->set_property = mime_edit_dialog_set_prop;
object_class->get_property = mime_edit_dialog_get_prop;
g_object_class_install_property
(object_class, PROP_MODEL,
g_param_spec_object ("model",
_("Model"),
_("Underlying model to notify when Ok is clicked"),
gtk_tree_model_get_type (),
G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_INFO,
g_param_spec_pointer ("mime-type-info",
_("MIME type information"),
_("Structure with data on the MIME type"),
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
(object_class, PROP_IS_ADD,
g_param_spec_boolean ("is-add",
_("Is add dialog"),
_("True if this dialog is for adding a MIME type"),
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
dialog_signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class), 0,
G_STRUCT_OFFSET (MimeEditDialogClass, done),
NULL, NULL,
(GSignalCMarshaller) g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
parent_class = G_OBJECT_CLASS
(g_type_class_ref (G_TYPE_OBJECT));
}
static void
mime_edit_dialog_set_prop (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
MimeEditDialog *mime_edit_dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_MIME_EDIT_DIALOG (object));
mime_edit_dialog = MIME_EDIT_DIALOG (object);
switch (prop_id) {
case PROP_MODEL:
mime_edit_dialog->p->model = GTK_TREE_MODEL (g_value_get_object (value));
break;
case PROP_INFO:
if (g_value_get_pointer (value) != NULL) {
mime_edit_dialog->p->info = g_value_get_pointer (value);
fill_dialog (mime_edit_dialog);
gtk_widget_show_all (mime_edit_dialog->p->dialog_win);
}
break;
case PROP_IS_ADD:
mime_edit_dialog->p->is_add = g_value_get_boolean (value);
if (mime_edit_dialog->p->is_add) {
mime_edit_dialog->p->info = mime_type_info_new (NULL,
mime_edit_dialog->p->model);
setup_add_dialog (mime_edit_dialog);
gtk_window_set_title (GTK_WINDOW (mime_edit_dialog->p->dialog_win),
(_("Add file type")));
gtk_widget_show_all (mime_edit_dialog->p->dialog_win);
}
break;
default:
g_warning ("Bad property set");
break;
}
}
static void
mime_edit_dialog_get_prop (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
MimeEditDialog *mime_edit_dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_MIME_EDIT_DIALOG (object));
mime_edit_dialog = MIME_EDIT_DIALOG (object);
switch (prop_id) {
case PROP_MODEL:
g_value_set_object (value, G_OBJECT (mime_edit_dialog->p->model));
break;
case PROP_INFO:
g_value_set_pointer (value, mime_edit_dialog->p->info);
break;
default:
g_warning ("Bad property get");
break;
}
}
static void
mime_edit_dialog_dispose (GObject *object)
{
MimeEditDialog *dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_MIME_EDIT_DIALOG (object));
dialog = MIME_EDIT_DIALOG (object);
if (dialog->p->dialog_xml != NULL) {
g_object_unref (G_OBJECT (dialog->p->dialog_xml));
dialog->p->dialog_xml = NULL;
}
if (dialog->p->dialog_win != NULL) {
gtk_widget_destroy (GTK_WIDGET (dialog->p->dialog_win));
dialog->p->dialog_win = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
mime_edit_dialog_finalize (GObject *object)
{
MimeEditDialog *mime_edit_dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (IS_MIME_EDIT_DIALOG (object));
mime_edit_dialog = MIME_EDIT_DIALOG (object);
g_free (mime_edit_dialog->p);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
GObject *
mime_edit_dialog_new (GtkTreeModel *model, MimeTypeInfo *info)
{
return g_object_new (mime_edit_dialog_get_type (),
"model", model,
"mime-type-info", info,
NULL);
}
GObject *
mime_add_dialog_new (GtkTreeModel *model, GtkWindow *parent)
{
GObject *obj = g_object_new (mime_edit_dialog_get_type (),
"model", model, /* must be before is-add */
NULL);
g_object_set (obj,
"is-add", TRUE,
NULL);
if (parent != NULL)
gtk_window_set_transient_for (
GTK_WINDOW (MIME_EDIT_DIALOG (obj)->p->dialog_win),
parent);
return obj;
}
static void
safe_set_entry (MimeEditDialog *dialog, char const *widget, char const *txt)
{
GtkEntry *entry = GTK_ENTRY (WID (widget));
g_return_if_fail (entry != NULL);
if (txt == NULL)
txt = "";
gtk_entry_set_text (entry, txt);
}
static void
fill_dialog (MimeEditDialog *dialog)
{
g_return_if_fail (dialog->p->info != NULL);
mime_type_info_load_all (dialog->p->info);
safe_set_entry (dialog, "description_entry",
dialog->p->info->description);
safe_set_entry (dialog, "mime_type_entry",
dialog->p->info->mime_type);
safe_set_entry (dialog, "category_entry",
mime_type_info_get_category_name (dialog->p->info));
dialog->p->use_cat_dfl = dialog->p->info->use_category;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("use_category_defaults_toggle")), dialog->p->use_cat_dfl);
update_sensitivity (dialog);
gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (WID ("icon_entry")), mime_type_info_get_icon_path (dialog->p->info));
populate_component_list (dialog);
populate_application_list (dialog);
populate_extensions_list (dialog);
}
static void
setup_add_dialog (MimeEditDialog *dialog)
{
GtkWidget *menu, *item;
item = gtk_menu_item_new_with_label (_("None"));
menu = gtk_menu_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_option_menu_set_menu (GTK_OPTION_MENU (WID ("component_select")), menu);
item = gtk_menu_item_new_with_label (_("Custom"));
menu = gtk_menu_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_option_menu_set_menu (GTK_OPTION_MENU (WID ("default_action_select")), menu);
gtk_widget_set_sensitive (WID ("component_box"), FALSE);
gtk_widget_set_sensitive (WID ("default_action_box"), FALSE);
gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (WID ("icon_entry")),
gnome_vfs_icon_path_from_filename ("nautilus/i-regular-24.png"));
}
static void
populate_component_list (MimeEditDialog *dialog)
{
GList *component_list, *tmp;
GtkMenu *menu;
GtkWidget *menu_item;
GtkOptionMenu *component_select;
gchar *component_name;
Bonobo_ServerInfo *info, *default_component;
int found_idx = -1, i;
menu = GTK_MENU (gtk_menu_new ());
component_list = gnome_vfs_mime_get_all_components (dialog->p->info->mime_type);
/* FIXME: We are leaking the whole list here, but this will be the case until I know of an easy way to duplicate
* Bonobo_ServerInfo structures */
default_component = dialog->p->info->default_component;
for (tmp = component_list, i = 0; tmp != NULL; tmp = tmp->next, i++) {
info = tmp->data;
g_return_if_fail (info != NULL);
if (default_component != NULL &&
!strcmp (info->iid, default_component->iid))
found_idx = i;
component_name = mime_type_get_pretty_name_for_server (info);
menu_item = gtk_menu_item_new_with_label (component_name);
g_free (component_name);
/* Store copy of component name in item; free when item destroyed. */
g_object_set_data (G_OBJECT (menu_item),
"component", info);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
}
dialog->p->component_active = !(i == 0);
menu_item = gtk_menu_item_new_with_label (_("None"));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
if (found_idx < 0)
found_idx = i;
component_select = GTK_OPTION_MENU (WID ("component_select"));
gtk_option_menu_set_menu (component_select, GTK_WIDGET (menu));
gtk_option_menu_set_history (component_select, found_idx);
update_sensitivity (dialog);
}
static void
populate_application_list (MimeEditDialog *dialog)
{
GList *app_list, *tmp;
GtkMenu *menu;
GtkWidget *menu_item;
GtkOptionMenu *app_select;
GnomeVFSMimeApplication *app;
int found_idx = -1, i;
menu = GTK_MENU (gtk_menu_new ());
app_list = gnome_vfs_application_registry_get_applications (dialog->p->info->mime_type);
for (tmp = app_list, i = 0; tmp != NULL; tmp = tmp->next, i++) {
app = gnome_vfs_application_registry_get_mime_application (tmp->data);
if (dialog->p->info->default_action != NULL &&
dialog->p->info->default_action->id != NULL &&
!strcmp (app->id, dialog->p->info->default_action->id))
found_idx = i;
menu_item = gtk_menu_item_new_with_label (app->name);
/* Store copy of application in item; free when item destroyed. */
g_object_set_data_full (G_OBJECT (menu_item),
"app", app,
(GDestroyNotify) gnome_vfs_mime_application_free);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
gtk_widget_show (menu_item);
}
dialog->p->default_action_active = !(i == 0);
dialog->p->custom_action = (found_idx < 0);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_menu_item_new_with_label (_("Custom")));
if (found_idx < 0) {
found_idx = i;
if (dialog->p->info->default_action->command != NULL)
gnome_file_entry_set_filename (GNOME_FILE_ENTRY (WID ("program_entry")),
dialog->p->info->default_action->command);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("needs_terminal_toggle")),
dialog->p->info->default_action->requires_terminal);
} else {
gtk_widget_set_sensitive (WID ("program_entry_box"), FALSE);
}
app_select = GTK_OPTION_MENU (WID ("default_action_select"));
gtk_option_menu_set_menu (app_select, GTK_WIDGET (menu));
gtk_option_menu_set_history (app_select, found_idx);
g_list_free (app_list);
update_sensitivity (dialog);
}
static void
populate_extensions_list (MimeEditDialog *dialog)
{
GList *tmp;
GtkTreeIter iter;
for (tmp = dialog->p->info->file_extensions; tmp != NULL; tmp = tmp->next) {
gtk_tree_store_append (dialog->p->ext_store, &iter, NULL);
gtk_tree_store_set (dialog->p->ext_store, &iter, 0, tmp->data, -1);
}
}
static GList *
collect_filename_extensions (MimeEditDialog *dialog)
{
GtkTreeIter iter;
GValue value;
GList *ret = NULL;
if (!gtk_tree_model_get_iter_root (GTK_TREE_MODEL (dialog->p->ext_store), &iter))
return NULL;
value.g_type = G_TYPE_INVALID;
do {
gtk_tree_model_get_value (GTK_TREE_MODEL (dialog->p->ext_store), &iter, 0, &value);
ret = g_list_prepend (ret, g_value_dup_string (&value));
g_value_unset (&value);
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->p->ext_store), &iter));
ret = g_list_reverse (ret);
return ret;
}
/**
* mime_edit_dialog_get_app :
* @glade :
* @mime_type : a fall back in case we can't generate a meaningful application name.
* @current :
*
* A utility routine for looking up applications. it should handle life cycle
* and hopefully merge in existing copies of custom applications.
**/
void
mime_edit_dialog_get_app (GladeXML *glade, char const *mime_type,
GnomeVFSMimeApplication **current)
{
GtkWidget *menu = glade_xml_get_widget (glade, "default_action_select");
gint idx = gtk_option_menu_get_history (GTK_OPTION_MENU (menu));
GtkWidget *shell = gtk_option_menu_get_menu (GTK_OPTION_MENU (menu));
GObject *item = (g_list_nth (GTK_MENU_SHELL (shell)->children, idx))->data;
GnomeVFSMimeApplication *res, *app = g_object_get_data (item, "app");
if (app == NULL) {
char *cmd = gnome_file_entry_get_full_path (
GNOME_FILE_ENTRY (glade_xml_get_widget (glade, "program_entry")), FALSE);
gboolean requires_terminal = gtk_toggle_button_get_active (
GTK_TOGGLE_BUTTON (glade_xml_get_widget (glade, "needs_terminal_toggle")));
char *base_cmd;
GList *ptr, *app_list = NULL;
/* I have no idea what semantics people want, but I'll be anal
* and avoid NULL
*/
if (cmd != NULL)
cmd = g_strdup ("");
base_cmd = g_path_get_basename (cmd);
if (base_cmd == NULL);
base_cmd = g_strdup ("");
app_list = gnome_vfs_application_registry_get_applications (NULL);
for (ptr = app_list; ptr != NULL ; ptr = ptr->next) {
char const *app_cmd = gnome_vfs_application_registry_peek_value (ptr->data,
GNOME_VFS_APPLICATION_REGISTRY_COMMAND);
/* Look for a matching application (with or without path) */
if (app_cmd != NULL &&
(!strcmp (cmd, app_cmd) || !strcmp (base_cmd, app_cmd))) {
gboolean ok, app_req = gnome_vfs_application_registry_get_bool_value (ptr->data,
GNOME_VFS_APPLICATION_REGISTRY_REQUIRES_TERMINAL, &ok);
if (ok && app_req == requires_terminal)
break;
}
}
/* No existing application, lets create one */
if (ptr == NULL) {
res = g_new0 (GnomeVFSMimeApplication, 1);
res->command = cmd;
res->requires_terminal = requires_terminal;
res->name = base_cmd;
if (res->name != NULL && *res->name) {
/* Can we use the app name as the id ?
* We know that there are no apps with the same
* command, so if the id is taken we are screwed
*/
if (gnome_vfs_application_registry_get_mime_application (res->name) == NULL)
res->id = g_strdup (res->name);
} else { /* fail safe to ensure a name */
g_free (res->name);
res->name = g_strdup_printf ("Custom %s", mime_type);
}
/* If there is no id yet, make up a unique string */
if (res->id == NULL) {
uuid_t app_uuid;
gchar app_uuid_str[100];
uuid_generate (app_uuid);
uuid_unparse (app_uuid, app_uuid_str);
res->id = g_strdup (app_uuid_str);
}
gnome_vfs_application_registry_save_mime_application (res);
} else {
g_free (cmd);
g_free (base_cmd);
res = gnome_vfs_application_registry_get_mime_application (ptr->data);
}
g_list_free (app_list);
} else
res = gnome_vfs_mime_application_copy (app);
gnome_vfs_mime_application_free (*current);
*current = res;
}
static void
store_data (MimeEditDialog *dialog)
{
GtkOptionMenu *option_menu;
GtkMenuShell *menu_shell;
GObject *menu_item;
gint idx;
gchar *tmp;
const gchar *tmp1;
gboolean cat_changed = FALSE;
GList *ext_list;
uuid_t mime_uuid;
gchar mime_uuid_str[100];
GtkTreeIter iter;
GtkTreePath *path;
g_free (dialog->p->info->description);
dialog->p->info->description = g_strdup (gtk_entry_get_text (GTK_ENTRY (WID ("description_entry"))));
g_free (dialog->p->info->mime_type);
tmp1 = gtk_entry_get_text (GTK_ENTRY (WID ("mime_type_entry")));
if (tmp1 != NULL && *tmp1 != '\0') {
dialog->p->info->mime_type = g_strdup (tmp1);
} else {
uuid_generate (mime_uuid);
uuid_unparse (mime_uuid, mime_uuid_str);
dialog->p->info->mime_type = g_strconcat ("custom/", mime_uuid_str, NULL);
}
g_free (dialog->p->info->icon_path);
dialog->p->info->icon_path = NULL;
g_free (dialog->p->info->icon_name);
dialog->p->info->icon_name = g_strdup (gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (WID ("icon_entry"))));
if (dialog->p->info->icon_pixbuf != NULL) {
g_object_unref (G_OBJECT (dialog->p->info->icon_pixbuf));
dialog->p->info->icon_pixbuf = NULL;
}
if (dialog->p->info->small_icon_pixbuf != NULL) {
g_object_unref (G_OBJECT (dialog->p->info->small_icon_pixbuf));
dialog->p->info->small_icon_pixbuf = NULL;
}
dialog->p->info->use_category =
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (WID ("use_category_defaults_toggle")));
option_menu = GTK_OPTION_MENU (WID ("component_select"));
menu_shell = GTK_MENU_SHELL (gtk_option_menu_get_menu (option_menu));
idx = gtk_option_menu_get_history (option_menu);
menu_item = (g_list_nth (menu_shell->children, idx))->data;
CORBA_free (dialog->p->info->default_component);
dialog->p->info->default_component = g_object_get_data (menu_item, "component");
mime_edit_dialog_get_app (dialog->p->dialog_xml,
dialog->p->info->mime_type,
&(dialog->p->info->default_action));
ext_list = collect_filename_extensions (dialog);
mime_type_info_set_file_extensions (dialog->p->info, ext_list);
tmp = mime_type_info_get_category_name (dialog->p->info);
tmp1 = gtk_entry_get_text (GTK_ENTRY (WID ("category_entry")));
if (strcmp (tmp, tmp1)) {
cat_changed = TRUE;
mime_type_info_set_category_name (dialog->p->info, tmp1, tmp1, dialog->p->model);
}
g_free (tmp);
model_entry_save (MODEL_ENTRY (dialog->p->info));
if (!cat_changed) {
mime_types_model_construct_iter (MIME_TYPES_MODEL (dialog->p->model),
MODEL_ENTRY (dialog->p->info), &iter);
path = gtk_tree_model_get_path (dialog->p->model, &iter);
gtk_tree_model_row_changed (dialog->p->model, path, &iter);
gtk_tree_path_free (path);
}
}
static gboolean
validate_data (MimeEditDialog *dialog)
{
const gchar *mime_type;
GtkWidget *err_dialog = NULL;
mime_type = gtk_entry_get_text (GTK_ENTRY (WID ("mime_type_entry")));
if (mime_type != NULL && *mime_type != '\0') {
if (strchr (mime_type, ' ') || !strchr (mime_type, '/')) {
err_dialog = gtk_message_dialog_new (
GTK_WINDOW (dialog->p->dialog_win),
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CANCEL,
_("Please enter a valid MIME type. It should be of the form "
"class/type and may not contain any spaces."));
} else if (dialog->p->is_add && (gnome_vfs_mime_type_is_known (mime_type) ||
get_mime_type_info (mime_type) != NULL)) {
err_dialog = gtk_message_dialog_new (
GTK_WINDOW (dialog->p->dialog_win),
GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
GTK_BUTTONS_OK_CANCEL,
_("A MIME type with that name already exists, overwrite ?."));
}
}
if (err_dialog) {
int res = gtk_dialog_run (GTK_DIALOG (err_dialog));
gtk_object_destroy (GTK_OBJECT (err_dialog));
return res != GTK_RESPONSE_CANCEL;
}
return TRUE;
}
static void
add_ext_cb (MimeEditDialog *dialog)
{
GtkTreeIter iter;
const gchar *ext_name;
ext_name = gtk_entry_get_text (GTK_ENTRY (WID ("new_ext_entry")));
if (ext_name != NULL && *ext_name != '\0') {
gtk_tree_store_append (dialog->p->ext_store, &iter, NULL);
gtk_tree_store_set (dialog->p->ext_store, &iter, 0, ext_name, -1);
}
gtk_entry_set_text (GTK_ENTRY (WID ("new_ext_entry")), "");
}
static void
remove_ext_foreach_cb (GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter)
{
gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
}
static void
remove_ext_cb (MimeEditDialog *dialog)
{
gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("ext_list"))),
(GtkTreeSelectionForeachFunc) remove_ext_foreach_cb, NULL);
}
static void
choose_cat_cb (MimeEditDialog *dialog)
{
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkWidget *treeview;
GtkWidget *dialog_win;
GtkWidget *scrolled_win;
GtkCellRenderer *renderer;
model = GTK_TREE_MODEL (mime_types_model_new (TRUE));
treeview = gtk_tree_view_new_with_model (model);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
if (dialog->p->info->entry.parent != NULL) {
mime_types_model_construct_iter (MIME_TYPES_MODEL (model), dialog->p->info->entry.parent, &iter);
gtk_tree_selection_select_iter (selection, &iter);
}
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_insert_column_with_attributes
(GTK_TREE_VIEW (treeview), -1, _("Category"), renderer,
"text", MODEL_COLUMN_DESCRIPTION,
NULL);
dialog_win = gtk_dialog_new_with_buttons
(_("Choose a file category"), NULL, -1,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
gtk_widget_set_size_request (dialog_win, 300, 300);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolled_win), treeview);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_win)->vbox), scrolled_win, TRUE, TRUE, GNOME_PAD_SMALL);
gtk_widget_show_all (dialog_win);
if (gtk_dialog_run (GTK_DIALOG (dialog_win)) == GTK_RESPONSE_OK) {
gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_entry_set_text (GTK_ENTRY (WID ("category_entry")),
mime_category_info_get_full_name (MIME_CATEGORY_INFO (MODEL_ENTRY_FROM_ITER (&iter))));
}
gtk_widget_destroy (dialog_win);
g_object_unref (G_OBJECT (model));
}
static void
default_action_changed_cb (MimeEditDialog *dialog)
{
int id;
GtkOptionMenu *option_menu;
GtkMenuShell *menu;
option_menu = GTK_OPTION_MENU (WID ("default_action_select"));
menu = GTK_MENU_SHELL (gtk_option_menu_get_menu (option_menu));
id = gtk_option_menu_get_history (option_menu);
dialog->p->custom_action = (id == g_list_length (menu->children) - 1);
update_sensitivity (dialog);
}
static void
use_category_defaults_toggled_cb (MimeEditDialog *dialog, GtkToggleButton *tb)
{
dialog->p->use_cat_dfl = gtk_toggle_button_get_active (tb);
update_sensitivity (dialog);
}
static void
response_cb (MimeEditDialog *dialog, gint response_id)
{
if (response_id == GTK_RESPONSE_OK) {
if (validate_data (dialog)) {
store_data (dialog);
g_signal_emit (G_OBJECT (dialog), dialog_signals[DONE], 0, TRUE);
g_object_unref (G_OBJECT (dialog));
}
} else {
if (dialog->p->is_add)
mime_type_info_free (dialog->p->info);
g_signal_emit (G_OBJECT (dialog), dialog_signals[DONE], 0, FALSE);
g_object_unref (G_OBJECT (dialog));
}
}
static void
update_sensitivity (MimeEditDialog *dialog)
{
gtk_widget_set_sensitive (WID ("component_box"), dialog->p->component_active && !dialog->p->use_cat_dfl);
gtk_widget_set_sensitive (WID ("default_action_box"), dialog->p->default_action_active && !dialog->p->use_cat_dfl);
gtk_widget_set_sensitive (WID ("program_entry_box"), dialog->p->custom_action && !dialog->p->use_cat_dfl);
gtk_widget_set_sensitive (WID ("needs_terminal_toggle"), dialog->p->custom_action && !dialog->p->use_cat_dfl);
}