#!/usr/bin/env python #GetCache - a tool to gather and process geocache descriptions #Copyright (C) 2008 Hein Ragas # #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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # CHANGELOG: # 1.1 : Initial public release # 1.2 : Added capabilities of showing a certain number of logs in the HTML # 1.3 : Added capabilities of mirroring images in descriptions # 1.4 : Multi-language # 1.5 : Ported to use lxml """GetCache v1.5 Downloads and combines geocache-descriptions of geocaching.com. Exports the descriptions to HTML and waypoint information to KML and GPX formats. Offers the possibility to upload the waypoints directly to a Garmin USB-GPS receiver. The geo-* tools (http://geo.rkkda.com/) and GPSBabel (http://www.gpsbabel.org) have to be installed and available in the path. Usage: gecache [options] [waypoint] ([waypoint]...) Options: -?, --help Shows this help -g, --gpx (1 or 0) Produces a GPX-file when set to 1 -k, --kml (1 or 0) Produces a KML-file when set to 1 -h, --html (1 or 0) Produces a HTML-file when set to 1 -s, --sendtogps (1 or 0) Sends the waypoints to a Garmin USB-GPS Receiver. Implies '-g 1'. -r, --redownload Do not cache the geocache information from gc.com -n, --name File-name to be used for the output files -d, --desc Descriptions of the list -z, --zip Creates a ZIP-file of all output files -l, --logs ('a' or a number) Shows logs in the HTML. '-l a' shows all logs, '-l 0' shows no logs, otherwise it will show the given number of logs. Implies '-h 1'. -m, --mirror (1 or 0) Makes a local copy of images used in the HTML, so that the geocache descriptions can also be read offline. Implies '-h 1'. If no name or description is given, the GUI will appear. Options that are not set will be read from the configuration file (~/.getcacherc). After a run through the GUI, the settings will be written back to the configuration file. Examples: getcache getcache -g 1 -s 1 GCxxxx GCyyyy For more help, see http://www.logrus.nl/getcache . """ FALSE = 0 TRUE = 1 import sys import gobject import pygtk pygtk.require('2.0') import gtk import datetime import math import os import re import ConfigParser from lxml import etree import lxml.html from user import home import getopt from sgmllib import SGMLParser import htmlentitydefs class BaseHTMLProcessor(SGMLParser): def reset(self): # extend (called by SGMLParser.__init__) self.pieces = [] SGMLParser.reset(self) def unknown_starttag(self, tag, attrs): # called for each start tag # attrs is a list of (attr, value) tuples # e.g. for
, tag="pre", attrs=[("class", "screen")]
        # Ideally we would like to reconstruct original tag and attributes, but
        # we may end up quoting attribute values that weren't quoted in the source
        # document, or we may change the type of quotes around the attribute value
        # (single to double quotes).
        # Note that improperly embedded non-HTML code (like client-side Javascript)
        # may be parsed incorrectly by the ancestor, causing runtime script errors.
        # All non-HTML code must be enclosed in HTML comment tags ()
        # to ensure that it will pass through this parser unaltered (in handle_comment).
        strattrs = "".join([' %s="%s"' % (key, value) for key, value in attrs])
        self.pieces.append("<%(tag)s%(strattrs)s>" % locals())

    def unknown_endtag(self, tag):         
        # called for each end tag, e.g. for 
