From d6d5ff20d9cb8d19b26365672d76aa9883fd1487 Mon Sep 17 00:00:00 2001 From: Bradford Hovinen Date: Mon, 14 Jan 2002 15:28:36 +0000 Subject: [PATCH] Implement. Mostly a copy from the corresponding function in 2002-01-14 Bradford Hovinen * mime-category-edit-dialog.c (populate_application_list): Implement. Mostly a copy from the corresponding function in mime-edit-dialog.c * mime-types-model.c (get_insertion_point): Make this public (find_supported_apps_for_category, reduce_supported_app_list) (intersect_lists, find_possible_supported_apps): Implement * mime-edit-dialog.c (fill_dialog): Fill category_entry (choose_cat_cb): Implement (mime_edit_dialog_init): Connect choose_button to choose_cat_cb * mime-type-info.c (mime_type_info_load): Load category name (mime_type_info_save): Call reinsert_iter to affect category name change * mime-types-model.c (mime_types_model_new): Add parameter is_category_select; TRUE iff this model should be only for selecting a category and not list the actual file types or Internet services (get_category_name): Implement * mime-edit-dialog.c (mime_edit_dialog_init): Add category_label to first size group 2002-01-13 Bradford Hovinen * file-types-capplet.c (edit_cb, row_activated_cb): Don't try to create a category edit dialog if this is the Internet Services category (count_cb): Only count other than internet services category * mime-types-model.c (model_entry_is_category): Implement (model_entry_is_protocol): Use categories[INTERNET_SERVICES_IDX] rather than string (model_entry_is_internet_services_category): Implement * Makefile.am (gnome_file_types_properties_SOURCES): Add mime-category-edit-dialog.[ch] * file-types-capplet.c (edit_cb): Construct a category edit dialog if the tree iterator has children (row_activated_cb): Ditto --- capplets/file-types/ChangeLog | 46 ++ capplets/file-types/Makefile.am | 15 +- capplets/file-types/TODO_NOTES | 1 + capplets/file-types/file-types-capplet.c | 16 +- .../file-types/file-types-properties.glade | 98 ++++- .../file-types/file-types-properties.glade1 | 92 +++- .../file-types/mime-category-edit-dialog.c | 396 ++++++++++++++++++ .../file-types/mime-category-edit-dialog.h | 59 +++ capplets/file-types/mime-edit-dialog.c | 50 +++ capplets/file-types/mime-type-info.c | 8 +- capplets/file-types/mime-type-info.h | 1 + capplets/file-types/mime-types-model.c | 211 +++++++++- capplets/file-types/mime-types-model.h | 21 +- 13 files changed, 945 insertions(+), 69 deletions(-) create mode 100644 capplets/file-types/mime-category-edit-dialog.c create mode 100644 capplets/file-types/mime-category-edit-dialog.h diff --git a/capplets/file-types/ChangeLog b/capplets/file-types/ChangeLog index b72487c3e..71e766df4 100644 --- a/capplets/file-types/ChangeLog +++ b/capplets/file-types/ChangeLog @@ -1,3 +1,49 @@ +2002-01-14 Bradford Hovinen + + * mime-category-edit-dialog.c (populate_application_list): + Implement. Mostly a copy from the corresponding function in + mime-edit-dialog.c + + * mime-types-model.c (get_insertion_point): Make this public + (find_supported_apps_for_category, reduce_supported_app_list) + (intersect_lists, find_possible_supported_apps): Implement + + * mime-edit-dialog.c (fill_dialog): Fill category_entry + (choose_cat_cb): Implement + (mime_edit_dialog_init): Connect choose_button to choose_cat_cb + + * mime-type-info.c (mime_type_info_load): Load category name + (mime_type_info_save): Call reinsert_iter to affect category name + change + + * mime-types-model.c (mime_types_model_new): Add parameter + is_category_select; TRUE iff this model should be only for + selecting a category and not list the actual file types or + Internet services + (get_category_name): Implement + + * mime-edit-dialog.c (mime_edit_dialog_init): Add category_label + to first size group + +2002-01-13 Bradford Hovinen + + * file-types-capplet.c (edit_cb, row_activated_cb): Don't try to + create a category edit dialog if this is the Internet Services + category + (count_cb): Only count other than internet services category + + * mime-types-model.c (model_entry_is_category): Implement + (model_entry_is_protocol): Use categories[INTERNET_SERVICES_IDX] + rather than string + (model_entry_is_internet_services_category): Implement + + * Makefile.am (gnome_file_types_properties_SOURCES): Add + mime-category-edit-dialog.[ch] + + * file-types-capplet.c (edit_cb): Construct a category edit dialog + if the tree iterator has children + (row_activated_cb): Ditto + 2002-01-11 Bradford Hovinen * file-types-capplet.c (selection_changed_cb): Implement diff --git a/capplets/file-types/Makefile.am b/capplets/file-types/Makefile.am index 92f5289bb..8cc0c2c43 100644 --- a/capplets/file-types/Makefile.am +++ b/capplets/file-types/Makefile.am @@ -4,13 +4,14 @@ bin_PROGRAMS = gnome-file-types-properties gnome_file_types_properties_LDADD = $(GNOMECC_CAPPLETS_LIBS) $(VFS_CAPPLET_LIBS) libuuid/libuuid.a -gnome_file_types_properties_SOURCES = \ - file-types-capplet.c \ - mime-types-model.c mime-types-model.h \ - mime-type-info.c mime-type-info.h \ - mime-edit-dialog.c mime-edit-dialog.h \ - service-info.c service-info.h \ - service-edit-dialog.c service-edit-dialog.h +gnome_file_types_properties_SOURCES = \ + file-types-capplet.c \ + mime-types-model.c mime-types-model.h \ + mime-type-info.c mime-type-info.h \ + mime-edit-dialog.c mime-edit-dialog.h \ + mime-category-edit-dialog.c mime-category-edit-dialog.h \ + service-info.c service-info.h \ + service-edit-dialog.c service-edit-dialog.h @INTLTOOL_DESKTOP_RULE@ diff --git a/capplets/file-types/TODO_NOTES b/capplets/file-types/TODO_NOTES index a272a9a8a..33b8e4ffa 100644 --- a/capplets/file-types/TODO_NOTES +++ b/capplets/file-types/TODO_NOTES @@ -9,6 +9,7 @@ - Generate MIME type if field is empty - When no apps/components are available, desensitize app/component list - Better sorting on the MIME types tree + - Category selection CVS Surgery - Move file-types to gnome-control-center, rename ??? diff --git a/capplets/file-types/file-types-capplet.c b/capplets/file-types/file-types-capplet.c index 532e2ca7e..574612ebf 100644 --- a/capplets/file-types/file-types-capplet.c +++ b/capplets/file-types/file-types-capplet.c @@ -38,6 +38,7 @@ #include "mime-types-model.h" #include "mime-edit-dialog.h" +#include "mime-category-edit-dialog.h" #include "mime-type-info.h" #include "service-edit-dialog.h" #include "service-info.h" @@ -71,7 +72,10 @@ edit_cb (GtkButton *button, GladeXML *dialog) if (model_entry_is_protocol (model, &iter)) edit_dialog = service_edit_dialog_new (service_info_load (model, &iter, changeset)); - else + else if (model_entry_is_category (model, &iter)) { + if (!model_entry_is_internet_services_category (model, &iter)) + edit_dialog = mime_category_edit_dialog_new (model, &iter); + } else edit_dialog = mime_edit_dialog_new (mime_type_info_load (model, &iter)); } @@ -88,14 +92,18 @@ row_activated_cb (GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *colum if (model_entry_is_protocol (model, &iter)) edit_dialog = service_edit_dialog_new (service_info_load (model, &iter, changeset)); - else + else if (model_entry_is_category (model, &iter)) { + if (!model_entry_is_internet_services_category (model, &iter)) + edit_dialog = mime_category_edit_dialog_new (model, &iter); + } else edit_dialog = mime_edit_dialog_new (mime_type_info_load (model, &iter)); } static void count_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gint *count) { - (*count)++; + if (!model_entry_is_internet_services_category (model, iter)) + (*count)++; } static void @@ -150,7 +158,7 @@ create_dialog (void) dialog = glade_xml_new (GNOMECC_DATA_DIR "/interfaces/file-types-properties.glade", "main_dialog", NULL); - model = mime_types_model_new (); + model = mime_types_model_new (FALSE); treeview = WID ("mime_types_tree"); gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), model); diff --git a/capplets/file-types/file-types-properties.glade b/capplets/file-types/file-types-properties.glade index 967b06296..7598e768a 100644 --- a/capplets/file-types/file-types-properties.glade +++ b/capplets/file-types/file-types-properties.glade @@ -249,28 +249,10 @@ yes - - 0 - yes - yes - - - - - - Icon - GTK_JUSTIFY_CENTER - no - 0.5 - 0.5 - 0 - 0 - yes - 0 no - no + yes @@ -369,7 +351,68 @@ - + + no + 4 + yes + + + + Category + GTK_JUSTIFY_CENTER + no + 0 + 0.5 + 0 + 0 + yes + + + 0 + no + no + + + + + + yes + yes + + 0 + yes + yes + + + 0 + yes + yes + + + + + + yes + Choose... + GTK_RELIEF_NORMAL + yes + + + 0 + no + no + + + + + 0 + no + yes + + + + + Filename extensions 0 GTK_SHADOW_ETCHED_IN @@ -502,6 +545,21 @@ 4 yes + + + yes + Use category defaults + no + yes + yes + + + 0 + no + no + + + no diff --git a/capplets/file-types/file-types-properties.glade1 b/capplets/file-types/file-types-properties.glade1 index cd07f956e..8fc1721e6 100644 --- a/capplets/file-types/file-types-properties.glade1 +++ b/capplets/file-types/file-types-properties.glade1 @@ -254,27 +254,10 @@ GnomeIconEntry icon_entry 10 - - 0 - True - True - - - - - GtkLabel - label13 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 0 False - False + True @@ -366,9 +349,66 @@ + + GtkHBox + hbox12 + False + 4 + + 0 + False + True + + + + GtkLabel + category_label + + GTK_JUSTIFY_CENTER + False + 0 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkEntry + category_entry + True + True + True + 0 + + + 0 + True + True + + + + + GtkButton + choose_button + True + + GTK_RELIEF_NORMAL + + 0 + False + False + + + + GtkFrame - frame2 + file_extensions_frame 0 GTK_SHADOW_ETCHED_IN @@ -517,6 +557,20 @@ False 4 + + GtkCheckButton + use_category_defaults_toggle + True + + False + True + + 0 + False + False + + + GtkHBox hbox6 diff --git a/capplets/file-types/mime-category-edit-dialog.c b/capplets/file-types/mime-category-edit-dialog.c new file mode 100644 index 000000000..43980cb90 --- /dev/null +++ b/capplets/file-types/mime-category-edit-dialog.c @@ -0,0 +1,396 @@ +/* -*- mode: c; style: linux -*- */ + +/* mime-category-edit-dialog.c + * Copyright (C) 2001 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * 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 +#include +#include + +#include "mime-types-model.h" +#include "mime-category-edit-dialog.h" + +#define WID(x) (glade_xml_get_widget (dialog->p->dialog_xml, x)) + +enum { + PROP_0, + PROP_MODEL, + PROP_ITER +}; + +struct _MimeCategoryEditDialogPrivate +{ + GladeXML *dialog_xml; + GtkWidget *dialog_win; + GtkTreeModel *model; + GtkTreeIter *iter; +}; + +static GObjectClass *parent_class; + +static void mime_category_edit_dialog_init (MimeCategoryEditDialog *dialog, + MimeCategoryEditDialogClass *class); +static void mime_category_edit_dialog_class_init (MimeCategoryEditDialogClass *class); +static void mime_category_edit_dialog_base_init (MimeCategoryEditDialogClass *class); + +static void mime_category_edit_dialog_set_prop (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void mime_category_edit_dialog_get_prop (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void mime_category_edit_dialog_dispose (GObject *object); +static void mime_category_edit_dialog_finalize (GObject *object); + +static void populate_application_list (MimeCategoryEditDialog *dialog); + +static void fill_dialog (MimeCategoryEditDialog *dialog); +static void store_data (MimeCategoryEditDialog *dialog); + +static void default_action_changed_cb (MimeCategoryEditDialog *dialog); +static void response_cb (MimeCategoryEditDialog *dialog, + gint response_id); + +GType +mime_category_edit_dialog_get_type (void) +{ + static GType mime_category_edit_dialog_type = 0; + + if (!mime_category_edit_dialog_type) { + GTypeInfo mime_category_edit_dialog_info = { + sizeof (MimeCategoryEditDialogClass), + (GBaseInitFunc) mime_category_edit_dialog_base_init, + NULL, /* GBaseFinalizeFunc */ + (GClassInitFunc) mime_category_edit_dialog_class_init, + NULL, /* GClassFinalizeFunc */ + NULL, /* user-supplied data */ + sizeof (MimeCategoryEditDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) mime_category_edit_dialog_init, + NULL + }; + + mime_category_edit_dialog_type = + g_type_register_static (G_TYPE_OBJECT, + "MimeCategoryEditDialog", + &mime_category_edit_dialog_info, 0); + } + + return mime_category_edit_dialog_type; +} + +static void +mime_category_edit_dialog_init (MimeCategoryEditDialog *dialog, MimeCategoryEditDialogClass *class) +{ + GtkSizeGroup *size_group; + + dialog->p = g_new0 (MimeCategoryEditDialogPrivate, 1); + dialog->p->dialog_xml = glade_xml_new + (GNOMECC_DATA_DIR "/interfaces/file-types-properties.glade", "edit_widget", NULL); + + dialog->p->model = NULL; + dialog->p->iter = 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")); + + gtk_widget_set_sensitive (WID ("icon_entry"), FALSE); + gtk_widget_set_sensitive (WID ("mime_type_entry"), FALSE); + gtk_widget_set_sensitive (WID ("mime_type_label"), FALSE); + gtk_widget_set_sensitive (WID ("description_entry"), FALSE); + gtk_widget_set_sensitive (WID ("file_extensions_frame"), FALSE); + gtk_widget_set_sensitive (WID ("component_label"), FALSE); + gtk_widget_set_sensitive (WID ("component_select"), FALSE); + + dialog->p->dialog_win = gtk_dialog_new_with_buttons + (_("Edit file category"), NULL, -1, + GTK_STOCK_OK, GTK_RESPONSE_OK, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + NULL); + + 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 ("default_action_select")), "changed", (GCallback) default_action_changed_cb, dialog); + + g_signal_connect_swapped (G_OBJECT (dialog->p->dialog_win), "response", (GCallback) response_cb, dialog); +} + +static void +mime_category_edit_dialog_base_init (MimeCategoryEditDialogClass *class) +{ +} + +static void +mime_category_edit_dialog_class_init (MimeCategoryEditDialogClass *class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (class); + + object_class->dispose = mime_category_edit_dialog_dispose; + object_class->finalize = mime_category_edit_dialog_finalize; + object_class->set_property = mime_category_edit_dialog_set_prop; + object_class->get_property = mime_category_edit_dialog_get_prop; + + g_object_class_install_property + (object_class, PROP_MODEL, + g_param_spec_pointer ("model", + _("Model"), + _("GtkTreeModel that contains the category data"), + G_PARAM_READWRITE)); + g_object_class_install_property + (object_class, PROP_ITER, + g_param_spec_pointer ("iterator", + _("Iterator"), + _("GtkTreeIter that contains the category data"), + G_PARAM_READWRITE)); + + parent_class = G_OBJECT_CLASS + (g_type_class_ref (G_TYPE_OBJECT)); +} + +static void +mime_category_edit_dialog_set_prop (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + MimeCategoryEditDialog *dialog; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_MIME_CATEGORY_EDIT_DIALOG (object)); + + dialog = MIME_CATEGORY_EDIT_DIALOG (object); + + switch (prop_id) { + case PROP_MODEL: + dialog->p->model = g_value_get_pointer (value); + + if (dialog->p->iter != NULL) + fill_dialog (dialog); + + break; + + case PROP_ITER: + dialog->p->iter = gtk_tree_iter_copy (g_value_get_pointer (value)); + + if (dialog->p->model != NULL) + fill_dialog (dialog); + + break; + + default: + g_warning ("Bad property set"); + break; + } +} + +static void +mime_category_edit_dialog_get_prop (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + MimeCategoryEditDialog *dialog; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_MIME_CATEGORY_EDIT_DIALOG (object)); + + dialog = MIME_CATEGORY_EDIT_DIALOG (object); + + switch (prop_id) { + case PROP_MODEL: + g_value_set_pointer (value, dialog->p->model); + break; + + case PROP_ITER: + g_value_set_pointer (value, dialog->p->iter); + break; + + default: + g_warning ("Bad property get"); + break; + } +} + +static void +mime_category_edit_dialog_dispose (GObject *object) +{ + MimeCategoryEditDialog *dialog; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_MIME_CATEGORY_EDIT_DIALOG (object)); + + dialog = MIME_CATEGORY_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_category_edit_dialog_finalize (GObject *object) +{ + MimeCategoryEditDialog *mime_category_edit_dialog; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_MIME_CATEGORY_EDIT_DIALOG (object)); + + mime_category_edit_dialog = MIME_CATEGORY_EDIT_DIALOG (object); + + g_free (mime_category_edit_dialog->p); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +GObject * +mime_category_edit_dialog_new (GtkTreeModel *model, GtkTreeIter *iter) +{ + return g_object_new (mime_category_edit_dialog_get_type (), + "model", model, + "iterator", iter, + NULL); +} + +static void +fill_dialog (MimeCategoryEditDialog *dialog) +{ + GValue value; + GtkTreeIter iter; + + value.g_type = G_TYPE_INVALID; + + gtk_tree_model_get_value (dialog->p->model, dialog->p->iter, DESCRIPTION_COLUMN, &value); + gtk_entry_set_text (GTK_ENTRY (WID ("description_entry")), g_value_get_string (&value)); + g_value_unset (&value); + + populate_application_list (dialog); + + if (!gtk_tree_model_iter_parent (dialog->p->model, &iter, dialog->p->iter)) + gtk_widget_set_sensitive (WID ("use_category_defaults_toggle"), FALSE); + + gtk_widget_show_all (dialog->p->dialog_win); +} + +/* FIXME: This should be factored with corresponding functions in mime-edit-dialog.c and service-edit-dialog.c */ + +static void +populate_application_list (MimeCategoryEditDialog *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 = find_supported_apps_for_category (dialog->p->model, dialog->p->iter); + + for (tmp = app_list, i = 0; tmp != NULL; tmp = tmp->next, i++) { + app = gnome_vfs_application_registry_get_mime_application (tmp->data); +#if 0 + if (dialog->p->info->default_action != NULL && + !strcmp (tmp->data, dialog->p->info->default_action->id)) + found_idx = i; +#endif + + 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) g_free); + + gtk_menu_append (menu, menu_item); + gtk_widget_show (menu_item); + } + + gtk_menu_append (menu, gtk_menu_item_new_with_label (_("Custom"))); + + if (found_idx < 0) { + found_idx = i; +#if 0 + if (dialog->p->info->custom_line != NULL) + gnome_file_entry_set_filename (GNOME_FILE_ENTRY (WID ("program_entry")), + dialog->p->info->custom_line); +#endif + } 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); +} + +static void +store_data (MimeCategoryEditDialog *dialog) +{ +} + +static void +default_action_changed_cb (MimeCategoryEditDialog *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); + + if (id == g_list_length (menu->children) - 1) { + gtk_widget_set_sensitive (WID ("program_entry_box"), TRUE); + gtk_widget_set_sensitive (WID ("needs_terminal_toggle"), TRUE); + } else { + gtk_widget_set_sensitive (WID ("program_entry_box"), FALSE); + gtk_widget_set_sensitive (WID ("needs_terminal_toggle"), FALSE); + } +} + +static void +response_cb (MimeCategoryEditDialog *dialog, gint response_id) +{ + if (response_id == GTK_RESPONSE_OK) + store_data (dialog); + + g_object_unref (G_OBJECT (dialog)); +} diff --git a/capplets/file-types/mime-category-edit-dialog.h b/capplets/file-types/mime-category-edit-dialog.h new file mode 100644 index 000000000..64c78a474 --- /dev/null +++ b/capplets/file-types/mime-category-edit-dialog.h @@ -0,0 +1,59 @@ +/* -*- mode: c; style: linux -*- */ + +/* mime-category-edit-dialog.h + * Copyright (C) 2001 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * 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. + */ + +#ifndef __MIME_CATEGORY_EDIT_DIALOG_H +#define __MIME_CATEGORY_EDIT_DIALOG_H + +#include + + +G_BEGIN_DECLS + +#define MIME_CATEGORY_EDIT_DIALOG(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, mime_category_edit_dialog_get_type (), MimeCategoryEditDialog) +#define MIME_CATEGORY_EDIT_DIALOG_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, mime_category_edit_dialog_get_type (), MimeCategoryEditDialogClass) +#define IS_MIME_CATEGORY_EDIT_DIALOG(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, mime_category_edit_dialog_get_type ()) + +typedef struct _MimeCategoryEditDialog MimeCategoryEditDialog; +typedef struct _MimeCategoryEditDialogClass MimeCategoryEditDialogClass; +typedef struct _MimeCategoryEditDialogPrivate MimeCategoryEditDialogPrivate; + +struct _MimeCategoryEditDialog +{ + GObject parent; + + MimeCategoryEditDialogPrivate *p; +}; + +struct _MimeCategoryEditDialogClass +{ + GObjectClass g_object_class; +}; + +GType mime_category_edit_dialog_get_type (void); + +GObject *mime_category_edit_dialog_new (GtkTreeModel *model, + GtkTreeIter *iter); + +G_END_DECLS + +#endif /* __MIME_CATEGORY_EDIT_DIALOG_H */ diff --git a/capplets/file-types/mime-edit-dialog.c b/capplets/file-types/mime-edit-dialog.c index 2e1a09017..fdc233757 100644 --- a/capplets/file-types/mime-edit-dialog.c +++ b/capplets/file-types/mime-edit-dialog.c @@ -29,6 +29,7 @@ #include #include "mime-edit-dialog.h" +#include "mime-types-model.h" #define WID(x) (glade_xml_get_widget (dialog->p->dialog_xml, x)) @@ -72,6 +73,7 @@ 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 response_cb (MimeEditDialog *dialog, gint response_id); @@ -118,6 +120,7 @@ mime_edit_dialog_init (MimeEditDialog *dialog, MimeEditDialogClass *class) 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")); @@ -142,6 +145,7 @@ mime_edit_dialog_init (MimeEditDialog *dialog, MimeEditDialogClass *class) 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 (dialog->p->dialog_win), "response", (GCallback) response_cb, dialog); @@ -277,6 +281,7 @@ fill_dialog (MimeEditDialog *dialog) { gtk_entry_set_text (GTK_ENTRY (WID ("description_entry")), dialog->p->info->description); gtk_entry_set_text (GTK_ENTRY (WID ("mime_type_entry")), dialog->p->info->mime_type); + gtk_entry_set_text (GTK_ENTRY (WID ("category_entry")), dialog->p->info->category); if (dialog->p->info->custom_line != NULL) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (WID ("program_entry")), dialog->p->info->custom_line); @@ -465,6 +470,9 @@ store_data (MimeEditDialog *dialog) 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")))); + g_free (dialog->p->info->category); + dialog->p->info->category = g_strdup (gtk_entry_get_text (GTK_ENTRY (WID ("category_entry")))); + 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); @@ -527,6 +535,48 @@ remove_ext_cb (MimeEditDialog *dialog) (GtkTreeSelectionForeachFunc) remove_ext_foreach_cb, NULL); } +static void +choose_cat_cb (MimeEditDialog *dialog) +{ + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkWidget *treeview; + GtkWidget *dialog_win; + GtkCellRenderer *renderer; + + 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); + get_insertion_point (GTK_TREE_STORE (model), dialog->p->info->category, &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", DESCRIPTION_COLUMN, + NULL); + + dialog_win = gtk_dialog_new_with_buttons + (_("Choose a file category"), NULL, -1, + GTK_STOCK_OK, GTK_RESPONSE_OK, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + NULL); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_win)->vbox), treeview, 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")), get_category_name (model, &iter, TRUE)); + } + + gtk_widget_destroy (dialog_win); + g_object_unref (G_OBJECT (model)); +} + static void default_action_changed_cb (MimeEditDialog *dialog) { diff --git a/capplets/file-types/mime-type-info.c b/capplets/file-types/mime-type-info.c index b022d43ee..a22885b3e 100644 --- a/capplets/file-types/mime-type-info.c +++ b/capplets/file-types/mime-type-info.c @@ -120,6 +120,7 @@ mime_type_info_load (GtkTreeModel *model, GtkTreeIter *iter) info->edit_line = g_strdup (gnome_vfs_mime_get_value (info->mime_type, "edit-line")); info->print_line = g_strdup (gnome_vfs_mime_get_value (info->mime_type, "print-line")); info->default_action = gnome_vfs_mime_get_default_application (info->mime_type); + info->category = get_category_name (model, iter, FALSE); tmp = g_strdup_printf ("Custom %s", info->mime_type); @@ -149,8 +150,7 @@ mime_type_info_load (GtkTreeModel *model, GtkTreeIter *iter) void mime_type_info_save (const MimeTypeInfo *info) { - gchar *tmp, *tmp1; - gchar *appid; + gchar *tmp; uuid_t app_uuid; gchar app_uuid_str[100]; GnomeVFSMimeApplication app; @@ -185,6 +185,9 @@ mime_type_info_save (const MimeTypeInfo *info) tmp = form_extensions_string (info, " ", NULL); gnome_vfs_mime_set_extensions_list (info->mime_type, tmp); g_free (tmp); + + if (strcmp (info->category, get_category_name (info->model, info->iter, FALSE))) + reinsert_model_entry (info->model, info->iter); } void @@ -219,6 +222,7 @@ mime_type_info_free (MimeTypeInfo *info) g_free (info->custom_line); g_free (info->edit_line); g_free (info->print_line); + g_free (info->category); g_free (info); } diff --git a/capplets/file-types/mime-type-info.h b/capplets/file-types/mime-type-info.h index 283512e7a..f3cbef3fb 100644 --- a/capplets/file-types/mime-type-info.h +++ b/capplets/file-types/mime-type-info.h @@ -52,6 +52,7 @@ struct _MimeTypeInfo gchar *print_line; gboolean is_category; + gchar *category; }; MimeTypeInfo *mime_type_info_load (GtkTreeModel *model, diff --git a/capplets/file-types/mime-types-model.c b/capplets/file-types/mime-types-model.c index 8473f67fb..9e96b1061 100644 --- a/capplets/file-types/mime-types-model.c +++ b/capplets/file-types/mime-types-model.c @@ -27,6 +27,7 @@ #endif #include +#include #include #include #include @@ -37,9 +38,11 @@ #include "mime-types-model.h" const gchar *categories[] = { - "Documents", "Images", "Audio", "Video", "Internet Services", NULL + N_("Documents"), N_("Images"), N_("Audio"), N_("Video"), N_("Internet Services"), NULL }; +#define INTERNET_SERVICES_IDX 4 + const gchar *url_descriptions[][2] = { { "unknown", N_("Unknown service types") }, { "http", N_("World wide web") }, @@ -115,17 +118,6 @@ get_path_num_from_str (GtkTreeStore *model, GtkTreeIter *iter, const gchar *path g_free (first_component); } -static void -get_insertion_point (GtkTreeStore *model, const gchar *path_str, GtkTreeIter *iter) -{ - GString *path_num; - - path_num = g_string_new (""); - get_path_num_from_str (model, NULL, path_str, path_num); - gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), iter, path_num->str + 1); - g_string_free (path_num, TRUE); -} - static const gchar * get_protocol_name (const gchar *key) { @@ -140,7 +132,7 @@ get_protocol_name (const gchar *key) } GtkTreeModel * -mime_types_model_new (void) +mime_types_model_new (gboolean is_category_select) { GtkTreeStore *model; GList *type_list; @@ -173,7 +165,7 @@ mime_types_model_new (void) mime_type = tmp->data; path_str = get_category_path_for_mime_type (mime_type); - if (path_str != NULL) { + if (path_str != NULL && !is_category_select) { description = gnome_vfs_mime_get_description (mime_type); extensions = gnome_vfs_mime_get_extensions_pretty_string (mime_type); @@ -196,6 +188,9 @@ mime_types_model_new (void) g_list_free (type_list); + if (is_category_select) + return GTK_TREE_MODEL (model); + tmps = url_list = gconf_client_all_dirs (gconf_client_get_default (), "/desktop/gnome/url-handlers", NULL); @@ -227,6 +222,11 @@ mime_types_model_new (void) return GTK_TREE_MODEL (model); } +void +reinsert_model_entry (GtkTreeModel *model, GtkTreeIter *iter) +{ +} + GdkPixbuf * get_icon_pixbuf (const gchar *short_icon_name) { @@ -289,6 +289,52 @@ get_description_for_protocol (const gchar *protocol_name) return NULL; } +gchar * +get_category_name (GtkTreeModel *model, GtkTreeIter *iter, gboolean incl_iter) +{ + GString *string; + gchar *ret; + GValue value; + GtkTreeIter tmp[2]; + gint flip = 0; + + value.g_type = G_TYPE_INVALID; + string = g_string_new (""); + + if (incl_iter) + /* FIXME: Ugh */ memcpy (&(tmp[0]), iter, sizeof (GtkTreeIter)); + else if (!gtk_tree_model_iter_parent (model, &(tmp[0]), iter)) + return g_strdup (""); + + while (1) { + gtk_tree_model_get_value (model, &(tmp[flip]), DESCRIPTION_COLUMN, &value); + g_string_prepend (string, g_value_get_string (&value)); + g_value_unset (&value); + + if (gtk_tree_model_iter_parent (model, &(tmp[1-flip]), &(tmp[flip]))) + g_string_prepend (string, "/"); + else + break; + + flip = 1 - flip; + } + + ret = string->str; + g_string_free (string, FALSE); + return ret; +} + +void +get_insertion_point (GtkTreeStore *model, const gchar *path_str, GtkTreeIter *iter) +{ + GString *path_num; + + path_num = g_string_new (""); + get_path_num_from_str (model, NULL, path_str, path_num); + gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), iter, path_num->str + 1); + g_string_free (path_num, TRUE); +} + gboolean model_entry_is_protocol (GtkTreeModel *model, GtkTreeIter *iter) { @@ -296,7 +342,7 @@ model_entry_is_protocol (GtkTreeModel *model, GtkTreeIter *iter) GtkTreePath *parent_path, *child_path; gboolean ret; - get_insertion_point (GTK_TREE_STORE (model), "Internet Services", &parent_iter); + get_insertion_point (GTK_TREE_STORE (model), categories[INTERNET_SERVICES_IDX], &parent_iter); parent_path = gtk_tree_model_get_path (model, &parent_iter); child_path = gtk_tree_model_get_path (model, iter); @@ -307,3 +353,138 @@ model_entry_is_protocol (GtkTreeModel *model, GtkTreeIter *iter) return ret; } +gboolean +model_entry_is_category (GtkTreeModel *model, GtkTreeIter *iter) +{ + GValue value; + const gchar *str; + gboolean ret; + + value.g_type = G_TYPE_INVALID; + + gtk_tree_model_get_value (GTK_TREE_MODEL (model), iter, MIME_TYPE_COLUMN, &value); + + str = g_value_get_string (&value); + + if (str == NULL || *str == '\0') + ret = TRUE; + else + ret = FALSE; + + g_value_unset (&value); + + return ret; +} + +gboolean +model_entry_is_internet_services_category (GtkTreeModel *model, GtkTreeIter *iter) +{ + GValue value; + const gchar *str; + gboolean ret; + + value.g_type = G_TYPE_INVALID; + + gtk_tree_model_get_value (GTK_TREE_MODEL (model), iter, DESCRIPTION_COLUMN, &value); + + str = g_value_get_string (&value); + + if (str != NULL && !strcmp (str, categories[INTERNET_SERVICES_IDX])) + ret = TRUE; + else + ret = FALSE; + + g_value_unset (&value); + + return ret; +} + +static GList * +find_possible_supported_apps (GtkTreeModel *model, GtkTreeIter *iter) +{ + GValue value; + GtkTreeIter child; + GList *ret; + + value.g_type = G_TYPE_INVALID; + gtk_tree_model_get_value (model, iter, MIME_TYPE_COLUMN, &value); + + if (g_value_get_string (&value) == NULL) { + if (gtk_tree_model_iter_has_child (model, iter)) { + gtk_tree_model_iter_nth_child (model, &child, iter, 0); + ret = find_possible_supported_apps (model, &child); + } + else if (gtk_tree_model_iter_next (model, iter)) { + ret = find_possible_supported_apps (model, iter); + } else { + ret = NULL; + } + } else { + ret = gnome_vfs_application_registry_get_applications (g_value_get_string (&value)); + } + + g_value_unset (&value); + + return ret; +} + +static GList * +intersect_lists (GList *list, GList *list1) +{ + GList *tmp, *tmp1, *tmpnext; + + tmp = list; + + while (tmp != NULL) { + tmpnext = tmp->next; + + for (tmp1 = list1; tmp1 != NULL; tmp1 = tmp1->next) + if (!strcmp (tmp->data, tmp1->data)) + break; + + if (tmp1 == NULL) + list = g_list_remove_link (list, tmp); + + tmp = tmpnext; + } + + return list; +} + +static void +reduce_supported_app_list (GtkTreeModel *model, GtkTreeIter *iter, GList *list) +{ + GtkTreeIter child; + GList *type_list; + GValue value; + + value.g_type = G_TYPE_INVALID; + + if (gtk_tree_model_iter_has_child (model, iter)) { + gtk_tree_model_iter_nth_child (model, &child, iter, 0); + reduce_supported_app_list (model, &child, list); + } else { + do { + gtk_tree_model_get_value (model, iter, MIME_TYPE_COLUMN, &value); + + if (g_value_get_string (&value) != NULL) { + type_list = gnome_vfs_application_registry_get_applications (g_value_get_string (&value)); + list = intersect_lists (list, type_list); + g_list_free (type_list); + } + + g_value_unset (&value); + } while (gtk_tree_model_iter_next (model, iter)); + } +} + +GList * +find_supported_apps_for_category (GtkTreeModel *model, GtkTreeIter *iter) +{ + GList *ret; + + ret = find_possible_supported_apps (model, iter); + reduce_supported_app_list (model, iter, ret); + return ret; +} + diff --git a/capplets/file-types/mime-types-model.h b/capplets/file-types/mime-types-model.h index 15d5f1a85..46ac6cedb 100644 --- a/capplets/file-types/mime-types-model.h +++ b/capplets/file-types/mime-types-model.h @@ -36,13 +36,30 @@ enum { EXTENSIONS_COLUMN }; -GtkTreeModel *mime_types_model_new (void); +GtkTreeModel *mime_types_model_new (gboolean is_category_select); -GdkPixbuf *get_icon_pixbuf (const gchar *short_icon_name); +void reinsert_model_entry (GtkTreeModel *model, + GtkTreeIter *iter); + +GdkPixbuf *get_icon_pixbuf (const gchar *short_icon_name); gchar *get_description_for_protocol (const gchar *protocol_name); +gchar *get_category_name (GtkTreeModel *model, + GtkTreeIter *iter, + gboolean include_iter); +void get_insertion_point (GtkTreeStore *model, + const gchar *path_str, + GtkTreeIter *iter); + gboolean model_entry_is_protocol (GtkTreeModel *model, GtkTreeIter *iter); +gboolean model_entry_is_category (GtkTreeModel *model, + GtkTreeIter *iter); +gboolean model_entry_is_internet_services_category (GtkTreeModel *model, + GtkTreeIter *iter); + +GList *find_supported_apps_for_category (GtkTreeModel *model, + GtkTreeIter *iter); G_END_DECLS