Gnumed.timelinelib.canvas.data.immutable

Package Gnumed :: Package timelinelib :: Package canvas :: Package data :: Module immutable |
[frames] | no frames]

# Source Code for Module Gnumed.timelinelib.canvas.data.immutable

      1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg
      2  #
      3  # This file is part of Timeline.
      4  #
      5  # Timeline is free software: you can redistribute it and/or modify
      6  # it under the terms of the GNU General Public License as published by
      7  # the Free Software Foundation, either version 3 of the License, or
      8  # (at your option) any later version.
      9  #
     10  # Timeline is distributed in the hope that it will be useful,
     11  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  # GNU General Public License for more details.
     14  #
     15  # You should have received a copy of the GNU General Public License
     16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>.
     17
     18
     19  from timelinelib.canvas.drawing.drawers import get_progress_color
     20  from timelinelib.general.immutable import Field
     21  from timelinelib.general.immutable import ImmutableDict
     22  from timelinelib.general.immutable import ImmutableRecord
     23
     24
     25 -class ImmutableEvent(ImmutableRecord):
     26
     27      text = Field(None)
     28      time_period = Field(None)
     29      category_id = Field(None)
     30      category_ids = Field(ImmutableDict())
     31      fuzzy = Field(False)
     32      locked = Field(False)
     33      ends_today = Field(False)
     34      description = Field(None)
     35      icon = Field(None)
     36      hyperlink = Field(None)
     37      alert = Field(None)
     38      progress = Field(None)
     39      default_color = Field(None)
     40      container_id = Field(None)
     41      sort_order = Field(None)
     42
     43
     44 -class ImmutableMilestone(ImmutableRecord):
     45
     46      text = Field(None)
     47      category_id = Field(None)
     48      category_ids = Field(ImmutableDict())
     49      time_period = Field(None)
     50      description = Field(None)
     51      default_color = Field((255, 255, 128))
     52      sort_order = Field(None)
     53
     54
     55 -class ImmutableEra(ImmutableRecord):
     56
     57      name = Field(None)
     58      time_period = Field(None)
     59      color = Field((200, 200, 200))
     60      ends_today = Field(False)
     61
     62
     63 -class ImmutableCategory(ImmutableRecord):
     64
     65      name = Field("")
     66      color = Field((255, 0, 0))
     67      progress_color = Field(get_progress_color((255, 0, 0)))
     68      done_color = Field(get_progress_color((255, 0, 0)))
     69      font_color = Field((0, 0, 0))
     70      parent_id = Field(None)
     71
     72
     73 -class ImmutableContainer(ImmutableRecord):
     74
     75      text = Field(None)
     76      category_id = Field(None)
     77      category_ids = Field(ImmutableDict())
     78      time_period = Field(None)
     79      description = Field(None)
     80
     81
     82 -class ImmutableDB(ImmutableRecord):
     83
     84      categories = Field(ImmutableDict())
     85      containers = Field(ImmutableDict())
     86      events = Field(ImmutableDict())
     87      milestones = Field(ImmutableDict())
     88      eras = Field(ImmutableDict())
     89
     90 -    def save_event(self, event, id_):
     91          self._ensure_non_none_category_exists(event.category_id)
     92          self._ensure_non_none_container_exists(event.container_id)
     93          return self.update(
     94              events=self.events.update({
     95                  id_: event,
     96              })
     97          )
     98
     99 -    def delete_event(self, id_):
    100          self._ensure_event_exists(id_)
    101          return self.update(
    102              events=self.events.remove(id_)
    103          )
    104
    105 -    def save_milestone(self, milestone, id_):
    106          self._ensure_non_none_category_exists(milestone.category_id)
    107          return self.update(
    108              milestones=self.milestones.update({
    109                  id_: milestone
    110              })
    111          )
    112
    113 -    def delete_milestone(self, id_):
    114          self._ensure_milestone_exists(id_)
    115          return self.update(
    116              milestones=self.milestones.remove(id_)
    117          )
    118
    119 -    def save_era(self, era, id_):
    120          return self.update(
    121              eras=self.eras.update({
    122                  id_: era,
    123              })
    124          )
    125
    126 -    def delete_era(self, id_):
    127          self._ensure_era_exists(id_)
    128          return self.update(
    129              eras=self.eras.remove(id_)
    130          )
    131
    132 -    def save_category(self, category, id_):
    133          self._ensure_category_name_is_unique(id_, category.name)
    134          self._ensure_non_none_category_exists(category.parent_id)
    135          self._ensure_no_category_circular(id_, category.parent_id)
    136          return self.update(
    137              categories=self.categories.update({id_: category})
    138          )
    139
    140 -    def delete_category(self, delete_id):
    141          self._ensure_category_exists(delete_id)
    142          new_parent_id = self.categories.get(delete_id).parent_id
    143
    144          def update_parent_id(category):
    145              if category.parent_id == delete_id:
    146                  return category.update(parent_id=new_parent_id)
    147              else:
    148                  return category
    149
    150          def update_category_id(thing):
    151              if thing.category_id == delete_id:
    152                  return thing.update(category_id=new_parent_id)
    153              else:
    154                  return thing
    155          return self.update(
    156              categories=self.categories.remove(delete_id).map(update_parent_id),
    157              events=self.events.map(update_category_id),
    158              milestones=self.milestones.map(update_category_id),
    159              containers=self.containers.map(update_category_id)
    160          )
    161
    162 -    def save_container(self, container, id_):
    163          self._ensure_non_none_category_exists(container.category_id)
    164          return self.update(
    165              containers=self.containers.update({id_: container})
    166          )
    167
    168 -    def delete_container(self, delete_id):
    169          self._ensure_container_exists(delete_id)
    170
    171          def update_container_id(event):
    172              if event.container_id == delete_id:
    173                  return event.update(container_id=None)
    174              else:
    175                  return event
    176          return self.update(
    177              containers=self.containers.remove(delete_id),
    178              events=self.events.map(update_container_id),
    179          )
    180
    181 -    def _ensure_event_exists(self, id_):
    182          if id_ not in self.events:
    183              raise InvalidOperationError(
    184                  "Event with id {0!r} does not exist".format(id_)
    185              )
    186
    187 -    def _ensure_milestone_exists(self, id_):
    188          if id_ not in self.milestones:
    189              raise InvalidOperationError(
    190                  "Milestone with id {0!r} does not exist".format(id_)
    191              )
    192
    193 -    def _ensure_era_exists(self, id_):
    194          if id_ not in self.eras:
    195              raise InvalidOperationError(
    196                  "Era with id {0!r} does not exist".format(id_)
    197              )
    198
    199 -    def _ensure_category_name_is_unique(self, save_id, save_name):
    200          for id_, category in self.categories:
    201              if id_ != save_id and category.name == save_name:
    202                  raise InvalidOperationError(
    203                      "Category name {0!r} is not unique".format(save_name)
    204                  )
    205
    206 -    def _ensure_non_none_category_exists(self, id_):
    207          if id_ is not None:
    208              self._ensure_category_exists(id_)
    209
    210 -    def _ensure_category_exists(self, id_):
    211          if id_ not in self.categories:
    212              raise InvalidOperationError(
    213                  "Category with id {0!r} does not exist".format(id_)
    214              )
    215
    216 -    def _ensure_no_category_circular(self, save_id, parent_id):
    217          while parent_id is not None:
    218              if parent_id == save_id:
    219                  raise InvalidOperationError(
    220                      "Circular category parent"
    221                  )
    222              else:
    223                  parent_id = self.categories.get(parent_id).parent_id
    224
    225 -    def _ensure_non_none_container_exists(self, id_):
    226          if id_ is not None:
    227              self._ensure_container_exists(id_)
    228
    229 -    def _ensure_container_exists(self, id_):
    230          if id_ not in self.containers:
    231              raise InvalidOperationError(
    232                  "Container with id {0!r} does not exist".format(id_)
    233              )
    234
    235
    236 -class InvalidOperationError(Exception):
    237      pass
    238