1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* NautilusUndoTransaction - An object for an undoable transaction.
4 * Used internally by undo machinery.
7 * Copyright (C) 2000 Eazel, Inc.
9 * Author: Gene Z. Ragan <gzr@eazel.com>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
28 #include <libnautilus-private/nautilus-undo.h>
29 #include <libnautilus-private/nautilus-undo-manager.h>
30 #include <libnautilus-private/nautilus-undo-transaction.h>
32 #include "nautilus-undo-private.h"
33 #include <gtk/gtksignal.h>
35 #define NAUTILUS_UNDO_TRANSACTION_LIST_DATA "Nautilus undo transaction list"
38 static void undo_atom_list_free (GList
*list
);
39 static void undo_atom_list_undo_and_free (GList
*list
);
41 G_DEFINE_TYPE (NautilusUndoTransaction
, nautilus_undo_transaction
,
45 static Nautilus_Undo_MenuItem
*
46 impl_Nautilus_Undo_Transaction__get_undo_menu_item (PortableServer_Servant servant
,
47 CORBA_Environment
*ev
)
49 NautilusUndoTransaction
*transaction
;
50 Nautilus_Undo_MenuItem
*item
;
52 transaction
= NAUTILUS_UNDO_TRANSACTION (bonobo_object_from_servant (servant
));
54 item
= Nautilus_Undo_MenuItem__alloc ();
55 item
->label
= CORBA_string_dup (transaction
->undo_menu_item_label
);
56 item
->hint
= CORBA_string_dup (transaction
->undo_menu_item_hint
);
61 static Nautilus_Undo_MenuItem
*
62 impl_Nautilus_Undo_Transaction__get_redo_menu_item (PortableServer_Servant servant
,
63 CORBA_Environment
*ev
)
65 NautilusUndoTransaction
*transaction
;
66 Nautilus_Undo_MenuItem
*item
;
68 transaction
= NAUTILUS_UNDO_TRANSACTION (bonobo_object_from_servant (servant
));
70 item
= Nautilus_Undo_MenuItem__alloc ();
71 item
->label
= CORBA_string_dup (transaction
->redo_menu_item_label
);
72 item
->hint
= CORBA_string_dup (transaction
->redo_menu_item_hint
);
78 impl_Nautilus_Undo_Transaction__get_operation_name (PortableServer_Servant servant
,
79 CORBA_Environment
*ev
)
81 NautilusUndoTransaction
*transaction
;
83 transaction
= NAUTILUS_UNDO_TRANSACTION (bonobo_object_from_servant (servant
));
84 return CORBA_string_dup (transaction
->operation_name
);
89 NautilusUndoTransaction
*
90 nautilus_undo_transaction_new (const char *operation_name
,
91 const char *undo_menu_item_label
,
92 const char *undo_menu_item_hint
,
93 const char *redo_menu_item_label
,
94 const char *redo_menu_item_hint
)
96 NautilusUndoTransaction
*transaction
;
98 transaction
= NAUTILUS_UNDO_TRANSACTION (g_object_new (nautilus_undo_transaction_get_type (), NULL
));
100 transaction
->operation_name
= g_strdup (operation_name
);
101 transaction
->undo_menu_item_label
= g_strdup (undo_menu_item_label
);
102 transaction
->undo_menu_item_hint
= g_strdup (undo_menu_item_hint
);
103 transaction
->redo_menu_item_label
= g_strdup (redo_menu_item_label
);
104 transaction
->redo_menu_item_hint
= g_strdup (redo_menu_item_hint
);
110 nautilus_undo_transaction_init (NautilusUndoTransaction
*transaction
)
115 remove_transaction_from_object (gpointer list_data
, gpointer callback_data
)
117 NautilusUndoAtom
*atom
;
118 NautilusUndoTransaction
*transaction
;
121 g_assert (list_data
!= NULL
);
123 transaction
= NAUTILUS_UNDO_TRANSACTION (callback_data
);
125 /* Remove the transaction from the list on the atom. */
126 list
= g_object_get_data (atom
->target
, NAUTILUS_UNDO_TRANSACTION_LIST_DATA
);
129 list
= g_list_remove (list
, transaction
);
130 g_object_set_data (atom
->target
, NAUTILUS_UNDO_TRANSACTION_LIST_DATA
, list
);
135 remove_transaction_from_atom_targets (NautilusUndoTransaction
*transaction
)
138 g_list_foreach (transaction
->atom_list
,
139 remove_transaction_from_object
,
144 nautilus_undo_transaction_finalize (GObject
*object
)
146 NautilusUndoTransaction
*transaction
;
148 transaction
= NAUTILUS_UNDO_TRANSACTION (object
);
150 remove_transaction_from_atom_targets (transaction
);
151 undo_atom_list_free (transaction
->atom_list
);
153 g_free (transaction
->operation_name
);
154 g_free (transaction
->undo_menu_item_label
);
155 g_free (transaction
->undo_menu_item_hint
);
156 g_free (transaction
->redo_menu_item_label
);
157 g_free (transaction
->redo_menu_item_hint
);
159 if (transaction
->owner
!= NULL
) {
160 g_object_unref (transaction
->owner
);
163 G_OBJECT_CLASS (nautilus_undo_transaction_parent_class
)->finalize (object
);
167 nautilus_undo_transaction_add_atom (NautilusUndoTransaction
*transaction
,
168 const NautilusUndoAtom
*atom
)
172 g_return_if_fail (NAUTILUS_IS_UNDO_TRANSACTION (transaction
));
173 g_return_if_fail (atom
!= NULL
);
174 g_return_if_fail (GTK_IS_OBJECT (atom
->target
));
176 /* Add the atom to the atom list in the transaction. */
177 transaction
->atom_list
= g_list_append
178 (transaction
->atom_list
, g_memdup (atom
, sizeof (*atom
)));
180 /* Add the transaction to the list on the atoms target object. */
181 list
= g_object_get_data (atom
->target
, NAUTILUS_UNDO_TRANSACTION_LIST_DATA
);
182 if (g_list_find (list
, transaction
) != NULL
) {
186 /* If it's not already on that atom, this object is new. */
187 list
= g_list_prepend (list
, transaction
);
188 g_object_set_data (atom
->target
, NAUTILUS_UNDO_TRANSACTION_LIST_DATA
, list
);
190 /* Connect a signal handler to the atom so it will unregister
191 * itself when it's destroyed.
193 g_signal_connect (atom
->target
, "destroy",
194 G_CALLBACK (nautilus_undo_transaction_unregister_object
),
199 nautilus_undo_transaction_undo (NautilusUndoTransaction
*transaction
)
201 g_return_if_fail (NAUTILUS_IS_UNDO_TRANSACTION (transaction
));
203 remove_transaction_from_atom_targets (transaction
);
204 undo_atom_list_undo_and_free (transaction
->atom_list
);
206 transaction
->atom_list
= NULL
;
210 nautilus_undo_transaction_add_to_undo_manager (NautilusUndoTransaction
*transaction
,
211 NautilusUndoManager
*manager
)
213 g_return_if_fail (NAUTILUS_IS_UNDO_TRANSACTION (transaction
));
214 g_return_if_fail (transaction
->owner
== NULL
);
216 if (manager
!= NULL
) {
217 nautilus_undo_manager_append (manager
, transaction
);
218 transaction
->owner
= g_object_ref (manager
);
223 remove_atoms (NautilusUndoTransaction
*transaction
,
227 NautilusUndoAtom
*atom
;
229 g_assert (NAUTILUS_IS_UNDO_TRANSACTION (transaction
));
230 g_assert (G_IS_OBJECT (object
));
232 /* Destroy any atoms for this object. */
233 for (p
= transaction
->atom_list
; p
!= NULL
; p
= next
) {
237 if (atom
->target
== object
) {
238 transaction
->atom_list
= g_list_remove_link
239 (transaction
->atom_list
, p
);
240 undo_atom_list_free (p
);
244 /* If all the atoms are gone, forget this transaction.
245 * This may end up freeing the transaction.
247 if (transaction
->atom_list
== NULL
) {
248 nautilus_undo_manager_forget (
249 transaction
->owner
, transaction
);
254 remove_atoms_cover (gpointer list_data
, gpointer callback_data
)
256 if (NAUTILUS_IS_UNDO_TRANSACTION (list_data
)) {
257 remove_atoms (NAUTILUS_UNDO_TRANSACTION (list_data
), G_OBJECT (callback_data
));
262 nautilus_undo_transaction_unregister_object (GObject
*object
)
266 g_return_if_fail (G_IS_OBJECT (object
));
268 /* Remove atoms from each transaction on the list. */
269 list
= g_object_get_data (object
, NAUTILUS_UNDO_TRANSACTION_LIST_DATA
);
271 g_list_foreach (list
, remove_atoms_cover
, object
);
273 g_object_set_data (object
, NAUTILUS_UNDO_TRANSACTION_LIST_DATA
, NULL
);
278 undo_atom_free (NautilusUndoAtom
*atom
)
280 /* Call the destroy-notify function if it's present. */
281 if (atom
->callback_data_destroy_notify
!= NULL
) {
282 (* atom
->callback_data_destroy_notify
) (atom
->callback_data
);
285 /* Free the atom storage. */
290 undo_atom_undo_and_free (NautilusUndoAtom
*atom
)
292 /* Call the function that does the actual undo. */
293 (* atom
->callback
) (atom
->target
, atom
->callback_data
);
295 /* Get rid of the atom now that it's spent. */
296 undo_atom_free (atom
);
300 undo_atom_free_cover (gpointer atom
, gpointer callback_data
)
302 g_assert (atom
!= NULL
);
303 g_assert (callback_data
== NULL
);
304 undo_atom_free (atom
);
308 undo_atom_undo_and_free_cover (gpointer atom
, gpointer callback_data
)
310 g_assert (atom
!= NULL
);
311 g_assert (callback_data
== NULL
);
312 undo_atom_undo_and_free (atom
);
316 undo_atom_list_free (GList
*list
)
318 g_list_foreach (list
, undo_atom_free_cover
, NULL
);
323 undo_atom_list_undo_and_free (GList
*list
)
325 g_list_foreach (list
, undo_atom_undo_and_free_cover
, NULL
);
330 nautilus_undo_transaction_class_init (NautilusUndoTransactionClass
*klass
)
332 G_OBJECT_CLASS (klass
)->finalize
= nautilus_undo_transaction_finalize
;