, tag will be "pre" # Reconstruct the original end tag. self.pieces.append("" % locals()) def handle_charref(self, ref): # called for each character reference, e.g. for " ", ref will be "160" # Reconstruct the original character reference. self.pieces.append("&#%(ref)s;" % locals()) def handle_entityref(self, ref): # called for each entity reference, e.g. for "©", ref will be "copy" # Reconstruct the original entity reference. self.pieces.append("&%(ref)s" % locals()) # standard HTML entities are closed with a semicolon; other entities are not if htmlentitydefs.entitydefs.has_key(ref): self.pieces.append(";") def handle_data(self, text): # called for each block of plain text, i.e. outside of any tag and # not containing any character or entity references # Store the original text verbatim. self.pieces.append(text) def handle_comment(self, text): # called for each HTML comment, e.g. # Reconstruct the original comment. # It is especially important that the source document enclose client-side # code (like Javascript) within comments so it can pass through this # processor undisturbed; see comments in unknown_starttag for details. self.pieces.append("" % locals()) def handle_pi(self, text): # called for each processing instruction, e.g. # Reconstruct original processing instruction. self.pieces.append("" % locals()) def handle_decl(self, text): # called for the DOCTYPE, if present, e.g. # # Reconstruct original DOCTYPE self.pieces.append("" % locals()) def output(self): """Return processed HTML as a single string""" return "".join(self.pieces) class ImageMirror(BaseHTMLProcessor): name = '' def setName(self, name): self.name = name def reset(self): self.imageList = [] BaseHTMLProcessor.reset(self) def retrieveImages(self, conf): for img in self.imageList: imageParts = img.split(".") newImageName = str(self.imageList.index(img))+'.'+imageParts[len(imageParts)-1] os.popen('curl "' + img + '" -o ' + newImageName) def start_img(self, attrs): newAttr = [] for attr, val in attrs: if attr.lower() == 'src': if not(val in self.imageList): self.imageList.append(val) imageParts = val.split(".") newVal = self.name+'/'+str(self.imageList.index(val))+'.'+imageParts[len(imageParts)-1] newAttr.append((attr, newVal)) else: newAttr.append((attr, val)) self.unknown_starttag('img', newAttr) def getText(node): return lxml.html.tostring(node) def getAllText(xpathExpr,node): text = "" nodes = node.xpath(xpathExpr) for node in nodes: text += node.text return text def convertD2DM(degs): mydegrees = int(float(degs)) remaining = float(degs) - float(mydegrees * 1.0) myminutes = remaining * 60.0 myminutes = round(myminutes * 1000.0, 0) / 1000.0 return str(mydegrees) + " " + str(myminutes) def getCoordinate(waypoint): lat = waypoint.get('lat') lon = waypoint.get('lon') if lat < 0: latDir = "S" lat = abs(lat) else: latDir = "N" if lon < 0: lonDir = "W" lon = abs(lon) else: lonDir = "E" lat = latDir + " " + convertD2DM(lat) lon = lonDir + " " + convertD2DM(lon) return lat + " " + lon def printCache(doc): cacheOutput = '' waypoints = doc.xpath('//wpt') for wpt in waypoints: # Determine whether this is a cache or an additional waypoint cacheType = "0" if wpt.xpath('sym')[0].text == "Geocache" or wpt.xpath('sym')[0].text == "Geocache Found": # Determine the type of cache cacheType = wpt.xpath('type')[0].text if cacheType == "Geocache|Traditional Cache": cacheType = "2" if cacheType == "Geocache|Multi-cache": cacheType = "3" if cacheType == "Geocache|Unknown Cache": cacheType = "8" if cacheType == "Geocache|Virtual Cache": cacheType = "4" cacheOutput += '' cacheOutput += ''+getAllText('name',wpt)+'' cacheOutput += ' - '+getAllText('urlname',wpt) cacheOutput += ' - ' + getCoordinate(wpt) cacheOutput += ' - Size: ' + getAllText('cache/container',wpt) cacheOutput += ' Difficulty: ' + getAllText('cache/difficulty',wpt) cacheOutput += ' Terrain: ' + getAllText('cache/terrain',wpt) + '
' descNode = wpt.xpath('cache/long_description') for desc in descNode: if desc.get('html') == 'False': descText = getText(desc) pat = re.compile('\n') cacheOutput += pat.sub('
', descText) else: cacheOutput += getText(desc) cacheOutput += '
Additional Hint: ' + getAllText('cache/encoded_hints',wpt) + '' pat = re.compile('<') cacheOutput = pat.sub('<', cacheOutput) pat = re.compile('>') cacheOutput = pat.sub('>', cacheOutput) pat = re.compile('&') cacheOutput = pat.sub('&', cacheOutput) return cacheOutput def printCacheLogs(doc, conf): cacheOutput = '' logCounter = 0 logs = doc.xpath('//log') for log in logs: if conf.showLogs == 'a' or int(conf.showLogs) > logCounter: cacheOutput += '
' cacheOutput += getAllText('finder', log) + " " + getAllText('type', log).lower() cacheOutput += ' on ' + getAllText('date',log)[:10] + '
' cacheOutput += getAllText('text',log) logCounter += 1 pat = re.compile('\n') cacheOutput = pat.sub('
', cacheOutput) return cacheOutput # Function to do the actual work def createDescs(name, desc, cacheList, conf): gcCodes = '' mergeList = '' os.chdir(conf.gpxDir) for f in cacheList: mergeList += ' -i gpx -f '+f+'.gpx' if conf.redownload == 1 or (not (os.path.isfile(f+'.gpx'))): gcCodes += f + ' ' if gcCodes != '': if conf.gcUser != '': gcCodes = "-u '" + conf.gcUser + "' -p '" + conf.gcPasswd + "' " + gcCodes print "geo-gpx "+gcCodes os.popen('geo-gpx '+gcCodes) if conf.doHTML == 1: totalHtml = '' for f in cacheList: os.popen("sed 's/groundspeak://g' "+f+".gpx > "+f+"-t.gpx") os.popen("sed 's//g' "+f+"-t.gpx > "+f+"-ns.gpx") os.remove(f+'-t.gpx') doc = etree.parse(f+'-ns.gpx') totalHtml += printCache(doc) if conf.showLogs != 0: totalHtml += printCacheLogs(doc, conf) totalHtml += '
' if conf.mirrorImgs == 1: myMirror = ImageMirror() myMirror.setName(name) myMirror.feed(totalHtml) totalHtml = myMirror.output() if not (os.path.exists(conf.gpxDir+'/'+name)): os.makedirs(conf.gpxDir+'/'+name) os.chdir(conf.gpxDir+'/'+name) myMirror.retrieveImages(conf) os.chdir(conf.gpxDir) # Open the output myhtml = open(conf.gpxDir+'/'+name+'.html', 'w') myhtml.write('') myhtml.write(totalHtml) myhtml.write('') myhtml.close() for f in cacheList: os.remove(f+'-ns.gpx') if conf.doGPX == 1: os.popen("gpsbabel" + mergeList + " -o gpx -x track,merge -F tussen.gpx") os.popen("sed 's/Various geocachers<\/author>/g' tussen.gpx > '"+conf.gpxDir+"/"+ name + ".gpx'") os.remove('tussen.gpx') if conf.sendImmediately == 1: os.popen("gpsbabel -r -t -w -i gpx -f '"+conf.gpxDir+"/"+name+".gpx' -o garmin -F USB:") if conf.doKML == 1: os.popen("gpsbabel" + mergeList + " -o kml -x track,merge -F tussen.kml") os.popen("sed 's/ tussen2.kml") os.popen("sed 's/GPS device/"+desc+"/g' tussen2.kml > '"+conf.gpxDir+"/"+name+".kml'") os.remove('tussen.kml') os.remove('tussen2.kml') if conf.zip == 1: os.chdir(conf.gpxDir) zipList = [] if conf.doHTML == 1: zipList.append(name+'.html') if conf.doGPX == 1: zipList.append(name+'.gpx') if conf.doKML == 1: zipList.append(name+'.kml') if conf.mirrorImgs == 1: zipList.append(name+'/*.*') if len(zipList) > 0: os.popen("zip -m " + name+".zip " + " ".join(zipList)) if conf.mirrorImgs == 1: os.rmdir(conf.gpxDir+'/'+name) class AppLanguage: def __init__(self): self.alreadyPresent = 'Already in the list!' self.nameFirst = 'Give a name first!' self.descFirst = 'Give a description first!' self.nothingToDo = 'Nothing to do' self.processFinished = 'Finished' self.collectionName = 'Name' self.description = 'Description' self.cachesForDate = 'Geocaches for ' self.output = 'Output' self.sendToGPS = 'Send to GPSr' self.redownload = 'Re-download' self.includeImages = 'Incl. images' self.showLogs = 'Show logs' self.allLogs = 'All logs' self.numberOfLogs = 'Number:' self.addCache = 'Add cache:' def readLanguage(self, language): if os.path.isfile(home+'/.getcache.'+language+'.lng'): config = ConfigParser.ConfigParser() config.read(home+'/.getcache.'+language+'.lng') self.alreadyPresent = config.get('language','AlreadyPresent') self.nameFirst = config.get('language','NameFirst') self.descFirst = config.get('language','descFirst') self.nothingToDo = config.get('language','NothingToDo') self.processFinished = config.get('language','ProcessFinished') self.collectionName = config.get('language','CollectionName') self.description = config.get('language','Description') self.cachesForDate = config.get('language','CachesForDate') self.output = config.get('language','Output') self.sendToGPS = config.get('language','SendToGPS') self.redownload = config.get('language','Redownload') self.includeImages = config.get('language','IncludeImages') self.showLogs = config.get('language','ShowLogs') self.allLogs = config.get('language','AllLogs') self.numberOfLogs = config.get('language','NumberOfLogs') self.addCache = config.get('language','AddCache') class AppConfig: def __init__(self): self.doGPX = 1 self.doHTML = 1 self.doKML = 1 self.gpxDir = '.' self.sendImmediately = 0 self.redownload = 0 self.zip = 0 self.gcUser = '' self.gcPasswd = '' self.showLogs = '0' self.mirrorImgs = 0 self.language = 'english' self.lang = AppLanguage() self.sourceGPX = None self.doEverything = 0 def readConfig(self): if os.path.isfile(home+'/.getcacherc'): config = ConfigParser.ConfigParser() config.read(home+'/.getcacherc') self.doGPX = int(config.get('main','gpx')) self.doHTML = int(config.get('main','html')) self.doKML = int(config.get('main','kml')) self.gpxDir = config.get('main','gpxdir') self.sendImmediately = config.get('main','sendtogps') try: self.showLogs = config.get('main','showlogs') self.mirrorImgs = int(config.get('main','mirrorimgs')) self.language = config.get('main','language') self.gcUser = config.get('main','gcuser') self.gcPasswd = config.get('main','gcpwd') except ConfigParser.NoOptionError: pass self.writeConfig() self.lang.readLanguage(self.language) def writeConfig(self): config = ConfigParser.ConfigParser() config.add_section('main') config.set('main','gpx',str(self.doGPX)) config.set('main','html',str(self.doHTML)) config.set('main','kml',str(self.doKML)) config.set('main','gpxdir',self.gpxDir) config.set('main','sendtogps',self.sendImmediately) config.set('main','showlogs',self.showLogs) config.set('main','mirrorimgs',self.mirrorImgs) config.set('main','language',self.language) config.set('main','gcuser',self.gcUser) config.set('main','gcpwd',self.gcPasswd) f = open(home+'/.getcacherc','w') config.write(f) f.close() class GetCache: def digits_check_input(self, widget, event, data=None): key = gtk.gdk.keyval_name (event.keyval) ONLYDIGITS="([0-9.,]|BackSpace|Left|Right|F1|period|Tab|Up|Down)" if not re.match (ONLYDIGITS, key): return True def callback(self, widget, data): self.iter = self.lstore.get_iter_first() found = FALSE while self.iter != None: if self.lstore.get_value(self.iter,0) == self.waypoint.get_text(): found = TRUE self.iter = self.lstore.iter_next(self.iter) if found == TRUE: self.mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, self.conf.lang.alreadyPresent) self.mbox.run() self.mbox.destroy() else: self.iter = self.lstore.append() self.lstore.set(self.iter, 0, self.waypoint.get_text()) # Callback for the start def execute(self, widget, data): if self.namebox.get_text() == '': self.mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, self.conf.lang.nameFirst) self.run() self.mbox.destroy() self.namebox.grab_focus() else: if self.descbox.get_text() == '': self.mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, self.conf.lang.descFirst) self.mbox.run() self.mbox.destroy() self.descbox.grab_focus() else: self.cacheList = [] self.iter = self.lstore.get_iter_first() while self.iter != None: self.cacheList.append(self.lstore.get_value(self.iter,0)) self.iter = self.lstore.iter_next(self.iter) if len(self.cacheList) == 0: self.mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, self.conf.lang.nothingToDo) self.mbox.run() self.mbox.destroy() else: if self.checkGPX.get_active(): self.conf.doGPX = 1 else: self.conf.doGPX = 0 if self.checkHTML.get_active(): self.conf.doHTML = 1 else: self.conf.doHTML = 0 if self.checkKML.get_active(): self.conf.doKML = 1 else: self.conf.doKML = 0 if self.checkSendToGPS.get_active(): self.conf.sendImmediately = 1 else: self.conf.sendImmediately = 0 if self.checkRedownload.get_active(): self.conf.redownload = 1 if self.checkLogs.get_active(): if self.checkAllLogs.get_active(): self.conf.showLogs = 'a' else: self.conf.showLogs = self.numLogEntry.get_text() else: self.conf.showLogs = '0' if self.checkMirror.get_active(): self.conf.mirrorImgs = 1 else: self.conf.mirrorImgs = 0 self.conf.writeConfig() createDescs(self.namebox.get_text(), self.descbox.get_text(), self.cacheList, self.conf) self.mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, self.conf.lang.processFinished) self.mbox.run() self.mbox.destroy() gtk.main_quit() # another callback def delete_event(self, widget, event, data=None): gtk.main_quit() return False def toGPSClicked(self, widget, data=None): if self.checkSendToGPS.get_active(): self.checkGPX.set_active(True) def toGPXClicked(self, widget, data=None): if not(self.checkGPX.get_active()): self.checkSendToGPS.set_active(False) def checkLogsClicked(self, widget, data=None): if self.checkLogs.get_active(): self.checkHTML.set_active(True) self.checkAllLogs.set_sensitive(True) self.checkNumber.set_sensitive(True) self.numLogEntry.set_sensitive(self.checkNumber.get_active()) else: self.checkAllLogs.set_sensitive(False) self.checkNumber.set_sensitive(False) self.numLogEntry.set_sensitive(False) def checkHTMLClicked(self, widget, data=None): if not(self.checkHTML.get_active()): self.checkLogs.set_active(False) self.checkAllLogs.set_sensitive(False) self.checkNumber.set_sensitive(False) self.numLogEntry.set_sensitive(False) self.checkMirror.set_active(False) def checkMirrorClicked(self, widget, data=None): if self.checkMirror.get_active(): self.checkHTML.set_active(True) def logChoiceClicked(self, widget, data=None): self.numLogEntry.set_sensitive(self.checkNumber.get_active()) def __init__(self, conf): self.conf = conf # Create a new window self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title("Get Cache") self.window.connect("delete_event", self.delete_event) self.window.set_border_width(10) # The Table that holds all the stuff self.box2 = gtk.Table(10, 1, True) self.window.add(self.box2) # Label and textbox for setting the name self.box1 = gtk.HBox(False, 0) self.box2.attach(self.box1, 0, 1, 0, 1) self.label = gtk.Label(self.conf.lang.collectionName) self.box1.pack_start(self.label, True, True, 0) self.namebox = gtk.Entry(15) self.namebox.set_text(str(datetime.date.today())) self.box1.pack_start(self.namebox, True, True, 0) self.label.show() self.namebox.show() self.box1.show() # Label and textbox for setting the description self.box1 = gtk.HBox(False, 0) self.box2.attach(self.box1, 0, 1, 1, 2) self.label = gtk.Label(self.conf.lang.description) self.box1.pack_start(self.label, True, True, 0) self.descbox = gtk.Entry(40) self.descbox.set_text(self.conf.lang.cachesForDate + str(datetime.date.today())) self.box1.pack_start(self.descbox, True, True, 0) self.label.show() self.descbox.show() self.box1.show() # Output formats self.box1 = gtk.HBox(False, 0) self.box2.attach(self.box1, 0, 1, 2, 3) self.label = gtk.Label(self.conf.lang.output) self.box1.pack_start(self.label, True, True, 0) self.checkGPX = gtk.CheckButton("GPX") self.checkGPX.set_active(conf.doGPX == 1) self.checkGPX.connect("toggled", self.toGPXClicked, "") self.box1.pack_end(self.checkGPX, True, True, 0) self.checkHTML = gtk.CheckButton("HTML") self.checkHTML.set_active(conf.doHTML == 1) self.checkHTML.connect("toggled", self.checkHTMLClicked, "") self.box1.pack_end(self.checkHTML, True, True, 0) self.checkKML = gtk.CheckButton("KML") self.checkKML.set_active(conf.doKML == 1) self.box1.pack_end(self.checkKML, True, True, 0) self.checkKML.show() self.checkHTML.show() self.checkGPX.show() self.label.show() self.box1.show() # Option to send to GPS & re-download GPX-files self.box1 = gtk.HBox(False, 0) self.box2.attach(self.box1, 0, 1, 3, 4) self.checkSendToGPS = gtk.CheckButton(self.conf.lang.sendToGPS) self.checkSendToGPS.set_active(conf.sendImmediately == 1) self.checkSendToGPS.connect("toggled", self.toGPSClicked, "") self.box1.pack_end(self.checkSendToGPS, True, True, 0) self.checkRedownload = gtk.CheckButton(self.conf.lang.redownload) self.checkRedownload.set_active(False) self.box1.pack_start(self.checkRedownload, True, True, 0) self.checkMirror = gtk.CheckButton(self.conf.lang.includeImages) self.checkMirror.set_active(conf.mirrorImgs == 1) self.checkMirror.connect("toggled", self.checkMirrorClicked, "") self.box1.pack_end(self.checkMirror, True, True, 0) self.checkMirror.show() self.checkRedownload.show() self.checkSendToGPS.show() self.box1.show() # Option to download logs self.box1 = gtk.HBox(False, 0) self.box2.attach(self.box1, 0, 1, 4, 5) self.checkLogs = gtk.CheckButton(self.conf.lang.showLogs) self.checkLogs.set_active(conf.showLogs != '0') self.checkLogs.connect("toggled", self.checkLogsClicked,"") self.box1.pack_start(self.checkLogs, True, True, 0) self.checkAllLogs = gtk.RadioButton(None, self.conf.lang.allLogs) self.checkAllLogs.connect("toggled", self.logChoiceClicked, "") self.box1.pack_start(self.checkAllLogs, True, True, 0) self.checkNumber = gtk.RadioButton(self.checkAllLogs, self.conf.lang.numberOfLogs) self.checkNumber.connect("toggled", self.logChoiceClicked, "") self.box1.pack_start(self.checkNumber, True, True, 0) self.numLogEntry = gtk.Entry(3) self.numLogEntry.connect("key_press_event",self.digits_check_input,"") self.box1.pack_start(self.numLogEntry, True, True, 0) if self.conf.showLogs == '0': self.checkAllLogs.set_sensitive(False) self.checkNumber.set_sensitive(False) self.numLogEntry.set_sensitive(False) else: if self.conf.showLogs == 'a': self.checkAllLogs.set_active(True) self.numLogEntry.set_sensitive(False) else: self.checkNumber.set_active(True) self.numLogEntry.set_text(self.conf.showLogs) self.numLogEntry.show() self.checkNumber.show() self.checkAllLogs.show() self.label.show() self.checkLogs.show() self.box1.show() # Textbox and button to add waypoints to the list self.box1 = gtk.HBox(False, 0) self.box2.attach(self.box1, 0, 1, 5, 6) self.label = gtk.Label(self.conf.lang.addCache) self.box1.pack_start(self.label, True, True, 0) self.waypoint = gtk.Entry(8) self.waypoint.set_text("GC") self.box1.pack_start(self.waypoint, True, True, 0) self.button2 = gtk.Button(None, gtk.STOCK_ADD) self.button2.connect("clicked", self.callback, None) self.box1.pack_start(self.button2, True, True, 0) self.label.show() self.waypoint.show() self.button2.show() self.box1.show() # Scrolling window to contain the list self.sw = gtk.ScrolledWindow() self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) self.box2.attach(self.sw, 0, 1, 6, 10) self.sw.show() # List store self.lstore = gtk.ListStore(gobject.TYPE_STRING) # Tree view self.treeview = gtk.TreeView(self.lstore) self.column = gtk.TreeViewColumn('Waypoint', gtk.CellRendererText(), text=0) self.treeview.append_column(self.column) self.sw.add(self.treeview) self.treeview.show() # Button to start the whole process self.button2 = gtk.Button(None, gtk.STOCK_EXECUTE) self.button2.connect("clicked", self.execute, None) self.box2.attach(self.button2, 0, 1, 10, 11) self.button2.show() # Make everything visible self.box2.show() self.window.show() self.waypoint.select_region(2,2) self.waypoint.grab_focus() def usage(): print __doc__ def main(): gtk.main() if __name__ == "__main__": conf = AppConfig() conf.readConfig() listName = '' listDesc = '' try: opts, args = getopt.getopt(sys.argv[1:],"z?g:k:h:s:rn:d:l:m:epq:",["gpx=","kml=","html=","sendtogps=","redownload","name=","desc=","help","zip","logs=","mirror=","everything","pocketquery="]) except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ("-?", "--help"): usage() sys.exit(2) if opt in ("-g", "--gpx"): conf.doGPX = int(arg) if opt in ("-k", "--kml"): conf.doKML = int(arg) if opt in ("-h", "--html"): conf.doHTML = int(arg) if opt in ("-s", "--sendtogps"): conf.sendImmediately = int(arg) if opt in ("-r", "--redownload"): conf.redownload = 1 if opt in ("-n", "--name"): listName = arg if opt in ("-d", "--desc"): listDesc = arg if opt in ("-z", "--zip"): conf.zip = 1 if opt in ("-l", "--logs"): conf.showLogs = arg if opt in ("-m", "--mirror"): conf.mirrorImgs = int(arg) if opt in ("-e", "--everything"): conf.doEverything = 1 if opt in ("-pq", "--pocketquery"): conf.sourceGPX = arg if conf.sendImmediately == 1: conf.doGPX = 1 if conf.showLogs != '0' or conf.mirrorImgs == 1: conf.doHTML = 1 if listName != '' and listDesc != '': cacheList = args createDescs(listName, listDesc, cacheList, conf) print "Process finished." else: getcache = GetCache(conf) main()