diff options
author | Darin Adler <darin@src.gnome.org> | 2000-06-21 00:29:59 +0000 |
---|---|---|
committer | Darin Adler <darin@src.gnome.org> | 2000-06-21 00:29:59 +0000 |
commit | d2822cb5d85d7cb43cd8cea389b522a6f37ae232 (patch) | |
tree | e5e68f86934f2ffa29301e2ede3daac4def1a03b /libnautilus-private/nautilus-undo-manager.c | |
parent | 81b81f62f4efcfc18f6c271bf64f6e6adfd638dc (diff) | |
download | nautilus-d2822cb5d85d7cb43cd8cea389b522a6f37ae232.tar.gz |
Make octal permissions always at least 3 digits long.
* libnautilus-extensions/nautilus-file.c:
(nautilus_file_get_octal_permissions_as_string):
Make octal permissions always at least 3 digits long.
* libnautilus-extensions/nautilus-undo-manager.c:
(destroy_servant), (create_servant), (release_transaction),
(corba_append), (corba_forget), (corba_undo),
(nautilus_undo_manager_initialize),
(nautilus_undo_manager_initialize_class),
(nautilus_undo_manager_undo), (destroy), (update_undo_menu_item):
Rewrote undo manager to support one level of undo and redo.
Diffstat (limited to 'libnautilus-private/nautilus-undo-manager.c')
-rw-r--r-- | libnautilus-private/nautilus-undo-manager.c | 501 |
1 files changed, 161 insertions, 340 deletions
diff --git a/libnautilus-private/nautilus-undo-manager.c b/libnautilus-private/nautilus-undo-manager.c index b8b6e7bf8..481705b3a 100644 --- a/libnautilus-private/nautilus-undo-manager.c +++ b/libnautilus-private/nautilus-undo-manager.c @@ -33,10 +33,17 @@ #include "nautilus-undo-context.h" struct NautilusUndoManagerDetails { - GList *undo_list; - GList *redo_list; - gboolean enable_redo; - gint queue_depth; + Nautilus_Undo_Transaction transaction; + + /* These are used to tell undo from redo. */ + gboolean current_transaction_is_redo; + gboolean new_transaction_is_redo; + + /* These are used only so that we can complain if we get more + * than one transaction inside undo. + */ + gboolean undo_in_progress; + int num_transactions_during_undo; }; enum { @@ -48,7 +55,7 @@ static guint signals[LAST_SIGNAL]; typedef struct { POA_Nautilus_Undo_Manager servant; NautilusUndoManager *bonobo_object; -} impl_POA_Nautilus_Undo_Manager; +} UndoManagerServant; typedef struct { BonoboUIHandler *handler; @@ -58,57 +65,53 @@ typedef struct { } UndoMenuHandlerConnection; /* GtkObject */ -static void nautilus_undo_manager_initialize_class (NautilusUndoManagerClass *class); -static void nautilus_undo_manager_initialize (NautilusUndoManager *item); -static void destroy (GtkObject *object); -static void free_undo_manager_list (GList *list); -static GList *prune_undo_manager_list (GList *list, - int items); +static void nautilus_undo_manager_initialize_class (NautilusUndoManagerClass *class); +static void nautilus_undo_manager_initialize (NautilusUndoManager *item); +static void destroy (GtkObject *object); + /* CORBA/Bonobo */ -static void impl_Nautilus_Undo_Manager__append (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev); -static void impl_Nautilus_Undo_Manager__forget (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev); -static void impl_Nautilus_Undo_Manager__undo (PortableServer_Servant servant, - CORBA_Environment *ev); -static void nautilus_undo_manager_add_transaction (NautilusUndoManager *manager, - Nautilus_Undo_Transaction transaction); -static void nautilus_undo_manager_forget_transaction (NautilusUndoManager *manager, - Nautilus_Undo_Transaction transaction); - -NAUTILUS_DEFINE_CLASS_BOILERPLATE(NautilusUndoManager, nautilus_undo_manager, BONOBO_OBJECT_TYPE) - -static POA_Nautilus_Undo_Manager__epv libnautilus_Nautilus_Undo_Manager_epv = -{ +static void corba_append (PortableServer_Servant servant, + Nautilus_Undo_Transaction transaction, + CORBA_Environment *ev); +static void corba_forget (PortableServer_Servant servant, + Nautilus_Undo_Transaction transaction, + CORBA_Environment *ev); +static void corba_undo (PortableServer_Servant servant, + CORBA_Environment *ev); + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusUndoManager, nautilus_undo_manager, BONOBO_OBJECT_TYPE) + +static PortableServer_ServantBase__epv base_epv; +static POA_Nautilus_Undo_Manager__epv epv = { NULL, - &impl_Nautilus_Undo_Manager__append, - &impl_Nautilus_Undo_Manager__forget, - &impl_Nautilus_Undo_Manager__undo, + &corba_append, + &corba_forget, + &corba_undo, }; -static PortableServer_ServantBase__epv base_epv; -static POA_Nautilus_Undo_Manager__vepv vepv = -{ +static POA_Nautilus_Undo_Manager__vepv vepv = { &base_epv, NULL, - &libnautilus_Nautilus_Undo_Manager_epv + &epv }; static void -impl_Nautilus_Undo_Manager__destroy (BonoboObject *object, - impl_POA_Nautilus_Undo_Manager *servant) +destroy_servant (BonoboObject *object, + UndoManagerServant *servant) { PortableServer_ObjectId *object_id; CORBA_Environment ev; CORBA_exception_init (&ev); + /* Deactivate the object. */ object_id = PortableServer_POA_servant_to_id (bonobo_poa (), servant, &ev); PortableServer_POA_deactivate_object (bonobo_poa (), object_id, &ev); CORBA_free (object_id); + + /* Disconnect the object from the servant. */ object->servant = NULL; + /* Free the servant. */ POA_Nautilus_Undo_Manager__fini (servant, &ev); g_free (servant); @@ -116,58 +119,110 @@ impl_Nautilus_Undo_Manager__destroy (BonoboObject *object, } static Nautilus_Undo_Manager -impl_Nautilus_Undo_Manager__create (NautilusUndoManager *bonobo_object, - CORBA_Environment *ev) +create_servant (NautilusUndoManager *bonobo_object, + CORBA_Environment *ev) { - impl_POA_Nautilus_Undo_Manager *servant; + UndoManagerServant *servant; - servant = g_new0 (impl_POA_Nautilus_Undo_Manager, 1); - - vepv.Bonobo_Unknown_epv = bonobo_object_get_epv (); + /* Create the servant. */ + servant = g_new0 (UndoManagerServant, 1); servant->servant.vepv = &vepv; + servant->bonobo_object = bonobo_object; POA_Nautilus_Undo_Manager__init ((PortableServer_Servant) servant, ev); + /* Set up code so we will destroy the servant when the bonobo_object is destroyed. */ gtk_signal_connect (GTK_OBJECT (bonobo_object), "destroy", - GTK_SIGNAL_FUNC (impl_Nautilus_Undo_Manager__destroy), - servant); + destroy_servant, servant); - servant->bonobo_object = bonobo_object; + /* Activate the servant to create the CORBA object. */ return bonobo_object_activate_servant (BONOBO_OBJECT (bonobo_object), servant); } static void -impl_Nautilus_Undo_Manager__append (PortableServer_Servant servant, - Nautilus_Undo_Transaction undo_transaction, - CORBA_Environment *ev) +release_transaction (NautilusUndoManager *manager) +{ + Nautilus_Undo_Transaction transaction; + + CORBA_Environment ev; + + CORBA_exception_init (&ev); + + transaction = manager->details->transaction; + manager->details->transaction = CORBA_OBJECT_NIL; + if (!CORBA_Object_is_nil (transaction, &ev)) { + Nautilus_Undo_Transaction_unref (transaction, &ev); + CORBA_Object_release (transaction, &ev); + } + + CORBA_exception_free (&ev); +} + +static void +corba_append (PortableServer_Servant servant, + Nautilus_Undo_Transaction transaction, + CORBA_Environment *ev) { NautilusUndoManager *manager; + Nautilus_Undo_Transaction duplicate_transaction; - manager = ((impl_POA_Nautilus_Undo_Manager *) servant)->bonobo_object; + manager = ((UndoManagerServant *) servant)->bonobo_object; g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); - nautilus_undo_manager_add_transaction (manager, undo_transaction); + /* Check, complain, and ignore the passed-in transaction if we + * get more than one within a single undo operation. The single + * transaction we get during the undo operation is supposed to + * be the one for redoing the undo (or re-undoing the redo). + */ + if (manager->details->undo_in_progress) { + manager->details->num_transactions_during_undo += 1; + g_return_if_fail (manager->details->num_transactions_during_undo == 1); + } + + g_return_if_fail (!CORBA_Object_is_nil (transaction, ev)); + + /* Keep a copy of this transaction (dump the old one). */ + duplicate_transaction = CORBA_Object_duplicate (transaction, ev); + Nautilus_Undo_Transaction_ref (duplicate_transaction, ev); + release_transaction (manager); + manager->details->transaction = duplicate_transaction; + manager->details->current_transaction_is_redo = + manager->details->new_transaction_is_redo; + + /* Fire off signal indicating that the undo state has changed. */ + gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); } static void -impl_Nautilus_Undo_Manager__forget (PortableServer_Servant servant, - Nautilus_Undo_Transaction transaction, - CORBA_Environment *ev) +corba_forget (PortableServer_Servant servant, + Nautilus_Undo_Transaction transaction, + CORBA_Environment *ev) { NautilusUndoManager *manager; - manager = ((impl_POA_Nautilus_Undo_Manager *) servant)->bonobo_object; + manager = ((UndoManagerServant *) servant)->bonobo_object; g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); - nautilus_undo_manager_forget_transaction (manager, transaction); + /* Nothing to forget unless the item we are passed is the + * transaction we are currently holding. + */ + if (!CORBA_Object_is_equivalent (manager->details->transaction, transaction, ev)) { + return; + } + + /* Get rid of the transaction we are holding on to. */ + release_transaction (manager); + + /* Fire off signal indicating that the undo state has changed. */ + gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); } -static void -impl_Nautilus_Undo_Manager__undo (PortableServer_Servant servant, - CORBA_Environment *ev) +static void +corba_undo (PortableServer_Servant servant, + CORBA_Environment *ev) { NautilusUndoManager *manager; - manager = ((impl_POA_Nautilus_Undo_Manager *) servant)->bonobo_object; + manager = ((UndoManagerServant *) servant)->bonobo_object; g_assert (NAUTILUS_IS_UNDO_MANAGER (manager)); nautilus_undo_manager_undo (manager); @@ -188,322 +243,83 @@ nautilus_undo_manager_initialize (NautilusUndoManager *manager) manager->details = g_new0 (NautilusUndoManagerDetails, 1); - /* Set queue depth to a single level */ - manager->details->queue_depth = 1; - bonobo_object_construct (BONOBO_OBJECT (manager), - impl_Nautilus_Undo_Manager__create (manager, &ev)); + create_servant (manager, &ev)); CORBA_exception_free (&ev); } - static void nautilus_undo_manager_initialize_class (NautilusUndoManagerClass *klass) { GtkObjectClass *object_class; + vepv.Bonobo_Unknown_epv = bonobo_object_get_epv (); + object_class = GTK_OBJECT_CLASS (klass); object_class->destroy = destroy; - signals[CHANGED] - = gtk_signal_new ("changed", - GTK_RUN_LAST, - object_class->type, - GTK_SIGNAL_OFFSET (NautilusUndoManagerClass, - changed), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); + signals[CHANGED] = gtk_signal_new + ("changed", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (NautilusUndoManagerClass, + changed), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); } -void +void nautilus_undo_manager_undo (NautilusUndoManager *manager) { - GList *last_in_list; - CORBA_Object undo_transaction; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - /* Verify we have a transaction to be undone */ - if (manager->details->undo_list == NULL) { - return; - } - - /* Pop last transaction off undo list */ - last_in_list = g_list_last (manager->details->undo_list); - g_assert (last_in_list != NULL); - undo_transaction = last_in_list->data; - manager->details->undo_list = g_list_remove (manager->details->undo_list, undo_transaction); - - /* Undo transaction */ - Nautilus_Undo_Transaction_undo (undo_transaction, &ev); - - /* Place transaction into redo list */ - if (manager->details->enable_redo) { - /* FIXME bugzilla.eazel.com 1290: Implement redo. */ - /* nautilus_undo_manager_add_redo_transaction (undo_transaction); */ - } else { - /* Purge transaction */ - Nautilus_Undo_Transaction_unref (undo_transaction, &ev); - } - - /* Fire off signal informing that an undo transaction has occurred */ - gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); - - CORBA_exception_free (&ev); -} - -#if 0 -static void -nautilus_undo_manager_redo (NautilusUndoManager *manager) -{ - GList *list; - CORBA_Object redo_transaction; - CORBA_Object undo_transaction; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - /* Are we allowing redo operations? */ - if (manager->details->enable_redo) { - g_warning ("NautilusUndoManager is not configure to allow redo operations."); - return; - } - - /* Verify we have a transaction to be redone */ - if (manager->details->redo_list == NULL) { - g_warning ("NautilusUndoManager has no transaction to be redone."); - return; - } - - /* Pop last transaction off redo list */ - list = g_list_last (manager->details->redo_list); - g_assert(list); - redo_transaction = list->data; - - Nautilus_Undo_Transaction_undo (redo_transaction, &ev); - - /* Place transaction into undo list */ - undo_transaction = bonobo_object_corba_objref (BONOBO_OBJECT (redo_transaction)); - nautilus_undo_manager_add_transaction (manager, undo_transaction); - - CORBA_exception_free (&ev); -} -#endif - -static void -nautilus_undo_manager_add_transaction (NautilusUndoManager *manager, - Nautilus_Undo_Transaction transaction) -{ - int length; - Nautilus_Undo_Transaction duplicate_transaction; CORBA_Environment ev; + Nautilus_Undo_Transaction transaction; g_return_if_fail (NAUTILUS_IS_UNDO_MANAGER (manager)); - g_return_if_fail (transaction != CORBA_OBJECT_NIL); - - CORBA_exception_init (&ev); - - /* Check and see if we are over our queue limit */ - length = g_list_length (manager->details->undo_list); - if (length >= manager->details->queue_depth) { - manager->details->undo_list = prune_undo_manager_list - (manager->details->undo_list, - (length - manager->details->queue_depth) + 1); - } - - /* Perform refs on the transaction */ - duplicate_transaction = CORBA_Object_duplicate (transaction, &ev); - Nautilus_Undo_Transaction_ref (duplicate_transaction, &ev); - /* Add transaction to undo list */ - manager->details->undo_list = g_list_append (manager->details->undo_list, duplicate_transaction); - - /* Fire off signal informing that an undo transaction has occurred */ - gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); - - CORBA_exception_free (&ev); -} - - -static void -nautilus_undo_manager_forget_transaction (NautilusUndoManager *manager, - Nautilus_Undo_Transaction transaction) -{ - GList *list; - int index, length; - CORBA_Environment ev; - gboolean success; - - CORBA_exception_init (&ev); - - success = FALSE; - - /* Check undo list */ - length = g_list_length (manager->details->undo_list); - for (index = 0; index < length; index++) { - list = g_list_nth (manager->details->undo_list, index); - if (list) { - transaction = list->data; - manager->details->undo_list = - g_list_remove (manager->details->undo_list, transaction); - Nautilus_Undo_Transaction_unref (transaction, &ev); - success = TRUE; - index--; - } - } + CORBA_exception_init (&ev); - /* Check redo list */ - length = g_list_length (manager->details->redo_list); - for (index = 0; index < length; index++) { - list = g_list_nth (manager->details->redo_list, index); - if (list) { - transaction = list->data; - manager->details->redo_list = - g_list_remove (manager->details->redo_list, transaction); - Nautilus_Undo_Transaction_unref (transaction, &ev); - success = TRUE; - index--; - } - } + transaction = manager->details->transaction; + manager->details->transaction = CORBA_OBJECT_NIL; + if (!CORBA_Object_is_nil (transaction, &ev)) { + /* Perform the undo. New transactions that come in + * during an undo are redo transactions. New + * transactions that come in during a redo are undo + * transactions. Transactions that come in outside + * are always undo and never redo. + */ + manager->details->new_transaction_is_redo = + !manager->details->current_transaction_is_redo; + manager->details->undo_in_progress = TRUE; + manager->details->num_transactions_during_undo = 0; + Nautilus_Undo_Transaction_undo (transaction, &ev); + manager->details->undo_in_progress = TRUE; + manager->details->new_transaction_is_redo = FALSE; + + /* Let go of the transaction. */ + Nautilus_Undo_Transaction_unref (transaction, &ev); + CORBA_Object_release (transaction, &ev); - if (success) { - /* Fire off signal informing that a transaction has occurred */ + /* Fire off signal indicating the undo state has changed. */ gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); } - - CORBA_exception_free (&ev); -} - -#if 0 -gboolean -nautilus_undo_manager_can_undo (NautilusUndoManager *manager) -{ - return manager != NULL - && manager->details->undo_list != NULL; -} - -gboolean -nautilus_undo_manager_can_redo (NautilusUndoManager *manager) -{ - return manager != NULL - && manager->details->enable_redo - && manager->details->redo_list != NULL; + CORBA_exception_free (&ev); } -#endif - static void destroy (GtkObject *object) { NautilusUndoManager *manager; manager = NAUTILUS_UNDO_MANAGER (object); - - /* Clear lists */ - free_undo_manager_list (manager->details->undo_list); - free_undo_manager_list (manager->details->redo_list); - - NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); -} - -#if 0 - -/* nautilus_undo_manager_enable_redo - * - * Enable or disable redo functionality - */ -void -nautilus_undo_manager_enable_redo (NautilusUndoManager *manager, gboolean value) -{ - g_return_if_fail (NAUTILUS_IS_UNDO_MANAGER (manager)); - g_return_if_fail (value == FALSE || value == TRUE); - - manager->details->enable_redo = value; - - /* Flush and free redo queue */ - free_undo_manager_list (manager->details->redo_list); - manager->details->redo_list = NULL; -} -void -nautilus_undo_manager_set_queue_depth (NautilusUndoManager *manager, int depth) -{ - int length; + release_transaction (manager); - g_return_if_fail (NAUTILUS_IS_UNDO_MANAGER (manager)); - g_return_if_fail (depth > 0); - - manager->details->queue_depth = depth; - - /* Prune lists */ - length = g_list_length (manager->details->undo_list); - if (length > depth) { - manager->details->undo_list = prune_undo_manager_list (manager->details->undo_list, - length - depth); - } - length = g_list_length (manager->details->redo_list); - if (length > depth) { - manager->details->undo_list = prune_undo_manager_list (manager->details->redo_list, - length - depth); - } - - /* Fire off signal informing that an undo transaction has occurred */ - gtk_signal_emit (GTK_OBJECT (manager), signals[CHANGED]); -} - -#endif - -/* free_undo_manager_list - * - * Clear undo data from list - */ -static void -free_undo_manager_list (GList *list) -{ - GList *p; - Nautilus_Undo_Transaction transaction; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - for (p = list; p != NULL; p = p->next) { - transaction = p->data; - - Nautilus_Undo_Transaction_unref (transaction, &ev); - } - CORBA_exception_free (&ev); - - g_list_free (list); -} - - -/* prune_undo_manager_list - * - * Prune n items from start of list - */ -static GList * -prune_undo_manager_list (GList *list, int items) -{ - int i; - Nautilus_Undo_Transaction transaction; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - for (i = 0; i < items; i++) { - if (list != NULL) { - transaction = list->data; - list = g_list_remove (list, transaction); - Nautilus_Undo_Transaction_unref (transaction, &ev); - } - } - CORBA_exception_free (&ev); - - return list; + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); } void @@ -545,11 +361,16 @@ update_undo_menu_item (NautilusUndoManager *manager, CORBA_exception_init (&ev); - if (manager->details->undo_list == NULL) { + if (CORBA_Object_is_nil (manager->details->transaction, &ev)) { menu_item = NULL; } else { - menu_item = Nautilus_Undo_Transaction__get_undo_menu_item - (g_list_last (manager->details->undo_list)->data, &ev); + if (manager->details->current_transaction_is_redo) { + menu_item = Nautilus_Undo_Transaction__get_redo_menu_item + (manager->details->transaction, &ev); + } else { + menu_item = Nautilus_Undo_Transaction__get_undo_menu_item + (manager->details->transaction, &ev); + } } bonobo_ui_handler_menu_set_sensitivity |