Changeset 2074

Show
Ignore:
Timestamp:
09/01/07 13:43:29 (1 year ago)
Author:
arj..@yirdis.nl
Message:

Fixed signal emission from umlproperties, do undo manager can deal with them.
Be more strict in emitting events.
Also extended test cases.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gaphor/trunk/gaphor/UML/properties.py

    r2067 r2074  
    176176            return 
    177177 
    178         #undoattributeaction(self, obj, self._get(obj)) 
    179178        if value == self.default: 
    180179            delattr(obj, self._name) 
     
    187186        old = self._get(obj) 
    188187        try: 
    189             #undoattributeaction(self, obj, self._get(obj)) 
    190188            delattr(obj, self._name) 
    191189        except AttributeError: 
     
    194192            component.handle(AttributeChangeEvent(obj, self, old, self.default)) 
    195193            self.notify(obj) 
    196  
    197  
    198 #class undosetassociationaction(undoaction): 
    199 #    """ 
    200 #    Undo a 'set' action in an association. 
    201 #    """ 
    202 # 
    203 #    def undo(self): 
    204 #        #log.debug('undosetassociationaction del: %s %s %s' % (self.obj, self.prop.name, self.value)) 
    205 #        self.prop._del(self.obj, self.value) 
    206 #        return self.redo 
    207 # 
    208 #    def redo(self): 
    209 #        #log.debug('undosetassociationaction set: %s %s %s' % (self.obj, self.prop.name, self.value)) 
    210 #        self.prop._set(self.obj, self.value) 
    211 ##        return self.undo 
    212  
    213  
    214 #class undodelassociationaction(undoaction): 
    215 #    """Undo a 'del' action in an association. 
    216 #    """ 
    217 # 
    218 #    def undo(self): 
    219 #        #log.debug('undodelassociationaction set: %s %s %s' % (self.obj, self.prop.name, self.value)) 
    220 #        self.prop._set(self.obj, self.value) 
    221 #        return self.redo 
    222 # 
    223 #    def redo(self): 
    224 #        #log.debug('undodelassociationaction del: %s %s %s' % (self.obj, self.prop.name, self.value)) 
    225 #        self.prop._del(self.obj, self.value) 
    226 #        return self.undo 
    227194 
    228195 
     
    300267        This method is called from the opposite association property. 
    301268        """ 
    302         #print '__set__', self, obj, value 
     269        #print '__set__', self, obj, value, self._get(obj) 
    303270        if not (isinstance(value, self.type) or \ 
    304271                (value is None and self.upper == 1)): 
     
    309276 
    310277            # do nothing if we are assigned our current value: 
     278            # Still do your thing, since undo handlers expect that. 
    311279            if value is old: 
    312280                return 
    313281 
    314282            if old: 
    315                 if not from_opposite and self.opposite: 
    316                     getattr(type(old), self.opposite)._del(old, obj, from_opposite=True) 
    317                 old.disconnect(self.__on_unlink, obj) 
    318                 if self.composite: 
    319                     obj.disconnect(self.__on_composite_unlink, old) 
    320  
    321             if value is None: 
    322                 return 
    323  
    324             setattr(obj, self._name, value) 
     283                self._del(obj, old, from_opposite=from_opposite, do_notify=False) 
     284 
    325285            if do_notify: 
    326286                event = AssociationSetEvent(obj, self, old, value) 
     287 
     288            if value is None: 
     289                if do_notify: 
     290                    self.notify(obj) 
     291                    component.handle(event) 
     292                return 
     293 
     294            setattr(obj, self._name, value) 
     295 
    327296        else: 
    328297            # Set the actual value 
     
    351320            component.handle(event) 
    352321 
    353     def _del(self, obj, value, from_opposite=False): 
     322    def _del(self, obj, value, from_opposite=False, do_notify=True): 
    354323        """ 
    355324        Delete is used for element deletion and for removal of 
     
    368337            getattr(type(value), self.opposite)._del(value, obj, from_opposite=True) 
    369338 
     339        event = None 
    370340        if self.upper > 1: 
    371341            c = self._get(obj) 
     
    377347                    pass 
    378348                else: 
    379                     component.handle(AssociationDeleteEvent(obj, self, value)) 
     349                    if do_notify: 
     350                        event = AssociationDeleteEvent(obj, self, value) 
    380351 
    381352                # Remove items collection if empty 
     
    388359                pass 
    389360            else: 
    390                 component.handle(AssociationSetEvent(obj, self, value, None)) 
     361                if do_notify: 
     362                    event = AssociationSetEvent(obj, self, value, None) 
    391363 
    392364        value.disconnect(self.__on_unlink, obj) 
    393365        if self.composite: 
    394366            obj.disconnect(self.__on_composite_unlink, value) 
    395         self.notify(obj) 
     367        if do_notify and event: 
     368            self.notify(obj) 
     369            component.handle(event) 
    396370 
    397371    def __on_unlink(self, value, pspec, obj): 
  • gaphor/trunk/gaphor/UML/tests/test_properties.py

    r2067 r2074  
    2222        assert b.two is a 
    2323 
     24        a.one = None 
     25        assert a.one is None 
     26        assert b.two is None 
     27 
     28        a.one = b 
     29        assert a.one is b 
     30        assert b.two is a 
     31 
     32        del a.one 
     33        assert a.one is None 
     34        assert b.two is None 
     35 
     36 
    2437    def test_association_n_x(self): 
    2538        # 
     
    3851        assert b in a.one 
    3952        assert b.two is a 
     53 
    4054 
    4155    def test_association_1_1(self): 
     
    7993        assert len(a._observers.get('__unlink__')) == 0 
    8094        assert len(b._observers.get('__unlink__')) == 0 
     95 
    8196 
    8297    def test_association_1_n(self): 
     
    150165        else: 
    151166            assert 0, 'should not be removed' 
     167 
    152168 
    153169    def test_association_n_n(self): 
  • gaphor/trunk/gaphor/services/tests/test_undomanager.py

    r1859 r2074  
    4343        assert undo_manager._current_transaction is None 
    4444 
     45        undo_manager.shutdown() 
     46 
    4547    def test_not_in_transaction(self): 
    4648        undo_manager = UndoManager() 
     
    5658        assert undo_manager.can_undo() 
    5759        assert len(undo_manager._current_transaction._actions) == 1 
     60 
     61        undo_manager.shutdown() 
    5862 
    5963         
     
    96100        assert undone[0] == -1, undone 
    97101 
     102        undo_manager.shutdown() 
     103 
     104 
    98105    def test_undo_attribute(self): 
    99106        import types 
     
    120127        assert a.attr == 'five' 
    121128 
    122     def test_undo_aassociation_1_x(self): 
     129        undo_manager.shutdown() 
     130 
     131    def test_undo_association_1_x(self): 
    123132        from gaphor.UML.properties import association 
    124133        from gaphor.UML.element import Element 
     
    144153        assert a.one is b 
    145154        assert b.two is a 
     155        assert len(undo_manager._undo_stack) == 1 
     156        assert len(undo_manager._undo_stack[0]._actions) == 2, undo_manager._undo_stack[0]._actions 
    146157 
    147158        undo_manager.undo_transaction() 
    148159        assert a.one is None 
    149160        assert b.two is None 
    150  
    151         undo_manager.redo_transaction() 
     161        assert undo_manager.can_redo() 
     162        assert len(undo_manager._redo_stack) == 1 
     163        assert len(undo_manager._redo_stack[0]._actions) == 2, undo_manager._redo_stack[0]._actions 
     164 
     165        undo_manager.redo_transaction() 
     166        assert len(undo_manager._undo_stack) == 1 
     167        assert len(undo_manager._undo_stack[0]._actions) == 2, undo_manager._undo_stack[0]._actions 
     168        assert b.two is a 
    152169        assert a.one is b 
    153         assert b.two is a 
     170 
     171        undo_manager.shutdown() 
    154172 
    155173    def test_undo_association_1_n(self): 
     
    177195        assert a1 in b1.two 
    178196        assert b1 is a1.one 
     197        assert len(undo_manager._undo_stack) == 1 
     198        assert len(undo_manager._undo_stack[0]._actions) == 2, undo_manager._undo_stack[0]._actions 
    179199 
    180200        undo_manager.undo_transaction() 
    181201        assert len(b1.two) == 0 
    182202        assert a1.one is None 
     203        assert undo_manager.can_redo() 
     204        assert len(undo_manager._redo_stack) == 1 
     205        assert len(undo_manager._redo_stack[0]._actions) == 2, undo_manager._redo_stack[0]._actions 
    183206 
    184207        undo_manager.redo_transaction() 
     
    195218        assert b1 is a2.one 
    196219 
     220        undo_manager.shutdown() 
     221 
     222 
    197223    def test_element_factory_undo(self): 
    198224        from gaphor.UML.elementfactory import ElementFactory 
     
    221247        assert ef.lselect()[0] is p 
    222248         
     249        undo_manager.shutdown() 
     250 
     251 
     252    def test_uml_associations(self): 
     253 
     254        from zope import component 
     255        from gaphor.UML.event import AssociationChangeEvent 
     256        from gaphor.UML.properties import association, derivedunion 
     257        from gaphor.UML import Element 
     258 
     259        class A(Element): 
     260            is_unlinked = False 
     261            def unlink(self): 
     262                self.is_unlinked = True 
     263                Element.unlink(self) 
     264 
     265        A.a1 = association('a1', A, upper=1) 
     266        A.a2 = association('a2', A, upper=1) 
     267        A.b1 = association('b1', A, upper='*') 
     268        A.b2 = association('b2', A, upper='*') 
     269        A.b3 = association('b3', A, upper=1) 
     270 
     271        A.derived_a = derivedunion('derived_a', 0, 1, A.a1, A.a2) 
     272        A.derived_b = derivedunion('derived_b', 0, '*', A.b1, A.b2, A.b3) 
     273 
     274        events = [] 
     275        @component.adapter(AssociationChangeEvent) 
     276        def handler(event, events=events): 
     277            events.append(event) 
     278 
     279        Application.register_handler(handler) 
     280        try: 
     281            a = A() 
     282 
     283            undo_manager = UndoManager() 
     284            undo_manager.init(Application) 
     285            undo_manager.begin_transaction() 
     286 
     287            a.a1 = A() 
     288            undo_manager.commit_transaction() 
     289             
     290            assert len(events) == 2 
     291            assert events[0].property is A.derived_a 
     292            assert events[1].property is A.a1 
     293            assert undo_manager.can_undo() 
     294 
     295            undo_manager.undo_transaction() 
     296            assert not undo_manager.can_undo() 
     297            assert undo_manager.can_redo() 
     298            assert len(events) == 4, len(events) 
     299            assert events[2].property is A.derived_a 
     300            assert events[3].property is A.a1 
     301 
     302        finally: 
     303            Application.unregister_handler(handler) 
     304            undo_manager.shutdown() 
     305 
     306 
    223307# vim:sw=4:et 
  • gaphor/trunk/gaphor/services/undomanager.py

    r1892 r2074  
    208208 
    209209    def discard_transaction(self): 
    210  
    211210        if not self._current_transaction: 
    212211            raise TransactionError, 'No transaction to discard' 
     
    348347        obj = event.element 
    349348        value = event.old_value 
     349        #print 'got new set event', association, obj, value 
    350350        def _undo_association_set_event(): 
    351351            #print 'undoing action', obj, value