From: <jb...@us...> - 2010-01-17 04:25:54
|
Revision: 483 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=483&view=rev Author: jblance Date: 2010-01-17 04:25:47 +0000 (Sun, 17 Jan 2010) Log Message: ----------- Added function to populate date_time_local and fix date if needed - does not update date_time_local for manaul entries. Also moved date parsing function to Date.py to remove duplication Modified Paths: -------------- pytrainer/trunk/import/file_garmintcxv1.py pytrainer/trunk/import/file_garmintcxv2.py pytrainer/trunk/import/file_garmintools.py pytrainer/trunk/import/file_gpxplus.py pytrainer/trunk/pytrainer/lib/date.py pytrainer/trunk/pytrainer/lib/ddbb.py pytrainer/trunk/pytrainer/lib/gpx.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/import/file_garmintcxv1.py =================================================================== --- pytrainer/trunk/import/file_garmintcxv1.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/import/file_garmintcxv1.py 2010-01-17 04:25:47 UTC (rev 483) @@ -20,11 +20,10 @@ import logging import os from lxml import etree -import dateutil.parser -from dateutil.tz import * # for tzutc() from pytrainer.lib.xmlUtils import XMLParser from pytrainer.lib.system import checkConf +from pytrainer.lib.date import Date #from pytrainer.gui.dialogs import fileChooserDialog, guiFlush class garmintcxv1(): @@ -132,20 +131,7 @@ return timeElement.text def getDateTime(self, time_): - # Time can be in multiple formats - # - zulu 2009-12-15T09:00Z - # - local ISO8601 2009-12-15T10:00+01:00 - if time_ is None or time_ == "": - return (None, None) - dateTime = dateutil.parser.parse(time_) - timezone = dateTime.tzname() - if timezone == 'UTC': #got a zulu time - local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) - else: - local_dateTime = dateTime #use datetime as supplied - utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset - #print utc_dateTime, local_dateTime - return (utc_dateTime,local_dateTime) + return Date().getDateTime(time_) def getGPXFile(self, ID): """ Modified: pytrainer/trunk/import/file_garmintcxv2.py =================================================================== --- pytrainer/trunk/import/file_garmintcxv2.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/import/file_garmintcxv2.py 2010-01-17 04:25:47 UTC (rev 483) @@ -20,8 +20,7 @@ import logging import os from lxml import etree -import dateutil.parser -from dateutil.tz import * # for tzutc() +from pytrainer.lib.date import Date from pytrainer.lib.xmlUtils import XMLParser from pytrainer.lib.system import checkConf @@ -137,20 +136,7 @@ return timeElement.text def getDateTime(self, time_): - # Time can be in multiple formats - # - zulu 2009-12-15T09:00Z - # - local ISO8601 2009-12-15T10:00+01:00 - if time_ is None or time_ == "": - return (None, None) - dateTime = dateutil.parser.parse(time_) - timezone = dateTime.tzname() - if timezone == 'UTC': #got a zulu time - local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) - else: - local_dateTime = dateTime #use datetime as supplied - utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset - #print utc_dateTime, local_dateTime - return (utc_dateTime,local_dateTime) + return Date().getDateTime(time_) def getGPXFile(self, ID): """ Modified: pytrainer/trunk/import/file_garmintools.py =================================================================== --- pytrainer/trunk/import/file_garmintools.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/import/file_garmintools.py 2010-01-17 04:25:47 UTC (rev 483) @@ -21,8 +21,7 @@ import os import StringIO from lxml import etree -import dateutil.parser -from dateutil.tz import * # for tzutc() +from pytrainer.lib.date import Date #from pytrainer.lib.xmlUtils import XMLParser #from pytrainer.gui.dialogs import fileChooserDialog, guiFlush @@ -84,20 +83,7 @@ return False def getDateTime(self, time_): - # Time can be in multiple formats - # - zulu 2009-12-15T09:00Z - # - local ISO8601 2009-12-15T10:00+01:00 - if time_ is None or time_ == "": - return (None, None) - dateTime = dateutil.parser.parse(time_) - timezone = dateTime.tzname() - if timezone == 'UTC': #got a zulu time - local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) - else: - local_dateTime = dateTime #use datetime as supplied - utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset - #print utc_dateTime, local_dateTime - return (utc_dateTime,local_dateTime) + return Date().getDateTime(time_) def inDatabase(self, tree, startTime): #comparing date and start time (sport may have been changed in DB after import) Modified: pytrainer/trunk/import/file_gpxplus.py =================================================================== --- pytrainer/trunk/import/file_gpxplus.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/import/file_gpxplus.py 2010-01-17 04:25:47 UTC (rev 483) @@ -21,8 +21,7 @@ import os #import StringIO from lxml import etree -import dateutil.parser -from dateutil.tz import * # for tzutc() +from pytrainer.lib.date import Date #from pytrainer.lib.xmlUtils import XMLParser #from pytrainer.gui.dialogs import fileChooserDialog, guiFlush @@ -81,20 +80,7 @@ return False def getDateTime(self, time_): - # Time can be in multiple formats - # - zulu 2009-12-15T09:00Z - # - local ISO8601 2009-12-15T10:00+01:00 - if time_ is None or time_ == "": - return (None, None) - dateTime = dateutil.parser.parse(time_) - timezone = dateTime.tzname() - if timezone == 'UTC': #got a zulu time - local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) - else: - local_dateTime = dateTime #use datetime as supplied - utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset - #print utc_dateTime, local_dateTime - return (utc_dateTime,local_dateTime) + return Date().getDateTime(time_) def inDatabase(self, tree, startTime): #comparing date and start time (sport may have been changed in DB after import) Modified: pytrainer/trunk/pytrainer/lib/date.py =================================================================== --- pytrainer/trunk/pytrainer/lib/date.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/pytrainer/lib/date.py 2010-01-17 04:25:47 UTC (rev 483) @@ -21,6 +21,8 @@ import time import datetime import calendar +import dateutil.parser +from dateutil.tz import * # for tzutc() class Date: def __init__(self, calendar=None): @@ -124,3 +126,17 @@ day = tm[2] return "%0.4d-%0.2d-%0.2d" %(year,month,day) + def getDateTime(self, time_): + # Time can be in multiple formats + # - zulu 2009-12-15T09:00Z + # - local ISO8601 2009-12-15T10:00+01:00 + dateTime = dateutil.parser.parse(time_) + timezone = dateTime.tzname() + if timezone == 'UTC': #got a zulu time + local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) + else: + local_dateTime = dateTime #use datetime as supplied + utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset + #print utc_dateTime, local_dateTime + return (utc_dateTime,local_dateTime) + Modified: pytrainer/trunk/pytrainer/lib/ddbb.py =================================================================== --- pytrainer/trunk/pytrainer/lib/ddbb.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/pytrainer/lib/ddbb.py 2010-01-17 04:25:47 UTC (rev 483) @@ -21,8 +21,9 @@ import logging import traceback -import commands +import commands, os from system import checkConf +from pytrainer.lib.date import Date class DDBB: def __init__(self, configuration): @@ -271,12 +272,16 @@ traceback.print_exc() exit(-1) + #Check Tables for entry in tablesList: if entry not in tablesDB: logging.warn('Table '+str(entry)+' does not exist in DB') self.ddbbObject.createTableDefault(entry,tablesList[entry]) else: self.ddbbObject.checkTable(entry,tablesList[entry]) + + #Run any functions to update or correct data + self.populate_date_time_local() logging.debug('<<') def createDatabaseBackup(self): @@ -289,3 +294,35 @@ logging.info('Database backup successfully created') logging.debug('<<') + def populate_date_time_local(self): + ''' Populate date_time_local and date from date_time_utc + only access records that date_time_local is NULL + using OS timezone to create local_time + + also updates date if date != local_time + ''' + logging.debug('--') + listOfRecords = self.ddbbObject.select("records","id_record,date,date_time_utc,date_time_local", "date_time_local is NULL") + logging.debug("Found %d records in DB without date_time_local field populated" % (len(listOfRecords) ) ) + for record in listOfRecords: + try: + gpxfile = self.conf.getValue("gpxdir")+"/%s.gpx"%(record[0]) + dateFromUTC = Date().getDateTime(record[2]) + if os.path.isfile(gpxfile) : #GPX file exists for this record - probably not a manual record + date_time_local = str(dateFromUTC[1]) + dateFromLocal = dateFromUTC[1].strftime("%Y-%m-%d") + if record[1] != dateFromLocal: + #date field incorrect - update it + logging.debug("Updating record id: %s with date: %s and date_time_local: %s" % (record[0], dateFromLocal, date_time_local) ) + self.ddbbObject.update("records","date, date_time_local",[dateFromLocal, date_time_local], "id_record = %d" %record[0]) + else: + #date field OK, just update date_time_local + logging.debug("Updating record id: %s with date_time_local: %s" % (record[0], date_time_local) ) + self.ddbbObject.update("records","date_time_local",[date_time_local], "id_record = %d" %record[0]) + else: #Manual entry? + #For manual entries, the UTC time is the local time + #TODO figure out a way to correct this... + pass + except: + print "Error updating record: " + str(record) + logging.debug("Error updating record: " + str(record)) Modified: pytrainer/trunk/pytrainer/lib/gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gpx.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/pytrainer/lib/gpx.py 2010-01-17 04:25:47 UTC (rev 483) @@ -28,8 +28,7 @@ import logging from xmlUtils import XMLParser from lxml import etree -import dateutil.parser -from dateutil.tz import * # for tzutc() +from pytrainer.lib.date import Date # use of namespaces is mandatory if defined mainNS = string.Template(".//{http://www.topografix.com/GPX/1/1}$tag") @@ -65,6 +64,7 @@ self.maxvel = 0 self.maxhr = 0 self.date = "" + #self.Date = Date() self.calories= 0 if filename != None: if not os.path.isfile(self.filename): @@ -103,18 +103,7 @@ return tracks def getDateTime(self, time_): - # Time can be in multiple formats - # - zulu 2009-12-15T09:00Z - # - local ISO8601 2009-12-15T10:00+01:00 - dateTime = dateutil.parser.parse(time_) - timezone = dateTime.tzname() - if timezone == 'UTC': #got a zulu time - local_dateTime = dateTime.astimezone(tzlocal()) #datetime with localtime offset (from OS) - else: - local_dateTime = dateTime #use datetime as supplied - utc_dateTime = dateTime.astimezone(tzutc()) #datetime with 00:00 offset - #print utc_dateTime, local_dateTime - return (utc_dateTime,local_dateTime) + return Date().getDateTime(time_) def getUnevenness(self): return self.upositive,self.unegative Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/pytrainer/main.py 2010-01-17 04:25:47 UTC (rev 483) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.0_svn#481" + self.version ="1.7.0_svn#483" self.DB_version = 1 self.date = Date() # Checking profile Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-01-17 02:53:53 UTC (rev 482) +++ pytrainer/trunk/pytrainer/record.py 2010-01-17 04:25:47 UTC (rev 483) @@ -257,7 +257,7 @@ "date=\"%s\" and records.sport=sports.id_sports" %date) def getrecordPeriod(self,date_ini, date_end, sport=None): - #This is essentially the same as getrecordPeriodSport (except date ranges) - need to look at merging the two + #TODO This is essentially the same as getrecordPeriodSport (except date ranges) - need to look at merging the two tables = "records,sports" if not sport: condition = "date>=\"%s\" and date<=\"%s\" and records.sport=sports.id_sports" %(date_ini,date_end) @@ -472,13 +472,13 @@ logging.debug('<<') """ - def shortFromLocal(self): + #def shortFromLocal(self): """25.03.2008 - dgranda Retrieves sport, date and start time from each entry stored locally 12.07.2008 - dgranda - Added id_record for each one returns: list with lists: SPORT|DATE_START_TIME|ID_RECORD 31.08.2008 - dgranda - Only available due to migration purposes from Main class""" - logging.debug('>>') + '''logging.debug('>>') listTracksGPX = [] sport = "Run" #hardcoded - 25.03.2008 (no info stored in gpx files yet) # looking in configuration for storing directory @@ -495,13 +495,13 @@ else: logging.error('Skipping '+gpxFile+' because of wrong format') logging.debug('<<') - return listTracksGPX + return listTracksGPX''' - def shortFromLocalDB(self, getSport=True): + #def shortFromLocalDB(self, getSport=True): """12.07.2008 - dgranda Retrieves sport, date and start time from local database returns: list with lists: SPORT|DATE_START_TIME""" - logging.debug('>>') + '''logging.debug('>>') # Retrieving sport (optional) and date_time (UTC) for each entry in DB # ToDo: replace id_sports with name listTracksGPX = self.ddbb.shortFromLocal(getSport) @@ -516,21 +516,21 @@ listTracksGPX = tempList logging.debug('Retrieved info: '+str(listTracksGPX)) logging.debug('<<') - return listTracksGPX + return listTracksGPX''' - def removeSportFromList(self, list1): - resultList = [] + #def removeSportFromList(self, list1): + '''resultList = [] for entry in list1: resultList.append(entry[1]) - return resultList + return resultList''' - def compareLists(self,list1,list2): - # Optimizing comparison - 26042008 + #def compareLists(self,list1,list2): + '''# Optimizing comparison - 26042008 # http://mail.python.org/pipermail/python-list/2002-May/141458.html tempDict = dict(zip(list1,list1)) - return [x for x in list2 if x not in tempDict] + return [x for x in list2 if x not in tempDict]''' - def compareTracks(self,listTracksGPS,listTracksLocal,checkSport=True): + #def compareTracks(self,listTracksGPS,listTracksLocal,checkSport=True): """22.03.2008 - dgranda Compares tracks retrieved from GPS with already locally stored args: @@ -538,7 +538,7 @@ listTracksLocal: local track list with lists -> (SPORT)|DATE_START_TIME checkSport (02.09.2008): indicates if sport data is included when comparing returns: tracks which are not present locally (list with lists)""" - logging.debug('>>') + '''logging.debug('>>') if checkSport is True: logging.info('Comparing sport info') listGPS = listTracksGPS[:] @@ -562,5 +562,5 @@ logging.info('Tracks to be imported: '+str(len(resultList))) logging.debug('Tracks summary: '+str(resultList)) logging.debug('<<') - return resultList + return resultList ''' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-01-18 06:49:09
|
Revision: 489 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=489&view=rev Author: jblance Date: 2010-01-18 06:48:59 +0000 (Mon, 18 Jan 2010) Log Message: ----------- Added plugins tab to unified import gui - buttons not yet active Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-01-17 20:32:21 UTC (rev 488) +++ pytrainer/trunk/glade/importdata.glade 2010-01-18 06:48:59 UTC (rev 489) @@ -347,6 +347,32 @@ </packing> </child> <child> + <widget class="GtkVBox" id="vboxPlugins"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labelPluginsPage"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Plugins</b></property> + <property name="use_markup">True</property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="position">3</property> + <property name="tab_expand">True</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> <widget class="GtkVBox" id="vboxOptions"> <property name="visible">True</property> <property name="orientation">vertical</property> @@ -493,7 +519,7 @@ </child> </widget> <packing> - <property name="position">2</property> + <property name="position">3</property> </packing> </child> <child> @@ -504,8 +530,7 @@ <property name="single_line_mode">True</property> </widget> <packing> - <property name="position">2</property> - <property name="tab_expand">True</property> + <property name="position">3</property> <property name="tab_fill">False</property> <property name="type">tab</property> </packing> Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-01-17 20:32:21 UTC (rev 488) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-01-18 06:48:59 UTC (rev 489) @@ -24,6 +24,8 @@ import logging from lxml import etree +from pytrainer.plugins import Plugins + class WindowImportdata(SimpleGladeApp): def __init__(self, data_path = None, parent=None, config=None): self.data_path = data_path @@ -34,6 +36,7 @@ self.configuration = config self.store = None self.processClass = None + self.plugins = Plugins(data_path, self.parent.parent) #SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) def run(self): @@ -56,6 +59,9 @@ #'Import from File' tab self.init_file_tab() elif page ==2: + #'Plugins' tab + self.init_plugins_tab() + elif page ==3: #'Options' tab self.init_options_tab() else: @@ -69,7 +75,6 @@ return context_id def init_gpsdevice_tab(self): - return def init_file_tab(self): @@ -84,6 +89,58 @@ self.buttonFileImport.set_sensitive(0) return + def init_plugins_tab(self): + #Remove all components in vbox - in case of re-detection + for child in self.vboxPlugins.get_children(): + print "removing ", child + self.vboxPlugins.remove(child) + pluginList = self.plugins.getPluginsList() + for plugin in pluginList: + #Store plugin details + pluginClass = plugin[0] + pluginName = plugin[1] + pluginDescription = plugin[2] + #Build frame with name and description + pluginFrame = gtk.Frame(label="<b>"+pluginName+"</b>") + pluginFrameLabel = pluginFrame.get_label_widget() + pluginFrameLabel.set_use_markup(True) + description = gtk.Label("<small>"+pluginDescription+"</small>") + description.set_alignment(0,0) + description.set_use_markup(True) + description.set_line_wrap(True) + pluginFrame.add(description) + #Get plugin information + name,description,status = self.plugins.getPluginInfo(pluginClass) + #get plugin conf params ## These are the default params, need to get those stored for the user + #params = self.plugins.getPluginConfParams(pluginClass) + #print params + #Create buttons + statusButton = gtk.Button(label="Disable") + statusButton.connect('clicked', self.pluginsButton_clicked, pluginClass) + configButton = gtk.Button(label="Configure") + configButton.connect('clicked', self.pluginsButton_clicked, pluginClass) + runButton = gtk.Button(label="Run") + runButton.connect('clicked', self.pluginsButton_clicked, pluginClass) + + if status == 0 or status == "0": + #Plugin disabled + pluginFrame.set_sensitive(0) + statusButton.set_label("Enable") + configButton.set_sensitive(0) + runButton.set_sensitive(0) + else: + pass + #Create a table for the frame and button + pluginTable = gtk.Table() + pluginTable.attach(pluginFrame, 0, 1, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, xpadding=5) + pluginTable.attach(statusButton, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) + pluginTable.attach(configButton, 2, 3, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) + pluginTable.attach(runButton, 3, 4, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) + #Add frame to tab + self.vboxPlugins.pack_start(pluginTable, expand=False, fill=False, padding=5) + self.win_importdata.show_all() + return + def init_options_tab(self): #Set correct radiobutton based on saved preference if self.defaulttab == 1: @@ -309,6 +366,12 @@ ## Window signal handlers ## ############################ + def pluginsButton_clicked(self, button, pluginClass): + ''' + Handler for plugin Buttons + ''' + print button.get_label(), pluginClass + def treeviewImportEvents_header_checkbox(self, column, store): """ Handler for click on checkbox column Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-01-17 20:32:21 UTC (rev 488) +++ pytrainer/trunk/pytrainer/main.py 2010-01-18 06:48:59 UTC (rev 489) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.0_svn#485" + self.version ="1.7.0_svn#489" self.DB_version = 1 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-01-21 03:44:01
|
Revision: 491 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=491&view=rev Author: jblance Date: 2010-01-21 03:43:55 +0000 (Thu, 21 Jan 2010) Log Message: ----------- Bug fixes for wordpress extension - needs wordpress blog that supports uploads of html, gpx and kml files Modified Paths: -------------- pytrainer/trunk/extensions/wordpress/googlemaps.py pytrainer/trunk/extensions/wordpress/main.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/extensions/wordpress/googlemaps.py =================================================================== --- pytrainer/trunk/extensions/wordpress/googlemaps.py 2010-01-20 07:41:33 UTC (rev 490) +++ pytrainer/trunk/extensions/wordpress/googlemaps.py 2010-01-21 03:43:55 UTC (rev 491) @@ -19,16 +19,20 @@ import os import re import sys -sys.path.insert(0,os.path.join(sys.path[0],'../../pytrainer/lib')) -from gpx import Gpx -import points as Points -from fileUtils import fileUtils import fileinput +import shutil + +import pytrainer.lib.points as Points +from pytrainer.lib.gpx import Gpx +from pytrainer.lib.fileUtils import fileUtils + def drawMap(gpxfile,key,htmlpath): + #Not sure why need to process gpx file cachefile = "/tmp/gpx.txt" - trackdistance = 100 - os.system("gpsbabel -t -i gpx -f %s -x position,distance=%sm -o gpx -F %s" %(gpxfile,trackdistance,cachefile)) + #trackdistance = 100 + #os.system("gpsbabel -t -i gpx -f %s -x position,distance=%sm -o gpx -F %s" %(gpxfile,trackdistance,cachefile)) + shutil.copy2(gpxfile, cachefile) # Test if file already contains gpxdata attribute found = False Modified: pytrainer/trunk/extensions/wordpress/main.py =================================================================== --- pytrainer/trunk/extensions/wordpress/main.py 2010-01-20 07:41:33 UTC (rev 490) +++ pytrainer/trunk/extensions/wordpress/main.py 2010-01-21 03:43:55 UTC (rev 491) @@ -1,15 +1,14 @@ #!/usr/bin/env python -import wordpresslib -import points as Points from optparse import OptionParser import os -import googlemaps import sys -sys.path.insert(0,os.path.join(sys.path[0],'../../pytrainer/lib')) -from date import Date - import SOAPpy +import wordpresslib +import googlemaps +import pytrainer.lib.points as Points +from pytrainer.lib.date import Date + class Main: def __init__(self,options): self.wordpressurl = options.wordpressurl Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-01-20 07:41:33 UTC (rev 490) +++ pytrainer/trunk/pytrainer/main.py 2010-01-21 03:43:55 UTC (rev 491) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.0_svn#489" + self.version ="1.7.1_pre-release-svn#491" self.DB_version = 1 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-01-21 03:47:34
|
Revision: 492 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=492&view=rev Author: jblance Date: 2010-01-21 03:47:28 +0000 (Thu, 21 Jan 2010) Log Message: ----------- Initial update of CHANGES for release 1.7.1 Modified Paths: -------------- pytrainer/trunk/CHANGES pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/CHANGES =================================================================== --- pytrainer/trunk/CHANGES 2010-01-21 03:43:55 UTC (rev 491) +++ pytrainer/trunk/CHANGES 2010-01-21 03:47:28 UTC (rev 492) @@ -1,3 +1,36 @@ +See the pytrainer roadmap for more information http://sourceforge.net/apps/trac/pytrainer/roadmap + +- PyTrainer changes for 1.7.1: + + * New import plugin - Garmintools - svn [430], [431], [436], [452], [453], [459], [460], [461], [463], [464], [486], [487], [488] + o both file (dump file) and device import implemented + o smart import from device to cater for different start times compared to GPSBabel (to reduce duplicated activities) + * Move to Google maps API version 3 - svn [477] + * Add lap functionality - svn [433], [447], [448], [451], [454], [455] + o display individual laps under activity on treeview + o visually display lap duration on record graphs (user selectable) + o display lap markers on route map + * Improve check functionality - svn [437], [438], [439], [475], [478], [479], [480], [482] + o Can be initiated by command line option --check + o Will be initiated if DB version in code is newer than user's DB version + o DB migration checks refactored and improved + * Timezone support - svn [434], [440], [442], [483] + o DB updated with new field date_time_local + o field populated on import (or when DB check is run) + o field used in preference to UTC if present for display + * Cadence / RPM support and graph added (tcx v2 file import only) - svn [432] + * Improved install process and remove unneeded files - svn [445], [446], [462], [467], [472], [473] + * Bug fix to TCX v2 to cater for multiple activities per file - svn [435] + * Bug fix for calorie calculation - svn [441], [474] + * Bug fix for migration/new install error bug #2924209 - svn [456] + * Bug fix for GPX import without elevation data - svn [490] + * Separate some GUI elements into separate files to ease development - svn [443], [457], [465] + * EXPERIMENTAL Unified Import GUI begun (for testing/feedback only) - svn [458], [466], [468], [469], [470], [471], [476], [481], [489] + o disabled by default + o enabled on startup with --testimport + o file import functional + o device import NOT functional + - PyTrainer changes for 1.7.0: Updated Spanish translation (svn rev 420,423,424) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-01-21 03:43:55 UTC (rev 491) +++ pytrainer/trunk/pytrainer/main.py 2010-01-21 03:47:28 UTC (rev 492) @@ -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#491" + self.version ="1.7.1_pre-release-svn#492" self.DB_version = 1 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <dg...@us...> - 2010-01-24 17:38:45
|
Revision: 500 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=500&view=rev Author: dgranda Date: 2010-01-24 17:38:39 +0000 (Sun, 24 Jan 2010) Log Message: ----------- Updating to version 1.7.1 Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/aboutdialog.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/setup.py Modified: pytrainer/trunk/pytrainer/gui/aboutdialog.py =================================================================== --- pytrainer/trunk/pytrainer/gui/aboutdialog.py 2010-01-24 17:21:59 UTC (rev 499) +++ pytrainer/trunk/pytrainer/gui/aboutdialog.py 2010-01-24 17:38:39 UTC (rev 500) @@ -34,12 +34,12 @@ def run(self): authors = ["Fiz Vázquez <vu...@si...>\nDavid García Granda <dg...@gm...>\nJohn Blance <joh...@gm...>\n\n-Package maintainers:\n\nRedHat/Fedora: Douglas E. Warner <sil...@si...>\nDebian: Noèl Köthe <no...@de...>\nUbuntu: Kevin Dwyer <ke...@ph...>, Alessio Treglia <qua...@ub...>"] translator_credits = "Basque: Jabier Santamaria <men...@gm...>\nCatalan: Eloi Crespillo Itchart <el...@ik...>\nCzech: Lobus Pokorny <sp...@se...>\nFrench: Dj <dj...@dj...>, Pierre Gaigé <pg...@fr...>\nNorwegian: Havard Davidsen <hav...@gm...>\nPolish: Seweryn Kokot <sk...@po...>\nGerman: Aleks <al...@sc...>, Noèl Köthe <no...@de...>\nSpanish: Fiz Vázquez <vu...@si...>, David García Granda <dg...@gm...>" - license = "PyTrainer - The free sport tracking center\nCopyright (C) 2005-09 Fiz Vázquez\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA" + license = "PyTrainer - The free sport tracking center\nCopyright (C) 2005-10 Fiz Vázquez\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program; if not, write to the Free Software\nFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA" about_dialog = gtk.AboutDialog() about_dialog.set_destroy_with_parent(True) about_dialog.set_name("pyTrainer") about_dialog.set_version(self.version) - about_dialog.set_copyright("Copyright \xc2\xa9 2005-9 Fiz Vázquez") + about_dialog.set_copyright("Copyright \xc2\xa9 2005-10 Fiz Vázquez") about_dialog.set_website("http://sourceforge.net/projects/pytrainer") about_dialog.set_website_label("http://sourceforge.net/projects/pytrainer") about_dialog.set_comments("The free sport tracking center") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-01-24 17:21:59 UTC (rev 499) +++ pytrainer/trunk/pytrainer/main.py 2010-01-24 17:38:39 UTC (rev 500) @@ -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#498" + self.version ="1.7.1" self.DB_version = 1 self.date = Date() # Checking profile Modified: pytrainer/trunk/setup.py =================================================================== --- pytrainer/trunk/setup.py 2010-01-24 17:21:59 UTC (rev 499) +++ pytrainer/trunk/setup.py 2010-01-24 17:38:39 UTC (rev 500) @@ -15,7 +15,7 @@ return "share/pytrainer/extensions/%s"%extension_name, glob("extensions/%s/*"%extension_name) setup( name="pytrainer", - version="1.7.0", + version="1.7.1", author="Fiz Vazquez", maintainer_email="pyt...@li...", url="https://sourceforge.net/projects/pytrainer/", This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-02-01 09:52:09
|
Revision: 508 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=508&view=rev Author: jblance Date: 2010-02-01 09:52:03 +0000 (Mon, 01 Feb 2010) Log Message: ----------- Update remove record code to delete lap info as well Modified Paths: -------------- pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-02-01 09:37:15 UTC (rev 507) +++ pytrainer/trunk/glade/newrecord.glade 2010-02-01 09:52:03 UTC (rev 508) @@ -245,7 +245,7 @@ <property name="width_request">47</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="adjustment">0 0 23 1 2 2</property> + <property name="adjustment">0 0 23 1 2 0</property> <property name="climb_rate">1</property> <property name="numeric">True</property> <property name="wrap">True</property> @@ -271,7 +271,7 @@ <property name="width_request">47</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="adjustment">0 0 59 2 2 2</property> + <property name="adjustment">0 0 59 2 2 0</property> <property name="climb_rate">1</property> <property name="numeric">True</property> <property name="wrap">True</property> @@ -297,7 +297,7 @@ <property name="width_request">42</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 1 2 0</property> <property name="climb_rate">1</property> <property name="wrap">True</property> </widget> Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-01 09:37:15 UTC (rev 507) +++ pytrainer/trunk/pytrainer/main.py 2010-02-01 09:52:03 UTC (rev 508) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.1_svn#507" + self.version ="1.7.1_svn#508" self.DB_version = 2 self.date = Date() # Checking profile Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-02-01 09:37:15 UTC (rev 507) +++ pytrainer/trunk/pytrainer/record.py 2010-02-01 09:52:03 UTC (rev 508) @@ -72,7 +72,8 @@ def removeRecord(self,id_record): #TODO remember to update once laps are in DB logging.debug('>>') record = self.ddbb.delete("records", "id_record=\"%s\"" %id_record) - logging.debug('removed record '+str(id_record)+' from bbdd') + laps = self.ddbb.delete("laps", "record=\"%s\"" %id_record) + logging.debug('removed record '+str(id_record)+' (and associated laps) from DB') gpxfile = self.conf.getValue("gpxdir")+"/%d.gpx"%int(id_record) if os.path.isfile(gpxfile): os.remove(gpxfile) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-02-08 08:03:57
|
Revision: 510 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=510&view=rev Author: jblance Date: 2010-02-08 08:03:51 +0000 (Mon, 08 Feb 2010) Log Message: ----------- Update to unified import to allow import of multiple files at once Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/import/file_gpxplus.py pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-02-03 09:49:07 UTC (rev 509) +++ pytrainer/trunk/glade/importdata.glade 2010-02-08 08:03:51 UTC (rev 510) @@ -179,33 +179,64 @@ <property name="visible">True</property> <property name="left_padding">12</property> <child> - <widget class="GtkHBox" id="hbox2"> + <widget class="GtkVBox" id="vboxImportfromFileSelectFiles"> <property name="visible">True</property> + <property name="orientation">vertical</property> <child> - <widget class="GtkFileChooserButton" id="filechooserbuttonSelectFile"> + <widget class="GtkTreeView" id="treeviewImportFiles"> <property name="visible">True</property> - <property name="create_folders">False</property> - <property name="focus_on_click">False</property> - <signal name="file_set" handler="on_filechooserbuttonSelectFile_file_set"/> + <property name="can_focus">True</property> </widget> <packing> - <property name="position">0</property> + <property name="pack_type">end</property> + <property name="position">1</property> </packing> </child> <child> - <widget class="GtkButton" id="buttonClearFile"> - <property name="label" translatable="yes">Clear</property> + <widget class="GtkHBox" id="hbox2"> <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="focus_on_click">False</property> - <signal name="clicked" handler="on_buttonClearFile_clicked"/> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkButton" id="buttonRemoveSelectedFiles"> + <property name="label">gtk-remove</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip" translatable="yes">Remove selected files and the associated activities</property> + <property name="use_stock">True</property> + <property name="yalign">0.4699999988079071</property> + <signal name="clicked" handler="on_buttonRemoveSelectedFiles_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">5</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="buttonSelectFiles"> + <property name="label">gtk-add</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + <property name="focus_on_click">False</property> + <signal name="clicked" handler="on_buttonSelectFiles_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">5</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> </widget> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> + <property name="pack_type">end</property> + <property name="position">0</property> </packing> </child> </widget> @@ -215,7 +246,7 @@ <child> <widget class="GtkLabel" id="labelSelectFileFrame"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Select a file to import</b></property> + <property name="label" translatable="yes"><b>Select file(s) to import activities from</b></property> <property name="use_markup">True</property> <property name="single_line_mode">True</property> </widget> @@ -258,7 +289,7 @@ <child> <widget class="GtkLabel" id="labelEvents"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Select Activities to Import</b></property> + <property name="label" translatable="yes"><b>Select activities to import</b></property> <property name="use_markup">True</property> <property name="single_line_mode">True</property> </widget> Modified: pytrainer/trunk/import/file_gpxplus.py =================================================================== --- pytrainer/trunk/import/file_gpxplus.py 2010-02-03 09:49:07 UTC (rev 509) +++ pytrainer/trunk/import/file_gpxplus.py 2010-02-08 08:03:51 UTC (rev 510) @@ -51,8 +51,7 @@ logging.debug('>>') logging.debug("Testing " + filename) #Check if file is a GPX - #try: - while True: + try: #parse as xml xmldoc = etree.parse(filename) #Parse XML schema @@ -74,9 +73,9 @@ sport, ) ) return True - #except: + except: #Not gpx file - # return False + return False return False def getDateTime(self, time_): Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-03 09:49:07 UTC (rev 509) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-08 08:03:51 UTC (rev 510) @@ -25,6 +25,7 @@ from lxml import etree from pytrainer.plugins import Plugins +from pytrainer.gui.dialogs import fileChooserDialog class WindowImportdata(SimpleGladeApp): def __init__(self, data_path = None, parent=None, config=None): @@ -34,8 +35,9 @@ self.domain = None self.parent = parent self.configuration = config - self.store = None - self.processClass = None + self.activities_store = None + self.files_store = None + self.processClasses = [] self.plugins = Plugins(data_path, self.parent.parent) #SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) @@ -78,14 +80,18 @@ return def init_file_tab(self): - self.filechooserbuttonSelectFile.unselect_all() + #self.filechooserbuttonSelectFile.unselect_all() self.updateStatusbar(self.statusbarImportFile, _("No file selected") ) - self.processClass = None - if self.store is None: - self.store = self.build_tree_view() + self.processClasses = [] + if self.activities_store is None: + self.activities_store = self.build_activities_tree_view() else: - self.store.clear() - self.buttonClearFile.set_sensitive(0) + self.activities_store.clear() + if self.files_store is None: + self.files_store = self.build_files_tree_view() + else: + self.files_store.clear() + self.buttonRemoveSelectedFiles.set_sensitive(0) self.buttonFileImport.set_sensitive(0) return @@ -220,6 +226,7 @@ self.updateStatusbar(self.statusbarImportFile, "Checking file type for: " + import_filename) #Get import files_* files fileList = glob.glob(self.data_path+"import/file_*.py") + fileList.sort() for processingFile in fileList: directory, filename = os.path.split(processingFile) filename = filename.rstrip('.py') @@ -239,20 +246,45 @@ logging.debug('<<') return processClass + def build_files_tree_view(self): + store = gtk.ListStore( gobject.TYPE_STRING, + gobject.TYPE_BOOLEAN, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, ) + column_names=["id", _(""), _("File"), _("Type"), _("Activities")] + for column_index, column_name in enumerate(column_names): + if column_index == 1: + #Add button column + self.renderer1 = gtk.CellRendererToggle() + self.renderer1.set_property('activatable', True) + self.renderer1.connect( 'toggled', self.treeviewImportFiles_toggled_checkbox, store ) + column = gtk.TreeViewColumn(column_name, self.renderer1 ) + column.add_attribute( self.renderer1, "active", column_index) + column.set_sort_column_id(-1) + #column.connect('clicked', self.treeviewImportFiles_header_checkbox, store) + else: + #Add other columns + column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) + column.set_sort_column_id(column_index) + if column_name == "id": + column.set_visible(False) + column.set_resizable(True) + self.treeviewImportFiles.append_column(column) + self.treeviewImportFiles.set_headers_clickable(True) + self.treeviewImportFiles.set_model(store) + return store - self.updateStatusbar(self.statusbarImportFile, "Unknown file type") - logging.debug('<<') - return None - - def build_tree_view(self): - store = gtk.ListStore(gobject.TYPE_STRING, + def build_activities_tree_view(self): + store = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, + gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, - gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING ) - column_names=["id", _(""),_("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("Notes")] + column_names=["id", _(""), _("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("Notes"), "file_id"] for column_index, column_name in enumerate(column_names): if column_index == 1: #Add checkbox column @@ -267,7 +299,7 @@ #Add other columns column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) column.set_sort_column_id(column_index) - if column_name == "id": + if column_name == "id" or column_name == "file_id": column.set_visible(False) column.set_resizable(True) self.treeviewImportEvents.append_column(column) @@ -275,25 +307,35 @@ self.treeviewImportEvents.set_model(store) return store - def treeviewImportEvents_toggled_checkbox( self, cell, path, store ): + def treeviewImportFiles_toggled_checkbox(self, cell, path, store): """ Sets the state of the checkbox to true or false. """ store[path][1] = not store[path][1] + self.buttonRemoveSelectedFiles.set_sensitive(0) + for item in store: + if item[1]: + #Only enable remove button if at least one file is selected + self.buttonRemoveSelectedFiles.set_sensitive(1) + + def treeviewImportEvents_toggled_checkbox(self, cell, path, store): + """ + Sets the state of the checkbox to true or false. + """ + store[path][1] = not store[path][1] self.buttonFileImport.set_sensitive(0) for item in store: if item[1]: #Only enable import button if at least one activity is selected self.buttonFileImport.set_sensitive(1) - return def treeviewImportEvents_setCheckboxes(self, state): """ Sets or unsets all checkboxes """ - if self.store is None or len(self.store) == 0: + if self.activities_store is None or len(self.activities_store) == 0: return - for item in self.store: + for item in self.activities_store: item[1] = state if state: self.buttonFileImport.set_sensitive(1) @@ -312,6 +354,32 @@ self.configuration.setValue("pytraining","import_default_tab",self.defaulttab) #option + def removeSelectedFiles(self): + """ + Function to determine which files are selected + * remove them from the list + * remove the associated activities from the list also + """ + if self.files_store is None: + return + file_index = 0 + file_iters = [] + activity_iters = [] + for item in self.files_store: + if item[1] is True: #Checkbox is True, file for removal + file_id = item[0] + activity_index = 0 + for activity in self.activities_store: + if activity[7] == file_id: #Activity relates to file to be removed + activity_iters.append(self.activities_store.get_iter(activity_index)) + activity_index += 1 + file_iters.append( self.files_store.get_iter(file_index)) + file_index += 1 + for activity_iter in activity_iters: + self.activities_store.remove(activity_iter) + for file_iter in file_iters: + self.files_store.remove(file_iter) + def getSelectedActivities(self): """ Function to determine which activities are selected @@ -319,43 +387,49 @@ Returns array of the ids of the selected activities """ selectedActivities = [] - if self.store is None: + if self.activities_store is None: return None - for item in self.store: + for item in self.activities_store: if item[1] is True: #Checkbox is True - logging.debug("Added activity id:%s to selected list" % item[0]) - selectedActivities.append(item[0]) + logging.debug("Added activity %s to selected list" % item) + selectedActivities.append(item) logging.debug( "Found %d selected activities to import" % len(selectedActivities) ) return selectedActivities - def importSelectedActivities(self, selectedActivities): + def importSelectedActivity(self, activity): """ - Function to import selected activities + Function to import selected activity """ - if selectedActivities is None or len(selectedActivities) == 0: - return - for activityID in selectedActivities: - logging.debug( "Importing activity %s" % activityID) - sport, gpxFile = self.processClass.getGPXFile(activityID) - #process returned GPX files - if os.path.isfile(gpxFile): - logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(gpxFile), sport)) - #TODO trigger newentry screen to allow user to edit data - self.parent.parent.record.importFromGPX(gpxFile, sport) - #Deselect imported activity and change note - self.updateActivity(activityID, status=False, notes="Imported into database") - else: - logging.error('File %s not valid' % gpxFile) + activity_id = activity[0] + #selected = activity[1] + #start_time = activity[2] + #distance = activity[3] + #duration = activity[4] + #sport = activity[5] + #notes = activity[6] + file_id = int(activity[7]) + + logging.debug( "Importing activity %s from file %s" % (activity_id, file_id)) + sport, gpxFile = self.processClasses[file_id].getGPXFile(activity_id) + #process returned GPX files + if os.path.isfile(gpxFile): + logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(gpxFile), sport)) + #TODO trigger newentry screen to allow user to edit data + self.parent.parent.record.importFromGPX(gpxFile, sport) + #Deselect imported activity and change note + self.updateActivity(activity_id, file_id, status=False, notes="Imported into database") + else: + logging.error('File %s not valid' % gpxFile) - def updateActivity(self, activityID, status = None, notes = None): + def updateActivity(self, activityID, file_id, status = None, notes = None): path = 0 - for item in self.store: - if item[0] == activityID: + for item in self.activities_store: + if item[0] == activityID and item[7] == file_id: if status is not None: - self.store[path][1] = status + self.activities_store[path][1] = status if notes is not None: - self.store[path][6] = notes + self.activities_store[path][6] = notes path +=1 def close_window(self): @@ -391,13 +465,14 @@ def on_notebookMainTabs_switch_page(self, notebook, page, new_page): self.init_tab(new_page) - def on_filechooserbuttonSelectFile_file_set(self, widget): + #def on_filechooserbuttonSelectFile_file_set(self, widget): + ''' self.buttonClearFile.set_sensitive(1) #Enable clear button self.buttonFileImport.set_sensitive(0) #Disable import button self.updateStatusbar(self.statusbarImportFile, "" ) #Clear status bar #Clear store - if self.store is not None: - self.store.clear() + if self.activities_store is not None: + self.activities_store.clear() #Validate file self.processClass = self.validateFile(self.filechooserbuttonSelectFile.get_filename()) if self.processClass is not None: @@ -412,8 +487,8 @@ else: note = _("Found in database") #Add activity details to TreeView store to display - iter = self.store.append() - self.store.set( + iter = self.activities_store.append() + self.activities_store.set( iter, 0, activity[0], 1, not activity[1], @@ -431,10 +506,10 @@ md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) md.set_title("Error") md.run() - md.destroy() + md.destroy()''' - def on_buttonClearFile_clicked(self, widget): - self.init_tab(1) + #def on_buttonClearFile_clicked(self, widget): + # self.init_tab(1) def on_buttonOptionsSave_clicked(self, widget): self.updateStatusbar(self.statusbarOptions, "Saving options") @@ -448,6 +523,11 @@ self.init_options_tab() self.updateStatusbar(self.statusbarOptions, "") + def on_buttonRemoveSelectedFiles_clicked(self, widget): + #Remove selected files and associated activities from list + #TODO + self.removeSelectedFiles() + def on_buttonFileImport_clicked(self, widget): #Import selected activities selectedActivities = self.getSelectedActivities() @@ -462,7 +542,9 @@ self.updateStatusbar(self.statusbarImportFile, msgImporting) while gtk.events_pending(): # This allows the GUI to update gtk.main_iteration() # before completion of this entire action - self.importSelectedActivities(selectedActivities) + for activity in selectedActivities: + self.importSelectedActivity(activity) + #TODO progress bar here?? self.updateStatusbar(self.statusbarImportFile, msgImported) #Display informational dialog box md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, msgImported) @@ -470,6 +552,60 @@ md.run() md.destroy() self.buttonFileImport.set_sensitive(0) #Disable import button + + def on_buttonSelectFiles_clicked(self, widget): + selectedFiles = fileChooserDialog(title="Choose a file (or files) to import activities from", multiple=True).getFiles() + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + if selectedFiles is None or len(selectedFiles) == 0: + #Nothing selected + return + for filename in selectedFiles: #Multiple files + class_index = len(self.processClasses) + #Validate file + self.processClasses.append(self.validateFile(filename)) + if self.processClasses[class_index] is not None: + self.updateStatusbar(self.statusbarImportFile, _("Found file of type: %s") % self.processClasses[class_index].getFileType() ) + activitiesSummary = self.processClasses[class_index].getActivitiesSummary() + activity_count = len(activitiesSummary) + #Add file to files treeview + iter = self.files_store.append() + self.files_store.set( + iter, + 0, class_index, + 1, False, + 2, filename, + 3, self.processClasses[class_index].getFileType(), + 4, activity_count + ) + #Get activities in file + for activity in activitiesSummary: + #Add activity details to TreeView store to display + if not activity[1]: + #Activity selected, so enable import button + self.buttonFileImport.set_sensitive(1) + note = "" + else: + note = _("Found in database") + activity_iter = self.activities_store.append() + self.activities_store.set( + activity_iter, + 0, activity[0], + 1, not activity[1], + 2, activity[2], + 3, activity[3], + 4, activity[4], + 5, activity[5], + 6, note, + 7, class_index, + ) + else: #Selected file not understood by any of the process files + #Display error + msg = _("File %s is of unknown or unsupported file type" % filename) + md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) + md.set_title("Error") + md.run() + md.destroy() def on_buttonFileClose_clicked(self, widget): self.close_window() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-03 09:49:07 UTC (rev 509) +++ pytrainer/trunk/pytrainer/main.py 2010-02-08 08:03:51 UTC (rev 510) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.1_svn#509" + self.version ="1.7.1_svn#510" self.DB_version = 3 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-02-15 08:26:39
|
Revision: 511 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=511&view=rev Author: jblance Date: 2010-02-15 08:26:32 +0000 (Mon, 15 Feb 2010) Log Message: ----------- Bug fixes in Unified Import - file import tab Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-02-08 08:03:51 UTC (rev 510) +++ pytrainer/trunk/glade/importdata.glade 2010-02-15 08:26:32 UTC (rev 511) @@ -222,6 +222,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="tooltip" translatable="yes">Add files to import activities from</property> <property name="use_stock">True</property> <property name="focus_on_click">False</property> <signal name="clicked" handler="on_buttonSelectFiles_clicked"/> @@ -246,7 +247,7 @@ <child> <widget class="GtkLabel" id="labelSelectFileFrame"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Select file(s) to import activities from</b></property> + <property name="label" translatable="yes"><b>Add file(s) to import activities from</b></property> <property name="use_markup">True</property> <property name="single_line_mode">True</property> </widget> @@ -312,6 +313,7 @@ <property name="sensitive">False</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="tooltip" translatable="yes">Import selected activities</property> <signal name="clicked" handler="on_buttonFileImport_clicked"/> </widget> <packing> @@ -328,6 +330,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="tooltip" translatable="yes">Close Import dialog</property> <property name="use_stock">True</property> <signal name="clicked" handler="on_buttonFileClose_clicked"/> </widget> Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-08 08:03:51 UTC (rev 510) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-15 08:26:32 UTC (rev 511) @@ -306,28 +306,31 @@ self.treeviewImportEvents.set_headers_clickable(True) self.treeviewImportEvents.set_model(store) return store + + def checkTreestoreForSelection(self, store): + """ + Function iterates over store checking if any items are selected + returns True if at least one item is selected, False otherwise + Checks item in position 1 only + """ + for item in store: + if item[1]: + return True + return False def treeviewImportFiles_toggled_checkbox(self, cell, path, store): """ Sets the state of the checkbox to true or false. """ store[path][1] = not store[path][1] - self.buttonRemoveSelectedFiles.set_sensitive(0) - for item in store: - if item[1]: - #Only enable remove button if at least one file is selected - self.buttonRemoveSelectedFiles.set_sensitive(1) - + self.buttonRemoveSelectedFiles.set_sensitive(self.checkTreestoreForSelection(store)) + def treeviewImportEvents_toggled_checkbox(self, cell, path, store): """ Sets the state of the checkbox to true or false. """ store[path][1] = not store[path][1] - self.buttonFileImport.set_sensitive(0) - for item in store: - if item[1]: - #Only enable import button if at least one activity is selected - self.buttonFileImport.set_sensitive(1) + self.buttonFileImport.set_sensitive(self.checkTreestoreForSelection(store)) def treeviewImportEvents_setCheckboxes(self, state): """ @@ -377,6 +380,7 @@ file_index += 1 for activity_iter in activity_iters: self.activities_store.remove(activity_iter) + self.buttonFileImport.set_sensitive(self.checkTreestoreForSelection(self.activities_store)) #Set correct state for import button for file_iter in file_iters: self.files_store.remove(file_iter) @@ -425,7 +429,7 @@ def updateActivity(self, activityID, file_id, status = None, notes = None): path = 0 for item in self.activities_store: - if item[0] == activityID and item[7] == file_id: + if item[0] == activityID and item[7] == str(file_id): if status is not None: self.activities_store[path][1] = status if notes is not None: @@ -525,7 +529,6 @@ def on_buttonRemoveSelectedFiles_clicked(self, widget): #Remove selected files and associated activities from list - #TODO self.removeSelectedFiles() def on_buttonFileImport_clicked(self, widget): Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-08 08:03:51 UTC (rev 510) +++ pytrainer/trunk/pytrainer/main.py 2010-02-15 08:26:32 UTC (rev 511) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.1_svn#510" + self.version ="1.7.1_svn#511" self.DB_version = 3 self.date = Date() # Checking profile This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-02-15 10:40:44
|
Revision: 512 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=512&view=rev Author: jblance Date: 2010-02-15 10:40:37 +0000 (Mon, 15 Feb 2010) Log Message: ----------- Unified import - plugins tab now functional Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/glade/pytrainer.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/gui/windowplugins.py pytrainer/trunk/pytrainer/importdata.py pytrainer/trunk/pytrainer/main.py Added Paths: ----------- pytrainer/trunk/glade/plugins.glade Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-02-15 08:26:32 UTC (rev 511) +++ pytrainer/trunk/glade/importdata.glade 2010-02-15 10:40:37 UTC (rev 512) @@ -381,11 +381,65 @@ </packing> </child> <child> - <widget class="GtkVBox" id="vboxPlugins"> + <widget class="GtkVBox" id="vboxPluginsTab"> <property name="visible">True</property> <property name="orientation">vertical</property> <child> - <placeholder/> + <widget class="GtkVBox" id="vboxPlugins"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkHBox" id="hboxPluginsButtons"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkButton" id="buttonPluginsClose"> + <property name="label">gtk-close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_buttonPluginsClose_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">5</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkStatusbar" id="statusbarPlugins"> + <property name="visible">True</property> + <property name="spacing">2</property> + <property name="has_resize_grip">False</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> </child> </widget> <packing> @@ -454,6 +508,27 @@ <property name="position">1</property> </packing> </child> + <child> + <widget class="GtkRadioButton" id="radiobuttonPlugins"> + <property name="label" translatable="yes">Plugins</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="yalign">0.4699999988079071</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">radiobuttonTabGPSDevice</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">10</property> + <property name="position">2</property> + </packing> + </child> + <child> + <placeholder/> + </child> </widget> </child> </widget> Added: pytrainer/trunk/glade/plugins.glade =================================================================== --- pytrainer/trunk/glade/plugins.glade (rev 0) +++ pytrainer/trunk/glade/plugins.glade 2010-02-15 10:40:37 UTC (rev 512) @@ -0,0 +1,224 @@ +<?xml version="1.0"?> +<glade-interface> + <!-- interface-requires gtk+ 2.16 --> + <!-- interface-naming-policy toplevel-contextual --> + <widget class="GtkWindow" id="plugins"> + <property name="width_request">650</property> + <property name="height_request">230</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Plugins</property> + <property name="icon">logo_mini.png</property> + <child> + <widget class="GtkHBox" id="hbox34"> + <property name="width_request">32</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="border_width">9</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow5"> + <property name="width_request">230</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">in</property> + <child> + <widget class="GtkTreeView" id="pluginsTreeview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="rules_hint">True</property> + <signal name="button_release_event" handler="on_pluginsTree_clicked"/> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox21"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <widget class="GtkTable" id="table12"> + <property name="visible">True</property> + <property name="border_width">5</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="column_spacing">5</property> + <property name="row_spacing">5</property> + <child> + <widget class="GtkLabel" id="label-2147483647"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Plugin Details</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="descriptionEntry"> + <property name="height_request">78</property> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">description-entry </property> + <property name="use_underline">True</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label11113"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">Description:</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="statusEntry"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">status-entry</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label11114"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Status:</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="nameEntry"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">nameEntry</property> + </widget> + <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> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label11112"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Name:</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox35"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label11118"> + <property name="visible">True</property> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label11119"> + <property name="visible">True</property> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button32"> + <property name="label">gtk-preferences</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_preferences_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button33"> + <property name="label">gtk-ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_accept_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> Modified: pytrainer/trunk/glade/pytrainer.glade =================================================================== --- pytrainer/trunk/glade/pytrainer.glade 2010-02-15 08:26:32 UTC (rev 511) +++ pytrainer/trunk/glade/pytrainer.glade 2010-02-15 10:40:37 UTC (rev 512) @@ -9090,393 +9090,6 @@ </child> </widget> -<widget class="GtkWindow" id="plugins"> - <property name="width_request">650</property> - <property name="height_request">230</property> - <property name="visible">True</property> - <property name="title" translatable="yes">Plugins</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> - - <child> - <widget class="GtkHBox" id="hbox34"> - <property name="border_width">9</property> - <property name="width_request">32</property> - <property name="height_request">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow5"> - <property name="width_request">230</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="pluginsTreeview"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">True</property> - <property name="rules_hint">True</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - <signal name="button_release_event" handler="on_pluginsTree_clicked" last_modification_time="Tue, 27 Mar 2007 11:56:15 GMT"/> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox21"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkTable" id="table12"> - <property name="border_width">5</property> - <property name="visible">True</property> - <property name="n_rows">4</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">5</property> - <property name="column_spacing">5</property> - - <child> - <widget class="GtkLabel" id="label-2147483647"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Plugin Details</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="descriptionEntry"> - <property name="height_request">78</property> - <property name="visible">True</property> - <property name="label" translatable="yes">description-entry </property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label11113"> - <property name="visible">True</property> - <property name="label" translatable="yes">Description:</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0</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="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options">fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="statusEntry"> - <property name="visible">True</property> - <property name="label" translatable="yes">status-entry</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</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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label11114"> - <property name="visible">True</property> - <property name="label" translatable="yes">Status:</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="nameEntry"> - <property name="visible">True</property> - <property name="label" translatable="yes">nameEntry</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</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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label11112"> - <property name="visible">True</property> - <property name="label" translatable="yes">Name:</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox35"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label11118"> - <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="GtkLabel" id="label11119"> - <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="button32"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-preferences</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_preferences_clicked" last_modification_time="Tue, 31 Oct 2006 10:35:46 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button33"> - <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="Tue, 31 Oct 2006 11:54:10 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </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">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - <widget class="GtkWindow" id="selecttrackdialog"> <property name="width_request">350</property> <property name="height_request">235</property> Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-15 08:26:32 UTC (rev 511) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-15 10:40:37 UTC (rev 512) @@ -28,21 +28,22 @@ from pytrainer.gui.dialogs import fileChooserDialog class WindowImportdata(SimpleGladeApp): - def __init__(self, data_path = None, parent=None, config=None): + def __init__(self, data_path = None, parent=None, config=None, pytrainer_main=None): self.data_path = data_path self.glade_path=data_path+"glade/importdata.glade" self.root = "win_importdata" self.domain = None self.parent = parent + self.pytrainer_main = pytrainer_main self.configuration = config self.activities_store = None self.files_store = None self.processClasses = [] self.plugins = Plugins(data_path, self.parent.parent) - #SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) + SimpleGladeApp.__init__(self, self.glade_path, self.root, self.domain) - def run(self): - SimpleGladeApp.__init__(self, self.glade_path, self.root, self.domain) + #def run(self): + # SimpleGladeApp.__init__(self, self.glade_path, self.root, self.domain) def new(self): self.defaulttab = self.configuration.getValue("pytraining","import_default_tab") @@ -96,10 +97,10 @@ return def init_plugins_tab(self): - #Remove all components in vbox - in case of re-detection + #Remove components in vbox - in case of re-detection for child in self.vboxPlugins.get_children(): - print "removing ", child - self.vboxPlugins.remove(child) + if isinstance(child, gtk.Table): + self.vboxPlugins.remove(child) pluginList = self.plugins.getPluginsList() for plugin in pluginList: #Store plugin details @@ -117,29 +118,24 @@ pluginFrame.add(description) #Get plugin information name,description,status = self.plugins.getPluginInfo(pluginClass) - #get plugin conf params ## These are the default params, need to get those stored for the user - #params = self.plugins.getPluginConfParams(pluginClass) - #print params - #Create buttons - statusButton = gtk.Button(label="Disable") - statusButton.connect('clicked', self.pluginsButton_clicked, pluginClass) - configButton = gtk.Button(label="Configure") - configButton.connect('clicked', self.pluginsButton_clicked, pluginClass) - runButton = gtk.Button(label="Run") - runButton.connect('clicked', self.pluginsButton_clicked, pluginClass) - + #Create labels and buttons + configButton = gtk.Button(label=_("Configure")) + runButton = gtk.Button(label=_("Run")) + #Connect button handlers + configButton.connect('clicked', self.on_pluginsButton_Configure_clicked, pluginClass) + runButton.connect('clicked', self.on_pluginsButton_Run_clicked, pluginClass) if status == 0 or status == "0": #Plugin disabled pluginFrame.set_sensitive(0) - statusButton.set_label("Enable") - configButton.set_sensitive(0) runButton.set_sensitive(0) + statusLabel = gtk.Label(_("Disabled")) else: - pass + statusLabel = gtk.Label(_("Enabled")) + #Create a table for the frame and button pluginTable = gtk.Table() pluginTable.attach(pluginFrame, 0, 1, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, xpadding=5) - pluginTable.attach(statusButton, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) + pluginTable.attach(statusLabel, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) pluginTable.attach(configButton, 2, 3, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) pluginTable.attach(runButton, 3, 4, 0, 1, xoptions=gtk.FILL, yoptions=gtk.SHRINK, xpadding=5, ypadding=5) #Add frame to tab @@ -151,24 +147,25 @@ #Set correct radiobutton based on saved preference if self.defaulttab == 1: self.radiobuttonFile.set_active(1) + elif self.defaulttab == 2: + self.radiobuttonPlugins.set_active(1) else: self.radiobuttonTabGPSDevice.set_active(1) return def detect_tools(self): - """ + ''' Iterate through all tool files from import directory Each file contains information on a particular tool and knows how to determine if the tool is present on the system and what configuration options are needed for the tool Currently displays the tool info and config grayed out if tool is not present - """ + ''' logging.debug('>>') self.updateStatusbar(self.statusbarDevice, "Checking for tools") #Remove all components in vbox - in case of re-detection for child in self.vboxImportTools.get_children(): - print "removing ", child self.vboxImportTools.remove(child) #Get import tool_* files fileList = glob.glob(self.data_path+"import/tool_*.py") @@ -213,7 +210,7 @@ self.win_importdata.show_all() def validateFile(self, import_filename): - """ + ''' Iterate through all supported types of file by reading processing files from import directory Each processing file understands one type of file @@ -221,7 +218,7 @@ returns the instantiated class otherwise: returns None - """ + ''' logging.debug('>>') self.updateStatusbar(self.statusbarImportFile, "Checking file type for: " + import_filename) #Get import files_* files @@ -308,27 +305,27 @@ return store def checkTreestoreForSelection(self, store): - """ + ''' Function iterates over store checking if any items are selected returns True if at least one item is selected, False otherwise Checks item in position 1 only - """ + ''' for item in store: if item[1]: return True return False def treeviewImportFiles_toggled_checkbox(self, cell, path, store): - """ + ''' Sets the state of the checkbox to true or false. - """ + ''' store[path][1] = not store[path][1] self.buttonRemoveSelectedFiles.set_sensitive(self.checkTreestoreForSelection(store)) def treeviewImportEvents_toggled_checkbox(self, cell, path, store): - """ + ''' Sets the state of the checkbox to true or false. - """ + ''' store[path][1] = not store[path][1] self.buttonFileImport.set_sensitive(self.checkTreestoreForSelection(store)) @@ -354,15 +351,17 @@ self.defaulttab = "0" elif self.radiobuttonFile.get_active(): self.defaulttab = "1" + elif self.radiobuttonPlugins.get_active(): + self.defaulttab = "2" self.configuration.setValue("pytraining","import_default_tab",self.defaulttab) #option def removeSelectedFiles(self): - """ + ''' Function to determine which files are selected * remove them from the list * remove the associated activities from the list also - """ + ''' if self.files_store is None: return file_index = 0 @@ -438,22 +437,78 @@ def close_window(self): self.win_importdata.hide() - self.win_importdata.destroy() + #self.win_importdata.destroy() + self.quit() ############################ ## Window signal handlers ## ############################ - def pluginsButton_clicked(self, button, pluginClass): + def on_pluginsButton_Configure_clicked(self, button, pluginClass): ''' Handler for plugin Buttons ''' - print button.get_label(), pluginClass - + name,description,status = self.plugins.getPluginInfo(pluginClass) + prefs = self.plugins.getPluginConfParams(pluginClass) + + self.prefwindow = gtk.Window() + self.prefwindow.set_border_width(20) + self.prefwindow.set_title(_("%s settings" %name)) + + table = gtk.Table(1,2) + i=0 + self.entryList = [] + for pref in prefs: + label = gtk.Label("<b>%s</b>"%pref[0]) + label.set_use_markup(True) + if pref[0] != "status": + entry = gtk.Entry() + entry.set_text(pref[1]) + self.entryList.append(entry) + table.attach(entry,1,2,i,i+1) + else: + combobox = gtk.combo_box_new_text() + combobox.append_text(_("Disable")) + combobox.append_text(_("Enable")) + combobox.set_active(int(pref[1])) + table.attach(combobox,1,2,i,i+1) + self.entryList.append(combobox) + table.attach(label,0,1,i,i+1) + i+=1 + + button = gtk.Button(_("Ok")) + button.connect("clicked", self.on_pluginAcceptSettings_clicked, pluginClass) + table.attach(button,0,2,i,i+1) + self.prefwindow.add(table) + self.prefwindow.show_all() + + def on_pluginsButton_Run_clicked(self, button, pluginClass): + ''' + Handler for plugin Buttons + ''' + self.pytrainer_main.runPlugin(button,pluginClass) + + def on_pluginAcceptSettings_clicked(self, widget, pluginClass): + prefs = self.plugins.getPluginConfParams(pluginClass) + savedOptions = [] + i = 0 + for pref in prefs: + try: + savedOptions.append((pref[0],self.entryList[i].get_text())) + except: + combobox = self.entryList[i] + index = combobox.get_active() + savedOptions.append((pref[0],"%s" %index)) + i+=1 + self.prefwindow.hide() + self.prefwindow = None + self.plugins.setPluginConfParams(pluginClass,savedOptions) + self.init_plugins_tab() + def treeviewImportEvents_header_checkbox(self, column, store): - """ + ''' Handler for click on checkbox column - """ + ''' if store is None: return for item in store: @@ -463,62 +518,16 @@ self.treeviewImportEvents_setCheckboxes(True) def on_win_importdata_delete_event(self, widget, window): - """ Windows closed """ + ''' Window closed ''' self.close_window() def on_notebookMainTabs_switch_page(self, notebook, page, new_page): self.init_tab(new_page) - #def on_filechooserbuttonSelectFile_file_set(self, widget): - ''' - self.buttonClearFile.set_sensitive(1) #Enable clear button - self.buttonFileImport.set_sensitive(0) #Disable import button - self.updateStatusbar(self.statusbarImportFile, "" ) #Clear status bar - #Clear store - if self.activities_store is not None: - self.activities_store.clear() - #Validate file - self.processClass = self.validateFile(self.filechooserbuttonSelectFile.get_filename()) - if self.processClass is not None: - self.updateStatusbar(self.statusbarImportFile, _("Found file of type: %s") % self.processClass.getFileType() ) - #Get activities in file - activitiesSummary = self.processClass.getActivitiesSummary() - for activity in activitiesSummary: - if not activity[1]: - #Activity selected, so enable import button - self.buttonFileImport.set_sensitive(1) - note = "" - else: - note = _("Found in database") - #Add activity details to TreeView store to display - iter = self.activities_store.append() - self.activities_store.set( - iter, - 0, activity[0], - 1, not activity[1], - 2, activity[2], - 3, activity[3], - 4, activity[4], - 5, activity[5], - 6, note, - ) - else: - #Selected file not understood by any of the process files - self.updateStatusbar(self.statusbarImportFile, _("Unknown file type") ) - #Display error - msg = _("File selected is of unknown or unsupported file type") - md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) - md.set_title("Error") - md.run() - md.destroy()''' - - #def on_buttonClearFile_clicked(self, widget): - # self.init_tab(1) - def on_buttonOptionsSave_clicked(self, widget): - self.updateStatusbar(self.statusbarOptions, "Saving options") + self.updateStatusbar(self.statusbarOptions, _("Saving options")) self.saveOptions() - self.updateStatusbar(self.statusbarOptions, "Options saved") + self.updateStatusbar(self.statusbarOptions, _("Options saved")) def on_buttonOptionsReset_clicked(self, widget): #GPS Device is default @@ -557,7 +566,7 @@ self.buttonFileImport.set_sensitive(0) #Disable import button def on_buttonSelectFiles_clicked(self, widget): - selectedFiles = fileChooserDialog(title="Choose a file (or files) to import activities from", multiple=True).getFiles() + selectedFiles = fileChooserDialog(title=_("Choose a file (or files) to import activities from"), multiple=True).getFiles() while gtk.events_pending(): # This allows the GUI to update gtk.main_iteration() # before completion of this entire action if selectedFiles is None or len(selectedFiles) == 0: @@ -618,6 +627,9 @@ def on_buttonOptionsClose_clicked(self, widget): self.close_window() + + def on_buttonPluginsClose_clicked(self, widget): + self.close_window() def on_buttonDeviceToolRescan_clicked(self, widget): self.detect_tools() Modified: pytrainer/trunk/pytrainer/gui/windowplugins.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowplugins.py 2010-02-15 08:26:32 UTC (rev 511) +++ pytrainer/trunk/pytrainer/gui/windowplugins.py 2010-02-15 10:40:37 UTC (rev 512) @@ -23,7 +23,7 @@ class WindowPlugins(SimpleGladeApp): def __init__(self, data_path = None, parent=None): - glade_path="glade/pytrainer.glade" + glade_path="glade/plugins.glade" root = "plugins" domain = None self.parent = parent @@ -61,7 +61,6 @@ i+=1 def on_pluginsTree_clicked(self,widget,widget2): - print "clicked" selected,iter = self.pluginsTreeview.get_selection().get_selected() name,description,status = self.parent.getPluginInfo(selected.get_value(iter,0)) self.nameEntry.set_text(name) Modified: pytrainer/trunk/pytrainer/importdata.py =================================================================== --- pytrainer/trunk/pytrainer/importdata.py 2010-02-15 08:26:32 UTC (rev 511) +++ pytrainer/trunk/pytrainer/importdata.py 2010-02-15 10:40:37 UTC (rev 512) @@ -27,9 +27,10 @@ def __init__(self, data_path = None, parent = None, config = None): self.data_path=data_path self.parent = parent + self.pytrainer_main = parent #self.conf = checkConf() self.configuration = config def runImportdata(self): - windowImportdata = WindowImportdata(self.data_path, self, self.configuration) + windowImportdata = WindowImportdata(self.data_path, self, self.configuration, self.pytrainer_main) windowImportdata.run() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-15 08:26:32 UTC (rev 511) +++ pytrainer/trunk/pytrainer/main.py 2010-02-15 10:40:37 UTC (rev 512) @@ -101,7 +101,7 @@ def __init__(self,filename = None, data_path = None): logging.debug('>>') self.data_path = data_path - self.version ="1.7.1_svn#511" + self.version ="1.7.1_svn#512" self.DB_version = 3 self.date = Date() # Checking profile @@ -369,7 +369,11 @@ def importData(self): logging.debug('>>') + activeplugins_before = self.plugins.getActivePlugins() self.importdata.runImportdata() + activeplugins_after = self.plugins.getActivePlugins() + #Need to check for plugins that have been disabled (were active and now are not) + self.setMenuPlugins(activeplugins_before, activeplugins_after) logging.debug('<<') def editGpsPlugins(self): @@ -378,6 +382,12 @@ self.plugins.managePlugins() activeplugins_after = self.plugins.getActivePlugins() #Need to check for plugins that have been disabled (were active and now are not) + self.setMenuPlugins(activeplugins_before, activeplugins_after) + logging.debug('<<') + + def setMenuPlugins(self, activeplugins_before, activeplugins_after): + logging.debug('>>') + #Need to check for plugins that have been disabled (were active and now are not) for plugin in activeplugins_before: if plugin not in activeplugins_after: #disabled plugin -> need to unload plugin This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-02-22 06:39:02
|
Revision: 514 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=514&view=rev Author: jblance Date: 2010-02-22 06:38:56 +0000 (Mon, 22 Feb 2010) Log Message: ----------- Update to edit record window in preparation for editing import info - currently incomplete and not visible Modified Paths: -------------- pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-02-17 09:27:56 UTC (rev 513) +++ pytrainer/trunk/glade/newrecord.glade 2010-02-22 06:38:56 UTC (rev 514) @@ -12,6 +12,24 @@ <property name="visible">True</property> <property name="orientation">vertical</property> <child> + <widget class="GtkScrolledWindow" id="scrolledwindowEntries"> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <widget class="GtkTreeView" id="treeviewEntries"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> <widget class="GtkNotebook" id="notebook2"> <property name="visible">True</property> <property name="can_focus">True</property> @@ -1079,7 +1097,8 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">0</property> + <property name="pack_type">end</property> + <property name="position">1</property> </packing> </child> <child> @@ -1130,7 +1149,8 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> - <property name="position">1</property> + <property name="pack_type">end</property> + <property name="position">0</property> </packing> </child> </widget> Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-17 09:27:56 UTC (rev 513) +++ pytrainer/trunk/pytrainer/main.py 2010-02-22 06:38:56 UTC (rev 514) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#513" + self.version ="1.7.1_svn#514" self.DB_version = 3 #Setup usage and permitted options This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-02-22 09:48:04
|
Revision: 515 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=515&view=rev Author: jblance Date: 2010-02-22 09:47:56 +0000 (Mon, 22 Feb 2010) Log Message: ----------- Start of converting the googleearth plugin to new plugin format Modified Paths: -------------- pytrainer/trunk/plugins/garmin-gpx/garmingpx.py pytrainer/trunk/plugins/garmin-tcxv2/garmin-tcxv2.py pytrainer/trunk/plugins/googleearth/main.py pytrainer/trunk/pytrainer/lib/gpx.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Added Paths: ----------- pytrainer/trunk/schemas/ogckml22.xsd Modified: pytrainer/trunk/plugins/garmin-gpx/garmingpx.py =================================================================== --- pytrainer/trunk/plugins/garmin-gpx/garmingpx.py 2010-02-22 06:38:56 UTC (rev 514) +++ pytrainer/trunk/plugins/garmin-gpx/garmingpx.py 2010-02-22 09:47:56 UTC (rev 515) @@ -61,7 +61,6 @@ if not self.inDatabase(filename): sport = self.getSport(filename) gpxfile = "%s/garmin-gpx-%d.gpx" % (self.tmpdir, len(importfiles)) - shutil shutil.copy(filename, gpxfile) importfiles.append((gpxfile, sport)) else: Modified: pytrainer/trunk/plugins/garmin-tcxv2/garmin-tcxv2.py =================================================================== --- pytrainer/trunk/plugins/garmin-tcxv2/garmin-tcxv2.py 2010-02-22 06:38:56 UTC (rev 514) +++ pytrainer/trunk/plugins/garmin-tcxv2/garmin-tcxv2.py 2010-02-22 09:47:56 UTC (rev 515) @@ -75,7 +75,7 @@ return True else: xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/GarminTrainingCenterDatabase_v2.xsd" - from lib.xmlValidation import xmlValidator + from pytrainer.lib.xmlValidation import xmlValidator validator = xmlValidator() return validator.validateXSL(filename, xslfile) Modified: pytrainer/trunk/plugins/googleearth/main.py =================================================================== --- pytrainer/trunk/plugins/googleearth/main.py 2010-02-22 06:38:56 UTC (rev 514) +++ pytrainer/trunk/plugins/googleearth/main.py 2010-02-22 09:47:56 UTC (rev 515) @@ -20,18 +20,83 @@ import os import commands +import logging +from lxml import etree +from pytrainer.gui.dialogs import fileChooserDialog, guiFlush class googleearth(): - def __init__(self, parent = None): + def __init__(self, parent = None, validate=False): self.parent = parent + self.validate = validate + self.data_path = os.path.dirname(__file__) self.tmpdir = self.parent.conf.getValue("tmpdir") def run(self): - f = os.popen("zenity --file-selection --title 'Choose a Google Earth file (.kml) to import'") - inputData = f.read().strip() + logging.debug(">>") + selectedFiles = fileChooserDialog(title="Choose a Google Earth file (.kml) to import", multiple=True).getFiles() + guiFlush() + importfiles = [] + if not selectedFiles: + return importfiles + for filename in selectedFiles: + if self.valid_input_file(filename): + if not self.inDatabase(filename): + sport = self.getSport(filename) #TODO Fix sport determination + gpxfile = "%s/googleearth-%d.gpx" % (self.tmpdir, len(importfiles)) + outgps = commands.getstatusoutput("gpsbabel -t -i kml -f %s -o gpx -F %s" % (filename, gpxfile) ) + #self.createGPXfile(gpxfile, filename) #TODO Fix processing so not dependant on the broken gpsbabel + importfiles.append((gpxfile, sport)) + else: + logging.debug("%s already in database. Skipping import." % (filename) ) + else: + logging.info("File %s failed validation" % (filename)) + logging.debug("<<") + return importfiles - tmpgpx="/tmp/reg.gpx" - outgps = commands.getstatusoutput("gpsbabel -t -i kml -f %s -o gpx -F %s" % (inputData, tmpgpx) ) + def valid_input_file(self, filename): + """ Function to validate input file if requested""" + if not self.validate: #not asked to validate + logging.debug("Not validating %s" % (filename) ) + return True + else: + return True + #TODO need to check schema and validation for example kml files + #xslfile = os.path.realpath(self.parent.parent.data_path)+ "/schemas/ogckml22.xsd" + #from pytrainer.lib.xmlValidation import xmlValidator + #validator = xmlValidator() + #return validator.validateXSL(filename, xslfile) + + def inDatabase(self, filename): + """ Function to determine if a given file has already been imported into the database + only compares date and start time (sport may have been changed in DB after import) + """ + #time = self.detailsFromKML(filename) + #if self.parent.parent.ddbb.select("records","*","date_time_utc=\"%s\"" % (time)): + # return True + #else: + return False + + def getSport(self, filename): + #TODO Fix sport determination + return "Run" + + def detailsFromKML(self, filename): + """ Function to return the first time element from a KML file """ + #TODO + #tree = xml.etree.cElementTree.ElementTree(file=filename) + #root = tree.getroot() + #timeElement = root.find(".//{http://www.topografix.com/GPX/1/1}time") + #if timeElement is None: + # return None + #else: + # return timeElement.text + + def createGPXfile(self, gpxfile, filename): + ''' Function to transform a GPSBabel kml file to a valid GPX+ file + ''' + #TODO!! + xslt_doc = etree.parse(self.data_path+"/translate.xsl") + transform = etree.XSLT(xslt_doc) + result_tree = transform(filename) + result_tree.write(gpxfile, xml_declaration=True) - return [tmpgpx, ] - Modified: pytrainer/trunk/pytrainer/lib/gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gpx.py 2010-02-22 06:38:56 UTC (rev 514) +++ pytrainer/trunk/pytrainer/lib/gpx.py 2010-02-22 09:47:56 UTC (rev 515) @@ -53,6 +53,7 @@ class Gpx: def __init__(self, data_path = None, filename = None, trkname = None): logging.debug(">>") + global mainNS, timeTag, trackTag, trackPointTag, trackPointTagLast, trackSegTag, elevationTag, nameTag self.data_path = data_path self.filename = filename self.trkname = trkname @@ -72,6 +73,28 @@ return None logging.debug("parsing content from "+self.filename) self.tree = etree.ElementTree(file=filename).getroot() + if self.tree.get("version") == "1.0": + #Got an old GPX file + print "Old gpx version" + mainNS = string.Template(".//{http://www.topografix.com/GPX/1/0}$tag") + timeTag = mainNS.substitute(tag="time") + trackTag = mainNS.substitute(tag="trk") + trackPointTag = mainNS.substitute(tag="trkpt") + trackPointTagLast = mainNS.substitute(tag="trkpt[last()]") + trackSegTag = mainNS.substitute(tag="trkseg") + elevationTag = mainNS.substitute(tag="ele") + nameTag = mainNS.substitute(tag="name") + else: + print self.tree.get("version") + mainNS = string.Template(".//{http://www.topografix.com/GPX/1/1}$tag") + timeTag = mainNS.substitute(tag="time") + trackTag = mainNS.substitute(tag="trk") + trackPointTag = mainNS.substitute(tag="trkpt") + trackPointTagLast = mainNS.substitute(tag="trkpt[last()]") + trackSegTag = mainNS.substitute(tag="trkseg") + elevationTag = mainNS.substitute(tag="ele") + nameTag = mainNS.substitute(tag="name") + logging.debug("getting values...") self.Values = self._getValues() logging.debug("<<") @@ -154,11 +177,14 @@ tree = self.tree # Calories data comes within laps. Maybe more than one, adding them together - dgranda 20100114 laps = tree.findall(lapTag) - for lap in laps: - lapCalories = lap.findtext(calorieTag) - logging.debug("Lap calories: "+str(lapCalories)) - self.calories += int(lapCalories) - logging.debug("Calories: "+str(self.calories)) + if laps is not None and laps != "": + for lap in laps: + lapCalories = lap.findtext(calorieTag) + logging.debug("Lap calories: "+str(lapCalories)) + self.calories += int(lapCalories) + logging.debug("Calories: "+str(self.calories)) + else: + laps = [] retorno = [] his_vel = [] @@ -169,9 +195,9 @@ total_hr = 0 tmp_alt = 0 len_validhrpoints = 0 - trkpoints = tree.findall(trackPointTag) - if not len(trkpoints): + if trkpoints is None or len(trkpoints) == 0: + logging.debug( "No trkpoints found in file") return retorno date_ = tree.find(timeTag).text @@ -179,6 +205,7 @@ mk_time = self.getDateTime(date_)[1] #Local Date self.date = mk_time.strftime("%Y-%m-%d") + for trkpoint in trkpoints: lat = trkpoint.get("lat") lon = trkpoint.get("lon") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-22 06:38:56 UTC (rev 514) +++ pytrainer/trunk/pytrainer/main.py 2010-02-22 09:47:56 UTC (rev 515) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#514" + self.version ="1.7.1_svn#515" self.DB_version = 3 #Setup usage and permitted options @@ -203,7 +203,9 @@ for (pluginFile, sport) in pluginFiles: if os.path.isfile(pluginFile): logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(pluginFile), sport)) - self.record.importFromGPX(pluginFile, sport) + if self.record.importFromGPX(pluginFile, sport) is None: + print "Error importing file "+pluginFile + logging.error("Error importing file "+pluginFile) else: logging.error('File '+pluginFile+' not valid') else: Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-02-22 06:38:56 UTC (rev 514) +++ pytrainer/trunk/pytrainer/record.py 2010-02-22 09:47:56 UTC (rev 515) @@ -181,7 +181,9 @@ Moves GPX file to store destination and updates database args: path to source GPX file""" logging.debug('--') - list_options, gpx_laps = self.summaryFromGPX(gpxOrig, entry) + (list_options, gpx_laps) = self.summaryFromGPX(gpxOrig, entry) + if list_options is None: + return None return self.insertRecord(list_options, laps=gpx_laps) def lapsFromGPX(self, gpx): @@ -214,7 +216,8 @@ gpx = Gpx(self.data_path,gpxOrig) distance, time, maxspeed, maxheartrate = gpx.getMaxValues() if time == 0: #invalid record - return None + print "Invalid record" + return (None, None) upositive,unegative = gpx.getUnevenness() speed = distance*3600/time time_hhmmss = [time//3600,(time/60)%60,time%60] Added: pytrainer/trunk/schemas/ogckml22.xsd =================================================================== --- pytrainer/trunk/schemas/ogckml22.xsd (rev 0) +++ pytrainer/trunk/schemas/ogckml22.xsd 2010-02-22 09:47:56 UTC (rev 515) @@ -0,0 +1,1642 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:kml="http://www.opengis.net/kml/2.2" + xmlns:atom="http://www.w3.org/2005/Atom" + xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" + targetNamespace="http://www.opengis.net/kml/2.2" + elementFormDefault="qualified" + version="2.2.0"> + + <xsd:annotation> + <xsd:appinfo>ogckml22.xsd 2008-01-23</xsd:appinfo> + <xsd:documentation>XML Schema Document for OGC KML version 2.2. Copyright (c) + 2008 Open Geospatial Consortium, Inc. All Rights Reserved. + </xsd:documentation> + </xsd:annotation> + + <!-- import atom:author and atom:link --> + <xsd:import namespace="http://www.w3.org/2005/Atom" + schemaLocation="atom-author-link.xsd"/> + + <!-- import xAL:Address --> + <xsd:import namespace="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" + schemaLocation="http://docs.oasis-open.org/election/external/xAL.xsd"/> + + <!-- KML field types (simple content) --> + + <xsd:simpleType name="anglepos90Type"> + <xsd:restriction base="double"> + <xsd:minInclusive value="0.0"/> + <xsd:maxInclusive value="90.0"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="angle90Type"> + <xsd:restriction base="double"> + <xsd:minInclusive value="-90"/> + <xsd:maxInclusive value="90.0"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="anglepos180Type"> + <xsd:restriction base="double"> + <xsd:minInclusive value="0.0"/> + <xsd:maxInclusive value="180.0"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="angle180Type"> + <xsd:restriction base="double"> + <xsd:minInclusive value="-180.0"/> + <xsd:maxInclusive value="180.0"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="angle360Type"> + <xsd:restriction base="double"> + <xsd:minInclusive value="-360.0"/> + <xsd:maxInclusive value="360.0"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="altitudeModeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="clampToGround"/> + <xsd:enumeration value="relativeToGround"/> + <xsd:enumeration value="absolute"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="colorType"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + + aabbggrr + + ffffffff: opaque white + ff000000: opaque black + + ]]></xsd:documentation> + </xsd:annotation> + <xsd:restriction base="hexBinary"> + <xsd:length value="4"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="coordinatesType"> + <xsd:list itemType="string"/> + </xsd:simpleType> + + <xsd:simpleType name="colorModeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="random"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="dateTimeType"> + <xsd:union memberTypes="dateTime date gYearMonth gYear"/> + </xsd:simpleType> + + <xsd:simpleType name="displayModeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="default"/> + <xsd:enumeration value="hide"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="gridOriginEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="lowerLeft"/> + <xsd:enumeration value="upperLeft"/> + </xsd:restriction> + </xsd:simpleType> + <xsd:simpleType name="itemIconStateType"> + <xsd:list itemType="kml:itemIconStateEnumType"/> + </xsd:simpleType> + + <xsd:simpleType name="itemIconStateEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="open"/> + <xsd:enumeration value="closed"/> + <xsd:enumeration value="error"/> + <xsd:enumeration value="fetching0"/> + <xsd:enumeration value="fetching1"/> + <xsd:enumeration value="fetching2"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="listItemTypeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="radioFolder"/> + <xsd:enumeration value="check"/> + <xsd:enumeration value="checkHideChildren"/> + <xsd:enumeration value="checkOffOnly"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="refreshModeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="onChange"/> + <xsd:enumeration value="onInterval"/> + <xsd:enumeration value="onExpire"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="viewRefreshModeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="never"/> + <xsd:enumeration value="onRequest"/> + <xsd:enumeration value="onStop"/> + <xsd:enumeration value="onRegion"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="shapeEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="rectangle"/> + <xsd:enumeration value="cylinder"/> + <xsd:enumeration value="sphere"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="styleStateEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="highlight"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="unitsEnumType"> + <xsd:restriction base="string"> + <xsd:enumeration value="fraction"/> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="insetPixels"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="vec2Type" abstract="false"> + <xsd:attribute name="x" type="double" default="1.0"/> + <xsd:attribute name="y" type="double" default="1.0"/> + <xsd:attribute name="xunits" type="kml:unitsEnumType" use="optional" + default="fraction"/> + <xsd:attribute name="yunits" type="kml:unitsEnumType" use="optional" + default="fraction"/> + </xsd:complexType> + + <xsd:element name="address" type="string"/> + <xsd:element name="altitude" type="double" default="0.0"/> + <xsd:element name="altitudeModeGroup" abstract="true"/> + <xsd:element name="altitudeMode" type="kml:altitudeModeEnumType" + default="clampToGround" substitutionGroup="kml:altitudeModeGroup"/> + <xsd:element name="begin" type="kml:dateTimeType"/> + <xsd:element name="bgColor" type="kml:colorType" default="ffffffff"/> + <xsd:element name="bottomFov" type="kml:angle90Type" default="0.0"/> + <xsd:element name="color" type="kml:colorType" default="ffffffff"/> + <xsd:element name="colorMode" type="kml:colorModeEnumType" default="normal"/> + <xsd:element name="cookie" type="string"/> + <xsd:element name="coordinates" type="kml:coordinatesType"/> + <xsd:element name="description" type="string"/> + <xsd:element name="displayName" type="string"/> + <xsd:element name="displayMode" type="kml:displayModeEnumType" default="default"/> + <xsd:element name="drawOrder" type="int" default="0"/> + <xsd:element name="east" type="kml:angle180Type" default="180.0"/> + <xsd:element name="end" type="kml:dateTimeType"/> + <xsd:element name="expires" type="kml:dateTimeType"/> + <xsd:element name="extrude" type="boolean" default="0"/> + <xsd:element name="fill" type="boolean" default="1"/> + <xsd:element name="flyToView" type="boolean" default="0"/> + <xsd:element name="gridOrigin" type="kml:gridOriginEnumType" default="lowerLeft"/> + <xsd:element name="heading" type="kml:angle360Type" default="0.0"/> + <xsd:element name="href" type="string"> + <xsd:annotation> + <xsd:documentation>not anyURI due to $[x] substitution in + PhotoOverlay</xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="httpQuery" type="string"/> + <xsd:element name="hotSpot" type="kml:vec2Type"/> + <xsd:element name="key" type="kml:styleStateEnumType" default="normal"/> + <xsd:element name="latitude" type="kml:angle90Type" default="0.0"/> + <xsd:element name="leftFov" type="kml:angle180Type" default="0.0"/> + <xsd:element name="linkDescription" type="string"/> + <xsd:element name="linkName" type="string"/> + <xsd:element name="linkSnippet" type="kml:SnippetType"/> + <xsd:element name="listItemType" type="kml:listItemTypeEnumType" default="check"/> + <xsd:element name="longitude" type="kml:angle180Type" default="0.0"/> + <xsd:element name="maxSnippetLines" type="int" default="2"/> + <xsd:element name="maxSessionLength" type="double" default="-1.0"/> + <xsd:element name="message" type="string"/> + <xsd:element name="minAltitude" type="double" default="0.0"/> + <xsd:element name="minFadeExtent" type="double" default="0.0"/> + <xsd:element name="minLodPixels" type="double" default="0.0"/> + <xsd:element name="minRefreshPeriod" type="double" default="0.0"/> + <xsd:element name="maxAltitude" type="double" default="0.0"/> + <xsd:element name="maxFadeExtent" type="double" default="0.0"/> + <xsd:element name="maxLodPixels" type="double" default="-1.0"/> + <xsd:element name="maxHeight" type="int" default="0"/> + <xsd:element name="maxWidth" type="int" default="0"/> + <xsd:element name="name" type="string"/> + <xsd:element name="near" type="double" default="0.0"/> + <xsd:element name="north" type="kml:angle180Type" default="180.0"/> + <xsd:element name="open" type="boolean" default="0"/> + <xsd:element name="outline" type="boolean" default="1"/> + <xsd:element name="overlayXY" type="kml:vec2Type"/> + <xsd:element name="phoneNumber" type="string"/> + <xsd:element name="range" type="double" default="0.0"/> + <xsd:element name="refreshMode" type="kml:refreshModeEnumType" + default="onChange"/> + <xsd:element name="refreshInterval" type="double" default="4.0"/> + <xsd:element name="refreshVisibility" type="boolean" default="0"/> + <xsd:element name="rightFov" type="kml:angle180Type" default="0.0"/> + <xsd:element name="roll" type="kml:angle180Type" default="0.0"/> + <xsd:element name="rotation" type="kml:angle180Type" default="0.0"/> + <xsd:element name="rotationXY" type="kml:vec2Type"/> + <xsd:element name="scale" type="double" default="1.0"/> + <xsd:element name="screenXY" type="kml:vec2Type"/> + <xsd:element name="shape" type="kml:shapeEnumType" default="rectangle"/> + <xsd:element name="size" type="kml:vec2Type"/> + <xsd:element name="south" type="kml:angle180Type" default="-180.0"/> + <xsd:element name="sourceHref" type="anyURI"/> + <xsd:element name="snippet" type="string"/> + <xsd:element name="state" type="kml:itemIconStateType"/> + <xsd:element name="styleUrl" type="anyURI"/> + <xsd:element name="targetHref" type="anyURI"/> + <xsd:element name="tessellate" type="boolean" default="0"/> + <xsd:element name="text" type="string"/> + <xsd:element name="textColor" type="kml:colorType" default="ff000000"/> + <xsd:element name="tileSize" type="int" default="256"/> + <xsd:element name="tilt" type="kml:anglepos180Type" default="0.0"/> + <xsd:element name="topFov" type="kml:angle90Type" default="0.0"/> + <xsd:element name="value" type="string"/> + <xsd:element name="viewBoundScale" type="double" default="1.0"/> + <xsd:element name="viewFormat" type="string"/> + <xsd:element name="viewRefreshMode" type="kml:viewRefreshModeEnumType" + default="never"/> + <xsd:element name="viewRefreshTime" type="double" default="4.0"/> + <xsd:element name="visibility" type="boolean" default="1"/> + <xsd:element name="west" type="kml:angle180Type" default="-180.0"/> + <xsd:element name="when" type="kml:dateTimeType"/> + <xsd:element name="width" type="double" default="1.0"/> + <xsd:element name="x" type="double" default="1.0"/> + <xsd:element name="y" type="double" default="1.0"/> + <xsd:element name="z" type="double" default="1.0"/> + + <xsd:element name="AbstractObjectGroup" type="kml:AbstractObjectType" + abstract="true"/> + <xsd:complexType name="AbstractObjectType" abstract="true"> + <xsd:sequence> + <xsd:element ref="kml:ObjectSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attributeGroup ref="kml:idAttributes"/> + </xsd:complexType> + <xsd:element name="ObjectSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + + <xsd:attributeGroup name="idAttributes"> + <xsd:attribute name="id" type="ID" use="optional"/> + <xsd:attribute name="targetId" type="NCName" use="optional"/> + </xsd:attributeGroup> + + <xsd:element name="AbstractFeatureGroup" type="kml:AbstractFeatureType" + abstract="true" substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="AbstractFeatureType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:name" minOccurs="0"/> + <xsd:element ref="kml:visibility" minOccurs="0"/> + <xsd:element ref="kml:open" minOccurs="0"/> + <xsd:element ref="atom:author" minOccurs="0"/> + <xsd:element ref="atom:link" minOccurs="0"/> + <xsd:element ref="kml:address" minOccurs="0"/> + <xsd:element ref="xal:AddressDetails" minOccurs="0"/> + <xsd:element ref="kml:phoneNumber" minOccurs="0"/> + <xsd:choice> + <xsd:annotation> + <xsd:documentation>Snippet deprecated in 2.2</xsd:documentation> + </xsd:annotation> + <xsd:element ref="kml:Snippet" minOccurs="0"/> + <xsd:element ref="kml:snippet" minOccurs="0"/> + </xsd:choice> + <xsd:element ref="kml:description" minOccurs="0"/> + <xsd:element ref="kml:AbstractViewGroup" minOccurs="0"/> + <xsd:element ref="kml:AbstractTimePrimitiveGroup" minOccurs="0"/> + <xsd:element ref="kml:styleUrl" minOccurs="0"/> + <xsd:element ref="kml:AbstractStyleSelectorGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:Region" minOccurs="0"/> + <xsd:choice> + <xsd:annotation> + <xsd:documentation>Metadata deprecated in 2.2</xsd:documentation> + </xsd:annotation> + <xsd:element ref="kml:Metadata" minOccurs="0"/> + <xsd:element ref="kml:ExtendedData" minOccurs="0"/> + </xsd:choice> + <xsd:element ref="kml:AbstractFeatureSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractFeatureObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractFeatureObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:element name="AbstractFeatureSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + + <xsd:element name="Snippet" type="kml:SnippetType"/> + <xsd:complexType name="SnippetType" final="#all"> + <xsd:simpleContent> + <xsd:extension base="string"> + <xsd:attribute name="maxLines" type="int" use="optional" default="2"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + <xsd:element name="AbstractViewGroup" type="kml:AbstractViewType" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="AbstractViewType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractViewSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractViewObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractViewSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AbstractViewObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="LookAt" type="kml:LookAtType" + substitutionGroup="kml:AbstractViewGroup"/> + <xsd:complexType name="LookAtType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractViewType"> + <xsd:sequence> + <xsd:element ref="kml:longitude" minOccurs="0"/> + <xsd:element ref="kml:latitude" minOccurs="0"/> + <xsd:element ref="kml:altitude" minOccurs="0"/> + <xsd:element ref="kml:heading" minOccurs="0"/> + <xsd:element ref="kml:tilt" minOccurs="0"/> + <xsd:element ref="kml:range" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:LookAtSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LookAtObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LookAtSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="LookAtObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Camera" type="kml:CameraType" + substitutionGroup="kml:AbstractViewGroup"/> + <xsd:complexType name="CameraType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractViewType"> + <xsd:sequence> + <xsd:element ref="kml:longitude" minOccurs="0"/> + <xsd:element ref="kml:latitude" minOccurs="0"/> + <xsd:element ref="kml:altitude" minOccurs="0"/> + <xsd:element ref="kml:heading" minOccurs="0"/> + <xsd:element ref="kml:tilt" minOccurs="0"/> + <xsd:element ref="kml:roll" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:CameraSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:CameraObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="CameraSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="CameraObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Metadata" type="kml:MetadataType"> + <xsd:annotation> + <xsd:documentation>Metadata deprecated in 2.2</xsd:documentation> + </xsd:annotation> + </xsd:element> + + <xsd:complexType name="MetadataType" final="#all"> + <xsd:annotation> + <xsd:documentation>MetadataType deprecated in 2.2</xsd:documentation> + </xsd:annotation> + <xsd:sequence> + <xsd:any namespace="##any" processContents="lax" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="ExtendedData" type="kml:ExtendedDataType"/> + <xsd:complexType name="ExtendedDataType" final="#all"> + <xsd:sequence> + <xsd:element ref="kml:Data" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:SchemaData" minOccurs="0" maxOccurs="unbounded"/> + <xsd:any namespace="##other" processContents="lax" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:element name="SchemaData" type="kml:SchemaDataType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="SchemaDataType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:SimpleData" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:SchemaDataExtension" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="schemaUrl" type="anyURI"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="SchemaDataExtension" abstract="true"/> + + <xsd:element name="SimpleData" type="kml:SimpleDataType"/> + <xsd:complexType name="SimpleDataType" final="#all"> + <xsd:simpleContent> + <xsd:extension base="string"> + <xsd:attribute name="name" type="string" use="required"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + <xsd:element name="Data" type="kml:DataType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="DataType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:displayName" minOccurs="0"/> + <xsd:element ref="kml:value"/> + <xsd:element ref="kml:DataExtension" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="name" type="string"/> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="DataExtension" abstract="true"/> + + <xsd:element name="AbstractContainerGroup" type="kml:AbstractContainerType" + abstract="true" substitutionGroup="kml:AbstractFeatureGroup"/> + <xsd:complexType name="AbstractContainerType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractFeatureType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractContainerSimpleExtensionGroup" + minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractContainerObjectExtensionGroup" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractContainerSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AbstractContainerObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="AbstractGeometryGroup" type="kml:AbstractGeometryType" + abstract="true" substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="AbstractGeometryType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractGeometrySimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractGeometryObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractGeometrySimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AbstractGeometryObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="AbstractOverlayGroup" type="kml:AbstractOverlayType" + abstract="true" substitutionGroup="kml:AbstractFeatureGroup"/> + <xsd:complexType name="AbstractOverlayType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractFeatureType"> + <xsd:sequence> + <xsd:element ref="kml:color" minOccurs="0"/> + <xsd:element ref="kml:drawOrder" minOccurs="0"/> + <xsd:element ref="kml:Icon" minOccurs="0"/> + <xsd:element ref="kml:AbstractOverlaySimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractOverlayObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractOverlaySimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AbstractOverlayObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="AbstractStyleSelectorGroup" + type="kml:AbstractStyleSelectorType" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="AbstractStyleSelectorType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractStyleSelectorSimpleExtensionGroup" + minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractStyleSelectorObjectExtensionGroup" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractStyleSelectorSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AbstractStyleSelectorObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="AbstractTimePrimitiveGroup" + type="kml:AbstractTimePrimitiveType" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="AbstractTimePrimitiveType" abstract="true"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractTimePrimitiveSimpleExtensionGroup" + minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractTimePrimitiveObjectExtensionGroup" + minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AbstractTimePrimitiveSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AbstractTimePrimitiveObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="kml" type="kml:KmlType"> + <xsd:annotation> + <xsd:documentation><![CDATA[ + + <kml> is the root element. + + ]]></xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:complexType name="KmlType" final="#all"> + <xsd:sequence> + <xsd:element ref="kml:NetworkLinkControl" minOccurs="0"/> + <xsd:element ref="kml:AbstractFeatureGroup" minOccurs="0"/> + <xsd:element ref="kml:KmlSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:KmlObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="hint" type="string"/> + </xsd:complexType> + <xsd:element name="KmlSimpleExtensionGroup" abstract="true" type="anySimpleType"/> + <xsd:element name="KmlObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="NetworkLinkControl" type="kml:NetworkLinkControlType"/> + <xsd:complexType name="NetworkLinkControlType" final="#all"> + <xsd:sequence> + <xsd:element ref="kml:minRefreshPeriod" minOccurs="0"/> + <xsd:element ref="kml:maxSessionLength" minOccurs="0"/> + <xsd:element ref="kml:cookie" minOccurs="0"/> + <xsd:element ref="kml:message" minOccurs="0"/> + <xsd:element ref="kml:linkName" minOccurs="0"/> + <xsd:element ref="kml:linkDescription" minOccurs="0"/> + <xsd:element ref="kml:linkSnippet" minOccurs="0"/> + <xsd:element ref="kml:expires" minOccurs="0"/> + <xsd:element ref="kml:Update" minOccurs="0"/> + <xsd:element ref="kml:AbstractViewGroup" minOccurs="0"/> + <xsd:element ref="kml:NetworkLinkControlSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:NetworkLinkControlObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="NetworkLinkControlSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="NetworkLinkControlObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Document" type="kml:DocumentType" + substitutionGroup="kml:AbstractContainerGroup"/> + <xsd:complexType name="DocumentType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractContainerType"> + <xsd:sequence> + <xsd:element ref="kml:Schema" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:AbstractFeatureGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:DocumentSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:DocumentObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="DocumentSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="DocumentObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Schema" type="kml:SchemaType"/> + <xsd:complexType name="SchemaType" final="#all"> + <xsd:sequence> + <xsd:element ref="kml:SimpleField" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:SchemaExtension" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="name" type="string"/> + <xsd:attribute name="id" type="ID"/> + </xsd:complexType> + <xsd:element name="SchemaExtension" abstract="true"/> + + <xsd:element name="SimpleField" type="kml:SimpleFieldType"/> + <xsd:complexType name="SimpleFieldType" final="#all"> + <xsd:sequence> + <xsd:element ref="kml:displayName" minOccurs="0"/> + <xsd:element ref="kml:SimpleFieldExtension" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="type" type="string"/> + <xsd:attribute name="name" type="string"/> + </xsd:complexType> + <xsd:element name="SimpleFieldExtension" abstract="true"/> + + <xsd:element name="Folder" type="kml:FolderType" + substitutionGroup="kml:AbstractContainerGroup"/> + <xsd:complexType name="FolderType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractContainerType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractFeatureGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:FolderSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:FolderObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="FolderSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="FolderObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Placemark" type="kml:PlacemarkType" + substitutionGroup="kml:AbstractFeatureGroup"/> + <xsd:complexType name="PlacemarkType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractFeatureType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractGeometryGroup" minOccurs="0"/> + <xsd:element ref="kml:PlacemarkSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:PlacemarkObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="PlacemarkSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="PlacemarkObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="NetworkLink" type="kml:NetworkLinkType" + substitutionGroup="kml:AbstractFeatureGroup"/> + <xsd:complexType name="NetworkLinkType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractFeatureType"> + <xsd:sequence> + <xsd:element ref="kml:refreshVisibility" minOccurs="0"/> + <xsd:element ref="kml:flyToView" minOccurs="0"/> + <xsd:choice> + <xsd:annotation> + <xsd:documentation>Url deprecated in 2.2</xsd:documentation> + </xsd:annotation> + <xsd:element ref="kml:Url" minOccurs="0"/> + <xsd:element ref="kml:Link" minOccurs="0"/> + </xsd:choice> + <xsd:element ref="kml:NetworkLinkSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:NetworkLinkObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="NetworkLinkSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="NetworkLinkObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Region" type="kml:RegionType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="RegionType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:LatLonAltBox" minOccurs="0"/> + <xsd:element ref="kml:Lod" minOccurs="0"/> + <xsd:element ref="kml:RegionSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:RegionObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="RegionSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="RegionObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="LatLonAltBox" type="kml:LatLonAltBoxType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="LatLonAltBoxType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractLatLonBoxType"> + <xsd:sequence> + <xsd:element ref="kml:minAltitude" minOccurs="0"/> + <xsd:element ref="kml:maxAltitude" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:LatLonAltBoxSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LatLonAltBoxObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LatLonAltBoxSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="LatLonAltBoxObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Lod" type="kml:LodType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="LodType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:minLodPixels" minOccurs="0"/> + <xsd:element ref="kml:maxLodPixels" minOccurs="0"/> + <xsd:element ref="kml:minFadeExtent" minOccurs="0"/> + <xsd:element ref="kml:maxFadeExtent" minOccurs="0"/> + <xsd:element ref="kml:LodSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LodObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LodSimpleExtensionGroup" abstract="true" type="anySimpleType"/> + <xsd:element name="LodObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Icon" type="kml:LinkType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:element name="Link" type="kml:LinkType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:element name="Url" type="kml:LinkType" + substitutionGroup="kml:AbstractObjectGroup"> + <xsd:annotation> + <xsd:documentation>Url deprecated in 2.2</xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:complexType name="LinkType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:BasicLinkType"> + <xsd:sequence> + <xsd:element ref="kml:refreshMode" minOccurs="0"/> + <xsd:element ref="kml:refreshInterval" minOccurs="0"/> + <xsd:element ref="kml:viewRefreshMode" minOccurs="0"/> + <xsd:element ref="kml:viewRefreshTime" minOccurs="0"/> + <xsd:element ref="kml:viewBoundScale" minOccurs="0"/> + <xsd:element ref="kml:viewFormat" minOccurs="0"/> + <xsd:element ref="kml:httpQuery" minOccurs="0"/> + <xsd:element ref="kml:LinkSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LinkObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LinkSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="LinkObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="MultiGeometry" type="kml:MultiGeometryType" + substitutionGroup="kml:AbstractGeometryGroup"/> + <xsd:complexType name="MultiGeometryType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractGeometryType"> + <xsd:sequence> + <xsd:element ref="kml:AbstractGeometryGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:MultiGeometrySimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:MultiGeometryObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="MultiGeometrySimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="MultiGeometryObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Point" type="kml:PointType" + substitutionGroup="kml:AbstractGeometryGroup"/> + <xsd:complexType name="PointType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractGeometryType"> + <xsd:sequence> + <xsd:element ref="kml:extrude" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:coordinates" minOccurs="0"/> + <xsd:element ref="kml:PointSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:PointObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="PointSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="PointObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="LineString" type="kml:LineStringType" + substitutionGroup="kml:AbstractGeometryGroup"/> + <xsd:complexType name="LineStringType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractGeometryType"> + <xsd:sequence> + <xsd:element ref="kml:extrude" minOccurs="0"/> + <xsd:element ref="kml:tessellate" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:coordinates" minOccurs="0"/> + <xsd:element ref="kml:LineStringSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LineStringObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LineStringSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="LineStringObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="LinearRing" type="kml:LinearRingType" + substitutionGroup="kml:AbstractGeometryGroup"/> + <xsd:complexType name="LinearRingType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractGeometryType"> + <xsd:sequence> + <xsd:element ref="kml:extrude" minOccurs="0"/> + <xsd:element ref="kml:tessellate" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:coordinates" minOccurs="0"/> + <xsd:element ref="kml:LinearRingSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LinearRingObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LinearRingSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="LinearRingObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Polygon" type="kml:PolygonType" + substitutionGroup="kml:AbstractGeometryGroup"/> + <xsd:complexType name="PolygonType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractGeometryType"> + <xsd:sequence> + <xsd:element ref="kml:extrude" minOccurs="0"/> + <xsd:element ref="kml:tessellate" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:outerBoundaryIs" minOccurs="0"/> + <xsd:element ref="kml:innerBoundaryIs" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:PolygonSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:PolygonObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="PolygonSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="PolygonObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="outerBoundaryIs" type="kml:BoundaryType"/> + <xsd:element name="innerBoundaryIs" type="kml:BoundaryType"/> + <xsd:complexType name="BoundaryType" final="#all"> + <xsd:sequence> + <xsd:element ref="kml:LinearRing" minOccurs="0"/> + <xsd:element ref="kml:BoundarySimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:BoundaryObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:complexType> + <xsd:element name="BoundarySimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="BoundaryObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Model" type="kml:ModelType" + substitutionGroup="kml:AbstractGeometryGroup"/> + <xsd:complexType name="ModelType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractGeometryType"> + <xsd:sequence> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:Location" minOccurs="0"/> + <xsd:element ref="kml:Orientation" minOccurs="0"/> + <xsd:element ref="kml:Scale" minOccurs="0"/> + <xsd:element ref="kml:Link" minOccurs="0"/> + <xsd:element ref="kml:ResourceMap" minOccurs="0"/> + <xsd:element ref="kml:ModelSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:ModelObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="ModelSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="ModelObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Location" type="kml:LocationType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="LocationType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:longitude" minOccurs="0"/> + <xsd:element ref="kml:latitude" minOccurs="0"/> + <xsd:element ref="kml:altitude" minOccurs="0"/> + <xsd:element ref="kml:LocationSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:LocationObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="LocationSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="LocationObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Orientation" type="kml:OrientationType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="OrientationType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:heading" minOccurs="0"/> + <xsd:element ref="kml:tilt" minOccurs="0"/> + <xsd:element ref="kml:roll" minOccurs="0"/> + <xsd:element ref="kml:OrientationSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:OrientationObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="OrientationSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="OrientationObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Scale" type="kml:ScaleType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="ScaleType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:x" minOccurs="0"/> + <xsd:element ref="kml:y" minOccurs="0"/> + <xsd:element ref="kml:z" minOccurs="0"/> + <xsd:element ref="kml:ScaleSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:ScaleObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="ScaleSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="ScaleObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="ResourceMap" type="kml:ResourceMapType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="ResourceMapType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:Alias" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="kml:ResourceMapSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:ResourceMapObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="ResourceMapSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="ResourceMapObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="Alias" type="kml:AliasType" + substitutionGroup="kml:AbstractObjectGroup"/> + <xsd:complexType name="AliasType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractObjectType"> + <xsd:sequence> + <xsd:element ref="kml:targetHref" minOccurs="0"/> + <xsd:element ref="kml:sourceHref" minOccurs="0"/> + <xsd:element ref="kml:AliasSimpleExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + <xsd:element ref="kml:AliasObjectExtensionGroup" minOccurs="0" + maxOccurs="unbounded"/> + </xsd:sequence> + </xsd:extension> + </xsd:complexContent> + </xsd:complexType> + <xsd:element name="AliasSimpleExtensionGroup" abstract="true" + type="anySimpleType"/> + <xsd:element name="AliasObjectExtensionGroup" abstract="true" + substitutionGroup="kml:AbstractObjectGroup"/> + + <xsd:element name="GroundOverlay" type="kml:GroundOverlayType" + substitutionGroup="kml:AbstractOverlayGroup"/> + <xsd:complexType name="GroundOverlayType" final="#all"> + <xsd:complexContent> + <xsd:extension base="kml:AbstractOverlayType"> + <xsd:sequence> + <xsd:element ref="kml:altitude" minOccurs="0"/> + <xsd:element ref="kml:altitudeModeGroup" minOccurs="0"/> + <xsd:element ref="kml:LatLonBox" minOccurs="0"/> + <xsd:element ref="km... [truncated message content] |
From: <jb...@us...> - 2010-02-25 10:03:41
|
Revision: 517 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=517&view=rev Author: jblance Date: 2010-02-25 10:03:33 +0000 (Thu, 25 Feb 2010) Log Message: ----------- Start of 'editing details before import work' for unified import Modified Paths: -------------- pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/lib/gpx.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-02-25 08:50:25 UTC (rev 516) +++ pytrainer/trunk/glade/newrecord.glade 2010-02-25 10:03:33 UTC (rev 517) @@ -24,8 +24,6 @@ </child> </widget> <packing> - <property name="expand">False</property> - <property name="fill">False</property> <property name="position">2</property> </packing> </child> Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-25 08:50:25 UTC (rev 516) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-02-25 10:03:33 UTC (rev 517) @@ -395,36 +395,42 @@ for item in self.activities_store: if item[1] is True: #Checkbox is True logging.debug("Added activity %s to selected list" % item) - selectedActivities.append(item) + file_id = int(item[7]) + activity_id = item[0] + start_time = item[2] + distance = item[3] + duration = item[4] + sport = item[5] + gpx_file = self.processClasses[file_id].getGPXFile(activity_id)[1] + selectedActivities.append((activity_id, start_time, distance, duration, sport, gpx_file)) logging.debug( "Found %d selected activities to import" % len(selectedActivities) ) return selectedActivities - def importSelectedActivity(self, activity): + def importSelectedActivities(self, activities): """ Function to import selected activity """ - activity_id = activity[0] - #selected = activity[1] - #start_time = activity[2] - #distance = activity[3] - #duration = activity[4] - #sport = activity[5] - #notes = activity[6] - file_id = int(activity[7]) - logging.debug( "Importing activity %s from file %s" % (activity_id, file_id)) - sport, gpxFile = self.processClasses[file_id].getGPXFile(activity_id) + #selectedActivities.append((activity_id, start_time, distance, duration, sport, gpx_file)) + logging.debug( "Importing %d activities" % len(activities)) + list_sport = self.pytrainer_main.profile.getSportList() + self.pytrainer_main.record.newMultiRecord(activities, list_sport) + #sport, gpxFile = self.processClasses[file_id].getGPXFile(activity_id) #process returned GPX files - if os.path.isfile(gpxFile): + '''if os.path.isfile(gpxFile): logging.info('File exists. Size: %d. Sport: %s' % (os.path.getsize(gpxFile), sport)) #TODO trigger newentry screen to allow user to edit data - self.parent.parent.record.importFromGPX(gpxFile, sport) + #list_sport = self.pytrainer_main.profile.getSportList() + #logging.debug('id_record: '+str(id_record)+' | list_sport: '+str(list_sport)) + #def newRecord(self, list_sport, date, title=None, distance=None, time=None, upositive=None, unegative=None, bpm=None, calories=None, comment=None): + #self.pytrainer_main.record.newMultiRecord(list_sport, date=start_time, distance=distance, time=duration, comment=sport) + #self.pytrainer_main.record.importFromGPX(gpxFile, sport) #Deselect imported activity and change note self.updateActivity(activity_id, file_id, status=False, notes="Imported into database") else: logging.error('File %s not valid' % gpxFile) + ''' - def updateActivity(self, activityID, file_id, status = None, notes = None): path = 0 for item in self.activities_store: @@ -554,9 +560,8 @@ self.updateStatusbar(self.statusbarImportFile, msgImporting) while gtk.events_pending(): # This allows the GUI to update gtk.main_iteration() # before completion of this entire action - for activity in selectedActivities: - self.importSelectedActivity(activity) - #TODO progress bar here?? + #for activity in selectedActivities: + self.importSelectedActivities(selectedActivities) self.updateStatusbar(self.statusbarImportFile, msgImported) #Display informational dialog box md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, msgImported) Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-02-25 08:50:25 UTC (rev 516) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-02-25 10:03:33 UTC (rev 517) @@ -18,6 +18,7 @@ import os import logging +import gtk, gobject from SimpleGladeApp import SimpleGladeApp from windowcalendar import WindowCalendar from filechooser import FileChooser @@ -34,6 +35,7 @@ domain = None self.mode = "newrecord" self.id_record = "" + self.store = None SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) self.conf_options = [ "rcd_date", @@ -77,7 +79,49 @@ self.rcd_unegative.set_text(unegative) if calories != None: self.rcd_calories.set_text(calories) + + def populateMultiWindow(self, activities): + #activities (activity_id, start_time, distance, duration, sport, gpx_file) + #Make treeview + self.store = self.build_tree_view() + #Add data + for activity in activities: + iter = self.store.append() + self.store.set( + iter, + 0, activity[0], + 1, activity[1], + 2, activity[2], + 3, activity[3], + 4, activity[4], + 5, activity[5] + ) + #Make row clickable to show details + #Select first activity + + self.scrolledwindowEntries.show_all() + + def build_tree_view(self): + store = gtk.ListStore( gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING ) + column_names=["id", _("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("GPX File")] + for column_index, column_name in enumerate(column_names): + #Add columns + column = gtk.TreeViewColumn(column_name, gtk.CellRendererText(), text=column_index) + column.set_sort_column_id(column_index) + #if column_name == "id": + # column.set_visible(False) + column.set_resizable(True) + self.treeviewEntries.append_column(column) + self.treeviewEntries.set_headers_clickable(True) + self.treeviewEntries.set_model(store) + return store + def on_accept_clicked(self,widget): list_options = {} trackSummary = {} Modified: pytrainer/trunk/pytrainer/lib/gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gpx.py 2010-02-25 08:50:25 UTC (rev 516) +++ pytrainer/trunk/pytrainer/lib/gpx.py 2010-02-25 10:03:33 UTC (rev 517) @@ -75,7 +75,7 @@ self.tree = etree.ElementTree(file=filename).getroot() if self.tree.get("version") == "1.0": #Got an old GPX file - print "Old gpx version" + logging.debug("Old gpx version") mainNS = string.Template(".//{http://www.topografix.com/GPX/1/0}$tag") timeTag = mainNS.substitute(tag="time") trackTag = mainNS.substitute(tag="trk") @@ -85,7 +85,7 @@ elevationTag = mainNS.substitute(tag="ele") nameTag = mainNS.substitute(tag="name") else: - print self.tree.get("version") + logging.debug("Importing version %s gpx file" % self.tree.get("version")) mainNS = string.Template(".//{http://www.topografix.com/GPX/1/1}$tag") timeTag = mainNS.substitute(tag="time") trackTag = mainNS.substitute(tag="trk") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-02-25 08:50:25 UTC (rev 516) +++ pytrainer/trunk/pytrainer/main.py 2010-02-25 10:03:33 UTC (rev 517) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#516" + self.version ="1.7.1_svn#517" self.DB_version = 3 #Setup usage and permitted options Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-02-25 08:50:25 UTC (rev 516) +++ pytrainer/trunk/pytrainer/record.py 2010-02-25 10:03:33 UTC (rev 517) @@ -48,9 +48,18 @@ logging.debug('<<') def newRecord(self, list_sport, date, title=None, distance=None, time=None, upositive=None, unegative=None, bpm=None, calories=None, comment=None): + logging.debug('>>') self.recordwindow = WindowRecord(self.data_path, list_sport,self, date, title, distance, time, upositive, unegative, bpm, calories, comment) self.recordwindow.run() logging.debug('<<') + + def newMultiRecord(self, activities, list_sport): + logging.debug('>>') + #activities (activity_id, start_time, distance, duration, sport, gpx_file) + self.recordwindow = WindowRecord(self.data_path, list_sport, windowTitle="Modify details before importing") + self.recordwindow.populateMultiWindow(activities) + self.recordwindow.run() + logging.debug('<<') def editRecord(self,id_record,list_sport): logging.debug('>>') @@ -497,7 +506,6 @@ Add a record from a valid pytrainer type GPX file """ logging.debug('>>') - print gpxFile if not os.path.isfile(gpxFile): logging.error("Invalid file: " +gpxFile) else: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dg...@us...> - 2010-03-03 22:25:42
|
Revision: 518 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=518&view=rev Author: dgranda Date: 2010-03-03 22:25:30 +0000 (Wed, 03 Mar 2010) Log Message: ----------- Removing Firefox from dependencies, reviewing others Modified Paths: -------------- pytrainer/trunk/INSTALL pytrainer/trunk/bin/pytrainer Modified: pytrainer/trunk/INSTALL =================================================================== --- pytrainer/trunk/INSTALL 2010-02-25 10:03:33 UTC (rev 517) +++ pytrainer/trunk/INSTALL 2010-03-03 22:25:30 UTC (rev 518) @@ -7,11 +7,12 @@ Here you are dependencies for PyTrainer. Of course you must have a working environment with proper shell configuration and typical GNU tools to uncompress (gunzip) and untar (tar) files. -1.1.- Packages (Fedora 12 working versions as of 2010.01.21 for 1.7.1) +1.1.- Packages (Fedora 12 working versions as of 2010.03.03 for 1.7.2 dev) python-2.6.2 python-devel-2.6.2 (to run installation from tarball) python-matplotlib-0.98.5.2 +python-dateutil-1.4.1 gnome-python2-gtkmozembed-2.25.3 pygtk2-libglade-2.16.0 pygtk2-2.16.0 @@ -22,8 +23,7 @@ libxslt-python-1.1.26 libxslt-1.1.26 sqlite-3.6.20 (sqlite is preferred as db than mysql) -xulrunner-1.9.1.6 -firefox-3.5.6 +xulrunner-1.9.1.8 - Only needed if correspondent plugin is enabled: gpsbabel-1.3.5 ("Garmin via GPSBabel 1.3.5" aka garmin_hr) Modified: pytrainer/trunk/bin/pytrainer =================================================================== --- pytrainer/trunk/bin/pytrainer 2010-02-25 10:03:33 UTC (rev 517) +++ pytrainer/trunk/bin/pytrainer 2010-03-03 22:25:30 UTC (rev 518) @@ -38,9 +38,6 @@ from pytrainer.main import pyTrainer -os.environ['MOZILLA_FIVE_HOME']="/usr/lib/firefox" -os.environ['LD_LIBRARY_PATH']="/usr/lib/firefox" -#os.environ['MOZILLA_FIVE_HOME']="/usr/lib64/xulrunner-1.9.1" os.environ['MOZILLA_FIVE_HOME']=commands.getstatusoutput("find /usr/li* -name xulrunner -exec dirname {} \; 2>/dev/null")[1] def main(argv): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-04 09:07:57
|
Revision: 519 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=519&view=rev Author: jblance Date: 2010-03-04 09:07:17 +0000 (Thu, 04 Mar 2010) Log Message: ----------- Unified import - auto start file import option Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-03-03 22:25:30 UTC (rev 518) +++ pytrainer/trunk/glade/importdata.glade 2010-03-04 09:07:17 UTC (rev 519) @@ -475,6 +475,7 @@ <child> <widget class="GtkHBox" id="hboxDefaultTab"> <property name="visible">True</property> + <property name="orientation">vertical</property> <child> <widget class="GtkRadioButton" id="radiobuttonTabGPSDevice"> <property name="label" translatable="yes">Import from GPS Device</property> @@ -492,19 +493,41 @@ </packing> </child> <child> - <widget class="GtkRadioButton" id="radiobuttonFile"> - <property name="label" translatable="yes">Import from File</property> + <widget class="GtkHBox" id="hbox1"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <property name="group">radiobuttonTabGPSDevice</property> + <child> + <widget class="GtkRadioButton" id="radiobuttonFile"> + <property name="label" translatable="yes">Import from File</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + <property name="group">radiobuttonTabGPSDevice</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="checkbuttonAutoLaunch"> + <property name="label" translatable="yes">Launch 'File Select' on start</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip" translatable="yes">Automatically start the file selection dialog</property> + <property name="xalign">0.47999998927116394</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">10</property> + <property name="position">1</property> + </packing> + </child> </widget> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">10</property> <property name="position">1</property> </packing> </child> Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-03-03 22:25:30 UTC (rev 518) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-03-04 09:07:17 UTC (rev 519) @@ -51,16 +51,21 @@ self.defaulttab = 0 else: self.defaulttab = int(self.defaulttab) + self.auto_launch = self.configuration.getValue("pytraining","auto_launch_file_selection") + if self.auto_launch == "True": + self.auto_launch = True + else: + self.auto_launch = False self.notebookMainTabs.set_current_page(self.defaulttab) - self.init_tab(self.defaulttab) + self.init_tab(self.defaulttab, first=True) - def init_tab(self, page): + def init_tab(self, page, first=False): if page == 0: #'Import from GPS Device' tab self.init_gpsdevice_tab() elif page == 1: #'Import from File' tab - self.init_file_tab() + self.init_file_tab(first) elif page ==2: #'Plugins' tab self.init_plugins_tab() @@ -80,7 +85,7 @@ def init_gpsdevice_tab(self): return - def init_file_tab(self): + def init_file_tab(self, first=False): #self.filechooserbuttonSelectFile.unselect_all() self.updateStatusbar(self.statusbarImportFile, _("No file selected") ) self.processClasses = [] @@ -94,6 +99,11 @@ self.files_store.clear() self.buttonRemoveSelectedFiles.set_sensitive(0) self.buttonFileImport.set_sensitive(0) + if first and self.auto_launch: + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + print "autolaunch active" + self.buttonSelectFiles.clicked() return def init_plugins_tab(self): @@ -147,10 +157,13 @@ #Set correct radiobutton based on saved preference if self.defaulttab == 1: self.radiobuttonFile.set_active(1) + self.checkbuttonAutoLaunch.set_sensitive(1) elif self.defaulttab == 2: self.radiobuttonPlugins.set_active(1) else: self.radiobuttonTabGPSDevice.set_active(1) + if self.auto_launch: + self.checkbuttonAutoLaunch.set_active(1) return def detect_tools(self): @@ -346,14 +359,18 @@ """ Save options selected in options tab """ + self.autoLaunchFileSelection = "False" #Default tab option if self.radiobuttonTabGPSDevice.get_active(): self.defaulttab = "0" elif self.radiobuttonFile.get_active(): self.defaulttab = "1" + if self.checkbuttonAutoLaunch.get_active(): + self.autoLaunchFileSelection = "True" elif self.radiobuttonPlugins.get_active(): self.defaulttab = "2" self.configuration.setValue("pytraining","import_default_tab",self.defaulttab) + self.configuration.setValue("pytraining","auto_launch_file_selection",self.autoLaunchFileSelection) #option def removeSelectedFiles(self): @@ -450,6 +467,9 @@ ## Window signal handlers ## ############################ + def on_radiobuttonFile_toggled(self, *args): + print "radio button toggled" + def on_pluginsButton_Configure_clicked(self, button, pluginClass): ''' Handler for plugin Buttons Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-03 22:25:30 UTC (rev 518) +++ pytrainer/trunk/pytrainer/main.py 2010-03-04 09:07:17 UTC (rev 519) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#517" + self.version ="1.7.1_svn#519" self.DB_version = 3 #Setup usage and permitted options This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dg...@us...> - 2010-03-04 17:58:56
|
Revision: 520 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=520&view=rev Author: dgranda Date: 2010-03-04 17:58:49 +0000 (Thu, 04 Mar 2010) Log Message: ----------- Making shebang compatible with all python versions installed, see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=568781 Modified Paths: -------------- pytrainer/trunk/bin/pytrainer pytrainer/trunk/extensions/dotclear/main.py pytrainer/trunk/plugins/garmin-hr/garminhr.py pytrainer/trunk/plugins/garmin-hr-file/garminhrfile.py pytrainer/trunk/plugins/garmintools_full/garmintools_full.py pytrainer/trunk/plugins/googleearth/main.py pytrainer/trunk/pytrainer/lib/gtrnctr2gpx.py pytrainer/trunk/schemas/validate_gpsfile.py Modified: pytrainer/trunk/bin/pytrainer =================================================================== --- pytrainer/trunk/bin/pytrainer 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/bin/pytrainer 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) Fiz Vazquez vu...@si... Modified: pytrainer/trunk/extensions/dotclear/main.py =================================================================== --- pytrainer/trunk/extensions/dotclear/main.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/extensions/dotclear/main.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) DJ dj...@na... http://blog.dedj.be Modified: pytrainer/trunk/plugins/garmin-hr/garminhr.py =================================================================== --- pytrainer/trunk/plugins/garmin-hr/garminhr.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/plugins/garmin-hr/garminhr.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) Fiz Vazquez vu...@si... Modified: pytrainer/trunk/plugins/garmin-hr-file/garminhrfile.py =================================================================== --- pytrainer/trunk/plugins/garmin-hr-file/garminhrfile.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/plugins/garmin-hr-file/garminhrfile.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) Modified: pytrainer/trunk/plugins/garmintools_full/garmintools_full.py =================================================================== --- pytrainer/trunk/plugins/garmintools_full/garmintools_full.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/plugins/garmintools_full/garmintools_full.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) Fiz Vazquez vu...@si... Modified: pytrainer/trunk/plugins/googleearth/main.py =================================================================== --- pytrainer/trunk/plugins/googleearth/main.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/plugins/googleearth/main.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) Fiz Vazquez vu...@si... Modified: pytrainer/trunk/pytrainer/lib/gtrnctr2gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gtrnctr2gpx.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/pytrainer/lib/gtrnctr2gpx.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # -*- coding: iso-8859-1 -*- #Copyright (C) Fiz Vazquez vu...@si... Modified: pytrainer/trunk/schemas/validate_gpsfile.py =================================================================== --- pytrainer/trunk/schemas/validate_gpsfile.py 2010-03-04 09:07:17 UTC (rev 519) +++ pytrainer/trunk/schemas/validate_gpsfile.py 2010-03-04 17:58:49 UTC (rev 520) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python import os, sys from optparse import OptionParser This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-07 07:49:58
|
Revision: 521 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=521&view=rev Author: jblance Date: 2010-03-07 07:49:52 +0000 (Sun, 07 Mar 2010) Log Message: ----------- Unified import - file import allows editing of information before import Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/import/file_garmintcxv1.py pytrainer/trunk/import/file_garmintcxv2.py pytrainer/trunk/import/file_garmintools.py pytrainer/trunk/import/file_gpxplus.py pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/glade/importdata.glade 2010-03-07 07:49:52 UTC (rev 521) @@ -183,12 +183,19 @@ <property name="visible">True</property> <property name="orientation">vertical</property> <child> - <widget class="GtkTreeView" id="treeviewImportFiles"> + <widget class="GtkScrolledWindow" id="scrolledwindowImportFiles"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">never</property> + <child> + <widget class="GtkTreeView" id="treeviewImportFiles"> + <property name="visible">True</property> + <property name="can_focus">True</property> + </widget> + </child> </widget> <packing> - <property name="pack_type">end</property> <property name="position">1</property> </packing> </child> Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/glade/newrecord.glade 2010-03-07 07:49:52 UTC (rev 521) @@ -15,11 +15,12 @@ <widget class="GtkScrolledWindow" id="scrolledwindowEntries"> <property name="can_focus">True</property> <property name="hscrollbar_policy">automatic</property> - <property name="vscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">never</property> <child> <widget class="GtkTreeView" id="treeviewEntries"> <property name="visible">True</property> <property name="can_focus">True</property> + <signal name="button_press_event" handler="on_treeviewEntries_row_activated"/> </widget> </child> </widget> @@ -71,6 +72,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="invisible_char">●</property> + <signal name="changed" handler="on_rcd_title_changed"/> </widget> <packing> <property name="left_attach">1</property> @@ -160,6 +162,7 @@ <property name="width_request">134</property> <property name="visible">True</property> <property name="items" translatable="yes"></property> + <signal name="changed" handler="on_rcd_sport_changed"/> </widget> <packing> <property name="left_attach">1</property> @@ -448,7 +451,7 @@ </packing> </child> <child> - <widget class="GtkEntry" id="rcd_time"> + <widget class="GtkEntry" id="rcd_starttime"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="width_chars">10</property> Modified: pytrainer/trunk/import/file_garmintcxv1.py =================================================================== --- pytrainer/trunk/import/file_garmintcxv1.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/import/file_garmintcxv1.py 2010-03-07 07:49:52 UTC (rev 521) @@ -133,7 +133,7 @@ def getDateTime(self, time_): return Date().getDateTime(time_) - def getGPXFile(self, ID): + def getGPXFile(self, ID, file_id): """ Generate GPX file based on activity ID @@ -148,7 +148,7 @@ sport, activities = self.activities[sportID] activitiesCount = len(self.activities) if activitiesCount > 0 and activityID < activitiesCount: - gpxFile = "%s/garmin-tcxv1-%d.gpx" % (self.tmpdir, activityID) + gpxFile = "%s/garmin-tcxv1-%s-%d.gpx" % (self.tmpdir, file_id, activityID) activity = activities[activityID] self.createGPXfile(gpxFile, activity) return sport, gpxFile Modified: pytrainer/trunk/import/file_garmintcxv2.py =================================================================== --- pytrainer/trunk/import/file_garmintcxv2.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/import/file_garmintcxv2.py 2010-03-07 07:49:52 UTC (rev 521) @@ -138,7 +138,7 @@ def getDateTime(self, time_): return Date().getDateTime(time_) - def getGPXFile(self, ID): + def getGPXFile(self, ID, file_id): """ Generate GPX file based on activity ID @@ -149,7 +149,7 @@ activityID = int(ID) activitiesCount = len(self.activities) if activitiesCount > 0 and activityID < activitiesCount: - gpxFile = "%s/garmin-tcxv2-%d.gpx" % (self.tmpdir, activityID) + gpxFile = "%s/garmin-tcxv2-%s-%d.gpx" % (self.tmpdir, file_id, activityID) activity = self.activities[int(activityID)] sport = self.getSport(activity) self.createGPXfile(gpxFile, activity) Modified: pytrainer/trunk/import/file_garmintools.py =================================================================== --- pytrainer/trunk/import/file_garmintools.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/import/file_garmintools.py 2010-03-07 07:49:52 UTC (rev 521) @@ -135,7 +135,7 @@ return time return None - def getGPXFile(self, ID): + def getGPXFile(self, ID, file_id): """ Generate GPX file based on activity ID @@ -144,7 +144,7 @@ sport = None gpxFile = None if ID == "0": #Only one activity in file - gpxFile = "%s/garmintools-%s.gpx" % (self.tmpdir, ID) + gpxFile = "%s/garmintools-%s-%s.gpx" % (self.tmpdir, file_id, ID) sport = self.getSport(self.xmldoc) self.createGPXfile(gpxFile, self.xmldoc) return sport, gpxFile Modified: pytrainer/trunk/import/file_gpxplus.py =================================================================== --- pytrainer/trunk/import/file_gpxplus.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/import/file_gpxplus.py 2010-03-07 07:49:52 UTC (rev 521) @@ -111,7 +111,7 @@ return timeElement.text return None - def getGPXFile(self, ID): + def getGPXFile(self, ID, file_id): """ Generate GPX file based on activity ID @@ -120,7 +120,7 @@ sport = None gpxFile = None if ID == "0": #Only one activity in file - gpxFile = "%s/gpx-%s.gpx" % (self.tmpdir, ID) + gpxFile = "%s/gpx-%s-%s.gpx" % (self.tmpdir, file_id, ID) sport = self.getSport(self.xmldoc) self.createGPXfile(gpxFile, self.xmldoc) return sport, gpxFile Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-03-07 07:49:52 UTC (rev 521) @@ -418,7 +418,7 @@ distance = item[3] duration = item[4] sport = item[5] - gpx_file = self.processClasses[file_id].getGPXFile(activity_id)[1] + gpx_file = self.processClasses[file_id].getGPXFile(activity_id, file_id)[1] selectedActivities.append((activity_id, start_time, distance, duration, sport, gpx_file)) logging.debug( "Found %d selected activities to import" % len(selectedActivities) ) return selectedActivities @@ -584,10 +584,10 @@ self.importSelectedActivities(selectedActivities) self.updateStatusbar(self.statusbarImportFile, msgImported) #Display informational dialog box - md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, msgImported) - md.set_title(_("Import Success")) - md.run() - md.destroy() + #md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, msgImported) + #md.set_title(_("Import Success")) + #md.run() + #md.destroy() self.buttonFileImport.set_sensitive(0) #Disable import button def on_buttonSelectFiles_clicked(self, widget): Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-03-07 07:49:52 UTC (rev 521) @@ -926,6 +926,7 @@ def on_gpsplugins_activate(self,widget): self.parent.editGpsPlugins() #hasta aqui revisado + def on_allRecordTreeView_button_press(self, treeview, event): logging.debug(">>") #print "on_allRecordTreeView_" Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-07 07:49:52 UTC (rev 521) @@ -36,6 +36,7 @@ self.mode = "newrecord" self.id_record = "" self.store = None + self.active_row = None SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) self.conf_options = [ "rcd_date", @@ -81,8 +82,9 @@ self.rcd_calories.set_text(calories) def populateMultiWindow(self, activities): - + self.mode = "multiple_activities" #activities (activity_id, start_time, distance, duration, sport, gpx_file) + self.activity_data = [] #Make treeview self.store = self.build_tree_view() #Add data @@ -97,11 +99,44 @@ 4, activity[4], 5, activity[5] ) - #Make row clickable to show details - #Select first activity - + details = {} + details["complete"] = False + details["rcd_distance"] = activity[2] + duration = activity[3] + hours, mins, secs = duration.split(":") + #details["rcd_hour"] = float(hours) + #details["rcd_min"] = float(mins) + #details["rcd_second"] = float(secs) + #details["rcd_time"] = (((float(hours) * 60) + float(mins)) * 60) + float(secs) + details["rcd_time"] = (float(hours), float(mins), float(secs)) + details["rcd_sport"] = activity[4] + details["rcd_gpxfile"] = activity[5] + self.activity_data.append(details) self.scrolledwindowEntries.show_all() + #Hide some of the buttons + self.button25.hide() #GPX file "Open" button + self.button24.hide() #GPX file "Calculate Values" button + self.button10.hide() #Distance "Calculate" button + self.button11.hide() #Duration "Calculate" button + self.button12.hide() #Velocity "Calculate" button + self.button43.hide() #Pace "Calculate" button + #Make GPX file 'unsensitive' + self.rcd_gpxfile.set_sensitive(0) + #Make General settings unsensitive + self.frameGeneral.set_sensitive(0) #TODO fix update to allow edits here + #Make Velocity settings unsensitive + self.frameVelocity.set_sensitive(0) #TODO fix update to allow edits here + #Make advanced tab settings unsensitive + self.vbox26.set_sensitive(0) #TODO fix update to allow edits here + #Make comments unsensitive + self.frame23.set_sensitive(0) #TODO fix update to allow edits here + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + #Select first row and display details + self.treeviewEntries.set_cursor(0) + self.show_treeviewEntries_row(0) + def build_tree_view(self): store = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING, @@ -123,42 +158,58 @@ return store def on_accept_clicked(self,widget): - list_options = {} - trackSummary = {} - for i in self.conf_options: - var = getattr(self,i) - if i == "rcd_title": - list_options[i] = var.get_text().replace("\"","'") - elif i != "rcd_sport" and i != "rcd_comments": - list_options[i] = var.get_text() - elif i == "rcd_sport": - list_options[i] = var.get_active_text() - elif i == "rcd_comments": - buffer = var.get_buffer() - start,end = buffer.get_bounds() - list_options[i] = buffer.get_text(start,end, True) - list_options[i] = list_options[i].replace("\"","'") - list_options["rcd_time"] = [self.rcd_hour.get_value_as_int(),self.rcd_min.get_value_as_int(),self.rcd_second.get_value_as_int()] - 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') - trackSummary=(list_options["rcd_sport"],"","") - self.parent.insertNewRecord(list_options["rcd_gpxfile"], trackSummary) - else: - logging.info('Adding new activity based on provided data') - #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) + if self.mode == "multiple_activities": + print "Multi window true and accept clicked" + print "#TODO" + row = 0 + for activity in self.activity_data: + if activity["complete"] is False: + #Did not view or modify this record - need to get all the details + print "Activity incomplete.. " + activity["rcd_gpxfile"] + self.update_activity_data(row, activity["rcd_gpxfile"], activity["rcd_sport"]) + activity["rcd_title"] = activity["rcd_title"].replace("\"","'") + #Add activity to DB etc + laps = activity.pop("laps", ()) + self.parent.insertRecord(activity, laps) + row += 1 + + else: + list_options = {} + trackSummary = {} + for i in self.conf_options: + var = getattr(self,i) + if i == "rcd_title": + list_options[i] = var.get_text().replace("\"","'") + elif i != "rcd_sport" and i != "rcd_comments": + list_options[i] = var.get_text() + elif i == "rcd_sport": + list_options[i] = var.get_active_text() + elif i == "rcd_comments": + buffer = var.get_buffer() + start,end = buffer.get_bounds() + list_options[i] = buffer.get_text(start,end, True) + list_options[i] = list_options[i].replace("\"","'") + list_options["rcd_time"] = [self.rcd_hour.get_value_as_int(),self.rcd_min.get_value_as_int(),self.rcd_second.get_value_as_int()] + 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') + trackSummary=(list_options["rcd_sport"],"","") + self.parent.insertNewRecord(list_options["rcd_gpxfile"], trackSummary) + else: + logging.info('Adding new activity based on provided data') + #Manual entry, calculate time info + record_time = self.rcd_starttime.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) self.close_window() def on_cancel_clicked(self,widget): @@ -185,12 +236,13 @@ self.rcd_min.set_value(min) self.rcd_second.set_value(sec) - def setValue(self,var,value, format="%0.2f"): - var = getattr(self,var) + def setValue(self,var_name,value, format="%0.2f"): + var = getattr(self,var_name) try: - valueString = format %value + valueString = format % value var.set_text(valueString) - except: + except Exception as e: + print var_name, value, e pass def setValues(self,values): @@ -215,7 +267,7 @@ if local_time is not None: dateTime = dateutil.parser.parse(local_time) sTime = dateTime.strftime("%X") - self.rcd_time.set_text("%s" % sTime) + self.rcd_starttime.set_text("%s" % sTime) sportID = values[2] sportPosition = self.getSportPosition(sportID) self.rcd_sport.set_active(sportPosition) @@ -226,7 +278,7 @@ def getSportPosition(self, sportID): """ - Function to determin the position in the sport array for a given sport ID + Function to determine the position in the sport array for a given sport ID Needed as once sports are deleted there are gaps in the list... """ count = 0 @@ -235,7 +287,19 @@ return count count +=1 return 0 - + + def getSportPositionByName(self, sport): + """ + Function to determine the position in the sport array for a given sport + Needed as once sports are deleted there are gaps in the list... + """ + count = 0 + for key, value in self.listSport.iteritems(): + if value == sport: + return count + count +=1 + return None + def on_calctime_clicked(self,widget): try: distance = self.rcd_distance.get_text() @@ -245,6 +309,119 @@ except: pass + def update_activity_data(self, row, gpx_file, sport): + self.activity_data[row]["rcd_comments"] = "" + gpx_summary, laps = self.parent.summaryFromGPX(gpx_file, (sport,"")) + local_time = gpx_summary['date_time_local'] + start_date = local_time.strftime("%Y-%m-%d") + start_time = local_time.strftime("%H:%M:%S") + self.activity_data[row]["rcd_date"] = start_date + self.activity_data[row]["rcd_starttime"] = start_time + self.activity_data[row]["date_time_local"] = gpx_summary['date_time_local'] + self.activity_data[row]["date_time_utc"] = gpx_summary['date_time_utc'] + self.activity_data[row]["rcd_average"] = gpx_summary["rcd_average"] + self.activity_data[row]["rcd_calories"] = gpx_summary["rcd_calories"] + self.activity_data[row]["rcd_beats"] = gpx_summary["rcd_beats"] + self.activity_data[row]["rcd_upositive"] = gpx_summary["rcd_upositive"] + self.activity_data[row]["rcd_unegative"] = gpx_summary["rcd_unegative"] + self.activity_data[row]["rcd_maxvel"] = gpx_summary["rcd_maxvel"] + self.activity_data[row]["rcd_maxpace"] = gpx_summary["rcd_maxpace"] + self.activity_data[row]["rcd_pace"] = gpx_summary["rcd_pace"] + self.activity_data[row]["rcd_maxbeats"] = gpx_summary["rcd_maxbeats"] + self.activity_data[row]["rcd_title"] = "" + self.activity_data[row]["laps"] = laps + self.activity_data[row]["complete"] = True + + + def show_treeviewEntries_row(self, row): + ''' + Show details of treeview entry + TODO need to maintain any changes and display those.... + ''' + self.active_row = row + #Get details from stored data + #set sport + sport = self.activity_data[row]["rcd_sport"] + sportPosition = self.getSportPositionByName(sport) + if sportPosition is not None: + self.rcd_sport.set_active(sportPosition) + #Set gpx file name + gpx_file = self.activity_data[row]["rcd_gpxfile"] + self.setValue("rcd_gpxfile", gpx_file, "%s") + #set duration + time = Date().time2second(self.activity_data[row]["rcd_time"]) #TODO Fix to use timeinseconds!! + self.setTime(time) #TODO Fix to use timeinseconds!! + #self.rcd_hour.set_value(self.activity_data[row]["rcd_hour"]) + #self.rcd_min.set_value(self.activity_data[row]["rcd_min"]) + #self.rcd_second.set_value(self.activity_data[row]["rcd_second"]) + #Set distance + self.setValue("rcd_distance",self.activity_data[row]["rcd_distance"], "%s") + #set start date + #start_date = start + #self.setValue("rcd_date", start, "%s") + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + if self.activity_data[row]["complete"] is False: + #Haven't processed GPX file yet + #Blank values not yet known + self.setValue("rcd_date", "", "%s") + self.setValue("rcd_starttime", "", "%s") + self.setValue("rcd_average", "", "%s") + self.setValue("rcd_calories","", "%s") + self.setValue("rcd_beats", "", "%s") + self.setValue("rcd_upositive", "", "%s") + self.setValue("rcd_unegative", "", "%s") + self.setValue("rcd_maxvel", "", "%s") + self.rcd_maxpace.set_text("") + self.rcd_pace.set_text("") + self.setValue("rcd_maxbeats", "", "%s") + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + #Get some info from gpx file + self.update_activity_data(row, gpx_file, sport) + + self.setValue("rcd_date", self.activity_data[row]["rcd_date"], "%s") + self.setValue("rcd_starttime", self.activity_data[row]["rcd_starttime"], "%s") + self.setValue("rcd_average",self.activity_data[row]["rcd_average"]) + self.setValue("rcd_calories",self.activity_data[row]["rcd_calories"], "%0.0f") + self.setValue("rcd_beats",self.activity_data[row]["rcd_beats"], "%0.0f") + self.setValue("rcd_upositive",self.activity_data[row]["rcd_upositive"]) + self.setValue("rcd_unegative",self.activity_data[row]["rcd_unegative"]) + self.setValue("rcd_maxvel",self.activity_data[row]["rcd_maxvel"]) + self.rcd_maxpace.set_text(self.activity_data[row]["rcd_maxpace"]) + self.rcd_pace.set_text(self.activity_data[row]["rcd_pace"]) + self.setValue("rcd_maxbeats",self.activity_data[row]["rcd_maxbeats"], "%0.0f") + self.rcd_title.set_text(self.activity_data[row]["rcd_title"]) + + def on_rcd_title_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + self.activity_data[self.active_row]["rcd_title"] = self.rcd_title.get_text() + + def on_rcd_sport_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + sport = self.rcd_sport.get_active_text() + #Update sport in data store + self.activity_data[self.active_row]["rcd_sport"] = sport + #Update sport in treeview + self.store[self.active_row][4] = sport + + def on_treeviewEntries_row_activated(self, treeview, event): + ''' + Callback to display details of different activity + ''' + #Get row that was selected + x = int(event.x) + y = int(event.y) + time = event.time + pthinfo = treeview.get_path_at_pos(x, y) + if pthinfo is not None: + path, col, cellx, celly = pthinfo + treeview.grab_focus() + treeview.set_cursor(path, col, 0) + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + self.show_treeviewEntries_row(path[0]) + def on_calcaverage_clicked(self,widget): try: hour = self.rcd_hour.get_value_as_int() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/pytrainer/main.py 2010-03-07 07:49:52 UTC (rev 521) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#519" + self.version ="1.7.1_svn#521" self.DB_version = 3 #Setup usage and permitted options Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-03-04 17:58:49 UTC (rev 520) +++ pytrainer/trunk/pytrainer/record.py 2010-03-07 07:49:52 UTC (rev 521) @@ -56,7 +56,7 @@ def newMultiRecord(self, activities, list_sport): logging.debug('>>') #activities (activity_id, start_time, distance, duration, sport, gpx_file) - self.recordwindow = WindowRecord(self.data_path, list_sport, windowTitle="Modify details before importing") + self.recordwindow = WindowRecord(self.data_path, list_sport, parent=self, windowTitle="Modify details before importing") self.recordwindow.populateMultiWindow(activities) self.recordwindow.run() logging.debug('<<') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-08 08:58:48
|
Revision: 522 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=522&view=rev Author: jblance Date: 2010-03-08 08:58:42 +0000 (Mon, 08 Mar 2010) Log Message: ----------- Unified import - expand editable options before import Modified Paths: -------------- pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-03-07 07:49:52 UTC (rev 521) +++ pytrainer/trunk/glade/newrecord.glade 2010-03-08 08:58:42 UTC (rev 522) @@ -268,6 +268,7 @@ <property name="climb_rate">1</property> <property name="numeric">True</property> <property name="wrap">True</property> + <signal name="value_changed" handler="on_rcd_duration_value_changed"/> </widget> <packing> <property name="expand">False</property> @@ -290,10 +291,11 @@ <property name="width_request">47</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="adjustment">0 0 59 2 2 0</property> + <property name="adjustment">0 0 59 1 2 0</property> <property name="climb_rate">1</property> <property name="numeric">True</property> <property name="wrap">True</property> + <signal name="value_changed" handler="on_rcd_duration_value_changed"/> </widget> <packing> <property name="expand">False</property> @@ -319,6 +321,7 @@ <property name="adjustment">0 0 59 1 2 0</property> <property name="climb_rate">1</property> <property name="wrap">True</property> + <signal name="value_changed" handler="on_rcd_duration_value_changed"/> </widget> <packing> <property name="expand">False</property> @@ -340,6 +343,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <property name="width_chars">7</property> + <signal name="changed" handler="on_rcd_distance_changed"/> </widget> <packing> <property name="left_attach">1</property> @@ -389,6 +393,7 @@ <property name="can_focus">True</property> <property name="editable">False</property> <property name="width_chars">10</property> + <signal name="changed" handler="on_rcd_date_changed"/> </widget> <packing> <property name="expand">False</property> @@ -456,6 +461,7 @@ <property name="can_focus">True</property> <property name="width_chars">10</property> <property name="text" translatable="yes">12:00:00</property> + <signal name="changed" handler="on_rcd_starttime_changed"/> </widget> <packing> <property name="left_attach">3</property> Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-07 07:49:52 UTC (rev 521) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-08 08:58:42 UTC (rev 522) @@ -123,7 +123,7 @@ #Make GPX file 'unsensitive' self.rcd_gpxfile.set_sensitive(0) #Make General settings unsensitive - self.frameGeneral.set_sensitive(0) #TODO fix update to allow edits here + #self.frameGeneral.set_sensitive(0) #TODO fix update to allow edits here #Make Velocity settings unsensitive self.frameVelocity.set_sensitive(0) #TODO fix update to allow edits here #Make advanced tab settings unsensitive @@ -405,6 +405,35 @@ #Update sport in treeview self.store[self.active_row][4] = sport + def on_rcd_distance_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + distance = self.rcd_distance.get_text() + #Update distance in data store + self.activity_data[self.active_row]["rcd_distance"] = distance + #Update distance in treeview + self.store[self.active_row][2] = distance + + def on_rcd_duration_value_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + hour = self.rcd_hour.get_value() + min = self.rcd_min.get_value() + sec = self.rcd_second.get_value() + #print hour, min, sec + #Update duration in data store + self.activity_data[self.active_row]["rcd_time"] = (hour, min, sec) + #Update duration in treeview + self.store[self.active_row][3] = "%d:%d:%d" % (int(hour), int(min), int(sec)) + + def on_rcd_date_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + #Update date in data store + self.activity_data[self.active_row]["rcd_date"] = self.rcd_date.get_text() + + def on_rcd_starttime_changed(self, widget): + if self.mode == "multiple_activities" and self.active_row is not None: + #Update start time in data store + self.activity_data[self.active_row]["rcd_starttime"] = self.rcd_starttime.get_text() + def on_treeviewEntries_row_activated(self, treeview, event): ''' Callback to display details of different activity Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-07 07:49:52 UTC (rev 521) +++ pytrainer/trunk/pytrainer/main.py 2010-03-08 08:58:42 UTC (rev 522) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#521" + self.version ="1.7.1_svn#522" self.DB_version = 3 #Setup usage and permitted options This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-08 10:29:56
|
Revision: 523 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=523&view=rev Author: jblance Date: 2010-03-08 10:29:29 +0000 (Mon, 08 Mar 2010) Log Message: ----------- Unified import - Initial attempt at processing kml files, files accepted but not imported yet Modified Paths: -------------- pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/schemas/ogckml22.xsd Added Paths: ----------- pytrainer/trunk/import/file_kml20.py pytrainer/trunk/schemas/atom-author-link.xsd pytrainer/trunk/schemas/kml20-geodistance.xsd pytrainer/trunk/schemas/xAL.xsd Added: pytrainer/trunk/import/file_kml20.py =================================================================== --- pytrainer/trunk/import/file_kml20.py (rev 0) +++ pytrainer/trunk/import/file_kml20.py 2010-03-08 10:29:29 UTC (rev 523) @@ -0,0 +1,115 @@ +# -*- coding: iso-8859-1 -*- + +#Copyright (C) Fiz Vazquez vu...@si... +# Modified by dgranda + +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; either version 2 +#of the License, or (at your option) any later version. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. + +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import logging +import os +import datetime +from lxml import etree + +from pytrainer.lib.xmlUtils import XMLParser +from pytrainer.lib.system import checkConf +from pytrainer.lib.date import Date +#from pytrainer.gui.dialogs import fileChooserDialog, guiFlush + +class kml20(): + def __init__(self, parent = None, data_path = None): + self.parent = parent + self.conf = checkConf() + self.tmpdir = self.conf.getValue("tmpdir") + self.main_data_path = data_path + self.data_path = os.path.dirname(__file__) + self.xmldoc = None + self.activitiesSummary = [] + self.activities = [] + #self.sportsList = ("Running", "Biking", "Other", "MultiSport") + + def getXmldoc(self): + ''' Function to return parsed xmlfile ''' + return self.xmldoc + + def getFileType(self): + return _("Geodistance kml version 2.0 file") + + def getActivitiesSummary(self): + return self.activitiesSummary + + def testFile(self, filename): + logging.debug('>>') + logging.debug("Testing " + filename) + try: + #parse filename as xml + xmldoc = etree.parse(filename) + #Parse XML schema + xmlschema_doc = etree.parse(self.main_data_path+"schemas/kml20-geodistance.xsd") + xmlschema = etree.XMLSchema(xmlschema_doc) + if (xmlschema.validate(xmldoc)): + #Valid file + self.xmldoc = xmldoc + startTime = datetime.datetime.now() + inDatabase = False #cant really check, as dont have start time etc + duration = 0 # + distance = "" + index = "%d:%d" % (0,0) + sport = "Running" + self.activitiesSummary.append( (index, + inDatabase, + startTime.strftime("%Y-%m-%dT%H:%M:%S"), + distance, + str(duration), + sport, + ) ) + #print self.activitiesSummary + return True + except: + #Not valid file + return False + return False + + def getDateTime(self, time_): + return Date().getDateTime(time_) + + def getGPXFile(self, ID, file_id): + ''' + Generate GPX file based on activity ID + Returns (sport, GPX filename) + ''' + '''sport = None + gpxFile = None + #index = "%d:%d" % (self.activities.index((sport, activities)), activities.index(activity)) + sportID, activityID = ID.split(':') + sportID = int(sportID) + activityID = int(activityID) + sport, activities = self.activities[sportID] + activitiesCount = len(self.activities) + if activitiesCount > 0 and activityID < activitiesCount: + gpxFile = "%s/kml20-%s-%d.gpx" % (self.tmpdir, file_id, activityID) + activity = activities[activityID] + self.createGPXfile(gpxFile, activity) + return sport, gpxFile''' + + def createGPXfile(self, gpxfile, activity): + ''' Function to transform a Garmin Training Center v2 Track to a valid GPX+ file + ''' + '''xslt_doc = etree.parse(self.data_path+"/translate_garmintcxv1.xsl") + transform = etree.XSLT(xslt_doc) + #xml_doc = etree.parse(filename) + xml_doc = activity + result_tree = transform(xml_doc) + result_tree.write(gpxfile, xml_declaration=True)''' + Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-08 08:58:42 UTC (rev 522) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-08 10:29:29 UTC (rev 523) @@ -159,8 +159,6 @@ def on_accept_clicked(self,widget): if self.mode == "multiple_activities": - print "Multi window true and accept clicked" - print "#TODO" row = 0 for activity in self.activity_data: if activity["complete"] is False: Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-08 08:58:42 UTC (rev 522) +++ pytrainer/trunk/pytrainer/main.py 2010-03-08 10:29:29 UTC (rev 523) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#522" + self.version ="1.7.1_svn#523" self.DB_version = 3 #Setup usage and permitted options Added: pytrainer/trunk/schemas/atom-author-link.xsd =================================================================== --- pytrainer/trunk/schemas/atom-author-link.xsd (rev 0) +++ pytrainer/trunk/schemas/atom-author-link.xsd 2010-03-08 10:29:29 UTC (rev 523) @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" + elementFormDefault="qualified" + targetNamespace="http://www.w3.org/2005/Atom" + xmlns:atom="http://www.w3.org/2005/Atom" version="1.0.0"> + + <annotation> + <appinfo>atom-author-link.xsd 2008-01-23</appinfo> + <documentation>There is no official atom XSD. This XSD is created based on: + http://atompub.org/2005/08/17/atom.rnc. A subset of Atom as used in the + ogckml22.xsd is defined here. </documentation> + </annotation> + + <!-- Person Construct --> + <complexType name="atomPersonConstruct"> + <choice minOccurs="0" maxOccurs="unbounded"> + <element ref="atom:name"/> + <element ref="atom:uri"/> + <element ref="atom:email"/> + </choice> + </complexType> + + <element name="name" type="string"/> + <element name="uri" type="string"/> + <element name="email" type="atom:atomEmailAddress"/> + + <!-- atom:author --> + <element name="author" type="atom:atomPersonConstruct"/> + + <!-- atom:link --> + <element name="link"> + <complexType> + + <attribute name="href" use="required"/> + <attribute name="rel"/> + <attribute name="type" type="atom:atomMediaType"/> + <attribute name="hreflang" type="atom:atomLanguageTag"/> + <attribute name="title"/> + <attribute name="length"/> + + </complexType> + + </element> + + <!-- Whatever a media type is, it contains at least one slash --> + <simpleType name="atomMediaType"> + <restriction base="string"> + <pattern value=".+/.+"/> + </restriction> + </simpleType> + + <!-- As defined in RFC 3066 --> + <simpleType name="atomLanguageTag"> + <restriction base="string"> + <pattern value="[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*"/> + </restriction> + </simpleType> + + <!-- Whatever an email address is, it contains at least one @ --> + <simpleType name="atomEmailAddress"> + <restriction base="string"> + <pattern value=".+@.+"/> + </restriction> + </simpleType> + +</schema> Added: pytrainer/trunk/schemas/kml20-geodistance.xsd =================================================================== --- pytrainer/trunk/schemas/kml20-geodistance.xsd (rev 0) +++ pytrainer/trunk/schemas/kml20-geodistance.xsd 2010-03-08 10:29:29 UTC (rev 523) @@ -0,0 +1,773 @@ +<?xml version="1.0" encoding="utf-8"?> +<?xml-stylesheet type="text/xsl" href="xs3p.xsl"?> +<xsd:schema targetNamespace="http://earth.google.com/kml/2.0" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://earth.google.com/kml/2.0"> + <xsd:annotation> + <xsd:documentation>TimeStamp: 30-10-2005 + KML schema version 2.0 - + For more information on KML visit http://www.keyhole.com/kml/docs/webhelp/index.htm + The KML 2.0 vocabulary was not fixed at the end of October 2005. + This schema will be update weekly until fixation.</xsd:documentation> + </xsd:annotation> + <!-- ="/\w(\w|\d\_|)*/ --> + <xsd:attribute name="id" type="xsd:ID"/> + <xsd:element name="kml"> + <xsd:complexType> + <xsd:choice> + <xsd:element ref="Document"/> + <xsd:element ref="Folder"/> + <xsd:element ref="Placemark"/> + <xsd:element ref="LookAt"/> + <xsd:element ref="NetworkLink"/> + <xsd:element ref="NetworkLinkControl"/> + <xsd:element ref="GroundOverlay"/> + <xsd:element ref="ScreenOverlay"/> + </xsd:choice> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Document"> + <xsd:complexType> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element ref="Document" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Folder" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="GroundOverlay" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="LookAt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="NetworkLink" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Placemark" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Schema" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="ScreenOverlay" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Style" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="StyleMap" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="StyleBlinker" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="description" minOccurs="0"/> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="Snippet" minOccurs="0"/> + <xsd:element ref="visibility" minOccurs="0"/> + </xsd:choice> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Folder"> + <xsd:complexType> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element ref="Document" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Folder" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="GroundOverlay" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="LookAt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="NetworkLink" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Placemark" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="ScreenOverlay" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Style" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="description" minOccurs="0"/> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="Snippet" minOccurs="0"/> + <xsd:element ref="open" minOccurs="0"/> + <xsd:element ref="visibility" minOccurs="0"/> + </xsd:choice> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Placemark"> + <xsd:complexType> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element ref="description" minOccurs="0"/> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element name="open" type="xsd:boolean"/> + <xsd:element ref="Snippet" minOccurs="0"/> + <xsd:element ref="Style" minOccurs="0"/> + <xsd:element ref="LookAt" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiGeometry" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiLineString" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiPoint" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiPolygon" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Point" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Polygon" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="TimePeriod" minOccurs="0"/> + <xsd:element ref="LineString" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="address" minOccurs="0"/> + <xsd:element ref="styleUrl" minOccurs="0"/> + <xsd:element ref="visibility" minOccurs="0"/> + </xsd:choice> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="GroundOverlay"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="Icon"/> + <xsd:element ref="LatLonBox"/> + <xsd:element ref="drawOrder" minOccurs="0"/> + <xsd:element ref="description" minOccurs="0"/> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="LookAt" minOccurs="0"/> + <xsd:element ref="visibility" minOccurs="0"/> + <xsd:element ref="refreshInterval" minOccurs="0"/> + <xsd:element ref="color" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="LatLonBox"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="north"/> + <xsd:element ref="east"/> + <xsd:element ref="south"/> + <xsd:element ref="west"/> + <xsd:element ref="rotation" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="north" type="xsd:double"/> + <xsd:element name="east" type="xsd:double"/> + <xsd:element name="south" type="xsd:double"/> + <xsd:element name="west" type="xsd:double"/> + <xsd:element name="rotation" type="xsd:decimal"/> + <xsd:element name="ScreenOverlay"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="Icon"/> + <xsd:element ref="drawOrder" minOccurs="0"/> + <xsd:element ref="description" minOccurs="0"/> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="overlayXY" minOccurs="0"/> + <xsd:element ref="screenXY" minOccurs="0"/> + <xsd:element ref="size" minOccurs="0"/> + <xsd:element ref="visibility" minOccurs="0"/> + <xsd:element ref="rotation" minOccurs="0"/> + <xsd:element ref="refreshInterval" minOccurs="0"/> + <xsd:element ref="color" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="overlayXY"> + <xsd:complexType> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + <xsd:attribute name="x" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="y" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="xunits" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="fraction"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="yunits" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="fraction"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + <xsd:element name="screenXY"> + <xsd:complexType> + <xsd:attribute name="x" type="xsd:decimal" use="required"/> + <xsd:attribute name="y" type="xsd:decimal" use="required"/> + <xsd:attribute name="xunits" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="insetPixels"/> + <xsd:enumeration value="fraction"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="yunits" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="insetPixels"/> + <xsd:enumeration value="fraction"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + <xsd:element name="drawOrder"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + <xsd:maxInclusive value="99"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="Icon"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="href"/> + <xsd:element ref="h" minOccurs="0"/> + <xsd:element ref="w" minOccurs="0"/> + <xsd:element ref="x" minOccurs="0"/> + <xsd:element ref="y" minOccurs="0"/> + <xsd:element ref="refreshInterval" minOccurs="0"/> + <xsd:element ref="refreshMode" minOccurs="0"/> + <xsd:element ref="viewRefreshMode" minOccurs="0"/> + <xsd:element ref="viewRefreshTime" minOccurs="0"/> + <xsd:element ref="viewBoundScale" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="x"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="y"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="w"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="-1"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="h"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="-1"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="viewBoundScale" type="xsd:double"> + <xsd:annotation> + <xsd:documentation>Used for overlays in either network links or placemark overlays to indicate the percentage of screen space to fill with data. If you are creating a ground overlay to deliver dynamic data via a network link, you can set the view-bound scale to 1.0 so that the dynamic date entirely fills the screen. This would be a typical setting to use when the user will not need to adjust the size of the overlay. Values: View bound scale is set to 1.0 as default for network links and 0.75 for overlays if not specified. Otherwise, you can set the value to a fractional portion of the screen size, including values greater than 1.0. Keep in mind that when using this tag for ground overlays where the user might want to modify the position, you should keep the value to a smaller fraction of the screen size to provide for easier editing. Otherwise, set the bound to reflect the area of data relative to the viewing boundaries of the client screen that you want to display.</xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="LookAt"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="longitude"/> + <xsd:element ref="latitude"/> + <xsd:element ref="range"/> + <xsd:element ref="tilt"/> + <xsd:element ref="heading"/> + <xsd:element ref="timePosition" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="longitude" type="xsd:double"/> + <xsd:element name="latitude" type="xsd:double"/> + <xsd:element name="range" type="xsd:double"/> + <xsd:element name="tilt"> + <xsd:simpleType> + <xsd:restriction base="xsd:double"> + <xsd:minInclusive value="-90"/> + <xsd:maxInclusive value="90"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="heading"> + <xsd:simpleType> + <xsd:restriction base="xsd:double"> + <xsd:minInclusive value="-360"/> + <xsd:maxInclusive value="360"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="timePosition"> + <xsd:simpleType> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="(\d{4})*(\-\d{2})*(\-\d{2})*(T\d{2}:\d{2}:\d{2})*Z*"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="MultiGeometry"> + <xsd:complexType> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + <xsd:element ref="extrude" minOccurs="0"/> + <xsd:element ref="tessellate" minOccurs="0"/> + <xsd:element ref="altitudeMode" minOccurs="0"/> + <xsd:element ref="MultiGeometry" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiLineString" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiPoint" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="MultiPolygon" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="LineString" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Point" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Polygon" minOccurs="0" maxOccurs="unbounded"/> + <xsd:element ref="Placemark" minOccurs="0" maxOccurs="unbounded"/> + </xsd:choice> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="MultiLineString"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="LineString" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="LineString"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="extrude" minOccurs="0"/> + <xsd:element ref="tessellate" minOccurs="0"/> + <xsd:element ref="altitudeMode" minOccurs="0"/> + <xsd:element ref="coordinates"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="MultiPoint"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="Point" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Point"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="altitudeMode" minOccurs="0"/> + <xsd:element ref="extrude" minOccurs="0"/> + <xsd:element ref="coordinates"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="MultiPolygon"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="Polygon" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Polygon"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="extrude" minOccurs="0"/> + <xsd:element ref="tessellate" minOccurs="0"/> + <xsd:element ref="altitudeMode" minOccurs="0"/> + <xsd:element ref="innerBoundaryIs" minOccurs="0"/> + <xsd:element ref="outerBoundaryIs" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="innerBoundaryIs"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="LinearRing"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="outerBoundaryIs"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="LinearRing"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="LinearRing"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="coordinates"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="coordinates" type="xsd:string"/> + <xsd:element name="NetworkLinkControl"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="cookie" minOccurs="0"/> + <xsd:element ref="linkDescription" minOccurs="0"/> + <xsd:element ref="linkName" minOccurs="0"/> + <!--xsd:element ref="linkSnippet" minOccurs="0"/--> + <xsd:element ref="message" minOccurs="0"/> + <xsd:element ref="minRefreshPeriod" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="cookie" type="xsd:string"/> + <xsd:element name="linkDescription" type="xsd:string"/> + <xsd:element name="linkName" type="xsd:string"/> + <xsd:element name="message" type="xsd:string"/> + <xsd:element name="minRefreshPeriod" type="xsd:int"/> + <xsd:element name="NetworkLink"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="Url"/> + <xsd:element ref="flyToView" minOccurs="0"/> + <xsd:element ref="description" minOccurs="0"/> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="refreshVisibility" minOccurs="0"/> + <xsd:element ref="visibility" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Url"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="href"/> + <xsd:element ref="refreshMode" minOccurs="0"/> + <xsd:element ref="refreshInterval" minOccurs="0"/> + <xsd:element ref="viewRefreshMode" minOccurs="0"/> + <xsd:element ref="viewRefreshTime" minOccurs="0"/> + <xsd:element ref="viewFormat" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="flyToView" type="xsd:boolean"/> + <xsd:element name="Schema"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="ObjArrayField" minOccurs="0"/> + <xsd:element ref="ObjField" minOccurs="0"/> + <xsd:element ref="SimpleArrayField" minOccurs="0"/> + <xsd:element ref="SimpleField" minOccurs="0"/> + <xsd:element ref="parent" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="ObjArrayField"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="name"/> + <xsd:element ref="type"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="ObjField"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="name"/> + <xsd:element ref="type"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="SimpleArrayField"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="type" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="SimpleField"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="name" minOccurs="0"/> + <xsd:element ref="type" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="parent" type="xsd:string"/> + <xsd:element name="type" type="xsd:string"/> + <xsd:element name="Style"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="Icon" minOccurs="0"/> + <xsd:element ref="IconStyle" minOccurs="0"/> + <xsd:element ref="LineStyle" minOccurs="0"/> + <xsd:element ref="PolyStyle" minOccurs="0"/> + <xsd:element ref="LabelStyle" minOccurs="0"/> + <xsd:element ref="BalloonStyle" minOccurs="0"/> + <xsd:element ref="color" minOccurs="0"/> + <xsd:element ref="scale" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="BalloonStyle"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="color" minOccurs="0"/> + <xsd:element ref="text" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="text" type="xsd:string"> + <xsd:annotation> + <xsd:documentation>Child element of BalloonStyle, can contain HTML + Content should be wrapped by CDATA + name or description content is substituted by this text content + by using $[name] or $[description] one can use name/description content in the balloon</xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="IconStyle"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="color" minOccurs="0"/> + <xsd:element ref="colorMode" minOccurs="0"/> + <xsd:element ref="heading" minOccurs="0"/> + <xsd:element ref="Icon" minOccurs="0"/> + <xsd:element ref="scale" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="LabelStyle"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="color" minOccurs="0"/> + <xsd:element ref="colorMode" minOccurs="0"/> + <xsd:element ref="scale" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="LineStyle"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="color" minOccurs="0"/> + <xsd:element ref="colorMode" minOccurs="0"/> + <xsd:element ref="width" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="PolyStyle"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="color" minOccurs="0"/> + <xsd:element ref="colorMode" minOccurs="0"/> + <xsd:element ref="fill" minOccurs="0"/> + <xsd:element ref="outline" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="width"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="StyleBlinker"> + <xsd:complexType> + <xsd:sequence> + <xsd:element ref="numCycles"/> + <xsd:element ref="State" minOccurs="2" maxOccurs="2"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="State"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="duration"/> + <xsd:element ref="key"/> + <xsd:element ref="styleUrl"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="duration" type="xsd:int"/> + <xsd:element name="numCycles" type="xsd:int"/> + <xsd:element name="StyleMap"> + <xsd:complexType> + <xsd:choice> + <xsd:element ref="Pair" minOccurs="2" maxOccurs="2"/> + </xsd:choice> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="Pair"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="key"/> + <xsd:element ref="styleUrl"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="key"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="highlight"/> + <xsd:enumeration value="select"/> + <xsd:enumeration value="on"/> + <xsd:enumeration value="off"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="styleUrl" type="xsd:anyURI"/> + <xsd:element name="viewFormat" type="xsd:string"> + <xsd:annotation> + <xsd:documentation>A user defined variable. Available parameters are as follows: + BBOX= [bboxWest],[bboxSouth],[bboxEast],[bboxNorth],[lookatLon], + [lookatLat],[lookatRange],[lookatTilt],[lookatHeading] + To check if it can occur as a child of Icon aswell.</xsd:documentation> + </xsd:annotation> + </xsd:element> + <xsd:element name="altitudeMode"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="clampedToGround"/> + <xsd:enumeration value="relativeToGround"/> + <xsd:enumeration value="absolute"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="color"> + <xsd:simpleType> + <xsd:restriction base="xsd:hexBinary"/> + </xsd:simpleType> + </xsd:element> + <xsd:element name="colorMode"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="normal"/> + <xsd:enumeration value="random"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="scale" type="xsd:decimal"/> + <xsd:element name="TimePeriod"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="begin" minOccurs="0"/> + <xsd:element ref="end" minOccurs="0"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="begin"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="TimeInstant" minOccurs="0"/> + </xsd:all> + </xsd:complexType> + </xsd:element> + <xsd:element name="end"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="TimeInstant" minOccurs="0"/> + </xsd:all> + </xsd:complexType> + </xsd:element> + <xsd:element name="TimeInstant"> + <xsd:complexType> + <xsd:all> + <xsd:element ref="timePosition"/> + </xsd:all> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> + <xsd:element name="name" type="xsd:string"/> + <xsd:element name="description" type="xsd:string"/> + <xsd:element name="Snippet"> + <xsd:complexType> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="maxLines" type="xsd:unsignedByte" use="optional"/> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + </xsd:element> + <xsd:element name="open" type="xsd:boolean"/> + <xsd:element name="visibility" type="xsd:boolean"/> + <xsd:element name="extrude" type="xsd:boolean"/> + <xsd:element name="fill" type="xsd:boolean"/> + <xsd:element name="outline" type="xsd:boolean"/> + <xsd:element name="tessellate" type="xsd:boolean"/> + <xsd:element name="href" type="xsd:anyURI"/> + <xsd:element name="address" type="xsd:string"/> + <xsd:element name="refreshMode"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="onChange"/> + <xsd:enumeration value="onInterval"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="refreshInterval" type="xsd:int"/> + <xsd:element name="refreshVisibility" type="xsd:boolean"/> + <xsd:element name="viewRefreshMode"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="never"/> + <xsd:enumeration value="onRequest"/> + <xsd:enumeration value="onStop"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="viewRefreshTime"> + <xsd:simpleType> + <xsd:restriction base="xsd:int"> + <xsd:minInclusive value="0"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + <xsd:element name="size"> + <xsd:complexType> + <xsd:attribute name="x" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <xsd:minInclusive value="-1"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="y" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:decimal"> + <xsd:minInclusive value="-1"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="xunits" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="insetPixels"/> + <xsd:enumeration value="fraction"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="yunits" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="pixels"/> + <xsd:enumeration value="insetPixels"/> + <xsd:enumeration value="fraction"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="id" type="xsd:ID" use="optional"/> + </xsd:complexType> + </xsd:element> +</xsd:schema> Modified: pytrainer/trunk/schemas/ogckml22.xsd =================================================================== --- pytrainer/trunk/schemas/ogckml22.xsd 2010-03-08 08:58:42 UTC (rev 522) +++ pytrainer/trunk/schemas/ogckml22.xsd 2010-03-08 10:29:29 UTC (rev 523) @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" +<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" @@ -16,11 +17,11 @@ <!-- import atom:author and atom:link --> <xsd:import namespace="http://www.w3.org/2005/Atom" - schemaLocation="atom-author-link.xsd"/> + schemaLocation="atom-author-link.xsd"/> <!-- import xAL:Address --> <xsd:import namespace="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" - schemaLocation="http://docs.oasis-open.org/election/external/xAL.xsd"/> + schemaLocation="xAL.xsd"/> <!-- KML field types (simple content) --> Added: pytrainer/trunk/schemas/xAL.xsd =================================================================== --- pytrainer/trunk/schemas/xAL.xsd (rev 0) +++ pytrainer/trunk/schemas/xAL.xsd 2010-03-08 10:29:29 UTC (rev 523) @@ -0,0 +1,1680 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--Modified by Ram Kumar (MSI) on 24 July 2002--> +<xs:schema targetNamespace="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" elementFormDefault="qualified"> + <xs:annotation> + <xs:documentation>xAL: eXtensible Address Language +This is an XML document type definition (DTD) for +defining addresses. +Original Date of Creation: 1 March 2001 +Copyright(c) 2000, OASIS. All Rights Reserved [http://www.oasis-open.org] +Contact: Customer Information Quality Technical Committee, OASIS +http://www.oasis-open.org/committees/ciq +VERSION: 2.0 [MAJOR RELEASE] Date of Creation: 01 May 2002 +Last Update: 24 July 2002 +Previous Version: 1.3</xs:documentation> + </xs:annotation> + <xs:annotation> + <xs:documentation>Common Attributes:Type - If not documented then it means, possible values of Type not limited to: Official, Unique, Abbreviation, OldName, Synonym +Code:Address element codes are used by groups like postal groups like ECCMA, ADIS, UN/PROLIST for postal services</xs:documentation> + </xs:annotation> + <xs:attributeGroup name="grPostal"> + <xs:attribute name="Code"> + <xs:annotation> + <xs:documentation>Used by postal services to encode the name of the element.</xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:attributeGroup> + <xs:element name="xAL"> + <xs:annotation> + <xs:documentation>Root element for a list of addresses</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element ref="AddressDetails" maxOccurs="unbounded"/> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="Version"> + <xs:annotation> + <xs:documentation>Specific to DTD to specify the version number of DTD</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="AddressDetails" type="AddressDetails"> + <xs:annotation> + <xs:documentation>This container defines the details of the address. Can define multiple addresses including tracking address history</xs:documentation> + </xs:annotation> + </xs:element> + <xs:complexType name="AddressDetails"> + <xs:sequence> + <xs:element name="PostalServiceElements" minOccurs="0"> + <xs:annotation> + <xs:documentation>Postal authorities use specific postal service data to expedient delivery of mail</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element name="AddressIdentifier" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>A unique identifier of an address assigned by postal authorities. Example: DPID in Australia</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="IdentifierType"> + <xs:annotation> + <xs:documentation>Type of identifier. eg. DPID as in Australia</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="Type"/> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="EndorsementLineCode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Directly affects postal service distribution</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="KeyLineCode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Required for some postal services</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="Barcode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Required for some postal services</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="SortingCode" minOccurs="0"> + <xs:annotation> + <xs:documentation>Used for sorting addresses. Values may for example be CEDEX 16 (France)</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + </xs:complexType> + </xs:element> + <xs:element name="AddressLatitude" minOccurs="0"> + <xs:annotation> + <xs:documentation>Latitude of delivery address</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="AddressLatitudeDirection" minOccurs="0"> + <xs:annotation> + <xs:documentation>Latitude direction of delivery address;N = North and S = South</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + <xs:attribute name="Type"/> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="AddressLongitude" minOccurs="0"> + <xs:annotation> + <xs:documentation>Longtitude of delivery address</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="AddressLongitudeDirection" minOccurs="0"> + <xs:annotation> + <xs:documentation>Longtitude direction of delivery address;N=North and S=South</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="SupplementaryPostalServiceData" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>any postal service elements not covered by the container can be represented using this element</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Specific to postal service</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>USPS, ECMA, UN/PROLIST, etc</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:choice minOccurs="0"> + <xs:annotation> + <xs:documentation>Use the most suitable option. Country contains the most detailed information while Locality is missing Country and AdminArea</xs:documentation> + </xs:annotation> + <xs:element name="Address"> + <xs:annotation> + <xs:documentation>Address as one line of free text</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>Postal, residential, corporate, etc</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="AddressLines" type="AddressLinesType"> + <xs:annotation> + <xs:documentation>Container for Address lines</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Country"> + <xs:annotation> + <xs:documentation>Specification of a country</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element ref="AddressLine" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="CountryNameCode" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>A country code according to the specified scheme</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Scheme"> + <xs:annotation> + <xs:documentation>Country code scheme possible values, but not limited to: iso.3166-2, iso.3166-3 for two and three character country codes.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element ref="CountryName" minOccurs="0" maxOccurs="unbounded"/> + <xs:choice minOccurs="0"> + <xs:element ref="AdministrativeArea"/> + <xs:element ref="Locality"/> + <xs:element ref="Thoroughfare"/> + </xs:choice> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element ref="AdministrativeArea"/> + <xs:element ref="Locality"/> + <xs:element ref="Thoroughfare"/> + </xs:choice> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="AddressType"> + <xs:annotation> + <xs:documentation>Type of address. Example: Postal, residential,business, primary, secondary, etc</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="CurrentStatus"> + <xs:annotation> + <xs:documentation>Moved, Living, Investment, Deceased, etc..</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="ValidFromDate"> + <xs:annotation> + <xs:documentation>Start Date of the validity of address</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="ValidToDate"> + <xs:annotation> + <xs:documentation>End date of the validity of address</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="Usage"> + <xs:annotation> + <xs:documentation>Communication, Contact, etc.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:attribute name="AddressDetailsKey"> + <xs:annotation> + <xs:documentation>Key identifier for the element for not reinforced references from other elements. Not required to be unique for the document to be valid, but application may get confused if not unique. Extend this schema adding unique contraint if needed.</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="AddressLinesType"> + <xs:sequence> + <xs:element ref="AddressLine" maxOccurs="unbounded"/> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="BuildingNameType" mixed="true"> + <xs:attribute name="Type"/> + <xs:attribute name="TypeOccurrence"> + <xs:annotation> + <xs:documentation>Occurrence of the building name before/after the type. eg. EGIS BUILDING where name appears before type</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:NMTOKEN"> + <xs:enumeration value="Before"/> + <xs:enumeration value="After"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="DependentLocalityType"> + <xs:sequence> + <xs:element ref="AddressLine" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="DependentLocalityName" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Name of the dependent locality</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"/> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="DependentLocalityNumber" minOccurs="0"> + <xs:annotation> + <xs:documentation>Number of the dependent locality. Some areas are numbered. Eg. SECTOR 5 in a Suburb as in India or SOI SUKUMVIT 10 as in Thailand</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="NameNumberOccurrence"> + <xs:annotation> + <xs:documentation>Eg. SECTOR occurs before 5 in SECTOR 5</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:NMTOKEN"> + <xs:enumeration value="Before"/> + <xs:enumeration value="After"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:choice minOccurs="0"> + <xs:element ref="PostBox"/> + <xs:element name="LargeMailUser" type="LargeMailUserType"> + <xs:annotation> + <xs:documentation>Specification of a large mail user address. Examples of large mail users are postal companies, companies in France with a cedex number, hospitals and airports with their own post code. Large mail user addresses do not have a street name with premise name or premise number in countries like Netherlands. But they have a POBox and street also in countries like France</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element ref="PostOffice"/> + <xs:element name="PostalRoute" type="PostalRouteType"> + <xs:annotation> + <xs:documentation> A Postal van is specific for a route as in Is`rael, Rural route</xs:documentation> + </xs:annotation> + </xs:element> + </xs:choice> + <xs:element ref="Thoroughfare" minOccurs="0"/> + <xs:element ref="Premise" minOccurs="0"/> + <xs:element name="DependentLocality" type="DependentLocalityType" minOccurs="0"> + <xs:annotation> + <xs:documentation>Dependent localities are Districts within cities/towns, locality divisions, postal +divisions of cities, suburbs, etc. DependentLocality is a recursive element, but no nesting deeper than two exists (Locality-DependentLocality-DependentLocality).</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element ref="PostalCode" minOccurs="0"/> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="Type"> + <xs:annotation> + <xs:documentation>City or IndustrialEstate, etc</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="UsageType"> + <xs:annotation> + <xs:documentation>Postal or Political - Sometimes locations must be distinguished between postal system, and physical locations as defined by a political system</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="Connector"> + <xs:annotation> + <xs:documentation>"VIA" as in Hill Top VIA Parish where Parish is a locality and Hill Top is a dependent locality</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="Indicator"> + <xs:annotation> + <xs:documentation>Eg. Erode (Dist) where (Dist) is the Indicator</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="FirmType"> + <xs:sequence> + <xs:element ref="AddressLine" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="FirmName" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Name of the firm</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"/> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element ref="Department" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="MailStop" type="MailStopType" minOccurs="0"> + <xs:annotation> + <xs:documentation>A MailStop is where the the mail is delivered to within a premise/subpremise/firm or a facility.</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element ref="PostalCode" minOccurs="0"/> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="Type"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="LargeMailUserType"> + <xs:sequence> + <xs:element ref="AddressLine" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="LargeMailUserName" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Name of the large mail user. eg. Smith Ford International airport</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type" type="xs:string"> + <xs:annotation> + <xs:documentation>Airport, Hospital, etc</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="Code" type="xs:string"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="LargeMailUserIdentifier" minOccurs="0"> + <xs:annotation> + <xs:documentation>Specification of the identification number of a large mail user. An example are the Cedex codes in France.</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type" type="xs:string"> + <xs:annotation> + <xs:documentation>CEDEX Code</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="Indicator"> + <xs:annotation> + <xs:documentation>eg. Building 429 in which Building is the Indicator</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="BuildingName" type="BuildingNameType" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation>Name of the building</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element ref="Department" minOccurs="0"/> + <xs:element ref="PostBox" minOccurs="0"/> + <xs:element ref="Thoroughfare" minOccurs="0"/> + <xs:element ref="PostalCode" minOccurs="0"/> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="Type" type="xs:string"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="MailStopType"> + <xs:sequence> + <xs:element ref="AddressLine" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="MailStopName" minOccurs="0"> + <xs:annotation> + <xs:documentation>Name of the the Mail Stop. eg. MSP, MS, etc</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"/> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:element name="MailStopNumber" minOccurs="0"> + <xs:annotation> + <xs:documentation>Number of the Mail stop. eg. 123 in MS 123</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="NameNumberSeparator"> + <xs:annotation> + <xs:documentation>"-" in MS-123</xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + </xs:element> + <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="Type"/> + <xs:anyAttribute namespace="##other"/> + </xs:complexType> + <xs:complexType name="PostalRouteType"> + <xs:sequence> + <xs:element ref="AddressLine" minOccurs="0" maxOccurs="unbounded"/> + <xs:choice> + <xs:element name="PostalRouteName" maxOccurs="unbounded"> + <xs:annotation> + <xs:documentation> Name of the Postal Route</xs:documentation> + </xs:annotation> + <xs:complexType mixed="true"> + <xs:attribute name="Type"/> + <xs:attributeGroup ref="grPostal"/> + <xs:anyAttribute namespace="##other"/> + <... [truncated message content] |
From: <jb...@us...> - 2010-03-10 09:34:28
|
Revision: 525 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=525&view=rev Author: jblance Date: 2010-03-10 09:34:21 +0000 (Wed, 10 Mar 2010) Log Message: ----------- Unified import now supports kml files as exported by geodistance Modified Paths: -------------- pytrainer/trunk/glade/newrecord.glade pytrainer/trunk/import/file_kml20.py pytrainer/trunk/pytrainer/extensions/waypointeditor.py pytrainer/trunk/pytrainer/gui/windowrecord.py pytrainer/trunk/pytrainer/lib/gpx.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/pytrainer/record.py Modified: pytrainer/trunk/glade/newrecord.glade =================================================================== --- pytrainer/trunk/glade/newrecord.glade 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/glade/newrecord.glade 2010-03-10 09:34:21 UTC (rev 525) @@ -546,7 +546,7 @@ <widget class="GtkLabel" id="label133"> <property name="visible">True</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Velocity (km/h)</property> + <property name="label" translatable="yes">Average (km/h)</property> </widget> <packing> <property name="left_attach">2</property> @@ -592,7 +592,7 @@ <child> <widget class="GtkLabel" id="label162"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>Velocity</b></property> + <property name="label" translatable="yes"><b>Speed</b></property> <property name="use_markup">True</property> </widget> <packing> Modified: pytrainer/trunk/import/file_kml20.py =================================================================== --- pytrainer/trunk/import/file_kml20.py 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/import/file_kml20.py 2010-03-10 09:34:21 UTC (rev 525) @@ -19,7 +19,10 @@ import logging import os +import math import datetime +from dateutil.tz import * +from StringIO import StringIO from lxml import etree from pytrainer.lib.xmlUtils import XMLParser @@ -59,17 +62,18 @@ xmlschema_doc = etree.parse(self.main_data_path+"schemas/kml20-geodistance.xsd") xmlschema = etree.XMLSchema(xmlschema_doc) if (xmlschema.validate(xmldoc)): + self.activities.append(xmldoc) # Assuming one activity per file #Valid file self.xmldoc = xmldoc - startTime = datetime.datetime.now() + self.startTime = datetime.datetime.now(tzlocal()) inDatabase = False #cant really check, as dont have start time etc duration = 0 # - distance = "" + distance = self.getDistance(xmldoc) index = "%d:%d" % (0,0) sport = "Running" self.activitiesSummary.append( (index, inDatabase, - startTime.strftime("%Y-%m-%dT%H:%M:%S"), + self.startTime.strftime("%Y-%m-%dT%H:%M:%S%z"), distance, str(duration), sport, @@ -81,6 +85,35 @@ return False return False + def getDistance(self, xmldoc): + ''' function to calculate distance from gps coordinates - code from gpx.py and of uncertain origins.... + ''' + total_dist = 0 + last_lat = last_lon = None + coords = xmldoc.find(".//{http://earth.google.com/kml/2.0}coordinates") + if coords is None: + return total_dist + else: + logging.debug("Found %s coords" % len(coords)) + items = coords.text.strip().split() + lat = lon = None + for item in items: + lon, lat, other = item.split(',') + #Convert lat and lon from degrees to radians + tmp_lat = float(lat)*0.01745329252 #0.01745329252 = number of radians in a degree + tmp_lon = float(lon)*0.01745329252 #57.29577951 = 1/0.01745329252 or degrees per radian + if last_lat is not None: + try: + #dist=math.acos(tempnum)*111.302*57.29577951 + dist=math.acos((math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)))*111.302*57.29577951 + except Exception as e: + print e + dist=0 + total_dist += dist + last_lat = tmp_lat + last_lon = tmp_lon + return round(total_dist, 2) + def getDateTime(self, time_): return Date().getDateTime(time_) @@ -89,27 +122,55 @@ Generate GPX file based on activity ID Returns (sport, GPX filename) ''' - '''sport = None + sport = None gpxFile = None #index = "%d:%d" % (self.activities.index((sport, activities)), activities.index(activity)) sportID, activityID = ID.split(':') sportID = int(sportID) activityID = int(activityID) - sport, activities = self.activities[sportID] + #activities = self.activities[sportID] activitiesCount = len(self.activities) if activitiesCount > 0 and activityID < activitiesCount: gpxFile = "%s/kml20-%s-%d.gpx" % (self.tmpdir, file_id, activityID) - activity = activities[activityID] + activity = self.activities[activityID] self.createGPXfile(gpxFile, activity) - return sport, gpxFile''' + return sport, gpxFile def createGPXfile(self, gpxfile, activity): ''' Function to transform a Garmin Training Center v2 Track to a valid GPX+ file ''' - '''xslt_doc = etree.parse(self.data_path+"/translate_garmintcxv1.xsl") - transform = etree.XSLT(xslt_doc) - #xml_doc = etree.parse(filename) - xml_doc = activity - result_tree = transform(xml_doc) - result_tree.write(gpxfile, xml_declaration=True)''' + tree = etree.parse(StringIO('''<?xml version='1.0' encoding='ASCII'?> + <gpx creator="pytrainer http://sourceforge.net/projects/pytrainer" + version="1.1" + xmlns="http://www.topografix.com/GPX/1/1" + xmlns:gpxdata="http://www.cluetrust.com/XML/GPXDATA/1/0" > + </gpx>''')) + + root = tree.getroot() + + metadata = etree.SubElement(root, "metadata") + name = etree.SubElement(metadata, "name") + name.text = "NeedsaName" #TODO + link = etree.SubElement(metadata, "link", href="http://sourceforge.net/projects/pytrainer") + time = etree.SubElement(metadata, "time") + time.text = self.startTime.strftime("%Y-%m-%dT%H:%M:%S%z") + trk = etree.SubElement(root, "trk") + trkseg = etree.SubElement(trk, "trkseg") + #for trkpt in file + coords = activity.find(".//{http://earth.google.com/kml/2.0}coordinates") + if coords is None: + pass + else: + items = coords.text.strip().split() + lat = lon = None + for item in items: + lon, lat, other = item.split(',') + trkpt = etree.SubElement(trkseg, "trkpt", lat=lat, lon=lon) + ele = etree.SubElement(trkpt, "ele") + ele.text = "0" #TODO + #trkpt_time = etree.SubElement(trkpt, "time") + #trkpt_time.text = "2010-03-02T04:52:35Z" #TODO + + #print(etree.tostring(tree, pretty_print=True)) + tree.write(gpxfile, method="xml", pretty_print=True, xml_declaration=True) Modified: pytrainer/trunk/pytrainer/extensions/waypointeditor.py =================================================================== --- pytrainer/trunk/pytrainer/extensions/waypointeditor.py 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/pytrainer/extensions/waypointeditor.py 2010-03-10 09:34:21 UTC (rev 525) @@ -65,7 +65,6 @@ lon, lat, id_waypoint = float(lon), float(lat), int(id_waypoint) retorno = self.waypoint.getwaypointInfo(id_waypoint) if retorno: - print retorno name, comment, sym = retorno[0][5], retorno[0][3], retorno[0][6] self.waypoint.updateWaypoint(id_waypoint, lat, lon, name, comment, sym) else: Modified: pytrainer/trunk/pytrainer/gui/windowrecord.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/pytrainer/gui/windowrecord.py 2010-03-10 09:34:21 UTC (rev 525) @@ -103,7 +103,10 @@ details["complete"] = False details["rcd_distance"] = activity[2] duration = activity[3] - hours, mins, secs = duration.split(":") + if duration.count(":") == 2: + hours, mins, secs = duration.split(":") + else: + hours = mins = secs = 0 #details["rcd_hour"] = float(hours) #details["rcd_min"] = float(mins) #details["rcd_second"] = float(secs) @@ -118,14 +121,14 @@ self.button24.hide() #GPX file "Calculate Values" button self.button10.hide() #Distance "Calculate" button self.button11.hide() #Duration "Calculate" button - self.button12.hide() #Velocity "Calculate" button + #self.button12.hide() #Velocity "Calculate" button self.button43.hide() #Pace "Calculate" button #Make GPX file 'unsensitive' self.rcd_gpxfile.set_sensitive(0) #Make General settings unsensitive #self.frameGeneral.set_sensitive(0) #TODO fix update to allow edits here #Make Velocity settings unsensitive - self.frameVelocity.set_sensitive(0) #TODO fix update to allow edits here + #self.frameVelocity.set_sensitive(0) #TODO fix update to allow edits here #Make advanced tab settings unsensitive self.vbox26.set_sensitive(0) #TODO fix update to allow edits here #Make comments unsensitive @@ -420,7 +423,7 @@ #Update duration in data store self.activity_data[self.active_row]["rcd_time"] = (hour, min, sec) #Update duration in treeview - self.store[self.active_row][3] = "%d:%d:%d" % (int(hour), int(min), int(sec)) + self.store[self.active_row][3] = "%d:%.2d:%.2d" % (int(hour), int(min), int(sec)) def on_rcd_date_changed(self, widget): if self.mode == "multiple_activities" and self.active_row is not None: Modified: pytrainer/trunk/pytrainer/lib/gpx.py =================================================================== --- pytrainer/trunk/pytrainer/lib/gpx.py 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/pytrainer/lib/gpx.py 2010-03-10 09:34:21 UTC (rev 525) @@ -65,6 +65,7 @@ self.unegative = 0 self.maxvel = 0 self.maxhr = 0 + self.hr_average = 0 self.date = "" #self.Date = Date() self.calories= 0 @@ -199,6 +200,7 @@ if trkpoints is None or len(trkpoints) == 0: logging.debug( "No trkpoints found in file") return retorno + logging.debug("%d trkpoints in file" % len(trkpoints)) date_ = tree.find(timeTag).text #mk_time = self.getDateTime(date_)[0] #UTC Date @@ -210,6 +212,7 @@ lat = trkpoint.get("lat") lon = trkpoint.get("lon") if lat is None or lat == "" or lon is None or lon == "": + logging.debug("lat or lon is blank") continue #get the heart rate value from the gpx extended format file hrResult = trkpoint.find(hrTag) @@ -258,22 +261,23 @@ #Para las vueltas diferentes a la primera / For the returns different from first if last_lat != "False": time_ = tmp_time - last_time + #if time_>0: + #Caqlculate diference betwen last and new point + #tempnum=(math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)) + #try: + #Pasamos la distancia de radianes a metros.. creo / We convert the distance from radians to meters + #David no me mates que esto lo escribi hace anhos / Do not kill me this was written ages ago + #http://faculty.washington.edu/blewis/ocn499/EXER04.htm equation for the distance between 2 points on a spherical earth + try: + #dist=math.acos(tempnum)*111.302*57.29577951 + dist=math.acos((math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)))*111.302*57.29577951 + except: + dist=0 + total_dist += dist + total_hr += hr + if hr>self.maxhr: + self.maxhr = hr if time_>0: - #Caqlculate diference betwen last and new point - #tempnum=(math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)) - #try: - #Pasamos la distancia de radianes a metros.. creo / We convert the distance from radians to meters - #David no me mates que esto lo escribi hace anhos / Do not kill me this was written ages ago - #http://faculty.washington.edu/blewis/ocn499/EXER04.htm equation for the distance between 2 points on a spherical earth - try: - #dist=math.acos(tempnum)*111.302*57.29577951 - dist=math.acos((math.sin(last_lat)*math.sin(tmp_lat))+(math.cos(last_lat)*math.cos(tmp_lat)*math.cos(tmp_lon-last_lon)))*111.302*57.29577951 - except: - dist=0 - total_dist += dist - total_hr += hr - if hr>self.maxhr: - self.maxhr = hr #dividimos kilometros por hora (no por segundo) / Calculate kilometers per hour (not including seconds) tmp_vel = dist/((time_)/3600.0) vel,his_vel = self._calculate_velocity(tmp_vel,his_vel, 3) @@ -282,12 +286,14 @@ if vel>self.maxvel: self.maxvel=vel self.total_time += time_ - retorno.append((total_dist,tmp_alt, self.total_time,vel,lat,lon,hr,cadence)) - rel_alt = tmp_alt - last_alt #Could allow for some 'jitter' in height here - if rel_alt > 0: - self.upositive += rel_alt - elif rel_alt < 0: - self.unegative -= rel_alt + else: + vel = 0 + rel_alt = tmp_alt - last_alt #Could allow for some 'jitter' in height here + if rel_alt > 0: + self.upositive += rel_alt + elif rel_alt < 0: + self.unegative -= rel_alt + retorno.append((total_dist,tmp_alt, self.total_time,vel,lat,lon,hr,cadence)) last_lat = tmp_lat last_lon = tmp_lon Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/pytrainer/main.py 2010-03-10 09:34:21 UTC (rev 525) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#524" + self.version ="1.7.1_svn#525" self.DB_version = 3 #Setup usage and permitted options Modified: pytrainer/trunk/pytrainer/record.py =================================================================== --- pytrainer/trunk/pytrainer/record.py 2010-03-10 06:37:50 UTC (rev 524) +++ pytrainer/trunk/pytrainer/record.py 2010-03-10 09:34:21 UTC (rev 525) @@ -224,28 +224,31 @@ logging.debug('>>') gpx = Gpx(self.data_path,gpxOrig) distance, time, maxspeed, maxheartrate = gpx.getMaxValues() - if time == 0: #invalid record - print "Invalid record" - return (None, None) + #if time == 0: #invalid record + # print "Invalid record" + # return (None, None) upositive,unegative = gpx.getUnevenness() - speed = distance*3600/time - time_hhmmss = [time//3600,(time/60)%60,time%60] + if time > 0: + speed = distance*3600/time + time_hhmmss = [time//3600,(time/60)%60,time%60] + else: + speed = 0 + time_hhmmss = [0,0,0] summaryRecord = {} summaryRecord['rcd_gpxfile'] = gpxOrig summaryRecord['rcd_sport'] = entry[0] summaryRecord['rcd_date'] = gpx.getDate() summaryRecord['rcd_calories'] = gpx.getCalories() - logging.debug('rcd_calories: ' + str(summaryRecord['rcd_calories'])) summaryRecord['rcd_comments'] = '' summaryRecord['rcd_title'] = '' summaryRecord['rcd_time'] = time_hhmmss #ToDo: makes no sense to work with arrays summaryRecord['rcd_distance'] = "%0.2f" %distance if speed == 0: - summaryRecord['rcd_pace'] = 0 + summaryRecord['rcd_pace'] = "0" else: summaryRecord['rcd_pace'] = "%d.%02d" %((3600/speed)/60,(3600/speed)%60) if maxspeed == 0: - summaryRecord['rcd_maxpace'] = 0 + summaryRecord['rcd_maxpace'] = "0" else: summaryRecord['rcd_maxpace'] = "%d.%02d" %((3600/maxspeed)/60,(3600/maxspeed)%60) summaryRecord['rcd_average'] = speed This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-11 06:10:01
|
Revision: 526 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=526&view=rev Author: jblance Date: 2010-03-11 06:09:55 +0000 (Thu, 11 Mar 2010) Log Message: ----------- Unified import - improved logging and bug fix to translated versions Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-03-10 09:34:21 UTC (rev 525) +++ pytrainer/trunk/glade/importdata.glade 2010-03-11 06:09:55 UTC (rev 526) @@ -60,6 +60,17 @@ </packing> </child> <child> + <widget class="GtkLabel" id="labelTemp"> + <property name="visible">True</property> + <property name="label" translatable="yes">Import from GPS Device is not yet implemented</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">4</property> + </packing> + </child> + <child> <widget class="GtkFrame" id="frameImportFromDevice"> <property name="label_xalign">0</property> <child> Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-03-10 09:34:21 UTC (rev 525) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-03-11 06:09:55 UTC (rev 526) @@ -46,47 +46,60 @@ # SimpleGladeApp.__init__(self, self.glade_path, self.root, self.domain) def new(self): - self.defaulttab = self.configuration.getValue("pytraining","import_default_tab") - if self.defaulttab == "": - self.defaulttab = 0 - else: + logging.debug(">>") + try: + self.defaulttab = self.configuration.getValue("pytraining","import_default_tab") self.defaulttab = int(self.defaulttab) + except Exception as e: + logging.debug("Exception: %s", str(e)) + self.defaulttab = 0 self.auto_launch = self.configuration.getValue("pytraining","auto_launch_file_selection") if self.auto_launch == "True": self.auto_launch = True else: self.auto_launch = False + logging.debug("Default tab: %s, Auto launch: %s" % (str(self.defaulttab), str(self.auto_launch))) self.notebookMainTabs.set_current_page(self.defaulttab) self.init_tab(self.defaulttab, first=True) + logging.debug("<<") def init_tab(self, page, first=False): + ''' Initialise tab ''' + logging.debug(">>") + logging.debug("page: %d first: %s" % (page, first)) if page == 0: #'Import from GPS Device' tab self.init_gpsdevice_tab() elif page == 1: #'Import from File' tab self.init_file_tab(first) - elif page ==2: + elif page == 2: #'Plugins' tab self.init_plugins_tab() - elif page ==3: + elif page == 3: #'Options' tab self.init_options_tab() else: #unknown tab + logging.error("Unknown page %d passed to init_tab" % page) pass def updateStatusbar(self, statusbar, text, context_id = None): + ''' Help function to set the text of the statusbar ''' + logging.debug("Setting statusbar %s to %s" % (statusbar.get_name(), text) ) if context_id is None: context_id = statusbar.get_context_id(text) statusbar.push(context_id, text) return context_id def init_gpsdevice_tab(self): + logging.debug(">>") + logging.error("GPS Device import not yet implemented") + logging.debug("<<") return def init_file_tab(self, first=False): - #self.filechooserbuttonSelectFile.unselect_all() + logging.debug(">>") self.updateStatusbar(self.statusbarImportFile, _("No file selected") ) self.processClasses = [] if self.activities_store is None: @@ -102,16 +115,19 @@ if first and self.auto_launch: while gtk.events_pending(): # This allows the GUI to update gtk.main_iteration() # before completion of this entire action - print "autolaunch active" + logging.debug("autolaunch active") self.buttonSelectFiles.clicked() + logging.debug(">>") return def init_plugins_tab(self): + logging.debug(">>") #Remove components in vbox - in case of re-detection for child in self.vboxPlugins.get_children(): if isinstance(child, gtk.Table): self.vboxPlugins.remove(child) pluginList = self.plugins.getPluginsList() + logging.debug(pluginList) for plugin in pluginList: #Store plugin details pluginClass = plugin[0] @@ -151,9 +167,12 @@ #Add frame to tab self.vboxPlugins.pack_start(pluginTable, expand=False, fill=False, padding=5) self.win_importdata.show_all() + logging.debug("<<") return def init_options_tab(self): + logging.debug(">>") + logging.debug("Default tab %s" % str(self.defaulttab) ) #Set correct radiobutton based on saved preference if self.defaulttab == 1: self.radiobuttonFile.set_active(1) @@ -164,6 +183,7 @@ self.radiobuttonTabGPSDevice.set_active(1) if self.auto_launch: self.checkbuttonAutoLaunch.set_active(1) + logging.debug("<<") return def detect_tools(self): @@ -182,6 +202,7 @@ self.vboxImportTools.remove(child) #Get import tool_* files fileList = glob.glob(self.data_path+"import/tool_*.py") + logging.debug("Tools filelist: %s" % fileList) for toolFile in fileList: index = fileList.index(toolFile) directory, filename = os.path.split(toolFile) @@ -221,6 +242,7 @@ #toolFrame.set_sensitive(0) self.vboxImportTools.pack_start(toolFrame, expand=False, fill=False, padding=5) self.win_importdata.show_all() + logging.debug('<<') def validateFile(self, import_filename): ''' @@ -237,9 +259,11 @@ #Get import files_* files fileList = glob.glob(self.data_path+"import/file_*.py") fileList.sort() + logging.debug("File filelist: %s" % fileList) for processingFile in fileList: directory, filename = os.path.split(processingFile) filename = filename.rstrip('.py') + logging.debug("Trying: %s" % filename) classname = filename.lstrip('file_') #Import module sys.path.insert(0, self.data_path+"import") @@ -257,12 +281,14 @@ return processClass def build_files_tree_view(self): + ''' Build tree view to hold files from which the activities are read ''' + logging.debug('>>') store = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, ) - column_names=["id", _(""), _("File"), _("Type"), _("Activities")] + column_names=["id", "", _("File"), _("Type"), _("Activities")] for column_index, column_name in enumerate(column_names): if column_index == 1: #Add button column @@ -283,9 +309,12 @@ self.treeviewImportFiles.append_column(column) self.treeviewImportFiles.set_headers_clickable(True) self.treeviewImportFiles.set_model(store) + logging.debug('<<') return store def build_activities_tree_view(self): + ''' Build tree view to hold activities that can be selected for import ''' + logging.debug('>>') store = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, @@ -294,7 +323,7 @@ gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING ) - column_names=["id", _(""), _("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("Notes"), "file_id"] + column_names=["id", "", _("Start Time"), _("Distance"),_("Duration"),_("Sport"), _("Notes"), "file_id"] for column_index, column_name in enumerate(column_names): if column_index == 1: #Add checkbox column @@ -315,6 +344,7 @@ self.treeviewImportEvents.append_column(column) self.treeviewImportEvents.set_headers_clickable(True) self.treeviewImportEvents.set_model(store) + logging.debug('<<') return store def checkTreestoreForSelection(self, store): @@ -343,9 +373,9 @@ self.buttonFileImport.set_sensitive(self.checkTreestoreForSelection(store)) def treeviewImportEvents_setCheckboxes(self, state): - """ + ''' Sets or unsets all checkboxes - """ + ''' if self.activities_store is None or len(self.activities_store) == 0: return for item in self.activities_store: @@ -356,9 +386,9 @@ self.buttonFileImport.set_sensitive(0) def saveOptions(self): - """ + ''' Save options selected in options tab - """ + ''' self.autoLaunchFileSelection = "False" #Default tab option if self.radiobuttonTabGPSDevice.get_active(): @@ -369,6 +399,7 @@ self.autoLaunchFileSelection = "True" elif self.radiobuttonPlugins.get_active(): self.defaulttab = "2" + logging.debug("Saving default tab: %s, auto launch: %s" % (str(self.defaulttab), str(self.autoLaunchFileSelection))) self.configuration.setValue("pytraining","import_default_tab",self.defaulttab) self.configuration.setValue("pytraining","auto_launch_file_selection",self.autoLaunchFileSelection) #option @@ -394,9 +425,11 @@ activity_index += 1 file_iters.append( self.files_store.get_iter(file_index)) file_index += 1 + logging.debug("Removing %d activities from activity tree view" % len(activity_iters) ) for activity_iter in activity_iters: self.activities_store.remove(activity_iter) self.buttonFileImport.set_sensitive(self.checkTreestoreForSelection(self.activities_store)) #Set correct state for import button + logging.debug("Removing %d files from file tree view" % len(file_iters) ) for file_iter in file_iters: self.files_store.remove(file_iter) @@ -408,6 +441,7 @@ """ selectedActivities = [] if self.activities_store is None: + logging.debug("activities_store is empty") return None for item in self.activities_store: if item[1] is True: #Checkbox is True @@ -459,6 +493,7 @@ path +=1 def close_window(self): + logging.debug('--') self.win_importdata.hide() #self.win_importdata.destroy() self.quit() @@ -505,16 +540,22 @@ button = gtk.Button(_("Ok")) button.connect("clicked", self.on_pluginAcceptSettings_clicked, pluginClass) table.attach(button,0,2,i,i+1) - self.prefwindow.add(table) - self.prefwindow.show_all() + self.prefwindow.add(table) + self.prefwindow.show_all() def on_pluginsButton_Run_clicked(self, button, pluginClass): ''' Handler for plugin Buttons ''' + logging.debug('>>') self.pytrainer_main.runPlugin(button,pluginClass) + logging.debug('<<') def on_pluginAcceptSettings_clicked(self, widget, pluginClass): + ''' + Duplicate of plugin settings accept handler + ''' + logging.debug('>>') prefs = self.plugins.getPluginConfParams(pluginClass) savedOptions = [] i = 0 @@ -530,11 +571,13 @@ self.prefwindow = None self.plugins.setPluginConfParams(pluginClass,savedOptions) self.init_plugins_tab() + logging.debug('<<') def treeviewImportEvents_header_checkbox(self, column, store): ''' Handler for click on checkbox column ''' + logging.debug('--') if store is None: return for item in store: @@ -545,29 +588,38 @@ def on_win_importdata_delete_event(self, widget, window): ''' Window closed ''' + logging.debug('--') self.close_window() def on_notebookMainTabs_switch_page(self, notebook, page, new_page): + logging.debug('--') self.init_tab(new_page) def on_buttonOptionsSave_clicked(self, widget): + logging.debug('>>') self.updateStatusbar(self.statusbarOptions, _("Saving options")) self.saveOptions() self.updateStatusbar(self.statusbarOptions, _("Options saved")) + logging.debug('<<') def on_buttonOptionsReset_clicked(self, widget): + logging.debug('>>') #GPS Device is default self.defaulttab = 0 #Redisplay tab self.init_options_tab() self.updateStatusbar(self.statusbarOptions, "") + logging.debug('<<') def on_buttonRemoveSelectedFiles_clicked(self, widget): - #Remove selected files and associated activities from list + ''' Remove selected files and associated activities from list ''' + logging.debug('>>') self.removeSelectedFiles() + logging.debug('<<') def on_buttonFileImport_clicked(self, widget): - #Import selected activities + ''' Import selected activities ''' + logging.debug('>>') selectedActivities = self.getSelectedActivities() selectedCount = len(selectedActivities) if selectedCount > 0: @@ -578,33 +630,43 @@ msgImporting = _("Importing %d activities" % selectedCount) msgImported = _("Imported %d activities" % selectedCount) self.updateStatusbar(self.statusbarImportFile, msgImporting) + logging.debug(msgImporting) while gtk.events_pending(): # This allows the GUI to update gtk.main_iteration() # before completion of this entire action #for activity in selectedActivities: self.importSelectedActivities(selectedActivities) self.updateStatusbar(self.statusbarImportFile, msgImported) + logging.debug(msgImported) #Display informational dialog box #md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, msgImported) #md.set_title(_("Import Success")) #md.run() #md.destroy() self.buttonFileImport.set_sensitive(0) #Disable import button + logging.debug('<<') def on_buttonSelectFiles_clicked(self, widget): + logging.debug('>>') selectedFiles = fileChooserDialog(title=_("Choose a file (or files) to import activities from"), multiple=True).getFiles() while gtk.events_pending(): # This allows the GUI to update gtk.main_iteration() # before completion of this entire action if selectedFiles is None or len(selectedFiles) == 0: #Nothing selected + logging.debug("No files selected") + logging.debug('<<') return + logging.debug("%s files selected" % len(selectedFiles)) for filename in selectedFiles: #Multiple files class_index = len(self.processClasses) #Validate file self.processClasses.append(self.validateFile(filename)) if self.processClasses[class_index] is not None: - self.updateStatusbar(self.statusbarImportFile, _("Found file of type: %s") % self.processClasses[class_index].getFileType() ) + filetype = self.processClasses[class_index].getFileType() + self.updateStatusbar(self.statusbarImportFile, _("Found file of type: %s") % filetype ) + logging.debug(_("Found file of type: %s") % filetype) activitiesSummary = self.processClasses[class_index].getActivitiesSummary() activity_count = len(activitiesSummary) + logging.debug("%s activities in file: %s" % (str(activity_count), filename) ) #Add file to files treeview iter = self.files_store.append() self.files_store.set( @@ -638,26 +700,34 @@ ) else: #Selected file not understood by any of the process files #Display error + logging.debug(_("File %s is of unknown or unsupported file type" % filename)) msg = _("File %s is of unknown or unsupported file type" % filename) md = gtk.MessageDialog(self.win_importdata, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) md.set_title("Error") md.run() md.destroy() + logging.debug('<<') def on_buttonFileClose_clicked(self, widget): + logging.debug('--') self.close_window() def on_buttonDeviceClose_clicked(self, widget): + logging.debug('--') self.close_window() def on_buttonOptionsClose_clicked(self, widget): + logging.debug('--') self.close_window() def on_buttonPluginsClose_clicked(self, widget): + logging.debug('--') self.close_window() def on_buttonDeviceToolRescan_clicked(self, widget): + logging.debug('--') self.detect_tools() def on_comboboxDevice_changed(self, widget): + logging.debug('--') self.detect_tools() Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-10 09:34:21 UTC (rev 525) +++ pytrainer/trunk/pytrainer/main.py 2010-03-11 06:09:55 UTC (rev 526) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#525" + self.version ="1.7.1_svn#526" self.DB_version = 3 #Setup usage and permitted options This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-11 07:34:58
|
Revision: 527 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=527&view=rev Author: jblance Date: 2010-03-11 07:34:51 +0000 (Thu, 11 Mar 2010) Log Message: ----------- Refactored extensions to run as internal classes - removed use of webservice in extension and in main Modified Paths: -------------- pytrainer/trunk/extensions/wordpress/conf.xml pytrainer/trunk/pytrainer/extension.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/main.py Added Paths: ----------- pytrainer/trunk/extensions/wordpress/wordpress.py Removed Paths: ------------- pytrainer/trunk/extensions/wordpress/main.py Modified: pytrainer/trunk/extensions/wordpress/conf.xml =================================================================== --- pytrainer/trunk/extensions/wordpress/conf.xml 2010-03-11 06:09:55 UTC (rev 526) +++ pytrainer/trunk/extensions/wordpress/conf.xml 2010-03-11 07:34:51 UTC (rev 527) @@ -6,7 +6,7 @@ extensioncode="wordpress" type="record" helpfile="README.txt" - executable="main.py" + executable="wordpress" > <conf-values variable="googlekey" value=""/> <conf-values variable="wordpressuser" value=""/> Deleted: pytrainer/trunk/extensions/wordpress/main.py =================================================================== --- pytrainer/trunk/extensions/wordpress/main.py 2010-03-11 06:09:55 UTC (rev 526) +++ pytrainer/trunk/extensions/wordpress/main.py 2010-03-11 07:34:51 UTC (rev 527) @@ -1,188 +0,0 @@ -#!/usr/bin/env python -from optparse import OptionParser -import os -import sys -import SOAPpy - -import wordpresslib -import googlemaps -import pytrainer.lib.points as Points -from pytrainer.lib.date import Date - -class Main: - def __init__(self,options): - self.wordpressurl = options.wordpressurl - self.user = options.wordpressuser - self.password = options.wordpresspass - self.gpxfile = options.gpxfile - self.googlekey = options.googlekey - self.idrecord = options.idrecord - self.wordpresscategory = options.wordpresscategory - self.webserviceserver = SOAPpy.SOAPProxy("http://localhost:8081/") - try: - self.wp = wordpresslib.WordPressClient(self.wordpressurl, self.user, self.password) - self.error = False - except: - self.error = True - self.log = "Url, user or pass are incorrect. Please, check your configuration" - - def createRoute(self): - htmlpath = "/tmp/index.html" - kmlpath = "/tmp/gps.kml" - description_route = '' - if os.path.isfile(self.gpxfile): - #create the html file - googlemaps.drawMap(self.gpxfile,self.googlekey,htmlpath) - #create the kml file - os.system("gpsbabel -t -i gpx -f %s -o kml,points=0,line_color=ff0000ff -F %s" %(self.gpxfile,kmlpath)) - - gfile = self.wp.newMediaObject(self.gpxfile) - hfile = self.wp.newMediaObject(htmlpath) - kfile = self.wp.newMediaObject(kmlpath) - - description_route = '''<strong>Map: </strong> <br/> - <iframe width='480' height='480' src='%s'> Need frame support </iframe><br/> - <a href='%s'>Gpx-format</a> <a href='%s'>Kml-format (GoogleEarth)</a><br/><br/>''' %(hfile,gfile,kfile) - return description_route - - def loadRecordInfo(self): - date = Date() - record = self.webserviceserver.getRecordInfo(self.idrecord) - self.sport = record["sport"] - self.date = record["date"] - self.distance = record["distance"] - self.time = date.second2time(float(record["time"])) - self.beats = record["beats"] - self.comments = record["comments"] - self.average = record["average"] - self.calories = record["calories"] - self.title = record["title"] - self.upositive = record["upositive"] - self.unegative = record["unegative"] - self.unegative = record["unegative"] - self.maxspeed = record["maxspeed"] - self.maxpace = record["maxpace"] - self.pace = record["pace"] - self.maxbeats = record["maxbeats"] - - def createBody(self): - return '''<b> Description: </b><br/> -%s<br/>''' %self.comments - - def createTable(self): - description_table = ''' - <br/> - <table border=0> - <tr> - <td><strong>Activity:</strong></td> - <td>%s</td> - <td><strong>Date:</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Distance:</strong></td> - <td>%s</td> - <td><strong>Time (hh, mm, ss):</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Max speed:</strong></td> - <td>%s</td> - <td><strong>Avg speed (km/h):</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Max pace (min/km):</strong></td> - <td>%s</td> - <td><strong>Avg pace (min/km):</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Max pulse:</strong></td> - <td>%s</td> - <td><strong>Avg pulse:</strong></td> - <td>%s</td> - </tr> - <tr> - <td><strong>Acc elevation +:</strong></td> - <td>%s</td> - <td><strong>Acc elevation -:</strong></td> - <td>%s</td> - </tr> - </table> - ''' %(self.sport,self.date,self.distance,self.time,self.maxspeed,self.average,self.maxpace,self.pace,self.maxbeats,self.beats,self.upositive,self.unegative) - return description_table - - def createFigureHR(self): - hr_fig_path = "/tmp/hr.png" - blog_figures = '' - # If there are no graphs, return empty string. - if os.path.isfile(hr_fig_path): - #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) - hrfile = self.wp.newMediaObject(hr_fig_path) - blog_figures = '''<br/> <img src='%s' /> ''' %hrfile - return blog_figures - - def createFigureStage(self): - stage_fig_path = "/tmp/stage.png" - blog_figures = '' - # If there are no graphs, return empty string. - if os.path.isfile(stage_fig_path): - #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) - stagefile = self.wp.newMediaObject(stage_fig_path) - blog_figures = '''<br/> <img src='%s' /> ''' %stagefile - return blog_figures - - def createFoot(self): - return ''' <br/><center>Powered by <a href='http://sourceforge.net/projects/pytrainer/'>Pytrainer</a></center>''' - - def createTitle(self): - if self.title==None: - self.error = True - self.log = "A Title must be defined. Please, configure the record propierly" - return self.title - - def createCategory(self): - if self.wordpresscategory==None: - self.error = True - self.log = "A wordpress category must be defined. Please, configure the wordpress extension" - else: - return ([self.wordpresscategory]) - - def run(self): - self.loadRecordInfo() - blog_title = self.createTitle() - blog_category = self.createCategory() - - if self.error == False: - blog_route = self.createRoute() - blog_body = self.createBody() - blog_table = self.createTable() - blog_figureHR = self.createFigureHR() - blog_figureStage = self.createFigureStage() - blog_foot = self.createFoot() - self.wp.selectBlog(0) - - post = wordpresslib.WordPressPost() - post.title = blog_title - post.description = blog_body+blog_table+blog_route+blog_figureHR+blog_figureStage+blog_foot - post.categories = blog_category - idNewPost = self.wp.newPost(post, True) - return "The post has been submited" - - else: - return self.log - -parser = OptionParser() -parser.add_option("-d", "--device", dest="device") -parser.add_option("-k", "--googlekey", dest="googlekey") -parser.add_option("-u", "--wordpressuser", dest="wordpressuser") -parser.add_option("-p", "--wordpresspass", dest="wordpresspass") -parser.add_option("-l", "--wordpressurl", dest="wordpressurl") -parser.add_option("-c", "--wordpresscategory", dest="wordpresscategory") -parser.add_option("-g", "--gpxfile", dest="gpxfile") -parser.add_option("-i", "--idrecord", dest="idrecord") -(options,args) = parser.parse_args() - -main = Main(options) -print main.run() Added: pytrainer/trunk/extensions/wordpress/wordpress.py =================================================================== --- pytrainer/trunk/extensions/wordpress/wordpress.py (rev 0) +++ pytrainer/trunk/extensions/wordpress/wordpress.py 2010-03-11 07:34:51 UTC (rev 527) @@ -0,0 +1,178 @@ +#!/usr/bin/env python +from optparse import OptionParser +import os +import sys + +import wordpresslib +import googlemaps +import pytrainer.lib.points as Points +from pytrainer.lib.date import Date + +class wordpress: + def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): + self.parent = parent + self.pytrainer_main = pytrainer_main + self.options = options + self.conf_dir = conf_dir + + def run(self, id): + options = self.options + self.wordpressurl = options["wordpressurl"] + self.user = options["wordpressuser"] + self.password = options["wordpresspass"] + self.gpxfile = "%s/gpx/%s.gpx " %(self.conf_dir,id) + self.googlekey = options["googlekey"] + self.idrecord = id #options.idrecord + self.wordpresscategory = options["wordpresscategory"] + print self.wordpressurl, self.user, self.password, self.gpxfile, self.googlekey, self.googlekey, self.idrecord, self.wordpresscategory + + try: + self.wp = wordpresslib.WordPressClient(self.wordpressurl, self.user, self.password) + self.error = False + except: + self.error = True + self.log = "Url, user or pass are incorrect. Please, check your configuration" + self.loadRecordInfo() + blog_title = self.createTitle() + blog_category = self.createCategory() + + if self.error == False: + blog_route = self.createRoute() + blog_body = self.createBody() + blog_table = self.createTable() + blog_figureHR = self.createFigureHR() + blog_figureStage = self.createFigureStage() + blog_foot = self.createFoot() + self.wp.selectBlog(0) + + post = wordpresslib.WordPressPost() + post.title = blog_title + post.description = blog_body+blog_table+blog_route+blog_figureHR+blog_figureStage+blog_foot + post.categories = blog_category + idNewPost = self.wp.newPost(post, True) + print "The post has been submited" + + else: + print self.log + + def createRoute(self): + htmlpath = "/tmp/index.html" + kmlpath = "/tmp/gps.kml" + description_route = '' + if os.path.isfile(self.gpxfile): + #create the html file + googlemaps.drawMap(self.gpxfile,self.googlekey,htmlpath) + #create the kml file + os.system("gpsbabel -t -i gpx -f %s -o kml,points=0,line_color=ff0000ff -F %s" %(self.gpxfile,kmlpath)) + + gfile = self.wp.newMediaObject(self.gpxfile) + hfile = self.wp.newMediaObject(htmlpath) + kfile = self.wp.newMediaObject(kmlpath) + + description_route = '''<strong>Map: </strong> <br/> + <iframe width='480' height='480' src='%s'> Need frame support </iframe><br/> + <a href='%s'>Gpx-format</a> <a href='%s'>Kml-format (GoogleEarth)</a><br/><br/>''' %(hfile,gfile,kfile) + return description_route + + def loadRecordInfo(self): + date = Date() + record = self.pytrainer_main.record.getrecordInfo(self.idrecord)[0] + #"sports.name,date,distance,time,beats,comments,average,calories,id_record,title,upositive,unegative,maxspeed,maxpace,pace,maxbeats,date_time_utc,date_time_local", + self.sport = record[0] + self.date = record[1] + self.distance = record[2] + self.time = date.second2time(float(record[3])) + self.beats = record[4] + self.comments = record[5] + self.average = record[6] + self.calories = record[7] + self.title = record[9] + self.upositive = record[10] + self.unegative = record[11] + self.maxspeed = record[12] + self.maxpace = record[13] + self.pace = record[14] + self.maxbeats = record[15] + + def createBody(self): + return '''<b> Description: </b><br/>%s<br/>''' %self.comments + + def createTable(self): + description_table = ''' + <br/> + <table border=0> + <tr> + <td><strong>Activity:</strong></td> + <td>%s</td> + <td><strong>Date:</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Distance:</strong></td> + <td>%s</td> + <td><strong>Time (hh, mm, ss):</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Max speed:</strong></td> + <td>%s</td> + <td><strong>Avg speed (km/h):</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Max pace (min/km):</strong></td> + <td>%s</td> + <td><strong>Avg pace (min/km):</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Max pulse:</strong></td> + <td>%s</td> + <td><strong>Avg pulse:</strong></td> + <td>%s</td> + </tr> + <tr> + <td><strong>Acc elevation +:</strong></td> + <td>%s</td> + <td><strong>Acc elevation -:</strong></td> + <td>%s</td> + </tr> + </table> + ''' %(self.sport,self.date,self.distance,self.time,self.maxspeed,self.average,self.maxpace,self.pace,self.maxbeats,self.beats,self.upositive,self.unegative) + return description_table + + def createFigureHR(self): + hr_fig_path = "/tmp/hr.png" + blog_figures = '' + # If there are no graphs, return empty string. + if os.path.isfile(hr_fig_path): + #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) + hrfile = self.wp.newMediaObject(hr_fig_path) + blog_figures = '''<br/> <img src='%s' /> ''' %hrfile + return blog_figures + + def createFigureStage(self): + stage_fig_path = "/tmp/stage.png" + blog_figures = '' + # If there are no graphs, return empty string. + if os.path.isfile(stage_fig_path): + #the graph files are created because the graph tabs are automatically visited (which invokes graph generation) + stagefile = self.wp.newMediaObject(stage_fig_path) + blog_figures = '''<br/> <img src='%s' /> ''' %stagefile + return blog_figures + + def createFoot(self): + return ''' <br/><center>Powered by <a href='http://sourceforge.net/projects/pytrainer/'>Pytrainer</a></center>''' + + def createTitle(self): + if self.title==None: + self.error = True + self.log = "A Title must be defined. Please, configure the record propierly" + return self.title + + def createCategory(self): + if self.wordpresscategory==None: + self.error = True + self.log = "A wordpress category must be defined. Please, configure the wordpress extension" + else: + return ([self.wordpresscategory]) Property changes on: pytrainer/trunk/extensions/wordpress/wordpress.py ___________________________________________________________________ Added: svn:executable + * Modified: pytrainer/trunk/pytrainer/extension.py =================================================================== --- pytrainer/trunk/pytrainer/extension.py 2010-03-11 06:09:55 UTC (rev 526) +++ pytrainer/trunk/pytrainer/extension.py 2010-03-11 07:34:51 UTC (rev 527) @@ -16,7 +16,8 @@ #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 os, sys +import logging from lib.xmlUtils import XMLParser from lib.system import checkConf @@ -24,9 +25,10 @@ from gui.windowextensions import WindowExtensions class Extension: - def __init__(self, data_path = None): + def __init__(self, data_path = None, parent = None): self.data_path=data_path self.conf = checkConf() + self.parent = parent def getActiveExtensions(self): retorno = [] @@ -80,9 +82,10 @@ prefs = info.getAllValues("conf-values") prefs.append(("status","0")) info = XMLParser(extensiondir+"/"+code+"/conf.xml") - params = [] + params = {} for pref in prefs: - params.append((pref[0],info.getValue("pytrainer-extension",pref[0]))) + params[pref[0]] = info.getValue("pytrainer-extension",pref[0]) + #params.append((pref[0],info.getValue("pytrainer-extension",pref[0]))) return params def setExtensionConfParams(self,pathExtension,savedOptions): @@ -109,25 +112,44 @@ extensiondir = self.conf.getValue("extensiondir") info = XMLParser(extensiondir+"/"+code+"/conf.xml") return info.getValue("pytrainer-extension",value) + + def importClass(self, pathExtension): + logging.debug('>>') + info = XMLParser(pathExtension+"/conf.xml") + #import extension + extension_dir = os.path.realpath(pathExtension) + extension_filename = info.getValue("pytrainer-extension","executable") + extension_classname = info.getValue("pytrainer-extension","extensioncode") + extension_type = info.getValue("pytrainer-extension","type") + options = self.getExtensionConfParams(pathExtension) + logging.debug("Extension Filename: " + extension_filename ) + logging.debug("Extension Classname: " + extension_classname) + logging.debug("Extension Type: " + extension_type) + logging.debug("Extension options: " + str(options)) + sys.path.insert(0, extension_dir) + module = __import__(extension_filename) + extensionMain = getattr(module, extension_classname) + logging.debug('<<') + return extensionMain(parent=self, pytrainer_main=self.parent, conf_dir=self.conf.getValue("confdir"), options=options) - def runExtension(self,pathExtension,id): - info = XMLParser(pathExtension+"/conf.xml") - bin = info.getValue("pytrainer-extension","executable") - extensiontype = info.getValue("pytrainer-extension","type") - binnary = pathExtension+"/"+bin - params = "" - for opt in self.getExtensionConfParams(pathExtension): - if opt[0]!="status" and opt[1]!="": - params += "--%s %s " %(opt[0],opt[1]) - if extensiontype=="record": - params += "--gpxfile %s/gpx/%s.gpx " %(self.conf.getValue("confdir"),id) - params += "--idrecord %s " %id - bin = info.getValue("pytrainer-extension","executable") - print params - alert = os.popen("%s %s" %(binnary,params)).read() + #def runExtension(self,pathExtension,id): + #info = XMLParser(pathExtension+"/conf.xml") + #bin = info.getValue("pytrainer-extension","executable") + #extensiontype = info.getValue("pytrainer-extension","type") + #binnary = pathExtension+"/"+bin + #params = "" + #for opt in self.getExtensionConfParams(pathExtension): + # if opt[0]!="status" and opt[1]!="": + # params += "--%s %s " %(opt[0],opt[1]) + #if extensiontype=="record": + # params += "--gpxfile %s/gpx/%s.gpx " %(self.conf.getValue("confdir"),id) + # params += "--idrecord %s " %id + #bin = info.getValue("pytrainer-extension","executable") + #print params + #alert = os.popen("%s %s" %(binnary,params)).read() - from gui.warning import Warning - warning = Warning(self.data_path) - warning.set_text(alert) - warning.run() + #from gui.warning import Warning + #warning = Warning(self.data_path) + # warning.set_text(alert) + # warning.run() Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-03-11 06:09:55 UTC (rev 526) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-03-11 07:34:51 UTC (rev 527) @@ -116,6 +116,7 @@ def runExtension(self,widget,widget2,extension): txtbutton,extensioncode,extensiontype = extension + id = None if extensiontype=="record": selected,iter = self.recordTreeView.get_selection().get_selected() id = selected.get_value(iter,0) Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-11 06:09:55 UTC (rev 526) +++ pytrainer/trunk/pytrainer/main.py 2010-03-11 07:34:51 UTC (rev 527) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#526" + self.version ="1.7.1_svn#527" self.DB_version = 3 #Setup usage and permitted options @@ -145,12 +145,12 @@ #Preparamos el webservice #TODO check reason for webservice - remove / change to optional start if not needed - gtk.gdk.threads_init() - self.webservice = webService(data_path,self.refreshWaypointView,self.newRecord) - self.webservice.start() + #gtk.gdk.threads_init() + #self.webservice = webService(data_path,self.refreshWaypointView,self.newRecord) + #self.webservice.start() self.waypoint = Waypoint(data_path,self) - self.extension = Extension(data_path) + self.extension = Extension(data_path, self) self.plugins = Plugins(data_path, self) self.importdata = Importdata(data_path, self, self.configuration) self.loadPlugins() @@ -217,9 +217,12 @@ def runExtension(self,extension,id): logging.debug('>>') txtbutton,pathExtension,type = extension - if type == "record": - #Si es record le tenemos que crear el googlemaps, el gpx y darle el id de la bbdd - alert = self.extension.runExtension(pathExtension,id) + self.extensionClass = self.extension.importClass(pathExtension) + self.extensionClass.run(id) + #if type == "record": + # #Si es record le tenemos que crear el googlemaps, el gpx y darle el id de la bbdd + # alert = self.extension.runExtension(pathExtension,id) + logging.debug('<<') def refreshMainSportList(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-14 02:49:45
|
Revision: 532 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=532&view=rev Author: jblance Date: 2010-03-14 02:49:38 +0000 (Sun, 14 Mar 2010) Log Message: ----------- Changed startup script to work with different paths Modified Paths: -------------- pytrainer/trunk/bin/pytrainer pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/bin/pytrainer =================================================================== --- pytrainer/trunk/bin/pytrainer 2010-03-11 08:24:47 UTC (rev 531) +++ pytrainer/trunk/bin/pytrainer 2010-03-14 02:49:38 UTC (rev 532) @@ -27,9 +27,16 @@ import os import commands -data_path = "/usr/share/pytrainer/" -DIR = "/usr/share/locale" +bin_path = os.path.realpath(os.path.dirname(__file__)) # directory that the pytrainer script executes from e.g. /usr/bin or /usr/local/bin +base_path = os.path.dirname(bin_path) + +data_path = base_path + "/share/pytrainer/" +DIR = base_path + "/share/locale" + +print "data_path: " + data_path +print "DIR: " + DIR + gettext.bindtextdomain("pytrainer", DIR) gtk.glade.bindtextdomain("pytrainer", DIR) gtk.glade.textdomain("pytrainer") Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-11 08:24:47 UTC (rev 531) +++ pytrainer/trunk/pytrainer/main.py 2010-03-14 02:49:38 UTC (rev 532) @@ -54,7 +54,7 @@ from gui.warning import Warning from lib.date import Date from lib.gpx import Gpx -from lib.soapUtils import webService +#from lib.soapUtils import webService from lib.ddbb import DDBB from lib.xmlUtils import XMLParser from lib.system import checkConf @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#530" + self.version ="1.7.1_svn#532" self.DB_version = 3 #Setup usage and permitted options This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-15 09:18:54
|
Revision: 536 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=536&view=rev Author: jblance Date: 2010-03-15 09:18:47 +0000 (Mon, 15 Mar 2010) Log Message: ----------- Some minor fixes to extension code. Start of Openstreetmap extension - INCOMPLETE Modified Paths: -------------- pytrainer/trunk/glade/pytrainer.glade pytrainer/trunk/pytrainer/extension.py pytrainer/trunk/pytrainer/gui/windowextensions.py pytrainer/trunk/pytrainer/gui/windowmain.py pytrainer/trunk/pytrainer/main.py pytrainer/trunk/setup.py Added Paths: ----------- pytrainer/trunk/extensions/openstreetmap/ pytrainer/trunk/extensions/openstreetmap/README.txt pytrainer/trunk/extensions/openstreetmap/conf.xml pytrainer/trunk/extensions/openstreetmap/openstreetmap.py pytrainer/trunk/glade/extensions.glade Added: pytrainer/trunk/extensions/openstreetmap/README.txt =================================================================== --- pytrainer/trunk/extensions/openstreetmap/README.txt (rev 0) +++ pytrainer/trunk/extensions/openstreetmap/README.txt 2010-03-15 09:18:47 UTC (rev 536) @@ -0,0 +1,18 @@ + Openstreetmap pytrainer extension + =============================== + This extension allows you to post your sport record directly + into Openstreetmap. + + CONFIG OPTIONS + ============== + You MUST fill in all the fields + + username: A valid Openstreetmap username + + password: The password for the Openstreetmap username. + + + USAGE + ===== + Simply submit the openstreetmap extension preferences form and then go + to the record tab and press "Post to Openstreetmap". Added: pytrainer/trunk/extensions/openstreetmap/conf.xml =================================================================== --- pytrainer/trunk/extensions/openstreetmap/conf.xml (rev 0) +++ pytrainer/trunk/extensions/openstreetmap/conf.xml 2010-03-15 09:18:47 UTC (rev 536) @@ -0,0 +1,13 @@ +<?xml version="1.0" ?> +<pytrainer-extension + name="Openstreetmap Export" + description="Publish your record to Openstreetmap" + extensionbutton="Post to Openstreetmap" + extensioncode="openstreetmap" + type="record" + helpfile="README.txt" + executable="openstreetmap" +> +<conf-values variable="username" value=""/> +<conf-values variable="password" value=""/> +</pytrainer-extension> Added: pytrainer/trunk/extensions/openstreetmap/openstreetmap.py =================================================================== --- pytrainer/trunk/extensions/openstreetmap/openstreetmap.py (rev 0) +++ pytrainer/trunk/extensions/openstreetmap/openstreetmap.py 2010-03-15 09:18:47 UTC (rev 536) @@ -0,0 +1,18 @@ +#!/usr/bin/env python +from optparse import OptionParser +import os +import sys + +class openstreetmap: + def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): + #TODO could use some logging + self.parent = parent + self.pytrainer_main = pytrainer_main + self.options = options + self.conf_dir = conf_dir + + def run(self, id): + options = self.options + print options + print "Record id: %s" % str(id) + print "THIS DOESNT WORK YET!!!!" Added: pytrainer/trunk/glade/extensions.glade =================================================================== --- pytrainer/trunk/glade/extensions.glade (rev 0) +++ pytrainer/trunk/glade/extensions.glade 2010-03-15 09:18:47 UTC (rev 536) @@ -0,0 +1,227 @@ +<?xml version="1.0"?> +<glade-interface> + <!-- interface-requires gtk+ 2.16 --> + <!-- interface-naming-policy toplevel-contextual --> + <widget class="GtkWindow" id="extensions"> + <property name="width_request">606</property> + <property name="height_request">249</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Extensions</property> + <property name="icon">logo_mini.png</property> + <signal name="destroy" handler="gtk_main_quit"/> + <child> + <widget class="GtkHBox" id="hbox32"> + <property name="width_request">32</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="border_width">9</property> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow4"> + <property name="width_request">230</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">in</property> + <child> + <widget class="GtkTreeView" id="extensionsTree"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="rules_hint">True</property> + <signal name="button_release_event" handler="on_extensionsTree_clicked"/> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox20"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <widget class="GtkTable" id="table11"> + <property name="visible">True</property> + <property name="border_width">5</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <property name="column_spacing">5</property> + <property name="row_spacing">5</property> + <child> + <widget class="GtkLabel" id="label-2147483648"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Extension Details</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="nameEntry"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">name-entry</property> + </widget> + <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> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label166"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Name:</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label168"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Status:</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label167"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Description:</property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="statusEntry"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">status-entry</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="descriptionEntry"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">description-entry</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox33"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label11111"> + <property name="visible">True</property> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button30"> + <property name="label">gtk-help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_help_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button29"> + <property name="label">gtk-preferences</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_preferences_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="button28"> + <property name="label">gtk-ok</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_accept_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> Modified: pytrainer/trunk/glade/pytrainer.glade =================================================================== --- pytrainer/trunk/glade/pytrainer.glade 2010-03-15 08:06:45 UTC (rev 535) +++ pytrainer/trunk/glade/pytrainer.glade 2010-03-15 09:18:47 UTC (rev 536) @@ -8711,385 +8711,6 @@ </child> </widget> -<widget class="GtkWindow" id="extensions"> - <property name="width_request">606</property> - <property name="height_request">249</property> - <property name="visible">True</property> - <property name="title" translatable="yes">Extensions</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, 30 Oct 2006 13:17:50 GMT"/> - - <child> - <widget class="GtkHBox" id="hbox32"> - <property name="border_width">9</property> - <property name="width_request">32</property> - <property name="height_request">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow4"> - <property name="width_request">230</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="extensionsTree"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">True</property> - <property name="rules_hint">True</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - <property name="fixed_height_mode">False</property> - <property name="hover_selection">False</property> - <property name="hover_expand">False</property> - <signal name="button_release_event" handler="on_extensionsTree_clicked" last_modification_time="Tue, 31 Oct 2006 09:45:28 GMT"/> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox20"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkTable" id="table11"> - <property name="border_width">5</property> - <property name="visible">True</property> - <property name="n_rows">4</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">5</property> - <property name="column_spacing">5</property> - - <child> - <widget class="GtkLabel" id="label-2147483648"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Extension Details</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="nameEntry"> - <property name="visible">True</property> - <property name="label" translatable="yes">name-entry</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</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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label166"> - <property name="visible">True</property> - <property name="label" translatable="yes">Name:</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label168"> - <property name="visible">True</property> - <property name="label" translatable="yes">Status:</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label167"> - <property name="visible">True</property> - <property name="label" translatable="yes">Description:</property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="statusEntry"> - <property name="visible">True</property> - <property name="label" translatable="yes">status-entry</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</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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="descriptionEntry"> - <property name="visible">True</property> - <property name="label" translatable="yes">description-entry</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">True</property> - <property name="selectable">False</property> - <property name="xalign">0</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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox33"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="GtkLabel" id="label11111"> - <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="button30"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-help</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_help_clicked" last_modification_time="Fri, 10 Nov 2006 16:26:02 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button29"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-preferences</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_preferences_clicked" last_modification_time="Tue, 31 Oct 2006 10:35:46 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="button28"> - <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="Tue, 31 Oct 2006 11:54:10 GMT"/> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </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">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - <widget class="GtkWindow" id="selecttrackdialog"> <property name="width_request">350</property> <property name="height_request">235</property> Modified: pytrainer/trunk/pytrainer/extension.py =================================================================== --- pytrainer/trunk/pytrainer/extension.py 2010-03-15 08:06:45 UTC (rev 535) +++ pytrainer/trunk/pytrainer/extension.py 2010-03-15 09:18:47 UTC (rev 536) @@ -64,25 +64,29 @@ extensiondir = self.conf.getValue("extensiondir") helpfile = pathExtension+"/"+info.getValue("pytrainer-extension","helpfile") type = info.getValue("pytrainer-extension","type") + if not os.path.isfile(extensiondir+"/"+code+"/conf.xml"): status = 0 else: info = XMLParser(extensiondir+"/"+code+"/conf.xml") status = info.getValue("pytrainer-extension","status") + #print name,description,status,helpfile,type return name,description,status,helpfile,type def getExtensionConfParams(self,pathExtension): info = XMLParser(pathExtension+"/conf.xml") code = info.getValue("pytrainer-extension","extensioncode") extensiondir = self.conf.getValue("extensiondir") + params = {} if not os.path.isfile(extensiondir+"/"+code+"/conf.xml"): - params = info.getAllValues("conf-values") - params.append(("status","0")) + prefs = info.getAllValues("conf-values") + prefs.append(("status","0")) + for pref in prefs: + params[pref[0]] = info.getValue("pytrainer-extension",pref[0]) else: prefs = info.getAllValues("conf-values") prefs.append(("status","0")) info = XMLParser(extensiondir+"/"+code+"/conf.xml") - params = {} for pref in prefs: params[pref[0]] = info.getValue("pytrainer-extension",pref[0]) #params.append((pref[0],info.getValue("pytrainer-extension",pref[0]))) @@ -104,7 +108,7 @@ txtbutton = info.getValue("pytrainer-extension","extensionbutton") name = info.getValue("pytrainer-extension","name") type = info.getValue("pytrainer-extension","type") - print "Loading Extension %s" %name + #print "Loading Extension %s" %name return txtbutton,pathExtension,type Modified: pytrainer/trunk/pytrainer/gui/windowextensions.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowextensions.py 2010-03-15 08:06:45 UTC (rev 535) +++ pytrainer/trunk/pytrainer/gui/windowextensions.py 2010-03-15 09:18:47 UTC (rev 536) @@ -23,7 +23,7 @@ class WindowExtensions(SimpleGladeApp): def __init__(self, data_path = None, parent=None): - glade_path="glade/pytrainer.glade" + glade_path="glade/extensions.glade" root = "extensions" domain = None self.parent = parent @@ -66,10 +66,10 @@ name,description,status,helpfile,type = self.parent.getExtensionInfo(selected.get_value(iter,0)) self.nameEntry.set_text(name) self.descriptionEntry.set_text(description) - if int(status) > 0: + if status is None or int(status) == 0: + self.statusEntry.set_text(_("Disable")) + else: self.statusEntry.set_text(_("Enable")) - else: - self.statusEntry.set_text(_("Disable")) def on_preferences_clicked(self,widget): selected,iter = self.extensionsTree.get_selection().get_selected() @@ -83,19 +83,27 @@ table = gtk.Table(1,2) i=0 self.entryList = [] - for pref in prefs: - label = gtk.Label("<b>%s</b>"%pref[0]) + #print prefs + for key in prefs.keys(): + #print key, prefs[key] + label = gtk.Label("<b>%s</b>"%key) label.set_use_markup(True) - if pref[0] != "status": + if key != "status": entry = gtk.Entry() - entry.set_text(pref[1]) + if prefs[key] is None: + entry.set_text("") + else: + entry.set_text(prefs[key]) self.entryList.append(entry) table.attach(entry,1,2,i,i+1) else: combobox = gtk.combo_box_new_text() combobox.append_text("Disable") combobox.append_text("Enable") - combobox.set_active(int(pref[1])) + if prefs[key] is None: + combobox.set_active(0) + else: + combobox.set_active(int(prefs[key])) table.attach(combobox,1,2,i,i+1) self.entryList.append(combobox) table.attach(label,0,1,i,i+1) @@ -138,13 +146,13 @@ prefs = self.parent.getExtensionConfParams(selected.get_value(iter,0)) savedOptions = [] i = 0 - for pref in prefs: + for key in prefs.keys(): try: - savedOptions.append((pref[0],self.entryList[i].get_text())) + savedOptions.append((key,self.entryList[i].get_text())) except: combobox = self.entryList[i] index = combobox.get_active() - savedOptions.append((pref[0],"%s" %index)) + savedOptions.append((key,"%s" %index)) i+=1 self.prefwindow.hide() self.prefwindow = None Modified: pytrainer/trunk/pytrainer/gui/windowmain.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowmain.py 2010-03-15 08:06:45 UTC (rev 535) +++ pytrainer/trunk/pytrainer/gui/windowmain.py 2010-03-15 09:18:47 UTC (rev 536) @@ -99,6 +99,12 @@ for widget in self.menuitem1_menu: if widget.get_name() == plugin[1]: self.menuitem1_menu.remove(widget) + + def removeExtension(self, extension): + for widget in self.recordbuttons_hbox: + if widget.get_name() == extension[1]: + logging.debug("Removing extension: %s " % extension[0]) + self.recordbuttons_hbox.remove(widget) def addImportPlugin(self,plugin): button = gtk.MenuItem(plugin[0]) @@ -108,13 +114,15 @@ self.menuitem1_menu.show_all() def addExtension(self,extension): - txtbutton,extensioncode,extensiontype = extension - button = gtk.Button(txtbutton) + #txtbutton,extensioncode,extensiontype = extension + button = gtk.Button(extension[0]) + button.set_name(extension[1]) button.connect("button_press_event", self.runExtension, extension) self.recordbuttons_hbox.pack_start(button,False,False,0) self.recordbuttons_hbox.show_all() def runExtension(self,widget,widget2,extension): + print extension txtbutton,extensioncode,extensiontype = extension id = None if extensiontype=="record": Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-15 08:06:45 UTC (rev 535) +++ pytrainer/trunk/pytrainer/main.py 2010-03-15 09:18:47 UTC (rev 536) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#535" + self.version ="1.7.1_svn#536" self.DB_version = 3 #Setup usage and permitted options @@ -362,7 +362,10 @@ def editExtensions(self): logging.debug('>>') + before = self.extension.getActiveExtensions() self.extension.manageExtensions() + after = self.extension.getActiveExtensions() + self.setExtensions(before, after) logging.debug('<<') def importData(self): @@ -400,6 +403,24 @@ txtbutton = self.plugins.loadPlugin(plugin) self.windowmain.addImportPlugin(txtbutton) logging.debug('<<') + + def setExtensions(self, before, after): + logging.debug('>>') + #Need to check for extensions that have been disabled (were active and now are not) + for extension in before: + if extension not in after: + #disabled extension -> need to unload extension + print "Need to disable extension %s " % extension + txtbutton = self.extension.loadExtension(extension) + self.windowmain.removeExtension(txtbutton) + #Need to check for plugins that have been enabled (were not active and now are) + for extension in after: + if extension not in before: + #new active extension -> need to load extension + logging.debug("Enabling extension %s " % extension) + txtbutton = self.extension.loadExtension(extension) + self.windowmain.addExtension(txtbutton) + logging.debug('<<') def newRecord(self,title=None,distance=None,time=None,upositive=None,unegative=None,bpm=None,calories=None,date=None,comment=None): logging.debug('>>') Modified: pytrainer/trunk/setup.py =================================================================== --- pytrainer/trunk/setup.py 2010-03-15 08:06:45 UTC (rev 535) +++ pytrainer/trunk/setup.py 2010-03-15 09:18:47 UTC (rev 536) @@ -42,6 +42,7 @@ install_plugin("garmintools"), install_plugin("garmintools_full"), install_extension("wordpress"), + install_extension("openstreetmap"), (install_locale("ca")), (install_locale("cs")), (install_locale("da")), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2010-03-21 09:59:43
|
Revision: 540 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=540&view=rev Author: jblance Date: 2010-03-21 09:59:37 +0000 (Sun, 21 Mar 2010) Log Message: ----------- Openstreetmap upload extension code complete Modified Paths: -------------- pytrainer/trunk/extensions/openstreetmap/openstreetmap.py pytrainer/trunk/pytrainer/main.py Modified: pytrainer/trunk/extensions/openstreetmap/openstreetmap.py =================================================================== --- pytrainer/trunk/extensions/openstreetmap/openstreetmap.py 2010-03-20 16:36:53 UTC (rev 539) +++ pytrainer/trunk/extensions/openstreetmap/openstreetmap.py 2010-03-21 09:59:37 UTC (rev 540) @@ -1,18 +1,167 @@ #!/usr/bin/env python from optparse import OptionParser -import os +import os, stat import sys +import logging +import gtk +import httplib, httplib2 +import urllib2 +import mimetools, mimetypes + class openstreetmap: def __init__(self, parent = None, pytrainer_main = None, conf_dir = None, options = None): - #TODO could use some logging self.parent = parent self.pytrainer_main = pytrainer_main self.options = options self.conf_dir = conf_dir + self.description = " " + self.tags = "" + self.visibility = "private" def run(self, id): - options = self.options - print options - print "Record id: %s" % str(id) - print "THIS DOESNT WORK YET!!!!" + logging.debug(">>") + uri = "http://api.openstreetmap.org/api/0.6/gpx/create" #URI for uploading traces to OSM + if 'username' not in self.options or self.options['username'] == "" or 'password' not in self.options or self.options['password'] == "": + logging.error("Must have username and password configured") + msg = _("Must have username and password configured") + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) + md.set_title(_("Openstreetmap Extension Error")) + md.run() + md.destroy() + return + username = self.options['username'] + password = self.options['password'] + gpx_file = "%s/gpx/%s.gpx" % (self.conf_dir, id) + if os.path.isfile(gpx_file): + #GPX file is ok and found, so open it + logging.debug("GPX file: %s found, size: %d" % (gpx_file, os.path.getsize(gpx_file))) + f = open(gpx_file, 'r') + file_contents = f.read() + if file_contents.find("<?xml version='1.0' encoding='ASCII'?>") != -1: + logging.debug("GPX file: %s has ASCII encoding - updating to UTF-8 for OSM support" % gpx_file) + f.close() #Close readonly file + f = open(gpx_file, 'w') #and open file for writing + file_contents = file_contents.replace("<?xml version='1.0' encoding='ASCII'?>","<?xml version='1.0' encoding='UTF-8'?>", 1) + f.write(file_contents) #Write new content + f.close() #Close + f = open(gpx_file, 'r') #Reopen in readonly mode + #Get extra info from user + self.display_options_window() + fields = (("description",self.description), ("tags",self.tags), ("visibility",self.visibility)) + logging.debug("Added fields: %s" % str(fields)) + #Multipart encode the request + boundary, body = self.multipart_encode(fields=fields, files=(("file", f),)) + content_type = 'multipart/form-data; boundary=%s' % boundary + #Finished with the file so close it + f.close() + #Add the http headers to the request + h = httplib2.Http() + headers = { + 'Content-Type': content_type + } + #Add basic authentication credentials to the request + h.add_credentials(username, password) + #Show user something is happening + msg = _("Posting GPX trace to Openstreetmap\n\nPlease wait this could take several minutes") + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, msg) + md.set_title(_("Openstreetmap Extension Processing")) + md.set_modal(True) + md.show() + while gtk.events_pending(): # This allows the GUI to update + gtk.main_iteration() # before completion of this entire action + logging.debug("before request posting") + #POST request to OSM + res, content = h.request(uri, 'POST', body=body, headers=headers) + logging.debug("after request posting") + logging.debug("Got response status: %s, reason: %s, content: %s" % (res.status, res.reason, content)) + if res.reason == 'OK': + res_msg = "Successfully posted to OSM.\nYou should get an email with the outcome of the upload soon\n\nTrace id is %s" % content + else: + res_msg = "Some error occured\nGot a status %s, reason %s\nContent was: %s" % (res.status, res.reason, content) + #Close 'Please wait' dialog + md.destroy() + #Show the user the result + md = gtk.MessageDialog(self.pytrainer_main.windowmain.window1, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, res_msg) + md.set_title(_("Openstreetmap Extension Upload Complete")) + md.set_modal(False) + md.run() + md.destroy() + + else: + logging.error("GPX file: %s NOT found!!!" % (gpx_file)) + logging.debug("<<") + + def display_options_window(self): + self.prefwindow = gtk.Dialog(title=_("Please add any additional information for this upload"), parent=None, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) + self.prefwindow.set_modal(False) + table = gtk.Table(1,2) + self.entryList = [] + #Add description + label = gtk.Label("<b>Description</b>") + label.set_use_markup(True) + entry = gtk.Entry() + self.entryList.append(entry) + table.attach(label,0,1,0,1) + table.attach(entry,1,2,0,1) + #Add tags + label = gtk.Label("<b>Tags</b>") + label.set_use_markup(True) + entry = gtk.Entry() + self.entryList.append(entry) + table.attach(label,0,1,1,2) + table.attach(entry,1,2,1,2) + #Add visibility + label = gtk.Label("<b>Visibility</b>") + label.set_use_markup(True) + combobox = gtk.combo_box_new_text() + combobox.append_text("private") + combobox.append_text("public") + combobox.append_text("trackable") + combobox.append_text("identifiable") + combobox.set_active(0) + table.attach(combobox,1,2,2,3) + self.entryList.append(combobox) + table.attach(label,0,1,2,3) + #Buld dialog and show + self.prefwindow.vbox.pack_start(table) + self.prefwindow.show_all() + self.prefwindow.connect("response", self.on_options_ok_clicked) + self.prefwindow.run() + + def on_options_ok_clicked(self, widget, response_id): + widget.destroy() + self.description = self.entryList[0].get_text() + if self.description == "": + logging.debug("A description is required - setting to default") + self.description = "Uploaded from pytrainer" + self.tags = self.entryList[1].get_text() + self.visibility = self.entryList[2].get_active_text() + logging.debug("Description: %s, tags: %s, visibility: %s" % ( self.description, self.tags, self.visibility) ) + + def multipart_encode(self, fields, files, boundary = None, buffer = None): + ''' + Multipart encode data for posting + from examples at from http://odin.himinbi.org/MultipartPostHandler.py & http://bitworking.org/projects/httplib2/doc/html/libhttplib2.html + ''' + if boundary is None: + boundary = mimetools.choose_boundary() + if buffer is None: + buffer = '' + for (key, value) in fields: + buffer += '--%s\r\n' % boundary + buffer += 'Content-Disposition: form-data; name="%s"' % key + buffer += '\r\n\r\n' + value + '\r\n' + print files + for (key, fd) in files: + file_size = os.fstat(fd.fileno())[stat.ST_SIZE] + filename = os.path.basename(fd.name) + contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + buffer += '--%s\r\n' % boundary + buffer += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename) + buffer += 'Content-Type: %s\r\n' % contenttype + # buffer += 'Content-Length: %s\r\n' % file_size + fd.seek(0) + buffer += '\r\n' + fd.read() + '\r\n' + buffer += '--%s--\r\n\r\n' % boundary + return boundary, buffer Modified: pytrainer/trunk/pytrainer/main.py =================================================================== --- pytrainer/trunk/pytrainer/main.py 2010-03-20 16:36:53 UTC (rev 539) +++ pytrainer/trunk/pytrainer/main.py 2010-03-21 09:59:37 UTC (rev 540) @@ -63,7 +63,7 @@ class pyTrainer: def __init__(self,filename = None, data_path = None): #Version constants - self.version ="1.7.1_svn#538" + self.version ="1.7.1_svn#540" self.DB_version = 3 #Setup usage and permitted options This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |