From: <jb...@us...> - 2010-01-06 09:53:21
|
Revision: 470 http://pytrainer.svn.sourceforge.net/pytrainer/?rev=470&view=rev Author: jblance Date: 2010-01-06 09:53:15 +0000 (Wed, 06 Jan 2010) Log Message: ----------- Unified import - start of device import functionality Modified Paths: -------------- pytrainer/trunk/glade/importdata.glade pytrainer/trunk/pytrainer/gui/windowimportdata.py Added Paths: ----------- pytrainer/trunk/import/tool_gant.py pytrainer/trunk/import/tool_garmintools.py pytrainer/trunk/import/tool_gpsbabel.py Modified: pytrainer/trunk/glade/importdata.glade =================================================================== --- pytrainer/trunk/glade/importdata.glade 2010-01-05 22:36:39 UTC (rev 469) +++ pytrainer/trunk/glade/importdata.glade 2010-01-06 09:53:15 UTC (rev 470) @@ -30,15 +30,22 @@ <property name="visible">True</property> <property name="left_padding">12</property> <child> - <placeholder/> + <widget class="GtkVBox" id="vboxImportTools"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + </widget> </child> </widget> </child> <child> - <widget class="GtkLabel" id="label1"> + <widget class="GtkLabel" id="labelImportDeviceTools"> <property name="visible">True</property> - <property name="label" translatable="yes"><b>frame1</b></property> + <property name="label" translatable="yes"><b>Tools</b></property> <property name="use_markup">True</property> + <property name="single_line_mode">True</property> </widget> <packing> <property name="type">label_item</property> @@ -53,16 +60,30 @@ <widget class="GtkHBox" id="hboxDeviceButtons"> <property name="visible">True</property> <child> - <placeholder/> + <widget class="GtkButton" id="buttonDeviceToolRescan"> + <property name="label" translatable="yes">Rescan</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip" translatable="yes">Rescan system for available tools</property> + <signal name="clicked" handler="on_buttonDeviceToolRescan_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">10</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> </child> <child> - <widget class="GtkButton" id="buttonDeviceCancel"> - <property name="label">gtk-cancel</property> + <widget class="GtkButton" id="buttonDeviceClose"> + <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_buttonDeviceCancel_clicked"/> + <signal name="clicked" handler="on_buttonDeviceClose_clicked"/> </widget> <packing> <property name="expand">False</property> @@ -226,18 +247,19 @@ <packing> <property name="expand">False</property> <property name="fill">False</property> + <property name="padding">10</property> <property name="pack_type">end</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkButton" id="buttonFileCancel"> + <widget class="GtkButton" id="buttonFileClose"> <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_buttonFileCancel_clicked"/> + <signal name="clicked" handler="on_buttonFileClose_clicked"/> </widget> <packing> <property name="expand">False</property> @@ -372,7 +394,7 @@ <property name="expand">False</property> <property name="fill">False</property> <property name="pack_type">end</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> <child> @@ -388,6 +410,22 @@ <property name="fill">False</property> <property name="padding">10</property> <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="buttonOptionsClose"> + <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_buttonOptionsClose_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> <property name="position">0</property> </packing> </child> Added: pytrainer/trunk/import/tool_gant.py =================================================================== --- pytrainer/trunk/import/tool_gant.py (rev 0) +++ pytrainer/trunk/import/tool_gant.py 2010-01-06 09:53:15 UTC (rev 470) @@ -0,0 +1,68 @@ +# -*- 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, sys, commands +import StringIO +from lxml import etree +import dateutil.parser +from dateutil.tz import * # for tzutc() + +from pytrainer.lib.system import checkConf + +class gant(): + 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__) + + def getName(self): + return _("Gant") + + def getVersion(self): + return None + + def getSourceLocation(self): + return "http://cgit.get-open.com/cgit.cgi/gant/" + + def deviceExists(self): + return True + + def isPresent(self): + if self.getVersion(): + return True + else: + 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 + return (utc_dateTime,local_dateTime) Added: pytrainer/trunk/import/tool_garmintools.py =================================================================== --- pytrainer/trunk/import/tool_garmintools.py (rev 0) +++ pytrainer/trunk/import/tool_garmintools.py 2010-01-06 09:53:15 UTC (rev 470) @@ -0,0 +1,77 @@ +# -*- 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, sys, commands +import StringIO +from lxml import etree +import dateutil.parser +from dateutil.tz import * # for tzutc() + +from pytrainer.lib.system import checkConf + +class garmintools(): + 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__) + + def getName(self): + return _("Garmintools") + + def getVersion(self): + outstatus = commands.getstatusoutput('which garmin_save_runs') + if outstatus[0] == 0: #Found garmin_save_runs in path + path = "Unknown" + return path + else: + return None + + def getSourceLocation(self): + return "http://code.google.com/p/garmintools/" + + def deviceExists(self): + outstatus = commands.getstatusoutput('garmin_get_info') + if outstatus[0] is not 0 or outstatus[1].startswith("garmin unit could not be opened"): + return False + else: + return True + + def isPresent(self): + if self.getVersion(): + return True + else: + 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 + return (utc_dateTime,local_dateTime) Added: pytrainer/trunk/import/tool_gpsbabel.py =================================================================== --- pytrainer/trunk/import/tool_gpsbabel.py (rev 0) +++ pytrainer/trunk/import/tool_gpsbabel.py 2010-01-06 09:53:15 UTC (rev 470) @@ -0,0 +1,84 @@ +# -*- 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, sys, commands +import StringIO +from lxml import etree +import dateutil.parser +from dateutil.tz import * # for tzutc() + +from pytrainer.lib.system import checkConf + +class gpsbabel(): + 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__) + + def getName(self): + return _("GPSBabel") + + def getVersion(self): + result = commands.getstatusoutput('gpsbabel -V') + if result[0] == 0: + version = result[1].split() + try: + return version[2] + except: + logging.error("Unexpected result from gpsbabel -V") + return None + return None + + def getSourceLocation(self): + return "http://www.gpsbabel.org/" + + def deviceExists(self): + try: + #TODO Check if this is correct??? + outmod = commands.getstatusoutput('/sbin/lsmod | grep garmin_gps') + if outmod[0]==256: #there is no garmin_gps module loaded + return False + else: + return True + except: + return False + + def isPresent(self): + if self.getVersion(): + return True + else: + 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 + return (utc_dateTime,local_dateTime) Modified: pytrainer/trunk/pytrainer/gui/windowimportdata.py =================================================================== --- pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-01-05 22:36:39 UTC (rev 469) +++ pytrainer/trunk/pytrainer/gui/windowimportdata.py 2010-01-06 09:53:15 UTC (rev 470) @@ -24,8 +24,6 @@ import logging from lxml import etree -from pytrainer.gui.warning import Warning - class WindowImportdata(SimpleGladeApp): def __init__(self, data_path = None, parent=None, config=None): self.data_path = data_path @@ -36,6 +34,7 @@ self.configuration = config self.store = None self.processClass = None + self.toolsDetected = False #SimpleGladeApp.__init__(self, data_path+glade_path, root, domain) def run(self): @@ -71,6 +70,14 @@ return context_id def init_gpsdevice_tab(self): + #Only detect tools once (or if requested) + if not self.toolsDetected: + #Remove all components in vbox - in case of re-detection + for child in self.vboxImportTools.get_children(): + print "removing ", child + self.vboxImportTools.remove(child) + self.detect_tools() + self.toolsDetected = True return def init_file_tab(self): @@ -92,8 +99,59 @@ 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") + #Get import tool_* files + fileList = glob.glob(self.data_path+"import/tool_*.py") + for toolFile in fileList: + index = fileList.index(toolFile) + directory, filename = os.path.split(toolFile) + filename = filename.rstrip('.py') + classname = filename.lstrip('tool_') + #Import module + sys.path.insert(0, self.data_path+"import") + module = __import__(filename) + toolMain = getattr(module, classname) + #Instantiate module + toolClass = toolMain(self.parent, self.data_path) + #Get info from class + toolName = toolClass.getName() + toolTable = gtk.Table() + toolFrame = gtk.Frame(label=toolName) + toolFrame.add(toolTable) + if toolClass.isPresent(): + version = gtk.Label("Version: " + toolClass.getVersion()) + version.set_alignment(0,0) + if toolClass.deviceExists(): + deviceExists = gtk.Label(_("GPS device found") ) + else: + deviceExists = gtk.Label(_("GPS device <b>not</b> found")) + deviceExists.set_alignment(0,0) + deviceExists.set_use_markup(True) + toolTable.attach(version, 0, 1, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, xpadding=5) + toolTable.attach(deviceExists, 0, 1, 1, 2, xoptions=gtk.EXPAND|gtk.FILL, xpadding=5) + toolFrame.set_sensitive(1) + else: + info = gtk.Label(_("This tool was not found on the system") ) + info.set_alignment(0,0.5) + location = gtk.LinkButton(toolClass.getSourceLocation(), _("Tool Homepage")) + info.set_sensitive(0) + toolTable.attach(info, 0, 1, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, xpadding=5) + toolTable.attach(location, 1, 2, 0, 1, xoptions=gtk.EXPAND|gtk.FILL, xpadding=5) + #toolFrame.set_sensitive(0) + self.vboxImportTools.pack_start(toolFrame, expand=False, fill=False, padding=5) + self.win_importdata.show_all() - def validateFile(self, import_filename): """ Iterate through all supported types of file by reading processing files from import directory @@ -247,7 +305,7 @@ def close_window(self): self.win_importdata.hide() - + self.win_importdata.destroy() ############################ ## Window signal handlers ## @@ -307,11 +365,12 @@ else: #Selected file not understood by any of the process files self.updateStatusbar(self.statusbarImportFile, _("Unknown file type") ) - #Display warning + #Display error msg = _("File selected is of unknown or unsupported file type") - warning = Warning(self.data_path) - warning.set_text(msg) - warning.run() + 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) @@ -342,15 +401,24 @@ self.updateStatusbar(self.statusbarImportFile, msgImporting) self.importSelectedActivities(selectedActivities) self.updateStatusbar(self.statusbarImportFile, msgImported) - warning = Warning(self.data_path) - warning.set_text(msgImpored) - warning.set_title(_("Import Success")) - warning.run() + + #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 - def on_buttonFileCancel_clicked(self, widget): + def on_buttonFileClose_clicked(self, widget): self.close_window() - def on_buttonDeviceCancel_clicked(self, widget): + def on_buttonDeviceClose_clicked(self, widget): self.close_window() + def on_buttonOptionsClose_clicked(self, widget): + self.close_window() + + def on_buttonDeviceToolRescan_clicked(self, widget): + self.toolsDetected = False + self.init_gpsdevice_tab() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |