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