Gnumed.timelinelib.canvas.data.event

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

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

      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.data.base import ItemBase
     20  from timelinelib.canvas.data.immutable import ImmutableEvent
     21  from timelinelib.canvas.data.item import TimelineItem
     22  from timelinelib.canvas.drawing.drawers import get_progress_color
     23
     24
     25  DEFAULT_COLOR = (200, 200, 200)
     26  EXPORTABLE_FIELDS = (_("Text"), _("Description"), _("Start"), _("End"), _("Category"),
     27                       _("Fuzzy"), _("Locked"), _("Ends Today"), _("Hyperlink"),
     28                       _("Progress"), _("Progress Color"), _("Done Color"), _("Alert"),
     29                       _("Is Container"), _("Is Subevent"))
     30
     31
     32 -class Event(ItemBase, TimelineItem):
     33
     34 -    def __init__(self, db=None, id_=None, immutable_value=ImmutableEvent()):
     35          ItemBase.__init__(self, db, id_, immutable_value)
     36          self._category = None
     37          self._categories = []
     38          self._container = None
     39          self._milestone = False
     40
     41 -    def duplicate(self, target_db=None):
     42          duplicate = ItemBase.duplicate(self, target_db=target_db)
     43          if duplicate.db is self.db:
     44              duplicate.category = self.category
     45          duplicate.sort_order = None
     46          return duplicate
     47
     48 -    def save(self):
     49          self._update_category_id()
     50          self._update_category_ids()
     51          self._update_container_id()
     52          self._update_sort_order()
     53          with self._db.transaction("Save event") as t:
     54              t.save_event(self._immutable_value, self.ensure_id())
     55          return self
     56
     57 -    def reload(self):
     58          return self._db.find_event_with_id(self.id)
     59
     60 -    def _update_category_id(self):
     61          if self.category is None:
     62              self._immutable_value = self._immutable_value.update(
     63                  category_id=None
     64              )
     65          elif self.category.id is None:
     66              raise Exception("Unknown category")
     67          else:
     68              self._immutable_value = self._immutable_value.update(
     69                  category_id=self.category.id
     70              )
     71
     72 -    def _update_category_ids(self):
     73          if self._categories == list():
     74              self._immutable_value = self._immutable_value.update(
     75                  category_ids={}
     76              )
     77          else:
     78              ids = [c.id for c in self._categories]
     79              # Using a dictionary because we don't have any ImmutableList class
     80              dic = {k: None for k in ids}
     81              self._immutable_value = self._immutable_value.update(
     82                  category_ids=dic
     83              )
     84
     85 -    def _update_container_id(self):
     86          if self.container is None:
     87              self._immutable_value = self._immutable_value.update(
     88                  container_id=None
     89              )
     90          elif self.container.id is None:
     91              raise Exception("Unknown container")
     92          else:
     93              self._immutable_value = self._immutable_value.update(
     94                  container_id=self.container.id
     95              )
     96
     97 -    def _update_sort_order(self):
     98          if self.sort_order is None:
     99              self.sort_order = 1 + self.db.get_max_sort_order()
    100
    101 -    def delete(self):
    102          with self._db.transaction("Delete event") as t:
    103              t.delete_event(self.id)
    104          self.id = None
    105
    106 -    def __eq__(self, other):
    107          return (isinstance(other, Event) and
    108                  self.get_fuzzy() == other.get_fuzzy() and
    109                  self.get_locked() == other.get_locked() and
    110                  self.get_ends_today() == other.get_ends_today() and
    111                  self.get_id() == other.get_id() and
    112                  self.get_time_period().start_time == other.get_time_period().start_time and
    113                  (self.get_time_period().end_time == other.get_time_period().end_time or self.get_ends_today()) and
    114                  self.get_text() == other.get_text() and
    115                  self.get_category() == other.get_category() and
    116                  self.get_description() == other.get_description() and
    117                  self.get_hyperlink() == other.get_hyperlink() and
    118                  self.get_progress() == other.get_progress() and
    119                  self.get_alert() == other.get_alert() and
    120                  self.get_icon() == other.get_icon() and
    121                  self.get_default_color() == other.get_default_color())
    122
    123 -    def __ne__(self, other):
    124          return not (self == other)
    125
    126 -    def __lt__(self, other):
    127          raise NotImplementedError("I don't believe this is in use.")
    128
    129 -    def __gt__(self, other):
    130          raise NotImplementedError("I don't believe this is in use.")
    131
    132 -    def __le__(self, other):
    133          raise NotImplementedError("I don't believe this is in use.")
    134
    135 -    def __ge__(self, other):
    136          raise NotImplementedError("I don't believe this is in use.")
    137
    138 -    def __repr__(self):
    139          return "%s<id=%r, text=%r, time_period=%r, ...>" % (
    140              self.__class__.__name__,
    141              self.get_id(),
    142              self.get_text(),
    143              self.get_time_period()
    144          )
    145
    146 -    def set_end_time(self, time):
    147          self.set_time_period(self.get_time_period().set_end_time(time))
    148
    149 -    def get_text(self):
    150          return self._immutable_value.text
    151
    152 -    def set_text(self, text):
    153          self._immutable_value = self._immutable_value.update(text=text.strip())
    154          return self
    155
    156      text = property(get_text, set_text)
    157
    158 -    def get_category(self):
    159          return self._category
    160
    161 -    def get_category_name(self):
    162          if self.get_category():
    163              return self.get_category().get_name()
    164          else:
    165              return None
    166
    167 -    def set_category(self, category):
    168          self._category = category
    169          return self
    170
    171      category = property(get_category, set_category)
    172
    173 -    def get_categories(self):
    174          return self._categories
    175
    176 -    def set_categories(self, categories):
    177          if categories:
    178              if self.category:
    179                  if self.category in categories:
    180                      categories.remove(self.category)
    181              else:
    182                  self.category = categories[0]
    183                  categories = categories[1:]
    184              self._categories = categories
    185
    186 -    def get_container(self):
    187          return self._container
    188
    189 -    def set_container(self, container):
    190          if self._container is not None:
    191              self._container.unregister_subevent(self)
    192          self._container = container
    193          if self._container is not None:
    194              self._container.register_subevent(self)
    195          return self
    196
    197      container = property(get_container, set_container)
    198
    199 -    def get_fuzzy(self):
    200          return self._immutable_value.fuzzy
    201
    202 -    def set_fuzzy(self, fuzzy):
    203          self._immutable_value = self._immutable_value.update(fuzzy=fuzzy)
    204          return self
    205
    206      fuzzy = property(get_fuzzy, set_fuzzy)
    207
    208 -    def get_locked(self):
    209          return self._immutable_value.locked
    210
    211 -    def set_locked(self, locked):
    212          self._immutable_value = self._immutable_value.update(locked=locked)
    213          return self
    214
    215      locked = property(get_locked, set_locked)
    216
    217 -    def get_ends_today(self):
    218          return self._immutable_value.ends_today
    219
    220 -    def set_ends_today(self, ends_today):
    221          if not self.locked:
    222              self._immutable_value = self._immutable_value.update(ends_today=ends_today)
    223          return self
    224
    225      ends_today = property(get_ends_today, set_ends_today)
    226
    227 -    def get_description(self):
    228          return self._immutable_value.description
    229
    230 -    def set_description(self, description):
    231          self._immutable_value = self._immutable_value.update(description=description)
    232          return self
    233
    234      description = property(get_description, set_description)
    235
    236 -    def get_icon(self):
    237          return self._immutable_value.icon
    238
    239 -    def set_icon(self, icon):
    240          self._immutable_value = self._immutable_value.update(icon=icon)
    241          return self
    242
    243      icon = property(get_icon, set_icon)
    244
    245 -    def get_hyperlink(self):
    246          return self._immutable_value.hyperlink
    247
    248 -    def set_hyperlink(self, hyperlink):
    249          self._immutable_value = self._immutable_value.update(hyperlink=hyperlink)
    250          return self
    251
    252      hyperlink = property(get_hyperlink, set_hyperlink)
    253
    254 -    def get_alert(self):
    255          return self._immutable_value.alert
    256
    257 -    def set_alert(self, alert):
    258          self._immutable_value = self._immutable_value.update(alert=alert)
    259          return self
    260
    261      alert = property(get_alert, set_alert)
    262
    263 -    def get_progress(self):
    264          return self._immutable_value.progress
    265
    266 -    def set_progress(self, progress):
    267          self._immutable_value = self._immutable_value.update(progress=progress)
    268          return self
    269
    270      progress = property(get_progress, set_progress)
    271
    272 -    def get_sort_order(self):
    273          return self._immutable_value.sort_order
    274
    275 -    def set_sort_order(self, sort_order):
    276          self._immutable_value = self._immutable_value.update(sort_order=sort_order)
    277          return self
    278
    279      sort_order = property(get_sort_order, set_sort_order)
    280
    281 -    def get_default_color(self):
    282          color = self._immutable_value.default_color
    283          if color is None:
    284              color = DEFAULT_COLOR
    285          return color
    286
    287 -    def set_default_color(self, color):
    288          self._immutable_value = self._immutable_value.update(default_color=color)
    289          return self
    290
    291      default_color = property(get_default_color, set_default_color)
    292
    293 -    def get_done_color(self):
    294          if self.category:
    295              return self.category.get_done_color()
    296          else:
    297              return get_progress_color(DEFAULT_COLOR)
    298
    299 -    def get_progress_color(self):
    300          category = self.category
    301          if category:
    302              if self.get_progress() == 100:
    303                  return category.get_done_color()
    304              else:
    305                  return category.get_progress_color()
    306          else:
    307              return get_progress_color(DEFAULT_COLOR)
    308
    309 -    def update(self, start_time, end_time, text, category=None, fuzzy=None,
    310                 locked=None, ends_today=None):
    311          """Change the event data."""
    312          self.update_period(start_time, end_time)
    313          self.text = text.strip()
    314          self.category = category
    315          if ends_today is not None:
    316              if not self.locked:
    317                  self.ends_today = ends_today
    318          if fuzzy is not None:
    319              self.fuzzy = fuzzy
    320          if locked is not None:
    321              self.locked = locked
    322          return self
    323
    324 -    def get_data(self, event_id):
    325          """
    326          Return data with the given id or None if no data with that id exists.
    327
    328          See set_data for information how ids map to data.
    329          """
    330          if event_id == "description":
    331              return self.description
    332          elif event_id == "icon":
    333              return self.icon
    334          elif event_id == "hyperlink":
    335              return self.hyperlink
    336          elif event_id == "alert":
    337              return self.alert
    338          elif event_id == "progress":
    339              return self.progress
    340          elif event_id == "default_color":
    341              if "default_color" in self._immutable_value:
    342                  return self._immutable_value.default_color
    343              else:
    344                  return None
    345          else:
    346              raise Exception("should not happen")
    347
    348 -    def set_data(self, event_id, data):
    349          """
    350          Set data with the given id.
    351
    352          Here is how ids map to data:
    353
    354              description - string
    355              icon - wx.Bitmap
    356          """
    357          if event_id == "description":
    358              self.description = data
    359          elif event_id == "icon":
    360              self.icon = data
    361          elif event_id == "hyperlink":
    362              self.hyperlink = data
    363          elif event_id == "alert":
    364              self.alert = data
    365          elif event_id == "progress":
    366              self.progress = data
    367          elif event_id == "default_color":
    368              self.default_color = data
    369          else:
    370              raise Exception("should not happen")
    371
    372 -    def get_whole_data(self):
    373          data = {}
    374          for event_id in DATA_FIELDS:
    375              data[event_id] = self.get_data(event_id)
    376          return data
    377
    378 -    def set_whole_data(self, data):
    379          for event_id in DATA_FIELDS:
    380              self.set_data(event_id, data.get(event_id, None))
    381
    382      data = property(get_whole_data, set_whole_data)
    383
    384 -    def has_data(self):
    385          """Return True if the event has associated data, or False if not."""
    386          for event_id in DATA_FIELDS:
    387              if self.get_data(event_id) is not None:
    388                  return True
    389          return False
    390
    391 -    def has_balloon_data(self):
    392          """Return True if the event has associated data to be displayed in a balloon."""
    393          return (self.get_data("description") is not None or
    394                  self.get_data("icon") is not None)
    395
    396 -    def get_label(self, time_type):
    397          """Returns a unicode label describing the event."""
    398          event_label = "%s (%s)" % (
    399              self.text,
    400              time_type.format_period(self.get_time_period()),
    401          )
    402          duration_label = self._get_duration_label(time_type)
    403          if duration_label != "":
    404              return "%s  %s: %s" % (event_label, _("Duration"), duration_label)
    405          else:
    406              return event_label
    407
    408 -    def _get_duration_label(self, time_type):
    409          label = time_type.format_delta(self.time_span())
    410          if label == "0":
    411              label = ""
    412          return label
    413
    414 -    def is_container(self):
    415          return False
    416
    417 -    def is_subevent(self):
    418          return False
    419
    420 -    def is_milestone(self):
    421          return False
    422
    423 -    def get_exportable_fields(self):
    424          return EXPORTABLE_FIELDS
    425
    426 -    def set_milestone(self, value):
    427          self._milestone = value
    428
    429 -    def get_milestone(self):
    430          return self._milestone
    431
    432
    433  DATA_FIELDS = [
    434      "description",
    435      "icon",
    436      "hyperlink",
    437      "alert",
    438      "progress",
    439      "default_color",
    440  ]
    441