mscelement.py 8.14 KB
Newer Older
Maxime Perrotin's avatar
Maxime Perrotin committed
1 2 3 4 5 6 7 8
#******************************************************************************
#
# TASTE Msc Diagram Editor
# http://taste.tuxfamily.org/
#
#  This file is part of TASTE Msc Editor.
#
#  TASTE Msc Diagram Editor is free software: you can redistribute it and/or
Maxime Perrotin's avatar
Maxime Perrotin committed
9
#  modify it under the terms of the GNU Lesser General Public License as published
Maxime Perrotin's avatar
Maxime Perrotin committed
10 11 12 13 14 15
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  TASTE Msc Diagram Editor 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
Maxime Perrotin's avatar
Maxime Perrotin committed
16
#  GNU Lesser General Public License for more details.
Maxime Perrotin's avatar
Maxime Perrotin committed
17
#
Maxime Perrotin's avatar
Maxime Perrotin committed
18
#  You should have received a copy of the GNU Lesser General Public License
Maxime Perrotin's avatar
Maxime Perrotin committed
19 20 21 22 23
#  along with TASTE Msc Diagram Editor.  If not, see
#  <http://www.gnu.org/licenses/>.
#
#  Author: Angel Esquinas <aesquina@datsi.fi.upm.es>
#
Maxime Perrotin's avatar
Maxime Perrotin committed
24
#  Copyright (c) 2012 UPM and European Space Agency
Maxime Perrotin's avatar
Maxime Perrotin committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
#
#******************************************************************************
"""
.. This docstring is intended to use with sphinx.

The :class:`msccore.MscElement` class is the base class of almost all msc \
elements. This class is intended to be subclassed.

It is a subclass of :class:`QtCore.QObject`, so it can use \
:class:`QtCore.Signal`. The :class:`msccore.MscElement` declares two \
:class:`~QtCore.Signal`: :attr:`MscElement.dataHasChanged` to notify when \
internal data structures or attributes of elements have been modified, and \
:attr:`~MscElement.nameChanged` to notify when the element's name has been
changed.

The :class:`MscElement` has the attribute :attr:`MscElement.Name` to hold \
the name of the element. To modify the name of the element use the method
:meth:`MscElement.setName` and to read the name of the element use
:meth:`MscElement.name`.
"""
45
from PySide.QtCore import QObject, Signal, QRegExp
Maxime Perrotin's avatar
Maxime Perrotin committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

import mscregexp


class MscElement(QObject):
    '''
    Constructs a :class:`MscElement` with the `name` and the given `parent`.

    :param name: default empty string, Name of the element.
    :type name: unicode
    :param parent: default None
    :type parent: QObject

    '''
    # String to print type of object
    TYPE = 'MscElement'

    # Signal that must be emitted when data of the element has changed.
    # dataChangedSignal = Signal()
    dataHasChanged = Signal()
    """
    :attr:`dataHasChanged` notify when internal properties of the
    :class:`MscElement` instance have changed.

    This signal is emitted within :meth:`dataChanged` method. When 
    :attr:`dataHasChanged` is emitted, :attr:`contentsChanged` should also be
    emitted, because if the internal properties of `MscElement` are modified
    this implies that the contents of the object have also changed.

    .. seealso::
       :attr:`MscElement.contentsChanged`, :meth:`MscElement.dataChanged`
    """

    nameChanged = Signal(unicode)
    """:param unicode: The new name.
       :type unicode: unicode"""

    contentsChanged = Signal()
    u"""
    :attr:`contentsChanged` signal is emitted when changes in the its
    child objects or changes in itself exist.

    When data is changed in an element, because of new objects or other change,
    this signal must be emitted. The difference with :attr:`dataHasChanged`
    signal is that dataHasChanged is only emitted when the data is changed
    in the object itself, not if it's changed in any of its child elements.

    .. seealso::

       :meth:`MscElement.dataChanged`, :attr:`MscElement.dataHasChanged`
    """

    deleted = Signal(QObject)
    u"""
    :attr:`deleted` signal is emitted before the :class:`MscElement` object \
    is deleted.

    This signal is emitted within :meth:`MscElement.delete` method.

    .. seealso::
       :meth:`MscElement.delete`
    """

