gnome-control-center/capplets/file-types/file-types-capplet-dialogs.c
Rebecca Schulman 40622502a6 Add support for the "supported_uri_schemes" attributes in the mime
2001-01-26  Rebecca Schulman  <rebecka@eazel.com>
	Add support for the "supported_uri_schemes"
	attributes in the mime applications file,
	and changed can_open_uris to "expects_uris"
	because this attribute is more about
	the way arguments should be specified than
	about its capabilities of understanding
	locations.
	The supported uri schemes attributes is
	optional, and if it is not included, the
	value is assumed to be file.

	reviewed by: Pavel Cisler <pavel@eazel.com>

	* libgnomevfs/gnome-vfs-application-registry.h:
	Add the new function
	gnome_vfs_application_registry_supports_uri_scheme to the
	public api

	* libgnomevfs/gnome-vfs-application-registry.c: (application_new),
	(add_application_to_mime_type_table),
	(add_mime_type_to_application),
	(add_supported_uri_scheme_to_application),
	(remove_application_from_mime_type_table),
	(remove_mime_type_for_application),
	(supported_uri_scheme_list_copy),
	(gnome_vfs_application_registry_supports_uri_scheme),
	(gnome_vfs_application_registry_supports_mime_type),
	(gnome_vfs_application_registry_add_mime_type),
	(gnome_vfs_application_registry_remove_mime_type),
	Add  supported uri schemes functions to complement
	the current mime type functions
	and refactor the mime_type functions to share code with
	the new supported_uri_schemes functions where
	appropriate
	(application_clear_mime_types),
	(application_add_key),
	Add ability to parse the supported_uri_schemes attribute
	(gnome_vfs_application_registry_get_mime_application),
	(gnome_vfs_application_registry_save_mime_application):
	Add supported_uri_schemes to these functions

	* libgnomevfs/gnome-vfs-mime-handlers.h:
	* libgnomevfs/gnome-vfs-mime-handlers.c:
	(gnome_vfs_mime_get_short_list_applications),
	(gnome_vfs_mime_application_copy),
	(gnome_vfs_mime_application_free),
	(copy_str_list):
	Add supported_uri_schemes to the MimeApplication
	structure

	* data/mime/gnome-vfs.applications:
	Add some new "supported_uri_schemes".
	What I have added is not complete.
	* doc/mime-data-specification.txt:
	Add information about how user files can augment, but
	not replace information about applications' accepted mime
	types and supported uri schemes.  Add FIXMEs about
	how this isn't clearly correct.

	* mime-type-capplet/nautilus-mime-type-capplet-dialogs.c:
	(add_or_update_application), (show_new_application_window),
	(show_edit_application_window):
	Change can_open_uris to "Expects URIs"

	* test/test-mime-handlers-set.c: (main):
	* test/test-mime-handlers.c: (append_comma_and_scheme),
	(format_supported_uri_schemes_for_display), (print_application):
	Update tests, by adding new attribute
2001-01-26 23:13:49 +00:00

