Package Gnumed :: Package timelinelib :: Package db :: Package backends :: Module dir |
[frames] | no frames]

# Source Code for Module Gnumed.timelinelib.db.backends.dir

      1  # Copyright (C) 2009, 2010, 2011  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  """
     20  Implementation of read-only timeline database where events show modification
     21  times of files in a directory.
     22  """
     23
     24
     25  import os
     26  import os.path
     27  import colorsys
     28  from datetime import datetime
     29  from datetime import timedelta
     30  import time
     31
     32  import wx
     33
     34  from timelinelib.db.backends.memory import MemoryDB
     35  from timelinelib.db.exceptions import TimelineIOError
     36  from timelinelib.db.objects import Category
     37  from timelinelib.db.objects import Event
     38
     39
     40 -class DirTimeline(MemoryDB):
     41
     42 -    def __init__(self, path):
     43          MemoryDB.__init__(self)
     44          self._load(path)
     45
     46 -    def is_read_only(self):
     47          """Override MemoryDB's read-only attribute."""
     48          return True
     49
     50 -    def _load(self, dir_path):
     51          """
     52          Load timeline data from the given directory.
     53
     54          Each file inside the directory (at any level) becomes an event where
     55          the text is the file name and the time is the modification time for
     56          the file.
     57
     58          For each sub-directory a category is created and all events (files)
     59          belong the category (directory) in which they are.
     60          """
     61          if not os.path.exists(dir_path):
     62              # Nothing to load
     63              return
     64          if not os.path.isdir(dir_path):
     65              # Nothing to load
     66              return
     67          try:
     68              self.disable_save()
     69              color_ranges = {} # Used to color categories
     70              color_ranges[dir_path] = (0.0, 1.0, 1.0)
     71              all_cats = []
     72              parents = {}
     73              for (dirpath, dirnames, filenames) in os.walk(dir_path):
     74                  # Assign color ranges
     75                  range = (rstart, rend, b) = color_ranges[dirpath]
     76                  step = (rend - rstart) / (len(dirnames) + 1)
     77                  next_start = rstart + step
     78                  new_b = b - 0.2
     79                  if new_b < 0:
     80                      new_b = 0
     81                  for dir in dirnames:
     82                      next_end = next_start + step
     83                      color_ranges[os.path.join(dirpath, dir)] = (next_start,
     84                                                                  next_end, new_b)
     85                      next_start = next_end
     86                  # Create the stuff
     87                  p = parents.get(os.path.normpath(os.path.join(dirpath, "..")),
     88                                  None)
     89                  cat = Category(dirpath, (233, 233, 233), None, False, parent=p)
     90                  parents[os.path.normpath(dirpath)] = cat
     91                  all_cats.append(cat)
     92                  self.save_category(cat)
     93                  for file in filenames:
     94                      path_inner = os.path.join(dirpath, file)
     95                      evt = self._event_from_path(path_inner)
     96                      self.save_event(evt)
     97              # Hide all categories but the first
     98              self._set_hidden_categories(all_cats[1:])
     99              # Set colors and change names
    100              for cat in self.get_categories():
    101                  cat.color = self._color_from_range(color_ranges[cat.name])
    102                  cat.name = os.path.basename(cat.name)
    103                  self.save_category(cat)
    104          except Exception, e:
    105              msg = _("Unable to read from file '%s'.") % dir_path
    106              whole_msg = "%s\n\n%s" % (msg, e)
    107              raise TimelineIOError(whole_msg)
    108          finally:
    109              self.enable_save(call_save=False)
    110
    111 -    def _event_from_path(self, file_path):
    112          stat = os.stat(file_path)
    113          # st_atime (time of most recent access),
    114          # st_mtime (time of most recent content modification),
    115          # st_ctime (platform dependent; time of most recent metadata change on
    116          #           Unix, or the time of creation on Windows):
    117          start_time = datetime.fromtimestamp(int(stat.st_mtime))
    118          end_time = start_time
    119          if start_time > end_time:
    120              start_time, end_time = end_time, start_time
    121          text = os.path.basename(file_path)
    122          category = self._category_from_path(file_path)
    123          evt = Event(self.get_time_type(), start_time, end_time, text, category)
    124          return evt
    125
    126 -    def _category_from_path(self, file_path):
    127          for cat in self.get_categories():
    128              if cat.name == os.path.dirname(file_path):
    129                  return cat
    130          return None
    131
    132 -    def _category_from_name(self, name):
    133          for cat in self.get_categories():
    134              if cat.name == name:
    135                  return cat
    136          return None
    137
    138 -    def _color_from_range(self, range):
    139          (rstart, rend, b) = range
    140          (r, g, b) = colorsys.hsv_to_rgb(rstart, b, 1)
    141          return (r*255, g*255, b*255)
    142