Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -0,0 +1,222 @@
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="dialog1">
<property name="border_width">5</property>
<property name="type">popup</property>
<property name="modal">True</property>
<property name="window_position">center-on-parent</property>
<property name="destroy_with_parent">True</property>
<property name="icon_name">applications-system</property>
<property name="type_hint">dialog</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="n_rows">3</property>
<property name="n_columns">4</property>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Verzeichnis f&#xFC;r heruntergeladene Geoaches:</property>
</object>
<packing>
<property name="right_attach">4</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
</object>
<packing>
<property name="right_attach">4</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="checkbutton1">
<property name="label" translatable="yes">heruntergeladene Bilder verkleinern auf</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="width_chars">4</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">Pixel</property>
</object>
<packing>
<property name="left_attach">3</property>
<property name="right_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Optionen zum Herunterladen&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="label" translatable="yes">Benutzername</property>
</object>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">Passwort</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="invisible_char_set">True</property>
</object>
<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>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Zugangsdaten&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">gtk-apply</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button2</action-widget>
<action-widget response="1">button1</action-widget>
</action-widgets>
</object>
</interface>

Large diffs are not rendered by default.

No changes.
Binary file not shown.

Large diffs are not rendered by default.

@@ -0,0 +1,50 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib
import urllib2, cookielib

class FileDownloader():
USER_AGENT='User-Agent: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.12) Gecko/2009070811 Windows NT Firefox/3.1'

def __init__(self, username, password):
self.username = username
self.password = password
self.logged_in = False

def update_userdata(self, username, password):
self.username = username
self.password = password
self.logged_in = False
print "Up"

def login(self):
cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)

url = 'http://www.geocaching.com/Default.aspx'
values = {'ctl00$MiniProfile$loginUsername':self.username,
'ctl00$MiniProfile$loginPassword':self.password,
'ctl00$MiniProfile$loginRemember': 'on',
'ctl00$MiniProfile$LoginBtn' : 'Go',
'__EVENTTARGET' : '',
'__EVENTARGUMENT' : ''
}

#headers = {'User-Agent' : self.USER_AGENT}
data = urllib.urlencode(values)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
page = response.read()
if 'combination does not match' in page:
raise Exception("Passwort oder Benutzername falsch!")

def get_reader(self, url, values = None):
if not self.logged_in:
self.login()
#headers = {'User-Agent' : self.USER_AGENT}
if values == None:
return urllib2.urlopen(urllib2.Request(url))
else:
data = urllib.urlencode(values)
return urllib2.urlopen(urllib2.Request(url, data))
Binary file not shown.

Large diffs are not rendered by default.

Binary file not shown.
@@ -0,0 +1,114 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

import math
import re

class Coordinate():
SQLROW = {'lat': 'REAL', 'lon' : 'REAL', 'name' : 'TEXT'}

FORMAT_D = 0
FORMAT_DM = 1
re_to_dm_array = re.compile('^(\d?)(\d)(\d) (\d)(\d)\.(\d)(\d)(\d)$')
re_to_d_array = re.compile('^(\d?)(\d)(\d).(\d)(\d)(\d)(\d)(\d)$')

def __init__(self, lat, lon, name = "No Name"):
self.lat = lat
self.lon = lon
self.name = name

def from_d(self, lat, lon):
self.lat = lat
self.lon = lon

def from_dm(self, latdd, latmm, londd, lonmm):
self.lat = latdd + (latmm/60)
self.lon = londd + (lonmm/60)

def from_dm_array(self, sign_lat, lat, sign_lon, lon):
self.from_dm(sign_lat * (lat[0]*10 + lat[1]),
float(str(lat[2]) + str(lat[3]) + "." + str(lat[4]) + str(lat[5]) + str(lat[6])),
sign_lon * (lon[0] * 100 + lon[1] * 10 + lon[2]),
float(str(lon[3]) + str(lon[4]) + "." + str(lon[5]) + str(lon[6]) + str(lon[7])))

