def cacheAddLog(found, self=self, cache=cache): if found: logType = 'Found It' logDate = cache.found_date else: logType = "Didn't find it" logDate = cache.dnf_date dlg = FoundCache(self, cache.code, logType, logDate, cache.own_log, cache.own_log_encoded) if dlg.ShowModal() == wx.ID_OK: Publisher.sendMessage('status.push', _('Marking cache %s as "%s"') % (cache.code, logType)) newLog = cache.addLog(None, date = wxDateTimeToPy(dlg.date.GetValue()), logType = logType, finder_id = geocacher.config().GCUserID, finder_name = geocacher.config().GCUserName, encoded = dlg.encodeLog.GetValue(), text = dlg.logText.GetValue()) if found: cache.found = True cache.found_date = newLog.date else: cache.dnf = True cache.dnf_date = newLog.date cache.own_log_id = newLog.logId cache.user_date = datetime.now() cache.save() geocacher.db().commit() cache.refreshOwnLog() self._table.ReloadRow(row) self.Reset() Publisher.sendMessage('status.pop') dlg.Destroy()
def DeleteRows(self, rows): """ Delete the given list of rows form the table. Argument rows: List containing the positions of the columns to delete. """ deleteCount = 0 rows = rows[:] rows.sort() toDelStr ="" for row in rows: if toDelStr == "": toDelStr = self.data[row]['code'] else: toDelStr = toDelStr + ', ' + self.data[row]['code'] dlg = wx.MessageDialog(None, message=_("Are you sure you wish to delete the following: ") + toDelStr, caption=_("Geocacher Delete Caches?"), style=wx.YES_NO|wx.ICON_QUESTION) if dlg.ShowModal() == wx.ID_YES: for row in rows: geocacher.db().getCacheByCode(self.data[row-deleteCount]['code']).delete() self.data.pop(row-deleteCount) # we need to advance the delete count # to make sure we delete the right rows deleteCount += 1
def DeleteRows(self, rows): """ Delete the given list of rows form the table. Argument rows: List containing the positions of the columns to delete. """ deleteCount = 0 rows = rows[:] rows.sort() toDelStr = "" for row in rows: if toDelStr == "": toDelStr = self.data[row]['code'] else: toDelStr = toDelStr + ', ' + self.data[row]['code'] dlg = wx.MessageDialog( None, message=_("Are you sure you wish to delete the following: ") + toDelStr, caption=_("Geocacher Delete Caches?"), style=wx.YES_NO | wx.ICON_QUESTION) if dlg.ShowModal() == wx.ID_YES: for row in rows: geocacher.db().getCacheByCode( self.data[row - deleteCount]['code']).delete() self.data.pop(row - deleteCount) # we need to advance the delete count # to make sure we delete the right rows deleteCount += 1
def cacheCorrect(event, self=self, row=row, cache=cache): '''Add/Edit Correction of the Lat/Lon for the selected cache (row)''' self.SelectRow(row) #cache = self._table.GetRowCache(row) # create data dictionary for the dialog and it's validators data = {'lat': cache.lat, 'lon': cache.lon, 'clat': cache.clat, 'clon': cache.clon, 'cnote': cache.cnote} dlg = CorrectLatLon(self, wx.ID_ANY, cache.code, data, not cache.corrected) # show the dialog and update the cache if OK clicked and there # where changes if dlg.ShowModal() == wx.ID_OK and (data['clat'] != cache.clat or data['clon'] != cache.clon or data['cnote'] != cache.cnote): Publisher.sendMessage('status.push',_('Correcting cache: %s') % cache.code) cache.clat = data['clat'] cache.clon = data['clon'] cache.cnote = data['cnote'] cache.corrected = True cache.user_date = datetime.now() cache.save() geocacher.db().commit() self._table.ReloadRow(row) self.Reset() Publisher.sendMessage('status.pop') dlg.Destroy()
def OnBackupDb(self, event=None): ### SQL """ Handles the event from the "Backup Database" menu item. Keyword Argument event: The event causing this function to be called. """ self.pushStatus(_("Backing up the Database")) geocacher.db().backup() self.popStatus()
def OnBackupDb(self, event=None): ### SQL ''' Handles the event from the "Backup Database" menu item. Keyword Argument event: The event causing this function to be called. ''' self.pushStatus(_('Backing up the Database')) geocacher.db().backup() self.popStatus()
def __init__(self, parent, id): ''' Initialisation for the main frame. Arguments parent: The parent window of the frame. id: The ID to give the frame. ''' self.displayCache = None size = geocacher.config().mainWinSize # check that the Current location is in the db if geocacher.config().currentLocation not in geocacher.db( ).getLocationNameList(): geocacher.config().currentLocation = geocacher.db( ).getLocationNameList()[0] wx.Frame.__init__(self, parent, wx.ID_ANY, _("Geocacher"), size=(size), style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE) self.Bind(wx.EVT_CLOSE, self.OnQuit) self.SetIcon( wx.Icon( os.path.join(geocacher.getBasePath(), 'gfx', 'treasure_chest.ico'), wx.BITMAP_TYPE_ICO)) self.buildStatusBar() self.buildMenu() self.buildToolBar() self.splitter = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_LIVE_UPDATE | wx.SP_BORDER) self.cacheGrid = CacheGrid(self.splitter) self.Description = Html.HtmlWindow(self.splitter, wx.ID_ANY, name="Description Pannel") self.splitter.SetMinimumPaneSize(20) self.splitter.SplitHorizontally(self.cacheGrid, self.Description, geocacher.config().detailSplit) self.updateStatus() self.displayedCache = None self.updateDetail(geocacher.config().displayedCache) Publisher.subscribe(self.updateDetailMsg, 'cache.selected') Publisher.subscribe(self.NewLocationMsg, 'location.new') Publisher.subscribe(self.popStatusMsg, 'status.pop') Publisher.subscribe(self.pushStatusMsg, 'status.push') Publisher.subscribe(self.updateStatusMsg, 'status.update')
def cacheUnArc(event, self=self, row=row, cache=cache): '''Mark the selected cache (row) as un-archived''' Publisher.sendMessage('status.push', _('Un-archiving cache: %s') % cache.code) cache.archived = False cache.user_date = datetime.now() cache.save() geocacher.db().commit() self._table.ReloadRow(row) self.Reset() Publisher.sendMessage('status.pop')
def __init__(self): Grid.PyGridTableBase.__init__(self) self.colLabels = [_('Name'), _('Latitude'), _('Longitude')] self.renderers = [None, LatRenderer, LonRenderer] self.editors = [None, LatEditor, LonEditor] self.data = [] locationNames = geocacher.db().getLocationNameList() for locationName in locationNames: location = geocacher.db().getLocationByName(locationName) self.data.append([location.name, location.lat, location.lon]) self._rows = self.GetNumberRows() self._cols = self.GetNumberCols()
def __init__(self): Grid.PyGridTableBase.__init__(self) self.colLabels = [_('Name'), _('Latitude'), _('Longitude')] self.renderers=[None, LatRenderer, LonRenderer] self.editors = [None, LatEditor, LonEditor] self.data = [] locationNames = geocacher.db().getLocationNameList() for locationName in locationNames: location = geocacher.db().getLocationByName(locationName) self.data.append([location.name, location.lat, location.lon]) self._rows = self.GetNumberRows() self._cols = self.GetNumberCols()
def OnMaintainDb(self, event=None): """ Handles the event from the "Maintain Database" menu item. Keyword Argument event: The event causing this function to be called. """ self.pushStatus(_("Maintaining Database")) opts = DatabaseCleanupOptions(self) if opts.ShowModal() == wx.ID_OK: opts.SaveConf() geocacher.db().maintdb() if geocacher.config().cleanupCacheAct != "none" or geocacher.config().cleanupLog > 0: self.cacheGrid.ReloadCaches() self.popStatus()
def __init__(self, lid=minint): cur = geocacher.db().cursor() if lid < 0: cur.execute("SELECT id FROM Logs WHERE id=?", (lid, )) if cur.fetchone() is None: cur.execute('SELECT MIN(id) FROM logs') row = cur.fetchone() if row[0] is None: lid = -1 else: lid = min(row[0] - 1, -1) cur.execute("SELECT id FROM Logs WHERE id=?", (lid, )) if cur.fetchone() is None: cur.execute("INSERT INTO Logs(id) VALUES (?)", (lid, )) #cur.execute("INSERT INTO Logs(id, cache_id, date, type, finder_id, finder_name, encoded, text) VALUES (?, -1, -0.1, '', 0, '', 0, '')", (lid,)) cur.execute( 'SELECT id, cache_id, log_date, type, finder_id, finder_name, encoded, text FROM Logs WHERE id=?', (lid, )) row = cur.fetchone() if type(row) is sqlite3.dbapi2.Row: self.logId = row[0] self.cache_id = row[1] self.date = row[2] self.logType = row[3] self.finder_id = row[4] self.finder_name = row[5] self.encoded = row[6] self.text = row[7] else: raise geocacher.InvalidID('Invalid Log ID: %d' % lid)
def findsByOwner(self): cur = geocacher.db().cursor() cur.execute( "SELECT owner, owner_id, COUNT(owner) AS cnt FROM Caches WHERE found = 1 GROUP BY owner ORDER BY cnt DESC" ) rows = cur.fetchall() data = [] maxVal = 0 i = 0 while i < 20 and i < len(rows): row = rows[i] i += 1 owner = "%i - <a href='http://www.geocaching.com/profile/?id=%i'>%s</a>" % ( i, row[1], row[0]) if i < 10: owner = ' ' + owner data.append([owner, row[2]]) if row[2] > maxVal: maxVal = row[2] html = self.titleWide('Finds By Owner') html += self.horizTable(data, maxVal, 50, 'Owner', True) numOthers = len(rows) - i if numOthers > 0: html += "<br /><i>%s has also found caches placed by <b>%i</b> other people</i>" % ( self.userName, numOthers) html += """<br /><br />\n""" return html
def delete(self): cur = geocacher.db().cursor() cur.execute("DELETE FROM Caches WHERE id=?", (self.id,)) cur.execute("DELETE FROM Attributes WHERE cache_id=?", (self.id,)) cur.execute("DELETE FROM Logs WHERE cache_id=?", (self.id,)) cur.execute("DELETE FROM Travelbugs WHERE cache_id=?", (self.id,)) cur.execute("DELETE FROM Waypoints WHERE cache_id=?", (self.id,))
def cacheYears(self): years = [] cur = geocacher.db().cursor() cur.execute("SELECT DISTINCT strftime('%Y', found_date) AS yr FROM Caches WHERE found = 1") for row in cur.fetchall(): years.append(int(row[0])) return years
def getAddWaypointCodes(self): '''Returns a list of the codes of the waypoints associated with the cache''' cur = geocacher.db().cursor() cur.execute( "SELECT code FROM Waypoints WHERE cache_id = ? ORDER BY code", (self.id, )) return rows2list(cur.fetchall())
def getTravelBugRefs(self): '''Returns a list of the ref's of the travel bugs in the cache''' cur = geocacher.db().cursor() cur.execute( "SELECT ref FROM Travelbugs WHERE cache_id = ? ORDER BY ref", (self.id, )) return rows2list(cur.fetchall())
def __init__(self, tbid=minint): cur = geocacher.db().cursor() if tbid < 0: cur.execute("SELECT id FROM Travelbugs WHERE id=?", (tbid, )) if cur.fetchone() is None: cur.execute('SELECT MIN(id) FROM Travelbugs') row = cur.fetchone() if row[0] is None: bid = -1 else: bid = min(row[0] - 1, -1) cur.execute("SELECT id FROM Travelbugs WHERE id=?", (tbid, )) if cur.fetchone() is None: cur.execute( "INSERT INTO Travelbugs(id, cache_id, name, ref) VALUES (?, -1, '', '')", (tbid, )) cur.execute( 'SELECT id, cache_id, name, ref FROM Travelbugs WHERE id=?', (tbid, )) row = cur.fetchone() if type(row) is sqlite3.dbapi2.Row: self.id = row[0] self.cache_id = row[1] self.name = row[2] self.ref = row[3] else: raise geocacher.InvalidID('Invalid Travel Bug ID: %d' % tbid)
def save(self): cur = geocacher.db().cursor() cur.execute("DELETE FROM Attributes WHERE id=? AND cache_id=?", (self.attribid, self.cache_id)) cur.execute( "INSERT INTO Attributes (id, inc, cache_id, description) VALUES (?, ?, ?, ?)", (self.attribid, self.inc, self.cache_id, self.description))
def delete(self): cur = geocacher.db().cursor() cur.execute("DELETE FROM Caches WHERE id=?", (self.id, )) cur.execute("DELETE FROM Attributes WHERE cache_id=?", (self.id, )) cur.execute("DELETE FROM Logs WHERE cache_id=?", (self.id, )) cur.execute("DELETE FROM Travelbugs WHERE cache_id=?", (self.id, )) cur.execute("DELETE FROM Waypoints WHERE cache_id=?", (self.id, ))
def OnMaintainDb(self, event=None): ''' Handles the event from the "Maintain Database" menu item. Keyword Argument event: The event causing this function to be called. ''' self.pushStatus(_("Maintaining Database")) opts = DatabaseCleanupOptions(self) if opts.ShowModal() == wx.ID_OK: opts.SaveConf() geocacher.db().maintdb() if geocacher.config( ).cleanupCacheAct != 'none' or geocacher.config().cleanupLog > 0: self.cacheGrid.ReloadCaches() self.popStatus()
def __init__(self, lid=minint): cur = geocacher.db().cursor() if lid < 0: cur.execute("SELECT id FROM Logs WHERE id=?", (lid, )) if cur.fetchone() is None: cur.execute('SELECT MIN(id) FROM logs') row = cur.fetchone() if row[0] is None: lid = -1 else: lid = min(row[0]-1, -1) cur.execute("SELECT id FROM Logs WHERE id=?", (lid, )) if cur.fetchone() is None: cur.execute("INSERT INTO Logs(id) VALUES (?)", (lid,)) #cur.execute("INSERT INTO Logs(id, cache_id, date, type, finder_id, finder_name, encoded, text) VALUES (?, -1, -0.1, '', 0, '', 0, '')", (lid,)) cur.execute('SELECT id, cache_id, log_date, type, finder_id, finder_name, encoded, text FROM Logs WHERE id=?', (lid,)) row = cur.fetchone() if type(row) is sqlite3.dbapi2.Row: self.logId = row[0] self.cache_id = row[1] self.date = row[2] self.logType = row[3] self.finder_id = row[4] self.finder_name = row[5] self.encoded = row[6] self.text = row[7] else: raise geocacher.InvalidID('Invalid Log ID: %d' % lid)
def findsByTerrainDifficulty(self): cur = geocacher.db().cursor() html = self.titleWide('Difficulty / Terrain Chart') html += '<table>\n' html += '<tr>\n' html += self.hrCell('') html += self.hrCell('Terrain', colspan=10, align='center') html += '<tr/>\n' html += '<tr>\n' html += self.hrCell('Difficulty', rowspan=10, align='center') html += self.tCell('') ttotals = {} combinations = 0 hard = 0 for tstar in POSSIBLE_STARS: html += self.tCell('<b>%0.1f</b>' % tstar, width=60, align='center') ttotals[tstar] = 0 html += "<td width='60'></td>\n" html += '</tr>\n' for dstar in POSSIBLE_STARS: dtotal = 0 html += '<tr>\n' html += self.tCell('<b>%0.1f</b>' % dstar, width=60, align='center') for tstar in POSSIBLE_STARS: cur.execute( "SELECT COUNT(id) AS cnt FROM Caches WHERE found = 1 AND difficulty = ? AND terrain = ?", ( dstar, tstar, )) value = cur.fetchone()[0] if value == 0: html += self.cCell('', width=60, align='center') else: html += self.cCell('%i' % value, width=60, align='center') dtotal += value ttotals[tstar] += value combinations += 1 if dstar >= 3.0 or tstar >= 3.0: hard += value html += self.tCell('%i' % dtotal, width=60, align='center') html += '</tr>\n' html += '<tr>\n' html += "<td width='60'></td>\n" html += "<td width='60'></td>\n" for tstar in POSSIBLE_STARS: html += self.tCell('%i' % ttotals[tstar], width=60, align='center') html += '</tr>\n' html += '</table>' html += '<br /><i><b>%i</b> (%i%%) Difficulty / Terrain combinations found, out of <b>81</b>\n' % ( combinations, (combinations * 100) / 81) html += '<br /><b>%i</b> (%0.2f%%) finds were rated with Diff or Terr of 3 or greater</i>\n' % ( hard, (float(hard) / float(self.found)) * 100.0) html += '<br /><br />\n' return html
def getAttributes(self): '''Returns a list of the attributes for the cache''' cur = geocacher.db().cursor() cur.execute("SELECT id, cache_id FROM Attributes WHERE cache_id = ? ORDER BY id" , (self.id,)) attributes = [] for row in cur.fetchall(): attributes.append(Attribute(row[0], row[1])) return attributes
def findsByDifficulty(self): cur = geocacher.db().cursor() cur.execute('SELECT difficulty, COUNT(difficulty) AS cnt FROM Caches WHERE found = 1 GROUP BY difficulty ORDER BY difficulty') data = cur.fetchall() html = self.titleNarrow('Finds by Difficulty Rating') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def findsByTerrain(self): cur = geocacher.db().cursor() cur.execute('SELECT terrain, COUNT(terrain) AS cnt FROM Caches WHERE found = 1 GROUP BY terrain ORDER BY terrain') data = cur.fetchall() html = self.titleNarrow('Finds by Terrain Rating') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def findsByYearPlaced(self): cur = geocacher.db().cursor() cur.execute("SELECT year, count(year) FROM (SELECT STRFTIME('%Y',placed) AS year FROM Caches WHERE found = 1) GROUP BY year ORDER BY year") data = cur.fetchall() html = self.titleNarrow('Finds by Year Placed') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def updateLocations(self): ''' Updates the location selector after a change to the list of locations. ''' for i in range(0, self.selLocation.GetCount()): self.selLocation.Delete(0) for location in geocacher.db().getLocationNameList(): self.selLocation.Append(location)
def getLogDates(self): ''' Returns a sorted list of the dates on which the cache has been logged with the most recent first ''' cur = geocacher.db().cursor() cur.execute("SELECT date FROM Logs WHERE cache_id = ? ORDER BY date DESC", (self.id,)) return rows2list(cur.fetchall())
def getTravelBugs(self): '''Returns a list of the travel bugs in the cache''' cur = geocacher.db().cursor() cur.execute("SELECT id FROM Travelbugs WHERE cache_id = ? ORDER BY ref" , (self.id,)) bugs = [] for row in cur.fetchall(): bugs.append(TravelBug(row[0])) return bugs
def findsByContainer(self): cur = geocacher.db().cursor() cur.execute('SELECT container, COUNT(container) AS cnt FROM Caches WHERE found = 1 GROUP BY container ORDER BY container') data = cur.fetchall() html = self.titleNarrow('Finds by Container') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def GetRowCache(self, row): ''' Returns the cache object associated with the given row. Argument row: Row to get the cache object for. ''' return geocacher.db().getCacheByCode(self.GetRowCode(row))
def updateLocations(self): """ Updates the location selector after a change to the list of locations. """ for i in range(0, self.selLocation.GetCount()): self.selLocation.Delete(0) for location in geocacher.db().getLocationNameList(): self.selLocation.Append(location)
def SetValue(self, row, col, value): ''' Sets the cell at the given coordinates to the given value. Arguments: row: Row coordinate of the cell to change the value for. col: Column coordinate of the cell to change the value for. value: Value to set the cell to. ''' id = self.colNames[col] cache = self.GetRowCache(row) if self.dataTypes[id] == Grid.GRID_VALUE_BOOL: value = bool(value) if id == 'locked': changed = (cache.locked != value) cache.locked = value elif not cache.locked: if id == 'ftf': changed = (cache.ftf != value) cache.ftf = value elif id == 'user_data1': changed = (cache.user_data1 != value) cache.user_data1 = value elif id == 'user_data2': changed = (cache.user_data2 != value) cache.user_data2 = value elif id == 'user_data3': changed = (cache.user_data3 != value) cache.user_data3 = value elif id == 'user_data4': changed = (cache.user_data4 != value) cache.user_data4 = value elif id == 'user_flag': changed = (cache.user_flag != value) cache.user_flag = value else: changed = False else: changed = False if changed: cache.user_date = datetime.now() cache.save() geocacher.db().commit() ## TODO check if moified column is sorted of filtered by, if so do a complete refresh self.ReloadRow(row) self.GetView().ForceRefresh()
def getCurrentLatLon(self): cur = geocacher.db().cursor() cur.execute("SELECT lat, lon FROM Locations WHERE name = ?",(self.currentLocation,)) row = cur.fetchone() if row is None: return (0.0, 0.0) else: return (row[0], row[1])
def buildToolBar(self): """ Builds the toolbar for the main window. """ TBFLAGS = wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT tb = self.CreateToolBar(TBFLAGS) self.tb = tb self.tbFilterName = wx.StaticText(tb, wx.ID_ANY, _("Fiter:"), style=wx.TEXT_ATTR_FONT_ITALIC) tb.AddControl(self.tbFilterName) self.cbHideMine = wx.CheckBox(tb, wx.ID_ANY, _("Hide Mine")) tb.AddControl(self.cbHideMine) self.Bind(wx.EVT_CHECKBOX, self.OnCbHideMine, self.cbHideMine) self.cbHideMine.SetValue(geocacher.config().filterMine) self.cbHideFound = wx.CheckBox(tb, wx.ID_ANY, _("Hide Found")) tb.AddControl(self.cbHideFound) self.Bind(wx.EVT_CHECKBOX, self.OnCbHideFound, self.cbHideFound) self.cbHideFound.SetValue(geocacher.config().filterFound) self.cbHideDisabled = wx.CheckBox(tb, wx.ID_ANY, _("Hide Disabled")) tb.AddControl(self.cbHideDisabled) self.Bind(wx.EVT_CHECKBOX, self.OnCbHideDisabled, self.cbHideDisabled) self.cbHideDisabled.SetValue(geocacher.config().filterDisabled) self.cbHideArchived = wx.CheckBox(tb, wx.ID_ANY, _("Hide Archived")) tb.AddControl(self.cbHideArchived) self.Bind(wx.EVT_CHECKBOX, self.OnCbHideArchived, self.cbHideArchived) self.cbHideArchived.SetValue(geocacher.config().filterArchived) self.cbHideOverDist = wx.CheckBox(tb, wx.ID_ANY, _("Hide Over")) tb.AddControl(self.cbHideOverDist) self.Bind(wx.EVT_CHECKBOX, self.OnCbHideOverDist, self.cbHideOverDist) self.cbHideOverDist.SetValue(geocacher.config().filterOverDist) self.tbMaxDistance = wx.TextCtrl(tb, wx.ID_ANY, value=str(geocacher.config().filterMaxDist), size=[100, -1]) tb.AddControl(self.tbMaxDistance) self.tbMaxDistance.Bind(wx.EVT_LEFT_DCLICK, self.OnMaxDistVal) tb.AddSeparator() tb.AddControl(wx.StaticText(tb, wx.ID_ANY, _("Home location"), style=wx.TEXT_ATTR_FONT_ITALIC)) choices = geocacher.db().getLocationNameList() if geocacher.config().currentLocation in choices: current = geocacher.config().currentLocation else: current = choices[0] geocacher.config().currentLocation = current self.selLocation = wx.ComboBox( tb, wx.ID_ANY, current, choices=choices, size=[150, -1], style=wx.CB_DROPDOWN | wx.CB_SORT ) tb.AddControl(self.selLocation) self.Bind(wx.EVT_COMBOBOX, self.OnSelLocation, self.selLocation) tb.Realize() self.ShowHideFilterBar(geocacher.config().showFilter)
def milestones(self, jump=100): cur = geocacher.db().cursor() cur.execute( "SELECT code, found_date FROM Caches WHERE found = 1 ORDER BY found_date, own_log_id" ) rows = cur.fetchall() dateFormat = geocacher.config().dateFormat html = self.titleWide('Milestones') html += "<table width='750' style='text-align: left;'>\n" html += "<tr>\n" html += self.hrCell('Milestone') html += self.hrCell('Date') html += self.hrCell('Interval') html += self.hrCell(' ') html += self.hrCell('Code') html += self.hrCell(' ') html += self.hrCell('Cache Name') html += "</tr>\n" if jump > 1: row, prevDate = self.mileStoneRow(rows[0][0], 1) html += row else: prevDate = None index = jump numFound = len(rows) while index < numFound: row, prevDate = self.mileStoneRow(rows[index - 1][0], index, prevDate) html += row index += jump row, prevDate = self.mileStoneRow(rows[numFound - 1][0], numFound, prevDate) html += row html += "</table>\n" firstDay = rows[0][1].date() lastDay = rows[numFound - 1][1].date() elapsedDays = (lastDay - firstDay).days + 1 elapsedRate = float(numFound) / float(elapsedDays) cur.execute( "SELECT COUNT(*) FROM (SELECT DISTINCT DATE(found_date) FROM Caches WHERE found = 1)" ) cacheDays = cur.fetchone()[0] cacheRate = float(numFound) / float(cacheDays) elapsedNext = roundUp((index - numFound) / elapsedRate) cacheNext = roundUp((index - numFound) / cacheRate) nextDate = lastDay + datetime.timedelta(days=elapsedNext) html += "<i><br />%s should reach <b>%i</b> finds in <b>%i</b> days (<b>%i</b> Caching days) on <b>%s</b> </i><br />\n" % ( self.userName, index, elapsedNext, cacheNext, nextDate.strftime(geocacher.config().dateFormat)) index += jump elapsedNext = roundUp((index - numFound) / elapsedRate) cacheNext = roundUp((index - numFound) / cacheRate) nextDate = lastDay + datetime.timedelta(days=elapsedNext) html += "and <b>%i</b> finds in <b>%i</b> days (<b>%i</b> Caching days) on <b>%s</b> </i><br />\n" % ( index, elapsedNext, cacheNext, nextDate.strftime(geocacher.config().dateFormat)) html += """<br /><br />\n""" return html
def __init__(self, parent, id): """ Initialisation for the main frame. Arguments parent: The parent window of the frame. id: The ID to give the frame. """ self.displayCache = None size = geocacher.config().mainWinSize # check that the Current location is in the db if geocacher.config().currentLocation not in geocacher.db().getLocationNameList(): geocacher.config().currentLocation = geocacher.db().getLocationNameList()[0] wx.Frame.__init__( self, parent, wx.ID_ANY, _("Geocacher"), size=(size), style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE, ) self.Bind(wx.EVT_CLOSE, self.OnQuit) self.SetIcon(wx.Icon(os.path.join(geocacher.getBasePath(), "gfx", "treasure_chest.ico"), wx.BITMAP_TYPE_ICO)) self.buildStatusBar() self.buildMenu() self.buildToolBar() self.splitter = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_LIVE_UPDATE | wx.SP_BORDER) self.cacheGrid = CacheGrid(self.splitter) self.Description = Html.HtmlWindow(self.splitter, wx.ID_ANY, name="Description Pannel") self.splitter.SetMinimumPaneSize(20) self.splitter.SplitHorizontally(self.cacheGrid, self.Description, geocacher.config().detailSplit) self.updateStatus() self.displayedCache = None self.updateDetail(geocacher.config().displayedCache) Publisher.subscribe(self.updateDetailMsg, "cache.selected") Publisher.subscribe(self.NewLocationMsg, "location.new") Publisher.subscribe(self.popStatusMsg, "status.pop") Publisher.subscribe(self.pushStatusMsg, "status.push") Publisher.subscribe(self.updateStatusMsg, "status.update")
def getLogById(self,id): '''Returns the log with the given id if found, otherwise "None"''' assert type(id)==int cur = geocacher.db().cursor() cur.execute("SELECT id FROM Logs WHERE cache_id = ? AND id = ?", (self.id, id,)) if cur.fetchone() is None: return None else: return Log(id)
def getLastLogDate(self): '''Returns the date of the last log or None if no logs''' cur = geocacher.db().cursor() cur.execute("SELECT MAX(date) FROM Logs WHERE cache_id = ?", (self.id,)) row = cur.fetchone() if row is None: return None else: return row[0]
def GetDisplayedCaches(self): ''' Returns a list containing the cache objects for the selected rows in the table. ''' caches = [] for row in self.data: caches.append(geocacher.db().getCacheByCode(row['code'])) return caches
def cacheYears(self): years = [] cur = geocacher.db().cursor() cur.execute( "SELECT DISTINCT strftime('%Y', found_date) AS yr FROM Caches WHERE found = 1" ) for row in cur.fetchall(): years.append(int(row[0])) return years
def getLastFound(self): '''Returns the date on which the cache was found or None if never Found''' cur = geocacher.db().cursor() cur.execute("SELECT date FROM Logs WHERE cache_id = ? AND type=? ORDER BY date DESC", (self.id,'Found it',)) row = cur.fetchone() if row is None: return None else: return row[0]
def getAttributeById(self,attribid): '''Returns the attribute with the given id if found, otherwise "None"''' assert type(attribid) is int cur = geocacher.db().cursor() cur.execute("SELECT id FROM Attributes WHERE cache_id = ? AND id = ?", (self.id, attribid,)) if cur.fetchone() is None: return None else: return Attribute(attribid, self.id)
def getFoundCount(self): cur = geocacher.db().cursor() cur.execute( "SELECT date FROM Logs WHERE cache_id = ? AND type=? ORDER BY date DESC", ( self.id, 'Found it', )) return len(cur.fetchall())
def getTravelBugs(self): '''Returns a list of the travel bugs in the cache''' cur = geocacher.db().cursor() cur.execute( "SELECT id FROM Travelbugs WHERE cache_id = ? ORDER BY ref", (self.id, )) bugs = [] for row in cur.fetchall(): bugs.append(TravelBug(row[0])) return bugs
def findsByYearPlaced(self): cur = geocacher.db().cursor() cur.execute( "SELECT year, count(year) FROM (SELECT STRFTIME('%Y',placed) AS year FROM Caches WHERE found = 1) GROUP BY year ORDER BY year" ) data = cur.fetchall() html = self.titleNarrow('Finds by Year Placed') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def findsByTerrain(self): cur = geocacher.db().cursor() cur.execute( 'SELECT terrain, COUNT(terrain) AS cnt FROM Caches WHERE found = 1 GROUP BY terrain ORDER BY terrain' ) data = cur.fetchall() html = self.titleNarrow('Finds by Terrain Rating') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def findsByDifficulty(self): cur = geocacher.db().cursor() cur.execute( 'SELECT difficulty, COUNT(difficulty) AS cnt FROM Caches WHERE found = 1 GROUP BY difficulty ORDER BY difficulty' ) data = cur.fetchall() html = self.titleNarrow('Finds by Difficulty Rating') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def findsByContainer(self): cur = geocacher.db().cursor() cur.execute( 'SELECT container, COUNT(container) AS cnt FROM Caches WHERE found = 1 GROUP BY container ORDER BY container' ) data = cur.fetchall() html = self.titleNarrow('Finds by Container') html += self.pieGraph(data) html += """<br /><br />\n""" return html
def NewLocation(self, lat, lon, source, name=""): """ Handles the creation of a new home location. Arguments lat: Latitude of the new location. lon: Longitude of the new location. source: Text describing the source that the new location has come from. Keyword Argument name: Default name for the new location. """ dlg = wx.TextEntryDialog( self, _("Please enter a name for the new Location from ") + source, caption=_("Location Name"), defaultValue=name, ) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return name = dlg.GetValue() dlg.Destroy() if name in geocacher.db().getLocationNameList(): dlg = wx.MessageDialog( self, message=_("Are you sure you want to replace the existing location named ") + name, caption=_("Replace Existing Location"), style=wx.YES_NO | wx.ICON_QUESTION, ) if dlg.ShowModal() == wx.ID_YES: dlg.Destroy() location = geocacher.db().getLocationByName(name) location.lat = lat location.lon = lon else: dlg.Destroy() return else: geocacher.db().addLocation(name, lat, lon) self.updateLocations() self.updateCurrentLocation(name)
def getAttributes(self): '''Returns a list of the attributes for the cache''' cur = geocacher.db().cursor() cur.execute( "SELECT id, cache_id FROM Attributes WHERE cache_id = ? ORDER BY id", (self.id, )) attributes = [] for row in cur.fetchall(): attributes.append(Attribute(row[0], row[1])) return attributes
def getAddWaypointByCode(self,code): '''Returns the additional waypoint with the given code if found, otherwise "None"''' assert type(code)==unicode or type(code)==str cur = geocacher.db().cursor() cur.execute("SELECT code FROM Waypoints WHERE code = ? AND cache_id = ? ORDER BY code",(code, self.id,)) row = cur.fetchone() if row is None: return None else: return Waypoint(row[0])