summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-undo-manager.c
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2000-06-21 00:29:59 +0000
committerDarin Adler <darin@src.gnome.org>2000-06-21 00:29:59 +0000
commitd2822cb5d85d7cb43cd8cea389b522a6f37ae232 (patch)
treee5e68f86934f2ffa29301e2ede3daac4def1a03b /libnautilus-private/nautilus-undo-manager.c
parent81b81f62f4efcfc18f6c271bf64f6e6adfd638dc (diff)
downloadnautilus-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.c501
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