def from_d_array(self, sign_lat, lat, sign_lon, lon):
self.lat = int(sign_lat) * float("%d%d.%d%d%d%d%d" % tuple(lat))
self.lon = int(sign_lon) * float("%d%d%d.%d%d%d%d%d" % tuple(lon))

def to_dm_array(self):
[[lat_d, lat_m],[lon_d, lon_m]] = self.to_dm()

d_lat = self.re_to_dm_array.search("%02d %06.3f" % (abs(lat_d), abs(lat_m)))
d_lon = self.re_to_dm_array.search("%03d %06.3f" % (abs(lon_d), abs(lon_m)))
return [
[d_lat.group(i) for i in range (2, 9)],
[d_lon.group(i) for i in range (1, 9)]
]

def to_d_array(self):

d_lat = self.re_to_d_array.search("%08.5f" % abs(self.lat))
d_lon = self.re_to_d_array.search("%09.5f" % abs(self.lon))
return [
[d_lat.group(i) for i in range (2, 7)],
[d_lon.group(i) for i in range (1, 7)]
]

def to_dm(self):
return [ [int(math.floor(self.lat)), (self.lat - math.floor(self.lat)) * 60] ,
[int(math.floor(self.lon)), (self.lon - math.floor(self.lon)) * 60] ]

def bearing_to(self, target):
lat1 = math.radians(self.lat)
lat2 = math.radians(target.lat)
lon1 = math.radians(self.lon)
lon2 = math.radians(target.lon)

dlon = math.radians(target.lon - self.lon);
y = math.sin(dlon) * math.cos(lat2)
x = math.cos(lat1) * math.sin(lat2) - math.sin(lat1)*math.cos(lat2)*math.cos(dlon)
bearing = math.degrees(math.atan2(y, x))
return (360 + bearing) % 360

def get_lat(self, format):
l = abs(self.lat)
if self.lat > 0:
c = 'N'
else:
c = 'S'
if format == self.FORMAT_D:
return "%s%8.5f°" % (c, l)
elif format == self.FORMAT_DM:
return "%s%2d° %06.3f'" % (c, math.floor(l), (l - math.floor(l)) * 60)

def get_lon(self, format):
l = abs(self.lon)
if self.lon > 0:
c = 'E'
else:
c = 'W'
if format == self.FORMAT_D:
return "%s%9.5f°" % (c, l)
elif format == self.FORMAT_DM:
return "%s%3d° %06.3f'" % (c, math.floor(l), (l - math.floor(l)) * 60)

def distance_to (self, target):
R = 6371000;
dlat = math.pow(math.sin(math.radians(target.lat-self.lat)/2),2)
dlon = math.pow(math.sin(math.radians(target.lon-self.lon)/2),2)
a = dlat + math.cos(math.radians(self.lat)) * math.cos(math.radians(target.lat)) * dlon;
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));
return R * c;

def __str__(self):
return "%s %s" % (self.get_lat(Coordinate.FORMAT_DM), self.get_lon(Coordinate.FORMAT_DM))

def serialize(self):

return {'lat': self.lat, 'lon' : self.lon, 'name' : self.name}

def unserialize(self, data):
self.lat = data['lat']
self.lon = data['lon']
self.name = data['name']

Binary file not shown.

Large diffs are not rendered by default.

Binary file not shown.
@@ -0,0 +1,108 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

import socket
import re
import geo

class GpsReader():

EMPTY = {
'position': None,
'altitude': None,
'bearing': None,
'speed': None,
'sats': 0,
'sats_known': 0
}

def __init__(self, gui):
self.gui = gui
self.status = "connecting..."
self.connected = False
self.connect()


def connect(self):
try:
global gpsd_connection
gpsd_connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
gpsd_connection.connect(("127.0.0.1", 2947))
self.status = "connected"
self.connected = True
except:
self.status = "Could not connect to GPSD on Localhost, Port 2947"
print "Could not connect"
self.connected = False

