~ubuntu-branches/debian/squeeze/inkscape/squeeze

« back to all changes in this revision

Viewing changes to src/document-undo.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 *   Lauris Kaplinski <lauris@kaplinski.com>
8
8
 *   MenTaLguY <mental@rydia.net>
9
9
 *
 
10
 * Copyright (C) 2007  MenTaLguY <mental@rydia.net>
10
11
 * Copyright (C) 1999-2003 authors
11
12
 * Copyright (C) 2001-2002 Ximian, Inc.
12
13
 *
22
23
 * stack. Two methods exist to indicate that the given action is completed:
23
24
 *
24
25
 * \verbatim
25
 
   void sp_document_done (SPDocument *document)
 
26
   void sp_document_done (SPDocument *document);
26
27
   void sp_document_maybe_done (SPDocument *document, const unsigned char *key) \endverbatim
27
28
 *
28
29
 * Both move the recent action list into the undo stack and clear the
57
58
#if HAVE_STDLIB_H
58
59
#endif
59
60
 
 
61
#include <string>
 
62
#include <cstring>
60
63
#include "xml/repr.h"
61
64
#include "document-private.h"
62
65
#include "inkscape.h"
63
66
#include "debug/event-tracker.h"
64
67
#include "debug/simple-event.h"
 
68
#include "debug/timestamp.h"
 
69
#include "event.h"
65
70
 
66
71
 
67
72
/*
74
79
 *   Since undo sensitivity needs to be nested, setting undo sensitivity
75
80
 *   should be done like this:
76
81
 *\verbatim
77
 
        gboolean saved = sp_document_get_undo_sensitive(document);
78
 
        sp_document_set_undo_sensitive(document, FALSE);
 
82
        bool saved = sp_document_get_undo_sensitive(document);
 
83
        sp_document_set_undo_sensitive(document, false);
79
84
        ... do stuff ...
80
85
        sp_document_set_undo_sensitive(document, saved);  \endverbatim
81
86
 */
82
87
void
83
 
sp_document_set_undo_sensitive (SPDocument *doc, gboolean sensitive)
 
88
sp_document_set_undo_sensitive (SPDocument *doc, bool sensitive)
84
89
{
85
90
        g_assert (doc != NULL);
86
91
        g_assert (doc->priv != NULL);
87
92
 
88
 
        if ( !(sensitive) == !(doc->priv->sensitive) )
 
93
        if ( sensitive == doc->priv->sensitive )
89
94
                return;
90
95
 
91
96
        if (sensitive) {
97
102
                );
98
103
        }
99
104
 
100
 
        doc->priv->sensitive = !!sensitive;
 
105
        doc->priv->sensitive = sensitive;
101
106
}
102
107
 
103
 
