[hamster-applet] filtering by category and ability to change start/end dates.
- From: Toms Baugis <tbaugis src gnome org>
- To: svn-commits-list gnome org
- Subject: [hamster-applet] filtering by category and ability to change start/end dates.
- Date: Sun, 7 Jun 2009 11:21:50 -0400 (EDT)
commit 980ea11f790f308d1028d8b660868f9519991abc
Author: Toms Bauģis <toms baugis gmail com>
Date: Sun Jun 7 16:04:07 2009 +0100
filtering by category and ability to change start/end dates.
---
data/stats.ui | 166 ++++++++++++++++++++++++++++++++++++++++++++
hamster/stats.py | 202 +++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 320 insertions(+), 48 deletions(-)
diff --git a/data/stats.ui b/data/stats.ui
index a7ab03f..1fadf8d 100644
--- a/data/stats.ui
+++ b/data/stats.ui
@@ -378,4 +378,170 @@
<property name="visible">True</property>
<property name="pixbuf">art/stock_calendar-view-month.png</property>
</object>
+ <object class="GtkFileChooserDialog" id="save_report_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Save report - Time Tracker</property>
+ <property name="type_hint">normal</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">4</property>
+ <property name="row_spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="date_interval_label">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Date interval:</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Categories:</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xscale">0</property>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkAlignment" id="from_date_box">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes">to</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="to_date_box">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xscale">0</property>
+ <child>
+ <object class="GtkHBox" id="category_box">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">6</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="save_button">
+ <property name="label" translatable="yes">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">save_button</action-widget>
+ <action-widget response="0">cancel_button</action-widget>
+ </action-widgets>
+ </object>
</interface>
diff --git a/hamster/stats.py b/hamster/stats.py
index 8857b36..9d30320 100644
--- a/hamster/stats.py
+++ b/hamster/stats.py
@@ -22,19 +22,139 @@ import pygtk
pygtk.require('2.0')
import os
-import gtk
+import gtk, gobject
import pango
from hamster import dispatcher, storage, SHARED_DATA_DIR, stuff
from hamster import charting
from hamster.edit_activity import CustomFactController
+from hamster import reports, widgets
import webbrowser
import datetime as dt
import calendar
import time
+class ReportChooserDialog(gtk.Dialog):
+ __gsignals__ = {
+ # format, path, start_date, end_date
+ 'report-chosen': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
+ (gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
+ gobject.TYPE_PYOBJECT)),
+ 'report-chooser-closed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
+ }
+ def __init__(self):
+ gtk.Dialog.__init__(self)
+ ui = stuff.load_ui_file("stats.ui")
+ self.dialog = ui.get_object('save_report_dialog')
+
+ self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
+ self.dialog.set_current_folder(os.path.expanduser("~"))
+
+ self.filters = {}
+
+ filter = gtk.FileFilter()
+ filter.set_name(_("HTML Report"))
+ filter.add_mime_type("text/html")
+ filter.add_pattern("*.html")
+ filter.add_pattern("*.htm")
+ self.filters[filter] = "html"
+ self.dialog.add_filter(filter)
+
+ filter = gtk.FileFilter()
+ filter.set_name(_("Tab Separated Values (TSV)"))
+ filter.add_mime_type("text/plain")
+ filter.add_pattern("*.tsv")
+ filter.add_pattern("*.txt")
+ self.filters[filter] = "tsv"
+ self.dialog.add_filter(filter)
+
+ filter = gtk.FileFilter()
+ filter.set_name(_("XML"))
+ filter.add_mime_type("text/xml")
+ filter.add_pattern("*.xml")
+ self.filters[filter] = "xml"
+ self.dialog.add_filter(filter)
+
+ filter = gtk.FileFilter()
+ filter.set_name(_("iCal"))
+ filter.add_mime_type("text/calendar")
+ filter.add_pattern("*.ics")
+ self.filters[filter] = "ical"
+ self.dialog.add_filter(filter)
+
+ filter = gtk.FileFilter()
+ filter.set_name("All files")
+ filter.add_pattern("*")
+ self.dialog.add_filter(filter)
+
+ self.start_date = widgets.DateInput()
+ ui.get_object('from_date_box').add(self.start_date)
+ self.end_date = widgets.DateInput()
+ ui.get_object('to_date_box').add(self.end_date)
+
+ self.category_box = ui.get_object('category_box')
+
+ ui.get_object('save_button').connect("clicked", self.on_save_button_clicked)
+ ui.get_object('cancel_button').connect("clicked", self.on_cancel_button_clicked)
+
+
+ def show(self, start_date, end_date):
+ #set suggested name to something readable, replace backslashes with dots
+ #so the name is valid in linux
+ filename = "Time track %s - %s" % (start_date.strftime("%x").replace("/", "."),
+ end_date.strftime("%x").replace("/", "."))
+ self.dialog.set_current_name(filename)
+
+ self.start_date.set_date(start_date)
+ self.end_date.set_date(end_date)
+
+ #add unsorted category
+ button_all = gtk.RadioButton(None, _("All").encode("utf-8"))
+ button_all.value = None
+ button_all.set_active(True)
+ self.category_box.pack_start(button_all)
+
+ categories = storage.get_category_list()
+ for category in categories:
+ button = gtk.RadioButton(button_all, category['name'].encode("utf-8"))
+ button.value = category['id']
+ self.category_box.pack_start(button)
+
+
+ response = self.dialog.show_all()
+
+ def present(self):
+ self.dialog.present()
+
+ def on_save_button_clicked(self, widget):
+ path, format = None, None
+
+ format = "html"
+ if self.dialog.get_filter() in self.filters:
+ format = self.filters[self.dialog.get_filter()]
+ path = self.dialog.get_filename()
+
+ category = None
+ for button in self.category_box.get_children():
+ if button.get_active():
+ category = button.value
+ print category
+
+ # format, path, start_date, end_date
+ self.emit("report-chosen", format, path,
+ self.start_date.get_date().date(),
+ self.end_date.get_date().date(),
+ category)
+ self.dialog.destroy()
+
+
+ def on_cancel_button_clicked(self, widget):
+ self.emit("report-chooser-closed")
+ self.dialog.destroy()
+
class StatsViewer(object):
def __init__(self, parent = None):
self.parent = parent# determine if app shut shut down on close
@@ -117,20 +237,8 @@ class StatsViewer(object):
self._gui.connect_signals(self)
self.fact_tree.grab_focus()
-
- """
- # this will help when profiling!
- import gobject
- self.i = 0
- def redraw():
- self.do_graph()
- self.start_date -= dt.timedelta(7)
- self.end_date -= dt.timedelta(7)
- self.i +=1
- return self.i < 50
-
- gobject.timeout_add(400, redraw)
- """
+
+ self.report_chooser = None
self.do_graph()
def more_on_left(self):
@@ -552,23 +660,21 @@ class StatsViewer(object):
custom_fact = CustomFactController(self, selected_date)
custom_fact.show()
- def on_report_button_clicked(self, widget):
+ def init_report_dialog(self):
+ chooser = self.get_widget('save_report_dialog')
+ chooser.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
+ """
+ chooser.set
+
chooser = gtk.FileChooserDialog(title = _("Save report - Time Tracker"),
parent = None,
- action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE,
gtk.RESPONSE_OK))
-
+ """
chooser.set_current_folder(os.path.expanduser("~"))
- #set suggested name to something readable, replace backslashes with dots
- #so the name is valid in linux
- filename = "Time track %s - %s" % (self.start_date.strftime("%x").replace("/", "."),
- self.end_date.strftime("%x").replace("/", "."))
- chooser.set_current_name(filename)
-
filters = {}
filter = gtk.FileFilter()
@@ -606,36 +712,36 @@ class StatsViewer(object):
filter.add_pattern("*")
chooser.add_filter(filter)
+ def on_report_chosen(self, widget, format, path, start_date, end_date,
+ category):
+ self.report_chooser = None
- response = chooser.run()
- if response == gtk.RESPONSE_OK:
- format = "html"
- if chooser.get_filter() in filters:
- format = filters[chooser.get_filter()]
+ facts = storage.get_facts(start_date, end_date, category_id = category)
+ reports.simple(facts,
+ self.start_date,
+ self.end_date,
+ format,
+ path)
- from hamster import reports
- facts = storage.get_facts(self.start_date, self.end_date)
- path = chooser.get_filename()
-
- reports.simple(facts,
- self.start_date,
- self.end_date,
- format,
- path)
-
- if format == ("html"):
- webbrowser.open_new("file://%s" % path)
- else:
- gtk.show_uri(gtk.gdk.Screen(),
- "file://%s" % os.path.split(path)[0], 0L)
+ if format == ("html"):
+ webbrowser.open_new("file://%s" % path)
+ else:
+ gtk.show_uri(gtk.gdk.Screen(),
+ "file://%s" % os.path.split(path)[0], 0L)
- chooser.destroy()
+ def on_report_chooser_closed(self, widget):
+ self.report_chooser = None
- # supported types: HTML, CSV, XML
- #save_as.add
+ def on_report_button_clicked(self, widget):
+ if not self.report_chooser:
+ self.report_chooser = ReportChooserDialog()
+ self.report_chooser.connect("report-chosen", self.on_report_chosen)
+ self.report_chooser.connect("report-chooser-closed", self.on_report_chooser_closed)
+ self.report_chooser.show(self.start_date, self.end_date)
+ else:
+ self.report_chooser.present()
-
def after_activity_update(self, widget, renames):
self.do_graph()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]