def get_data(self):
try:
if not self.connected:
self.connect()
if not self.connected:
return self.EMPTY
gpsd_connection.send("%s\r\n" % 'o')
data = gpsd_connection.recv(512)
gpsd_connection.send("%s\r\n" % 'y')
quality_data = gpsd_connection.recv(512)

# 1: Parse Quality Data

# example output:
# GPSD,Y=- 1243847265.000 10:32 3 105 0 0:2 36 303 20 0:16 9 65 26
# 1:13 87 259 35 1:4 60 251 30 1:23 54 60 37 1:25 51 149 24 0:8 2
# 188 0 0:7 33 168 24 1:20 26 110 28 1:

if quality_data == "GPSD,Y=?":
sats = 0
sats_known = 0
else:
sats = 0
groups = quality_data.split(':')
sats_known = int(groups[0].split(' ')[2])
for i in range(1, sats_known):
if groups[i].split(' ')[4] == "1":
sats = sats + 1

if data.strip() == "GPSD,O=?":
self.status = "No GPS signal"
return {
'position': None,
'altitude': None,
'bearing': None,
'speed': None,
'sats': sats,
'sats_known': sats_known
}

# 2: Get current position, altitude, bearing and speed

# example output:
# GPSD,O=- 1243530779.000 ? 49.736876 6.686998 271.49 1.20 1.61 49.8566 0.050 -0.175 ? ? ? 3
# GPSD,O=- 1251325613.000 ? 49.734453 6.686360 ? 10.55 ? 180.1476 1.350 ? ? ? ? 2

# or
# GPSD,O=?
try:
[tag, timestamp, time_error, lat, lon, alt, err_hor, err_vert, track, speed, delta_alt, err_track, err_speed, err_delta_alt, mode] = data.split(' ')
except:
print "GPSD Output: \n%s\n -- cannot be parsed." % data
self.status = "Could not read GPSD output."

return {
'position': geo.Coordinate(float(lat), float(lon)),
'altitude': self.to_float(alt),
'bearing': self.to_float(track),
'speed': self.to_float(speed),
'sats': int(sats),
'sats_known': sats_known
}
except Exception as e:
print "Fehler beim Auslesen der Daten: %s " % e
return self.EMPTY

def to_float(self, string):
try:
return float(string)
except:
return 0.0
Binary file not shown.

Large diffs are not rendered by default.

@@ -0,0 +1,200 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib
import os
import threading
import thread
import math
import gobject
import geo
import gtk

class TileLoader(threading.Thread):
downloading = []
semaphore = threading.Semaphore(5)
lock = thread.allocate_lock() #download-lock
drawlock = thread.allocate_lock()
running_threads = 0

#steps:
# - check if file exists.
# - NO: Download tile
# - load pixbuf from file
# - find target position in current pixmap (lock!)
# - draw to pixmap (still locked!)
# - call queue_draw
# optional: acquire locks in all related parts of gui
def __init__(self, tile, zoom, gui, base_dir):
threading.Thread.__init__(self)
self.daemon = False
self.tile = tile
self.zoom = zoom
self.gui = gui
self.base_dir = base_dir

def run(self):
TileLoader.running_threads += 1
filename = os.path.join("%d" % self.zoom, "%d" % self.tile[0], "%d.png" % self.tile[1])
self.local_filename = "%s%s" % (self.base_dir, filename)
self.remote_filename = "http://tile.openstreetmap.org/mapnik/%s" % filename
answer = True
if not os.path.isfile(self.local_filename):
path_1 = "%s%d" % (self.base_dir, self.zoom)
path_2 = "%s/%d" % (path_1, self.tile[0])
try:
if not os.path.exists(path_1):
os.mkdir(path_1)
if not os.path.exists(path_2):
os.mkdir(path_2)
except:
1 #this may file due to threading issues.
# too lazy to do proper locking here
# so just forget about the error