1356 lines
41 KiB
C

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* nautilus-mime-type-capplet-dialog.c
*
* Copyright (C) 2000 Eazel, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* 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.
*
* Authors: Jonathan Blandford <jrb@redhat.com>
* Gene Z. Ragan <gzr@eazel.com>
*/
#include <config.h>
#include <capplet-widget.h>
#include <ctype.h>
#include <gnome.h>
#include <gtk/gtk.h>
#include <gtk/gtklist.h>
#include <gtk/gtkbin.h>
#include <gtk/gtklistitem.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <libgnomevfs/gnome-vfs-application-registry.h>
#include <libgnomevfs/gnome-vfs-mime-info.h>
#include "nautilus-mime-type-capplet.h"
#include "nautilus-mime-type-capplet-dialogs.h"
/* gtk_window_set_default_width (and some other functions) use a
* magic undocumented number of -2 to mean "ignore this parameter".
*/
#define NO_DEFAULT_MAGIC_NUMBER -2
/* Scrolling list has no idea how tall to make itself. Its
* "natural height" is just enough to draw the scroll bar controls.
* Hardwire an initial window size here, but let user resize
* bigger or smaller.
*/
#define PROGRAM_CHOOSER_DEFAULT_HEIGHT 280
typedef struct {
GtkWidget *window;
GtkWidget *preferred_list;
GtkWidget *default_list;
} edit_dialog_details;
/* Global variables */
static edit_dialog_details *edit_application_details = NULL;
static edit_dialog_details *edit_component_details = NULL;
/* Local prototypes */
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 find_message_label_callback (GtkWidget *widget, gpointer callback_data);
static void find_message_label (GtkWidget *widget, const char *message);
static void
edit_applications_dialog_destroy (GtkWidget *widget, gpointer data)
{
g_free (edit_application_details);
edit_application_details = NULL;
}
static void
edit_component_dialog_destroy (GtkWidget *widget, gpointer data)
{
g_free (edit_component_details);
edit_component_details = NULL;
}
static gboolean
application_is_in_list (const char *search_id, GList *application_list)
{
GList *list_element;
GnomeVFSMimeApplication *application;
if (application_list == NULL || search_id == NULL) {
return FALSE;
}
/* Traverse the list looking for a match */
for (list_element = application_list; list_element != NULL; list_element = list_element->next) {
application = list_element->data;
if (strcmp (search_id, application->id) == 0) {
return TRUE;
}
}
return FALSE;
}
/*
* application_button_toggled_callback
*
* Check state of button. Based on state, determine whether to add or remove
* application from short list.
*/
static void
application_button_toggled_callback (GtkToggleButton *button, gpointer user_data)
{
const char *id;
const char *mime_type;
id = gtk_object_get_data (GTK_OBJECT (button), "application_id");
mime_type = gtk_object_get_data (GTK_OBJECT (button), "mime_type");
if (id == NULL || mime_type == NULL) {
return;
}
if (gtk_toggle_button_get_active (button)) {
/* Add to preferred list */
gnome_vfs_mime_add_application_to_short_list (mime_type, id);
} else {
/* Remove from preferred list */
gnome_vfs_mime_remove_application_from_short_list (mime_type, id);
}
}
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;
/* Get the application short list */
short_list = gnome_vfs_mime_get_short_list_applications (mime_type);
/* Get the list of all applications */
app_list = gnome_vfs_mime_get_all_applications (mime_type);
if (app_list != NULL) {
for (list_element = app_list; list_element != NULL; list_element = list_element->next) {
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);
/* 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);
/* 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);
}
}
static gboolean
component_is_in_list (const char *search_name, GList *component_list)
{
GList *list_element;
OAF_ServerInfo *info;
gchar *component_name;
if (component_list == NULL || search_name == NULL) {
return FALSE;
}
/* Traverse the list looking for a match */
for (list_element = component_list; list_element != NULL; list_element = list_element->next) {
info = list_element->data;
component_name = name_from_oaf_server_info (info);
if (strcmp (search_name, component_name) == 0) {
g_free (component_name);
return TRUE;
}
g_free (component_name);
}
return FALSE;
}
/*
* component_button_toggled_callback
*
* Check state of button. Based on state, determine whether to add or remove
* component from short list.
*/
static void
component_button_toggled_callback (GtkToggleButton *button, gpointer user_data)
{
const char *iid;
const char *mime_type;
iid = gtk_object_get_data (GTK_OBJECT (button), "component_iid");
mime_type = gtk_object_get_data (GTK_OBJECT (button), "mime_type");
if (iid == NULL || mime_type == NULL) {
return;
}
if (gtk_toggle_button_get_active (button)) {
/* Add to preferred list */
gnome_vfs_mime_add_component_to_short_list (mime_type, iid);
} else {
/* Remove from preferred list */
gnome_vfs_mime_remove_component_from_short_list (mime_type, iid);
}
}
static void
populate_default_components_box (GtkWidget *box, const char *mime_type)
{
GList *short_component_list;
GList *all_component_list, *list_element;
OAF_ServerInfo *info;
gchar *component_name;
GtkWidget *button;
/* Get short list of components */
short_component_list = gnome_vfs_mime_get_short_list_components (mime_type);
/* Get list of all components */
all_component_list = gnome_vfs_mime_get_all_components (mime_type);
if (all_component_list != NULL) {
for (list_element = all_component_list; list_element != NULL; list_element = list_element->next) {
info = list_element->data;
component_name = name_from_oaf_server_info (info);
button = gtk_check_button_new_with_label (component_name);
gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
/* Save IID and mime type*/
gtk_object_set_data_full (GTK_OBJECT (button), "component_iid", g_strdup (info->iid), g_free);
gtk_object_set_data_full (GTK_OBJECT (button), "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 (button),
component_is_in_list (component_name, short_component_list));
/* Connect to toggled signal */
gtk_signal_connect (GTK_OBJECT (button), "toggled",
GTK_SIGNAL_FUNC (component_button_toggled_callback), NULL);
g_free (component_name);
}
gnome_vfs_mime_component_list_free (all_component_list);
if (short_component_list != NULL) {
gnome_vfs_mime_component_list_free (short_component_list);
}
}
}
typedef struct {
GtkWidget *add_button;
GtkWidget *edit_button;
GtkWidget *delete_button;
} ButtonHolder;
static void
check_button_status (GtkList *list, GtkWidget *widget, ButtonHolder *button_holder)
{
int length = g_list_length (list->children);
if (length == 0) {
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);
}
}
/*
* initialize_edit_applications_dialog
*
* Set up dialog for default application list editing
*/
static void
initialize_edit_applications_dialog (const char *mime_type)
{
GtkWidget *main_vbox, *hbox;
GtkWidget *scroller, *label;
GtkWidget *button, *list;
char *label_text;
ButtonHolder *button_holder;
edit_application_details = g_new0 (edit_dialog_details, 1);
edit_application_details->window = gnome_dialog_new (_("Edit Applications List"),
GNOME_STOCK_BUTTON_OK,
NULL,
NULL);
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),
NO_DEFAULT_MAGIC_NUMBER,
PROGRAM_CHOOSER_DEFAULT_HEIGHT);
gtk_signal_connect (GTK_OBJECT (edit_application_details->window),
"destroy",
edit_applications_dialog_destroy,
NULL);
/* Main vertical box */
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 = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, FALSE, 0);
/* Add scrolling list of check buttons */
scroller = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start_defaults (GTK_BOX (main_vbox), scroller);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
list = gtk_list_new ();
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroller), list);
gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
/* Add edit buttons */
hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
button_holder = g_new (ButtonHolder, 1);
button = gtk_button_new_with_label (_("Add Application..."));
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_object_set_data_full (GTK_OBJECT (button), "mime_type", g_strdup (mime_type), g_free);
gtk_signal_connect (GTK_OBJECT (button), "clicked", show_new_application_window, list);
gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
button_holder->add_button = button;
button = gtk_button_new_with_label (_("Edit Application..."));
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", show_edit_application_window, list);
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
button_holder->edit_button = button;
button = gtk_button_new_with_label (_("Delete Application"));
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", delete_selected_application, list);
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
button_holder->delete_button = button;
/* 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);
populate_default_applications_list (list, mime_type);
gtk_widget_show_all (main_vbox);
}
/*
* initialize_edit_components_dialog
*
* Set up dialog for default component list editing
*/
static void
initialize_edit_components_dialog (const char *mime_type)
{
GtkWidget *main_vbox, *vbox;
GtkWidget *scroller, *label;
char *label_text;
edit_component_details = g_new0 (edit_dialog_details, 1);
edit_component_details->window = gnome_dialog_new (_("Edit Components List"),
GNOME_STOCK_BUTTON_OK,
NULL,
NULL);
gtk_container_set_border_width (GTK_CONTAINER (edit_component_details->window), GNOME_PAD);
gtk_window_set_policy (GTK_WINDOW (edit_component_details->window), FALSE, TRUE, FALSE);
gtk_window_set_default_size (GTK_WINDOW (edit_component_details->window),
NO_DEFAULT_MAGIC_NUMBER,
PROGRAM_CHOOSER_DEFAULT_HEIGHT);
gtk_signal_connect (GTK_OBJECT (edit_component_details->window),
"destroy",
edit_component_dialog_destroy,
NULL);
/* Main vertical box */
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 = gtk_label_new (label_text);
g_free (label_text);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
gtk_box_pack_start (GTK_BOX (main_vbox), label, FALSE, FALSE, 0);
/* Add scrolling list of check buttons */
scroller = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start_defaults (GTK_BOX (main_vbox), scroller);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroller), vbox);
populate_default_components_box (vbox, mime_type);
gtk_widget_show_all (main_vbox);
}
/*
* show_edit_applications_dialog
*
* Setup and display edit application list dialog
*/
void
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;
}
}
/*
* show_edit_components_dialog
*
* Setup and display edit component list dialog
*/
void
show_edit_components_dialog (const char *mime_type)
{
if (edit_component_details == NULL) {
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;
}
}
static GSList *
get_lang_list (void)
{
GSList *retval;
char *lang;
char * equal_char;
retval = NULL;
lang = g_getenv ("LANGUAGE");
if (!lang) {
lang = g_getenv ("LANG");
}
if (lang) {
equal_char = strchr (lang, '=');
if (equal_char != NULL) {
lang = equal_char + 1;
}
retval = g_slist_prepend (retval, lang);
}
return retval;
}
static gboolean
str_has_prefix (const char *haystack, const char *needle)
{
const char *h, *n;
/* Eat one character at a time. */
h = haystack == NULL ? "" : haystack;
n = needle == NULL ? "" : needle;
do {
if (*n == '\0') {
return TRUE;
}
if (*h == '\0') {
return FALSE;
}
} while (*h++ == *n++);
return FALSE;
}
char *
name_from_oaf_server_info (OAF_ServerInfo *server)
{
const char *view_as_name;
char *display_name;
GSList *langs;
display_name = NULL;
langs = get_lang_list ();
view_as_name = oaf_server_info_prop_lookup (server, "nautilus:view_as_name", langs);
if (view_as_name == NULL) {
view_as_name = oaf_server_info_prop_lookup (server, "name", langs);
}
if (view_as_name == NULL) {
view_as_name = server->iid;
}
g_slist_free (langs);
/* if the name is an OAFIID, clean it up for display */
if (str_has_prefix (view_as_name, "OAFIID:")) {
char *display_name, *colon_ptr;
display_name = g_strdup (view_as_name + 7);
colon_ptr = strchr (display_name, ':');
if (colon_ptr) {
*colon_ptr = '\0';
}
return display_name;
}
return g_strdup(view_as_name);
}
static void
find_message_label_callback (GtkWidget *widget, gpointer callback_data)
{
find_message_label (widget, callback_data);
}
static void
find_message_label (GtkWidget *widget, const char *message)
{
char *text;
/* Turn on the flag if we find a label with the message
* in it.
*/
if (GTK_IS_LABEL (widget)) {
gtk_label_get (GTK_LABEL (widget), &text);
if (strcmp (text, message) == 0) {
gtk_object_set_data (GTK_OBJECT (gtk_widget_get_toplevel (widget)),
"message label", widget);
}
}
/* Recurse for children. */
if (GTK_IS_CONTAINER (widget)) {
gtk_container_foreach (GTK_CONTAINER (widget),
find_message_label_callback,
(char *) message);
}
}
static GnomeDialog *
show_message_box (const char *message,
const char *dialog_title,
const char *type,
const char *button_one,
const char *button_two,
GtkWindow *parent)
{
GtkWidget *box;
GtkLabel *message_label;
g_assert (dialog_title != NULL);
box = gnome_message_box_new (message, type, button_one, button_two, NULL);
gtk_window_set_title (GTK_WINDOW (box), dialog_title);
/* A bit of a hack. We want to use gnome_message_box_new,
* but we want the message to be wrapped. So, we search
* for the label with this message so we can mark it.
*/
find_message_label (box, message);
message_label = GTK_LABEL (gtk_object_get_data (GTK_OBJECT (box), "message label"));
gtk_label_set_line_wrap (message_label, TRUE);
if (parent != NULL) {
gnome_dialog_set_parent (GNOME_DIALOG (box), parent);
}
gtk_widget_show (box);
return GNOME_DIALOG (box);
}
static void
display_upper_case_dialog (void)
{
char *message;
GnomeDialog *dialog;
message = _("The MIME type entered contained upper case characters. "
"Upper case characters were changed to lower case for you.");
dialog = show_message_box (message, _("Add New MIME Type"),
GNOME_MESSAGE_BOX_INFO, GNOME_STOCK_BUTTON_OK,
NULL, NULL);
gnome_dialog_run_and_close (dialog);
}
char *
nautilus_mime_type_capplet_show_new_mime_window (void)
{
GtkWidget *dialog;
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;
mime_type = NULL;
upper_case_alert = FALSE;
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);
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);
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);
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);
gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
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);
}
/* Fall through to close dialog */
break;
case 1:
default:
break;
}
gnome_dialog_close (GNOME_DIALOG (dialog));
if (upper_case_alert) {
display_upper_case_dialog ();
}
return mime_type;
}
static void
add_extension_clicked (GtkWidget *widget, gpointer data)
{
GtkList *extension_list;
char *new_extension;
GtkWidget *new_list_item;
GList *items_list;
g_assert (GTK_IS_LIST (data));
extension_list = GTK_LIST (data);
new_extension = nautilus_mime_type_capplet_show_new_extension_window ();
new_list_item = gtk_list_item_new_with_label (new_extension);
gtk_widget_show (new_list_item);
items_list = g_list_append (NULL, new_list_item);
gtk_list_append_items (GTK_LIST (extension_list), items_list);
g_free (new_extension);
/* GtkList takes ownership of the List we append. DO NOT free it. */
}
static void
remove_extension_clicked (GtkWidget *widget, gpointer data)
{
GtkList *list;
GList *selection_copy, *temp;
g_assert (GTK_IS_LIST (data));
list = GTK_LIST (data);
/* this is so fucking crapy !!! */
/* you have to make a copy of the selection list before
passing it to remove_items because before removing the
widget from the List, it modifies the list.
So, when you remove it, the list is not valid anymore */
selection_copy = NULL;
for (temp = list->selection; temp != NULL; temp = temp->next) {
selection_copy = g_list_prepend (selection_copy, temp->data);
}
if (list->selection != NULL) {
gtk_list_remove_items (GTK_LIST (list), selection_copy);
gtk_list_select_item (GTK_LIST (list), 0);
}
g_list_free (selection_copy);
}
static void
extension_list_selected (GtkWidget *list, GtkWidget *child, gpointer data)
{
GtkWidget *button;
g_assert (GTK_IS_BUTTON (data));
button = GTK_WIDGET (data);
gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);
}
static void
extension_list_deselected (GtkWidget *list, GtkWidget *child, gpointer data)
{
GtkWidget *button;
g_assert (GTK_IS_BUTTON (data));
button = GTK_WIDGET (data);
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
}
static char *
get_extensions_from_gtk_list (GtkList *list)
{
GList *temp;
GtkLabel *label;
char *extension, *extensions, *temp_text;
extensions = NULL;
for (temp = list->children; temp != NULL; temp = temp->next) {
label = GTK_LABEL (GTK_BIN (temp->data)->child);
gtk_label_get (GTK_LABEL (label), &extension);
temp_text = g_strconcat (extension, " ", extensions, NULL);
g_free (extensions);
extensions = temp_text;
}
return extensions;
}
char *
nautilus_mime_type_capplet_show_change_extension_window (const char *mime_type)
{
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *list;
char *extensions_list;
dialog = gnome_dialog_new (_("File Extensions "),
GNOME_STOCK_BUTTON_OK,
GNOME_STOCK_BUTTON_CANCEL,
NULL);
gnome_dialog_set_default (GNOME_DIALOG (dialog), 1);
gnome_dialog_set_close (GNOME_DIALOG (dialog), FALSE);
hbox = gtk_hbox_new (FALSE, GNOME_PAD_BIG);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
list = gtk_list_new ();
/* the right buttons */
{
GtkWidget *vbox;
vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_("Add..."));
gtk_signal_connect (GTK_OBJECT (button), "clicked",
add_extension_clicked, list);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
button = gtk_button_new_with_label (_(" Remove "));
gtk_widget_set_sensitive (button, FALSE);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
remove_extension_clicked, list);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (""), FALSE, FALSE, 0);
}
/* The left list */
{
GtkWidget *viewport;
GList *extensions_list, *widget_list, *temp;
viewport = gtk_viewport_new (NULL, NULL);
gtk_box_pack_start (GTK_BOX (hbox), viewport, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (list), "select_child",
extension_list_selected, button);
gtk_signal_connect (GTK_OBJECT (list), "unselect_child",
extension_list_deselected, button);
gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
gtk_container_add (GTK_CONTAINER (viewport), list);
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) {
widget_list = g_list_append (widget_list,
gtk_list_item_new_with_label ((char *) temp->data));
}
gtk_list_append_items (GTK_LIST (list), widget_list);
}
gtk_list_select_item (GTK_LIST (list), 0);
}
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;
}
gnome_dialog_close (GNOME_DIALOG (dialog));
return extensions_list;
}
char *
nautilus_mime_type_capplet_show_new_extension_window (void)
{
GtkWidget *mime_entry;
GtkWidget *label;
GtkWidget *hbox;
GtkWidget *dialog;
char *new_extension;
dialog = gnome_dialog_new (_("Add New Extension"), GNOME_STOCK_BUTTON_OK,
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"));
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 (_("Extension:"));
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);
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_widget_show_all (GNOME_DIALOG (dialog)->vbox);
/* Set focus to text entry widget */
gtk_window_set_focus (GTK_WINDOW (dialog), 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;
}
gnome_dialog_close (GNOME_DIALOG (dialog));
return new_extension;
}
/* add_or_update_application
*
* Create or update a GnomeVFSMimeApplication and register
* it with the mime database.
*/
static void
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;
/* Check for empty strings. Command can be empty. */
if (name[0] == '\0') {
return;
}
mime_type = nautilus_mime_type_capplet_get_selected_item_mime_type ();
g_assert (mime_type != NULL);
/* 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;
app.name = (char *)name;
app.command = (char *)command;
app.can_open_multiple_files = multiple;
app.expects_uris = expects_uris;
/* FIXME: We should be getting this information */
app.supported_uri_schemes = NULL;
app.requires_terminal = FALSE;
if (update) {
original = gnome_vfs_mime_application_new_from_id (name);
if (original == NULL) {
const char *original_id;
GList *selection;
GtkListItem *item;
int position;
/* 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;
}
/* Get application id and info */
item = GTK_LIST_ITEM (selection->data);
if (item == NULL) {
return;
}
original_id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
if (original_id == NULL) {
return;
}
/* Remove original application data */
gnome_vfs_application_registry_remove_mime_type (original_id, mime_type);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_remove_application_from_short_list (mime_type, original_id);
/* Remove widget from list */
position = gtk_list_child_position (GTK_LIST (list), GTK_WIDGET (item));
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);
}
}
gnome_vfs_application_registry_save_mime_application (&app);
gnome_vfs_application_registry_add_mime_type (name, mime_type);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_add_application_to_short_list (mime_type, app.id);
}
static void
add_item_to_application_list (GtkWidget *list, const char *name, const char *mime_type, 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);
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);
}
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);
/* Connect to toggled signal */
gtk_signal_connect (GTK_OBJECT (check_button), "toggled",
GTK_SIGNAL_FUNC (application_button_toggled_callback), NULL);
}
static void
show_new_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;
char *name, *command, *mime_type;
gboolean multiple, uri;
dialog = gnome_dialog_new (_("New Application"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL);
/* Create table */
table = gtk_table_new (3, 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);
/* 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_table_attach_defaults ( GTK_TABLE (table), command_entry, 1, 2, 1, 2);
/* Open Behavior frame */
/* FIXME: 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);
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);
uri_check_box = gtk_check_button_new_with_label (_("Expects URIs as arguments"));
gtk_box_pack_start (GTK_BOX (frame_vbox), uri_check_box, FALSE, FALSE, 0);
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:
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);
}
case 1:
gtk_widget_destroy (dialog);
break;
default:
break;
}
}
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;
GtkListItem *item;
/* 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;
}
/* Get application id and info */
item = GTK_LIST_ITEM (selection->data);
if (item == NULL) {
return;
}
id = gtk_object_get_data (GTK_OBJECT (item), "application_id");
if (id == NULL) {
return;
}
application = gnome_vfs_mime_application_new_from_id (id);
if (application == NULL) {
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);
/* 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);
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;
}
}
static void
delete_selected_application (GtkWidget *button, GtkWidget *list)
{
GtkListItem *item;
const char *mime_type, *name;
GList *selection;
/* Get selected list item */
selection = GTK_LIST (list)->selection;
if (selection == NULL) {
return;
}
item = GTK_LIST_ITEM (selection->data);
if (item == NULL) {
return;
}
name = 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);
gnome_vfs_application_registry_sync ();
gnome_vfs_mime_remove_application_from_short_list (mime_type, name);
}
/* Remove widget from list */
gtk_container_remove (GTK_CONTAINER (list), GTK_WIDGET (item));
}