27
31
from pytrainer.lib.date import Date
28
32
from pytrainer.lib.system import checkConf
29
33
from pytrainer.lib.xmlUtils import XMLParser
34
from pytrainer.lib.gpx import Gpx
31
35
from pytrainer.lib.unitsconversor import *
33
37
class Main(SimpleGladeApp):
34
def __init__(self, data_path = None, parent = None, version = None):
38
def __init__(self, data_path = None, parent = None, version = None, gpxDir = None):
35
39
def url_hook(dialog, url):
36
40
pytrainer.lib.webUtils.open_url_in_browser(url)
37
41
# Available in PyGTK 2.6 and above
47
51
self.popup = PopupMenu(data_path,self)
49
53
self.activeSport = None
57
self.testimport = self.parent.testimport
52
58
self.menublocking = 0
53
59
self.selected_view="day"
54
60
self.window1.set_title ("pyTrainer %s" % self.version)
55
61
self.record_list = []
56
62
#create the columns for the listdayrecord
57
column_names=[_("id"),_("Sport"),_("Kilometer")]
63
column_names=[_("id"),_("Start"), _("Sport"),_("Kilometer")]
58
64
self.create_treeview(self.recordTreeView,column_names)
59
65
#create the columns for the listarea
60
66
column_names=[_("id"),_("Title"),_("Date"),_("Distance"),_("Sport"),_("Time"),_("Beats"),_("Average"),("Calories")]
70
76
self.showAllRecordTreeViewColumns()
71
77
self.allRecordTreeView.set_search_column(1)
72
78
self.notebook.set_current_page(1)
80
#Disable import menu item unless specified on startup
81
if not self.testimport:
82
self.menu_importdata.set_sensitive(0)
74
84
def _createXmlListView(self,file):
75
85
menufile = XMLParser(file)
94
104
button = gtk.MenuItem(plugin[0])
95
105
button.set_name(plugin[1])
96
106
button.connect("activate", self.parent.runPlugin, plugin[1])
97
self.menuitem1_menu.insert(button,2)
107
self.menuitem1_menu.insert(button,3)
98
108
self.menuitem1_menu.show_all()
100
110
def addExtension(self,extension):
112
122
self.parent.runExtension(extension,id)
114
124
def createGraphs(self,RecordGraph,DayGraph,WeekGraph, MonthGraph,YearGraph,HeartRateGraph):
115
self.drawarearecord = RecordGraph(self.record_vbox, self.window1, self.record_combovalue, self.record_combovalue2)
125
self.drawarearecord = RecordGraph(self.record_vbox, self.window1, self.record_combovalue, self.record_combovalue2, self.btnShowLaps)
116
126
self.drawareaheartrate = HeartRateGraph(self.heartrate_vbox, self.window1, self.heartrate_vbox2)
117
127
#self.drawareaday = DayGraph(self.day_vbox, self.day_combovalue)
118
128
self.day_vbox.hide()
187
197
pace = self.parseFloat(record_list[14]) #to review
188
198
maxspeed = self.parseFloat(record_list[12]) #to review
189
199
maxpace = self.parseFloat(record_list[13])
201
#Get datetime from DB, use local time if available otherwise use date_time_utc and create a local datetime...
202
#TODO get data from date_time_local and parse
203
date_time_local = record_list[17]
204
date_time_utc = record_list[16]
205
if date_time_local is not None: #Have a local time stored in DB
206
dateTime = dateutil.parser.parse(date_time_local)
207
else: #No local time in DB
208
tmpDateTime = dateutil.parser.parse(date_time_utc)
209
dateTime = tmpDateTime.astimezone(tzlocal()) #datetime with localtime offset (using value from OS)
210
recordDateTime = dateTime.strftime("%Y-%m-%d %H:%M:%S")
211
recordDate = dateTime.strftime("%x")
212
recordTime = dateTime.strftime("%X")
213
recordDateTimeOffset = dateTime.strftime("%z")
191
215
if configuration.getValue("pytraining","prf_us_system") == "True":
192
216
self.record_distance.set_text("%0.2f" %km2miles(distance))
207
231
self.record_maxpace.set_text("%0.2f" %maxpace)
209
233
self.record_sport.set_text(sport)
210
self.record_date.set_text(str(date))
234
#self.record_date.set_text(str(date))
235
self.record_date.set_text(recordDate)
236
self.record_time.set_text(recordTime)
211
237
hour,min,sec=self.parent.date.second2time(int(record_list[3]))
212
238
self.record_hour.set_text("%d" %hour)
213
239
self.record_minute.set_text("%02d" %min)
214
240
self.record_second.set_text("%02d" %sec)
215
241
self.record_calories.set_text("%0.0f" %calories)
242
#self.record_datetime.set_text(recordDateTime)
243
#self.record_datetime_offset.set_text(recordDateTimeOffset)
216
244
self.record_title.set_text(title)
217
245
buffer = self.record_comments.get_buffer()
218
246
start,end = buffer.get_bounds()
222
250
self.recordview.set_sensitive(0)
223
251
logging.debug(">>")
225
def actualize_recordgraph(self,record_list):
253
def actualize_recordgraph(self,record_list,laps=None):
226
254
logging.debug(">>")
227
255
if len(record_list)>0:
228
256
self.record_vbox.set_sensitive(1)
259
vboxChildren = self.record_vbox.get_children()
260
logging.debug('Vbox has %d children %s' % (len(vboxChildren), str(vboxChildren) ))
261
# ToDo: check why vertical container is shared
262
for child in vboxChildren:
263
#Remove all FigureCanvasGTK and NavigationToolbar2GTKAgg to stop double ups of graphs
264
if isinstance(child, matplotlib.backends.backend_gtkagg.FigureCanvasGTK) or isinstance(child, matplotlib.backends.backend_gtkagg.NavigationToolbar2GTKAgg):
265
logging.debug('Removing child: '+str(child))
266
self.record_vbox.remove(child)
230
267
self.record_vbox.set_sensitive(0)
231
268
#logging.debug("Going to draw "+str(record_list))
232
self.drawarearecord.drawgraph(record_list)
269
self.drawarearecord.drawgraph(record_list,laps)
233
270
logging.debug("<<")
235
272
def actualize_heartrategraph(self,record_list):
306
344
tbeats = tbeats/(timeinseconds/60/60)
308
average = distance/(timeinseconds/60/60)
346
average = distance/(timeinseconds/60/60)
310
348
maxpace = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60)
814
852
def on_hidemap_clicked(self,widget):
815
853
self.maparea.hide()
816
854
self.infoarea.show()
856
def on_btnShowLaps_toggled(self,widget):
858
self.parent.refreshGraphView(self.selected_view)
818
860
def on_day_combovalue_changed(self,widget):
819
861
logging.debug("--")
874
916
self.classicarea.hide()
875
917
self.parent.refreshWaypointView()
876
918
self.waypointarea.show()
920
def on_menu_importdata_activate(self,widget):
921
self.parent.importData()
878
923
def on_extensions_activate(self,widget):
879
924
self.parent.editExtensions()
906
951
logging.debug("<<")
954
'''def actualize_recordTreeView(self, record_list):
957
store = gtk.ListStore(
963
for i in record_list:
964
iter = store.append()
968
if dateTime is not None:
969
localTime = dateutil.parser.parse(dateTime).strftime("%H:%M")
979
self.recordTreeView.set_model(store)
981
self.recordTreeView.get_selection().select_iter(iterOne)
983
#if len(record_list)>0:'''
909
985
def actualize_recordTreeView(self, record_list):
910
986
logging.debug(">>")
912
store = gtk.ListStore(
988
store = gtk.TreeStore(
989
gobject.TYPE_INT, #record_id
990
gobject.TYPE_STRING, #Time
991
gobject.TYPE_STRING, #Sport
992
gobject.TYPE_STRING, #Distance
917
994
for i in record_list:
918
iter = store.append()
995
#Get lap info #TODO refactor to use a database table
996
gpxfile = "%s/%s.gpx" %(self.gpxDir, i[8])
998
if os.path.isfile(gpxfile):
999
gpx = Gpx(self.data_path,gpxfile)
1000
laps = gpx.getLaps() #(elapsedTime, lat, lon, calories, distance)
1001
#print gpxfile, laps
1002
iter = store.append(None)
1006
if dateTime is not None:
1007
localTime = dateutil.parser.parse(dateTime).strftime("%H:%M")
1017
if laps is not None:
1019
lapNumber = "%s%d" % ( _("lap"), (laps.index(lap)+1) )
1020
distance = "%0.2f" % (float(lap[4]) / 1000.0)
1021
timeHours = int(float(lap[0]) / 3600)
1022
timeMin = int((float(lap[0]) / 3600.0 - timeHours) * 60)
1023
timeSec = float(lap[0]) - (timeHours * 3600) - (timeMin * 60)
1025
duration = "%d%s%02d%s%02d%s" % (timeHours, _("h"), timeMin, _("m"), timeSec, _("s"))
1027
duration = "%2d%s%02d%s" % (timeMin, _("m"), timeSec, _("s"))
1029
child_iter = store.append(iter)
927
1037
self.recordTreeView.set_model(store)
929
1039
self.recordTreeView.get_selection().select_iter(iterOne)