[billreminder] Timeline widget will not support displaying multiple bills with different states on the same day. Fi
- From: Og B. Maciel <ogmaciel src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [billreminder] Timeline widget will not support displaying multiple bills with different states on the same day. Fi
- Date: Sat, 10 Oct 2009 14:26:00 +0000 (UTC)
commit 950c8c8eb919e01930fd4a67121c2a8bc592edc4
Author: Luiz Fernando <luiz armesto gmail com>
Date: Sat Oct 10 10:24:08 2009 -0400
Timeline widget will not support displaying multiple bills with different states on the same day. Fixes b.g.o #569023
src/gui/maindialog.py | 49 ++--
src/gui/widgets/timeline.py | 641 +++++++++++++++++++++++++------------------
2 files changed, 403 insertions(+), 287 deletions(-)
---
diff --git a/src/gui/maindialog.py b/src/gui/maindialog.py
index 82f0abd..a0db5ad 100644
--- a/src/gui/maindialog.py
+++ b/src/gui/maindialog.py
@@ -96,7 +96,7 @@ class MainDialog:
# ViewBill
self.list = ViewBill()
- #self.list.connect('cursor_changed', self._on_list_cursor_changed)
+ self.list.connect('cursor_changed', self._on_list_cursor_changed)
self.list.connect('row_activated', self._on_list_row_activated)
self.list.connect('button_press_event', self._on_list_button_press_event)
@@ -409,25 +409,31 @@ class MainDialog:
def remove_bill(self):
try:
- if self.actions.delete_bill(self.currentrecord.Id):
- self.list.remove()
- self.update_statusbar()
- self.reloadTimeline()
+ session = DAL().Session()
+ session.delete(self.currentrecord)
+ session.commit()
+ self.list.remove()
+ self.update_statusbar()
+ self.reloadTimeline()
except Exception, e:
print str(e)
def toggle_bill_paid(self):
- # Toggle paid field
- self.currentrecord.Paid = (self.currentrecord.Paid == 0) and 1 or 0
-
try:
+ # Toggle paid field
+ self.currentrecord.paid = (self.currentrecord.paid == 0) and 1 or 0
# Edit bill to database
- self.actions.edit_bill(self.currentrecord.Dictionary)
+ session = DAL().Session()
+ session.update(self.currentrecord)
+ session.commit()
+ self._bullet_cache[self.currentrecord.dueDate] = self.actions.get_bills(
+ dueDate=self.currentrecord.dueDate
+ )
# Update list with updated record
idx = self.list.get_cursor()[0][0]
- self.list.listStore[idx] = \
- self.format_row(self.currentrecord.Dictionary)
self.update_statusbar(idx)
+ #self.reloadTreeView()
+ self.reloadTimeline()
except Exception, e:
print str(e)
@@ -523,7 +529,7 @@ class MainDialog:
c.addMenuItem(None,
self.on_btnEdit_clicked, gtk.STOCK_EDIT)
c.addMenuItem('-', None)
- if not self.currentrecord.Paid:
+ if not self.currentrecord.paid:
c.addMenuItem(_('_Paid'),
self.on_btnPaid_clicked, gtk.STOCK_APPLY, True)
else:
@@ -555,7 +561,7 @@ class MainDialog:
if self.currentrecord:
resp = self.message.ShowQuestionYesNo(
_("Do you really want to delete \"%s\"?") % \
- self.currentrecord.Payee,
+ self.currentrecord.payee,
self.window, _("Confirmation"))
if resp:
self.remove_bill()
@@ -593,7 +599,7 @@ class MainDialog:
self._bullet_cache = {}
self.timeline.refresh()
- def on_timeline_cb(self, date):
+ def on_timeline_cb(self, date, display_type):
# TODO: Improve tooltip
# TODO: Improve cache
if not date in self._bullet_cache.keys():
@@ -601,13 +607,11 @@ class MainDialog:
if self._bullet_cache[date]:
amount = 0
- paid = 1
tooltip = ''
bullet = Bullet()
bullet.date = date
for bill in self._bullet_cache[date]:
- paid *= bill.paid
amount += bill.amount
if tooltip:
tooltip += '\n'
@@ -615,13 +619,14 @@ class MainDialog:
if bill.notes:
tooltip += '\n' + bill.notes
+ if bill.paid:
+ bullet.status = bullet.status | bullet.PAID
+ elif date <= datetime.date.today():
+ bullet.status = bullet.status | bullet.OVERDUE
+ else:
+ bullet.status = bullet.status | bullet.TO_BE_PAID
+
bullet.amountDue = amount
- if paid:
- bullet.status = bullet.PAID
- elif date <= datetime.date.today():
- bullet.status = bullet.OVERDUE
- else:
- bullet.status = bullet.TO_BE_PAID
if len(self._bullet_cache[date]) > 1:
bullet.multi = True
diff --git a/src/gui/widgets/timeline.py b/src/gui/widgets/timeline.py
index d6c310c..31333f6 100644
--- a/src/gui/widgets/timeline.py
+++ b/src/gui/widgets/timeline.py
@@ -8,11 +8,14 @@ import gobject
import pango
import datetime
from math import pi, floor
+import warnings
debug = False
class Bullet(object):
- OVERDUE, TO_BE_PAID, PAID = range(-1, 2)
+ OVERDUE = 0b001
+ TO_BE_PAID = 0b010
+ PAID = 0b100
debug = False
@@ -33,11 +36,12 @@ class Timeline(gtk.DrawingArea):
date interval
"""
DAY, WEEK, MONTH, YEAR = range(4)
- DIVS = {}
- DIVS[DAY] = 16
- DIVS[WEEK] = 16
- DIVS[MONTH] = 24
- DIVS[YEAR] = 10
+ DIVS = {
+ DAY: 16,
+ WEEK: 16,
+ MONTH: 24,
+ YEAR: 10
+ }
debug = False
@@ -71,7 +75,7 @@ class Timeline(gtk.DrawingArea):
if callback:
self._bullet_func = callback
else:
- self._bullet_func = lambda date_: None
+ self._bullet_func = lambda date_, type_: None
# Set defaults
self._mindex = 0
@@ -89,44 +93,54 @@ class Timeline(gtk.DrawingArea):
self._clicked_position = -1
self.value = date
self.orientation = gtk.ORIENTATION_HORIZONTAL
- self.position = round((self._display_days - 1) / 2)
+ self._position = round((self._display_days - 1) / 2)
# Widget initialization
self.drag = False
super(gtk.DrawingArea, self).__init__()
- self.add_events(gtk.gdk.BUTTON_MOTION_MASK |
- gtk.gdk.BUTTON_PRESS_MASK |
- gtk.gdk.BUTTON_RELEASE_MASK |
- gtk.gdk.SCROLL_MASK)
- gobject.signal_new('value-changed',
- Timeline,
- gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,))
- gobject.signal_new('scroll',
- Timeline,
- gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,))
+ self.add_events(
+ gtk.gdk.BUTTON_MOTION_MASK |
+ gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.BUTTON_RELEASE_MASK |
+ gtk.gdk.SCROLL_MASK
+ )
+ gobject.signal_new(
+ 'value-changed',
+ Timeline,
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,)
+ )
+ gobject.signal_new(
+ 'scroll',
+ Timeline,
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT,)
+ )
self. connect('size-allocate', self.on_size_allocate)
def do_realize(self):
self.set_flags(self.flags() | gtk.REALIZED)
- events = (gtk.gdk.EXPOSURE_MASK |
- gtk.gdk.BUTTON_PRESS_MASK |
- gtk.gdk.POINTER_MOTION_MASK |
- gtk.gdk.KEY_PRESS_MASK |
- gtk.gdk.KEY_RELEASE_MASK)
- self.window = gtk.gdk.Window(self.get_parent_window(),
- x=self.allocation.x,
- y=self.allocation.y,
- width=self.allocation.width,
- height=self.allocation.height,
- window_type=gtk.gdk.WINDOW_CHILD,
- wclass=gtk.gdk.INPUT_OUTPUT,
- visual=self.get_visual(),
- colormap=self.get_colormap(),
- event_mask=self.get_events() | events)
+ events = (
+ gtk.gdk.EXPOSURE_MASK |
+ gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.POINTER_MOTION_MASK |
+ gtk.gdk.KEY_PRESS_MASK |
+ gtk.gdk.KEY_RELEASE_MASK
+ )
+ self.window = gtk.gdk.Window(
+ self.get_parent_window(),
+ x=self.allocation.x,
+ y=self.allocation.y,
+ width=self.allocation.width,
+ height=self.allocation.height,
+ window_type=gtk.gdk.WINDOW_CHILD,
+ wclass=gtk.gdk.INPUT_OUTPUT,
+ visual=self.get_visual(),
+ colormap=self.get_colormap(),
+ event_mask=self.get_events() | events
+ )
self.window.set_user_data(self)
self.style.attach(self.window)
self.style.set_background(self.window, gtk.STATE_NORMAL)
@@ -147,7 +161,9 @@ class Timeline(gtk.DrawingArea):
def refresh(self):
self._bullets = {}
self._dist_dates()
- self.queue_draw_area(0, 0, self.allocation.width, self.allocation.height)
+ self.queue_draw_area(
+ 0, 0, self.allocation.width, self.allocation.height
+ )
def draw(self, redraw=False):
if self.orientation == gtk.ORIENTATION_HORIZONTAL:
@@ -159,167 +175,206 @@ class Timeline(gtk.DrawingArea):
raise ValueError, 'self.orientation'
def _hdraw(self, redraw=False):
- # TODO Organize
""" Draw a horizontal timeline """
self._layout = self.create_pango_layout('')
-
- # base box
- self.window.draw_rectangle(self.style.base_gc[gtk.STATE_NORMAL], True,
- self._box_rect.x,
- self._box_rect.y,
- self._box_rect.width,
- self._box_rect.height)
-
cr = self.window.cairo_create()
- self.style.paint_shadow(self.window, self.state,
- gtk.SHADOW_IN, None, self, '',
- self._box_rect.x, self._box_rect.y,
- self._box_rect.width + 1,
- self._box_rect.height)
+ # Draw the base box
+ self.window.draw_rectangle(
+ self.style.base_gc[gtk.STATE_NORMAL], True,
+ self._box_rect.x,
+ self._box_rect.y,
+ self._box_rect.width,
+ self._box_rect.height
+ )
+
+ self.style.paint_shadow(
+ self.window, self.state,
+ gtk.SHADOW_IN, None, self, '',
+ self._box_rect.x, self._box_rect.y,
+ self._box_rect.width + 1,
+ self._box_rect.height
+ )
y_ = self._box_rect.y + self._box_rect.height / 2
- ## lines and bullets
- y = int(self._box_rect.y + self._box_rect.height / 2)
+
+ line_cg = self.style.text_gc
+ fg_color = {
+ 'red': self.parent.style.text[gtk.STATE_NORMAL].red / 65535.0,
+ 'green': self.parent.style.text[gtk.STATE_NORMAL].green / 65535.0,
+ 'blue': self.parent.style.text[gtk.STATE_NORMAL].blue / 65535.0
+ }
+ radius = self._bullet_radius
+ radius_by_two = radius / 2
+ radius_by_three = radius / 3
+ radius_by_four = radius / 4
+ radius_by_five = radius / 5
+ radius_by_seven = radius / 7
+ radius_by_eight = radius / 8
+ two_pi = 2 * pi;
+ arc = (two_pi) / 40
+ y = int(y_)
+
+ # Go through all visible positions
for i in range(self._display_days):
line_h = 3
- line_cg = self.style.dark_gc
-
x = self._box_rect.x + self._div_width * i + self._div_width / 2
- width = self._bullet_radius
- # bullets
+ # Draw bullets
if self._bullets[i] and i < self._display_days:
- arc = (2 * pi) / 40
bullet_ = self._bullets[i]
- if bullet_.status == Bullet.PAID:
- cr.set_source_rgb(0.27, 0.81, 0.44)
- cr.set_source_rgb(0.19, 0.51, 0)
- elif bullet_.status == Bullet.OVERDUE:
- cr.set_source_rgb(1, 0.16, 0.16)
- else:
- cr.set_source_rgb(0.52, 0.81, 0.87)
+ # Draw the behind bullet when is multiple
if bullet_.multi:
- x += width / 4
- y += width / 3
- cr.arc(x, y, width, 0, 2 * pi)
+ if bullet_.status & Bullet.TO_BE_PAID:
+ cr.set_source_rgba(0.13, 0.4, 0.48)
+ if bullet_.status & Bullet.OVERDUE:
+ cr.set_source_rgba(0.47, 0, 0)
+ if bullet_.status & Bullet.PAID:
+ cr.set_source_rgba(0.19, 0.51, 0)
+ ## Move to the position of behind bullet
+ x += radius_by_four
+ y += radius_by_three
+ ## Draw it
+ cr.arc(x, y, radius, 0, two_pi)
cr.fill_preserve()
- cr.set_line_width(width / 8)
- if bullet_.status == Bullet.PAID:
- cr.set_source_rgb(0.19, 0.51, 0)
- elif bullet_.status == Bullet.OVERDUE:
- cr.set_source_rgb(0.47, 0, 0)
- else:
- cr.set_source_rgb(0.13, 0.4, 0.48)
- #cr.arc(x, y, width, 0, 2 * pi)
+ cr.set_line_width(radius_by_eight)
cr.stroke()
- x -= width / 4
- y -= width / 3
- if bullet_.status == Bullet.PAID:
+ ## Move back to the main bullet position
+ x -= radius_by_four
+ y -= radius_by_three
+
+ # Draw the main bullet body
+ ## Set the color
+ if bullet_.status & Bullet.PAID:
cr.set_source_rgb(0.27, 0.81, 0.44)
- elif bullet_.status == Bullet.OVERDUE:
+ if bullet_.status & Bullet.OVERDUE:
cr.set_source_rgb(1, 0.16, 0.16)
- else:
+ if bullet_.status & Bullet.TO_BE_PAID:
cr.set_source_rgb(0.52, 0.81, 0.87)
- cr.arc(x, y, width, 0, 2 * pi)
+ ## Draw it
+ cr.arc(x, y, radius, 0, two_pi)
cr.fill()
- if bullet_.status == Bullet.PAID:
+ # Draw the main bullet border
+ ## Set the color
+ if bullet_.status & Bullet.PAID:
cr.set_source_rgb(0.19, 0.51, 0)
- elif bullet_.status == Bullet.OVERDUE:
+ if bullet_.status & Bullet.OVERDUE:
cr.set_source_rgb(0.47, 0, 0)
- else:
+ if bullet_.status & Bullet.TO_BE_PAID:
cr.set_source_rgb(0.13, 0.4, 0.48)
+ # Set different border size if is overthreshold
if bullet_.overthreshold:
- cr.set_line_width(width / 3)
+ cr.set_line_width(radius_by_three)
else:
- cr.set_line_width(width / 5)
+ cr.set_line_width(radius_by_five)
+
+ # Draw dotted border if is estimeded
if bullet_.estimated:
for j in range(0, 40, 2):
if bullet_.overthreshold:
- cr.arc(x, y, width, arc * j, arc * (j + 1))
+ cr.arc(x, y, radius, arc * j, arc * (j + 1))
else:
- cr.arc(x, y, width, arc * j, arc * (j + 0.5))
+ cr.arc(x, y, radius, arc * j, arc * (j + 0.5))
cr.stroke()
+ # Else draw the solid border
else:
- cr.arc(x, y, width, 0, 2 * pi)
+ cr.arc(x, y, radius, 0, two_pi)
cr.stroke()
- y = y_
-
+ # Draw vertical dashed line if the position is for today
+ if self._dates[i] == datetime.date.today():
+ cr.set_source_rgba(
+ fg_color['red'], fg_color['green'], fg_color['blue'], 0.75
+ )
+ cr.set_line_width(max(radius_by_eight, 0.8))
cr.set_source_rgb(0.4, 0.4, 0.4)
- cr.arc(x, y, width / 5, 0, 2 * pi)
- cr.fill()
- if self._dates[i].weekday() == 0:
- cr.set_line_width(max(width / 8, 0.8))
- cr.move_to(x, y - max(width / 2, 4))
- cr.line_to(x, y + max(width / 2, 4))
+ h_ = (self._box_rect.height + self._box_rect.y) / 10
+ for j in range(0, 10, 2):
+ cr.move_to(x, self._box_rect.y + h_ * j + 1)
+ cr.line_to(x, self._box_rect.y + h_ * (j + 1))
cr.stroke()
- if self._dates[i] == datetime.date.today():
- cr.set_line_width(max(width / 8, 0.8))
- cr.set_source_rgb(0.4, 0.4, 0.4)
- h_ = (self._box_rect.height + self._box_rect.y) / 10
- for j in range(0, 10, 2):
- cr.move_to(x, self._box_rect.y + h_ * j + 1)
- cr.line_to(x, self._box_rect.y + h_ * (j + 1))
- cr.stroke()
+ # Draw dots
+ cr.set_source_rgba(
+ fg_color['red'], fg_color['green'], fg_color['blue'], 0.75
+ )
+ if self._dates[i].weekday() == 6:
+ cr.arc(x, y, radius_by_five, 0, two_pi)
+ else:
+ cr.arc(x, y, radius_by_seven, 0, two_pi)
+ cr.fill()
- ## year label
+ #Draw label
+ ## Draw the year label
if (self._dates[i].day, self._dates[i].month) == (1, 1) or \
(self._dates[i].month == 1 and self._dates[i].day <= 7 and
self._type == self.WEEK):
if i < self._display_days:
- self._layout.set_markup('<small>' + str(self._dates[i].year) + '</small>')
+ self._layout.set_markup(
+ '<small>' + str(self._dates[i].year) + '</small>'
+ )
size_ = self._layout.get_pixel_size()
- self.style.paint_layout(self.window, self.state, False,
- None, self, '',
- int(self._box_rect.x + \
- self._div_width * i + \
- self._div_width / 2 - size_[0] / 2),
- self._box_rect.y + \
- self._box_rect.height + 12,
- self._layout)
+ self.style.paint_layout(
+ self.window, self.state, False,
+ None, self, '',
+ int(self._box_rect.x + \
+ self._div_width * i + \
+ self._div_width / 2 - size_[0] / 2),
+ self._box_rect.y + \
+ self._box_rect.height + 12,
+ self._layout
+ )
line_h = 6
- ## month label
+ ## Draw the month label
elif ((self._dates[i].day == 1 and self._type == self.DAY) or \
(self._dates[i].day <= 7 and self._type == self.WEEK) or \
(i == 0 and self.start_date.month == self.end_date.month)):
if i < self._display_days:
- self._layout.set_markup('<small>' + self._dates[i].strftime('%b') + '</small>')
+ self._layout.set_markup(
+ '<small>' + self._dates[i].strftime('%b') + '</small>'
+ )
size_ = self._layout.get_pixel_size()
- self.style.paint_layout(self.window, self.state, False,
- None, self, '',
- int(self._box_rect.x + \
- self._div_width * i + \
- self._div_width / 2 - size_[0] / 2),
- self._box_rect.y + \
- self._box_rect.height + 12,
- self._layout)
+ self.style.paint_layout(
+ self.window, self.state, False,
+ None, self, '',
+ int(self._box_rect.x + \
+ self._div_width * i + \
+ self._div_width / 2 - size_[0] / 2),
+ self._box_rect.y + \
+ self._box_rect.height + 12,
+ self._layout
+ )
line_h = 6
- self.window.draw_rectangle(line_cg[self.state],
- True,
- int(self._box_rect.x + self._div_width * i +
- self._div_width / 2),
- self._box_rect.height + \
- self._box_rect.y - 2,
- 1, line_h)
-
- ## day label
- # Draw today with bold font
+ self.window.draw_rectangle(
+ line_cg[self.state],
+ True,
+ int(self._box_rect.x + self._div_width * i +
+ self._div_width / 2),
+ self._box_rect.height + \
+ self._box_rect.y - 2,
+ 1, line_h
+ )
+
+ ## Draw day label
if i < self._display_days and \
(self.display_days < 20 or self._dates[i].weekday() == 0 or \
self._dates[i] == self.value):
+ # Draw today with bold font
if self._dates[i] == datetime.date.today():
- self._layout.set_markup('<b><small>' + str(self._dates[i].day) + '</small></b>')
+ self._layout.set_markup(
+ '<b><small>' + str(self._dates[i].day) + '</small></b>'
+ )
else:
- self._layout.set_markup('<small>' + str(self._dates[i].day) + '</small>')
+ self._layout.set_markup(
+ '<small>' + str(self._dates[i].day) + '</small>'
+ )
state_ = self.state
size_ = self._layout.get_pixel_size()
if self._dates[i] == self.value:
@@ -330,103 +385,126 @@ class Timeline(gtk.DrawingArea):
int(self._box_rect.x + self._div_width * i),
int(self._box_rect.y + self._box_rect.height),
int(self._div_width + 1),
- size_[1])
- self.style.paint_layout(self.window, state_, False,
- None, self, '',
- int(self._box_rect.x + \
- self._div_width * i + \
- self._div_width / 2 - size_[0] / 2),
- self._box_rect.y + \
- self._box_rect.height,
- self._layout)
-
-
- # Line
- cr.set_line_width(max(width / 8, 0.5))
- cr.set_source_rgb(0.4, 0.4, 0.4)
+ size_[1]
+ )
+ self.style.paint_layout(
+ self.window, state_, False,
+ None, self, '',
+ int(self._box_rect.x + \
+ self._div_width * i + \
+ self._div_width / 2 - size_[0] / 2),
+ self._box_rect.y + \
+ self._box_rect.height,
+ self._layout
+ )
+
+ # Draw the central line
+ cr.set_line_width(max(radius_by_eight, 0.5))
+ cr.set_source_rgba(
+ fg_color['red'], fg_color['green'], fg_color['blue'], 0.5
+ )
cr.move_to(self._box_rect.x + 1, y)
cr.line_to(self._box_rect.width + self._box_rect.x, y)
cr.stroke()
mx, my = self.get_pointer()
- # Arrows
+ # Draw the Arrows
arrow_y = self._box_rect.y + self._box_rect.height / 2 - 5
- ## left arrow
- self.style.paint_arrow(self.window, self.state, gtk.SHADOW_IN,
- None, self, '', gtk.ARROW_LEFT, True,
- self._box_rect.x - 15,
- arrow_y,
- 8, 10)
-
- ## right arrow
- self.style.paint_arrow(self.window, self.state, gtk.SHADOW_IN,
- None, self, '', gtk.ARROW_RIGHT, True,
- self._box_rect.x + self._box_rect.width + 9,
- arrow_y,
- 8, 10)
-
- # Focus rect
+ ## Draw the left arrow
+ self.style.paint_arrow(
+ self.window, self.state, gtk.SHADOW_IN,
+ None, self, '', gtk.ARROW_LEFT, True,
+ self._box_rect.x - 15, arrow_y,
+ 8, 10
+ )
+
+ ## Draw the right arrow
+ self.style.paint_arrow(
+ self.window, self.state, gtk.SHADOW_IN,
+ None, self, '', gtk.ARROW_RIGHT, True,
+ self._box_rect.x + self._box_rect.width + 9, arrow_y,
+ 8, 10
+ )
+
+ # Draw the focus rect
if self.get_property('has-focus'):
- self.style.paint_focus(self.window, self.state, None, self, '',
- 1,
- 1,
- self.width - 2,
- self.height -2)
+ self.style.paint_focus(
+ self.window, self.state, None, self, '',
+ 1, 1,
+ self.width - 2, self.height -2
+ )
def do_key_press_event(self, event):
if gtk.gdk.keyval_name(event.keyval) == 'Right':
+ # Control+right - go to next month
if event.state & gtk.gdk.CONTROL_MASK:
- # Control+right - go to next month
month = (self.value.month % 12) + 1
year = self.value.year + (self.value.month) / 12
self.select_month(month=month, year=year)
+ # Right - scroll right
else:
self.scroll(gtk.gdk.SCROLL_RIGHT)
+
if gtk.gdk.keyval_name(event.keyval) == 'Left':
+ # Control+left - go to prev month
if event.state & gtk.gdk.CONTROL_MASK:
- # Control+left - go to prev month
year = self.value.year - int(not self.value.month - 1)
month = self.value.month - 1 + (self.value.year - year) * 12
self.select_month(month=month, year=year)
+ # Left - scroll left
else:
self.scroll(gtk.gdk.SCROLL_LEFT)
- if gtk.gdk.keyval_name(event.keyval) == 'plus' or gtk.gdk.keyval_name(event.keyval) == 'KP_Add':
- # "+" - zoom in
+
+ # "+" - zoom in
+ if gtk.gdk.keyval_name(event.keyval) == 'plus' \
+ or gtk.gdk.keyval_name(event.keyval) == 'KP_Add':
self.display_days -= 2
- if gtk.gdk.keyval_name(event.keyval) == 'minus' or gtk.gdk.keyval_name(event.keyval) == 'KP_Subtract':
- # "-" - zoom out
+ # "-" - zoom out
+ if gtk.gdk.keyval_name(event.keyval) == 'minus' or \
+ gtk.gdk.keyval_name(event.keyval) == 'KP_Subtract':
self.display_days += 2
+ # Home - go to Today
if gtk.gdk.keyval_name(event.keyval) == 'Home':
- # Home - go to Today
self.value = datetime.date.today()
self._value_changed()
+ # PageUp
if gtk.gdk.keyval_name(event.keyval) == 'Page_Up':
- # PageUp
- self.set_position(self.position - self.display_days)
+ self.set_position(self._position - self.display_days)
self.move(self._box_rect.width / 2)
+ # PageDow
if gtk.gdk.keyval_name(event.keyval) == 'Page_Down':
- # PageDow
- self.set_position(self.position + self.display_days)
+ self.set_position(self._position + self.display_days)
self.move(self._box_rect.width / 2)
- self.queue_draw_area(0, 0, self.allocation.width, self.allocation.height)
- print gtk.gdk.keyval_name(event.keyval)
+ self.queue_draw_area(
+ 0, 0, self.allocation.width, self.allocation.height
+ )
+
+ if self.debug:
+ print gtk.gdk.keyval_name(event.keyval)
def do_button_release_event(self, event):
+ # Get the mouse position and set focus to the wiget
mx, my = self.get_pointer()
self.drag = False
+
+ # Released the click with the mouse left buttom
if event.button == 1:
self._pressed = False
# Stop the autoscroll trigger timer
if self._timer:
gobject.source_remove(self._timer)
self._timer = None
+ # Released from the main box area
if mx > self._box_rect.x and \
mx < self._box_rect.width + self._box_rect.x:
+ # The user didn't dragged the timeline
if not self._dragged:
self.move(mx - self._div_width / 2)
- gobject.timeout_add(self._scroll_delay, self._center_selection)
+ gobject.timeout_add(
+ self._scroll_delay, self._center_selection
+ )
if mx < self._box_rect.x or \
mx > self._box_rect.x + self._box_rect.width or \
my > self._box_rect.y + self._box_rect.height:
@@ -442,23 +520,32 @@ class Timeline(gtk.DrawingArea):
return False
def do_button_press_event(self, event):
+ # Get the mouse position and set focus to the wiget
mx, my = self.get_pointer()
self.grab_focus()
+
# Stop the autoscroll trigger timer
if self._timer:
gobject.source_remove(self._timer)
self._timer = None
+
+ # Clicked with the mouse left buttom
if event.button == 1:
+ # Clicked on the left arrow
if mx < self._box_rect.x:
self.scroll(gtk.gdk.SCROLL_LEFT)
# Start the autoscroll trigger timer
- self._timer = gobject.timeout_add(500, self.auto_scroll,
- gtk.gdk.SCROLL_LEFT)
+ self._timer = gobject.timeout_add(
+ 500, self.auto_scroll, gtk.gdk.SCROLL_LEFT
+ )
+ # Clicked on the right arrow
elif mx > self._box_rect.width + self._box_rect.x:
self.scroll(gtk.gdk.SCROLL_RIGHT)
# Start the autoscroll trigger timer
- self._timer = gobject.timeout_add(500, self.auto_scroll,
- gtk.gdk.SCROLL_RIGHT)
+ self._timer = gobject.timeout_add(
+ 500, self.auto_scroll, gtk.gdk.SCROLL_RIGHT
+ )
+ # Clicked on the main box area
elif mx > self._box_rect.x and \
mx < self._box_rect.width + self._box_rect.x:
self._pressed = True
@@ -472,7 +559,10 @@ class Timeline(gtk.DrawingArea):
pos_ = self._get_mouse_position()
if pos_ != self._clicked_position or self._dragged:
self._dragged = True
- self.set_position((self.display_days / 2) + (pos_ - self._clicked_position), True)
+ self.set_position(
+ (self.display_days / 2) + (pos_ - self._clicked_position),
+ True
+ )
else:
self._dragged = False
else:
@@ -481,12 +571,24 @@ class Timeline(gtk.DrawingArea):
mx > self._box_rect.x + self._box_rect.width or \
my > self._box_rect.y + self._box_rect.height:
self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
- elif my > self._box_rect.y - self._bullet_radius / 3 + (self._box_rect.height - self._bullet_radius) / 2 and \
- my < self._box_rect.y + self._bullet_radius / 3 + (self._box_rect.height / 2) + self._bullet_radius:
- if self._mindex != int((mx - self._box_rect.x) / self._div_width):
- self._mindex = int((mx - self._box_rect.x) / self._div_width)
- if self._mindex > -1 and self._mindex < self.DIVS[self._type] and self._bullets[self._mindex]:
- gobject.timeout_add(100, self.set_tooltip, self._bullets[self._mindex].tooltip)
+ elif my > self._box_rect.y - self._bullet_radius / 3 + \
+ (self._box_rect.height - self._bullet_radius) / 2 and \
+ my < self._box_rect.y + self._bullet_radius / 3 + \
+ (self._box_rect.height / 2) + self._bullet_radius:
+ if self._mindex != int(
+ (mx - self._box_rect.x) / self._div_width
+ ):
+ self._mindex = int(
+ (mx - self._box_rect.x) / self._div_width
+ )
+ if self._mindex > -1 and \
+ self._mindex < self.DIVS[self._type] and \
+ self._bullets[self._mindex]:
+ gobject.timeout_add(
+ 100,
+ self.set_tooltip,
+ self._bullets[self._mindex].tooltip
+ )
else:
self.set_tooltip_text(None)
self.window.set_cursor(None)
@@ -540,6 +642,8 @@ class Timeline(gtk.DrawingArea):
self._box_rect.y = 6
self._box_rect.width = allocation.width - self._box_rect.x * 2
self._box_rect.height = allocation.height - 33
+ if self._box_rect.height < 0:
+ self._box_rect.height = 0
# Set Bullet radius
if self._div_width - self._div_width / 4 > self._box_rect.height / 2:
self._bullet_radius = (self._box_rect.height / 2) / 2
@@ -551,31 +655,33 @@ class Timeline(gtk.DrawingArea):
def _dist_dates(self, first=None):
""" Calculate dates for visible positions """
if not first:
+ # Define the first day if not provided
selected = self.value
if self._type == self.WEEK and selected.weekday() != 0:
selected -= datetime.timedelta(days=selected.weekday())
if self._type == self.DAY:
- first = selected - datetime.timedelta(days=self.position)
+ first = selected - datetime.timedelta(days=self._position)
elif self._type == self.WEEK:
- first = selected - datetime.timedelta(days=self.position * 7)
+ first = selected - datetime.timedelta(days=self._position * 7)
elif self._type == self.MONTH:
- month = (selected.month - self.position) % 12
- year = selected.year + (selected.month - self.position) // 12
+ month = (selected.month - self._position) % 12
+ year = selected.year + (selected.month - self._position) // 12
if not month:
month = 12
year -= 1
first = selected.replace(month=month, year=year)
elif self._type == self.YEAR:
- first = selected.replace(year=selected.year - self.position)
+ first = selected.replace(year=selected.year - self._position)
+ # Define the day and create the bullet object for each visible position
if self._type == self.DAY:
for i in range(self._display_days + 1):
self._dates[i] = first + datetime.timedelta(days=i)
- self._bullets[i] = self._bullet_func(self._dates[i])
+ self._bullets[i] = self._bullet_func(self._dates[i], self._type)
elif self._type == self.WEEK:
for i in range(self._display_days + 1):
self._dates[i] = first + datetime.timedelta(days=i * 7)
- self._bullets[i] = self._bullet_func(self._dates[i])
+ self._bullets[i] = self._bullet_func(self._dates[i], self._type)
elif self._type == self.MONTH:
for i in range(self._display_days + 1):
month = (first.month + i) % 12
@@ -584,13 +690,13 @@ class Timeline(gtk.DrawingArea):
month = 12
year -= 1
self._dates[i] = first.replace(day=1, month=month, year=year)
- self._bullets[i] = self._bullet_func(self._dates[i])
+ self._bullets[i] = self._bullet_func(self._dates[i], self._type)
elif self._type == self.YEAR:
for i in range(self._display_days + 1):
- self._dates[i] = first.replace(day=1, month=1,
- year=first.year + i)
- self._bullets[i] = self._bullet_func(self._dates[i])
-
+ self._dates[i] = first.replace(
+ day=1, month=1, year=first.year + i
+ )
+ self._bullets[i] = self._bullet_func(self._dates[i], self._type)
def scroll(self, direction, redraw=True):
""" Scroll the timeline widget
@@ -604,10 +710,10 @@ class Timeline(gtk.DrawingArea):
Return True to be used in gobject.timeout_add()
"""
if direction == gtk.gdk.SCROLL_LEFT:
- self.set_position(self.position + 1, redraw)
+ self.set_position(self._position + 1, redraw)
self.emit('scroll', direction)
elif direction == gtk.gdk.SCROLL_RIGHT:
- self.set_position(self.position - 1, redraw)
+ self.set_position(self._position - 1, redraw)
self.emit('scroll', direction)
else:
raise ValueError, direction
@@ -626,52 +732,58 @@ class Timeline(gtk.DrawingArea):
Return False to run only one time when used in
gobject.timeout_add()
"""
- self._timer = gobject.timeout_add(self._scroll_delay,
- self.scroll,
- direction, redraw)
+ self._timer = gobject.timeout_add(
+ self._scroll_delay, self.scroll, direction, redraw
+ )
return False
def _center_selection(self):
- if self.position > (self._display_days - 1) / 2:
- self.set_position(self.position - 1, True)
- elif self.position < (self._display_days - 1) / 2:
- self.set_position(self.position + 1, True)
+ if self._position > (self._display_days - 1) / 2:
+ self.set_position(self._position - 1, True)
+ elif self._position < (self._display_days - 1) / 2:
+ self.set_position(self._position + 1, True)
- if self.position == (self._display_days - 1) / 2:
- self.value = self._dates[self.position]
+ if self._position == (self._display_days - 1) / 2:
+ self.value = self._dates[self._position]
self._dist_dates()
self._value_changed()
- return self.position != (self._display_days - 1) / 2
+ return self._position != (self._display_days - 1) / 2
def move(self, pos, update=True, redraw=True):
- position_old = self.position
- self.position = round((pos - self._box_rect.x) / self._div_width)
- x = self.position * self._div_width + self._box_rect.x
+ position_old = self._position
+ self._position = round((pos - self._box_rect.x) / self._div_width)
+ x = self._position * self._div_width + self._box_rect.x
if pos > x + self._div_width / 2:
- self.position += 1
+ self._position += 1
x += self._div_width
- self.queue_draw_area(0, 0,
- self.allocation.width, self.allocation.height)
+ self.queue_draw_area(
+ 0, 0, self.allocation.width, self.allocation.height
+ )
if self.debug :
if not self._dragged:
- print "Timeline.position: ", self.position
+ print "Timeline.position: ", self._position
if update:
# Update self.value
- if self.position < 0 or self.position > self._display_days - 1:
+ if self._position < 0 or self._position > self._display_days - 1:
return
- self.value = self._dates[self.position]
+ self.value = self._dates[self._position]
self._dist_dates()
self._value_changed()
- return position_old, self.position
+ return position_old, self._position
+ def get_position(self):
+ return int(self._position)
+
def set_position(self, pos, redraw=True):
- self.position = round(pos)
+ self._position = round(pos)
x = pos * self._div_width + self._box_rect.x
self.move(x, False, redraw)
self._dist_dates()
- return self.position
+ return int(self._position)
+
+ position = property(get_position, set_position)
def get_start_date(self):
return self.start_date
@@ -686,8 +798,10 @@ class Timeline(gtk.DrawingArea):
days_old = self._display_days
if days < 7:
days = 7
+ warnings.warn('Using the minimum allowed value: 7', RuntimeWarning)
elif days > 61:
days = 61
+ warnings.warn('Using the maximum allowed value: 61', RuntimeWarning)
if days == days_old:
return
self._display_days = days
@@ -695,8 +809,9 @@ class Timeline(gtk.DrawingArea):
# Set timeline subdivisions size
self.on_size_allocate(self, self.allocation)
self._center_selection()
- self.queue_draw_area(0, 0, self.allocation.width,
- self.allocation.height)
+ self.queue_draw_area(
+ 0, 0, self.allocation.width, self.allocation.height
+ )
display_days = property(get_display_days, set_display_days)
def get_type(self):
@@ -705,12 +820,15 @@ class Timeline(gtk.DrawingArea):
"""
return self._type
- def set_type(self, type):
- self._type = type
+ def set_type(self, display_type):
+ if display_type not in (DAY, WEEK, MONTH, YEAR):
+ raise ValueError
+ self._type = display_type
self._display_days = self.DIVS[self._type]
self._dist_dates()
- self.queue_draw_area(0, 0, self.allocation.width,
- self.allocation.height)
+ self.queue_draw_area(
+ 0, 0, self.allocation.width, self.allocation.height
+ )
def get_interval(self):
return self._interval
@@ -741,11 +859,14 @@ class Timeline(gtk.DrawingArea):
self._value_changed()
def set_bullet_function(self, func):
+ """
+ Set the function to be used to create the bullet object for
+ a given date.
+ """
self._bullet_func = func
-def bullet_cb(date):
- if debug:
- print date.day
+def bullet_cb(date, display_type):
+ #print date, display_type
bullets = []
@@ -755,30 +876,20 @@ def bullet_cb(date):
# date=None, amountDue=None, estimated=False, status=0,
# overthreshold=False, multi=False, tooltip=''
- if date == today:
- # return a multi-record bullet
- return Bullet(date, 50, False, [1,0], False, True, 'Tooltip')
- elif date == yesterday:
- return Bullet(date, 200, True, [0,1], True, True, 'Yep. This is a tooltip')
- elif date == tomorrow:
- return Bullet(date, 20, True, [0], False, False, 'What? Ah, tooltip...')
-
- return None
+ if date == today - datetime.timedelta(days=3):
+ return Bullet(date, 200, False, Bullet.PAID, False, True, 'PAID')
+ elif date == today - datetime.timedelta(days=2):
+ return Bullet(date, 200, False, Bullet.OVERDUE, False, True, 'OVERDUE')
+ elif date == today - datetime.timedelta(days=1):
+ return Bullet(date, 200, False, Bullet.OVERDUE | Bullet.PAID, False, True, 'OVERDUE and PAID')
+ elif date == today:
+ return Bullet(date, 50, False, Bullet.TO_BE_PAID, False, True, 'TO_BE_PAID')
+ elif date == today + datetime.timedelta(days=1):
+ return Bullet(date, 20, False, Bullet.TO_BE_PAID | Bullet.PAID, False, True, 'TO_BE_PAID and PAID')
- """
- if date == datetime.date(2008, 9, 10):
- return Bullet(today, 50, False, 1, False, False, 'Tooltip')
- elif date == datetime.date(2008, 9, 20):
- return Bullet(date, 200, False, -1, True, True, 'Another tooltip')
- elif date == datetime.date(2008, 9, 29):
- return Bullet(date, 200, False, 1, True, False, 'Yep. This is a tooltip')
- elif date == datetime.date(2008, 10, 2):
- return Bullet(date, 20, True, 0, False, False, 'What? Ah, tooltip...')
- elif date == datetime.date(2008, 10, 19):
- return Bullet(date, 700, False, 0, True, False, 'Do you really want more tooltip?')
return None
- """
+
if __name__ == '__main__':
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]