# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Timeline is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Timeline. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
import colorsys
import os.path
from timelinelib.calendar.gregorian.gregorian import GregorianDateTime
from timelinelib.canvas.data.memorydb.db import MemoryDB
from timelinelib.canvas.data.exceptions import TimelineIOError
from timelinelib.canvas.data import Category
from timelinelib.canvas.data import Event
[docs]def import_db_from_dir(path):
db = MemoryDB()
db.set_readonly()
_load(db, path)
db.clear_transactions()
return db
def _load(db, dir_path):
"""
Load timeline data from the given directory.
Each filename inside the directory (at any level) becomes an event where
the text is the filename name and the time is the modification time for
the filename.
For each sub-directory a category is created and all events (files)
belong the category (directory) in which they are.
"""
if not os.path.exists(dir_path):
# Nothing to load
return
if not os.path.isdir(dir_path):
# Nothing to load
return
try:
color_ranges = {} # Used to color categories
color_ranges[dir_path] = (0.0, 1.0, 1.0)
all_cats = []
parents = {}
for (dirpath, dirnames, filenames) in os.walk(dir_path):
# Assign color ranges
(rstart, rend, b) = color_ranges[dirpath]
step = (rend - rstart) // (len(dirnames) + 1)
next_start = rstart + step
new_b = b - 0.2
if new_b < 0:
new_b = 0
for dirname in dirnames:
next_end = next_start + step
color_ranges[os.path.join(dirpath, dirname)] = (next_start, next_end, new_b)
next_start = next_end
# Create the stuff
p = parents.get(os.path.normpath(os.path.join(dirpath, "..")),
None)
cat = Category().update(dirpath, (233, 233, 233), None, parent=p)
parents[os.path.normpath(dirpath)] = cat
all_cats.append(cat)
db.save_category(cat)
for filename in filenames:
path_inner = os.path.join(dirpath, filename)
evt = _event_from_path(db, path_inner)
db.save_event(evt)
# Hide all categories but the first
db.set_hidden_categories(all_cats[1:])
# Set colors and change names
used_names = []
for cat in db.get_categories():
cat.color = _color_from_range(color_ranges[cat.name])
cat.name = get_unique_cat_name(os.path.basename(cat.name), used_names)
db.save_category(cat)
except Exception as e:
msg = _("Unable to read from filename '%s'.") % dir_path
whole_msg = "%s\n\n%s" % (msg, e)
print(whole_msg)
raise TimelineIOError(whole_msg)
[docs]def get_unique_cat_name(name, used_names):
cat_name = name
if cat_name in used_names:
i = 1
cat_name = "%s(%d)" % (name, i)
while cat_name in used_names:
i += 1
cat_name = "%s(%d)" % (name, i)
used_names.append(cat_name)
return cat_name
def _event_from_path(db, file_path):
stat = os.stat(file_path)
# st_atime (time of most recent access),
# st_mtime (time of most recent content modification),
# st_ctime (platform dependent; time of most recent metadata change on
# Unix, or the time of creation on Windows):
dt = datetime.fromtimestamp(int(stat.st_mtime))
start_time = GregorianDateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second).to_time()
end_time = start_time
if start_time > end_time:
start_time, end_time = end_time, start_time
text = os.path.basename(file_path)
category = _category_from_path(db, file_path)
evt = Event().update(start_time, end_time, text, category)
return evt
def _category_from_path(db, file_path):
for cat in db.get_categories():
if cat.name == os.path.dirname(file_path):
return cat
return None
def _color_from_range(color_range):
(rstart, _, b) = color_range
(r, g, b) = colorsys.hsv_to_rgb(rstart, b, 1)
return r * 255, g * 255, b * 255