if not os.path.isfile(self.local_filename):
answer = self.download(self.remote_filename, self.local_filename)
# now the file hopefully exists
if not (answer == False):
if self.load():
gobject.idle_add(self.draw)

def load(self, tryno = 0):
# load the pixbuf to memory
try:
self.pbuf = gtk.gdk.pixbuf_new_from_file(self.local_filename)
return True
except Exception as inst:
if tryno == 0:
return self.recover()
else:
TileLoader.running_threads -= 1
if TileLoader.running_threads == 0:
gobject.idle_add(self.gui.draw_marks)
return False

def recover(self):
try:
os.remove(self.local_filename)
except:
pass
self.download(self.remote_filename, self.local_filename)
return self.load(1)

def draw(self):
acquired = False
try:

widget = self.gui.drawing_area
gc = widget.get_style().fg_gc[gtk.STATE_NORMAL]
gc.set_function(gtk.gdk.COPY)
# to draw "night mode": INVERT

a, b, width, height = widget.get_allocation()
size = self.gui.ts.tile_size()
x = self.gui.map_center_x
y = self.gui.map_center_y
xi = int(self.gui.map_center_x)
yi = int(self.gui.map_center_y)
offset_x = int(self.gui.map_width/2 - (x - int(x)) * size)
offset_y = int(self.gui.map_height/2 -(y - int(y)) * size)
span_x = int(math.ceil(float(self.gui.map_width)/(size * 2.0)))
span_y = int(math.ceil(float(self.gui.map_height)/(size * 2.0)))
if self.tile[0] in range(xi - span_x, xi + span_x + 1, 1) and self.tile[1] in range(yi - span_y, yi + span_y + 1, 1) and self.zoom == self.gui.ts.zoom:
dx = (self.tile[0] - xi) * size + offset_x
dy = (self.tile[1] - yi) * size + offset_y

self.drawlock.acquire()
acquired = True
self.gui.pixmap.draw_pixbuf(gc, self.pbuf, 0, 0, dx, dy, -1, -1)

widget.queue_draw_area(max(self.gui.draw_root_x + self.gui.draw_at_x + dx, 0), max(self.gui.draw_root_y + self.gui.draw_at_y + dy, 0), size, size)


finally:
if acquired:
self.drawlock.release()

TileLoader.running_threads -= 1

#if TileLoader.running_threads <= 0:
#gobject.idle_add(self.gui.draw_marks, self)

def download(self, remote, local):

self.lock.acquire()
try:
if (remote in self.downloading):
return None
if os.path.exists(local):
return None
self.downloading.append(remote)
finally:
self.lock.release()

self.semaphore.acquire()
try:
if not self.zoom == self.gui.ts.zoom:
return None
can_download = False
webFile = urllib.urlopen(remote)
if "text/html" in webFile.info()['Content-Type']:
print "File not found: %s" % remote
return False
localFile = open(local, 'wb')
localFile.write(webFile.read())
webFile.close()
localFile.close()
can_download = True
except:
pass
finally:
self.semaphore.release()
#self.lock.acquire()
#try:
self.downloading.remove(remote)
#if len(self.downloading) == 0 and can_download:
# Gui.schedule_redraw = True
#finally:
# self.lock.release()
return True

class TileServer():

def __init__(self):
self.zoom = 14
self.max_zoom = 17

def get_zoom(self):
return self.zoom

def set_zoom(self, zoom):
if zoom < 1 or zoom > self.max_zoom:
return
self.zoom = zoom

def tile_size(self):
return 256

