Changeset 1219
- Timestamp:
- 04/11/07 23:00:00 (1 year ago)
- Files:
-
- gaphor/trunk/gaphor/UML/elementfactory.py (modified) (4 diffs)
- gaphor/trunk/gaphor/UML/properties.py (modified) (2 diffs)
- gaphor/trunk/gaphor/UML/tests/test_elementfactory.py (modified) (1 diff)
- gaphor/trunk/gaphor/UML/tests/test_properties.py (modified) (1 diff)
- gaphor/trunk/gaphor/__init__.py (modified) (2 diffs)
- gaphor/trunk/gaphor/actions/__init__.py (modified) (1 diff)
- gaphor/trunk/gaphor/actions/diagramactions.py (modified) (3 diffs)
- gaphor/trunk/gaphor/actions/mainactions.py (modified) (3 diffs)
- gaphor/trunk/gaphor/application.py (modified) (6 diffs)
- gaphor/trunk/gaphor/data/plugins/plugineditor/plugineditor.py (modified) (2 diffs)
- gaphor/trunk/gaphor/data/plugins/pynsource/engineer.py (modified) (3 diffs)
- gaphor/trunk/gaphor/diagram/__init__.py (modified) (1 diff)
- gaphor/trunk/gaphor/diagram/comment.py (modified) (2 diffs)
- gaphor/trunk/gaphor/interfaces.py (modified) (1 diff)
- gaphor/trunk/gaphor/services/tests/test_undomanager.py (modified) (6 diffs)
- gaphor/trunk/gaphor/services/undomanager.py (modified) (6 diffs)
- gaphor/trunk/gaphor/storage.py (modified) (2 diffs)
- gaphor/trunk/gaphor/ui/__init__.py (modified) (1 diff)
- gaphor/trunk/gaphor/ui/accelmap.py (added)
- gaphor/trunk/gaphor/ui/mainwindow.py (modified) (2 diffs)
- gaphor/trunk/gaphor/ui/namespace.py (modified) (3 diffs)
- gaphor/trunk/gaphor/undomanager.py (deleted)
- gaphor/trunk/run-gaphor.sh (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gaphor/trunk/gaphor/UML/elementfactory.py
r1173 r1219 6 6 from zope import component 7 7 from gaphor.misc import uniqueid, odict 8 from gaphor.undomanager import get_undo_manager9 8 from gaphor.UML.element import Element 10 9 from gaphor.UML.diagram import Diagram … … 46 45 obj = type(id, self) 47 46 self._elements[id] = obj 48 #get_undo_manager().add_undo_action(_UndoCreateAction(self, obj))49 47 obj.connect('__unlink__', self._element_signal) 50 48 self.notify(obj, 'create') … … 172 170 # TODO: make undo action 173 171 del self._elements[element.id] 174 #get_undo_manager().add_undo_action(_UndoRemoveAction(self, element))175 172 self.notify(element, 'remove') 176 173 component.handle(ElementDeleteEvent(self, element)) … … 183 180 184 181 185 @component.adapter(IElementCreateEvent)186 def undo_create_event(event):187 factory = event.service188 element = event.element189 def _undo_create_event():190 try:191 del factory._elements[element.id]192 except KeyError:193 pass # Key was probably already removed in an unlink call194 factory.notify(element, 'remove')195 component.handle(ElementDeleteEvent(factory, element))196 get_undo_manager().add_undo_action(_undo_create_event)197 198 component.provideHandler(undo_create_event)199 200 201 @component.adapter(IElementDeleteEvent)202 def undo_delete_event(event):203 factory = event.service204 element = event.element205 def _undo_delete_event():206 factory._elements[element.id] = element207 factory.notify(element, 'create')208 component.handle(ElementCreateEvent(factory, element))209 get_undo_manager().add_undo_action(_undo_delete_event)210 211 component.provideHandler(undo_delete_event)212 213 182 214 183 # vim:sw=4:et gaphor/trunk/gaphor/UML/properties.py
r1176 r1219 35 35 from interfaces import IAttributeChangeEvent, IAssociationChangeEvent 36 36 import operator 37 from gaphor.undomanager import get_undo_manager38 37 39 38 … … 587 586 588 587 589 @component.adapter(IAttributeChangeEvent)590 def undo_attribute_change_event(event):591 attribute = event.property592 obj = event.element593 value = event.old_value594 def _undo_attribute_change_event():595 attribute._set(obj, value)596 get_undo_manager().add_undo_action(_undo_attribute_change_event)597 598 component.provideHandler(undo_attribute_change_event)599 600 601 @component.adapter(AssociationSetEvent)602 def undo_association_set_event(event):603 association = event.property604 obj = event.element605 value = event.old_value606 def _undo_association_set_event():607 #print 'undoing action', obj, value608 # Tell the assoctaion it should not need to let the opposite609 # side connect (it has it's own signal)610 association._set(obj, value, from_opposite=True)611 get_undo_manager().add_undo_action(_undo_association_set_event)612 613 component.provideHandler(undo_association_set_event)614 615 616 @component.adapter(AssociationAddEvent)617 def undo_association_add_event(event):618 association = event.property619 obj = event.element620 value = event.new_value621 def _undo_association_add_event():622 #print 'undoing action', obj, value623 # Tell the assoctaion it should not need to let the opposite624 # side connect (it has it's own signal)625 association._del(obj, value, from_opposite=True)626 get_undo_manager().add_undo_action(_undo_association_add_event)627 628 component.provideHandler(undo_association_add_event)629 630 631 @component.adapter(AssociationDeleteEvent)632 def undo_association_delete_event(event):633 association = event.property634 obj = event.element635 value = event.old_value636 def _undo_association_delete_event():637 #print 'undoing action', obj, value638 # Tell the assoctaion it should not need to let the opposite639 # side connect (it has it's own signal)640 association._set(obj, value, from_opposite=True)641 get_undo_manager().add_undo_action(_undo_association_delete_event)642 643 component.provideHandler(undo_association_delete_event)644 645 646 588 try: 647 589 import psyco gaphor/trunk/gaphor/UML/tests/test_elementfactory.py
r1171 r1219 111 111 self.assertTrue(IFlushFactoryEvent.providedBy(last_event) ) 112 112 113 def testUndo(self):114 from gaphor.services.undomanager import get_undo_manager115 get_undo_manager().begin_transaction()116 ef = self.factory117 p = ef.create(Parameter)118 119 assert get_undo_manager().can_undo()120 121 get_undo_manager().commit_transaction()122 assert get_undo_manager().can_undo()123 assert ef.size() == 1124 125 get_undo_manager().undo_transaction()126 assert not get_undo_manager().can_undo()127 assert get_undo_manager().can_redo()128 assert ef.size() == 0129 130 get_undo_manager().redo_transaction()131 assert get_undo_manager().can_undo()132 assert not get_undo_manager().can_redo()133 assert ef.size() == 1134 assert ef.lselect()[0] is p135 136 113 137 114 # vim:sw=4:et gaphor/trunk/gaphor/UML/tests/test_properties.py
r1176 r1219 374 374 assert b.is_unlinked 375 375 376 def test_undo_attribute(self):377 import types378 from gaphor.services.undomanager import get_undo_manager379 undo_manager = get_undo_manager()380 381 class A(Element):382 attr = attribute('attr', types.StringType, default='default')383 384 a = A()385 assert a.attr == 'default', a.attr386 undo_manager.begin_transaction()387 a.attr = 'five'388 389 undo_manager.commit_transaction()390 assert a.attr == 'five'391 392 undo_manager.undo_transaction()393 assert a.attr == 'default', a.attr394 395 undo_manager.redo_transaction()396 assert a.attr == 'five'397 398 def test_undo_aassociation_1_x(self):399 from gaphor.services.undomanager import get_undo_manager400 undo_manager = get_undo_manager()401 402 class A(Element): pass403 class B(Element): pass404 405 A.one = association('one', B, 0, 1, opposite='two')406 B.two = association('two', A, 0, 1)407 408 a = A()409 b = B()410 411 assert a.one is None412 assert b.two is None413 414 undo_manager.begin_transaction()415 a.one = b416 417 undo_manager.commit_transaction()418 assert a.one is b419 assert b.two is a420 421 undo_manager.undo_transaction()422 assert a.one is None423 assert b.two is None424 425 undo_manager.redo_transaction()426 assert a.one is b427 assert b.two is a428 429 def test_undo_association_1_n(self):430 from gaphor.services.undomanager import get_undo_manager431 undo_manager = get_undo_manager()432 433 class A(Element): pass434 class B(Element): pass435 436 A.one = association('one', B, lower=0, upper=1, opposite='two')437 B.two = association('two', A, lower=0, upper='*', opposite='one')438 439 a1 = A()440 a2 = A()441 b1 = B()442 b2 = B()443 444 445 undo_manager.begin_transaction()446 b1.two = a1447 448 undo_manager.commit_transaction()449 assert a1 in b1.two450 assert b1 is a1.one451 452 undo_manager.undo_transaction()453 assert len(b1.two) == 0454 assert a1.one is None455 456 undo_manager.redo_transaction()457 assert a1 in b1.two458 assert b1 is a1.one459 460 undo_manager.begin_transaction()461 b1.two = a2462 463 undo_manager.commit_transaction()464 assert a1 in b1.two465 assert a2 in b1.two466 assert b1 is a1.one467 assert b1 is a2.one468 469 376 470 377 # vim:sw=4:et:ai gaphor/trunk/gaphor/__init__.py
r1200 r1219 42 42 43 43 44 def new_main(gaphor_file=None):44 def main(gaphor_file=None): 45 45 """ 46 Not yet used. see main() below. 46 Start the main application by initiating and running 47 gaphor.application.Application. 47 48 """ 49 import pkg_resources 50 51 resource('DataDir', os.path.join(pkg_resources.get_distribution('gaphor').location, 'gaphor', 'data')) 52 48 53 from gaphor.application import Application 49 54 Application.init() 50 55 51 # backwards compatible 52 main_window = resource("MainWindow", Application.main_window) 53 56 main_window = resource('MainWindow') 54 57 if gaphor_file: 55 58 main_window.set_filename(gaphor_file) … … 61 64 62 65 63 def main(gaphor_file=None):64 """65 Start the interactive application.66 67 This involves importing plugins and creating the main window.68 """69 import pkg_resources70 71 resource('Version', pkg_resources.get_distribution('gaphor').version)72 resource('DataDir', os.path.join(pkg_resources.get_distribution('gaphor').location, 'gaphor', 'data'))73 74 # Import GUI stuff here, since the user might not need all the GUI stuff75 import gtk76 import ui77 import adapters78 import actions79 # Load plugin definitions:80 import services.pluginmanager81 import services.undomanager82 83 from ui.mainwindow import MainWindow84 85 resource('PluginManager').init(None)86 87 ui.load_accel_map()88 89 # should we set a default icon here or something?90 main_window = resource(MainWindow)91 main_window.construct()92 93 # When the state changes to CLOSED, quit the application94 main_window.connect(lambda win: win.get_state() == MainWindow.STATE_CLOSED and gtk.main_quit())95 96 if gaphor_file:97 main_window.set_filename(gaphor_file)98 main_window.execute_action('FileRevert')99 else:100 main_window.execute_action('FileNew')101 102 gtk.main()103 #gtk.threads_leave()104 105 resource.save()106 107 ui.save_accel_map()108 109 log.info('Bye!')110 111 112 66 # TODO: Remove this 113 67 import __builtin__ gaphor/trunk/gaphor/actions/__init__.py
r1121 r1219 2 2 Actions are used by the user interface to execute user events. 3 3 """ 4 5 import diagramactions6 import editoractions7 import mainactions8 9 import itemactions10 import placementactionsgaphor/trunk/gaphor/actions/diagramactions.py
r1170 r1219 9 9 from gaphor import resource 10 10 from gaphor import UML 11 from gaphor. undomanager import get_undo_manager, transactional11 from gaphor.transaction import Transaction, transactional 12 12 from gaphor.misc.action import Action, CheckAction, RadioAction 13 13 from gaphor.misc.action import register_action as _register_action … … 145 145 146 146 if view.is_focus(): 147 get_undo_manager().begin_transaction()147 tx = Transaction() 148 148 try: 149 149 items = view.selected_items … … 154 154 i.unlink() 155 155 finally: 156 get_undo_manager().commit_transaction()156 tx.commit() 157 157 158 158 def may_remove_from_model(self, view): gaphor/trunk/gaphor/actions/mainactions.py
r1190 r1219 8 8 import gtk 9 9 import gc 10 from threading import Thread 11 10 from gaphor.application import Application 12 11 from gaphor import resource 13 12 from gaphor import UML 14 13 from gaphor import diagram 15 from gaphor.undomanager import get_undo_manager16 14 from gaphor.misc.action import Action, CheckAction, RadioAction, register_action 17 15 from gaphor.misc.action import DynamicMenu, ObjectAction, register_slot … … 23 21 24 22 DEFAULT_EXT='.gaphor' 23 24 def get_undo_manager(): 25 return Application.get_service('undo_manager') 25 26 26 27 def show_status_window(title, message, parent=None, queue=None): … … 391 392 def execute(self): 392 393 logo = gtk.gdk.pixbuf_new_from_file (resource('DataDir') + '/pixmaps/logo.png') 393 version = resource('Version')394 version = Application.distribution.version 394 395 about = gtk.Dialog("About Gaphor", self._window.get_window(), gtk.DIALOG_MODAL, (gtk.STOCK_OK, gtk.RESPONSE_OK)) 395 396 about.set_default_response(gtk.RESPONSE_OK) gaphor/trunk/gaphor/application.py
r1188 r1219 15 15 from gaphor.interfaces import IService 16 16 17 import gaphor.ui 18 from gaphor.ui import mainwindow, load_accel_map, save_accel_map 17 import gaphor.UML 18 19 # Backwards compat 20 from gaphor import resource 19 21 20 22 class _Application(object): … … 24 26 def __init__(self): 25 27 self.services = { 26 'main_window': mainwindow.MainWindow(),27 28 'element_factory': gaphor.UML.ElementFactory() 28 29 } 29 30 30 def __getattr__(self, key):31 return self.services[key]31 # def __getattr__(self, key): 32 # return self.services[key] 32 33 33 34 def init(self): … … 35 36 Initialize the application. 36 37 """ 37 load_accel_map() 38 import gaphor.adapters 39 import gaphor.actions 38 #import gaphor.adapters 39 #import gaphor.actions 40 40 self.load_services() 41 self.main_window.construct()42 main_window.connect(lambda win: win.get_state() == MainWindow.STATE_CLOSED and gtk.main_quit())43 41 44 42 def load_services(self): … … 49 47 Service should provide an interface gaphor.interfaces.IService. 50 48 """ 49 services = [] 51 50 for ep in pkg_resources.iter_entry_points('gaphor.services'): 52 51 #print ep, dir(ep) … … 56 55 raise 'MisConfigurationException', 'Entry point %s doesn''t provide IService' % ep.name 57 56 srv = cls() 57 services.append((ep.name, srv)) 58 59 for name, srv in services: 60 log.debug('initializing service.%s' % name) 58 61 srv.init(self) 59 print 'service', srv 60 component.provideUtility(srv, IService, ep.name) 62 component.provideUtility(srv, IService, name) 63 64 distribution = property(lambda s: pkg_resources.get_distribution('gaphor'), 65 doc='Get the PkgResources distribution for Gaphor') 61 66 62 67 def get_service(self, name): 63 component.getUtility(IService, name)68 return component.getUtility(IService, name) 64 69 65 70 def run(self): … … 67 72 68 73 def shutdown(self): 69 save_accel_map()74 pass # for each IService: shutdown 70 75 71 76 # Make sure there is only one! gaphor/trunk/gaphor/data/plugins/plugineditor/plugineditor.py
r399 r1219 8 8 import pango 9 9 import gtk 10 from zope import component 10 11 import gaphor 12 from gaphor.interfaces import IService 11 13 from gaphor.ui.abstractwindow import AbstractWindow 12 14 from gaphor.plugin import resource … … 85 87 86 88 def update(self): 87 manager = resource('PluginManager')89 manager = component.getUtility(IService, 'plugin_manager') 88 90 model = self.model 89 91 gaphor/trunk/gaphor/data/plugins/pynsource/engineer.py
r543 r1219 35 35 36 36 try: 37 self._root_package = UML. select(lambda e: isinstance(e, UML.Package) and not e.namespace)[0]37 self._root_package = UML.lselect(lambda e: isinstance(e, UML.Package) and not e.namespace)[0] 38 38 except IndexError: 39 39 pass # running as test? … … 91 91 except KeyError, e: 92 92 print 'No class found named', superclassname 93 others = UML. select(lambda e: isinstance(e, UML.Class) and e.name == superclassname)93 others = UML.lselect(lambda e: isinstance(e, UML.Class) and e.name == superclassname) 94 94 if others: 95 95 superclass = others[0] … … 127 127 except KeyError, e: 128 128 print 'No class found named', classname 129 others = UML. select(lambda e: isinstance(e, UML.Class) and e.name == classname)129 others = UML.lselect(lambda e: isinstance(e, UML.Class) and e.name == classname) 130 130 if others: 131 131 superclass = others[0] gaphor/trunk/gaphor/diagram/__init__.py
r1193 r1219 90 90 91 91 92 ##93 ## Direct revert-statements from gaphas to the undomanager94 ###95 96 from gaphas import state97 from gaphor.undomanager import get_undo_manager, transactional98 99 state.observers.add(state.revert_handler)100 101 def _undo_handler(event):102 get_undo_manager().add_undo_action(lambda: state.saveapply(*event));103 104 state.subscribers.add(_undo_handler)105 106 92 # vim:sw=4:et gaphor/trunk/gaphor/diagram/comment.py
r1201 r1219 33 33 34 34 def on_subject_notify(self, pspec): 35 """See DiagramItem.on_subject_notify().""" 35 """ 36 See DiagramItem.on_subject_notify(). 37 """ 36 38 ElementItem.on_subject_notify(self, pspec, ('body',)) 37 39 … … 41 43 42 44 def on_subject_notify__body(self, subject, pspec): 43 print 'on_subject_notify__body: %s' % self.subject.body44 45 #self.sbody.set_text(self.subject.body or '') 45 46 self.request_update() gaphor/trunk/gaphor/interfaces.py
r1201 r1219 15 15 Initialize the service, this method is called after all services 16 16 are instantiated. 17 """ 18 19 def shutdown(self): 20 """ 21 Shutdown the services, free resources. 17 22 """ 18 23 gaphor/trunk/gaphor/services/tests/test_undomanager.py
r1171 r1219 5 5 import unittest 6 6 from gaphor.services.undomanager import UndoManager 7 from gaphor.transaction import Transaction 8 7 9 8 10 class TestUndoManager(unittest.TestCase): … … 11 13 12 14 undo_manager = UndoManager() 15 undo_manager.init(None) 16 13 17 assert undo_manager._transaction_depth == 0 14 18 assert not undo_manager._current_transaction 15 19 16 undo_manager.begin_transaction() 20 #undo_manager.begin_transaction() 21 tx = Transaction() 22 17 23 assert undo_manager._transaction_depth == 1 18 24 assert undo_manager._current_transaction 19 25 20 26 current = undo_manager._current_transaction 21 undo_manager.begin_transaction() 22 assert undo_manager._transaction_depth == 2 23 assert undo_manager._current_transaction is current 24 25 undo_manager.commit_transaction() 27 #undo_manager.begin_transaction() 28 tx2 = Transaction() 29 #assert undo_manager._transaction_depth == 2 26 30 assert undo_manager._transaction_depth == 1 27 31 assert undo_manager._current_transaction is current 28 32 29 undo_manager.commit_transaction() 33 #undo_manager.commit_transaction() 34 tx2.commit() 35 36 assert undo_manager._transaction_depth == 1 37 assert undo_manager._current_transaction is current 38 39 #undo_manager.commit_transaction() 40 tx.commit() 30 41 assert undo_manager._transaction_depth == 0 31 42 assert undo_manager._current_transaction is None … … 33 44 def test_not_in_transaction(self): 34 45 undo_manager = UndoManager() 46 undo_manager.init(None) 35 47 36 48 action = object() … … 58 70 59 71 undo_manager = UndoManager() 60 61 undo_manager.begin_transaction() 72 undo_manager.init(None) 73 74 #undo_manager.begin_transaction() 75 tx = Transaction() 62 76 undo_manager.add_undo_action(undo_action) 63 77 assert undo_manager._current_transaction … … 65 79 assert len(undo_manager._current_transaction._actions) == 1 66 80 67 undo_manager.commit_transaction() 81 #undo_manager.commit_transaction() 82 tx.commit() 68 83 69 84 undo_manager.undo_transaction() … … 80 95 assert undone[0] == -1, undone 81 96 82 97 def test_undo_attribute(self): 98 import types 99 from gaphor.UML.properties import attribute 100 from gaphor.UML.element import Element 101 undo_manager = UndoManager() 102 undo_manager.init(None) 103 104 class A(Element): 105 attr = attribute('attr', types.StringType, default='default') 106 107 a = A() 108 assert a.attr == 'default', a.attr 109 undo_manager.begin_transaction() 110 a.attr = 'five' 111 112 undo_manager.commit_transaction() 113 assert a.attr == 'five' 114 115 undo_manager.undo_transaction() 116 assert a.attr == 'default', a.attr 117 118 undo_manager.redo_transaction() 119 assert a.attr == 'five' 120 121 def test_undo_aassociation_1_x(self): 122 from gaphor.UML.properties import association 123 from gaphor.UML.element import Element 124 undo_manager = UndoManager() 125 undo_manager.init(None) 126 127 class A(Element): pass 128 class B(Element): pass 129 130 A.one = association('one', B, 0, 1, opposite='two') 131 B.two = association('two', A, 0, 1) 132 133 a = A() 134 b = B() 135 136 assert a.one is None 137 assert b.two is None 138 139 undo_manager.begin_transaction() 140 a.one = b 141 142 undo_manager.commit_transaction() 143 assert a.one is b 144 assert b.two is a 145 146 undo_manager.undo_transaction() 147 assert a.one is None 148 assert b.two is None 149 150 undo_manager.redo_transaction() 151 assert a.one is b 152 assert b.two is a 153 154 def test_undo_association_1_n(self): 155 from gaphor.UML.properties import association 156 from gaphor.UML.element import Element 157 undo_manager = UndoManager() 158 undo_manager.init(None) 159 160 class A(Element): pass 161 class B(Element): pass 162 163 A.one = association('one', B, lower=0, upper=1, opposite='two') 164 B.two = association('two', A, lower=0, upper='*', opposite='one') 165 166 a1 = A() 167 a2 = A() 168 b1 = B() 169 b2 = B() 170 171 172 undo_manager.begin_transaction() 173 b1.two = a1 174 175 undo_manager.commit_transaction() 176 assert a1 in b1.two 177 assert b1 is a1.one 178 179 undo_manager.undo_transaction() 180 assert len(b1.two) == 0 181 assert a1.one is None 182 183 undo_manager.redo_transaction() 184 assert a1 in b1.two 185 assert b1 is a1.one 186 187 undo_manager.begin_transaction() 188 b1.two = a2 189 190 undo_manager.commit_transaction() 191 assert a1 in b1.two 192 assert a2 in b1.two 193 assert b1 is a1.one 194 assert b1 is a2.one 195 196 def test_element_factory_undo(self): 197 from gaphor.UML.elementfactory import ElementFactory 198 from gaphor.UML.element import Element 199 undo_manager = UndoManager() 200 undo_manager.init(None) 201 undo_manager.begin_transaction() 202 ef = ElementFactory() 203 p = ef.create(Element) 204 205 assert undo_manager.can_undo() 206 207 undo_manager.commit_transaction() 208 assert undo_manager.can_undo() 209 assert ef.size() == 1 210 211 undo_manager.undo_transaction() 212 assert not undo_manager.can_undo() 213 assert undo_manager.can_redo() 214 assert ef.size() == 0 215 216 undo_manager.redo_transaction() 217 assert undo_manager.can_undo() 218 assert not undo_manager.can_redo() 219 assert ef.size() == 1 220 assert ef.lselect()[0] is p 221 83 222 # vim:sw=4:et gaphor/trunk/gaphor/services/undomanager.py
r1177 r1219 18 18 from zope import component 19 19 from gaphor.interfaces import IService, IServiceEvent 20 21 def get_undo_manager(): 22 """ 23 Return the default undo manager. 24 """ 25 return _default_undo_manager 26 27 28 def transactional(func): 29 """ 30 Descriptor. Begins a transaction around the method/function. 31 32 TODO: In casse of an exception, roll back the transaction if the transaction 33 level == 1. 34 """ 35 def wrapper(*args, **kwargs): 36 undo_manager = get_undo_manager() 37 undo_manager.begin_transaction() 38 try: 39 func(*args, **kwargs) 40 except: 41 undo_manager.rollback_transaction() 42 raise 43 else: 44 undo_manager.commit_transaction() 45 return wrapper 46 47 48 class TransactionError(Exception): 49 50 def __init__(self, msg): 51 self.args = msg 20 from gaphor.event import TransactionBegin, TransactionCommit, TransactionRollback 21 from gaphor.transaction import TransactionError, transactional 22 23 from gaphor.UML.event import ElementCreateEvent, ElementDeleteEvent, \ 24 FlushFactoryEvent, ModelFactoryEvent, \ 25 AttributeChangeEvent, AssociationSetEvent, \ 26 AssociationAddEvent, AssociationDeleteEvent 27 from gaphor.UML.interfaces import IElementCreateEvent, IElementDeleteEvent, \ 28 IAttributeChangeEvent, IAssociationChangeEvent 52 29 53 30 … … 112 89 def init(self, app): 113 90 self._app = app 91 component.provideHandler(self.begin_transaction) 92 component.provideHandler(self.commit_transaction) 93 component.provideHandler(self.rollback_transaction) 94 self._provide_undo_handlers() 95 96 def shutdown(self): 97 pass 114 98 115 99 def clear_undo_stack(self): … … 120 104 del self._redo_stack[:] 121 105 122 def begin_transaction(self): 106 @component.adapter(TransactionBegin) 107 def begin_transaction(self, event=None): 123 108 """ 124 109 Add an action to the current transaction … … 143 128 component.handle(UndoManagerStateChanged(self)) 144 129 145 def commit_transaction(self): 130 @component.adapter(TransactionCommit) 131 def commit_transaction(self, event=None): 146 132 #log.debug('commit_transaction') 147 133 if not self._current_transaction: … … 159 145 component.handle(UndoManagerStateChanged(self)) 160 146 161 def rollback_transaction(self): 147 @component.adapter(TransactionRollback) 148 def rollback_transaction(self, event=None): 162 149 """ 163 150 Roll back the transaction we're in. … … 230 217 return bool(self._redo_stack) 231 218 232 233 from gaphor import resource 234 _default_undo_manager = resource(UndoManager) 235 219 ## 220 ## Undo Handlers 221 ## 222 223 def _provide_undo_handlers(self): 224 component.provideHandler(self.undo_create_event) 225 component.provideHandler(self.undo_delete_event) 226 component.provideHandler(self.undo_attribute_change_event) 227 component.provideHandler(self.undo_association_set_event) 228 component.provideHandler(self.undo_association_add_event) 229 component.provideHandler(self.undo_association_delete_event) 230 231 # 232 # Direct revert-statements from gaphas to the undomanager 233 from gaphas import state 234 state.observers.add(state.revert_handler) 235 236 def _undo_handler(event): 237 self.add_undo_action(lambda: state.saveapply(*event)); 238 239 state.subscribers.add(_undo_handler) 240 241 242 @component.adapter(IElementCreateEvent) 243 def undo_create_event(self, event): 244 factory = event.service 245 element = event.element 246 def _undo_create_event(): 247 try: 248 del factory._elements[element.id] 249 except KeyError: 250 pass # Key was probably already removed in an unlink call 251 factory.notify(element, 'remove') 252 component.handle(ElementDeleteEvent(factory, element)) 253 self.add_undo_action(_undo_create_event) 254 255 256 @component.adapter(IElementDeleteEvent) 257 def undo_delete_event(self, event): 258 factory = event.service 259 element = event.element 260 def _undo_delete_event(): 261 factory._elements[element.id] = element 262 factory.notify(element, 'create') 263 component.handle(ElementCreateEvent(factory, element)) 264 self.add_undo_action(_undo_delete_event) 265 266 267 @component.adapter(IAttributeChangeEvent) 268 def undo_attribute_change_event(self, event): 269 attribute = event.property 270 obj = event.element 271 value = event.old_value 272 def _undo_attribute_change_event(): 273 attribute._set(obj, value) 274 self.add_undo_action(_undo_attribute_change_event) 275 276 277 @component.adapter(AssociationSetEvent) 278 def undo_association_set_event(self, event): 279 association = event.property 280 obj = event.element 281 value = event.old_value 282 def _undo_association_set_event(): 283 #print 'undoing action', obj, value 284 # Tell the assoctaion it should not need to let the opposite 285 # side connect (it has it's own signal) 286 association._set(obj, value, from_opposite=True) 287 self.add_undo_action(_undo_association_set_event) 288 289 290 @component.adapter(AssociationAddEvent) 291 def undo_association_add_event(self, event): 292 association = event.property 293 obj = event.element 294 value = event.new_value 295 def _undo_association_add_event(): 296 #print 'undoing action', obj, value 297 # Tell the assoctaion it should not need to let the opposite 298 # side connect (it has it's own signal) 299 association._del(obj, value, from_opposite=True) 300 self.add_undo_action(_undo_association_add_event) 301 302 303 @component.adapter(AssociationDeleteEvent) 304 def undo_association_delete_event(self, event): 305 association = event.property 306 obj = event.element 307 value = event.old_value 308 def _undo_association_delete_event(): 309 #print 'undoing action', obj, value 310 # Tell the assoctaion it should not need to let the opposite 311 # side connect (it has it's own signal) 312 association._set(obj, value, from_opposite=True) 313 self.add_undo_action(_undo_association_delete_event) 314 315 316 # vim:sw=4:et:ai gaphor/trunk/gaphor/storage.py
r1169 r1219 26 26 from gaphor import parser 27 27 from gaphor import diagram 28 from gaphor.application import Application 28 29 from gaphor.diagram import items 29 30 from gaphor import resource … … 134 135 writer.startDocument() 135 136 writer.startElement('gaphor', { 'version': FILE_FORMAT_VERSION, 136 'gaphor-version': resource('Version')})137 'gaphor-version': Application.distribution.version }) 137 138 138 139 size = factory.size() gaphor/trunk/gaphor/ui/__init__.py
