Code

OCAL. Fix for Bug #638844 (Errors printed to console if openclipart search fails).
[inkscape.git] / src / event-log.cpp
1 /*
2  * Author:
3  *   Gustav Broberg <broberg@kth.se>
4  *
5  * Copyright (c) 2006, 2007 Authors
6  *
7  * Released under GNU GPL, read the file 'COPYING' for more information
8  */
10 #include <glibmm/i18n.h>
12 #include "desktop.h"
13 #include "event-log.h"
14 #include "inkscape.h"
15 #include "util/ucompose.hpp"
16 #include "document.h"
17 #include "xml/repr.h"
18 #include "sp-object.h"
20 namespace Inkscape {
22 EventLog::EventLog(SPDocument* document) :
23     UndoStackObserver(),
24     _connected (false),
25     _document (document),
26     _event_list_store (Gtk::TreeStore::create(_columns)),
27     _event_list_selection (NULL),
28     _event_list_view (NULL),
29     _curr_event_parent (NULL),
30     _notifications_blocked (false),
31     _callback_connections (NULL)
32 {
33     // add initial pseudo event
34     Gtk::TreeRow curr_row = *(_event_list_store->append());
35     _curr_event = _last_saved = _last_event = curr_row;
36     
37     curr_row[_columns.description] = _("[Unchanged]");
38     curr_row[_columns.type] = SP_VERB_FILE_NEW;
39 }
41 EventLog::~EventLog() { }
43 void
44 EventLog::notifyUndoEvent(Event* log) 
45 {
46     if ( !_notifications_blocked ) {
47     
48         // make sure the supplied event matches the next undoable event
49         g_return_if_fail ( _getUndoEvent() && (*(_getUndoEvent()))[_columns.event] == log );
51         // if we're on the first child event...
52         if ( _curr_event->parent() &&
53              _curr_event == _curr_event->parent()->children().begin() )
54         {
55             // ...back up to the parent
56             _curr_event = _curr_event->parent();
57             _curr_event_parent = (iterator)NULL;
59         } else {
61             // if we're about to leave a branch, collapse it
62             if ( !_curr_event->children().empty() && _connected ) {
63                 (*_callback_connections)[CALLB_COLLAPSE].block();
64                 _event_list_view->collapse_row(_event_list_store->get_path(_curr_event));
65                 (*_callback_connections)[CALLB_COLLAPSE].block(false);
66             }
68             --_curr_event;
70             // if we're entering a branch, move to the end of it
71             if (!_curr_event->children().empty()) {
72                 _curr_event_parent = _curr_event;
73                 _curr_event = _curr_event->children().end();
74                 --_curr_event;
75             }
76         }
78         checkForVirginity();
80         // update the view
81         if (_connected) {
82             (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
83             (*_callback_connections)[CALLB_EXPAND].block();
85             Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
86             _event_list_view->expand_to_path(curr_path);
87             _event_list_selection->select(curr_path);
88             _event_list_view->scroll_to_row(curr_path);
90             (*_callback_connections)[CALLB_EXPAND].block(false);
91             (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
92         }
94         updateUndoVerbs();
95     }
97 }
99 void
100 EventLog::notifyRedoEvent(Event* log)
102     if ( !_notifications_blocked ) {
104         // make sure the supplied event matches the next redoable event
105         g_return_if_fail ( _getRedoEvent() && (*(_getRedoEvent()))[_columns.event] == log );
107         // if we're on a parent event...
108         if ( !_curr_event->children().empty() ) {
110             // ...move to its first child
111             _curr_event_parent = _curr_event;
112             _curr_event = _curr_event->children().begin();
114         } else {
115         
116             ++_curr_event;
118             // if we are about to leave a branch...
119             if ( _curr_event->parent() &&
120                  _curr_event == _curr_event->parent()->children().end() )
121             {
123                 // ...collapse it
124                 if (_connected) {
125                     (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
126                     (*_callback_connections)[CALLB_COLLAPSE].block();
127                     _event_list_view->collapse_row(_event_list_store->get_path(_curr_event->parent()));
128                     (*_callback_connections)[CALLB_COLLAPSE].block(false);
129                     (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
130                 }
132                 // ...and move to the next event at parent level
133                 _curr_event = _curr_event->parent();
134                 _curr_event_parent = (iterator)NULL;
136                 ++_curr_event;
137             }
138         }
140         checkForVirginity();
142         // update the view
143         if (_connected) {
144             Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
146             (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
147             (*_callback_connections)[CALLB_EXPAND].block();
149             _event_list_view->expand_to_path(curr_path);
150             _event_list_selection->select(curr_path);
151             _event_list_view->scroll_to_row(curr_path);
153             (*_callback_connections)[CALLB_EXPAND].block(false);
154             (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
155         }
157         updateUndoVerbs();
158     }
162 void 
163 EventLog::notifyUndoCommitEvent(Event* log)
165     _clearRedo();
167     const unsigned int event_type = log->type;
169     Gtk::TreeRow curr_row;
171     // if the new event is of the same type as the previous then create a new branch
172     if ( event_type == (*_curr_event)[_columns.type] ) {
173         if ( !_curr_event_parent ) {
174             _curr_event_parent = _curr_event;
175         }
176         curr_row = *(_event_list_store->append(_curr_event_parent->children()));
177         (*_curr_event_parent)[_columns.child_count] = _curr_event_parent->children().size() + 1;
178     } else {
179         curr_row = *(_event_list_store->append());
180         curr_row[_columns.child_count] = 1;
182         _curr_event = _last_event = curr_row;
184         // collapse if we're leaving a branch
185         if (_curr_event_parent && _connected) {
186             (*_callback_connections)[CALLB_COLLAPSE].block();
187             _event_list_view->collapse_row(_event_list_store->get_path(_curr_event_parent));
188             (*_callback_connections)[CALLB_COLLAPSE].block(false);
189         }
191         _curr_event_parent = (iterator)(NULL);
192     }      
194     _curr_event = _last_event = curr_row;
196     curr_row[_columns.event] = log;
197     curr_row[_columns.type] = event_type;
198     curr_row[_columns.description] = log->description;
200     checkForVirginity();
202     // update the view
203     if (_connected) {
204         Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
206         (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
207         (*_callback_connections)[CALLB_EXPAND].block();
209         _event_list_view->expand_to_path(curr_path);
210         _event_list_selection->select(curr_path);
211         _event_list_view->scroll_to_row(curr_path);
213         (*_callback_connections)[CALLB_EXPAND].block(false);
214         (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
215     }
217     updateUndoVerbs();
220 void
221 EventLog::notifyClearUndoEvent()
223     _clearUndo();    
224     updateUndoVerbs();
227 void
228 EventLog::notifyClearRedoEvent()
230     _clearRedo();
231     updateUndoVerbs();
234 void 
235 EventLog::connectWithDialog(Gtk::TreeView *event_list_view, CallbackMap *callback_connections)
237     _event_list_view = event_list_view;
238     _event_list_selection = event_list_view->get_selection();
239     _event_list_selection->set_mode(Gtk::SELECTION_SINGLE);
241     _callback_connections = callback_connections;
243     (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
244     (*_callback_connections)[CALLB_EXPAND].block();
246     _event_list_view->expand_to_path(_event_list_store->get_path(_curr_event));
247     _event_list_selection->select(_curr_event);
249     (*_callback_connections)[CALLB_EXPAND].block(false);
250     (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
252     _connected = true;
255 void
256 EventLog::updateUndoVerbs()
258     if(_document) {
260         if(_getUndoEvent()) { 
261             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->sensitive(_document, true);
263             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->name(_document, String::ucompose("%1: %2", 
264                       Glib::ustring(_("_Undo")),
265                       Glib::ustring((*_getUndoEvent())[_columns.description])));
266         } else {
267             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->name(_document, _("_Undo"));
268             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->sensitive(_document, false);
269         }
271         if(_getRedoEvent()) {
272             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->sensitive(_document, true);
273             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->name(_document, String::ucompose("%1: %2", 
274                       Glib::ustring(_("_Redo")),
275                       Glib::ustring((*_getRedoEvent())[_columns.description])));
277         } else {
278             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->name(_document, _("_Redo"));
279             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->sensitive(_document, false);
280         }
282     }
287 EventLog::const_iterator
288 EventLog::_getUndoEvent() const
290     const_iterator undo_event = (const_iterator)NULL;
291     if( _curr_event != _event_list_store->children().begin() )
292         undo_event = _curr_event;
293     return undo_event;
296 EventLog::const_iterator
297 EventLog::_getRedoEvent() const
299     const_iterator redo_event = (const_iterator)NULL;
301     if ( _curr_event != _last_event ) {
303         if ( !_curr_event->children().empty() )
304             redo_event = _curr_event->children().begin();
305         else  {
306             redo_event = _curr_event;
307             ++redo_event;
309             if ( redo_event->parent() &&
310                  redo_event == redo_event->parent()->children().end() ) {
312                 redo_event = redo_event->parent();
313                 ++redo_event;
315             }
316         }
318     }
320     return redo_event;
323 void
324 EventLog::_clearUndo()
326     // TODO: Implement when needed
329 void
330 EventLog::_clearRedo()
332     if ( _last_event != _curr_event ) {
334         _last_event = _curr_event;
336         if ( !_last_event->children().empty() ) {
337             _last_event = _last_event->children().begin();
338         } else {
339             ++_last_event;
340         }
342         while ( _last_event != _event_list_store->children().end() ) {
344             if (_last_event->parent()) {
345                 while ( _last_event != _last_event->parent()->children().end() ) {
346                     _last_event = _event_list_store->erase(_last_event);
347                 }
348                 _last_event = _last_event->parent();
350                 (*_last_event)[_columns.child_count] = _last_event->children().size() + 1;
352                 ++_last_event;
353             } else {
354                 _last_event = _event_list_store->erase(_last_event);
355             }
357         }
359     }
362 /* mark document as untouched if we reach a state where the document was previously saved */
363 void
364 EventLog::checkForVirginity() {
365     g_return_if_fail (_document);
366     if (_curr_event == _last_saved) {
367         _document->setModifiedSinceSave(false);
368     }
371 } // namespace Inkscape
374 /*
375   Local Variables:
376   mode:c++
377   c-file-style:"stroustrup"
378   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
379   indent-tabs-mode:nil
380   fill-column:99
381   End:
382 */
383 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :