summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog26
-rw-r--r--Makefile.am3
-rw-r--r--configure.in1
-rw-r--r--data/nautilus.xml.in59
-rw-r--r--libnautilus-private/apps_nautilus_preferences.schemas.in39
-rw-r--r--libnautilus-private/nautilus-autorun.c627
-rw-r--r--libnautilus-private/nautilus-autorun.h30
-rw-r--r--libnautilus-private/nautilus-file-attributes.h1
-rw-r--r--libnautilus-private/nautilus-file-private.h5
-rw-r--r--libnautilus-private/nautilus-file.c8
-rw-r--r--libnautilus-private/nautilus-file.h1
-rw-r--r--libnautilus-private/nautilus-global-preferences.c8
-rw-r--r--libnautilus-private/nautilus-global-preferences.h2
-rw-r--r--libnautilus-private/nautilus-program-choosing.c30
-rw-r--r--nautilus-autorun-software.desktop.in.in15
-rw-r--r--src/Makefile.am7
-rw-r--r--src/file-manager/fm-directory-view.c28
-rw-r--r--src/nautilus-application.c241
-rw-r--r--src/nautilus-autorun-software.c254
-rw-r--r--src/nautilus-file-management-properties.c152
-rw-r--r--src/nautilus-file-management-properties.glade973
-rw-r--r--src/nautilus-window-manage-views.c37
-rw-r--r--src/nautilus-x-content-bar.c297
-rw-r--r--src/nautilus-x-content-bar.h67
24 files changed, 2202 insertions, 709 deletions
diff --git a/ChangeLog b/ChangeLog
index 2444c6b39..6eb22cbc3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2008-01-17 Alexander Larsson <alexl@redhat.com>
+
+ * libnautilus-private/nautilus-file.[ch]:
+ * libnautilus-private/nautilus-file-attributes.h:
+ * libnautilus-private/nautilus-file-private.h:
+ Add GMount attribute to NautilusFile.
+ (not implemented yet)
+
+ * Makefile.am:
+ * configure.in:
+ * data/nautilus.xml.in:
+ * libnautilus-private/apps_nautilus_preferences.schemas.in:
+ * libnautilus-private/nautilus-autorun.[ch]:
+ * libnautilus-private/nautilus-global-preferences.c:
+ * libnautilus-private/nautilus-global-preferences.h:
+ * libnautilus-private/nautilus-program-choosing.c:
+ * src/Makefile.am:
+ * src/file-manager/fm-directory-view.c:
+ * src/nautilus-application.c:
+ * src/nautilus-autorun-software.c: Added.
+ * src/nautilus-file-management-properties.c:
+ * src/nautilus-file-management-properties.glade:
+ * src/nautilus-window-manage-views.c:
+ * src/nautilus-x-content-bar.[ch]: Added.
+ More work on autorun and x-content types from David Zeuthen
+
2008-01-16 Alexander Larsson <alexl@redhat.com>
* src/nautilus-application.c:
diff --git a/Makefile.am b/Makefile.am
index 79416d461..7e134d916 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,8 @@ desktop_in_files = \
nautilus-home.desktop.in \
nautilus-computer.desktop.in \
nautilus-folder-handler.desktop.in \
- nautilus-file-management-properties.desktop.in
+ nautilus-file-management-properties.desktop.in \
+ nautilus-autorun-software.desktop.in
SUBDIRS = \
libnautilus-extension \
diff --git a/configure.in b/configure.in
index ec9d3d039..a1695817c 100644
--- a/configure.in
+++ b/configure.in
@@ -484,6 +484,7 @@ nautilus-file-management-properties.desktop.in
nautilus-home.desktop.in
nautilus.desktop.in
nautilus-folder-handler.desktop.in
+nautilus-autorun-software.desktop.in
po/Makefile.in
src/Makefile
src/file-manager/Makefile
diff --git a/data/nautilus.xml.in b/data/nautilus.xml.in
index 5d6a312d7..0a32b2a06 100644
--- a/data/nautilus.xml.in
+++ b/data/nautilus.xml.in
@@ -13,11 +13,11 @@
<mime-type type="x-content/video-vcd">
<!-- http://en.wikipedia.org/wiki/Video_CD -->
- <_comment>VCD Video</_comment>
+ <_comment>Video CD</_comment>
</mime-type>
<mime-type type="x-content/video-svcd">
<!-- http://en.wikipedia.org/wiki/Super_Video_CD -->
- <_comment>SVCD Video</_comment>
+ <_comment>Super Video CD</_comment>
</mime-type>
<mime-type type="x-content/video-dvd">
<!-- http://en.wikipedia.org/wiki/DVD-Video -->
@@ -34,26 +34,57 @@
<_comment>Compact Disc Audio</_comment>
</mime-type>
- <mime-type type="x-content/blank-media">
+ <mime-type type="x-content/blank-cd">
<!-- http://en.wikipedia.org/wiki/Compact_Disc -->
+ <_comment>Blank CD Disc</_comment>
+ </mime-type>
+
+ <mime-type type="x-content/blank-dvd">
<!-- http://en.wikipedia.org/wiki/DVD -->
- <_comment>Blank Media</_comment>
+ <_comment>Blank DVD Disc</_comment>
</mime-type>
- <mime-type type="x-content/software-autostart">
- <!-- http://www.freedesktop.org/wiki/Specifications/autostart-spec -->
- <_comment>Software</_comment>
+ <mime-type type="x-content/blank-bd">
+ <!-- http://en.wikipedia.org/wiki/Blu-ray_Disc -->
+ <_comment>Blank Blu-Ray Disc</_comment>
</mime-type>
- <!-- TODO:
+ <mime-type type="x-content/blank-hddvd">
+ <!-- http://en.wikipedia.org/wiki/HD_DVD -->
+ <_comment>Blank HD DVD Disc</_comment>
+ </mime-type>
+
+ <mime-type type="x-content/audio-dvd">
+ <!-- http://en.wikipedia.org/wiki/DVD-Audio -->
+ <_comment>DVD Audio</_comment>
+ </mime-type>
+
+ <mime-type type="x-content/video-bluray">
+ <!-- http://en.wikipedia.org/wiki/Blu-ray_Disc -->
+ <_comment>Blu-Ray Video</_comment>
+ </mime-type>
- - Blu-Ray video : http://en.wikipedia.org/wiki/Blu-ray_Disc
- - HD-DVD video : http://en.wikipedia.org/wiki/HD_DVD
- - DVD-Audio : http://en.wikipedia.org/wiki/DVD-Audio
+ <mime-type type="x-content/video-hddvd">
+ <!-- http://en.wikipedia.org/wiki/HD_DVD -->
+ <_comment>HD DVD Video</_comment>
+ </mime-type>
- - Photo CD : http://en.wikipedia.org/wiki/Photo_CD
- - Picture CD : http://en.wikipedia.org/wiki/Picture_CD
+ <mime-type type="x-content/image-picturecd">
+ <!-- http://en.wikipedia.org/wiki/Picture_CD -->
+ <_comment>Picture CD</_comment>
+ </mime-type>
+ <mime-type type="x-content/audio-player">
+ <!-- see fd.o hal spec -->
+ <_comment>Portable Audio Player</_comment>
+ </mime-type>
+
+ <mime-type type="x-content/software">
+ <!-- http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html -->
+ <_comment>Software</_comment>
+ </mime-type>
+
+ <!-- TODO:
- SACD : http://en.wikipedia.org/wiki/Super_Audio_CD
- This might be dead and appear to be totally unsupported anyway
@@ -62,8 +93,6 @@
- Enhanced DVD Movie (see link 1. below)
- ??
- - music player (x-content/music-player)
-
- picture files
- audio files
- video files
diff --git a/libnautilus-private/apps_nautilus_preferences.schemas.in b/libnautilus-private/apps_nautilus_preferences.schemas.in
index 9d0ca0ce1..3e606106b 100644
--- a/libnautilus-private/apps_nautilus_preferences.schemas.in
+++ b/libnautilus-private/apps_nautilus_preferences.schemas.in
@@ -102,6 +102,21 @@
</schema>
<schema>
+ <key>/schemas/apps/nautilus/preferences/media_autorun_never_</key>
+ <applyto>/apps/nautilus/preferences/media_autorun_never</applyto>
+ <owner>nautilus</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Never prompt or autorun/autostart programs when media is inserted</short>
+ <long>
+ If set to true, then Nautilus will never prompt nor autorun/autostart
+ programs when media is inserted.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/nautilus/preferences/media_autorun_x_content_ask</key>
<applyto>/apps/nautilus/preferences/media_autorun_x_content_ask</applyto>
<owner>nautilus</owner>
@@ -109,9 +124,9 @@
<list_type>string</list_type>
<default>[]</default>
<locale name="C">
- <short>list of x-content/* types to ask the user what to do on insertion</short>
+ <short>List of x-content/* types to ask the user what to do on insertion</short>
<long>
- list of x-content/* types to ask the user what to do on insertion
+ List of x-content/* types to ask the user what to do on insertion.
</long>
</locale>
</schema>
@@ -124,9 +139,25 @@
<list_type>string</list_type>
<default>[]</default>
<locale name="C">
- <short>list of x-content/* types to ignore on insertion</short>
+ <short>List of x-content/* where to prompt the user on insertion</short>
+ <long>
+ List of x-content/* types to ask the user what to do on insertion.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/nautilus/preferences/media_autorun_x_content_open_folder</key>
+ <applyto>/apps/nautilus/preferences/media_autorun_x_content_open_folder</applyto>
+ <owner>nautilus</owner>
+ <type>list</type>
+ <list_type>string</list_type>
+ <default>[]</default>
+ <locale name="C">
+ <short>List of x-content/* types where a folder window should be opened</short>
<long>
- list of x-content/* types to ask the user what to do on insertion
+ List of x-content/* types where a folder window should be opened
+ on insertion.
</long>
</locale>
</schema>
diff --git a/libnautilus-private/nautilus-autorun.c b/libnautilus-private/nautilus-autorun.c
index 6ed1a6f42..eaf0bede3 100644
--- a/libnautilus-private/nautilus-autorun.c
+++ b/libnautilus-private/nautilus-autorun.c
@@ -29,6 +29,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gio/gdesktopappinfo.h>
+#include <X11/XKBlib.h>
#include <eel/eel-glib-extensions.h>
#include <eel/eel-stock-dialogs.h>
@@ -38,12 +39,15 @@
#include "nautilus-file-operations.h"
#include "nautilus-autorun.h"
#include "nautilus-program-choosing.h"
+#include "nautilus-open-with-dialog.h"
+#include "nautilus-desktop-icon-file.h"
enum
{
AUTORUN_ASK,
AUTORUN_IGNORE,
AUTORUN_APP,
+ AUTORUN_OPEN_FOLDER,
AUTORUN_SEP,
};
enum
@@ -56,24 +60,34 @@ enum
};
void
-nautilus_autorun_get_preferences (const char *x_content_type, gboolean *pref_ask, gboolean *pref_ignore)
+nautilus_autorun_get_preferences (const char *x_content_type,
+ gboolean *pref_ask,
+ gboolean *pref_ignore,
+ gboolean *pref_open_folder)
{
char **x_content_ask;
char **x_content_ignore;
+ char **x_content_open_folder;
g_return_if_fail (pref_ask != NULL);
g_return_if_fail (pref_ignore != NULL);
+ g_return_if_fail (pref_open_folder != NULL);
*pref_ask = FALSE;
*pref_ignore = FALSE;
+ *pref_open_folder = FALSE;
x_content_ask = eel_preferences_get_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_ASK);
x_content_ignore = eel_preferences_get_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_IGNORE);
+ x_content_open_folder = eel_preferences_get_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
if (x_content_ask != NULL) {
*pref_ask = eel_g_strv_find (x_content_ask, x_content_type) != -1;
}
if (x_content_ignore != NULL) {
*pref_ignore = eel_g_strv_find (x_content_ignore, x_content_type) != -1;
}
+ if (x_content_open_folder != NULL) {
+ *pref_open_folder = eel_g_strv_find (x_content_open_folder, x_content_type) != -1;
+ }
g_strfreev (x_content_ignore);
g_strfreev (x_content_ask);
@@ -112,13 +126,15 @@ add_elem_to_str_array (char **v, const char *s)
void
-nautilus_autorun_set_preferences (const char *x_content_type, gboolean pref_ask, gboolean pref_ignore)
+nautilus_autorun_set_preferences (const char *x_content_type, gboolean pref_ask, gboolean pref_ignore, gboolean pref_open_folder)
{
char **x_content_ask;
char **x_content_ignore;
+ char **x_content_open_folder;
x_content_ask = eel_preferences_get_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_ASK);
x_content_ignore = eel_preferences_get_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_IGNORE);
+ x_content_open_folder = eel_preferences_get_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
remove_elem_from_str_array (x_content_ask, x_content_type);
if (pref_ask) {
@@ -132,6 +148,13 @@ nautilus_autorun_set_preferences (const char *x_content_type, gboolean pref_ask,
}
eel_preferences_set_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_IGNORE, x_content_ignore);
+ remove_elem_from_str_array (x_content_open_folder, x_content_type);
+ if (pref_open_folder) {
+ x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type);
+ }
+ eel_preferences_set_string_array (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER, x_content_open_folder);
+
+ g_strfreev (x_content_open_folder);
g_strfreev (x_content_ignore);
g_strfreev (x_content_ask);
@@ -156,12 +179,24 @@ combo_box_separator_func (GtkTreeModel *model,
typedef struct
{
+ guint changed_signal_id;
+ GtkWidget *combo_box;
+
gboolean update_settings;
NautilusAutorunComboBoxChanged changed_cb;
gpointer user_data;
} NautilusAutorunComboBoxData;
static void
+nautilus_autorun_combobox_data_destroy (NautilusAutorunComboBoxData *data)
+{
+ /* signal handler may be automatically disconnected by destroying the widget */
+ if (g_signal_handler_is_connected (G_OBJECT (data->combo_box), data->changed_signal_id))
+ g_signal_handler_disconnect (G_OBJECT (data->combo_box), data->changed_signal_id);
+ g_free (data);
+}
+
+static void
combo_box_changed (GtkComboBox *combo_box,
NautilusAutorunComboBoxData *data)
{
@@ -193,26 +228,34 @@ combo_box_changed (GtkComboBox *combo_box,
switch (type) {
case AUTORUN_ASK:
if (data->changed_cb != NULL) {
- data->changed_cb (TRUE, FALSE, NULL, data->user_data);
+ data->changed_cb (TRUE, FALSE, FALSE, NULL, data->user_data);
}
if (data->update_settings) {
- nautilus_autorun_set_preferences (x_content_type, TRUE, FALSE);
+ nautilus_autorun_set_preferences (x_content_type, TRUE, FALSE, FALSE);
}
break;
case AUTORUN_IGNORE:
if (data->changed_cb != NULL) {
- data->changed_cb (FALSE, TRUE, NULL, data->user_data);
+ data->changed_cb (FALSE, TRUE, FALSE, NULL, data->user_data);
}
if (data->update_settings) {
- nautilus_autorun_set_preferences (x_content_type, FALSE, TRUE);
+ nautilus_autorun_set_preferences (x_content_type, FALSE, TRUE, FALSE);
+ }
+ break;
+ case AUTORUN_OPEN_FOLDER:
+ if (data->changed_cb != NULL) {
+ data->changed_cb (FALSE, FALSE, TRUE, NULL, data->user_data);
+ }
+ if (data->update_settings) {
+ nautilus_autorun_set_preferences (x_content_type, FALSE, FALSE, TRUE);
}
break;
case AUTORUN_APP:
if (data->changed_cb != NULL) {
- data->changed_cb (FALSE, FALSE, app_info, data->user_data);
+ data->changed_cb (FALSE, FALSE, FALSE, app_info, data->user_data);
}
if (data->update_settings) {
- nautilus_autorun_set_preferences (x_content_type, FALSE, FALSE);
+ nautilus_autorun_set_preferences (x_content_type, FALSE, FALSE, FALSE);
g_app_info_set_as_default_for_type (app_info,
x_content_type,
NULL);
@@ -230,7 +273,6 @@ out:
g_free (x_content_type);
}
-
void
nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
const char *x_content_type,
@@ -251,14 +293,16 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
int num_apps;
gboolean pref_ask;
gboolean pref_ignore;
+ gboolean pref_open_folder;
NautilusAutorunComboBoxData *data;
GtkCellRenderer *renderer;
- nautilus_autorun_get_preferences (x_content_type, &pref_ask, &pref_ignore);
+ nautilus_autorun_get_preferences (x_content_type, &pref_ask, &pref_ignore, &pref_open_folder);
icon_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
set_active = -1;
+ data = NULL;
app_info_list = g_app_info_get_all_for_type (x_content_type);
default_app_info = g_app_info_get_default_for_type (x_content_type, FALSE);
@@ -310,7 +354,7 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
gtk_list_store_append (list_store, &iter);
pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
- GTK_STOCK_CANCEL,
+ GTK_STOCK_CLOSE,
icon_size,
0,
NULL);
@@ -321,8 +365,23 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
COLUMN_AUTORUN_X_CONTENT_TYPE, x_content_type,
COLUMN_AUTORUN_ITEM_TYPE, AUTORUN_IGNORE,
-1);
- g_object_unref (pixbuf);
-
+ g_object_unref (pixbuf);
+
+ gtk_list_store_append (list_store, &iter);
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ "nautilus",
+ icon_size,
+ 0,
+ NULL);
+ gtk_list_store_set (list_store, &iter,
+ COLUMN_AUTORUN_PIXBUF, pixbuf,
+ COLUMN_AUTORUN_NAME, _("Open Folder"),
+ COLUMN_AUTORUN_APP_INFO, NULL,
+ COLUMN_AUTORUN_X_CONTENT_TYPE, x_content_type,
+ COLUMN_AUTORUN_ITEM_TYPE, AUTORUN_OPEN_FOLDER,
+ -1);
+ g_object_unref (pixbuf);
+
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
COLUMN_AUTORUN_PIXBUF, NULL,
@@ -332,7 +391,7 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
COLUMN_AUTORUN_ITEM_TYPE, AUTORUN_SEP,
-1);
- for (l = app_info_list, n = include_ask ? 3 : 2; l != NULL; l = l->next, n++) {
+ for (l = app_info_list, n = include_ask ? 4 : 3; l != NULL; l = l->next, n++) {
GIcon *icon;
NautilusIconInfo *icon_info;
char *open_string;
@@ -349,7 +408,7 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
g_object_unref (icon_info);
open_string = g_strdup_printf (_("Open %s"), g_app_info_get_name (app_info));
-
+
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
COLUMN_AUTORUN_PIXBUF, pixbuf,
@@ -376,15 +435,17 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (list_store));
+ gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo_box));
+
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
- "pixbuf", 0,
+ "pixbuf", COLUMN_AUTORUN_PIXBUF,
NULL);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer,
- "text", 1,
+ "text", COLUMN_AUTORUN_NAME,
NULL);
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo_box), combo_box_separator_func, NULL, NULL);
@@ -392,10 +453,13 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
gtk_widget_set_sensitive (combo_box, FALSE);
} else {
+ gtk_widget_set_sensitive (combo_box, TRUE);
if (pref_ask && include_ask) {
gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
} else if (pref_ignore) {
gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), include_ask ? 1 : 0);
+ } else if (pref_open_folder) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), include_ask ? 2 : 1);
} else if (set_active != -1) {
gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), set_active);
} else {
@@ -406,17 +470,18 @@ nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
data->update_settings = update_settings;
data->changed_cb = changed_cb;
data->user_data = user_data;
-
- g_signal_connect (G_OBJECT (combo_box),
- "changed",
- G_CALLBACK (combo_box_changed),
- data);
-
- /* TODO: unref 'data' when combo box goes bye-bye */
+ data->combo_box = combo_box;
+ data->changed_signal_id = g_signal_connect (G_OBJECT (combo_box),
+ "changed",
+ G_CALLBACK (combo_box_changed),
+ data);
}
-}
-#include <X11/XKBlib.h>
+ g_object_set_data_full (G_OBJECT (combo_box),
+ "nautilus_autorun_combobox_data",
+ data,
+ (GDestroyNotify) nautilus_autorun_combobox_data_destroy);
+}
static gboolean
is_shift_pressed (void)
@@ -441,51 +506,217 @@ is_shift_pressed (void)
/*-- BEGIN MOVE TO GIO --*/
static gboolean
-_dir_exists (GFile *mount_root, const char *dirname)
+_check_nonempty_dir (GFile *mount_root, const char *dirname)
{
GFile *file;
GFileInfo *file_info;
-
+ GFileEnumerator *file_enum;
+ gboolean ret;
+
+ ret = FALSE;
+
file = g_file_get_child (mount_root, dirname);
+ file_enum = g_file_enumerate_children (file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (file_enum != NULL) {
+ file_info = g_file_enumerator_next_file (file_enum, NULL, NULL);
+ if (file_info != NULL) {
+ ret = TRUE;
+ g_object_unref (file_info);
+ }
+ g_object_unref (file_enum);
+ }
+ g_object_unref (file);
+
+ return ret;
+}
+
+static gboolean
+_check_file (GFile *mount_root, const char *file_path, gboolean must_be_executable)
+{
+ GFile *file;
+ GFileInfo *file_info;
+ gboolean ret;
+
+ ret = FALSE;
+
+ file = g_file_get_child (mount_root, file_path);
file_info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
if (file_info != NULL) {
+ if (must_be_executable) {
+ if (g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))
+ ret = TRUE;
+ } else {
+ ret = TRUE;
+ }
g_object_unref (file_info);
}
g_object_unref (file);
- return file_info != NULL;
+ return ret;
}
-static char **
-_g_mount_guess_content_type_for_mount_root (GFile *mount_root,
- GError **error)
+/**
+ * _g_mount_guess_content_type:
+ * @mount: a #GMount.
+ * @force_rescan: Whether to force a rescan of the content. Otherwise a cached result will be used if available.
+ * @error: return location for error or %NULL to ignore.
+ *
+ * Tries to guess the type of content stored on @mount. Returns one or
+ * more textual identifiers of well-known content types (typically
+ * prefixed with "x-content/"). TODO: link to fd.o spec about this.
+ *
+ * This function may do I/O and thus may take a long time to
+ * complete. For the async version, see
+ * _g_mount_guess_content_type_async().
+ *
+ * Returns: a %NULL terminated array of content types or %NULL on
+ * error. Caller should free this array with g_strfreev() when done
+ * with it.
+ **/
+char **
+_g_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GError **error)
{
+ unsigned int n;
char **ret;
GPtrArray *types;
-
+ GFile *root;
+ GVolume *volume;
+ char *disc_type = NULL;
+
+ /* TODO: We can't really sensibly cache anything right now..
+ * But when moved to gio this can be done.
+ */
+
types = g_ptr_array_new ();
-
- /* TODO: analyze mount_root and add more content types as needed */
- if (g_file_has_uri_scheme (mount_root, "cdda")) {
+ root = g_mount_get_root (mount);
+ volume = g_mount_get_volume (mount);
+
+ /* Take advantage of information from HAL's quirk lists that maps a given
+ * make/model of (what appears to be just) a storage device to it's intended
+ * use.
+ *
+ * E.g. a mapping saying that a storage device is a music player, a digital
+ * camera, a videocam, a video play back device, a gps reader.. and so on...
+ */
+ if (volume != NULL) {
+ char **stor_device_caps;
+
+ /* See gvfs/hal/ghalvolume.c:do_update_from_hal()...
+ *
+ * This hack, using g_object_set|get_data() can be
+ * removed once g_mount_guess_content_type() is in gio
+ * and the actual code for probing media is in the
+ * gvfs hal backend.
+ */
+ stor_device_caps = (char **) g_object_get_data (G_OBJECT (volume), "hal-storage-device-capabilities");
+ if (stor_device_caps != NULL) {
+ for (n = 0; stor_device_caps[n] != NULL; n++) {
+ if (strcmp (stor_device_caps[n], "portable_audio_player") == 0) {
+ g_ptr_array_add (types, g_strdup ("x-content/audio-player"));
+ }
+ /* TODO: map other hal capabilities to x-content/ types */
+ }
+ }
+
+ disc_type = (char *) g_object_get_data (G_OBJECT (volume), "hal-volume.disc.type");
+ }
+
+ if (g_file_has_uri_scheme (root, "cdda")) {
g_ptr_array_add (types, g_strdup ("x-content/audio-cdda"));
goto no_sniff;
}
+
+ if (g_file_has_uri_scheme (root, "burn")) {
+ if (disc_type != NULL) {
+ if (g_str_has_prefix (disc_type, "dvd")) {
+ g_ptr_array_add (types, g_strdup ("x-content/blank-dvd"));
+ } else if (g_str_has_prefix (disc_type, "hddvd")) {
+ g_ptr_array_add (types, g_strdup ("x-content/blank-hddvd"));
+ } else if (g_str_has_prefix (disc_type, "bd")) {
+ g_ptr_array_add (types, g_strdup ("x-content/blank-bd"));
+ } else {
+ /* assume CD */
+ g_ptr_array_add (types, g_strdup ("x-content/blank-cd"));
+ }
+ }
+ goto no_sniff;
+ }
- if (_dir_exists (mount_root, "DCIM") ||
- _dir_exists (mount_root, "dcim")) {
+ if (_check_nonempty_dir (root, "DCIM") ||
+ _check_nonempty_dir (root, "dcim")) {
g_ptr_array_add (types, g_strdup ("x-content/image-dcf"));
}
- if (_dir_exists (mount_root, "VIDEO_TS") ||
- _dir_exists (mount_root, "video_ts")) {
+ if (_check_nonempty_dir (root, "VIDEO_TS") &&
+ disc_type != NULL) {
g_ptr_array_add (types, g_strdup ("x-content/video-dvd"));
}
+ if (_check_nonempty_dir (root, "AUDIO_TS") &&
+ disc_type != NULL) {
+ g_ptr_array_add (types, g_strdup ("x-content/audio-dvd"));
+ }
+
+
+ /* see http://www.ccs.neu.edu/home/bchafy/cdb/info/info.html for various docs */
+
+ if (_check_nonempty_dir (root, "SVCD") &&
+ _check_nonempty_dir (root, "EXT") &&
+ _check_nonempty_dir (root, "MPEG-2") &&
+ disc_type != NULL) {
+ /* http://everything2.com/index.pl?node_id=1009222 */
+ g_ptr_array_add (types, g_strdup ("x-content/video-svcd"));
+ }
+
+ if (_check_nonempty_dir (root, "VCD") &&
+ _check_nonempty_dir (root, "MPEGAV") &&
+ disc_type != NULL) {
+ /* http://www.herongyang.com/CD-DVD/VCD-Movie-File-Directory-Structure.html */
+ g_ptr_array_add (types, g_strdup ("x-content/video-vcd"));
+ }
+
+ if (_check_nonempty_dir (root, "BDAV") &&
+ _check_nonempty_dir (root, "BDMV") &&
+ disc_type != NULL) {
+ /* http://www.blu-raydisc.com/Section-13470/Section-13890/Index.html */
+ g_ptr_array_add (types, g_strdup ("x-content/video-bluray"));
+ }
+
+ if (_check_nonempty_dir (root, "HVDVD_TS") && /* not a typo; should really spell HVDVD_TS */
+ disc_type != NULL) {
+ /* http://www.cdfreaks.com/reviews/CDFreaks--CES-2006/Page-5.html */
+ g_ptr_array_add (types, g_strdup ("x-content/video-hddvd"));
+ }
+
+ if (_check_nonempty_dir (root, "PICTURES") &&
+ disc_type != NULL) {
+ /* http://www.re.org/kristin/picturecd.html */
+ g_ptr_array_add (types, g_strdup ("x-content/image-picturecd"));
+ }
+
+ if (_check_file (root, ".autorun", TRUE) ||
+ _check_file (root, "autorun", TRUE) ||
+ _check_file (root, "autorun.sh", TRUE) ||
+ _check_file (root, "autorun.exe", TRUE) || _check_file (root, "AUTORUN.EXE", TRUE) ||
+ _check_file (root, "autorun.inf", FALSE) || _check_file (root, "AUTORUN.INF", FALSE)) {
+ /* http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html */
+
+ /* http://bugzilla.gnome.org/show_bug.cgi?id=509823#c3 for the autorun.exe and autorun.inf stuff */
+ g_ptr_array_add (types, g_strdup ("x-content/software"));
+ }
+
+
no_sniff:
if (types->len == 0) {
@@ -495,12 +726,16 @@ no_sniff:
g_ptr_array_add (types, NULL);
ret = (char **) g_ptr_array_free (types, FALSE);
}
-
+
+ if (volume != NULL)
+ g_object_unref (volume);
+ g_object_unref (root);
return ret;
}
typedef struct {
char **guessed_content_type;
+ gboolean force_rescan;
} GuessContentData;
static void
@@ -512,8 +747,8 @@ guess_content_thread (GSimpleAsyncResult *res,
GError *error = NULL;
op = g_simple_async_result_get_op_res_gpointer (res);
-
- op->guessed_content_type = _g_mount_guess_content_type_for_mount_root (G_FILE (object), &error);
+
+ op->guessed_content_type = _g_mount_guess_content_type (G_MOUNT (object), op->force_rescan, &error);
if (error != NULL) {
g_simple_async_result_set_from_error (res, error);
@@ -523,28 +758,32 @@ guess_content_thread (GSimpleAsyncResult *res,
/**
* _g_mount_guess_content_type_async:
- * @mount_root: a #GFile.
+ * @mount: a #GMount.
+ * @force_rescan: Whether to force a rescan of the content. Otherwise a cached result will be used if available.
* @cancellable: optional #GCancellable object, %NULL to ignore.
* @callback: a #GAsyncReadyCallback.
* @user_data: user data passed to @callback.
*
- * Like _g_mount_guess_content_type_async() but analyzes a given sub
- * directory instead.
+ * This is an asynchronous version of _g_mount_guess_content_type(),
+ * and is finished by calling _g_mount_guess_content_type_finish() with
+ * the @mount and #GAsyncResults data returned in the @callback.
*/
-static void
-_g_mount_guess_content_type_for_mount_root_async (GFile *mount_root,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+void
+_g_mount_guess_content_type_async (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GSimpleAsyncResult *res;
GuessContentData *op;
op = g_new0 (GuessContentData, 1);
- res = g_simple_async_result_new (G_OBJECT (mount_root),
+ op->force_rescan = force_rescan;
+ res = g_simple_async_result_new (G_OBJECT (mount),
callback,
user_data,
- _g_mount_guess_content_type_for_mount_root_async);
+ _g_mount_guess_content_type_async);
g_simple_async_result_set_op_res_gpointer (res, op, g_free);
g_simple_async_result_run_in_thread (res, guess_content_thread, G_PRIORITY_DEFAULT, cancellable);
@@ -552,28 +791,29 @@ _g_mount_guess_content_type_for_mount_root_async (GFile *mount_roo
}
/**
- * _g_mount_guess_content_type_for_mount_root_finish:
- * @mount_root: a #GFile.
+ * _g_mount_guess_content_type_finish:
+ * @mount: a #GMount.
* @result: a #GAsyncResult.
* @error: a #GError location to store the error occuring, or %NULL to
* ignore.
*
- * Like _g_mount_guess_content_type_finish() but analyzes a given sub
- * directory instead.
+ * Finishes guessing content types of @mount. If any errors occured
+ * during the operation, @error will be set to contain the errors and
+ * %FALSE will be returned.
*
* Returns: a %NULL terminated array of content types or %NULL on
* error. Caller should free this array with g_strfreev() when done
* with it.
**/
-static char **
-_g_mount_guess_content_type_for_mount_root_finish (GFile *mount_root,
- GAsyncResult *result,
- GError **error)
+char **
+_g_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
GuessContentData *op;
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == _g_mount_guess_content_type_for_mount_root_async);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == _g_mount_guess_content_type_async);
op = g_simple_async_result_get_op_res_gpointer (simple);
return op->guessed_content_type;
@@ -584,19 +824,26 @@ _g_mount_guess_content_type_for_mount_root_finish (GFile *mount_ro
typedef struct
{
+ GtkWidget *dialog;
+
GMount *mount;
gboolean should_eject;
gboolean selected_ignore;
+ gboolean selected_open_folder;
GAppInfo *selected_app;
gboolean remember;
char *x_content_type;
+
+ NautilusAutorunOpenWindow open_window_func;
+ gpointer user_data;
} AutorunDialogData;
-static void
-autorun_launch_for_mount (GMount *mount, GAppInfo *app_info)
+
+void
+nautilus_autorun_launch_for_mount (GMount *mount, GAppInfo *app_info)
{
GFile *root;
NautilusFile *file;
@@ -613,6 +860,31 @@ autorun_launch_for_mount (GMount *mount, GAppInfo *app_info)
g_list_free (files);
}
+static void autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data);
+
+static void
+autorun_dialog_destroy (AutorunDialogData *data)
+{
+ g_signal_handlers_disconnect_by_func (G_OBJECT (data->mount),
+ G_CALLBACK (autorun_dialog_mount_unmounted),
+ data);
+
+ gtk_widget_destroy (GTK_WIDGET (data->dialog));
+ if (data->selected_app != NULL) {
+ g_object_unref (data->selected_app);
+ }
+ g_object_unref (data->mount);
+ g_free (data->x_content_type);
+ g_free (data);
+}
+
+static void
+autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data)
+{
+ /* remove the dialog if the media is unmounted */
+ autorun_dialog_destroy (data);
+}
+
static void
autorun_dialog_response (GtkDialog *dialog, gint response, AutorunDialogData *data)
{
@@ -620,13 +892,6 @@ autorun_dialog_response (GtkDialog *dialog, gint response, AutorunDialogData *da
case GTK_RESPONSE_NONE:
/* window was closed */
break;
- case 0:
- /* eject/unmount */
- nautilus_file_operations_unmount_mount (NULL,
- data->mount,
- data->should_eject,
- FALSE);
- break;
case GTK_RESPONSE_CANCEL:
break;
case GTK_RESPONSE_OK:
@@ -634,35 +899,33 @@ autorun_dialog_response (GtkDialog *dialog, gint response, AutorunDialogData *da
if (data->remember) {
/* make sure we don't ask again */
- nautilus_autorun_set_preferences (data->x_content_type, FALSE, data->selected_ignore);
- if (!data->selected_ignore && data->selected_app != NULL) {
+ nautilus_autorun_set_preferences (data->x_content_type, FALSE, data->selected_ignore, data->selected_open_folder);
+ if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) {
g_app_info_set_as_default_for_type (data->selected_app,
data->x_content_type,
NULL);
}
} else {
/* make sure we do ask again */
- nautilus_autorun_set_preferences (data->x_content_type, TRUE, FALSE);
+ nautilus_autorun_set_preferences (data->x_content_type, TRUE, FALSE, FALSE);
}
- if (!data->selected_ignore && data->selected_app != NULL) {
- autorun_launch_for_mount (data->mount, data->selected_app);
+ if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) {
+ nautilus_autorun_launch_for_mount (data->mount, data->selected_app);
+ } else if (!data->selected_ignore && data->selected_open_folder) {
+ if (data->open_window_func != NULL)
+ data->open_window_func (data->mount, data->user_data);
}
break;
}
- gtk_widget_destroy (GTK_WIDGET (dialog));
- if (data->selected_app != NULL) {
- g_object_unref (data->selected_app);
- }
- g_object_unref (data->mount);
- g_free (data->x_content_type);
- g_free (data);
+ autorun_dialog_destroy (data);
}
static void
autorun_combo_changed (gboolean selected_ask,
gboolean selected_ignore,
+ gboolean selected_open_folder,
GAppInfo *selected_app,
gpointer user_data)
{
@@ -673,6 +936,7 @@ autorun_combo_changed (gboolean selected_ask,
}
data->selected_app = selected_app != NULL ? g_object_ref (selected_app) : NULL;
data->selected_ignore = selected_ignore;
+ data->selected_open_folder = selected_open_folder;
}
@@ -683,8 +947,9 @@ autorun_always_toggled (GtkToggleButton *togglebutton, AutorunDialogData *data)
}
-static void
-do_autorun_for_content_type (GMount *mount, const char *x_content_type)
+/* returns TRUE if a folder window should be opened */
+static gboolean
+do_autorun_for_content_type (GMount *mount, const char *x_content_type, NautilusAutorunOpenWindow open_window_func, gpointer user_data)
{
AutorunDialogData *data;
GtkWidget *dialog;
@@ -705,27 +970,35 @@ do_autorun_for_content_type (GMount *mount, const char *x_content_type)
gboolean user_forced_dialog;
gboolean pref_ask;
gboolean pref_ignore;
+ gboolean pref_open_folder;
char *media_greeting;
+ gboolean ret;
+ ret = FALSE;
mount_name = NULL;
user_forced_dialog = is_shift_pressed ();
- nautilus_autorun_get_preferences (x_content_type, &pref_ask, &pref_ignore);
+ nautilus_autorun_get_preferences (x_content_type, &pref_ask, &pref_ignore, &pref_open_folder);
if (user_forced_dialog) {
goto show_dialog;
}
- if (!pref_ask && !pref_ignore) {
+ if (!pref_ask && !pref_ignore && !pref_open_folder) {
GAppInfo *app_info;
app_info = g_app_info_get_default_for_type (x_content_type, FALSE);
if (app_info != NULL) {
- autorun_launch_for_mount (mount, app_info);
+ nautilus_autorun_launch_for_mount (mount, app_info);
}
goto out;
}
+ if (pref_open_folder) {
+ ret = TRUE;
+ goto out;
+ }
+
if (pref_ignore) {
goto out;
}
@@ -746,6 +1019,7 @@ show_dialog:
icon_info = nautilus_icon_info_lookup (icon, icon_size);
pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size);
g_object_unref (icon_info);
+ g_object_unref (icon);
image = gtk_image_new_from_pixbuf (pixbuf);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
gtk_box_pack_start_defaults (GTK_BOX (hbox), image);
@@ -760,22 +1034,40 @@ show_dialog:
label = gtk_label_new (NULL);
+ /* Customize greeting for well-known x-content types */
if (strcmp (x_content_type, "x-content/audio-cdda") == 0) {
- media_greeting = _("You have just inserted an Audio CD");
+ media_greeting = _("You have just inserted an Audio CD.");
+ } else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) {
+ media_greeting = _("You have just inserted an Audio DVD.");
} else if (strcmp (x_content_type, "x-content/video-dvd") == 0) {
- media_greeting = _("You have just inserted a Video DVD");
+ media_greeting = _("You have just inserted a Video DVD.");
} else if (strcmp (x_content_type, "x-content/video-vcd") == 0) {
- media_greeting = _("You have just inserted a Video CD");
+ media_greeting = _("You have just inserted a Video CD.");
} else if (strcmp (x_content_type, "x-content/video-svcd") == 0) {
- media_greeting = _("You have just inserted a Super Video CD");
+ media_greeting = _("You have just inserted a Super Video CD.");
+ } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
+ media_greeting = _("You have just inserted a blank CD.");
+ } else if (strcmp (x_content_type, "x-content/blank-dvd") == 0) {
+ media_greeting = _("You have just inserted a blank DVD.");
+ } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
+ media_greeting = _("You have just inserted a blank Blu-Ray disc.");
+ } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
+ media_greeting = _("You have just inserted a blank HD DVD.");
+ } else if (strcmp (x_content_type, "x-content/image-photocd") == 0) {
+ media_greeting = _("You have just inserted a Photo CD.");
+ } else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) {
+ media_greeting = _("You have just inserted a Picture CD.");
} else if (strcmp (x_content_type, "x-content/image-dcf") == 0) {
- media_greeting = _("You have just inserted media with digital photos");
- } else if (strcmp (x_content_type, "x-content/blank-media") == 0) {
- media_greeting = _("You have just inserted blank media");
+ media_greeting = _("You have just inserted media with digital photos.");
+ } else if (strcmp (x_content_type, "x-content/audio-player") == 0) {
+ media_greeting = _("You have just inserted a digital audio player.");
+ } else if (strcmp (x_content_type, "x-content/software") == 0) {
+ media_greeting = _("You have just inserted media with software intended to be automatically started.");
} else {
- media_greeting = _("You have just inserted media");
+ /* fallback to generic greeting */
+ media_greeting = _("You have just inserted media.");
}
- markup = g_strdup_printf ("<big><b>%s. %s</b></big>", media_greeting, _("Choose what application to launch."));
+ markup = g_strdup_printf ("<big><b>%s %s</b></big>", media_greeting, _("Choose what application to launch."));
gtk_label_set_markup (GTK_LABEL (label), markup);
g_free (markup);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
@@ -793,11 +1085,14 @@ show_dialog:
gtk_box_pack_start_defaults (GTK_BOX (vbox), label);
data = g_new0 (AutorunDialogData, 1);
+ data->dialog = dialog;
data->mount = g_object_ref (mount);
data->remember = !pref_ask;
data->selected_ignore = pref_ignore;
data->x_content_type = g_strdup (x_content_type);
data->selected_app = g_app_info_get_default_for_type (x_content_type, FALSE);
+ data->open_window_func = open_window_func;
+ data->user_data = user_data;
combo_box = gtk_combo_box_new ();
nautilus_autorun_prepare_combo_box (combo_box, x_content_type, FALSE, FALSE, autorun_combo_changed, data);
@@ -844,8 +1139,29 @@ show_dialog:
G_CALLBACK (autorun_dialog_response),
data);
+ g_signal_connect (G_OBJECT (data->mount),
+ "unmounted",
+ G_CALLBACK (autorun_dialog_mount_unmounted),
+ data);
+
out:
g_free (mount_name);
+ return ret;
+}
+
+typedef struct {
+ GMount *mount;
+ NautilusAutorunOpenWindow open_window_func;
+ gpointer user_data;
+} AutorunData;
+
+
+static void
+autorun_open_folder_for_mount (AutorunData *data)
+{
+ if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT_OPEN) &&
+ data->open_window_func != NULL)
+ data->open_window_func (data->mount, data->user_data);
}
static void
@@ -855,30 +1171,46 @@ autorun_guessed_content_type_callback (GObject *source_object,
{
GError *error;
char **guessed_content_type;
- GMount *mount = G_MOUNT (user_data);
-
+ AutorunData *data = user_data;
+ gboolean open_folder;
+
+ open_folder = FALSE;
+
error = NULL;
- guessed_content_type = _g_mount_guess_content_type_for_mount_root_finish (G_FILE (source_object), res, &error);
+ guessed_content_type = _g_mount_guess_content_type_finish (G_MOUNT (source_object), res, &error);
if (error != NULL) {
g_warning ("Unabled to guess content type for mount: %s", error->message);
g_error_free (error);
} else {
- if (guessed_content_type != NULL) {
+ if (guessed_content_type != NULL && g_strv_length (guessed_content_type) > 0) {
int n;
for (n = 0; guessed_content_type[n] != NULL; n++) {
- do_autorun_for_content_type (mount, guessed_content_type[n]);
+ if (do_autorun_for_content_type (data->mount, guessed_content_type[n],
+ data->open_window_func, data->user_data)) {
+ open_folder = TRUE;
+ }
}
g_strfreev (guessed_content_type);
+ } else {
+ open_folder = TRUE;
}
}
- g_object_unref (mount);
+ /* only open the folder once.. */
+ if (open_folder)
+ autorun_open_folder_for_mount (data);
+
+ g_object_unref (data->mount);
+ g_free (data);
}
void
-nautilus_autorun (GMount *mount)
+nautilus_autorun (GMount *mount, NautilusAutorunOpenWindow open_window_func, gpointer user_data)
{
- GFile *root;
+ AutorunData *data;
+
+ if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_NEVER))
+ return;
/* TODO: only do this for local mounts */
@@ -886,10 +1218,81 @@ nautilus_autorun (GMount *mount)
* we do this asynchronously (in another thread) since it
* requires doing I/O.
*/
- root = g_mount_get_root (mount);
- _g_mount_guess_content_type_for_mount_root_async (root,
- NULL,
- autorun_guessed_content_type_callback,
- g_object_ref (mount));
- g_object_unref (root);
+
+ data = g_new0 (AutorunData, 1);
+ data->mount = g_object_ref (mount);
+ data->open_window_func = open_window_func;
+ data->user_data = user_data;
+
+ _g_mount_guess_content_type_async (mount,
+ TRUE,
+ NULL,
+ autorun_guessed_content_type_callback,
+ data);
+}
+
+char **
+nautilus_autorun_get_x_content_types_for_file (NautilusFile *nautilus_file,
+ GMount **out_mount,
+ gboolean force_rescan,
+ gboolean include_child_dirs)
+{
+ GMount *mount;
+ char **x_content_types;
+
+ x_content_types = NULL;
+
+ g_return_val_if_fail (nautilus_file != NULL, NULL);
+
+ mount = NULL;
+ if (g_type_is_a (G_OBJECT_TYPE (nautilus_file), NAUTILUS_TYPE_DESKTOP_ICON_FILE)) {
+ NautilusDesktopIconFile *desktop_icon_file = NAUTILUS_DESKTOP_ICON_FILE (nautilus_file);
+ NautilusDesktopLink *desktop_link;
+
+ desktop_link = nautilus_desktop_icon_file_get_link (desktop_icon_file);
+ if (desktop_link != NULL) {
+ if (nautilus_desktop_link_get_link_type (desktop_link) == NAUTILUS_DESKTOP_LINK_MOUNT) {
+ mount = nautilus_desktop_link_get_mount (desktop_link);
+ }
+ g_object_unref (desktop_link);
+ }
+ } else {
+ GFile *file;
+ file = nautilus_file_get_location (nautilus_file);
+ if (file != NULL) {
+ mount = g_file_find_enclosing_mount (file, NULL, NULL);
+ if (mount != NULL) {
+ GFile *mount_root;
+ mount_root = g_mount_get_root (mount);
+ if (!include_child_dirs) {
+ if (!g_file_equal (mount_root, file)) {
+ g_object_unref (mount);
+ mount = NULL;
+ }
+ }
+ g_object_unref (mount_root);
+ }
+ g_object_unref (file);
+ }
+ }
+
+
+ /* TODO: handle files in computer:///.
+ *
+ * Also need to handle those in libnautilus-private/nautilus-program-choosing.c:nautilus_launch_application()
+ *
+ * These NautilusFile instances are of class NautilusVFSFile.. URI is 'computer:///CompactFlash%20Drive.drive'
+ */
+
+ if (mount != NULL) {
+ /* since we always guess the content type at mount type, we're guaranteed
+ * to get the cached results
+ */
+ x_content_types = _g_mount_guess_content_type (mount, force_rescan, NULL);
+ if (out_mount != NULL)
+ *out_mount = g_object_ref (mount);
+ g_object_unref (mount);
+ }
+
+ return x_content_types;
}
diff --git a/libnautilus-private/nautilus-autorun.h b/libnautilus-private/nautilus-autorun.h
index 3726e29f4..131a49851 100644
--- a/libnautilus-private/nautilus-autorun.h
+++ b/libnautilus-private/nautilus-autorun.h
@@ -44,11 +44,29 @@
#include <eel/eel-background.h>
#include <libnautilus-private/nautilus-file.h>
+void _g_mount_guess_content_type_async (GMount *mount,
+ gboolean force_rescan,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+char ** _g_mount_guess_content_type_finish (GMount *mount,
+ GAsyncResult *result,
+ GError **error);
+
+char ** _g_mount_guess_content_type (GMount *mount,
+ gboolean force_rescan,
+ GError **error);
+
+
typedef void (*NautilusAutorunComboBoxChanged) (gboolean selected_ask,
gboolean selected_ignore,
+ gboolean selected_open_folder,
GAppInfo *selected_app,
gpointer user_data);
+typedef void (*NautilusAutorunOpenWindow) (GMount *mount, gpointer user_data);
+
void nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
const char *x_content_type,
gboolean include_ask,
@@ -56,10 +74,16 @@ void nautilus_autorun_prepare_combo_box (GtkWidget *combo_box,
NautilusAutorunComboBoxChanged changed_cb,
gpointer user_data);
-void nautilus_autorun_set_preferences (const char *x_content_type, gboolean pref_ask, gboolean pref_ignore);
-void nautilus_autorun_get_preferences (const char *x_content_type, gboolean *pref_ask, gboolean *pref_ignore);
+void nautilus_autorun_set_preferences (const char *x_content_type, gboolean pref_ask, gboolean pref_ignore, gboolean pref_open_folder);
+void nautilus_autorun_get_preferences (const char *x_content_type, gboolean *pref_ask, gboolean *pref_ignore, gboolean *pref_open_folder);
+
+void nautilus_autorun (GMount *mount, NautilusAutorunOpenWindow open_window_func, gpointer user_data);
-void nautilus_autorun (GMount *mount);
+char **nautilus_autorun_get_x_content_types_for_file (NautilusFile *file,
+ GMount **out_mount,
+ gboolean force_rescan,
+ gboolean include_child_dirs);
+void nautilus_autorun_launch_for_mount (GMount *mount, GAppInfo *app_info);
#endif /* NAUTILUS_AUTORUN_H */
diff --git a/libnautilus-private/nautilus-file-attributes.h b/libnautilus-private/nautilus-file-attributes.h
index d263cbec6..a660e48f2 100644
--- a/libnautilus-private/nautilus-file-attributes.h
+++ b/libnautilus-private/nautilus-file-attributes.h
@@ -40,6 +40,7 @@ typedef enum {
NAUTILUS_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT = 1 << 7,
NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO = 1 << 8,
NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL = 1 << 9,
+ NAUTILUS_FILE_ATTRIBUTE_MOUNT = 1 << 10,
} NautilusFileAttributes;
#endif /* NAUTILUS_FILE_ATTRIBUTES_H */
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
index efc9c84ec..01a2f6146 100644
--- a/libnautilus-private/nautilus-file-private.h
+++ b/libnautilus-private/nautilus-file-private.h
@@ -137,6 +137,9 @@ struct NautilusFileDetails
GHashTable *extension_attributes;
GHashTable *pending_extension_attributes;
+ /* Mount for mountpoint or the references GMount for a "mountable" */
+ GMount *mount;
+
/* boolean fields: bitfield to save space, since there can be
many NautilusFile objects. */
@@ -166,6 +169,8 @@ struct NautilusFileDetails
eel_boolean_bit mime_list_failed : 1;
eel_boolean_bit mime_list_is_up_to_date : 1;
+ eel_boolean_bit mount_is_up_to_date : 1;
+
eel_boolean_bit got_top_left_text : 1;
eel_boolean_bit got_large_top_left_text : 1;
eel_boolean_bit top_left_text_is_up_to_date : 1;
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index bd519a0e8..2f1f650eb 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -5606,6 +5606,14 @@ nautilus_file_is_mountpoint (NautilusFile *file)
return file->details->is_mountpoint;
}
+GMount *
+nautilus_file_get_mount (NautilusFile *file)
+{
+ if (file->details->mount) {
+ return g_object_ref (file->details->mount);
+ }
+ return NULL;
+}
/**
* nautilus_file_is_broken_symbolic_link
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
index 20c46a2cf..d735e1ea5 100644
--- a/libnautilus-private/nautilus-file.h
+++ b/libnautilus-private/nautilus-file.h
@@ -171,6 +171,7 @@ gboolean nautilus_file_is_mime_type (Nautilu
gboolean nautilus_file_is_launchable (NautilusFile *file);
gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
gboolean nautilus_file_is_mountpoint (NautilusFile *file);
+GMount * nautilus_file_get_mount (NautilusFile *file);
char * nautilus_file_get_volume_free_space (NautilusFile *file);
char * nautilus_file_get_volume_name (NautilusFile *file);
char * nautilus_file_get_symbolic_link_target_path (NautilusFile *file);
diff --git a/libnautilus-private/nautilus-global-preferences.c b/libnautilus-private/nautilus-global-preferences.c
index 55498d7f3..5f4f49860 100644
--- a/libnautilus-private/nautilus-global-preferences.c
+++ b/libnautilus-private/nautilus-global-preferences.c
@@ -492,6 +492,10 @@ static const PreferenceDefault preference_defaults[] = {
PREFERENCE_BOOLEAN,
GINT_TO_POINTER (TRUE)
},
+ { NAUTILUS_PREFERENCES_MEDIA_AUTORUN_NEVER,
+ PREFERENCE_BOOLEAN,
+ GINT_TO_POINTER (FALSE)
+ },
{ NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_ASK,
PREFERENCE_STRING_ARRAY,
"", NULL, NULL, NULL
@@ -500,6 +504,10 @@ static const PreferenceDefault preference_defaults[] = {
PREFERENCE_STRING_ARRAY,
"", NULL, NULL, NULL
},
+ { NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER,
+ PREFERENCE_STRING_ARRAY,
+ "", NULL, NULL, NULL
+ },
{ NULL }
};
diff --git a/libnautilus-private/nautilus-global-preferences.h b/libnautilus-private/nautilus-global-preferences.h
index 4e4432024..e6d030190 100644
--- a/libnautilus-private/nautilus-global-preferences.h
+++ b/libnautilus-private/nautilus-global-preferences.h
@@ -51,8 +51,10 @@ G_BEGIN_DECLS
#define NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT_OPEN "preferences/media_automount_open"
/* Autorun options */
+#define NAUTILUS_PREFERENCES_MEDIA_AUTORUN_NEVER "preferences/media_autorun_never"
#define NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_ASK "preferences/media_autorun_x_content_ask"
#define NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_IGNORE "preferences/media_autorun_x_content_ignore"
+#define NAUTILUS_PREFERENCES_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER "preferences/media_autorun_x_content_open_folder"
/* Trash options */
#define NAUTILUS_PREFERENCES_CONFIRM_TRASH "preferences/confirm_trash"
diff --git a/libnautilus-private/nautilus-program-choosing.c b/libnautilus-private/nautilus-program-choosing.c
index 73bb0810d..5f675af8f 100644
--- a/libnautilus-private/nautilus-program-choosing.c
+++ b/libnautilus-private/nautilus-program-choosing.c
@@ -49,6 +49,8 @@
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
+#include "nautilus-desktop-icon-file.h"
+
extern char **environ;
/* Cut and paste from gdkspawn-x11.c */
@@ -261,10 +263,30 @@ nautilus_launch_application (GAppInfo *application,
location = NULL;
- if (nautilus_file_is_nautilus_link (file)) {
- uri = nautilus_file_get_activation_uri (file);
- location = g_file_new_for_uri (uri);
- g_free (uri);
+ if (g_type_is_a (G_OBJECT_TYPE (file), NAUTILUS_TYPE_DESKTOP_ICON_FILE)) {
+ NautilusDesktopIconFile *desktop_icon_file = NAUTILUS_DESKTOP_ICON_FILE (file);
+ NautilusDesktopLink *desktop_link;
+
+ desktop_link = nautilus_desktop_icon_file_get_link (desktop_icon_file);
+ if (desktop_link != NULL) {
+ if (nautilus_desktop_link_get_link_type (desktop_link) == NAUTILUS_DESKTOP_LINK_MOUNT) {
+ GMount *mount;
+ mount = nautilus_desktop_link_get_mount (desktop_link);
+ if (mount != NULL) {
+ location = g_mount_get_root (mount);
+ g_object_unref (mount);
+ }
+ }
+ g_object_unref (desktop_link);
+ }
+ }
+
+ if (location == NULL) {
+ if (nautilus_file_is_nautilus_link (file)) {
+ uri = nautilus_file_get_activation_uri (file);
+ location = g_file_new_for_uri (uri);
+ g_free (uri);
+ }
}
if (location == NULL) {
diff --git a/nautilus-autorun-software.desktop.in.in b/nautilus-autorun-software.desktop.in.in
new file mode 100644
index 000000000..b3c48ef2c
--- /dev/null
+++ b/nautilus-autorun-software.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Autorun Prompt
+TryExec=nautilus-autorun-software
+Exec=nautilus-autorun-software %u
+Icon=application-x-executable
+NoDisplay=true
+Terminal=false
+StartupNotify=true
+Type=Application
+MimeType=x-content/software;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=nautilus
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-Version=@VERSION@
diff --git a/src/Makefile.am b/src/Makefile.am
index f31c3ce07..53740a20a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS=file-manager
bin_PROGRAMS= \
nautilus \
nautilus-file-management-properties \
+ nautilus-autorun-software \
$(NULL)
# nautilus-connect-server
@@ -130,6 +131,8 @@ nautilus_SOURCES = \
nautilus-window-toolbars.c \
nautilus-window.c \
nautilus-window.h \
+ nautilus-x-content-bar.c \
+ nautilus-x-content-bar.h \
nautilus-zoom-control.c \
nautilus-zoom-control.h \
$(NULL)
@@ -140,6 +143,10 @@ nautilus_file_management_properties_SOURCES= \
nautilus-file-management-properties-main.c \
$(NULL)
+nautilus_autorun_software_SOURCES= \
+ nautilus-autorun-software.c \
+ $(NULL)
+
# Disabled for now in the gio world
#nautilus_connect_server_SOURCES= \
# nautilus-connect-server-dialog.c \
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index 916c49a8b..f8c1fceee 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -95,6 +95,7 @@
#include <libnautilus-private/nautilus-trash-monitor.h>
#include <libnautilus-private/nautilus-ui-utilities.h>
#include <libnautilus-private/nautilus-signaller.h>
+#include <libnautilus-private/nautilus-autorun.h>
#include <unistd.h>
/* Minimum starting update inverval */
@@ -4158,6 +4159,27 @@ add_application_to_open_with_menu (FMDirectoryView *view,
g_free (tip);
}
+static void
+add_x_content_apps (NautilusFile *file, GList **applications)
+{
+ char **x_content_types;
+
+ g_return_if_fail (applications != NULL);
+
+ x_content_types = nautilus_autorun_get_x_content_types_for_file (file, NULL, FALSE, FALSE);
+
+ if (x_content_types != NULL) {
+ unsigned int n;
+ for (n = 0; x_content_types[n] != NULL; n++) {
+ char *x_content_type = x_content_types[n];
+ GList *app_info_for_x_content_type;
+
+ app_info_for_x_content_type = g_app_info_get_all_for_type (x_content_type);
+ *applications = g_list_concat (*applications, app_info_for_x_content_type);
+ }
+ g_strfreev (x_content_types);
+ }
+}
static void
reset_open_with_menu (FMDirectoryView *view, GList *selection)
@@ -4191,6 +4213,7 @@ reset_open_with_menu (FMDirectoryView *view, GList *selection)
filter_default = (selection != NULL);
for (node = selection; node != NULL; node = node->next) {
+
file = NAUTILUS_FILE (node->data);
other_applications_visible &=
@@ -4208,6 +4231,11 @@ reset_open_with_menu (FMDirectoryView *view, GList *selection)
applications = nautilus_mime_get_applications_for_files (selection);
}
+ if (g_list_length (selection) == 1) {
+ add_x_content_apps (NAUTILUS_FILE (selection->data), &applications);
+ }
+
+
num_applications = g_list_length (applications);
for (node = applications, index = 0; node != NULL; node = node->next, index++) {
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index b7198eb08..f772b6461 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -118,6 +118,11 @@ static void mount_added_callback (GVolumeMonitor *mo
static void volume_added_callback (GVolumeMonitor *monitor,
GVolume *volume,
NautilusApplication *application);
+static void drive_connected_callback (GVolumeMonitor *monitor,
+ GDrive *drive,
+ NautilusApplication *application);
+static void drive_listen_for_eject_button (GDrive *drive,
+ NautilusApplication *application);
static void update_session (gpointer callback_data);
static void init_session (void);
static gboolean is_kdesktop_present (void);
@@ -165,6 +170,55 @@ nautilus_application_get_n_windows (void)
}
static void
+startup_volume_mount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ if (!g_volume_mount_finish (G_VOLUME (source_object), res, NULL)) {
+ /* There was an error mounting the volume, so we
+ clear the automount part. This is otherwise done
+ when the mount is added to the volume monitor */
+ g_object_set_data (source_object, "nautilus-automounted", GINT_TO_POINTER (0));
+ }
+}
+
+static void
+automount_all_volumes (NautilusApplication *application)
+{
+ GList *volumes, *l;
+ GMount *mount;
+ GVolume *volume;
+
+ if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT)) {
+ /* automount all mountable volumes at start-up */
+ volumes = g_volume_monitor_get_volumes (application->volume_monitor);
+ for (l = volumes; l != NULL; l = l->next) {
+ volume = l->data;
+
+ /* TODO: only do this for local volumes */
+
+ if (!g_volume_can_mount (volume)) {
+ continue;
+ }
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL) {
+ g_object_unref (mount);
+ continue;
+ }
+
+ /* Set this so we don't autorun stuff from it */
+ g_object_set_data (G_OBJECT (volume), "nautilus-automounted", GINT_TO_POINTER (1));
+
+ /* pass NULL as GMountOperation to avoid user interaction */
+ g_volume_mount (volume, NULL, NULL, startup_volume_mount_cb, NULL);
+ }
+ eel_g_object_list_free (volumes);
+ }
+
+}
+
+static void
nautilus_application_instance_init (NautilusApplication *application)
{
/* Create an undo manager */
@@ -172,22 +226,6 @@ nautilus_application_instance_init (NautilusApplication *application)
application->shell = nautilus_shell_new (application);
- /* Watch for mounts so we can restore open windows This used
- * to be for showing new window on mount, but is not used
- * anymore */
-
- /* Watch for unmounts so we can close open windows */
- /* TODO-gio: This should be using the UNMOUNTED feature of GFileMonitor instead */
- application->volume_monitor = g_volume_monitor_get ();
- g_signal_connect_object (application->volume_monitor, "mount_removed",
- G_CALLBACK (mount_removed_callback), application, 0);
- g_signal_connect_object (application->volume_monitor, "mount_pre_unmount",
- G_CALLBACK (mount_removed_callback), application, 0);
- g_signal_connect_object (application->volume_monitor, "mount_added",
- G_CALLBACK (mount_added_callback), application, 0);
- g_signal_connect_object (application->volume_monitor, "volume_added",
- G_CALLBACK (volume_added_callback), application, 0);
-
/* register views */
fm_icon_view_register ();
fm_desktop_icon_view_register ();
@@ -343,49 +381,6 @@ nautilus_make_uri_list_from_shell_strv (const char * const *strv)
}
static void
-migrate_old_nautilus_files (void)
-{
- char *new_desktop_dir;
- char *old_desktop_dir;
- char *migrated_file;
- char *link_name;
- char *link_path;
- int fd;
-
- old_desktop_dir = nautilus_get_gmc_desktop_directory ();
- if (!g_file_test (old_desktop_dir, G_FILE_TEST_IS_DIR) ||
- g_file_test (old_desktop_dir, G_FILE_TEST_IS_SYMLINK)) {
- g_free (old_desktop_dir);
- return;
- }
- migrated_file = g_build_filename (old_desktop_dir, ".migrated", NULL);
- if (!g_file_test (migrated_file, G_FILE_TEST_EXISTS)) {
- link_name = g_filename_from_utf8 (_("Link To Old Desktop"), -1, NULL, NULL, NULL);
- new_desktop_dir = nautilus_get_desktop_directory ();
- link_path = g_build_filename (new_desktop_dir, link_name, NULL);
-
-
- symlink ("../.gnome-desktop", link_path);
-
- g_free (link_name);
- g_free (new_desktop_dir);
- g_free (link_path);
-
- fd = creat (migrated_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- if (fd >= 0) {
- close (fd);
- }
-
- eel_show_info_dialog (_("A link called \"Link To Old Desktop\" has been created on the desktop."),
- _("The location of the desktop directory has changed in GNOME 2.4. "
- "You can open the link and move over the files you want, then delete the link."),
- NULL);
- }
- g_free (old_desktop_dir);
- g_free (migrated_file);
-}
-
-static void
menu_provider_items_updated_handler (NautilusMenuProvider *provider, GtkWidget* parent_window, gpointer data)
{
@@ -417,6 +412,8 @@ menu_provider_init_callback (void)
static void
finish_startup (NautilusApplication *application)
{
+ GList *drives;
+
/* initialize nautilus modules */
nautilus_module_init ();
@@ -425,14 +422,34 @@ finish_startup (NautilusApplication *application)
/* attach menu-provider module callback */
menu_provider_init_callback ();
- /* initialize URI authentication manager */
- gnome_authentication_manager_init ();
-
- /* Make the desktop work with old Nautilus. */
- migrate_old_nautilus_files ();
-
/* Initialize the desktop link monitor singleton */
nautilus_desktop_link_monitor_get ();
+
+ /* Watch for mounts so we can restore open windows This used
+ * to be for showing new window on mount, but is not used
+ * anymore */
+
+ /* Watch for unmounts so we can close open windows */
+ /* TODO-gio: This should be using the UNMOUNTED feature of GFileMonitor instead */
+ application->volume_monitor = g_volume_monitor_get ();
+ g_signal_connect_object (application->volume_monitor, "mount_removed",
+ G_CALLBACK (mount_removed_callback), application, 0);
+ g_signal_connect_object (application->volume_monitor, "mount_pre_unmount",
+ G_CALLBACK (mount_removed_callback), application, 0);
+ g_signal_connect_object (application->volume_monitor, "mount_added",
+ G_CALLBACK (mount_added_callback), application, 0);
+ g_signal_connect_object (application->volume_monitor, "volume_added",
+ G_CALLBACK (volume_added_callback), application, 0);
+ g_signal_connect_object (application->volume_monitor, "drive_connected",
+ G_CALLBACK (drive_connected_callback), application, 0);
+
+ /* listen for eject button presses */
+ drives = g_volume_monitor_get_connected_drives (application->volume_monitor);
+ g_list_foreach (drives, (GFunc) drive_listen_for_eject_button, application);
+ g_list_foreach (drives, (GFunc) g_object_unref, NULL);
+ g_list_free (drives);
+
+ automount_all_volumes (application);
}
static void
@@ -1315,18 +1332,94 @@ volume_added_callback (GVolumeMonitor *monitor,
GVolume *volume,
NautilusApplication *application)
{
- if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT)) {
+ if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT) &&
+ g_volume_can_mount (volume)) {
nautilus_file_operations_mount_volume (NULL, volume);
}
}
static void
+drive_eject_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ char *primary;
+ char *name;
+ error = NULL;
+ if (!g_drive_eject_finish (G_DRIVE (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to eject %s"), name);
+ g_free (name);
+ eel_show_error_dialog (primary,
+ error->message,
+ NULL);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+}
+
+static void
+drive_eject_button_pressed (GDrive *drive,
+ NautilusApplication *application)
+{
+ g_drive_eject (drive, 0, NULL, drive_eject_cb, NULL);
+}
+
+static void
+drive_listen_for_eject_button (GDrive *drive, NautilusApplication *application)
+{
+ g_signal_connect (drive,
+ "eject-button",
+ G_CALLBACK (drive_eject_button_pressed),
+ application);
+}
+
+static void
+drive_connected_callback (GVolumeMonitor *monitor,
+ GDrive *drive,
+ NautilusApplication *application)
+{
+ drive_listen_for_eject_button (drive, application);
+}
+
+static void
+autorun_show_window (GMount *mount, gpointer user_data)
+{
+ GFile *location;
+ NautilusApplication *application = user_data;
+
+ location = g_mount_get_root (mount);
+
+ /* Ther should probably be an easier way to do this */
+ if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_ALWAYS_USE_BROWSER)) {
+ NautilusWindow *window;
+ window = nautilus_application_create_navigation_window (application,
+ NULL,
+ gdk_screen_get_default ());
+ nautilus_window_go_to (window, location);
+
+ } else {
+ nautilus_application_present_spatial_window (application,
+ NULL,
+ NULL,
+ location,
+ gdk_screen_get_default ());
+ }
+ g_object_unref (location);
+}
+
+static void
mount_added_callback (GVolumeMonitor *monitor,
GMount *mount,
NautilusApplication *application)
{
NautilusDirectory *directory;
GFile *root;
+ GVolume *enclosing_volume;
+ gboolean ignore_autorun;
root = g_mount_get_root (mount);
directory = nautilus_directory_get_existing (root);
@@ -1336,7 +1429,21 @@ mount_added_callback (GVolumeMonitor *monitor,
nautilus_directory_unref (directory);
}
- nautilus_autorun (mount);
+ ignore_autorun = FALSE;
+
+ enclosing_volume = g_mount_get_volume (mount);
+ if (enclosing_volume != NULL) {
+ if (g_object_get_data (G_OBJECT (enclosing_volume), "nautilus-automounted") != NULL) {
+ ignore_autorun = TRUE;
+ /* Autorun if the user unmounts and then mounts */
+ g_object_set_data (G_OBJECT (enclosing_volume), "nautilus-automounted", NULL);
+ }
+ g_object_unref (enclosing_volume);
+ }
+
+ if (!ignore_autorun) {
+ nautilus_autorun (mount, autorun_show_window, application);
+ }
}
/* Called whenever a mount is unmounted. Check and see if there are
diff --git a/src/nautilus-autorun-software.c b/src/nautilus-autorun-software.c
new file mode 100644
index 000000000..7c1b5a533
--- /dev/null
+++ b/src/nautilus-autorun-software.c
@@ -0,0 +1,254 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* Nautilus
+
+ Copyright (C) 2008 Red Hat, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: David Zeuthen <davidz@redhat.com>
+*/
+
+#include <config.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+#include <glib/gi18n.h>
+
+#include <libgnome/gnome-program.h>
+#include <libgnomeui/gnome-ui-init.h>
+#include <libnautilus-private/nautilus-module.h>
+#include <libnautilus-private/nautilus-icon-info.h>
+
+typedef struct
+{
+ GtkWidget *dialog;
+ GMount *mount;
+} AutorunSoftwareDialogData;
+
+static void autorun_software_dialog_mount_unmounted (GMount *mount, AutorunSoftwareDialogData *data);
+
+static void
+autorun_software_dialog_destroy (AutorunSoftwareDialogData *data)
+{
+ g_signal_handlers_disconnect_by_func (G_OBJECT (data->mount),
+ G_CALLBACK (autorun_software_dialog_mount_unmounted),
+ data);
+
+ gtk_widget_destroy (GTK_WIDGET (data->dialog));
+ g_object_unref (data->mount);
+ g_free (data);
+}
+
+static void
+autorun_software_dialog_mount_unmounted (GMount *mount, AutorunSoftwareDialogData *data)
+{
+ autorun_software_dialog_destroy (data);
+}
+
+static gboolean
+_check_file (GFile *mount_root, const char *file_path, gboolean must_be_executable)
+{
+ GFile *file;
+ GFileInfo *file_info;
+ gboolean ret;
+
+ ret = FALSE;
+
+ file = g_file_get_child (mount_root, file_path);
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (file_info != NULL) {
+ if (must_be_executable) {
+ if (g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE))
+ ret = TRUE;
+ } else {
+ ret = TRUE;
+ }
+ g_object_unref (file_info);
+ }
+ g_object_unref (file);
+
+ return ret;
+}
+
+static void
+autorun (GMount *mount)
+{
+ GFile *root;
+ GFile *program_to_spawn;
+ char *path_to_spawn;
+ char *cwd_for_program;
+
+ root = g_mount_get_root (mount);
+
+ /* Careful here, according to
+ *
+ * http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
+ *
+ * the ordering does matter.
+ */
+
+ program_to_spawn = NULL;
+ path_to_spawn = NULL;
+
+ if (_check_file (root, ".autorun", TRUE)) {
+ program_to_spawn = g_file_get_child (root, ".autorun");
+ } else if (_check_file (root, "autorun", TRUE)) {
+ program_to_spawn = g_file_get_child (root, "autorun");
+ } else if (_check_file (root, "autorun.sh", TRUE)) {
+ program_to_spawn = g_file_get_child (root, "autorun.sh");
+ } else if (_check_file (root, "autorun.exe", TRUE)) {
+ /* TODO */
+ } else if (_check_file (root, "AUTORUN.EXE", TRUE)) {
+ /* TODO */
+ } else if (_check_file (root, "autorun.inf", FALSE)) {
+ /* TODO */
+ } else if (_check_file (root, "AUTORUN.INF", FALSE)) {
+ /* TODO */
+ }
+
+ if (program_to_spawn != NULL)
+ path_to_spawn = g_file_get_path (program_to_spawn);
+
+ cwd_for_program = g_file_get_path (root);
+
+ if (path_to_spawn != NULL && cwd_for_program != NULL) {
+ if (chdir (cwd_for_program) == 0) {
+ execl (path_to_spawn, path_to_spawn, NULL);
+ g_warning ("Error execing program: %m");
+ }
+ g_warning ("Error chdir to '%s': %m", cwd_for_program);
+ }
+ g_warning ("Cannot find path for program to spawn");
+
+ if (program_to_spawn != NULL)
+ g_object_unref (program_to_spawn);
+ g_free (path_to_spawn);
+ g_free (cwd_for_program);
+}
+
+static void
+present_autorun_for_software_dialog (GMount *mount)
+{
+ GIcon *icon;
+ int icon_size;
+ NautilusIconInfo *icon_info;
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
+ char *mount_name;
+ GtkWidget *dialog;
+ AutorunSoftwareDialogData *data;
+
+ mount_name = g_mount_get_name (mount);
+
+ dialog = gtk_message_dialog_new_with_markup (NULL, /* TODO: parent window? */
+ 0,
+ GTK_MESSAGE_OTHER,
+ GTK_BUTTONS_CANCEL,
+ _("<big><b>This media contains software intended to be automatically started. Would you like to run it?</b></big>"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("The software will run directly from the media \"%s\". "
+ "You should never run software that you don't trust.\n"
+ "\n"
+ "If in doubt, press Cancel."),
+ mount_name);
+
+ /* TODO: in a star trek future add support for verifying
+ * software on media (e.g. if it has a certificate, check it
+ * etc.)
+ */
+
+
+ icon = g_mount_get_icon (mount);
+ icon_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_DIALOG);
+ icon_info = nautilus_icon_info_lookup (icon, icon_size);
+ pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size);
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+
+ gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), mount_name);
+ gtk_window_set_icon (GTK_WINDOW (dialog), pixbuf);
+
+ data = g_new0 (AutorunSoftwareDialogData, 1);
+ data->dialog = dialog;
+ data->mount = g_object_ref (mount);
+
+ g_signal_connect (G_OBJECT (mount),
+ "unmounted",
+ G_CALLBACK (autorun_software_dialog_mount_unmounted),
+ data);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("_Run"),
+ GTK_RESPONSE_OK);
+
+ gtk_widget_show_all (dialog);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ autorun (mount);
+ }
+
+ g_object_unref (icon_info);
+ g_object_unref (pixbuf);
+ g_free (mount_name);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GVolumeMonitor *monitor;
+ GFile *file;
+ GMount *mount;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gnome_program_init ("nautilus-autorun-software", VERSION,
+ LIBGNOMEUI_MODULE, argc, argv,
+ NULL, NULL);
+
+ if (argc != 2)
+ goto out;
+
+ /* instantiate monitor so we get the "unmounted" signal properly */
+ monitor = g_volume_monitor_get ();
+ if (monitor == NULL)
+ goto out;
+
+ file = g_file_new_for_commandline_arg (argv[1]);
+ if (file == NULL)
+ goto out;
+
+ mount = g_file_find_enclosing_mount (file, NULL, NULL);
+ if (mount == NULL)
+ goto out;
+
+ present_autorun_for_software_dialog (mount);
+
+out:
+ return 0;
+}
diff --git a/src/nautilus-file-management-properties.c b/src/nautilus-file-management-properties.c
index fa43efc62..7485b3c75 100644
--- a/src/nautilus-file-management-properties.c
+++ b/src/nautilus-file-management-properties.c
@@ -28,13 +28,8 @@
#include <string.h>
#include <time.h>
-#include <gtk/gtkdialog.h>
-#include <gtk/gtkmenu.h>
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtkmessagedialog.h>
-#include <gtk/gtknotebook.h>
-#include <gtk/gtkcombobox.h>
-#include <gtk/gtksizegroup.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
#include <libgnome/gnome-help.h>
#include <glib/gi18n.h>
@@ -74,8 +69,8 @@
#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_OPEN_NEW_WINDOW_WIDGET "new_window_checkbutton"
#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_SHOW_HIDDEN_WIDGET "hidden_files_checkbutton"
#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_TREE_VIEW_FOLDERS_WIDGET "treeview_folders_checkbutton"
-#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_MEDIA_AUTOMOUNT "media_automount_checkbutton"
#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_MEDIA_AUTOMOUNT_OPEN "media_automount_open_checkbutton"
+#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_MEDIA_AUTORUN_NEVER "media_autorun_never_checkbutton"
/* int enums */
#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_THUMBNAIL_LIMIT_WIDGET "preview_image_size_combobox"
@@ -515,24 +510,145 @@ nautilus_file_management_properties_dialog_setup_list_column_page (GladeXML *xml
gtk_box_pack_start (GTK_BOX (box), chooser, TRUE, TRUE, 0);
}
+static void
+nautilus_file_management_properties_dialog_update_media_sensitivity (GladeXML *xml_dialog)
+{
+ gtk_widget_set_sensitive (glade_xml_get_widget (xml_dialog, "media_handling_vbox"),
+ ! eel_preferences_get_boolean (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_NEVER));
+}
+
+static void
+other_type_combo_box_changed (GtkComboBox *combo_box, GtkComboBox *action_combo_box)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ char *x_content_type;
+
+ x_content_type = NULL;
+
+ if (!gtk_combo_box_get_active_iter (combo_box, &iter)) {
+ goto out;
+ }
+
+ model = gtk_combo_box_get_model (combo_box);
+ if (model == NULL) {
+ goto out;
+ }
+
+ gtk_tree_model_get (model, &iter,
+ 2, &x_content_type,
+ -1);
+
+ nautilus_autorun_prepare_combo_box (GTK_WIDGET (action_combo_box),
+ x_content_type,
+ TRUE,
+ TRUE,
+ NULL, NULL);
+out:
+ g_free (x_content_type);
+}
+
static void
nautilus_file_management_properties_dialog_setup_media_page (GladeXML *xml_dialog)
{
unsigned int n;
+ GList *l;
+ GList *content_types;
+ GtkWidget *other_type_combo_box;
+ GtkListStore *other_type_list_store;
+ GtkCellRenderer *renderer;
+ GtkTreeIter iter;
const char *s[] = {"media_audio_cdda_combobox", "x-content/audio-cdda",
"media_video_dvd_combobox", "x-content/video-dvd",
- "media_video_vcd_combobox", "x-content/video-vcd",
- "media_video_svcd_combobox", "x-content/video-svcd",
- "media_blank_combobox", "x-content/blank-media",
- "media_music_player_combobox", "x-content/music-player",
+ "media_music_player_combobox", "x-content/audio-player",
"media_dcf_combobox", "x-content/image-dcf",
+ "media_software_combobox", "x-content/software",
NULL};
for (n = 0; s[n*2] != NULL; n++) {
nautilus_autorun_prepare_combo_box (glade_xml_get_widget (xml_dialog, s[n*2]), s[n*2 + 1],
TRUE, TRUE, NULL, NULL);
}
+
+ other_type_combo_box = glade_xml_get_widget (xml_dialog, "media_other_type_combobox");
+
+ other_type_list_store = gtk_list_store_new (3,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (other_type_list_store),
+ 1, GTK_SORT_ASCENDING);
+
+
+ content_types = g_content_types_get_registered ();
+
+ for (l = content_types; l != NULL; l = l->next) {
+ char *content_type = l->data;
+ char *description;
+ GIcon *icon;
+ NautilusIconInfo *icon_info;
+ GdkPixbuf *pixbuf;
+ int icon_size;
+
+ if (!g_str_has_prefix (content_type, "x-content/"))
+ continue;
+ for (n = 0; s[n*2] != NULL; n++) {
+ if (strcmp (content_type, s[n*2 + 1]) == 0) {
+ goto skip;
+ }
+ }
+
+ icon_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
+
+ description = g_content_type_get_description (content_type);
+ gtk_list_store_append (other_type_list_store, &iter);
+ icon = g_content_type_get_icon (content_type);
+ if (icon != NULL) {
+ icon_info = nautilus_icon_info_lookup (icon, icon_size);
+ g_object_unref (icon);
+ pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size);
+ g_object_unref (icon_info);
+ } else {
+ pixbuf = NULL;
+ }
+
+ gtk_list_store_set (other_type_list_store, &iter,
+ 0, pixbuf,
+ 1, description,
+ 2, content_type,
+ -1);
+ if (pixbuf != NULL)
+ g_object_unref (pixbuf);
+ g_free (description);
+ skip:
+ ;
+ }
+ g_list_foreach (content_types, (GFunc) g_free, NULL);
+ g_list_free (content_types);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (other_type_combo_box), GTK_TREE_MODEL (other_type_list_store));
+
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (other_type_combo_box), renderer, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (other_type_combo_box), renderer,
+ "pixbuf", 0,
+ NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (other_type_combo_box), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (other_type_combo_box), renderer,
+ "text", 1,
+ NULL);
+
+ g_signal_connect (G_OBJECT (other_type_combo_box),
+ "changed",
+ G_CALLBACK (other_type_combo_box_changed),
+ glade_xml_get_widget (xml_dialog, "media_other_action_combobox"));
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (other_type_combo_box), 0);
+
+ nautilus_file_management_properties_dialog_update_media_sensitivity (xml_dialog);
}
static void
@@ -577,11 +693,11 @@ nautilus_file_management_properties_dialog_setup (GladeXML *xml_dialog, GtkWindo
NAUTILUS_PREFERENCES_ALWAYS_USE_BROWSER);
eel_preferences_glade_connect_bool (xml_dialog,
- NAUTILUS_FILE_MANAGEMENT_PROPERTIES_MEDIA_AUTOMOUNT,
- NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT);
- eel_preferences_glade_connect_bool (xml_dialog,
NAUTILUS_FILE_MANAGEMENT_PROPERTIES_MEDIA_AUTOMOUNT_OPEN,
NAUTILUS_PREFERENCES_MEDIA_AUTOMOUNT_OPEN);
+ eel_preferences_glade_connect_bool (xml_dialog,
+ NAUTILUS_FILE_MANAGEMENT_PROPERTIES_MEDIA_AUTORUN_NEVER,
+ NAUTILUS_PREFERENCES_MEDIA_AUTORUN_NEVER);
eel_preferences_glade_connect_bool (xml_dialog,
NAUTILUS_FILE_MANAGEMENT_PROPERTIES_TRASH_CONFIRM_WIDGET,
@@ -656,8 +772,12 @@ nautilus_file_management_properties_dialog_setup (GladeXML *xml_dialog, GtkWindo
nautilus_file_management_properties_dialog_setup_icon_caption_page (xml_dialog);
nautilus_file_management_properties_dialog_setup_list_column_page (xml_dialog);
-
nautilus_file_management_properties_dialog_setup_media_page (xml_dialog);
+
+ eel_preferences_add_callback (NAUTILUS_PREFERENCES_MEDIA_AUTORUN_NEVER,
+ (EelPreferencesCallback ) nautilus_file_management_properties_dialog_update_media_sensitivity,
+ g_object_ref (xml_dialog));
+
/* UI callbacks */
dialog = glade_xml_get_widget (xml_dialog, "file_management_dialog");
diff --git a/src/nautilus-file-management-properties.glade b/src/nautilus-file-management-properties.glade
index 979944cbc..95d5bdb4e 100644
--- a/src/nautilus-file-management-properties.glade
+++ b/src/nautilus-file-management-properties.glade
@@ -2204,569 +2204,530 @@ Never</property>
<property name="border_width">12</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
- <property name="spacing">18</property>
+ <property name="spacing">6</property>
<child>
- <widget class="GtkVBox" id="vbox42">
+ <widget class="GtkVBox" id="media_handling_vbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
- <widget class="GtkLabel" id="label41">
+ <widget class="GtkVBox" id="vbox44">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Automatic Mounting&lt;/span&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkAlignment" id="alignment19">
- <property name="visible">True</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xscale">1</property>
- <property name="yscale">1</property>
- <property name="top_padding">0</property>
- <property name="bottom_padding">0</property>
- <property name="left_padding">12</property>
- <property name="right_padding">0</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
<child>
- <widget class="GtkVBox" id="vbox46">
+ <widget class="GtkLabel" id="label42">
<property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">6</property>
-
- <child>
- <widget class="GtkCheckButton" id="media_automount_checkbutton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Automatically _mount media</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkCheckButton" id="media_automount_open_checkbutton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Open _folder when automounted</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">False</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Media Handling&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
</widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
</child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkVBox" id="vbox44">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">6</property>
-
- <child>
- <widget class="GtkLabel" id="label42">
- <property name="visible">True</property>
- <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Autorun&lt;/span&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkAlignment" id="alignment18">
- <property name="visible">True</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xscale">1</property>
- <property name="yscale">1</property>
- <property name="top_padding">0</property>
- <property name="bottom_padding">0</property>
- <property name="left_padding">12</property>
- <property name="right_padding">0</property>
<child>
- <widget class="GtkVBox" id="vbox49">
+ <widget class="GtkAlignment" id="alignment18">
<property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">6</property>
-
- <child>
- <widget class="GtkLabel" id="label60">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Choose what happens when inserting media or connecting devices to the system</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">True</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
<child>
- <widget class="GtkTable" id="table4">
+ <widget class="GtkVBox" id="vbox52">
<property name="visible">True</property>
- <property name="n_rows">7</property>
- <property name="n_columns">2</property>
<property name="homogeneous">False</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">6</property>
+ <property name="spacing">6</property>
<child>
- <widget class="GtkLabel" id="label44">
+ <widget class="GtkLabel" id="label60">
<property name="visible">True</property>
- <property name="label" translatable="yes">CD _Audio:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
+ <property name="label" translatable="yes">Choose what happens when inserting media or connecting devices to the system</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
+ <property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
- <property name="mnemonic_widget">media_audio_cdda_combobox</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">0</property>
- <property name="bottom_attach">1</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label50">
+ <widget class="GtkTable" id="table4">
<property name="visible">True</property>
- <property name="label" translatable="yes">_DVD Video:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">media_video_dvd_combobox</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label44">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">CD _Audio:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_audio_cdda_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label50">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_DVD Video:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_video_dvd_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="media_audio_cdda_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="media_video_dvd_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label54">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Music Player:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_music_player_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="media_music_player_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label59">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Photos:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_dcf_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="media_dcf_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label57">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Software:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_software_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="media_software_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
</widget>
<packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
</packing>
</child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
- <child>
- <widget class="GtkLabel" id="label51">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Video CD:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">media_video_vcd_combobox</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
+ <child>
+ <widget class="GtkVBox" id="vbox50">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
- <child>
- <widget class="GtkLabel" id="label52">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Super Video CD:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">media_video_svcd_combobox</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
+ <child>
+ <widget class="GtkLabel" id="label61">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Other Media&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
- <child>
- <widget class="GtkLabel" id="label57">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Blank Disc:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="mnemonic_widget">media_blank_combobox</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
+ <child>
+ <widget class="GtkAlignment" id="alignment20">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
- <child>
- <widget class="GtkLabel" id="label54">
- <property name="visible">True</property>
- <property name="label" translatable="yes">M_usic Player:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
+ <child>
+ <widget class="GtkVBox" id="vbox51">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
<child>
- <widget class="GtkLabel" id="label59">
+ <widget class="GtkLabel" id="label65">
<property name="visible">True</property>
- <property name="label" translatable="yes">_Photo Flash Card:</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
+ <property name="label" translatable="yes">Less common media formats can be configured here</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
+ <property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
- <property name="mnemonic_widget">media_dcf_combobox</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
- <property name="left_attach">0</property>
- <property name="right_attach">1</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_audio_cdda_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">0</property>
- <property name="bottom_attach">1</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_video_dvd_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_video_vcd_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_video_svcd_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_blank_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_music_player_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkComboBox" id="media_dcf_combobox">
- <property name="visible">True</property>
- <property name="add_tearoffs">False</property>
- <property name="focus_on_click">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- <property name="x_options">fill</property>
- <property name="y_options">fill</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkHBox" id="hbox37">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="stock">gtk-dialog-info</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">8</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
<property name="padding">0</property>
<property name="expand">False</property>
- <property name="fill">True</property>
+ <property name="fill">False</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label58">
+ <widget class="GtkTable" id="table5">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;i&gt;You can configure applications for other kinds of media and devices by holding down the Shift key while inserting the media or device.&lt;/i&gt;</property>
- <property name="use_underline">False</property>
- <property name="use_markup">True</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">True</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkComboBox" id="media_other_type_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label64">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Acti_on:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_other_action_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="media_other_action_combobox">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label63">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Type:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">media_other_type_combobox</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
</packing>
</child>
</widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
</child>
</widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
</child>
</widget>
<packing>
@@ -2778,8 +2739,46 @@ Never</property>
</widget>
<packing>
<property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="media_autorun_never_checkbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_Never prompt or start programs on media insertion</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="media_automount_open_checkbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">B_rowse media when inserted</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
</packing>
</child>
</widget>
diff --git a/src/nautilus-window-manage-views.c b/src/nautilus-window-manage-views.c
index 4eae4419e..df6df5799 100644
--- a/src/nautilus-window-manage-views.c
+++ b/src/nautilus-window-manage-views.c
@@ -36,6 +36,7 @@
#include "nautilus-main.h"
#include "nautilus-window-private.h"
#include "nautilus-trash-bar.h"
+#include "nautilus-x-content-bar.h"
#include "nautilus-zoom-control.h"
#include <eel/eel-accessibility.h>
#include <eel/eel-debug.h>
@@ -63,6 +64,7 @@
#include <libnautilus-private/nautilus-search-directory.h>
#include <libnautilus-private/nautilus-view-factory.h>
#include <libnautilus-private/nautilus-window-info.h>
+#include <libnautilus-private/nautilus-autorun.h>
/* FIXME bugzilla.gnome.org 41243:
* We should use inheritance instead of these special cases
@@ -1291,6 +1293,32 @@ add_extension_extra_widgets (NautilusWindow *window, GFile *location)
}
static void
+nautilus_window_show_x_content_bar (NautilusWindow *window, GMount *mount, char **x_content_types)
+{
+ unsigned int n;
+
+ g_assert (NAUTILUS_IS_WINDOW (window));
+
+ for (n = 0; x_content_types[n] != NULL; n++) {
+ GAppInfo *default_app;
+
+ /* skip blank media; the burn:/// location will provide it's own cluebar */
+ if (g_str_has_prefix (x_content_types[n], "x-content/blank-"))
+ continue;
+
+ /* only show the cluebar if a default app is available */
+ default_app = g_app_info_get_default_for_type (x_content_types[n], FALSE);
+ if (default_app != NULL) {
+ GtkWidget *bar;
+ bar = nautilus_x_content_bar_new (mount, x_content_types[n]);
+ gtk_widget_show (bar);
+ nautilus_window_add_extra_location_widget (window, bar);
+ g_object_unref (default_app);
+ }
+ }
+}
+
+static void
nautilus_window_show_trash_bar (NautilusWindow *window)
{
GtkWidget *bar;
@@ -1312,6 +1340,8 @@ update_for_new_location (NautilusWindow *window)
NautilusDirectory *directory;
gboolean location_really_changed;
char *uri;
+ char **x_content_types;
+ GMount *mount;
new_location = window->details->pending_location;
window->details->pending_location = NULL;
@@ -1370,6 +1400,13 @@ update_for_new_location (NautilusWindow *window)
nautilus_window_show_trash_bar (window);
}
+ x_content_types = nautilus_autorun_get_x_content_types_for_file (file, &mount, FALSE, TRUE);
+ if (x_content_types != NULL) {
+ nautilus_window_show_x_content_bar (window, mount, x_content_types);
+ g_strfreev (x_content_types);
+ g_object_unref (mount);
+ }
+
nautilus_directory_unref (directory);
add_extension_extra_widgets (window, window->details->location);
diff --git a/src/nautilus-x-content-bar.c b/src/nautilus-x-content-bar.c
new file mode 100644
index 000000000..be5869068
--- /dev/null
+++ b/src/nautilus-x-content-bar.c
@@ -0,0 +1,297 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2006 Paolo Borelli <pborelli@katamail.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 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: David Zeuthen <davidz@redhat.com>
+ * Paolo Borelli <pborelli@katamail.com>
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include "nautilus-x-content-bar.h"
+#include <libnautilus-private/nautilus-autorun.h>
+#include <libnautilus-private/nautilus-icon-info.h>
+
+#define NAUTILUS_X_CONTENT_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_X_CONTENT_BAR, NautilusXContentBarPrivate))
+
+struct NautilusXContentBarPrivate
+{
+ GtkWidget *label;
+ GtkWidget *button;
+
+ char *x_content_type;
+ GMount *mount;
+};
+
+enum {
+ PROP_0,
+ PROP_MOUNT,
+ PROP_X_CONTENT_TYPE,
+};
+
+G_DEFINE_TYPE (NautilusXContentBar, nautilus_x_content_bar, GTK_TYPE_HBOX)
+
+void
+nautilus_x_content_bar_set_x_content_type (NautilusXContentBar *bar, const char *x_content_type)
+{
+ char *message;
+ char *description;
+ GAppInfo *default_app;
+
+ g_free (bar->priv->x_content_type);
+ bar->priv->x_content_type = g_strdup (x_content_type);
+
+ description = g_content_type_get_description (x_content_type);
+
+ /* Customize greeting for well-known x-content types */
+ if (strcmp (x_content_type, "x-content/audio-cdda") == 0) {
+ message = g_strdup (_("These files are on an Audio CD."));
+ } else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) {
+ message = g_strdup (_("These files are on an Audio DVD."));
+ } else if (strcmp (x_content_type, "x-content/video-dvd") == 0) {
+ message = g_strdup (_("These files are on a Video DVD."));
+ } else if (strcmp (x_content_type, "x-content/video-vcd") == 0) {
+ message = g_strdup (_("These files are on a Video CD."));
+ } else if (strcmp (x_content_type, "x-content/video-svcd") == 0) {
+ message = g_strdup (_("These files are on a Super Video CD."));
+ } else if (strcmp (x_content_type, "x-content/image-photocd") == 0) {
+ message = g_strdup (_("These files are on a Photo CD."));
+ } else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) {
+ message = g_strdup (_("These files are on a Picture CD."));
+ } else if (strcmp (x_content_type, "x-content/image-dcf") == 0) {
+ message = g_strdup (_("The media contains digital photos."));
+ } else if (strcmp (x_content_type, "x-content/audio-player") == 0) {
+ message = g_strdup (_("These files are on a digital audio player."));
+ } else if (strcmp (x_content_type, "x-content/software") == 0) {
+ message = g_strdup (_("The media contains software."));
+ } else {
+ /* fallback to generic greeting */
+ message = g_strdup_printf (_("The media has been detected as \"%s\"."), description);
+ }
+
+
+ gtk_label_set_text (GTK_LABEL (bar->priv->label), message);
+ gtk_widget_show (bar->priv->label);
+
+ /* TODO: We really need a GtkBrowserBackButton-ish widget here.. until then, we only
+ * show the default application. */
+
+ default_app = g_app_info_get_default_for_type (x_content_type, FALSE);
+ if (default_app != NULL) {
+ char *button_text;
+ const char *name;
+ GIcon *icon;
+ GtkWidget *image;
+
+ icon = g_app_info_get_icon (default_app);
+ if (icon != NULL) {
+ GdkPixbuf *pixbuf;
+ int icon_size;
+ NautilusIconInfo *icon_info;
+ icon_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_BUTTON);
+ icon_info = nautilus_icon_info_lookup (icon, icon_size);
+ pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size);
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+ g_object_unref (icon_info);
+ g_object_unref (icon);
+ } else {
+ image = NULL;
+ }
+
+ name = g_app_info_get_name (default_app);
+ button_text = g_strdup_printf (_("Open %s"), name);
+
+ gtk_button_set_image (GTK_BUTTON (bar->priv->button), image);
+ gtk_button_set_label (GTK_BUTTON (bar->priv->button), button_text);
+ gtk_widget_show (bar->priv->button);
+ g_free (button_text);
+ g_object_unref (default_app);
+ } else {
+ gtk_widget_hide (bar->priv->button);
+ }
+
+ g_free (message);
+ g_free (description);
+}
+
+const char *
+nautilus_x_content_bar_get_x_content_type (NautilusXContentBar *bar)
+{
+ return bar->priv->x_content_type;
+}
+
+GMount *
+nautilus_x_content_bar_get_mount (NautilusXContentBar *bar)
+{
+ return bar->priv->mount != NULL ? g_object_ref (bar->priv->mount) : NULL;
+}
+
+void
+nautilus_x_content_bar_set_mount (NautilusXContentBar *bar, GMount *mount)
+{
+ if (bar->priv->mount != NULL)
+ g_object_unref (bar->priv->mount);
+ bar->priv->mount = mount != NULL ? g_object_ref (mount) : NULL;
+}
+
+
+static void
+nautilus_x_content_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusXContentBar *bar;
+
+ bar = NAUTILUS_X_CONTENT_BAR (object);
+
+ switch (prop_id) {
+ case PROP_MOUNT:
+ nautilus_x_content_bar_set_mount (bar, G_MOUNT (g_value_get_object (value)));
+ break;
+ case PROP_X_CONTENT_TYPE:
+ nautilus_x_content_bar_set_x_content_type (bar, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_x_content_bar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusXContentBar *bar;
+
+ bar = NAUTILUS_X_CONTENT_BAR (object);
+
+ switch (prop_id) {
+ case PROP_MOUNT:
+ g_value_set_object (value, bar->priv->mount);
+ break;
+ case PROP_X_CONTENT_TYPE:
+ g_value_set_string (value, bar->priv->x_content_type);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nautilus_x_content_bar_finalize (GObject *object)
+{
+ NautilusXContentBar *bar = NAUTILUS_X_CONTENT_BAR (object);
+
+ g_free (bar->priv->x_content_type);
+ if (bar->priv->mount != NULL)
+ g_object_unref (bar->priv->mount);
+
+ G_OBJECT_CLASS (nautilus_x_content_bar_parent_class)->finalize (object);
+}
+
+static void
+nautilus_x_content_bar_class_init (NautilusXContentBarClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = nautilus_x_content_bar_get_property;
+ object_class->set_property = nautilus_x_content_bar_set_property;
+ object_class->finalize = nautilus_x_content_bar_finalize;
+
+ g_type_class_add_private (klass, sizeof (NautilusXContentBarPrivate));
+
+ g_object_class_install_property (object_class,
+ PROP_MOUNT,
+ g_param_spec_object (
+ "mount",
+ "The GMount to run programs for",
+ "The GMount to run programs for",
+ G_TYPE_MOUNT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_X_CONTENT_TYPE,
+ g_param_spec_string (
+ "x-content-type",
+ "The x-content type for the cluebar",
+ "The x-content type for the cluebar",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+}
+
+static void
+button_clicked_callback (GtkWidget *button, NautilusXContentBar *bar)
+{
+ GAppInfo *default_app;
+
+ if (bar->priv->x_content_type == NULL ||
+ bar->priv->mount == NULL)
+ return;
+
+ default_app = g_app_info_get_default_for_type (bar->priv->x_content_type, FALSE);
+ if (default_app != NULL) {
+ nautilus_autorun_launch_for_mount (bar->priv->mount, default_app);
+ g_object_unref (default_app);
+ }
+}
+
+static void
+nautilus_x_content_bar_init (NautilusXContentBar *bar)
+{
+ GtkWidget *hbox;
+
+ bar->priv = NAUTILUS_X_CONTENT_BAR_GET_PRIVATE (bar);
+
+ hbox = GTK_WIDGET (bar);
+
+ bar->priv->label = gtk_label_new (NULL);
+ gtk_box_pack_start (GTK_BOX (bar), bar->priv->label, FALSE, FALSE, 0);
+
+ bar->priv->button = gtk_button_new ();
+ gtk_box_pack_end (GTK_BOX (hbox), bar->priv->button, FALSE, FALSE, 0);
+
+ g_signal_connect (bar->priv->button,
+ "clicked",
+ G_CALLBACK (button_clicked_callback),
+ bar);
+}
+
+GtkWidget *
+nautilus_x_content_bar_new (GMount *mount,
+ const char *x_content_type)
+{
+ GObject *bar;
+
+ bar = g_object_new (NAUTILUS_TYPE_X_CONTENT_BAR,
+ "mount", mount,
+ "x-content-type", x_content_type,
+ NULL);
+
+ return GTK_WIDGET (bar);
+}
diff --git a/src/nautilus-x-content-bar.h b/src/nautilus-x-content-bar.h
new file mode 100644
index 000000000..922cb1934
--- /dev/null
+++ b/src/nautilus-x-content-bar.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2006 Paolo Borelli <pborelli@katamail.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 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: David Zeuthen <davidz@redhat.com>
+ * Paolo Borelli <pborelli@katamail.com>
+ *
+ */
+
+#ifndef __NAUTILUS_X_CONTENT_BAR_H
+#define __NAUTILUS_X_CONTENT_BAR_H
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_X_CONTENT_BAR (nautilus_x_content_bar_get_type ())
+#define NAUTILUS_X_CONTENT_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_X_CONTENT_BAR, NautilusXContentBar))
+#define NAUTILUS_X_CONTENT_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NAUTILUS_TYPE_X_CONTENT_BAR, NautilusXContentBarClass))
+#define NAUTILUS_IS_X_CONTENT_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_X_CONTENT_BAR))
+#define NAUTILUS_IS_X_CONTENT_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NAUTILUS_TYPE_X_CONTENT_BAR))
+#define NAUTILUS_X_CONTENT_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NAUTILUS_TYPE_X_CONTENT_BAR, NautilusXContentBarClass))
+
+typedef struct NautilusXContentBarPrivate NautilusXContentBarPrivate;
+
+typedef struct
+{
+ GtkHBox box;
+
+ NautilusXContentBarPrivate *priv;
+} NautilusXContentBar;
+
+typedef struct
+{
+ GtkHBoxClass parent_class;
+} NautilusXContentBarClass;
+
+GType nautilus_x_content_bar_get_type (void) G_GNUC_CONST;
+
+GtkWidget *nautilus_x_content_bar_new (GMount *mount,
+ const char *x_content_type);
+const char *nautilus_x_content_bar_get_x_content_type (NautilusXContentBar *bar);
+void nautilus_x_content_bar_set_x_content_type (NautilusXContentBar *bar,
+ const char *x_content_type);
+void nautilus_x_content_bar_set_mount (NautilusXContentBar *bar,
+ GMount *mount);
+GMount *nautilus_x_content_bar_get_mount (NautilusXContentBar *bar);
+
+G_END_DECLS
+
+#endif /* __NAUTILUS_X_CONTENT_BAR_H */