gboolean sp_document_get_undo_sensitive(SPDocument const *document) {
 
108
/*TODO: Throughout the inkscape code tree set/get_undo_sensitive are used for
 
109
 * as is shown above.  Perhaps it makes sense to create new functions,
 
110
 * undo_ignore, and undo_recall to replace the start and end parts of the above.
 
111
 * The main complexity with this is that they have to nest, so you have to store
 
112
 * the saved bools in a stack.  Perhaps this is why the above solution is better.
 
113
 */
 
114
 
 
115
bool sp_document_get_undo_sensitive(SPDocument const *document) {
104
116
        g_assert(document != NULL);
105
117
        g_assert(document->priv != NULL);
106
118
 
108
120
}
109
121
 
110
122
void
111
 
sp_document_done (SPDocument *doc)
112
 
{
113
 
        sp_document_maybe_done (doc, NULL);
114
 
}
115
 
 
116
 
void
117
 
sp_document_reset_key (Inkscape::Application *inkscape, SPDesktop *desktop, GtkObject *base)
118
 
{
119
 
        SPDocument *doc = (SPDocument *) base;
120
 
        doc->actionkey = NULL;
121
 
}
122
 
 
123
 
void
124
 
sp_document_maybe_done (SPDocument *doc, const gchar *key)
 
123
sp_document_done (SPDocument *doc, const unsigned int event_type, Glib::ustring event_description)
 
124
{
 
125
        sp_document_maybe_done (doc, NULL, event_type, event_description);
 
126
}
 
127
 
 
128
void
 
129
sp_document_reset_key (Inkscape::Application */*inkscape*/, SPDesktop */*desktop*/, GtkObject *base)
 
130
{
 
131
    SPDocument *doc = (SPDocument *) base;
 
132
    doc->actionkey = NULL;
 
133
}
 
134
 
 
135
namespace {
 
136
 
 
137
using Inkscape::Debug::Event;
 
138
using Inkscape::Debug::SimpleEvent;
 
139
using Inkscape::Util::share_static_string;
 
140
using Inkscape::Debug::timestamp;
 
141
using Inkscape::Verb;
 
142
 
 
143
typedef SimpleEvent<Event::INTERACTION> InteractionEvent;
 
144
 
 
145
class CommitEvent : public InteractionEvent {
 
146
public:
 
147
 
 
148
    CommitEvent(SPDocument *doc, const gchar *key, const unsigned int type)
 
149
    : InteractionEvent(share_static_string("commit"))
 
150
    {
 
151
        _addProperty(share_static_string("timestamp"), timestamp());
 
152
        gchar *serial = g_strdup_printf("%lu", doc->serial());
 
153
        _addProperty(share_static_string("document"), serial);
 
154
        g_free(serial);
 
155
        Verb *verb = Verb::get(type);
 
156
        if (verb) {
 
157
            _addProperty(share_static_string("context"), verb->get_id());
 
158
        }
 
159
        if (key) {
 
160
            _addProperty(share_static_string("merge-key"), key);
 
161
        }
 
162
    }
 
163
};
 
164
 
 
165
}
 
166
 
 
167
void
 
168
sp_document_maybe_done (SPDocument *doc, const gchar *key, const unsigned int event_type,
 
169
                        Glib::ustring event_description)
125
170
{
126
171
        g_assert (doc != NULL);
127
172
        g_assert (doc->priv != NULL);
128
173
        g_assert (doc->priv->sensitive);
129
174
 
 
175
        Inkscape::Debug::EventTracker<CommitEvent> tracker(doc, key, event_type);
 
176
 
130
177
        doc->collectOrphans();
131
178
 
132
179
        sp_document_ensure_up_to_date (doc);
142
189
        }
143
190
 
144
191
        if (key && doc->actionkey && !strcmp (key, doc->actionkey) && doc->priv->undo) {
145
 
                doc->priv->undo->data = sp_repr_coalesce_log ((Inkscape::XML::Event *)doc->priv->undo->data, log);
 
192
                ((Inkscape::Event *)doc->priv->undo->data)->event =
 
193
                    sp_repr_coalesce_log (((Inkscape::Event *)doc->priv->undo->data)->event, log);
146
194
        } else {
147
 
                doc->priv->undo = g_slist_prepend (doc->priv->undo, log);
 
195
                Inkscape::Event *event = new Inkscape::Event(log, event_type, event_description);
 
196
                doc->priv->undo = g_slist_prepend (doc->priv->undo, event);
148
197
                doc->priv->history_size++;
149
 
                doc->priv->undoStackObservers.notifyUndoCommitEvent(log);
 
198
                doc->priv->undoStackObservers.notifyUndoCommitEvent(event);
150
199
        }
151
200
 
152
201
        doc->actionkey = key;
153
202
 
154
203
        doc->virgin = FALSE;
155
 
        if (!doc->rroot->attribute("sodipodi:modified")) {
156
 
                doc->rroot->setAttribute("sodipodi:modified", "true");
157
 
        }
 
204
        doc->setModifiedSinceSave();
158
205
 
159
206
        sp_repr_begin_transaction (doc->rdoc);
160
207
 
179
226
        sp_repr_begin_transaction (doc->rdoc);
180
227
}
181
228
 
182
 
