[billreminder] Timeline widget will not support displaying multiple bills with different states on the same day. Fi



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]