From: <jb...@us...> - 2010-01-24 02:02:56
|
Revision: 498 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=498&view=rev Author: jblance Date: 2010-01-24 00:21:23 +0000 (Sun, 24 Jan 2010) Log Message: ----------- Fix for trac bug 32 - manual entry broken, updated calendar code to select date in entry, moved calendar gui into separate file, greyed out uneditable items on edit record screen, fixed utc and local date_time fields for manual entry Modified Paths: -------------- pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/glade/pytrainer.glade pytrainer/trunk/pytrainer/gui/windowcalendar.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/lib/date.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Added Paths: ----------- pytrainer/trunk/glade/calendar.glade Added: pytrainer/trunk/glade/calendar.glade =================================================================== --- pytrainer/trunk/glade/calendar.glade (rev 0) +++ pytrainer/trunk/glade/calendar.glade 2010-01-24 00:21:23 UTC (rev 498) @@ -0,0 +1,128 @@ +<?xml version="1.0"?> +<glade-interface> + <!-- interface-requires gtk+ 2.16 --> + <!-- interface-naming-policy toplevel-contextual --> +<widget class="GtkWindow" id="calendardialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Calendar</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="icon">logo_mini.png</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <signal name="destroy" handler="gtk_main_quit" last_modification_time="Mon, 03 Apr 2006 18:04:31 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkCalendar" id="calendar"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="display_options">GTK_CALENDAR_SHOW_HEADING|GTK_CALENDAR_SHOW_DAY_NAMES</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHSeparator" id="hseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="label29"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button9"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_cancel_clicked" last_modification_time="Mon, 03 Apr 2006 18:10:09 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button8"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_accept_clicked" last_modification_time="Mon, 03 Apr 2006 18:09:48 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> +</glade-interface> Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/glade/newrecord.glade 2010-01-24 00:21:23 UTC (rev 498) @@ -179,7 +179,7 @@ </packing> </child> <child> - <widget class="GtkFrame" id="frame24"> + <widget class="GtkFrame" id="frameGeneral"> <property name="visible">True</property> <property name="border_width">4</property> <property name="label_xalign">0</property> @@ -248,6 +248,7 @@ <property name="adjustment">0 0 23 1 2 2</property> <property name="climb_rate">1</property> <property name="numeric">True</property> + <property name="wrap">True</property> </widget> <packing> <property name="expand">False</property> @@ -270,9 +271,10 @@ <property name="width_request">47</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="adjustment">0 0 59 1 2 2</property> + <property name="adjustment">0 0 59 2 2 2</property> <property name="climb_rate">1</property> <property name="numeric">True</property> + <property name="wrap">True</property> </widget> <packing> <property name="expand">False</property> @@ -297,6 +299,7 @@ <property name="can_focus">True</property> <property name="adjustment">0 0 59 1 2 2</property> <property name="climb_rate">1</property> + <property name="wrap">True</property> </widget> <packing> <property name="expand">False</property> @@ -432,8 +435,8 @@ <widget class="GtkEntry" id="rcd_time"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="editable">False</property> <property name="width_chars">10</property> + <property name="text" translatable="yes">12:00:00</property> </widget> <packing> <property name="left_attach">3</property> @@ -472,7 +475,7 @@ </packing> </child> <child> - <widget class="GtkFrame" id="Velocity"> + <widget class="GtkFrame" id="frameVelocity"> <property name="visible">True</property> <property name="border_width">5</property> <property name="label_xalign">0</property> Modified: pytrainer/trunk/glade/pytrainer.glade =================================================================== --- pytrainer/trunk/glade/pytrainer.glade 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/glade/pytrainer.glade 2010-01-24 00:21:23 UTC (rev 498) @@ -8576,130 +8576,6 @@ </child> </widget> -<widget class="GtkWindow" id="calendardialog"> - <property name="visible">True</property> - <property name="title" translatable="yes">Calendar</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="icon">logo_mini.png</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - <signal name="destroy" handler="gtk_main_quit" last_modification_time="Mon, 03 Apr 2006 18:04:31 GMT"/> - - <child> - <widget class="GtkVBox" id="vbox6"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkCalendar" id="calendar"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="display_options">GTK_CALENDAR_SHOW_HEADING|GTK_CALENDAR_SHOW_DAY_NAMES</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHSeparator" id="hseparator1"> - <property name="visible">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox6"> - <property name="border_width">3</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">5</property> - - <child> - <widget class="GtkLabel" id="label29"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button9"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_cancel_clicked" last_modification_time="Mon, 03 Apr 2006 18:10:09 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button8"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-ok</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <signal name="clicked" handler="on_accept_clicked" last_modification_time="Mon, 03 Apr 2006 18:09:48 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - <widget class="GtkFileChooserDialog" id="filechooserdialog"> <property name="border_width">5</property> <property name="visible">True</property> Modified: pytrainer/trunk/pytrainer/gui/windowcalendar.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowcalendar.py 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/pytrainer/gui/windowcalendar.py 2010-01-24 00:21:23 UTC (rev 498) @@ -19,12 +19,19 @@ from SimpleGladeApp import SimpleGladeApp class WindowCalendar(SimpleGladeApp): - def __init__(self, data_path = None, parent = None): + def __init__(self, data_path = None, parent = None, date = None): self.parent = parent - glade_path="glade/pytrainer.glade" + glade_path="glade/calendar.glade" root = "calendardialog" domain = None SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) + if date is not None: + try: + year, month, day = date.split("-") + self.calendar.select_month( int(month)-1, int(year) ) + self.calendar.select_day( int(day) ) + except: + pass def on_accept_clicked(self,widget): date = self.calendar.get_date() Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-01-24 00:21:23 UTC (rev 498) @@ -249,7 +249,7 @@ else: self.recordview.set_sensitive(0) logging.debug(">>") - + def actualize_recordgraph(self,record_list,laps=None): logging.debug(">>") if len(record_list)>0: @@ -321,6 +321,7 @@ beats = 0 maxbeats = 0 maxspeed = 0 + average = 0 maxpace = "0.00" pace = "0.00" for record in record_list: @@ -341,8 +342,8 @@ if tbeats > 0: tbeats = tbeats/(timeinseconds/60/60) - - average = distance/(timeinseconds/60/60) + if distance > 0: + average = distance/(timeinseconds/60/60) if maxspeed > 0: maxpace = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) if average > 0: @@ -993,6 +994,7 @@ for i in record_list: #Get lap info #TODO refactor to use a database table gpxfile = "%s/%s.gpx" %(self.gpxDir, i[8]) + laps = None if os.path.isfile(gpxfile): gpx = Gpx(self.data_path,gpxfile) laps = gpx.getLaps() #(elapsedTime, lat, lon, calories, distance) @@ -1012,25 +1014,26 @@ 2, str(i[0]), 3, str(i[2]) ) - for lap in laps: - lapNumber = "%s%d" % ( _("lap"), (laps.index(lap)+1) ) - distance = "%0.2f" % (float(lap[4]) / 1000.0) - timeHours = int(float(lap[0]) / 3600) - timeMin = int((float(lap[0]) / 3600.0 - timeHours) * 60) - timeSec = float(lap[0]) - (timeHours * 3600) - (timeMin * 60) - if timeHours > 0: - duration = "%d%s%02d%s%02d%s" % (timeHours, _("h"), timeMin, _("m"), timeSec, _("s")) - else: - duration = "%2d%s%02d%s" % (timeMin, _("m"), timeSec, _("s")) + if laps is not None: + for lap in laps: + lapNumber = "%s%d" % ( _("lap"), (laps.index(lap)+1) ) + distance = "%0.2f" % (float(lap[4]) / 1000.0) + timeHours = int(float(lap[0]) / 3600) + timeMin = int((float(lap[0]) / 3600.0 - timeHours) * 60) + timeSec = float(lap[0]) - (timeHours * 3600) - (timeMin * 60) + if timeHours > 0: + duration = "%d%s%02d%s%02d%s" % (timeHours, _("h"), timeMin, _("m"), timeSec, _("s")) + else: + duration = "%2d%s%02d%s" % (timeMin, _("m"), timeSec, _("s")) - child_iter = store.append(iter) - store.set ( - child_iter, - 0, int(i[8]), - 1, lapNumber, - 2, duration, - 3, distance - ) + child_iter = store.append(iter) + store.set ( + child_iter, + 0, int(i[8]), + 1, lapNumber, + 2, duration, + 3, distance + ) self.recordTreeView.set_model(store) if iterOne: self.recordTreeView.get_selection().select_iter(iterOne) Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-01-24 00:21:23 UTC (rev 498) @@ -16,11 +16,14 @@ #along with this program; if not, write to the Free Software #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +import os import logging from SimpleGladeApp import SimpleGladeApp from windowcalendar import WindowCalendar from filechooser import FileChooser +from pytrainer.lib.date import Date import dateutil.parser +from dateutil.tz import * # for tzutc() class WindowRecord(SimpleGladeApp): def __init__(self, data_path = None, listSport = None, parent = None, date = None, title=None, distance=None, time=None, upositive=None, unegative=None, bpm=None, calories=None, comment=None, windowTitle=None): @@ -47,7 +50,7 @@ "rcd_maxbeats", "rcd_pace", "rcd_maxpace", - "rcd_maxvel" + "rcd_maxvel", ] self.listSport = {} for i in listSport: @@ -95,12 +98,20 @@ if self.mode == "newrecord": logging.debug('Track data: '+str(list_options)) if list_options["rcd_gpxfile"] != "": - logging.info('Adding new activity based on GPX file') + logging.info('Adding new activity based on GPX file') trackSummary=(list_options["rcd_sport"],"","") self.parent.insertNewRecord(list_options["rcd_gpxfile"], trackSummary) else: logging.info('Adding new activity based on provided data') - list_options["date_time_utc"] = list_options["rcd_date"] + "T12:00:00Z" # hardcoded + #Manual entry, calculate time info + record_time = self.rcd_time.get_text() + record_date = self.rcd_date.get_text() + localtz = Date().getLocalTZ() + date = dateutil.parser.parse(record_date+" "+record_time+" "+localtz) + local_date = str(date) + utc_date = date.astimezone(tzutc()).strftime("%Y-%m-%dT%H:%M:%SZ") + list_options["date_time_utc"] = utc_date + list_options["date_time_local"] = local_date self.parent.insertRecord(list_options) elif self.mode == "editrecord": self.parent.updateRecord(list_options, self.id_record) @@ -115,7 +126,7 @@ self.quit() def on_calendar_clicked(self,widget): - calendardialog = WindowCalendar(self.data_path,self) + calendardialog = WindowCalendar(self.data_path,self, date=self.rcd_date.get_text()) calendardialog.run() def setDate(self,date): @@ -270,5 +281,8 @@ def on_calculatevalues_clicked(self,widget): gpxfile = self.rcd_gpxfile.get_text() - self.parent.actualize_fromgpx(gpxfile) + if os.path.isfile(gpxfile): + self.frameGeneral.set_sensitive(0) + self.frameVelocity.set_sensitive(0) + self.parent.actualize_fromgpx(gpxfile) Modified: pytrainer/trunk/pytrainer/lib/date.py =================================================================== --- pytrainer/trunk/pytrainer/lib/date.py 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/pytrainer/lib/date.py 2010-01-24 00:21:23 UTC (rev 498) @@ -21,6 +21,7 @@ import time import datetime import calendar +import datetime import dateutil.parser from dateutil.tz import * # for tzutc() @@ -29,6 +30,8 @@ self.calendar = calendar def second2time(self,seconds): + if not seconds: + return 0,0,0 time_in_hour = seconds/3600.0 hour = int(time_in_hour) min = int((time_in_hour-hour)*60) @@ -38,8 +41,12 @@ def time2second(self,time): hour,min,sec = time - return sec+(min*60)+(hour*3600) + return int(sec)+(int(min)*60)+(int(hour)*3600) + def getLocalTZ(self): + ''' Returns string representation of local timezone''' + return datetime.datetime.now(tzlocal()).tzname() + def getDate(self): #hack for the gtk calendar widget if self.calendar is not None: Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/pytrainer/main.py 2010-01-24 00:21:23 UTC (rev 498) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.1_pre-release-svn#492" + self.version ="1.7.1_pre-release-svn#498" self.DB_version = 1 self.date = Date() # Checking profile Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-01-23 17:36:32 UTC (rev 497) +++ pytrainer/trunk/pytrainer/record.py 2010-01-24 00:21:23 UTC (rev 498) @@ -61,6 +61,8 @@ self.recordwindow = WindowRecord(self.data_path, list_sport,self, None, windowTitle=_("Edit Entry")) if os.path.isfile(gpxfile): self.recordwindow.rcd_gpxfile.set_text(gpxfile) + self.recordwindow.frameGeneral.set_sensitive(0) #Currently record values not changed if a GPX file is present + self.recordwindow.frameVelocity.set_sensitive(0) #Greying out options to indicate this to user logging.debug('sending record info to window') self.recordwindow.setValues(record[0]) logging.debug('launching window') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |