Package Gnumed :: Package timelinelib :: Package dataimport :: Module dir |
[frames] | no frames]

# Source Code for Module Gnumed.timelinelib.dataimport.dir

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