The attached patch is meant to implement recursive file permission changes [1]. I'm eagerly awaiting feedback, in particular whether the GUI offers enough usability for you. [1] http://bugzilla.gnome.org/show_bug.cgi?id=44767 -- Christian Neumair <chris gnome-de org>
Index: src/file-manager/fm-properties-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/file-manager/fm-properties-window.c,v
retrieving revision 1.226
diff -u -p -r1.226 fm-properties-window.c
--- src/file-manager/fm-properties-window.c 20 Dec 2005 16:37:33 -0000 1.226
+++ src/file-manager/fm-properties-window.c 26 Dec 2005 00:24:04 -0000
@@ -68,7 +68,9 @@
#include <libgnomevfs/gnome-vfs.h>
#include <libnautilus-extension/nautilus-property-page-provider.h>
#include <libnautilus-private/nautilus-customization-data.h>
+#include <libnautilus-private/nautilus-directory.h>
#include <libnautilus-private/nautilus-entry.h>
+#include <libnautilus-private/nautilus-file.h>
#include <libnautilus-private/nautilus-file-attributes.h>
#include <libnautilus-private/nautilus-desktop-icon-file.h>
#include <libnautilus-private/nautilus-global-preferences.h>
@@ -119,6 +121,9 @@ struct FMPropertiesWindowDetails {
GList *permission_buttons;
GHashTable *initial_permissions;
+ GtkWidget *apply_recursively_button;
+ GtkWidget *apply_to_combo;
+
GList *value_fields;
GList *mime_list;
@@ -175,6 +180,20 @@ static const GtkTargetEntry target_table
{ "x-special/gnome-reset-background", 0, TARGET_RESET_BACKGROUND }
};
+typedef enum {
+ PERMISSIONS_CHANGE_SCOPE_SUBFOLDERS = 1 << 0,
+ PERMISSIONS_CHANGE_SCOPE_FILES = 1 << 1,
+} PermissionsChangeScope;
+
+typedef struct {
+ FMPropertiesWindow *window;
+ GnomeVFSFilePermissions permission_mask;
+ gboolean is_on;
+ PermissionsChangeScope scope;
+ unsigned int ref;
+} PermissionsChangeRequest;
+
+
#define DIRECTORY_CONTENTS_UPDATE_INTERVAL 200 /* milliseconds */
#define FILES_UPDATE_INTERVAL 200 /* milliseconds */
#define STANDARD_EMBLEM_HEIGHT 52
@@ -185,10 +204,14 @@ static void file_changed_callback
gpointer user_data);
static void permission_button_update (FMPropertiesWindow *window,
GtkToggleButton *button);
+static void permission_change_callback (NautilusFile *file,
+ GnomeVFSResult result,
+ PermissionsChangeRequest *request);
static void value_field_update (FMPropertiesWindow *window,
GtkLabel *field);
static void properties_window_update (FMPropertiesWindow *window,
GList *files);
+static gboolean file_list_at_least_one_directory (GList *file_list);
static void is_directory_ready_callback (NautilusFile *file,
gpointer data);
static void cancel_group_change_callback (gpointer callback_data);
@@ -1167,6 +1190,8 @@ properties_window_update (FMPropertiesWi
}
if (dirty_target) {
+ gboolean at_least_one_directory;
+
for (l = window->details->permission_buttons; l != NULL; l = l->next) {
permission_button_update (window, GTK_TOGGLE_BUTTON (l->data));
}
@@ -1174,6 +1199,11 @@ properties_window_update (FMPropertiesWi
for (l = window->details->value_fields; l != NULL; l = l->next) {
value_field_update (window, GTK_LABEL (l->data));
}
+
+ at_least_one_directory = file_list_at_least_one_directory (window->details->target_files);
+
+ gtk_widget_set_sensitive (window->details->apply_recursively_button, at_least_one_directory);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->details->apply_recursively_button), FALSE);
}
mime_list = get_mime_list (window);
@@ -1311,6 +1341,20 @@ file_list_all_directories (GList *file_l
return TRUE;
}
+static gboolean
+file_list_at_least_one_directory (GList *file_list)
+{
+ GList *l;
+
+ for (l = file_list; l != NULL; l = l->next) {
+ if (nautilus_file_is_directory (NAUTILUS_FILE (l->data))) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
value_field_update_internal (GtkLabel *label,
GList *file_list,
@@ -2484,23 +2528,119 @@ create_emblems_page (FMPropertiesWindow
}
static void
-permission_change_callback (NautilusFile *file, GnomeVFSResult result, gpointer callback_data)
+directory_contents_ready (NautilusDirectory *directory,
+ GList *files,
+ PermissionsChangeRequest *request)
{
- FMPropertiesWindow *window;
- g_assert (callback_data != NULL);
+ NautilusFile *file;
+ GList *l;
- window = FM_PROPERTIES_WINDOW (callback_data);
- if (GTK_WIDGET (window)->window != NULL &&
- window->details->long_operation_underway == 1) {
+ g_assert (FM_IS_PROPERTIES_WINDOW (request->window));
+
+ for (l = files; l != NULL; l = l->next) {
+ file = NAUTILUS_FILE (l->data);
+
+ request->ref++;
+ request->window->details->long_operation_underway++;
+
+ if (nautilus_file_can_set_permissions (file) &&
+ (((request->scope & PERMISSIONS_CHANGE_SCOPE_FILES) != 0 &&
+ !nautilus_file_is_directory (file)) ||
+ ((request->scope & PERMISSIONS_CHANGE_SCOPE_SUBFOLDERS) != 0 &&
+ nautilus_file_is_directory (file)))) {
+ GnomeVFSFilePermissions permissions;
+
+ permissions = nautilus_file_get_permissions (file);
+ if (request->is_on) {
+ permissions |= request->permission_mask;
+ } else {
+ permissions &= ~request->permission_mask;
+ }
+
+ nautilus_file_set_permissions
+ (file, permissions,
+ (NautilusFileOperationCallback) permission_change_callback,
+ request);
+ }
+ }
+
+
+ nautilus_directory_file_monitor_remove (directory, request->window);
+ nautilus_directory_unref (directory);
+
+ if (GTK_WIDGET (request->window)->window != NULL &&
+ request->window->details->long_operation_underway == 1) {
+ /* finished !! */
+ gdk_window_set_cursor (GTK_WIDGET (request->window)->window, NULL);
+ }
+
+ request->window->details->long_operation_underway--;
+
+ if (--request->ref == 0) {
+ g_object_unref (request->window);
+ g_free (request);
+ }
+}
+
+static void
+directory_done_loading (NautilusDirectory *directory,
+ PermissionsChangeRequest *request)
+{
+ g_assert (NAUTILUS_IS_DIRECTORY (directory));
+ g_assert (FM_IS_PROPERTIES_WINDOW (request->window));
+
+ nautilus_directory_call_when_ready (directory,
+ nautilus_mime_actions_get_minimum_file_attributes (),
+ TRUE,
+ (NautilusDirectoryCallback) directory_contents_ready,
+ request);
+}
+
+static void
+permission_change_callback (NautilusFile *file,
+ GnomeVFSResult result,
+ PermissionsChangeRequest *request)
+{
+ NautilusDirectory *directory;
+
+ g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (FM_IS_PROPERTIES_WINDOW (request->window));
+
+ if (request->scope != 0 &&
+ nautilus_file_is_directory (file)) {
+ /* will be dec. in directory_contents_ready */
+ request->ref++;
+ request->window->details->long_operation_underway++;
+
+ directory = nautilus_directory_get_for_file (file);
+ if (nautilus_directory_are_all_files_seen (directory)) {
+ directory_done_loading (directory, request);
+ } else {
+ g_signal_connect (directory, "done-loading",
+ G_CALLBACK (directory_done_loading),
+ request);
+ nautilus_directory_file_monitor_add (directory, request->window,
+ TRUE, TRUE,
+ NAUTILUS_FILE_ATTRIBUTE_CAPABILITIES |
+ NAUTILUS_FILE_ATTRIBUTE_IS_DIRECTORY,
+ NULL, NULL);
+ }
+ }
+
+ if (GTK_WIDGET (request->window)->window != NULL &&
+ request->window->details->long_operation_underway == 1) {
/* finished !! */
- gdk_window_set_cursor (GTK_WIDGET (window)->window, NULL);
+ gdk_window_set_cursor (GTK_WIDGET (request->window)->window, NULL);
}
- window->details->long_operation_underway--;
+ request->window->details->long_operation_underway--;
/* Report the error if it's an error. */
fm_report_error_setting_permissions (file, result, NULL);
- g_object_unref (window);
+ if (--request->ref == 0) {
+ g_object_unref (request->window);
+ g_free (request);
+ }
}
static void
@@ -2528,6 +2668,30 @@ get_initial_permission_state (FMProperti
}
}
+static PermissionsChangeScope
+get_permissions_change_scope (FMPropertiesWindow *window)
+{
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window->details->apply_recursively_button))) {
+ /* cf. append_recursive_buttons */
+ switch (gtk_combo_box_get_active (GTK_COMBO_BOX (window->details->apply_to_combo))) {
+ case 0:
+ return PERMISSIONS_CHANGE_SCOPE_FILES;
+
+ case 1:
+ return PERMISSIONS_CHANGE_SCOPE_SUBFOLDERS;
+
+ case 2:
+ return PERMISSIONS_CHANGE_SCOPE_FILES |
+ PERMISSIONS_CHANGE_SCOPE_SUBFOLDERS;
+
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ return 0;
+}
+
static void
permission_button_toggled (GtkToggleButton *button,
FMPropertiesWindow *window)
@@ -2536,6 +2700,7 @@ permission_button_toggled (GtkToggleButt
GnomeVFSFilePermissions permission_mask;
GList *files_on;
GList *files_off;
+ PermissionsChangeScope scope;
permission_mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
"permission"));
@@ -2586,6 +2751,11 @@ permission_button_toggled (GtkToggleButt
window->details->long_operation_underway += g_list_length (files_on);
window->details->long_operation_underway += g_list_length (files_off);
+ scope = 0;
+ if (file_list_at_least_one_directory (window->details->target_files)) {
+ scope = get_permissions_change_scope (window);
+ }
+
for (l = files_on; l != NULL; l = l->next) {
NautilusFile *file;
@@ -2593,15 +2763,22 @@ permission_button_toggled (GtkToggleButt
if (nautilus_file_can_set_permissions (file)) {
GnomeVFSFilePermissions permissions;
+ PermissionsChangeRequest *request;
permissions = nautilus_file_get_permissions (file);
permissions |= permission_mask;
-
- g_object_ref (window);
+
+ request = g_new (PermissionsChangeRequest, 1);
+ request->window = g_object_ref (window);
+ request->scope = scope;
+ request->is_on = TRUE;
+ request->permission_mask = permission_mask;
+ request->ref = 1;
+
nautilus_file_set_permissions
(file, permissions,
- permission_change_callback,
- window);
+ (NautilusFileOperationCallback) permission_change_callback,
+ request);
}
}
@@ -2613,15 +2790,22 @@ permission_button_toggled (GtkToggleButt
if (nautilus_file_can_set_permissions (file)) {
GnomeVFSFilePermissions permissions;
+ PermissionsChangeRequest *request;
permissions = nautilus_file_get_permissions (file);
permissions &= ~permission_mask;
- g_object_ref (window);
+ request = g_new (PermissionsChangeRequest, 1);
+ request->window = g_object_ref (window);
+ request->scope = scope;
+ request->is_on = FALSE;
+ request->permission_mask = permission_mask;
+ request->ref = 1;
+
nautilus_file_set_permissions
(file, permissions,
- permission_change_callback,
- window);
+ (NautilusFileOperationCallback) permission_change_callback,
+ request);
}
}
@@ -2826,6 +3010,56 @@ append_special_execution_flags (FMProper
}
+static void
+apply_recursively_button_toggled (GtkToggleButton *button,
+ GtkWidget *combo)
+{
+ gboolean sensitive;
+
+ sensitive = GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (button)) &&
+ gtk_toggle_button_get_active (button);
+
+ gtk_widget_set_sensitive (combo, sensitive);
+ if (sensitive) {
+ gtk_widget_grab_focus (combo);
+ }
+}
+
+static void
+append_recursive_buttons (FMPropertiesWindow *window,
+ GtkTable *table)
+{
+ unsigned int last_row;
+ GtkWidget *hbox;
+
+ last_row = append_row (table);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_widget_show (hbox);
+ gtk_table_attach (table, hbox,
+ TITLE_COLUMN, VALUE_COLUMN + 1,
+ last_row, last_row + 1,
+ GTK_FILL, 0,
+ 0, 0);
+
+ window->details->apply_recursively_button =
+ gtk_check_button_new_with_mnemonic ("_Apply recursively:");
+ gtk_widget_show (window->details->apply_recursively_button);
+ gtk_container_add (GTK_CONTAINER (hbox), window->details->apply_recursively_button);
+
+ window->details->apply_to_combo = gtk_combo_box_new_text ();
+ gtk_combo_box_append_text (GTK_COMBO_BOX (window->details->apply_to_combo), _("Files"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (window->details->apply_to_combo), _("Folders"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (window->details->apply_to_combo), _("Whole Contents"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (window->details->apply_to_combo), 2);
+ gtk_widget_show (window->details->apply_to_combo);
+ gtk_box_pack_start (GTK_BOX (hbox), window->details->apply_to_combo, FALSE, FALSE, 0);
+
+ g_signal_connect (window->details->apply_recursively_button, "toggled",
+ G_CALLBACK (apply_recursively_button_toggled),
+ window->details->apply_to_combo);
+}
+
static gboolean
all_can_get_permissions (GList *file_list)
{
@@ -3060,6 +3294,10 @@ create_permissions_page (FMPropertiesWin
(window, page_table, _("Last changed:"),
"date_permissions", _("--"),
FALSE);
+
+ append_separator (page_table);
+
+ append_recursive_buttons (window, page_table);
} else {
if (!is_multi_file_window (window)) {
file_name = nautilus_file_get_display_name (get_target_file (window));
Attachment:
signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil