object.py :  » Project-Management » Task-Coach » TaskCoach-1.0.3 » taskcoachlib » domain » base » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Project Management » Task Coach 
Task Coach » TaskCoach 1.0.3 » taskcoachlib » domain » base » object.py
# -*- coding: utf-8 -*-

'''
Task Coach - Your friendly task manager
Copyright (C) 2004-2010 Frank Niessink <frank@niessink.com>
Copyright (C) 2008 Jrme Laheurte <fraca7@free.fr>

Task Coach is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Task Coach is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

import time
from taskcoachlib import patterns
import attribute
from taskcoachlib.domain.attribute import icon


class SynchronizedObject(object):
    STATUS_NONE    = 0
    STATUS_NEW     = 1
    STATUS_CHANGED = 2
    STATUS_DELETED = 3

    def __init__(self, *args, **kwargs):
        self.__status = kwargs.pop('status', self.STATUS_NEW)
        super(SynchronizedObject, self).__init__(*args, **kwargs)

    @classmethod
    def markDeletedEventType(class_):
        return 'object.markdeleted'

    @classmethod
    def markNotDeletedEventType(class_):
        return 'object.marknotdeleted'
        
    def __getstate__(self):
        try:
            state = super(SynchronizedObject, self).__getstate__()
        except AttributeError:
            state = dict()

        state['status'] = self.__status
        return state

    def __setstate__(self, state, event=None):
        notify = event is None
        event = event or patterns.Event()
        try:
            super(SynchronizedObject, self).__setstate__(state, event)
        except AttributeError:
            pass
        if state['status'] != self.__status:
            if state['status'] == self.STATUS_CHANGED:
                self.markDirty(event=event)
            elif state['status'] == self.STATUS_DELETED:
                self.markDeleted(event)
            elif state['status'] == self.STATUS_NEW:
                self.markNew(event)
            elif state['status'] == self.STATUS_NONE:
                self.cleanDirty(event)
        if notify:
            event.send()

    def getStatus(self):
        return self.__status
        
    def markDirty(self, force=False, event=None):
        if not self.setStatusDirty(force):
            return
        notify = event is None
        event = event or patterns.Event()
        event.addSource(self, self.__status, 
                        type=self.markNotDeletedEventType())
        if notify:
            event.send()

    def setStatusDirty(self, force=False):
        oldStatus = self.__status
        if self.__status == self.STATUS_NONE or force:
            self.__status = self.STATUS_CHANGED
            return oldStatus == self.STATUS_DELETED
        else:
            return False

    def markNew(self, event=None):
        if not self.setStatusNew():
            return
        notify = event is None
        event = event or patterns.Event()
        event.addSource(self, self.__status,
                        type=self.markNotDeletedEventType())
        if notify:
            event.send()
            
    def setStatusNew(self):
        oldStatus = self.__status
        self.__status = self.STATUS_NEW
        return oldStatus == self.STATUS_DELETED

    def markDeleted(self, event=None):
        notify = event is None
        event = event or patterns.Event()
        self.setStatusDeleted()
        event.addSource(self, self.__status, type=self.markDeletedEventType())
        if notify:
            event.send()

    def setStatusDeleted(self):
        self.__status = self.STATUS_DELETED

    def cleanDirty(self, event=None):
        if not self.setStatusNone():
            return
        notify = event is None
        event = event or patterns.Event()
        event.addSource(self, self.__status, 
                        type=self.markNotDeletedEventType())
        if notify:
            event.send()
            
    def setStatusNone(self):
        oldStatus = self.__status
        self.__status = self.STATUS_NONE
        return oldStatus == self.STATUS_DELETED

    def isNew(self):
        return self.__status == self.STATUS_NEW

    def isModified(self):
        return self.__status == self.STATUS_CHANGED

    def isDeleted(self):
        return self.__status == self.STATUS_DELETED

        
class Object(SynchronizedObject):
    def __init__(self, *args, **kwargs):
        self.__subject = attribute.Attribute(kwargs.pop('subject', ''), self, 
                                             self.subjectChangedEvent)
        self.__description = attribute.Attribute(kwargs.pop('description', ''), 
                                                 self,
                                                 self.descriptionChangedEvent)
        self.__fgColor = attribute.Attribute(kwargs.pop('fgColor', None), self, 
                                             self.foregroundColorChangedEvent)
        self.__bgColor = attribute.Attribute(kwargs.pop('bgColor', None), self,
                                             self.backgroundColorChangedEvent)
        self.__font = attribute.Attribute(kwargs.pop('font', None), self,
                                          self.fontChangedEvent)
        self.__icon = attribute.Attribute(kwargs.pop('icon', ''), self,
                                          self.iconChangedEvent)
        self.__selectedIcon = attribute.Attribute(kwargs.pop('selectedIcon', ''), self,
                                                  self.selectedIconChangedEvent)
        self.__id = kwargs.pop('id', None) or '%s:%s'%(id(self), time.time())
        # FIXME: Not a valid XML id
        # FIXME: When dropping support for python 2.4, use the uuid module
        super(Object, self).__init__(*args, **kwargs)
        
    def __repr__(self):
        return self.subject()

    def __getstate__(self):
        try:
            state = super(Object, self).__getstate__()
        except AttributeError:
            state = dict()
        state.update(dict(id=self.__id, subject=self.__subject.get(), 
                          description=self.__description.get(),
                          fgColor=self.__fgColor.get(),
                          bgColor=self.__bgColor.get(),
                          font=self.__font.get(),
                          icon=self.__icon.get(),
                          selectedIcon=self.__selectedIcon.get()))
        return state
    
    def __setstate__(self, state, event=None):
        notify = event is None
        event = event or patterns.Event()
        try:
            super(Object, self).__setstate__(state, event)
        except AttributeError:
            pass
        self.setId(state['id'])
        self.setSubject(state['subject'], event)
        self.setDescription(state['description'], event)
        self.setForegroundColor(state['fgColor'], event)
        self.setBackgroundColor(state['bgColor'], event)
        self.setFont(state['font'], event)
        self.setIcon(state['icon'], event)
        self.setSelectedIcon(state['selectedIcon'], event)
        if notify:
            event.send()

    def __getcopystate__(self):
        ''' Return a dictionary that can be passed to __init__ when creating
            a copy of the object. 
            
            E.g. copy = obj.__class__(**original.__getcopystate__()) '''
        try:
            state = super(Object, self).__getcopystate__()
        except AttributeError:
            state = dict()
        # Note: we don't put the id in the state dict, because a copy should
        # get a new id:
        state.update(dict(\
            subject=self.__subject.get(), description=self.__description.get(),
            fgColor=self.__fgColor.get(), bgColor=self.__bgColor.get(),
            font=self.__font.get(), icon=self.__icon.get(),
            selectedIcon=self.__selectedIcon.get()))
        return state
    
    def copy(self):
        return self.__class__(**self.__getcopystate__())
 
    # Id:
       
    def id(self):
        return self.__id
    
    def setId(self, id_):
        self.__id = id_
        
    # Subject:
    
    def subject(self):
        return self.__subject.get()
    
    def setSubject(self, subject, event=None):
        self.__subject.set(subject, event)
        
    def subjectChangedEvent(self, event):
        event.addSource(self, self.subject(), type=self.subjectChangedEventType())
    
    @classmethod    
    def subjectChangedEventType(class_):
        return '%s.subject'%class_
    
    # Description:
    
    def description(self):
        return self.__description.get()
    
    def setDescription(self, description, event=None):
        self.__description.set(description, event)
        
    def descriptionChangedEvent(self, event):
        event.addSource(self, self.description(), 
                        type=self.descriptionChangedEventType())
            
    @classmethod    
    def descriptionChangedEventType(class_):
        return '%s.description'%class_
    
    # Color:
    
    def setForegroundColor(self, color, event=None):
        self.__fgColor.set(color, event)
    
    def foregroundColor(self, recursive=False): # pylint: disable-msg=W0613
        # The 'recursive' argument isn't actually used here, but some
        # code assumes composite objects where there aren't. This is
        # the simplest workaround.
        return self.__fgColor.get()

    def foregroundColorChangedEvent(self, event):
        event.addSource(self, self.foregroundColor(), 
                        type=self.foregroundColorChangedEventType())

    @classmethod
    def foregroundColorChangedEventType(class_):
        return '%s.fgColor'%class_
    
    def setBackgroundColor(self, color, event=None):
        self.__bgColor.set(color, event)
        
    def backgroundColor(self, recursive=False): # pylint: disable-msg=W0613
        # The 'recursive' argument isn't actually used here, but some
        # code assumes composite objects where there aren't. This is
        # the simplest workaround.
        return self.__bgColor.get()

    def backgroundColorChangedEvent(self, event):
        event.addSource(self, self.backgroundColor(), 
                        type=self.backgroundColorChangedEventType())

    @classmethod
    def backgroundColorChangedEventType(class_):
        return '%s.bgColor'%class_
    
    # Font:
    
    def font(self, recursive=False): # pylint: disable-msg=W0613
        # The 'recursive' argument isn't actually used here, but some
        # code assumes composite objects where there aren't. This is
        # the simplest workaround.
        return self.__font.get()
    
    def setFont(self, font, event=None):
        self.__font.set(font, event)
        
    def fontChangedEvent(self, event):
        event.addSource(self, self.font(), type=self.fontChangedEventType())

    @classmethod    
    def fontChangedEventType(class_):
        return '%s.font'%class_

    # Icons:

    def icon(self):
        return self.__icon.get()

    def setIcon(self, icon, event=None):
        self.__icon.set(icon, event)

    def iconChangedEvent(self, event):
        event.addSource(self, self.icon(), type=self.iconChangedEventType())

    @classmethod
    def iconChangedEventType(class_):
        return '%s.icon'%class_

    def selectedIcon(self):
        return self.__selectedIcon.get()

    def setSelectedIcon(self, icon, event=None):
        self.__selectedIcon.set(icon, event)

    def selectedIconChangedEvent(self, event):
        event.addSource(self, self.selectedIcon(),
                        type=self.selectedIconChangedEventType())

    @classmethod
    def selectedIconChangedEventType(class_):
        return '%s.selectedIcon'%class_
    
    # Event types:
    
    @classmethod
    def modificationEventTypes(class_):
        try:
            eventTypes = super(Object, class_).modificationEventTypes()
        except AttributeError:
            eventTypes = []
        return eventTypes + [class_.subjectChangedEventType(),
                             class_.descriptionChangedEventType(),
                             class_.foregroundColorChangedEventType(),
                             class_.backgroundColorChangedEventType(),
                             class_.fontChangedEventType(),
                             class_.iconChangedEventType(),
                             class_.selectedIconChangedEventType()]


class CompositeObject(Object, patterns.ObservableComposite):
    def __init__(self, *args, **kwargs):
        self.__expandedContexts = set()
        for context in kwargs.pop('expandedContexts', []):
            self.__expandedContexts.add(context)
        super(CompositeObject, self).__init__(*args, **kwargs)

    def __getcopystate__(self):
        state = super(CompositeObject, self).__getcopystate__()
        state.update(dict(expandedContexts=self.expandedContexts()))
        return state

    # Subject:
    
    def subject(self, recursive=False): # pylint: disable-msg=W0221
        subject = super(CompositeObject, self).subject()
        if recursive and self.parent():
            subject = u'%s -> %s'%(self.parent().subject(recursive=True), subject)
        return subject
        
    # Description:
        
    def description(self, recursive=False): # pylint: disable-msg=W0221,W0613
        # Allow for the recursive flag, but ignore it
        return super(CompositeObject, self).description()
        
    # Expansion state:

    # Note: expansion state is stored by context. A context is a simple string
    # identifier (without comma's) to distinguish between different contexts,
    # i.e. viewers. A composite object may be expanded in one context and
    # collapsed in another.
    
    def isExpanded(self, context='None'):
        ''' Returns a boolean indicating whether the composite object is 
            expanded in the specified context. ''' 
        return context in self.__expandedContexts

    def expandedContexts(self):
        ''' Returns a list of contexts where this composite object is 
            expanded. ''' 
        return list(self.__expandedContexts)
    
    def expand(self, expand=True, context='None', event=None):
        ''' Expands (or collapses) the composite object in the specified 
            context. ''' 
        if expand == self.isExpanded(context):
            return
        notify = event is None
        event = event or patterns.Event()
        if expand:
            self.__expandedContexts.add(context)
        else:
            self.__expandedContexts.discard(context)
        self.expansionChangedEvent(event)
        if notify:
            event.send()

    @classmethod
    def expansionChangedEventType(class_):
        return '%s.expanded'%class_

    def expansionChangedEvent(self, event):
        event.addSource(self, type=self.expansionChangedEventType())
    
    # Color:

    def foregroundColor(self, recursive=True):
        myFgColor = super(CompositeObject, self).foregroundColor()
        if not myFgColor and recursive and self.parent():
            return self.parent().foregroundColor(recursive=True)
        else:
            return myFgColor

    def foregroundColorChangedEvent(self, event):
        super(CompositeObject, self).foregroundColorChangedEvent(event)
        children = self.childrenWithoutOwnForegroundColor()
        fgColor = self.foregroundColor(recursive=False)
        for child in children:
            event.addSource(child, fgColor, type=child.foregroundColorChangedEventType())

    def childrenWithoutOwnForegroundColor(self, parent=None):
        parent = parent or self
        children = []
        for child in parent.children():
            if child.foregroundColor(recursive=False) is None:
                children.extend([child] + self.childrenWithoutOwnForegroundColor(child))
        return children
        
    def backgroundColor(self, recursive=True):
        myBgColor = super(CompositeObject, self).backgroundColor()
        if not myBgColor and recursive and self.parent():
            return self.parent().backgroundColor(recursive=True)
        else:
            return myBgColor
                
    def backgroundColorChangedEvent(self, event):
        super(CompositeObject, self).backgroundColorChangedEvent(event)
        children = self.childrenWithoutOwnBackgroundColor()
        bgColor = self.backgroundColor(recursive=False)
        for child in children:
            event.addSource(child, bgColor, type=child.backgroundColorChangedEventType())

    def childrenWithoutOwnBackgroundColor(self, parent=None):
        parent = parent or self
        children = []
        for child in parent.children():
            if child.backgroundColor(recursive=False) is None:
                children.extend([child] + self.childrenWithoutOwnBackgroundColor(child))
        return children
    
    # Font:
    
    def font(self, recursive=False):
        myFont = super(CompositeObject, self).font()
        if not myFont and recursive and self.parent():
            return self.parent().font(recursive=True)
        else:
            return myFont

    def fontChangedEvent(self, event):
        super(CompositeObject, self).fontChangedEvent(event)
        children = self.childrenWithoutOwnFont()
        font = self.font(recursive=False)
        for child in children:
            event.addSource(child, font, type=child.fontChangedEventType())
            
    def childrenWithoutOwnFont(self, parent=None):
        parent = parent or self
        children = []
        for child in parent.children():
            if child.font(recursive=False) is None:
                children.extend([child] + self.childrenWithoutOwnFont(child))
        return children

    # Icon:

    def icon(self, recursive=False):
        myIcon = super(CompositeObject, self).icon()
        if not recursive:
            return myIcon
        if not myIcon and self.parent():
            myIcon = self.parent().icon(recursive=True)
        return self.pluralOrSingularIcon(myIcon)

    def iconChangedEvent(self, event):
        super(CompositeObject, self).iconChangedEvent(event)
        children = self.childrenWithoutOwnIcon()
        icon = self.icon(recursive=False)
        for child in children:
            event.addSource(child, icon, type=child.iconChangedEventType())

    def childrenWithoutOwnIcon(self, parent=None):
        parent = parent or self
        children = []
        for child in parent.children():
            if not child.icon(recursive=False):
                children.extend([child] + self.childrenWithoutOwnIcon(child))
        return children

    def selectedIcon(self, recursive=False):
        myIcon = super(CompositeObject, self).selectedIcon()
        if not recursive:
            return myIcon
        if not myIcon and self.parent():
            myIcon = self.parent().selectedIcon(recursive=True)
        return self.pluralOrSingularIcon(myIcon)

    def selectedIconChangedEvent(self, event):
        super(CompositeObject, self).selectedIconChangedEvent(event)
        children = self.childrenWithoutOwnSelectedIcon()
        icon = self.selectedIcon(recursive=False)
        for child in children:
            event.addSource(child, icon, type=child.selectedIconChangedEventType())

    def childrenWithoutOwnSelectedIcon(self, parent=None):
        parent = parent or self
        children = []
        for child in parent.children():
            if not child.selectedIcon(recursive=False):
                children.extend([child] + self.childrenWithoutOwnSelectedIcon(child))
        return children

    def pluralOrSingularIcon(self, myIcon):
        hasChildren = any(child for child in self.children() if not child.isDeleted())
        mapping = icon.itemImagePlural if hasChildren else icon.itemImageSingular
        return mapping.get(myIcon, myIcon)
    
    # Event types:

    @classmethod
    def modificationEventTypes(class_):
        return super(CompositeObject, class_).modificationEventTypes() + \
            [class_.expansionChangedEventType()]

    # Override SynchronizedObject methods to also mark child objects

    def markDeleted(self, event=None):
        notify = event is None
        event = event or patterns.Event()
        super(CompositeObject, self).markDeleted(event)
        for child in self.children():
            child.markDeleted(event)
        if notify:
            event.send()
            
    def markNew(self, event=None):
        notify = event is None
        event = event or patterns.Event()
        super(CompositeObject, self).markNew(event)
        for child in self.children():
            child.markNew(event)
        if notify:
            event.send()

    def markDirty(self, force=False, event=None):
        notify = event is None
        event = event or patterns.Event()
        super(CompositeObject, self).markDirty(force, event)
        for child in self.children():
            child.markDirty(force, event)
        if notify:
            event.send()
            
    def cleanDirty(self, event=None):
        notify = event is None
        event = event or patterns.Event()
        super(CompositeObject, self).cleanDirty(event)
        for child in self.children():
            child.cleanDirty(event)
        if notify:
            event.send()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.