2 Copyright (C) 2001 Brett Viren & Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <pbd/xml++.h>
27 #include <pbd/shiva.h>
29 #include <sigc++/bind.h>
34 UndoTransaction::UndoTransaction ()
37 gettimeofday (&_timestamp
, 0);
40 UndoTransaction::UndoTransaction (const UndoTransaction
& rhs
)
45 actions
.insert(actions
.end(),rhs
.actions
.begin(),rhs
.actions
.end());
48 UndoTransaction::~UndoTransaction ()
55 command_death (UndoTransaction
* ut
, Command
* c
)
61 ut
->remove_command (c
);
69 UndoTransaction::operator= (const UndoTransaction
& rhs
)
71 if (this == &rhs
) return *this;
74 actions
.insert(actions
.end(),rhs
.actions
.begin(),rhs
.actions
.end());
79 UndoTransaction::add_command (Command
*const action
)
82 new PBD::ProxyShiva
<Command
,UndoTransaction
> (*action
, *this, &command_death
);
83 actions
.push_back (action
);
87 UndoTransaction::remove_command (Command
* const action
)
89 actions
.remove (action
);
93 UndoTransaction::empty () const
95 return actions
.empty();
99 UndoTransaction::clear ()
102 for (list
<Command
*>::iterator i
= actions
.begin(); i
!= actions
.end(); ++i
) {
110 UndoTransaction::operator() ()
112 for (list
<Command
*>::iterator i
= actions
.begin(); i
!= actions
.end(); ++i
) {
118 UndoTransaction::undo ()
120 for (list
<Command
*>::reverse_iterator i
= actions
.rbegin(); i
!= actions
.rend(); ++i
) {
126 UndoTransaction::redo ()
131 XMLNode
&UndoTransaction::get_state()
133 XMLNode
*node
= new XMLNode ("UndoTransaction");
135 ss
<< _timestamp
.tv_sec
;
136 node
->add_property("tv_sec", ss
.str());
138 ss
<< _timestamp
.tv_usec
;
139 node
->add_property("tv_usec", ss
.str());
140 node
->add_property("name", _name
);
142 list
<Command
*>::iterator it
;
143 for (it
=actions
.begin(); it
!=actions
.end(); it
++)
144 node
->add_child_nocopy((*it
)->get_state());
149 UndoHistory::UndoHistory ()
156 UndoHistory::set_depth (int32_t d
)
160 while (_depth
> 0 && UndoList
.size() > (uint32_t) _depth
) {
161 UndoList
.pop_front ();
166 UndoHistory::add (UndoTransaction
* const ut
)
168 ut
->GoingAway
.connect (bind (mem_fun (*this, &UndoHistory::remove
), ut
));
170 while (_depth
> 0 && UndoList
.size() > (uint32_t) _depth
) {
171 UndoList
.pop_front ();
174 UndoList
.push_back (ut
);
176 /* we are now owners of the transaction */
178 Changed (); /* EMIT SIGNAL */
182 UndoHistory::remove (UndoTransaction
* const ut
)
188 UndoList
.remove (ut
);
189 RedoList
.remove (ut
);
191 Changed (); /* EMIT SIGNAL */
195 UndoHistory::undo (unsigned int n
)
198 if (UndoList
.size() == 0) {
201 UndoTransaction
* ut
= UndoList
.back ();
202 UndoList
.pop_back ();
204 RedoList
.push_back (ut
);
207 Changed (); /* EMIT SIGNAL */
211 UndoHistory::redo (unsigned int n
)
214 if (RedoList
.size() == 0) {
217 UndoTransaction
* ut
= RedoList
.back ();
218 RedoList
.pop_back ();
220 UndoList
.push_back (ut
);
223 Changed (); /* EMIT SIGNAL */
227 UndoHistory::clear_redo ()
233 Changed (); /* EMIT SIGNAL */
238 UndoHistory::clear_undo ()
244 Changed (); /* EMIT SIGNAL */
248 UndoHistory::clear ()
253 Changed (); /* EMIT SIGNAL */
257 UndoHistory::get_state (int32_t depth
)
259 XMLNode
*node
= new XMLNode ("UndoHistory");
265 } else if (depth
< 0) {
269 for (list
<UndoTransaction
*>::iterator it
= UndoList
.begin(); it
!= UndoList
.end(); ++it
) {
270 node
->add_child_nocopy((*it
)->get_state());
275 /* just the last "depth" transactions */
277 list
<UndoTransaction
*> in_order
;
279 for (list
<UndoTransaction
*>::reverse_iterator it
= UndoList
.rbegin(); it
!= UndoList
.rend() && depth
; ++it
, depth
--) {
280 in_order
.push_front (*it
);
283 for (list
<UndoTransaction
*>::iterator it
= in_order
.begin(); it
!= in_order
.end(); it
++) {
284 node
->add_child_nocopy((*it
)->get_state());