def deg2tilenum(self, lat_deg, lon_deg):
lat_rad = lat_deg * math.pi / 180.0
n = 2.0 ** self.zoom
xtile = int((lon_deg + 180.0) / 360.0 * n)
ytile = int((1.0 - math.log(math.tan(lat_rad) + (1.0 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
return(xtile, ytile)

def deg2num(self, coord):
pi = 3.1415927
lat_rad = (coord.lat * math.pi) / 180.0
n = 2.0 ** self.zoom
xtile = (coord.lon + 180.0) / 360.0 * n
ytile = (1.0 - math.log(math.tan(lat_rad) + (1.0 / math.cos(lat_rad))) / math.pi) / 2.0 * n
return(xtile, ytile)

def num2deg(self, xtile, ytile):
n = 2.0 ** self.zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
lat_deg = lat_rad * 180.0 / math.pi
return geo.Coordinate(lat_deg, lon_deg)
Binary file not shown.
@@ -0,0 +1,195 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

#import downloader
import geocaching
import json
import sqlite3
import re
import copy


class PointProvider():
USER_AGENT='User-Agent: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.12) Gecko/2009070811 Windows NT Firefox/3.1'

def __init__(self, filename, downloader, ctype, table):
self.filterstack = []
self.conn = sqlite3.connect(filename)
self.conn.row_factory = sqlite3.Row
self.conn.text_factory = str
self.ctype = ctype
self.downloader = downloader
self.cache_table = table
self.filterstring = []
self.filterargs = []
c = self.conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS %s (%s)' % (self.cache_table, ', '.join([' '.join(m) for m in self.ctype.SQLROW.items()])))
c.execute('CREATE INDEX IF NOT EXISTS %s_latlon ON %s (lat ASC, lon ASC)' % (self.cache_table, self.cache_table))
c.close()

def save(self):
self.conn.commit()

def __del__(self):
print "closing"
self.conn.commit()
self.conn.close()

def add_point(self, p, replace = False):
c = self.conn.cursor()
if p.found:
f = 1
else:
f = 0
if replace:
mode = "REPLACE"
else:
mode = "IGNORE"
print p.serialize()
c.execute("INSERT OR %s INTO %s (`%s`) VALUES (%s)" % (mode, self.cache_table, '`, `'.join(self.ctype.SQLROW.keys()), ', '.join([':%s' % k for k in self.ctype.SQLROW.keys()])), p.serialize())
c.close()

def get_points(self, c1, c2):

c = self.conn.cursor()

c.execute('SELECT * FROM %s WHERE (lat BETWEEN ? AND ?) AND (lon BETWEEN ? AND ?)' % self.cache_table, (min(c1.lat, c2.lat), max(c1.lat, c2.lat), min(c1.lon, c2.lon), max(c1.lon, c2.lon)))
points = []
for row in c:
coord = self.ctype(row['lat'], row['lon'])
coord.unserialize(row)
points.append(coord)
c.close()
return points

def get_titles_and_names(self):
c = self.conn.cursor()
c.execute('SELECT name, title FROM %s' % self.cache_table)
strings = []
for row in c:
strings.append(row['name'])
strings.append(row['title'])
c.close()
return strings


def get_nearest_point_filter(self, center, c1, c2):
filterstring = copy.copy(self.filterstring)
filterargs = copy.copy(self.filterargs)

filterstring.append('((lat BETWEEN ? AND ?) AND (lon BETWEEN ? AND ?))')
filterargs.append(min(c1.lat, c2.lat))
filterargs.append(max(c1.lat, c2.lat))
filterargs.append(min(c1.lon, c2.lon))
filterargs.append(max(c1.lon, c2.lon))

c = self.conn.cursor()
# we don't have 'power' or other advanced mathematic operators
# in sqlite, so doing fake distance calculation here
query = 'SELECT * FROM %s WHERE %s ORDER BY ABS(lat-?)*ABS(lon-?) DESC LIMIT 1' % (self.cache_table, " AND ".join(filterstring))

filterargs.append(center.lat)
filterargs.append(center.lon)
c.execute(query, tuple(filterargs))

points = []
for row in c:
coord = self.ctype(row['lat'], row['lon'])
coord.unserialize(row)
return coord
return None

def set_filter(self, found = None, has_details = None, owner_search = '', name_search = '', size = None, terrain = None, diff = None, ctype = None, adapt_filter = False):
# a value "None" means: apply no filtering on this value

if adapt_filter:
filterstring = copy.copy(self.filterstring)
filterargs = copy.copy(self.filterargs)
else:
filterstring = []
filterargs = []

if found == True:
filterstring.append('(found = 1)')
elif found == False:
filterstring.append('(found = 0)')

if has_details == True:
filterstring.append("(desc != '' or shortdesc != '')")
elif has_details == False:
filterstring.append("NOT (desc != '' or shortdesc != '')")

if owner_search != None and len(owner_search) > 2:
filterstring.append("(owner LIKE '%%%s%%')" % owner_search)

if name_search != None and len(name_search) > 2:
filterstring.append("((name LIKE '%%%s%%') OR (title LIKE '%%%s%%'))" % (name_search, name_search))

if size != None:
filterstring.append('(size IN (%s))' % (", ".join([str(b) for b in size])))

if terrain != None:
filterstring.append('(terrain >= ?) AND (terrain <= ?)')
filterargs.append(terrain[0] * 10 )
filterargs.append(terrain[1] * 10 )

if diff != None:
filterstring.append('(difficulty >= ?) AND (difficulty <= ?)')
filterargs.append(diff[0] * 10 )
filterargs.append(diff[1] * 10 )

if ctype != None:
if len(ctype) > 0:
filterstring.append('(type IN (%s))' % (", ".join(['?' for b in ctype])))
for b in ctype:
filterargs.append(b)

if len(filterstring) == 0:
filterstring.append('1')

self.filterstring = filterstring
self.filterargs = filterargs

def push_filter(self):
self.filterstack.append((self.filterstring, self.filterargs))

def pop_filter(self):
self.filterstring, self.filterargs = self.filterstack.pop()

def get_points_filter(self, location = None):
filterstring = copy.copy(self.filterstring)
filterargs = copy.copy(self.filterargs)

if location != None:
c1, c2 = location
filterstring.append('((lat BETWEEN ? AND ?) AND (lon BETWEEN ? AND ?))')
filterargs.append(min(c1.lat, c2.lat))
filterargs.append(max(c1.lat, c2.lat))
filterargs.append(min(c1.lon, c2.lon))
filterargs.append(max(c1.lon, c2.lon))

c = self.conn.cursor()
query = 'SELECT * FROM %s WHERE %s' % (self.cache_table, " AND ".join(filterstring))

c.execute(query, tuple(filterargs))
points = []
for row in c:
coord = self.ctype(row['lat'], row['lon'])
coord.unserialize(row)
points.append(coord)
c.close()
return points

def find_by_string(self, string):
query = 'SELECT * FROM %s WHERE name LIKE ? OR title LIKE ? LIMIT 2' % self.cache_table
c = self.conn.cursor()
c.execute(query, (string, string))
row = c.fetchone()
coord = self.ctype(row['lat'], row['lon'])
coord.unserialize(row)

# we cannot reliably determine # of results, so using workaround here
if c.fetchone() != None:
return None
return coord

Binary file not shown.

Large diffs are not rendered by default.

Binary file not shown.
@@ -0,0 +1,15 @@

[Desktop Entry]
Name=AdvancedCaching
Comment=Advanced Geocaching Tool For Linux
Encoding=UTF-8
Version=0.0
Type=Application
Exec=advancedcaching.py --simple
Icon=advancedcaching
Terminal=false
Categories=Office;
SingleInstance=true
StartupNotify=true
Comment[de_DE.UTF-8]=An Advanced Linux Geocaching tool
Name[de_DE]=advancedcaching.desktop
Binary file not shown.