2
# -*- coding: utf-8 -*-
4
# Copyright (C) 2009 Daniel Fett
5
# This program is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation, either version 3 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
# Author: Daniel Fett simplecaching@fragcom.de
31
from htmlentitydefs import name2codepoint as n2cp
45
SETTINGS_CHECKBOXES = [
50
'download_create_index',
56
'download_run_after_string',
57
'download_output_dir',
58
'download_resize_pixel',
63
def __init__(self, core, pointprovider, userpointprovider):
64
self.ts = ts = openstreetmap.TileServer()
67
self.pointprovider = pointprovider
68
self.userpointprovider = userpointprovider
70
self.current_cache = None
72
self.block_changes = False
74
self.drawing_area_configured = False
75
self.drag_offset_x = 0
76
self.drag_offset_y = 0
77
self.map_center_x, self.map_center_y = 100, 100
78
self.inhibit_zoom = False
79
self.draw_lock = thread.allocate_lock()
83
builder = gtk.Builder()
84
builder.add_from_file("../../glade/main.glade")
85
self.window = builder.get_object("window")
87
builder.connect_signals({"on_window_destroy": self.destroy,
88
"on_zoomin_clicked": self.on_zoomin_clicked,
89
"on_zoomout_clicked": self.on_zoomout_clicked,
90
"on_download_clicked": self.on_download_clicked,
91
'save_config': self.on_save_config,
92
'on_button_download_now_clicked': self.on_download_descriptions_clicked,
93
'on_spinbutton_zoom_change_value': self.on_zoom_changed,
94
'start_search': self.on_start_search_simple,
95
'on_entry_search_key_release_event': self.on_search_simple_key_release,
96
# 'on_vscale_search_terrain_change_value' : self.search_value_terrain_change,
97
# 'on_vscale_search_diff_change_value' : self.search_value_diff_change
98
'on_button_advanced_search_clicked': self.on_search_advanced_clicked,
99
'on_check_search_find_no_details_toggled': self.on_search_details_toggled
103
self.drawing_area = builder.get_object('drawingarea')
104
self.drawing_area.connect("expose_event", self.expose_event)
105
self.drawing_area.connect("configure_event", self.configure_event)
106
self.drawing_area.connect("button_press_event", self.drag_start)
107
self.drawing_area.connect("scroll_event", self.scroll)
108
self.drawing_area.connect("button_release_event", self.drag_end)
109
self.drawing_area.connect("motion_notify_event", self.drag)
110
self.drawing_area.set_events(gtk.gdk.EXPOSURE_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.SCROLL)
111
#self.drawing_area.show()
114
self.zoom_adjustment = builder.get_object('spinbutton_zoom').get_adjustment()
116
self.hpaned = builder.get_object("hpaned1")
117
self.hpaned.set_position(0)
118
self.cache_elements = {
119
'name_downloaded': builder.get_object('link_cache_name'),
120
'name_not_downloaded': builder.get_object('button_cache_name'),
121
'title': builder.get_object('label_cache_title'),
122
'type': builder.get_object('label_cache_type'),
123
'size': builder.get_object('label_cache_size'),
124
'terrain': builder.get_object('label_cache_terrain'),
125
'difficulty': builder.get_object('label_cache_difficulty'),
126
'desc': builder.get_object('label_cache_desc'),
127
'shortdesc': builder.get_object('label_cache_shortdesc'),
128
'hints': builder.get_object('label_cache_hints'),
129
'coords': builder.get_object('label_cache_coords'),
130
'found': builder.get_object('check_cache_found'),
131
'homepage': builder.get_object('link_cache_homepage'),
132
'log': builder.get_object('link_cache_log'),
133
'notebook': builder.get_object('notebook_cache')
136
self.search_elements = {
137
'name': builder.get_object('entry_search_name'),
138
'owner': builder.get_object('entry_search_owner'),
140
'true': builder.get_object('radio_search_found_true'),
141
'false': builder.get_object('radio_search_found_false')
144
'regular': builder.get_object('check_search_type_traditional'),
145
'multi': builder.get_object('check_search_type_multi'),
146
'unknown': builder.get_object('check_search_type_unknown'),
147
'virtual': builder.get_object('check_search_type_virtual'),
148
'other': builder.get_object('check_search_type_other')
151
'1': builder.get_object('check_search_size_1'),
152
'2': builder.get_object('check_search_size_2'),
153
'3': builder.get_object('check_search_size_3'),
154
'4': builder.get_object('check_search_size_4'),
155
'5': builder.get_object('check_search_size_other')
158
'lower': builder.get_object('vscale_search_terrain_lower'),
159
'upper': builder.get_object('vscale_search_terrain_upper')
162
'lower': builder.get_object('vscale_search_diff_lower'),
163
'upper': builder.get_object('vscale_search_diff_upper')
166
'type': builder.get_object('frame_search_type'),
167
'size': builder.get_object('frame_search_size'),
168
'terrain': builder.get_object('frame_search_terrain'),
169
'diff': builder.get_object('frame_search_diff'),
171
'no_details': builder.get_object('check_search_no_details')
173
self.search_elements['terrain']['lower'].get_adjustment().set_value(1)
174
self.search_elements['terrain']['upper'].get_adjustment().set_value(5)
175
self.search_elements['diff']['lower'].get_adjustment().set_value(1)
176
self.search_elements['diff']['upper'].get_adjustment().set_value(5)
182
strings = self.pointprovider.get_titles_and_names()
183
liststore = gtk.ListStore(gobject.TYPE_STRING)
184
for string in strings:
185
liststore.append([string])
186
comp = builder.get_object('entrycompletion_search')
187
entry = builder.get_object('entry_search')
188
entry.set_completion(comp)
189
comp.set_model(liststore)
190
comp.set_text_column(0)
191
self.entry_search = entry
194
# Create the renderer used in the listview
195
txtRdr = gtk.CellRendererText()
196
pixbufRdr = gtk.CellRendererPixbuf()
207
('gefunden?', [(txtRdr, gobject.TYPE_STRING)], (ROW_FOUND, ROW_ID), False, True),
208
('Typ', [(txtRdr, gobject.TYPE_STRING)], (ROW_TYPE, ), False, True),
209
('GrƶĆe', [(txtRdr, gobject.TYPE_STRING)], (ROW_SIZE, ROW_ID), False, True),
210
('Terrain', [(txtRdr, gobject.TYPE_STRING)], (ROW_TERRAIN, ROW_ID), False, True),
211
('Difficulty', [(txtRdr, gobject.TYPE_STRING)], (ROW_DIFF, ROW_ID), False, True),
212
('ID', [(txtRdr, gobject.TYPE_STRING)], (ROW_ID, ), False, True),
213
('Titel', [(txtRdr, gobject.TYPE_STRING)], (ROW_TITLE, ), False, True),
215
self.cachelist = listview = extListview.ExtListView(columns, sortable=True, useMarkup=False, canShowHideColumns=False)
216
builder.get_object('scrolledwindow_search').add(listview)
217
listview.connect('extlistview-button-pressed', self.on_search_cache_clicked)
219
# Create the renderer used in the listview for user defined points
221
txtRdr = gtk.CellRendererText()
222
pixbufRdr = gtk.CellRendererPixbuf()
228
('Position', [(txtRdr, gobject.TYPE_STRING)], (ROW_COORD), False, True),
229
('Kommentar', [(txtRdr, gobject.TYPE_STRING)], (ROW_COMMENT, ), False, True),
231
self.userpointlist = extListview.ExtListView(columns, sortable=True, useMarkup=False, canShowHideColumns=False)
232
builder.get_object('scrolledwindow_userpoints').add(self.userpointlist)
236
point = self.ts.deg2num(coord)
237
size = self.ts.tile_size()
238
p_x = (point[0] * size - self.map_center_x * size)
239
p_y = (point[1] * size - self.map_center_y * size)
243
def __configure_event(self, widget, event):
245
x, y, width, height = widget.get_allocation()
246
self.map_width = int(width + 2 * width * self.MAP_FACTOR)
247
self.map_height = int(height + 2 * height * self.MAP_FACTOR)
249
openstreetmap.TileLoader.drawlock.acquire()
250
self.pixmap = gtk.gdk.Pixmap(widget.window, self.map_width, self.map_height)
252
openstreetmap.TileLoader.drawlock.release()
254
self.xgc = widget.get_style().fg_gc[gtk.STATE_NORMAL]
256
self.drawing_area_configured = True
259
self.draw_root_x = int(-width * self.MAP_FACTOR)
260
self.draw_root_y = int(-height * self.MAP_FACTOR)
263
def __coord2point(self, coord):
264
point = self.ts.deg2num(coord)
265
size = self.ts.tile_size()
267
p_x = int(point[0] * size - self.map_center_x * size + self.map_width / 2)
268
p_y = int(point[1] * size - self.map_center_y * size + self.map_height / 2)
273
def __decode_htmlentities(self, string):
274
def substitute_entity(match):
276
if match.group(1) == "#":
278
if match.group(2) == '':
279
# number is in decimal
280
return unichr(int(ent))
281
elif match.group(2) == 'x':
283
return unichr(int('0x' + ent, 16))
285
# they were using a name
292
entity_re = re.compile(r'&(#?)(x?)(\w+);')
293
return entity_re.subn(substitute_entity, string)[0]
295
def destroy(self, target):
298
def display_results_advanced(self, caches):
310
if r.difficulty == -1:
313
d = "%.1f" % r.difficulty
318
t = "%.1f" % r.terrain
320
rows.append((f, r.type, s, t, d, r.name, r.title))
321
self.cachelist.replaceContent(rows)
323
def __draw_map(self):
324
if not self.drawing_area_configured:
327
if self.map_width == 0 or self.map_height == 0:
329
size = self.ts.tile_size()
330
xi = int(self.map_center_x)
331
yi = int(self.map_center_y)
332
span_x = int(math.ceil(float(self.map_width) / (size * 2.0)))
333
span_y = int(math.ceil(float(self.map_height) / (size * 2.0)))
335
for i in range(0, span_x + 1, 1):
336
for j in range(0, span_y + 1, 1):
337
for dir in range(0, 4, 1):
339
if dir % 2 == 1: # if dir == 1 or dir == 3
344
tile = (xi + (i * dir_ew), yi + (j * dir_ns))
345
if not tile in tiles:
347
#print "Requesting ", tile, " zoom ", ts.zoom
349
d = openstreetmap.TileLoader(tile, self.ts.zoom, self)
353
def __drag(self, widget, event):
354
if not self.dragging:
356
self.drag_offset_x = self.drag_start_x - event.x
357
self.drag_offset_y = self.drag_start_y - event.y
359
def __drag_end(self, widget, event):
360
if not self.dragging:
362
self.dragging = False
363
offset_x = (self.drag_start_x - event.x)
364
offset_y = (self.drag_start_y - event.y)
365
if abs(offset_x) < 3 or abs(offset_y) < 3:
366
x, y = event.x, event.y
367
c = self.screenpoint2coord([x, y])
368
c1 = self.screenpoint2coord([x-self.CLICK_RADIUS, y-self.CLICK_RADIUS])
369
c2 = self.screenpoint2coord([x + self.CLICK_RADIUS, y + self.CLICK_RADIUS])
370
cache = self.pointprovider.get_nearest_point_filter(c, c1, c2)
371
self.core.on_cache_selected(cache)
373
self.map_center_x += (offset_x / self.ts.tile_size())
374
self.map_center_y += (offset_y / self.ts.tile_size())
378
def __drag_draw(self):
379
if not self.dragging:
381
#if abs(self.drag_offset_x) < 3 or abs(self.drag_offset_y) < 3:
383
widget = self.drawing_area
384
x, y, width, height = widget.get_allocation()
386
widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL],
387
self.pixmap, -self.draw_at_x + self.drag_offset_x - self.draw_root_x, -self.draw_at_y + self.drag_offset_y - self.draw_root_y, 0, 0, width, height)
391
def __drag_start(self, widget, event):
392
self.drag_start_x = event.x
393
self.drag_start_y = event.y
394
self.drag_offset_x = 0
395
self.drag_offset_y = 0
396
self.last_drag_offset_x = 0
397
self.last_drag_offset_y = 0
399
gobject.timeout_add(50, self.drag_draw)
403
def __draw_marks(self, thr):
406
position = Coordinate(49.75400, 6.66135)
407
target = Coordinate(49.755900, 6.649933)
410
p = self.coord2point(position)
414
t = self.coord2point(target)
419
xgc.set_function(gtk.gdk.AND_INVERT)
420
xgc.set_rgb_fg_color(gtk.gdk.color_parse("blue"))
421
self.pixmap.draw_line(xgc, p[0], p[1], t[0], t[1])
424
length = 0.001 * (2 ** ts.zoom)
425
xgc.set_function(gtk.gdk.COPY)
426
xgc.set_rgb_fg_color(gtk.gdk.color_parse("blue"))
427
self.pixmap.draw_line(xgc, p[0], p[1], int(p[0] + math.cos(bearing) * length), int(p[1] + math.sin(bearing) * length))
434
coords = self.pointprovider.get_points_filter((self.pixmappoint2coord([0, 0]), self.pixmappoint2coord([self.map_width, self.map_height])))
435
draw_short = (len(coords) > self.TOO_MUCH_POINTS)
437
xgc.set_function(gtk.gdk.AND)
439
color_default = gtk.gdk.color_parse('blue')
440
color_found = gtk.gdk.color_parse('grey')
441
color_regular = gtk.gdk.color_parse('green')
442
color_multi = gtk.gdk.color_parse('orange')
443
font = pango.FontDescription("Sans 8")
445
for c in coords: # for each geocache
446
color = color_default
449
elif c.type == "regular":
450
color = color_regular
451
elif c.type == "multi":
454
p = self.__coord2point(c)
455
xgc.set_rgb_fg_color(color)
458
self.pixmap.draw_line(xgc, p[0], p[1] - 2, p[0], p[1] + 3) # |
459
self.pixmap.draw_line(xgc, p[0] - 2, p[1], p[0] + 3, p[1]) # ---
464
self.pixmap.draw_rectangle(xgc, False, p[0] - radius, p[1] - radius, radius * 2, radius * 2)
467
if self.settings['options_show_name']:
468
layout = self.drawing_area.create_pango_layout(c.name)
469
layout.set_font_description(font)
470
self.pixmap.draw_layout(xgc, p[0] + 3 + radius, p[1] - 3 - radius, layout)
472
# if we have a description for this cache...
473
if c.was_downloaded():
474
# draw something like:
481
pos_x = p[0] + radius + 3 + 1
484
for i in range(0, 3):
485
self.pixmap.draw_line(xgc, pos_x, pos_y + dist * i, pos_x + width, pos_y + dist * i)
487
# if this cache is the active cache
488
if self.current_cache != None and c.name == self.current_cache.name:
490
xgc.set_rgb_fg_color(gtk.gdk.color_parse('black'))
492
self.pixmap.draw_rectangle(xgc, False, p[0] - radius, p[1] - radius, radius * 2, radius * 2)
495
# draw additional waypoints
496
# --> print description!
497
if self.current_cache != None and self.current_cache.waypoints != None:
498
xgc.set_function(gtk.gdk.AND)
499
xgc.set_rgb_fg_color(gtk.gdk.color_parse('red'))
501
for w in self.current_cache.waypoints:
502
if w['lat'] != -1 and w['lon'] != -1:
506
p = self.__coord2point(geo.Coordinate(w['lat'], w['lon']))
507
self.pixmap.draw_line(xgc, p[0], p[1] - 3, p[0], p[1] + 4) # |
508
self.pixmap.draw_line(xgc, p[0] - 3, p[1], p[0] + 4, p[1]) # ---
509
self.pixmap.draw_arc(xgc, False, p[0] - radius, p[1] - radius, radius * 2, radius * 2, 0, 360 * 64)
510
layout = self.drawing_area.create_pango_layout('')
511
layout.set_markup('<i>%s</i>' % (w['id']))
512
layout.set_font_description(font)
513
self.pixmap.draw_layout(xgc, p[0] + 3 + radius, p[1] - 3 - radius, layout)
517
# next, draw the user defined points
520
coords = self.userpointprovider.get_points_filter((self.pixmappoint2coord([0, 0]), self.pixmappoint2coord([self.map_width, self.map_height])))
522
xgc.set_function(gtk.gdk.AND)
524
color = gtk.gdk.color_parse('darkorchid')
525
for c in coords: # for each geocache
526
p = self.__coord2point(c)
528
xgc.set_rgb_fg_color(color)
530
self.pixmap.draw_line(xgc, p[0] - radius, p[1], p[0], p[1] + radius)
531
self.pixmap.draw_line(xgc, p[0], p[1] + radius, p[0] + radius, p[1])
532
self.pixmap.draw_line(xgc, p[0] + radius, p[1], p[0], p[1] - radius)
533
self.pixmap.draw_line(xgc, p[0], p[1] - radius, p[0] - radius, p[1])
535
self.pixmap.draw_line(xgc, p[0], p[1] - 2, p[0], p[1] + 3) # |
536
self.pixmap.draw_line(xgc, p[0] - 2, p[1], p[0] + 3, p[1]) # ---
537
layout = self.drawing_area.create_pango_layout(c.name)
538
layout.set_font_description(font)
539
self.pixmap.draw_layout(xgc, p[0] + 3 + radius, p[1] - 3 - radius, layout)
545
xgc.set_function(gtk.gdk.INVERT)
546
xgc.set_rgb_fg_color(gtk.gdk.color_parse("black"))
547
self.pixmap.draw_line(xgc, t[0] - radius_o, t[1], t[0] - radius_i, t[1])
548
self.pixmap.draw_line(xgc, t[0] + radius_o, t[1], t[0] + radius_i, t[1])
549
self.pixmap.draw_line(xgc, t[0], t[1] + radius_o, t[0], t[1] + radius_i)
550
self.pixmap.draw_line(xgc, t[0], t[1] - radius_o, t[0], t[1] - radius_i)
552
xgc.set_function(gtk.gdk.INVERT)
553
self.pixmap.draw_point(xgc, t[0], t[1])
556
xgc.set_rgb_fg_color(gtk.gdk.color_parse("black"))
557
xgc.set_function(gtk.gdk.COPY)
561
def expose_event(self, widget, event):
562
x, y, width, height = event.area
564
openstreetmap.TileLoader.drawlock.acquire()
565
widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL],
566
self.pixmap, x, y, self.draw_root_x + self.draw_at_x + x, self.draw_root_y + self.draw_at_y + y, -1, -1)
567
# width, height hier?
569
openstreetmap.TileLoader.drawlock.release()
572
def get_visible_area(self):
573
return (self.pixmappoint2coord([0, 0]), self.pixmappoint2coord([self.map_width, self.map_height]))
576
def on_download_descriptions_clicked(self, something):
577
self.core.on_download_descriptions(self.get_visible_area())
580
def on_download_clicked(self, something):
581
self.core.on_download(self.get_visible_area())
584
def on_save_config(self, something):
585
if not self.block_changes:
586
self.core.on_config_changed(self.read_settings())
588
def on_search_advanced_clicked(self, something):
589
if self.search_elements['found']['true'].get_active():
591
elif self.search_elements['found']['false'].get_active():
596
owner_search = self.search_elements['owner'].get_text()
597
name_search = self.search_elements['name'].get_text()
599
if not self.search_elements['type']['other'].get_active():
601
for type, el in self.search_elements['type'].items():
607
if not self.search_elements['no_details'].get_active():
609
for s in range(1, 6):
610
if self.search_elements['size'][str(s)].get_active():
613
terrain = [self.search_elements['terrain']['lower'].get_adjustment().get_value(),
614
self.search_elements['terrain']['upper'].get_adjustment().get_value()]
615
diff = [self.search_elements['diff']['lower'].get_adjustment().get_value(),
616
self.search_elements['diff']['upper'].get_adjustment().get_value()]
618
size = terrain = diff = None
619
self.core.on_start_search_advanced(found, owner_search, name_search, size, terrain, diff, ctype)
622
def on_search_details_toggled(self, some=None):
623
for k, i in self.search_elements['frames'].items():
625
i.set_sensitive(not self.search_elements['no_details'].get_active())
627
def on_search_cache_clicked(self, listview, event, element):
628
if event.type != gtk.gdk._2BUTTON_PRESS or element == None:
631
cachename = listview.getItem(element[0], 5)
632
cache = self.pointprovider.find_by_string(cachename)
633
self.core.on_cache_selected(cache)
636
def on_search_key_release(self, widget, event):
638
if event.keyval == 65293: # seems to be keycode of return key
639
self.core.on_start_search_simple(self.widget.get_text())
641
def on_search_simple_key_release(self, something):
642
self.core.on_start_search_simple(self.widget.get_text())
645
def on_start_search_simple(self, something):
646
self.core.on_start_search_simple(self.entry_search.get_text())
648
def on_zoom_changed(self, blub):
649
if not self.inhibit_zoom:
652
def on_zoomin_clicked(self, widget):
655
def on_zoomout_clicked(self, widget):
658
def pixmappoint2coord(self, point):
659
size = self.ts.tile_size()
660
coord = self.ts.num2deg(
661
(point[0] + self.map_center_x * size - self.map_width / 2) / size,
662
(point[1] + self.map_center_y * size - self.map_height / 2) / size
666
def read_settings(self):
667
c = self.ts.num2deg(self.map_center_x, self.map_center_y)
669
'map_position_lat': c.lat,
670
'map_position_lon': c.lon
672
for x in self.SETTINGS_CHECKBOXES:
673
settings[x] = builder.get_object('check_%s' % x).get_active()
675
for x in self.SETTINGS_INPUTS:
676
settings[x] = builder.get_object('input_%s' % x).get_text()
678
self.settings = settings
683
self.drawing_area.queue_draw()
685
def replace_image_tag(self, m):
686
if m.group(1) != None and m.group(1).strip() != '':
687
return ' [Bild: %s] ' % m.group(1).strip()
691
def screenpoint2coord(self, point):
692
size = self.ts.tile_size()
693
coord = self.ts.num2deg(
694
((point[0] - self.draw_root_x - self.draw_at_x) + self.map_center_x * size - self.map_width / 2) / size,
695
((point[1] - self.draw_root_y - self.draw_at_y) + self.map_center_y * size - self.map_height / 2) / size
699
def scroll(self, widget, event):
700
if event.direction == gtk.gdk.SCROLL_DOWN:
705
self.window.show_all()
710
def show_cache(self, cache):
712
self.hpaned.set_position(0)
714
self.current_cache = cache
715
self.hpaned.set_position(-1)
716
if cache.was_downloaded():
717
uri = 'file://%s/%s.html' % (self.settings['download_output_dir'], cache.name)
718
self.cache_elements['name_downloaded'].set_uri(uri)
719
self.cache_elements['name_downloaded'].set_label(cache.name)
720
self.cache_elements['name_downloaded'].show()
721
self.cache_elements['name_not_downloaded'].hide()
723
self.cache_elements['name_not_downloaded'].set_label(cache.name)
724
self.cache_elements['name_downloaded'].hide()
725
self.cache_elements['name_not_downloaded'].show()
726
self.cache_elements['title'].set_text(cache.title)
727
self.cache_elements['type'].set_text("%s" % cache.type)
728
self.cache_elements['size'].set_text("%d/5" % cache.size)
729
self.cache_elements['terrain'].set_text("%.1f/5" % (cache.terrain / 10.0))
730
self.cache_elements['difficulty'].set_text("%.1f/5" % (cache.difficulty / 10.0))
734
text_shortdesc = self.__strip_html(cache.shortdesc).strip()[:600]
735
if text_shortdesc == '':
736
text_shortdesc = '(Keine Kurzbeschreibung vorhanden)'
738
self.cache_elements['notebook'].set_current_page(0)
741
text_desc = self.__strip_html(cache.desc).strip()[:600]
743
text_desc = '(Keine Beschreibung vorhanden)'
745
self.cache_elements['notebook'].set_current_page(1)
747
text_hints = cache.hints.strip()
749
text_hints = '(Keine Hints vorhanden)'
751
text_coords = 'Start: %s\n' % cache
752
for w in cache.waypoints:
753
if not (w['lat'] == -1 and w['lon'] == -1):
754
n = geo.Coordinate(w['lat'], w['lon'])
755
latlon = "%s %s" % (re.sub(r' ', '', n.get_lat(geo.Coordinate.FORMAT_DM)), re.sub(r' ', '', n.get_lon(geo.Coordinate.FORMAT_DM)))
758
text_coords += "<b>%s</b> <tt>%s</tt> <i>%s</i>\n<small>%s</small>" % (w['id'], latlon, w['name'], w['comment'])
760
self.cache_elements['desc'].set_text(text_desc)
761
self.cache_elements['shortdesc'].set_text(text_shortdesc)
762
self.cache_elements['hints'].set_text(text_hints)
763
self.cache_elements['coords'].set_use_markup(True)
764
self.cache_elements['coords'].set_text(text_coords)
765
self.cache_elements['found'].set_active(cache.found)
766
self.cache_elements['homepage'].set_uri('http://www.geocaching.com/seek/cache_details.aspx?wp=%s' % cache.name)
767
self.cache_elements['log'].set_uri('http://www.geocaching.com/seek/log.aspx?wp=%s' % cache.name)
770
def set_center(self, coord):
771
builder.get_object("notebook_all").set_current_page(0)
772
self.map_center_x, self.map_center_y = self.ts.deg2num(coord)
778
def __strip_html(self, text):
779
text = re.sub(r"""(?i)<img[^>]+alt=["']?([^'"> ]+)[^>]+>""", self.replace_image_tag, text)
780
text = re.sub(r'<[^>]*?>', '', text)
781
text = self.__decode_htmlentities(text)
782
text = re.sub(r'[\n\r]+\s*[\n\r]+', '\n', text)
785
def write_settings(self, settings):
786
self.settings = settings
787
self.block_changes = True
788
self.set_center(geo.Coordinate(self.settings['map_position_lat'], self.settings['map_position_lon']))
790
for x in self.SETTINGS_CHECKBOXES:
791
if x in self.settings.keys():
792
builder.get_object('check_%s' % x).set_active(self.settings[x])
793
elif x in self.DEFAULT_SETTINGS.keys():
794
builder.get_object('check_%s' % x).set_active(self.DEFAULT_SETTINGS[x])
796
for x in self.SETTINGS_INPUTS:
797
if x in self.settings.keys():
798
builder.get_object('input_%s' % x).set_text(str(self.settings[x]))
799
elif x in self.DEFAULT_SETTINGS.keys():
800
builder.get_object('input_%s' % x).set_text(self.DEFAULT_SETTINGS[x])
802
self.block_changes = False
804
def zoom(self, direction=None):
805
size = self.ts.tile_size()
806
center = self.ts.num2deg(self.map_center_x - float(self.draw_at_x) / size, self.map_center_y - float(self.draw_at_y) / size)
807
if direction == None:
808
newzoom = self.zoom_adjustment.get_value()
810
newzoom = self.ts.get_zoom() + direction
811
self.ts.set_zoom(newzoom)
812
self.inhibit_zoom = True
813
self.zoom_adjustment.set_value(self.ts.get_zoom())
814
self.inhibit_zoom = False
815
self.set_center(center)