109 110
    _NameRegExp = None

Maxime Perrotin's avatar
Maxime Perrotin committed
111 112 113 114 115 116
    def __init__(self, name='', parent=None, elemType=TYPE):
        '''
        construct
        '''
        super(MscElement, self).__init__(parent)
        self._name = ''
117 118
        if not self._NameRegExp:
            self._NameRegExp = QRegExp('(' + mscregexp.Name + ')')
Maxime Perrotin's avatar
Maxime Perrotin committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
        self.elemType = elemType
        self.setName(name)
        self._comment = u""

    def setNameRegExp(self, reg=None):
        u"""
        Set :class:`QtCore.QRegExp` `reg` as the validator to allow the change
        of `name` property using :meth:`MscElement.setName`.

        :param reg: default `None`, :class:Pyside.QtCore.RegExp

        """

        self._NameRegExp = reg

    #  Name
    def getName(self):
        return self.name()

    def name(self):
        u'''
        Return the name of the element

        :rtype: unicode
        '''
        return self._name

    def setName(self, name):
        '''
        Set the name of the element.

        :param unicode name: Name of the element.

        Each :class:`MscElement` object should have a different name.
        The `name` property is changed with the `name` content if the
        :data:`msccore.mscregexp.NameRegExpr` property is not set or in case
        it is, the `name` is  partially or fully accepted.

        By default, this property contains an empty string
        '''
        # isCorrect = self.filterName(name)
        if self._NameRegExp.indexIn(name) > -1:
            accepted = self._NameRegExp.cap(1)
            self._name = accepted
            self.nameChanged.emit(self._name)
        self.dataChanged()

    def setExpression(self, expr):
        u"""
        Sets or changes internal properties based on `expr`.

        :param unicode expr: Expression to obtain the data.

        If this function is needed it has to be subclassed.

        *Example:*
           "process <<in>> extern" could be separated into 3 expressions,
           (process, <<in>>, extern) to set class properties.

        By default, this function calls :meth:`MscElement.setName` with `expr`
        as argument.
        """
        return self.setName(expr)

    # Comment
    def setComment(self, comment=u""):
        u"""
        Set the comment of the object.

        :param commment: unicode

        This property holds the comment of the object.

        By default, this property contains an empty string

        .. note:: After the property has changed this method calls \
        :meth:`MscElement.dataChanged` emitting the \
        :attr:`~MscElement.dataHasChanged` Signal.
        """
        self._comment = comment
        self.dataChanged()

    def comment(self):
        u"""
        Return the comment.

        :rtype: unicode

        This property holds the comment of the object.

        By default, this property contains an empty string
        """
        return self._comment

    def dataChanged(self):
        '''
        This function must be called when internal properties of the object
        have changed. It emits both the "dataChanged" signal
        and 'contentsChanged' signal.
        '''
        self.dataHasChanged.emit()
        self.contentsChanged.emit()
        #self.dataChangedSignal.emit()

    def _contentsChanged(self):
        """
        This function must be called when internal properties of the object
        or any of its childs have changed.

        This function can be overriden to add more functionality.
        """
        self.contentsChanged.emit()

    #Delete
    def delete(self):
        u"""
        This method must be overriden. By default only the signal
        :attr:`MscElement.deleted` is emitted.

        This method should be called inside the overriding method to
        emit the :attr:`MscElement.deleted` before
        any operation is done. This allows any other object that has a
        reference to this object know that it will be deleted and remove
        all of its references.
        """
        self.deleted.emit(self)

    def accept(self, visitor):
        u'''
        Implements the visitor pattern.

        :param visitor:
        :type visitor: msccore.MscVisitor

        .. note:: This function must be overriden in a subclass to use the \
        visitor pattern.
        '''
        pass

    # OUTPUT
    def __str__(self):
        return "<<{0}: {1}. Comment {2}>>".format(self.elemType, self._name,
                                                  self.comment())