namespace {
183
 
 
184
 
void finish_incomplete_transaction(SPDocument &doc) {
 
229
static void finish_incomplete_transaction(SPDocument &doc) {
185
230
        SPDocumentPrivate &priv=*doc.priv;
186
231
        Inkscape::XML::Event *log=sp_repr_commit_undoable(doc.rdoc);
187
232
        if (log || priv.partial) {
188
233
                g_warning ("Incomplete undo transaction:");
189
234
                priv.partial = sp_repr_coalesce_log(priv.partial, log);
190
235
                sp_repr_debug_print_log(priv.partial);
191
 
                priv.undo = g_slist_prepend(priv.undo, priv.partial);
 
236
                Inkscape::Event *event = new Inkscape::Event(priv.partial);
 
237
                priv.undo = g_slist_prepend(priv.undo, event);
 
238
                priv.undoStackObservers.notifyUndoCommitEvent(event);
192
239
                priv.partial = NULL;
193
240
        }
194
241
}
195
242
 
196
 
}
197
 
 
198
243
gboolean
199
244
sp_document_undo (SPDocument *doc)
200
245
{
210
255
        g_assert (doc->priv->sensitive);
211
256
 
212
257
        doc->priv->sensitive = FALSE;
 
258
        doc->priv->seeking = true;
213
259
 
214
260
        doc->actionkey = NULL;
215
261
 
216
262
        finish_incomplete_transaction(*doc);
217
263
 
218
264
        if (doc->priv->undo) {
219
 
                Inkscape::XML::Event *log=(Inkscape::XML::Event *)doc->priv->undo->data;
 
265
                Inkscape::Event *log=(Inkscape::Event *)doc->priv->undo->data;
220
266
                doc->priv->undo = g_slist_remove (doc->priv->undo, log);
221
 
                sp_repr_undo_log (log);
 
267
                sp_repr_undo_log (log->event);
222
268
                doc->priv->redo = g_slist_prepend (doc->priv->redo, log);
223
269
 
224
 
                doc->rroot->setAttribute("sodipodi:modified", "true");
225
 
                doc->priv->undoStackObservers.notifyUndoEvent(log);
 
270
                doc->setModifiedSinceSave();
 
271
                doc->priv->undoStackObservers.notifyUndoEvent(log);
226
272
 
227
273
                ret = TRUE;
228
274
        } else {
232
278
        sp_repr_begin_transaction (doc->rdoc);
233
279
 
234
280
        doc->priv->sensitive = TRUE;
 
281
        doc->priv->seeking = false;
235
282
 
236
283
        if (ret)
237
284
                inkscape_external_change();
254
301
        g_assert (doc->priv->sensitive);
255
302
 
256
303
        doc->priv->sensitive = FALSE;
 
304
        doc->priv->seeking = true;
257
305
 
258
306
        doc->actionkey = NULL;
259
307
 
260
308
        finish_incomplete_transaction(*doc);
261
309
 
262
310
        if (doc->priv->redo) {
263
 
                Inkscape::XML::Event *log=(Inkscape::XML::Event *)doc->priv->redo->data;
 
311
                Inkscape::Event *log=(Inkscape::Event *)doc->priv->redo->data;
264
312
                doc->priv->redo = g_slist_remove (doc->priv->redo, log);
265
 
                sp_repr_replay_log (log);
 
313
                sp_repr_replay_log (log->event);
266
314
                doc->priv->undo = g_slist_prepend (doc->priv->undo, log);
267
315
 
268
 
                doc->rroot->setAttribute("sodipodi:modified", "true");
 
316
                doc->setModifiedSinceSave();
269
317
                doc->priv->undoStackObservers.notifyRedoEvent(log);
270
318
 
271
319
                ret = TRUE;
276
324
        sp_repr_begin_transaction (doc->rdoc);
277
325
 
278
326
        doc->priv->sensitive = TRUE;
 
327
        doc->priv->seeking = false;
279
328
 
280
329
        if (ret)
281
330
                inkscape_external_change();
286
335
void
287
336
sp_document_clear_undo (SPDocument *doc)
288
337
{
 
338
        if (doc->priv->undo)
 
339
                doc->priv->undoStackObservers.notifyClearUndoEvent();
 
340
 
289
341
        while (doc->priv->undo) {
290
342
                GSList *current;
291
343
 
293
345
                doc->priv->undo = current->next;
294
346
                doc->priv->history_size--;
295
347
 
296
 
                sp_repr_free_log ((Inkscape::XML::Event *)current->data);
 
348
                delete ((Inkscape::Event *) current->data);
297
349
                g_slist_free_1 (current);
298
350
        }
299
351
}
301
353
void
302
354
sp_document_clear_redo (SPDocument *doc)
303
355
{
 
356
        if (doc->priv->redo)
 
357
                doc->priv->undoStackObservers.notifyClearRedoEvent();
 
358
 
304
359
        while (doc->priv->redo) {
305
360
                GSList *current;
306
361
 
308
363
                doc->priv->redo = current->next;
309
364
                doc->priv->history_size--;
310
365
 
311
 
                sp_repr_free_log ((Inkscape::XML::Event *)current->data);
 
366
                delete ((Inkscape::Event *) current->data);
312
367
                g_slist_free_1 (current);
313
368
        }
314
369
}