summaryrefslogtreecommitdiff
path: root/src/file-manager/fm-properties-window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/file-manager/fm-properties-window.c')
-rw-r--r--src/file-manager/fm-properties-window.c234
1 files changed, 139 insertions, 95 deletions
diff --git a/src/file-manager/fm-properties-window.c b/src/file-manager/fm-properties-window.c
index d7b81aeab..b217949fe 100644
--- a/src/file-manager/fm-properties-window.c
+++ b/src/file-manager/fm-properties-window.c
@@ -73,11 +73,10 @@ static GHashTable *windows;
static GHashTable *pending_files;
struct FMPropertiesWindowDetails {
- NautilusFile *file;
+ NautilusFile *original_file;
+ NautilusFile *target_file;
GtkNotebook *notebook;
GtkWidget *remove_image_button;
- GtkWidget *icon_selection;
- GtkWidget *file_entry;
guint file_changed_handler_id;
@@ -121,6 +120,12 @@ enum {
COLUMN_COUNT
};
+typedef struct {
+ NautilusFile *original_file;
+ NautilusFile *target_file;
+ FMDirectoryView *directory_view;
+} StartupData;
+
#define ERASE_EMBLEM_FILENAME "erase.png"
#define DIRECTORY_CONTENTS_UPDATE_INTERVAL 200 /* milliseconds */
@@ -130,17 +135,17 @@ static void real_finalize (GtkObject *obje
static void real_shutdown (GtkObject *object);
static void fm_properties_window_initialize_class (FMPropertiesWindowClass *class);
static void fm_properties_window_initialize (FMPropertiesWindow *window);
-static void create_properties_window_callback (NautilusFile *file,
+static void create_properties_window_callback (NautilusFile *file,
gpointer data);
static void cancel_group_change_callback (gpointer callback_data);
static void cancel_owner_change_callback (gpointer callback_data);
static void directory_view_destroyed_callback (FMDirectoryView *view,
gpointer callback_data);
static void select_image_button_callback (GtkWidget *widget,
- NautilusFile *file);
+ FMPropertiesWindow *properties_window);
static void remove_image_button_callback (GtkWidget *widget,
- NautilusFile *file);
-static void remove_pending_file (NautilusFile *file,
+ FMPropertiesWindow *properties_window);
+static void remove_pending_file (StartupData *data,
gboolean cancel_call_when_ready,
gboolean cancel_timed_wait,
gboolean cancel_destroy_handler);
@@ -1027,7 +1032,7 @@ directory_contents_value_field_update (FMPropertiesWindow *window)
g_assert (FM_IS_PROPERTIES_WINDOW (window));
- file = window->details->file;
+ file = window->details->target_file;
g_assert (nautilus_file_is_directory (file) || nautilus_file_is_gone (file));
status = nautilus_file_get_deep_counts (file,
@@ -1128,13 +1133,13 @@ attach_directory_contents_value_field (FMPropertiesWindow *window,
gtk_label_set_line_wrap (value_field, TRUE);
/* Always recompute from scratch when the window is shown. */
- nautilus_file_recompute_deep_counts (window->details->file);
+ nautilus_file_recompute_deep_counts (window->details->target_file);
/* Fill in the initial value. */
directory_contents_value_field_update (window);
/* Connect to signal to update value when file changes. */
- gtk_signal_connect_object_while_alive (GTK_OBJECT (window->details->file),
+ gtk_signal_connect_object_while_alive (GTK_OBJECT (window->details->target_file),
"updated_deep_count_in_progress",
schedule_directory_contents_update,
GTK_OBJECT (window));
@@ -1217,7 +1222,7 @@ update_visibility_of_item_count_fields (FMPropertiesWindow *window)
{
update_visibility_of_table_rows
(window->details->basic_table,
- nautilus_file_should_show_directory_item_count (window->details->file),
+ nautilus_file_should_show_directory_item_count (window->details->target_file),
window->details->directory_contents_row,
1,
window->details->directory_contents_widgets);
@@ -1349,7 +1354,7 @@ should_show_custom_icon_buttons (FMPropertiesWindow *window)
* we shouldn't pretend that they work by showing them here.
* When bug 5642 is fixed we can remove this case.
*/
- if (is_merged_trash_directory (window->details->file)) {
+ if (is_merged_trash_directory (window->details->target_file)) {
return FALSE;
}
@@ -1360,7 +1365,7 @@ static gboolean
should_show_file_type (FMPropertiesWindow *window)
{
/* The trash on the desktop is one-of-a-kind */
- if (is_merged_trash_directory (window->details->file)) {
+ if (is_merged_trash_directory (window->details->target_file)) {
return FALSE;
}
@@ -1374,7 +1379,7 @@ should_show_accessed_date (FMPropertiesWindow *window)
* day decide that it is useful, we should separately
* consider whether it's useful for "trash:".
*/
- if (nautilus_file_is_directory (window->details->file)) {
+ if (nautilus_file_is_directory (window->details->target_file)) {
return FALSE;
}
@@ -1389,7 +1394,7 @@ should_show_mime_type (FMPropertiesWindow *window)
* trash directory, but doesn't. I could trivially fix this
* with a check for is_merged_trash_directory here instead.
*/
- if (nautilus_file_is_directory (window->details->file)) {
+ if (nautilus_file_is_directory (window->details->target_file)) {
return FALSE;
}
@@ -1404,9 +1409,10 @@ create_basic_page (FMPropertiesWindow *window)
GtkWidget *icon_pixmap_widget, *icon_aligner, *name_field;
GtkWidget *button_box, *temp_button;
char *image_uri;
- NautilusFile *file;
+ NautilusFile *target_file, *original_file;
- file = window->details->file;
+ target_file = window->details->target_file;
+ original_file = window->details->original_file;
create_page_with_table_in_vbox (window->details->notebook,
_("Basic"),
@@ -1416,7 +1422,7 @@ create_basic_page (FMPropertiesWindow *window)
window->details->basic_table = table;
/* Icon pixmap */
- icon_pixmap_widget = create_image_widget_for_file (file);
+ icon_pixmap_widget = create_image_widget_for_file (original_file);
gtk_widget_show (icon_pixmap_widget);
icon_aligner = gtk_alignment_new (1, 0.5, 0, 0);
@@ -1444,10 +1450,10 @@ create_basic_page (FMPropertiesWindow *window)
0, 0);
/* Attach parameters and signal handler. */
- nautilus_file_ref (file);
+ nautilus_file_ref (original_file);
gtk_object_set_data_full (GTK_OBJECT (name_field),
"nautilus_file",
- file,
+ original_file,
(GtkDestroyNotify) nautilus_file_unref);
/* Update name field initially before hooking up changed signal. */
@@ -1482,31 +1488,31 @@ create_basic_page (FMPropertiesWindow *window)
}
/* React to name changes from elsewhere. */
- gtk_signal_connect_object_while_alive (GTK_OBJECT (file),
+ gtk_signal_connect_object_while_alive (GTK_OBJECT (target_file),
"changed",
name_field_update_to_match_file,
GTK_OBJECT (name_field));
if (should_show_file_type (window)) {
- append_title_value_pair (table, _("Type:"), file, "type");
+ append_title_value_pair (table, _("Type:"), target_file, "type");
}
- if (nautilus_file_is_directory (file)) {
+ if (nautilus_file_is_directory (target_file)) {
append_directory_contents_fields (window, table);
} else {
- append_title_value_pair (table, _("Size:"), file, "size");
+ append_title_value_pair (table, _("Size:"), target_file, "size");
}
- append_title_and_ellipsizing_value (table, _("Where:"), file, "where");
+ append_title_and_ellipsizing_value (table, _("Where:"), target_file, "where");
if (should_show_mime_type (window)) {
- append_title_value_pair (table, _("MIME type:"), file, "mime_type");
+ append_title_value_pair (table, _("MIME type:"), target_file, "mime_type");
}
/* Blank title ensures standard row height */
append_title_field (table, "");
- append_title_value_pair (table, _("Modified:"), file, "date_modified");
+ append_title_value_pair (table, _("Modified:"), target_file, "date_modified");
if (should_show_accessed_date (window)) {
- append_title_value_pair (table, _("Accessed:"), file, "date_accessed");
+ append_title_value_pair (table, _("Accessed:"), target_file, "date_accessed");
}
if (should_show_custom_icon_buttons (window)) {
@@ -1519,18 +1525,19 @@ create_basic_page (FMPropertiesWindow *window)
gtk_widget_show (temp_button);
gtk_box_pack_start (GTK_BOX (button_box), temp_button, FALSE, FALSE, 4);
nautilus_gtk_button_set_standard_padding (GTK_BUTTON (temp_button));
- gtk_signal_connect(GTK_OBJECT (temp_button), "clicked", GTK_SIGNAL_FUNC (select_image_button_callback), file);
+ gtk_signal_connect(GTK_OBJECT (temp_button), "clicked", GTK_SIGNAL_FUNC (select_image_button_callback), window);
temp_button = gtk_button_new_with_label (_("Remove Custom Icon"));
gtk_widget_show (temp_button);
gtk_box_pack_start (GTK_BOX(button_box), temp_button, FALSE, FALSE, 4);
nautilus_gtk_button_set_standard_padding (GTK_BUTTON (temp_button));
- gtk_signal_connect (GTK_OBJECT (temp_button), "clicked", GTK_SIGNAL_FUNC (remove_image_button_callback), file);
+ gtk_signal_connect (GTK_OBJECT (temp_button), "clicked", GTK_SIGNAL_FUNC (remove_image_button_callback), window);
window->details->remove_image_button = temp_button;
/* de-sensitize the remove button if there isn't a custom image */
- image_uri = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL);
+ image_uri = nautilus_file_get_metadata
+ (original_file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL);
gtk_widget_set_sensitive (temp_button, image_uri != NULL);
g_free (image_uri);
}
@@ -1554,7 +1561,7 @@ create_emblems_page (FMPropertiesWindow *window)
char *label;
NautilusFile *file;
- file = window->details->file;
+ file = window->details->target_file;
/* The emblems wrapped table */
emblems_table = nautilus_wrap_table_new (TRUE);
@@ -1807,7 +1814,7 @@ append_special_execution_checkbox (FMPropertiesWindow *window,
GTK_FILL, 0,
0, 0);
- set_up_permissions_checkbox (check_button, window->details->file, permission_to_check);
+ set_up_permissions_checkbox (check_button, window->details->target_file, permission_to_check);
++window->details->num_special_flags_rows;
return check_button;
@@ -1879,7 +1886,7 @@ create_permissions_page (FMPropertiesWindow *window)
guint last_row;
guint checkbox_titles_row;
- file = window->details->file;
+ file = window->details->target_file;
vbox = create_page_with_vbox (window->details->notebook, _("Permissions"));
@@ -2028,7 +2035,7 @@ should_show_emblems (FMPropertiesWindow *window)
* we shouldn't pretend that they work by showing them here.
* When bug 5643 is fixed we can remove this case.
*/
- if (is_merged_trash_directory (window->details->file)) {
+ if (is_merged_trash_directory (window->details->target_file)) {
return FALSE;
}
@@ -2041,45 +2048,75 @@ should_show_permissions (FMPropertiesWindow *window)
/* Don't show permissions for the Trash since it's not
* really a file system object.
*/
- if (is_merged_trash_directory (window->details->file)) {
+ if (is_merged_trash_directory (window->details->target_file)) {
return FALSE;
}
return TRUE;
}
+static StartupData *
+startup_data_new (NautilusFile *original_file,
+ NautilusFile *target_file,
+ FMDirectoryView *directory_view)
+{
+ StartupData *data;
+
+ data = g_new0 (StartupData, 1);
+ data->original_file = nautilus_file_ref (original_file);
+ data->target_file = nautilus_file_ref (target_file);
+ data->directory_view = directory_view;
+
+ return data;
+}
+
+static void
+startup_data_free (StartupData *data)
+{
+ nautilus_file_unref (data->original_file);
+ nautilus_file_unref (data->target_file);
+ g_free (data);
+}
+
static FMPropertiesWindow *
-create_properties_window (NautilusFile *file)
+create_properties_window (StartupData *startup_data)
{
FMPropertiesWindow *window;
GList *attributes;
window = FM_PROPERTIES_WINDOW (gtk_widget_new (fm_properties_window_get_type (), NULL));
- nautilus_file_ref (file);
- window->details->file = file;
+ window->details->original_file = nautilus_file_ref (startup_data->original_file);
+ window->details->target_file = nautilus_file_ref (startup_data->target_file);
gtk_container_set_border_width (GTK_CONTAINER (window), GNOME_PAD);
gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
gtk_window_set_wmclass (GTK_WINDOW (window), "file_properties", "Nautilus");
/* Set initial window title */
- update_properties_window_title (GTK_WINDOW (window), window->details->file);
+ update_properties_window_title (GTK_WINDOW (window), window->details->target_file);
- /* Start monitoring the file attributes we display */
+ /* Start monitoring the file attributes we display. Note that some
+ * of the attributes are for the original file, and some for the
+ * target file.
+ */
attributes = nautilus_icon_factory_get_required_file_attributes ();
- if (nautilus_file_is_directory (window->details->file)) {
+ nautilus_file_monitor_add (window->details->original_file, window, attributes);
+ g_list_free (attributes);
+
+ attributes = NULL;
+ if (nautilus_file_is_directory (window->details->target_file)) {
attributes = g_list_prepend (attributes,
NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS);
}
attributes = g_list_prepend (attributes,
NAUTILUS_FILE_ATTRIBUTE_METADATA);
- nautilus_file_monitor_add (window->details->file, window, attributes);
+ nautilus_file_monitor_add (window->details->target_file, window, attributes);
g_list_free (attributes);
/* React to future property changes and file deletions. */
window->details->file_changed_handler_id =
- gtk_signal_connect_object (GTK_OBJECT (window->details->file),
+ gtk_signal_connect_object (GTK_OBJECT (window->details->target_file),
"changed",
properties_window_file_changed_callback,
GTK_OBJECT (window));
@@ -2105,14 +2142,14 @@ create_properties_window (NautilusFile *file)
}
static NautilusFile *
-get_and_ref_file_to_display (NautilusFile *file)
+get_target_file (NautilusFile *file)
{
- NautilusFile *file_to_display;
+ NautilusFile *target_file;
char *uri;
char *uri_to_display;
char *local_path;
- file_to_display = NULL;
+ target_file = NULL;
if (nautilus_file_is_nautilus_link (file)) {
/* Note: This will only work on local files. For now
* that seems fine since the links we care about are
@@ -2127,7 +2164,7 @@ get_and_ref_file_to_display (NautilusFile *file)
case NAUTILUS_LINK_HOME:
/* map to linked URI for these types of links */
uri_to_display = nautilus_link_local_get_link_uri (local_path);
- file_to_display = nautilus_file_get (uri_to_display);
+ target_file = nautilus_file_get (uri_to_display);
g_free (uri_to_display);
break;
case NAUTILUS_LINK_GENERIC:
@@ -2140,8 +2177,8 @@ get_and_ref_file_to_display (NautilusFile *file)
g_free (uri);
}
- if (file_to_display != NULL) {
- return file_to_display;
+ if (target_file != NULL) {
+ return target_file;
}
/* Ref passed-in file here since we've decided to use it. */
@@ -2153,14 +2190,15 @@ static void
create_properties_window_callback (NautilusFile *file, gpointer callback_data)
{
FMPropertiesWindow *new_window;
+ StartupData *startup_data;
- g_assert (FM_IS_DIRECTORY_VIEW (callback_data));
+ startup_data = (StartupData *)callback_data;
- new_window = create_properties_window (file);
+ new_window = create_properties_window (startup_data);
- remove_pending_file (file, FALSE, TRUE, TRUE);
+ g_hash_table_insert (windows, startup_data->original_file, new_window);
- g_hash_table_insert (windows, file, new_window);
+ remove_pending_file (startup_data, FALSE, TRUE, TRUE);
/* FIXME bugzilla.eazel.com 2151:
* See comment elsewhere in this file about bug 2151.
@@ -2175,50 +2213,50 @@ create_properties_window_callback (NautilusFile *file, gpointer callback_data)
static void
cancel_create_properties_window_callback (gpointer callback_data)
{
- remove_pending_file (NAUTILUS_FILE (callback_data), TRUE, FALSE, TRUE);
+ remove_pending_file ((StartupData *)callback_data, TRUE, FALSE, TRUE);
}
static void
directory_view_destroyed_callback (FMDirectoryView *view, gpointer callback_data)
{
- remove_pending_file (NAUTILUS_FILE (callback_data), TRUE, TRUE, FALSE);
+ g_assert (view == ((StartupData *)callback_data)->directory_view);
+
+ remove_pending_file ((StartupData *)callback_data, TRUE, TRUE, FALSE);
}
static void
-remove_pending_file (NautilusFile *file,
+remove_pending_file (StartupData *startup_data,
gboolean cancel_call_when_ready,
gboolean cancel_timed_wait,
gboolean cancel_destroy_handler)
{
- FMDirectoryView *view;
-
- view = g_hash_table_lookup (pending_files, file);
- g_return_if_fail (view != NULL);
-
if (cancel_call_when_ready) {
- nautilus_file_cancel_call_when_ready (file, create_properties_window_callback, view);
+ nautilus_file_cancel_call_when_ready
+ (startup_data->target_file, create_properties_window_callback, startup_data);
}
if (cancel_timed_wait) {
- nautilus_timed_wait_stop (cancel_create_properties_window_callback, file);
+ nautilus_timed_wait_stop
+ (cancel_create_properties_window_callback, startup_data);
}
if (cancel_destroy_handler) {
- gtk_signal_disconnect_by_func (GTK_OBJECT (view),
+ gtk_signal_disconnect_by_func (GTK_OBJECT (startup_data->directory_view),
directory_view_destroyed_callback,
- file);
+ startup_data);
}
- g_hash_table_remove (pending_files, file);
- nautilus_file_unref (file);
+ g_hash_table_remove (pending_files, startup_data->original_file);
+ startup_data_free (startup_data);
}
void
-fm_properties_window_present (NautilusFile *file, FMDirectoryView *directory_view)
+fm_properties_window_present (NautilusFile *original_file, FMDirectoryView *directory_view)
{
GtkWindow *existing_window;
GtkWidget *parent_window;
- NautilusFile *file_to_display;
+ NautilusFile *target_file;
+ StartupData *startup_data;
GList attribute_list;
- g_return_if_fail (NAUTILUS_IS_FILE (file));
+ g_return_if_fail (NAUTILUS_IS_FILE (original_file));
g_return_if_fail (FM_IS_DIRECTORY_VIEW (directory_view));
/* Create the hash tables first time through. */
@@ -2232,34 +2270,36 @@ fm_properties_window_present (NautilusFile *file, FMDirectoryView *directory_vie
(NULL, NULL, "pending property window files");
}
- file_to_display = get_and_ref_file_to_display (file);
-
/* Look to see if there's already a window for this file. */
- existing_window = g_hash_table_lookup (windows, file_to_display);
+ existing_window = g_hash_table_lookup (windows, original_file);
if (existing_window != NULL) {
- nautilus_file_unref (file_to_display);
nautilus_gtk_window_present (existing_window);
return;
}
/* Look to see if we're already waiting for a window for this file. */
- if (g_hash_table_lookup (pending_files, file_to_display) != NULL) {
- nautilus_file_unref (file_to_display);
+ if (g_hash_table_lookup (pending_files, original_file) != NULL) {
return;
}
- /* Wait until we can tell whether it's a directory before showing. */
+ target_file = get_target_file (original_file);
+ startup_data = startup_data_new (original_file, target_file, directory_view);
+ nautilus_file_unref (target_file);
+
+ /* Wait until we can tell whether it's a directory before showing, since
+ * some one-time layout decisions depend on that info.
+ */
- g_hash_table_insert (pending_files, file_to_display, directory_view);
+ g_hash_table_insert (pending_files, target_file, target_file);
gtk_signal_connect (GTK_OBJECT (directory_view),
"destroy",
directory_view_destroyed_callback,
- file_to_display);
+ startup_data);
parent_window = gtk_widget_get_ancestor (GTK_WIDGET (directory_view), GTK_TYPE_WINDOW);
nautilus_timed_wait_start
(cancel_create_properties_window_callback,
- file_to_display,
+ startup_data,
_("Cancel Showing Properties Window?"),
_("Creating Properties window"),
parent_window == NULL ? NULL : GTK_WINDOW (parent_window));
@@ -2267,8 +2307,8 @@ fm_properties_window_present (NautilusFile *file, FMDirectoryView *directory_vie
attribute_list.next = NULL;
attribute_list.prev = NULL;
nautilus_file_call_when_ready
- (file_to_display, &attribute_list,
- create_properties_window_callback, directory_view);
+ (target_file, &attribute_list,
+ create_properties_window_callback, startup_data);
}
static void
@@ -2281,7 +2321,7 @@ real_shutdown (GtkObject *object)
/* Disconnect file-changed handler here to avoid infinite loop
* of change notifications when file is removed; see bug 4911.
*/
- gtk_signal_disconnect (GTK_OBJECT (window->details->file),
+ gtk_signal_disconnect (GTK_OBJECT (window->details->target_file),
window->details->file_changed_handler_id);
NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, shutdown, (object));
@@ -2294,9 +2334,14 @@ real_destroy (GtkObject *object)
window = FM_PROPERTIES_WINDOW (object);
- nautilus_file_monitor_remove (window->details->file, window);
- g_hash_table_remove (windows, window->details->file);
- nautilus_file_unref (window->details->file);
+ g_hash_table_remove (windows, window->details->original_file);
+
+ nautilus_file_monitor_remove (window->details->original_file, window);
+ nautilus_file_unref (window->details->original_file);
+
+ nautilus_file_monitor_remove (window->details->target_file, window);
+ nautilus_file_unref (window->details->target_file);
+
g_list_free (window->details->directory_contents_widgets);
g_list_free (window->details->special_flags_widgets);
@@ -2335,7 +2380,7 @@ set_icon_callback (const char* icon_path, FMPropertiesWindow *properties_window)
g_return_if_fail (FM_IS_PROPERTIES_WINDOW (properties_window));
if (icon_path != NULL) {
- file = properties_window->details->file;
+ file = properties_window->details->original_file;
nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_CUSTOM_ICON, NULL, icon_path);
nautilus_file_set_metadata (file, NAUTILUS_METADATA_KEY_ICON_SCALE, NULL, NULL);
@@ -2347,12 +2392,11 @@ set_icon_callback (const char* icon_path, FMPropertiesWindow *properties_window)
/* handle the "select icon" button */
static void
-select_image_button_callback (GtkWidget *widget, NautilusFile *file)
+select_image_button_callback (GtkWidget *widget, FMPropertiesWindow *properties_window)
{
GtkWidget *dialog;
- FMPropertiesWindow *properties_window;
- properties_window = FM_PROPERTIES_WINDOW (gtk_widget_get_toplevel (widget));
+ g_assert (FM_IS_PROPERTIES_WINDOW (properties_window));
dialog = nautilus_gnome_icon_selector_new (_("Select an icon:"),
NULL,
@@ -2362,14 +2406,14 @@ select_image_button_callback (GtkWidget *widget, NautilusFile *file)
}
static void
-remove_image_button_callback (GtkWidget *widget, NautilusFile *file)
+remove_image_button_callback (GtkWidget *widget, FMPropertiesWindow *properties_window)
{
- g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (FM_IS_PROPERTIES_WINDOW (properties_window));
- nautilus_file_set_metadata (NAUTILUS_FILE (file),
+ nautilus_file_set_metadata (properties_window->details->original_file,
NAUTILUS_METADATA_KEY_ICON_SCALE,
NULL, NULL);
- nautilus_file_set_metadata (NAUTILUS_FILE (file),
+ nautilus_file_set_metadata (properties_window->details->original_file,
NAUTILUS_METADATA_KEY_CUSTOM_ICON,
NULL, NULL);