3
# Copyright (C) 2009 Toms Bauģis <toms.baugis at gmail.com>
5
# This file is part of Project Hamster.
7
# Project Hamster is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
12
# Project Hamster is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with Project Hamster. If not, see <http://www.gnu.org/licenses/>.
20
from .hamster import graphics
23
class TimeLine(graphics.Area):
24
"""this widget is kind of half finished"""
31
graphics.Area.__init__(self)
32
self.start_date, self.end_date = None, None
38
def draw(self, facts):
41
for date, date_facts in itertools.groupby(facts, lambda x: x["start_time"].date()):
42
date_facts = list(date_facts)
43
self.facts[date] = date_facts
44
self.max_hours = max(self.max_hours,
45
sum([fact["delta"].seconds / 60 / float(60) +
46
fact["delta"].days * 24 for fact in date_facts]))
48
start_date = facts[0]["start_time"].date()
49
end_date = facts[-1]["start_time"].date()
51
self.draw_mode = self.MODE_YEAR
52
self.start_date = start_date.replace(month=1, day=1)
53
self.end_date = end_date.replace(month=12, day=31)
57
#TODO - for now we have only the year mode
58
if start_date.year != end_date.year or start_date.month != end_date.month:
59
self.draw_mode = self.MODE_YEAR
60
self.start_date = start_date.replace(month=1, day=1)
61
self.end_date = end_date.replace(month=12, day=31)
62
elif start_date.strftime("%W") != end_date.strftime("%W"):
63
self.draw_mode = self.MODE_MONTH
64
self.start_date = start_date.replace(day=1)
65
self.end_date = end_date.replace(date =
66
calendar.monthrange(self.end_date.year,
67
self.end_date.month)[1])
68
elif start_date != end_date:
69
self.draw_mode = self.MODE_WEEK
71
self.draw_mode = self.MODE_DAY
80
if self.draw_mode != self.MODE_YEAR:
83
self.fill_area(0, 0, self.width, self.height, (0.975,0.975,0.975))
84
self.set_color((100,100,100))
87
days = (self.end_date - self.start_date).days
88
pixels_in_day = self.width / float(days)
90
month_label_fits = True
91
for month in range(1, 13):
92
self.layout.set_text(calendar.month_abbr[month])
93
label_w, label_h = self.layout.get_pixel_size()
94
if label_w * 2 > pixels_in_day * 30:
95
month_label_fits = False
99
ticker_date = self.start_date
103
for year in range(self.start_date.year, self.end_date.year + 1):
104
#due to how things lay over, we are putting labels on backwards, so that they don't overlap
106
self.context.set_line_width(1)
107
for month in range(1, 13):
108
for day in range(1, calendar.monthrange(year, month)[1] + 1):
109
ticker_pos = (year_pos + ticker_date.timetuple().tm_yday * pixels_in_day)
113
if pixels_in_day > 5:
114
self.context.move_to(ticker_pos, self.height - 20)
115
self.context.line_to(ticker_pos, self.height)
117
self.layout.set_text(ticker_date.strftime("%d"))
118
label_w, label_h = self.layout.get_pixel_size()
120
if label_w < pixels_in_day / 1.2: #if label fits
121
self.context.move_to(ticker_pos + 2, self.height - 20)
122
self.context.show_layout(self.layout)
124
self.context.stroke()
127
facts_today = self.facts.get(ticker_date, [])
129
total_length = dt.timedelta()
130
for fact in facts_today:
131
total_length += fact["delta"]
132
total_length = total_length.seconds / 60 / 60.0 + total_length.days * 24
133
total_length = total_length / float(self.max_hours) * self.height - 16
135
self.fill_area(round(ticker_pos),
136
round(self.height - total_length),
137
round(pixels_in_day),
144
ticker_date += dt.timedelta(1)
150
month_pos = ticker_pos - (calendar.monthrange(year, month)[1] + 1) * pixels_in_day
152
self.context.move_to(month_pos, 0)
153
self.layout.set_text(dt.date(year, month, 1).strftime("%b"))
154
self.context.show_layout(self.layout)
160
self.layout.set_text("%d" % year)
161
label_w, label_h = self.layout.get_pixel_size()
163
self.context.move_to(year_pos + 2, month_label_fits * label_h * 1.2)
165
self.context.show_layout(self.layout)
167
self.context.stroke()
169
year_pos = ticker_pos #save current state for next year